diff --git a/CHANGELOG.md b/CHANGELOG.md index 260a83f9a..13f9a3e6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ### Added - #1202 Check for modifications outside FFDec and ask user to reload - #1155, #1602 AS3 remove trait button +- #1260, #1438 AS1/2 direct editing on(xxx), onClipEvent(xxx) handlers ### Fixed - #1298 AS1/2 properly decompiled setProperty/getProperty diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java index 72f049332..ca7e26d7d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash; import com.jpexs.decompiler.flash.action.Action; @@ -2079,12 +2080,13 @@ public class SWFInputStream implements AutoCloseable { * @param swf * @param tag * @param name + * @param parentClipActions * @return CLIPACTIONRECORD value * @throws IOException */ - public CLIPACTIONRECORD readCLIPACTIONRECORD(SWF swf, Tag tag, String name) throws IOException { + public CLIPACTIONRECORD readCLIPACTIONRECORD(SWF swf, Tag tag, String name, CLIPACTIONS parentClipActions) throws IOException { newDumpLevel(name, "CLIPACTIONRECORD"); - CLIPACTIONRECORD ret = new CLIPACTIONRECORD(swf, this, tag); + CLIPACTIONRECORD ret = new CLIPACTIONRECORD(swf, this, tag, parentClipActions); endDumpLevel(); if (ret.eventFlags.isClear()) { return null; @@ -2108,7 +2110,7 @@ public class SWFInputStream implements AutoCloseable { ret.allEventFlags = readCLIPEVENTFLAGS("allEventFlags"); CLIPACTIONRECORD cr; ret.clipActionRecords = new ArrayList<>(); - while ((cr = readCLIPACTIONRECORD(swf, tag, "record")) != null) { + while ((cr = readCLIPACTIONRECORD(swf, tag, "record", ret)) != null) { ret.clipActionRecords.add(cr); } endDumpLevel(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java index de060b927..0d11d275e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2Parser.java @@ -138,6 +138,9 @@ import com.jpexs.decompiler.flash.helpers.StringBuilderTextWriter; import com.jpexs.decompiler.flash.helpers.collections.MyEntry; import com.jpexs.decompiler.flash.tags.DoInitActionTag; import com.jpexs.decompiler.flash.tags.base.ASMSource; +import com.jpexs.decompiler.flash.types.BUTTONCONDACTION; +import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD; +import com.jpexs.decompiler.flash.types.CLIPEVENTFLAGS; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -226,10 +229,12 @@ public class ActionScript2Parser { private final int swfVersion; private List swfClasses = new ArrayList<>(); + private final ASMSource targetSource; - public ActionScript2Parser(SWF swf) { + public ActionScript2Parser(SWF swf, ASMSource targetSource) { this.swfVersion = swf.version; parseSwfClasses(swf); + this.targetSource = targetSource; } private long uniqLast = 0; @@ -1841,8 +1846,7 @@ public class ActionScript2Parser { } else if (newvar instanceof VariableActionItem) { ret = new NewObjectActionItem(null, null, newvar, args); } - } - else if (newvar instanceof ToNumberActionItem) { + } else if (newvar instanceof ToNumberActionItem) { List args = new ArrayList<>(); if (((ToNumberActionItem) newvar).value != null) { args.add(((ToNumberActionItem) newvar).value); @@ -1996,6 +2000,172 @@ public class ActionScript2Parser { this.constantPool = constantPool; lexer = new ActionScriptLexer(new StringReader(str)); + BUTTONCONDACTION newButtonCond = new BUTTONCONDACTION(); + + if (targetSource instanceof BUTTONCONDACTION) { + ParsedSymbol symb = lexer.lex(); + if (symb.type != SymbolType.IDENTIFIER || !"on".equals(symb.value)) { + throw new ActionParseException("on keyword expected but " + symb + " found", lexer.yyline()); + } + expectedType(SymbolType.PARENT_OPEN); + symb = lexer.lex(); + boolean condEmpty = true; + while (symb.type == SymbolType.IDENTIFIER) { + condEmpty = false; + switch ((String) symb.value) { + case "press": + newButtonCond.condOverUpToOverDown = true; + break; + case "release": + newButtonCond.condOverDownToOverUp = true; + break; + case "releaseOutside": + newButtonCond.condOutDownToIdle = true; + break; + case "rollOver": + newButtonCond.condIdleToOverUp = true; + break; + case "rollOut": + newButtonCond.condOverUpToIddle = true; + break; + case "dragOut": + newButtonCond.condOverDownToOutDown = true; + break; + case "dragOver": + newButtonCond.condOutDownToOverDown = true; + break; + case "keyPress": + symb = lexer.lex(); + expected(symb, lexer.yyline(), SymbolType.STRING); + Integer key = CLIPACTIONRECORD.stringToKey((String) symb.value); + if (key == null) { + throw new ActionParseException("Invalid key", lexer.yyline()); + } + newButtonCond.condKeyPress = key; + break; + default: + throw new ActionParseException("Unrecognized event type", lexer.yyline()); + } + symb = lexer.lex(); + if (symb.type == SymbolType.PARENT_CLOSE) { + break; + } + expected(symb, lexer.yyline(), SymbolType.COMMA); + symb = lexer.lex(); + } + expected(symb, lexer.yyline(), SymbolType.PARENT_CLOSE); + if (condEmpty) { + throw new ActionParseException("condition must be non empty", lexer.yyline()); + } + expectedType(SymbolType.CURLY_OPEN); + } + + CLIPEVENTFLAGS newClipEventFlags = new CLIPEVENTFLAGS(); + int newClipActionRecordKey = 0; + if (targetSource instanceof CLIPACTIONRECORD) { + ParsedSymbol symb = lexer.lex(); + if (symb.type != SymbolType.IDENTIFIER || (!"on".equals(symb.value) && !"onClipEvent".equals(symb.value))) { + throw new ActionParseException("on or onClipEvent keyword expected but " + symb + " found", lexer.yyline()); + } + expectedType(SymbolType.PARENT_OPEN); + if ("on".equals(symb.value)) { + symb = lexer.lex(); + boolean condEmpty = true; + while (symb.type == SymbolType.IDENTIFIER) { + condEmpty = false; + switch ((String) symb.value) { + case "press": + newClipEventFlags.clipEventPress = true; + break; + case "release": + newClipEventFlags.clipEventRelease = true; + break; + case "releaseOutside": + newClipEventFlags.clipEventReleaseOutside = true; + break; + case "rollOver": + newClipEventFlags.clipEventRollOver = true; + break; + case "rollOut": + newClipEventFlags.clipEventRollOut = true; + break; + case "dragOut": + newClipEventFlags.clipEventDragOut = true; + break; + case "dragOver": + newClipEventFlags.clipEventDragOver = true; + break; + case "initialize": + newClipEventFlags.clipEventInitialize = true; + break; + case "construct": + newClipEventFlags.clipEventConstruct = true; + break; + + case "keyPress": + symb = lexer.lex(); + expected(symb, lexer.yyline(), SymbolType.STRING); + Integer key = CLIPACTIONRECORD.stringToKey((String) symb.value); + if (key == null) { + throw new ActionParseException("Invalid key", lexer.yyline()); + } + newClipActionRecordKey = key; + newClipEventFlags.clipEventKeyPress = true; + break; + default: + throw new ActionParseException("Unrecognized event type", lexer.yyline()); + } + symb = lexer.lex(); + if (symb.type == SymbolType.PARENT_CLOSE) { + break; + } + expected(symb, lexer.yyline(), SymbolType.COMMA); + symb = lexer.lex(); + } + expected(symb, lexer.yyline(), SymbolType.PARENT_CLOSE); + if (condEmpty) { + throw new ActionParseException("condition must be non empty", lexer.yyline()); + } + } else if ("onClipEvent".equals(symb.value)) { + symb = lexer.lex(); + expected(symb, lexer.yyline(), SymbolType.IDENTIFIER); + + switch ((String) symb.value) { + case "keyUp": + newClipEventFlags.clipEventKeyUp = true; + break; + case "keyDown": + newClipEventFlags.clipEventKeyDown = true; + break; + case "mouseUp": + newClipEventFlags.clipEventMouseUp = true; + break; + case "mouseDown": + newClipEventFlags.clipEventMouseDown = true; + break; + case "mouseMove": + newClipEventFlags.clipEventMouseMove = true; + break; + case "unload": + newClipEventFlags.clipEventUnload = true; + break; + case "enterFrame": + newClipEventFlags.clipEventEnterFrame = true; + break; + case "load": + newClipEventFlags.clipEventLoad = true; + break; + case "data": + newClipEventFlags.clipEventData = true; + break; + default: + throw new ActionParseException("Unrecognized clipEvent type", lexer.yyline()); + } + expectedType(SymbolType.PARENT_CLOSE); + } + expectedType(SymbolType.CURLY_OPEN); + } + List vars = new ArrayList<>(); List functions = new ArrayList<>(); retTree.addAll(commands(false, false, 0, vars, functions)); @@ -2034,9 +2204,34 @@ public class ActionScript2Parser { v.setBoxedValue(new GetVariableActionItem(null, null, pushConst(varName))); } } + + if ((targetSource instanceof BUTTONCONDACTION) || (targetSource instanceof CLIPACTIONRECORD)) { + expectedType(SymbolType.CURLY_CLOSE); + } + if (lexer.lex().type != SymbolType.EOF) { throw new ActionParseException("Parsing finished before end of the file", lexer.yyline()); } + if (targetSource instanceof BUTTONCONDACTION) { + BUTTONCONDACTION targetButtonCond = (BUTTONCONDACTION) targetSource; + targetButtonCond.condIdleToOverDown = newButtonCond.condIdleToOverDown; + targetButtonCond.condIdleToOverUp = newButtonCond.condIdleToOverUp; + targetButtonCond.condOutDownToIdle = newButtonCond.condOutDownToIdle; + targetButtonCond.condOutDownToOverDown = newButtonCond.condOutDownToOverDown; + targetButtonCond.condOverDownToIdle = newButtonCond.condOverDownToIdle; + targetButtonCond.condOverDownToOutDown = newButtonCond.condOverDownToOutDown; + targetButtonCond.condOverDownToOverUp = newButtonCond.condOverDownToOverUp; + targetButtonCond.condOverUpToIddle = newButtonCond.condOverUpToIddle; + targetButtonCond.condOverUpToOverDown = newButtonCond.condOverUpToOverDown; + targetButtonCond.condKeyPress = newButtonCond.condKeyPress; + } + + if (targetSource instanceof CLIPACTIONRECORD) { + CLIPACTIONRECORD targetClipActionRecord = (CLIPACTIONRECORD) targetSource; + targetClipActionRecord.eventFlags = newClipEventFlags; + targetClipActionRecord.keyCode = newClipActionRecordKey; + targetClipActionRecord.getParentClipActions().calculateAllEventFlags(); + } return retTree; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS2ScriptImporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS2ScriptImporter.java index d29b04b05..aeb0e6b3f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS2ScriptImporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/importers/AS2ScriptImporter.java @@ -73,7 +73,7 @@ public class AS2ScriptImporter { if (new File(fileName).exists()) { String txt = Helper.readTextFile(fileName); - ActionScript2Parser par = new ActionScript2Parser(asm.getSwf()); + ActionScript2Parser par = new ActionScript2Parser(asm.getSwf(), asm); try { asm.setActions(par.actionsFromString(txt)); } catch (ActionParseException ex) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java index 9e33a7539..63bc8547d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/BUTTONCONDACTION.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.types; import com.jpexs.decompiler.flash.DisassemblyListener; @@ -169,7 +170,7 @@ public class BUTTONCONDACTION implements ASMSource, Serializable { */ @Override public String toString() { - return "BUTTONCONDACTION"; + return "BUTTONCONDACTION " + getHeader(false); } /** @@ -289,10 +290,10 @@ public class BUTTONCONDACTION implements ASMSource, Serializable { if (condOverUpToIddle) { events.add("rollOut"); } - if (condOverDownToOutDown) { + if (condOverDownToOutDown || condOverDownToIdle) { events.add("dragOut"); } - if (condOutDownToOverDown) { + if (condOutDownToOverDown || condIdleToOverDown) { events.add("dragOver"); } if (condKeyPress > 0) { @@ -337,7 +338,7 @@ public class BUTTONCONDACTION implements ASMSource, Serializable { @Override public String getExportFileName() { - return getHeader(true); + return "BUTTONCONDACTION " + getHeader(true); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java index f9efbfee9..80b106456 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONRECORD.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.types; import com.jpexs.decompiler.flash.DisassemblyListener; @@ -44,12 +45,17 @@ import java.util.List; public class CLIPACTIONRECORD implements ASMSource, Serializable { private String scriptName = "-"; + private CLIPACTIONS parentClipActions; @Override public String getScriptName() { return scriptName; } + public CLIPACTIONS getParentClipActions() { + return parentClipActions; + } + public static String keyToString(int key) { if ((key < CLIPACTIONRECORD.KEYNAMES.length) && (key > 0) && (CLIPACTIONRECORD.KEYNAMES[key] != null)) { return CLIPACTIONRECORD.KEYNAMES[key]; @@ -58,6 +64,20 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable { } } + public static Integer stringToKey(String str) { + for (int i = 0; i < KEYNAMES.length; i++) { + if (KEYNAMES[i] != null) { + if (str.equals(KEYNAMES[i])) { + return i; + } + } + } + if (str.length() == 1) { + return (int) str.charAt(0); + } + return null; + } + public static final String[] KEYNAMES = { null, "", @@ -113,7 +133,11 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable { this.scriptName = scriptName; } - public CLIPACTIONRECORD(SWF swf, SWFInputStream sis, Tag tag) throws IOException { + public void setParentClipActions(CLIPACTIONS parentClipActions) { + this.parentClipActions = parentClipActions; + } + + public CLIPACTIONRECORD(SWF swf, SWFInputStream sis, Tag tag, CLIPACTIONS parentClipActions) throws IOException { this.swf = swf; this.tag = tag; eventFlags = sis.readCLIPEVENTFLAGS("eventFlags"); @@ -126,6 +150,7 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable { actionRecordSize--; } actionBytes = sis.readByteRangeEx(actionRecordSize, "actionBytes", DumpInfoSpecialType.ACTION_BYTES, sis.getPos()); + this.parentClipActions = parentClipActions; } @Override @@ -157,7 +182,7 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable { */ @Override public String toString() { - return eventFlags.getHeader(keyCode, false); + return "CLIPACTIONRECORD " + eventFlags.getHeader(keyCode, false); } /** @@ -293,7 +318,7 @@ public class CLIPACTIONRECORD implements ASMSource, Serializable { @Override public String getExportFileName() { - return eventFlags.getHeader(keyCode, true); + return "CLIPACTIONRECORD " + eventFlags.getHeader(keyCode, true); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONS.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONS.java index b07860c3c..f703e3ec9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONS.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/types/CLIPACTIONS.java @@ -12,14 +12,18 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash.types; import com.jpexs.decompiler.flash.types.annotations.Reserved; import com.jpexs.decompiler.flash.types.annotations.SWFType; import java.io.Serializable; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Define event handlers for a sprite character @@ -41,4 +45,24 @@ public class CLIPACTIONS implements Serializable { * Individual event handlers */ public List clipActionRecords = new ArrayList<>(); + + public void calculateAllEventFlags() { + + Field[] fields = allEventFlags.getClass().getDeclaredFields(); + try { + for (Field f : fields) { + if (!f.getName().startsWith("clipEvent")) { + continue; + } + f.set(allEventFlags, false); + for (CLIPACTIONRECORD car : clipActionRecords) { + if (f.getBoolean(car.eventFlags)) { + f.set(allEventFlags, true); + } + } + } + } catch (IllegalArgumentException | IllegalAccessException ex) { + Logger.getLogger(CLIPACTIONS.class.getName()).log(Level.SEVERE, null, ex); + } + } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2CompilerTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2CompilerTest.java index 3d05f90f3..11d22970b 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2CompilerTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2CompilerTest.java @@ -57,7 +57,7 @@ public class ActionScript2CompilerTest extends ActionScript2TestBase { SWF swf = new SWF(); ASMSource asm = new DoActionTag(swf); - ActionScript2Parser par = new ActionScript2Parser(swf); + ActionScript2Parser par = new ActionScript2Parser(swf, asm); try { asm.setActions(par.actionsFromString(sourceAsToCompile)); } catch (ActionParseException | CompilationException ex) { diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java index 43a134e01..17a3c9105 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2DeobfuscatorTest.java @@ -55,7 +55,7 @@ public class ActionScript2DeobfuscatorTest extends ActionScript2TestBase { private String recompile(String str) throws ActionParseException, IOException, CompilationException, InterruptedException, TimeoutException { SWF swf = new SWF(); swf.version = SWF.DEFAULT_VERSION; - ActionScript2Parser par = new ActionScript2Parser(swf); + ActionScript2Parser par = new ActionScript2Parser(swf, new DoActionTag(swf)); HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); List actions = par.actionsFromString(str); byte[] hex = Action.actionsToBytes(actions, true, SWF.DEFAULT_VERSION); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ParserTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ParserTest.java index 6d53a9428..5478c7659 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ParserTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2ParserTest.java @@ -16,11 +16,21 @@ */ package com.jpexs.decompiler.flash; +import com.jpexs.decompiler.flash.action.Action; +import com.jpexs.decompiler.flash.action.ActionList; +import com.jpexs.decompiler.flash.action.ConstantPoolTooBigException; import com.jpexs.decompiler.flash.action.parser.script.ActionScript2Parser; import com.jpexs.decompiler.flash.action.swf4.ActionPush; import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; +import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.tags.DoActionTag; +import com.jpexs.decompiler.flash.tags.Tag; +import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.graph.CompilationException; +import com.jpexs.helpers.ByteArrayRange; import java.io.IOException; +import java.util.List; import static org.testng.Assert.fail; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -41,7 +51,7 @@ public class ActionScript2ParserTest extends ActionScript2TestBase { try { SWF swf = new SWF(); swf.version = SWF.DEFAULT_VERSION; - ActionScript2Parser par = new ActionScript2Parser(swf); + ActionScript2Parser par = new ActionScript2Parser(swf, new DoActionTag(swf)); par.actionsFromString(script); } catch (IOException | CompilationException | ParseException ex) { fail("Unable to parse: " + script, ex); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java index d95e723c8..8c3f31a50 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/DirectEditingTest.java @@ -109,9 +109,9 @@ public class DirectEditingTest extends FileTestBase { HighlightedTextWriter writer = new HighlightedTextWriter(new CodeFormatting(), false); asm.getActionScriptSource(writer, null); String as = writer.toString(); - as = asm.removePrefixAndSuffix(as); + //as = asm.removePrefixAndSuffix(as); - ActionScript2Parser par = new ActionScript2Parser(swf); + ActionScript2Parser par = new ActionScript2Parser(swf, asm); try { asm.setActions(par.actionsFromString(as)); } catch (ActionParseException | CompilationException ex) { @@ -120,7 +120,7 @@ public class DirectEditingTest extends FileTestBase { writer = new HighlightedTextWriter(new CodeFormatting(), false); asm.getActionScriptSource(writer, null); String as2 = writer.toString(); - as2 = asm.removePrefixAndSuffix(as2); + //as2 = asm.removePrefixAndSuffix(as2); try { asm.setActions(par.actionsFromString(as2)); } catch (ActionParseException | CompilationException ex) { @@ -129,7 +129,7 @@ public class DirectEditingTest extends FileTestBase { writer = new HighlightedTextWriter(new CodeFormatting(), false); asm.getActionScriptSource(writer, null); String as3 = writer.toString(); - as3 = asm.removePrefixAndSuffix(as3); + //as3 = asm.removePrefixAndSuffix(as3); if (!as3.equals(as2)) { fail("ActionScript is different: " + asm.getSwf().getShortFileName() + "/" + asm.toString()); } diff --git a/libsrc/ffdec_lib/testdata/as2/as2.fla b/libsrc/ffdec_lib/testdata/as2/as2.fla index f000147ec..e65e072ff 100644 Binary files a/libsrc/ffdec_lib/testdata/as2/as2.fla and b/libsrc/ffdec_lib/testdata/as2/as2.fla differ diff --git a/libsrc/ffdec_lib/testdata/as2/as2.swf b/libsrc/ffdec_lib/testdata/as2/as2.swf index e5d3ed2ab..69d0e1183 100644 Binary files a/libsrc/ffdec_lib/testdata/as2/as2.swf and b/libsrc/ffdec_lib/testdata/as2/as2.swf differ diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index e5b784ff0..3ab571ec5 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -3561,7 +3561,7 @@ public class CommandLineArgumentParser { private static void replaceAS2(String as, ASMSource src) throws IOException, InterruptedException { System.out.println("Replace AS1/2"); System.out.println("Warning: This feature is EXPERIMENTAL"); - ActionScript2Parser par = new ActionScript2Parser(src.getSwf()); + ActionScript2Parser par = new ActionScript2Parser(src.getSwf(), src); try { src.setActions(par.actionsFromString(as)); } catch (ActionParseException ex) { diff --git a/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java b/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java index d92094c23..31a400aa2 100644 --- a/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java +++ b/src/com/jpexs/decompiler/flash/gui/GenericTagTreePanel.java @@ -31,6 +31,8 @@ import com.jpexs.decompiler.flash.tags.Tag; import com.jpexs.decompiler.flash.tags.base.ASMSource; import com.jpexs.decompiler.flash.types.ARGB; import com.jpexs.decompiler.flash.types.BasicType; +import com.jpexs.decompiler.flash.types.CLIPACTIONRECORD; +import com.jpexs.decompiler.flash.types.CLIPACTIONS; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.RGBA; import com.jpexs.decompiler.flash.types.annotations.Conditional; @@ -1168,12 +1170,19 @@ public class GenericTagTreePanel extends GenericTagPanel { return; } ReflectionTools.addToField(obj, field, index, true, cls); + try { Object v = ReflectionTools.getValue(obj, field, index); if (v instanceof ASMSource) { ASMSource asv = (ASMSource) v; asv.setSourceTag(editedTag); } + + //Hack to set CLIPACTIONRECORD parent + if ((obj instanceof CLIPACTIONS) && (v instanceof CLIPACTIONRECORD)) { + ((CLIPACTIONRECORD) v).setParentClipActions((CLIPACTIONS) obj); + } + } catch (IllegalArgumentException | IllegalAccessException ex) { //ignore } diff --git a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java index a345e931f..e8debb24b 100644 --- a/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/action/ActionPanel.java @@ -930,21 +930,10 @@ public class ActionPanel extends JPanel implements SearchListener -1) { - if (lastLine - prefLines >= 0) { - decompiledEditor.gotoLine(lastLine - prefLines + 1); - } - } + setDecompiledText(src.getScriptName(), lastDecompiled.text); } else { setDecompiledText(src.getScriptName(), lastDecompiled.text); - if (lastLine > -1) { - decompiledEditor.gotoLine(lastLine + prefLines + 1); - } } } @@ -1071,7 +1060,7 @@ public class ActionPanel extends JPanel implements SearchListener