diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java b/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java index 35cafdcbf..ea53d4dd1 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -35,6 +35,7 @@ import com.jpexs.decompiler.flash.helpers.collections.MyEntry; import com.jpexs.decompiler.graph.Graph; import java.io.*; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -63,6 +64,20 @@ public class ABC { protected HashSet listeners = new HashSet<>(); private static final Logger logger = Logger.getLogger(ABC.class.getName()); + public int addMethodBody(MethodBody body) { + bodies = Arrays.copyOf(bodies, bodies.length + 1); + bodies[bodies.length - 1] = body; + bodyIdxFromMethodIdx = Arrays.copyOf(bodyIdxFromMethodIdx, bodyIdxFromMethodIdx.length + 1); + bodyIdxFromMethodIdx[bodyIdxFromMethodIdx.length - 1] = body.method_info; + return bodies.length - 1; + } + + public int addMethodInfo(MethodInfo mi) { + method_info = Arrays.copyOf(method_info, method_info.length + 1); + method_info[method_info.length - 1] = mi; + return method_info.length - 1; + } + public void addEventListener(EventListener listener) { listeners.add(listener); } @@ -196,7 +211,7 @@ public class ABC { Set namespaceUsages = getNsStringUsages(); int strIndex = constants.constant_multiname[multinameIndex].name_index; if (stringUsages.contains(strIndex) || namespaceUsages.contains(strIndex)) { //name is used elsewhere as string literal - strIndex = constants.forceGetStringId(newname); + strIndex = constants.getStringId(newname, true); constants.constant_multiname[multinameIndex].name_index = strIndex; } else { constants.constant_string[strIndex] = newname; @@ -256,11 +271,11 @@ public class ABC { name = fullname.substring(fullname.lastIndexOf(".") + 1); } if (!pkg.equals("")) { - int pkgStrIndex = constants.forceGetStringId(pkg); + int pkgStrIndex = constants.getStringId(pkg, true); pkgStrIndex = deobfuscatePackageName(stringUsageTypes, stringUsages, namesMap, pkgStrIndex, renameType); pkg = constants.constant_string[pkgStrIndex]; } - int nameStrIndex = constants.forceGetStringId(name); + int nameStrIndex = constants.getStringId(name, true); nameStrIndex = deobfuscateName(stringUsageTypes, stringUsages, namespaceUsages, namesMap, nameStrIndex, true, renameType); name = constants.constant_string[nameStrIndex]; String fullChanged = ""; @@ -268,7 +283,7 @@ public class ABC { fullChanged = pkg + "."; } fullChanged += name; - strIndex = constants.forceGetStringId(fullChanged); + strIndex = constants.getStringId(fullChanged, true); body.code.code.get(ip - 1).operands[0] = strIndex; } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index f33d712c5..4e60bae01 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1069,6 +1069,9 @@ public class AVM2Code implements Serializable { } public int fixIPAfterDebugLine(int ip) { + if (code.isEmpty()) { + return ip; + } if (ip >= code.size()) { return code.size() - 1; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/ConstantPool.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/ConstantPool.java index f1025ecfa..7c46254c8 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/ConstantPool.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/ConstantPool.java @@ -82,6 +82,19 @@ public class ConstantPool { return constant_string.length - 1; } + public int getNamespaceId(Namespace val, int index) { + for (int n = 1; n < constant_namespace.length; n++) { + Namespace ns = constant_namespace[n]; + if (ns.name_index == val.name_index && (ns.kind == val.kind)) { + if (index == 0) { + return n; + } + index--; + } + } + return 0; + } + public int getIntId(long value) { for (int i = 1; i < constant_int.length; i++) { if (constant_int[i] == value) { @@ -109,42 +122,82 @@ public class ConstantPool { return 0; } - public int getStringId(String s) { + public int getStringId(String val) { for (int i = 1; i < constant_string.length; i++) { - if (constant_string[i].equals(s)) { + if (constant_string[i].equals(val)) { return i; } } return 0; } - public int forceGetStringId(String val) { + public int getMultinameId(Multiname val) { + loopm: + for (int m = 1; m < constant_multiname.length; m++) { + Multiname mul = constant_multiname[m]; + if (mul.kind == val.kind && mul.name_index == val.name_index && mul.namespace_index == val.namespace_index && mul.namespace_set_index == val.namespace_set_index && mul.qname_index == val.qname_index && mul.params.size() == val.params.size()) { + for (int p = 0; p < mul.params.size(); p++) { + if (mul.params.get(p) != val.params.get(p)) { + continue loopm; + } + } + return m; + } + } + return 0; + } + + public int getQnameId(String name, int namespaceKind, String namespaceName, boolean add) { + return getMultinameId(new Multiname(Multiname.QNAME, getStringId(name, add), getNamespaceId(new Namespace(namespaceKind, getStringId(namespaceName, add)), 0, add), -1, -1, new ArrayList()), add); + } + + public int getPublicQnameId(String name, boolean add) { + return getQnameId(name, Namespace.KIND_PACKAGE, "", add); + } + + public int getMultinameId(Multiname val, boolean add) { + int id = getMultinameId(val); + if (add && id == 0) { + id = addMultiname(val); + } + return id; + } + + public int getStringId(String val, boolean add) { int id = getStringId(val); - if (id == 0) { + if (add && id == 0) { id = addString(val); } return id; } - public int forceGetIntId(long val) { + public int getIntId(long val, boolean add) { int id = getIntId(val); - if (id == 0) { + if (add && id == 0) { id = addInt(val); } return id; } - public int forceGetUIntId(long val) { + public int getNamespaceId(Namespace val, int index, boolean add) { + int id = getNamespaceId(val, index); + if (add && id == 0) { + id = addNamespace(val); + } + return id; + } + + public int getUIntId(long val, boolean add) { int id = getUIntId(val); - if (id == 0) { + if (add && id == 0) { id = addUInt(val); } return id; } - public int forceGetDoubleId(double val) { + public int getDoubleId(double val, boolean add) { int id = getDoubleId(val); - if (id == 0) { + if (add && id == 0) { id = addDouble(val); } return id; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/ASM3Parser.java b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/ASM3Parser.java index 6f0e9a878..63236635d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/ASM3Parser.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/avm2/parser/ASM3Parser.java @@ -251,16 +251,7 @@ public class ASM3Parser { } expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); - for (int n = 1; n < constants.constant_namespace.length; n++) { - Namespace ns = constants.constant_namespace[n]; - if (ns.getName(constants).equals(name.value) && (ns.kind == kind)) { - if (index == 0) { - return n; - } - index--; - } - } - return constants.addNamespace(new Namespace(kind, constants.forceGetStringId((String) name.value))); + return constants.getNamespaceId(new Namespace(kind, constants.getStringId((String) name.value, true)), index, true); } private static int parseMultiName(ConstantPool constants, Flasm3Lexer lexer) throws ParseException, IOException { @@ -320,7 +311,7 @@ public class ASM3Parser { expected(ParsedSymbol.TYPE_COMMA, ",", lexer); ParsedSymbol name = lexer.lex(); expected(name, ParsedSymbol.TYPE_STRING, "String"); - name_index = constants.forceGetStringId((String) name.value); + name_index = constants.getStringId((String) name.value, true); expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); break; case ParsedSymbol.TYPE_KEYWORD_RTQNAME: @@ -328,7 +319,7 @@ public class ASM3Parser { expected(ParsedSymbol.TYPE_PARENT_OPEN, "(", lexer); ParsedSymbol rtqName = lexer.lex(); expected(rtqName, ParsedSymbol.TYPE_STRING, "String"); - name_index = constants.forceGetStringId((String) rtqName.value); + name_index = constants.getStringId((String) rtqName.value, true); expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); break; case ParsedSymbol.TYPE_KEYWORD_RTQNAMEL: @@ -341,7 +332,7 @@ public class ASM3Parser { expected(ParsedSymbol.TYPE_PARENT_OPEN, "(", lexer); ParsedSymbol mName = lexer.lex(); expected(mName, ParsedSymbol.TYPE_STRING, "String"); - name_index = constants.forceGetStringId((String) mName.value); + name_index = constants.getStringId((String) mName.value, true); expected(ParsedSymbol.TYPE_COMMA, ",", lexer); namespace_set_index = parseNamespaceSet(constants, lexer); expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); @@ -366,20 +357,8 @@ public class ASM3Parser { expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); break; } - loopm: - for (int m = 1; m < constants.constant_multiname.length; m++) { - Multiname mul = constants.constant_multiname[m]; - if (mul.kind == kind && mul.name_index == name_index && mul.namespace_index == namespace_index && mul.namespace_set_index == namespace_set_index && mul.qname_index == qname_index && mul.params.size() == params.size()) { - for (int p = 0; p < mul.params.size(); p++) { - if (mul.params.get(p) != params.get(p)) { - continue loopm; - } - } - return m; - } - } - return constants.addMultiname(new Multiname(kind, name_index, namespace_index, namespace_set_index, qname_index, params)); + return constants.getMultinameId(new Multiname(kind, name_index, namespace_index, namespace_set_index, qname_index, params), true); } public static ValueKind parseValue(ConstantPool constants, Flasm3Lexer lexer) throws IOException, ParseException { @@ -394,7 +373,7 @@ public class ASM3Parser { value = lexer.lex(); expected(value, ParsedSymbol.TYPE_INTEGER, "Integer"); expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); - value_index = constants.forceGetIntId((Long) value.value); + value_index = constants.getIntId((Long) value.value, true); break; case ParsedSymbol.TYPE_KEYWORD_UINTEGER: value_kind = ValueKind.CONSTANT_UInt; @@ -402,7 +381,7 @@ public class ASM3Parser { value = lexer.lex(); expected(value, ParsedSymbol.TYPE_INTEGER, "UInteger"); expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); - value_index = constants.forceGetUIntId((Long) value.value); + value_index = constants.getUIntId((Long) value.value, true); break; case ParsedSymbol.TYPE_KEYWORD_DOUBLE: value_kind = ValueKind.CONSTANT_Double; @@ -410,7 +389,7 @@ public class ASM3Parser { value = lexer.lex(); expected(value, ParsedSymbol.TYPE_FLOAT, "Double"); expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); - value_index = constants.forceGetDoubleId((Double) value.value); + value_index = constants.getDoubleId((Double) value.value, true); break; /*case ParsedSymbol.TYPE_KEYWORD_DECIMAL: value_kind = ValueKind.CONSTANT_Decimal; @@ -421,7 +400,7 @@ public class ASM3Parser { value = lexer.lex(); expected(value, ParsedSymbol.TYPE_STRING, "String"); expected(ParsedSymbol.TYPE_PARENT_CLOSE, ")", lexer); - value_index = constants.forceGetStringId((String) value.value); + value_index = constants.getStringId((String) value.value, true); break; case ParsedSymbol.TYPE_KEYWORD_TRUE: value_kind = ValueKind.CONSTANT_True; @@ -540,7 +519,7 @@ public class ASM3Parser { if (symb.type == ParsedSymbol.TYPE_KEYWORD_NAME) { symb = lexer.lex(); expected(symb, ParsedSymbol.TYPE_STRING, "String"); - info.name_index = constants.forceGetStringId((String) symb.value); + info.name_index = constants.getStringId((String) symb.value, true); continue; } if (symb.type == ParsedSymbol.TYPE_KEYWORD_PARAM) { @@ -550,7 +529,7 @@ public class ASM3Parser { if (symb.type == ParsedSymbol.TYPE_KEYWORD_PARAMNAME) { symb = lexer.lex(); expected(symb, ParsedSymbol.TYPE_STRING, "String"); - paramNames.add(constants.forceGetStringId((String) symb.value)); + paramNames.add(constants.getStringId((String) symb.value, true)); continue; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/methodinfo_parser/MethodInfoParser.java b/trunk/src/com/jpexs/decompiler/flash/abc/methodinfo_parser/MethodInfoParser.java index 00d2ebef1..cbe8de8b3 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/methodinfo_parser/MethodInfoParser.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/methodinfo_parser/MethodInfoParser.java @@ -62,13 +62,13 @@ public class MethodInfoParser { int id = 0; switch (symbValue.type) { case ParsedSymbol.TYPE_INTEGER: - value = new ValueKind(abc.constants.forceGetIntId((Long) symbValue.value), ValueKind.CONSTANT_Int); + value = new ValueKind(abc.constants.getIntId((Long) symbValue.value, true), ValueKind.CONSTANT_Int); break; case ParsedSymbol.TYPE_FLOAT: - value = new ValueKind(abc.constants.forceGetDoubleId((Double) symbValue.value), ValueKind.CONSTANT_Double); + value = new ValueKind(abc.constants.getDoubleId((Double) symbValue.value, true), ValueKind.CONSTANT_Double); break; case ParsedSymbol.TYPE_STRING: - value = new ValueKind(abc.constants.forceGetStringId((String) symbValue.value), ValueKind.CONSTANT_Utf8); + value = new ValueKind(abc.constants.getStringId((String) symbValue.value, true), ValueKind.CONSTANT_Utf8); break; case ParsedSymbol.TYPE_TRUE: value = new ValueKind(0, ValueKind.CONSTANT_True); @@ -200,13 +200,13 @@ public class MethodInfoParser { int id = 0; switch (symbValue.type) { case ParsedSymbol.TYPE_INTEGER: - optionalValues.add(new ValueKind(abc.constants.forceGetIntId((Long) symbValue.value), ValueKind.CONSTANT_Int)); + optionalValues.add(new ValueKind(abc.constants.getIntId((Long) symbValue.value, true), ValueKind.CONSTANT_Int)); break; case ParsedSymbol.TYPE_FLOAT: - optionalValues.add(new ValueKind(abc.constants.forceGetDoubleId((Double) symbValue.value), ValueKind.CONSTANT_Double)); + optionalValues.add(new ValueKind(abc.constants.getDoubleId((Double) symbValue.value, true), ValueKind.CONSTANT_Double)); break; case ParsedSymbol.TYPE_STRING: - optionalValues.add(new ValueKind(abc.constants.forceGetStringId((String) symbValue.value), ValueKind.CONSTANT_Utf8)); + optionalValues.add(new ValueKind(abc.constants.getStringId((String) symbValue.value, true), ValueKind.CONSTANT_Utf8)); break; case ParsedSymbol.TYPE_TRUE: optionalValues.add(new ValueKind(0, ValueKind.CONSTANT_True)); @@ -304,7 +304,7 @@ public class MethodInfoParser { update.setFlagHas_paramnames(); update.paramNames = new int[paramNames.size()]; for (int p = 0; p < paramNames.size(); p++) { - update.paramNames[p] = abc.constants.forceGetStringId(paramNames.get(p)); + update.paramNames[p] = abc.constants.getStringId(paramNames.get(p), true); } } return true; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/Namespace.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/Namespace.java index be9222810..172a1cf60 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/Namespace.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/Namespace.java @@ -34,6 +34,24 @@ public class Namespace { public int kind; public int name_index; + public static String kindToStr(int kind) { + for (int i = 0; i < nameSpaceKinds.length; i++) { + if (nameSpaceKinds[i] == kind) { + return nameSpaceKindNames[i]; + } + } + return null; + } + + public static String kindToPrefix(int kind) { + for (int i = 0; i < nameSpaceKinds.length; i++) { + if (nameSpaceKinds[i] == kind) { + return namePrefixes[i]; + } + } + return null; + } + public Namespace(int kind, int name_index) { this.kind = kind; this.name_index = name_index; diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java index c3f97d9b8..45edf77bd 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/TraitSlotConst.java @@ -92,7 +92,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot { } if (assignedValue != null) { - valueStr = Highlighting.trim(assignedValue.toString(true, abc.constants, new HashMap(), fullyQualifiedNames)); + valueStr = Highlighting.trim(assignedValue.toString(highlight, abc.constants, new HashMap(), fullyQualifiedNames)); if (highlight && (parent instanceof TraitClass)) { TraitClass tc = (TraitClass) parent; int traitInitId = abc.class_info[tc.class_info].static_traits.traits.length diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index bd7c4a783..0d859ff58 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import java.io.Serializable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -34,6 +35,12 @@ public class Traits implements Serializable { public Trait[] traits = new Trait[0]; + public int addTrait(Trait t) { + traits = Arrays.copyOf(traits, traits.length + 1); + traits[traits.length - 1] = t; + return traits.length - 1; + } + public int removeTraps(int scriptIndex, int classIndex, boolean isStatic, ABC abc, String path) { int ret = 0; for (Trait t : traits) { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index f6abe42a5..8e4b28435 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -21,6 +21,17 @@ import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ClassPath; import com.jpexs.decompiler.flash.abc.ScriptPack; +import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.types.ABCException; +import com.jpexs.decompiler.flash.abc.types.MethodBody; +import com.jpexs.decompiler.flash.abc.types.MethodInfo; +import com.jpexs.decompiler.flash.abc.types.Multiname; +import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.abc.types.ValueKind; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.abc.types.traits.TraitMethodGetterSetter; +import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst; +import com.jpexs.decompiler.flash.abc.types.traits.Traits; import static com.jpexs.decompiler.flash.gui.AppStrings.translate; import com.jpexs.decompiler.flash.gui.Freed; import com.jpexs.decompiler.flash.gui.HeaderLabel; @@ -90,6 +101,8 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr private String searchFor; private boolean searchIgnoreCase; private boolean searchRegexp; + private NewTraitDialog newTraitDialog; + public JLabel scriptNameLabel; public boolean search(String txt, boolean ignoreCase, boolean regexp) { if ((txt != null) && (!txt.equals(""))) { @@ -283,9 +296,31 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr decompiledScrollPane = new JScrollPane(decompiledTextArea); + + JPanel iconDecPanel = new JPanel(); + iconDecPanel.setLayout(new BoxLayout(iconDecPanel, BoxLayout.Y_AXIS)); + JPanel iconsPanel = new JPanel(); + iconsPanel.setLayout(new BoxLayout(iconsPanel, BoxLayout.X_AXIS)); + + JButton newTraitButton = new JButton(View.getIcon("traitadd16")); + newTraitButton.setMargin(new Insets(5, 5, 5, 5)); + newTraitButton.addActionListener(this); + newTraitButton.setActionCommand("ADDTRAIT"); + newTraitButton.setToolTipText(translate("button.addtrait")); + iconsPanel.add(newTraitButton); + + + scriptNameLabel = new JLabel("-"); + scriptNameLabel.setAlignmentX(0); + iconsPanel.setAlignmentX(0); + decompiledScrollPane.setAlignmentX(0); + iconDecPanel.add(scriptNameLabel); + iconDecPanel.add(iconsPanel); + iconDecPanel.add(decompiledScrollPane); + JPanel decPanel = new JPanel(new BorderLayout()); decPanel.add(searchPanel, BorderLayout.NORTH); - decPanel.add(decompiledScrollPane, BorderLayout.CENTER); + decPanel.add(iconDecPanel, BorderLayout.CENTER); detailPanel = new DetailPanel(this); JPanel panB = new JPanel(); panB.setLayout(new BorderLayout()); @@ -535,25 +570,124 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Fr @Override public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("FILTERSCRIPT")) { - doFilter(); - } - if (e.getActionCommand().equals("SEARCHCANCEL")) { - foundPos = 0; - searchPanel.setVisible(false); - found = new ArrayList<>(); - searchFor = null; - } - if (e.getActionCommand().equals("SEARCHPREV")) { - foundPos--; - if (foundPos < 0) { - foundPos += found.size(); - } - updateSearchPos(); - } - if (e.getActionCommand().equals("SEARCHNEXT")) { - foundPos = (foundPos + 1) % found.size(); - updateSearchPos(); + switch (e.getActionCommand()) { + case "ADDTRAIT": + int class_index = decompiledTextArea.getClassIndex(); + if (class_index < 0) { + return; + } + if (newTraitDialog == null) { + newTraitDialog = new NewTraitDialog(); + } + int void_type = abc.constants.getPublicQnameId("void", true);//abc.constants.forceGetMultinameId(new Multiname(Multiname.QNAME, abc.constants.forceGetStringId("void"), abc.constants.forceGetNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.forceGetStringId("")), 0), -1, -1, new ArrayList())); + int int_type = abc.constants.getPublicQnameId("int", true); //abc.constants.forceGetMultinameId(new Multiname(Multiname.QNAME, abc.constants.forceGetStringId("int"), abc.constants.forceGetNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abc.constants.forceGetStringId("")), 0), -1, -1, new ArrayList())); + + Trait t = null; + int kind; + int nskind; + String name = null; + boolean isStatic; + Multiname m; + + boolean again = false; + loopm: + do { + if (again) { + View.showMessageDialog(null, translate("error.trait.exists").replace("%name%", name), translate("error"), JOptionPane.ERROR_MESSAGE); + } + again = false; + if (!newTraitDialog.display()) { + return; + } + kind = newTraitDialog.getTraitType(); + nskind = newTraitDialog.getNamespaceKind(); + name = newTraitDialog.getTraitName(); + isStatic = newTraitDialog.getStatic(); + m = new Multiname(Multiname.QNAME, abc.constants.getStringId(name, true), abc.constants.getNamespaceId(new Namespace(nskind, abc.constants.getStringId("", true)), 0, true), -1, -1, new ArrayList()); + int mid = abc.constants.getMultinameId(m); + if (mid == 0) { + break; + } + for (Trait tr : abc.class_info[class_index].static_traits.traits) { + if (tr.name_index == mid) { + again = true; + break; + } + } + + for (Trait tr : abc.instance_info[class_index].instance_traits.traits) { + if (tr.name_index == mid) { + again = true; + break; + } + } + } while (again); + switch (kind) { + case Trait.TRAIT_GETTER: + case Trait.TRAIT_SETTER: + case Trait.TRAIT_METHOD: + TraitMethodGetterSetter tm = new TraitMethodGetterSetter(); + MethodInfo mi = new MethodInfo(new int[0], void_type, abc.constants.getStringId(name, true), 0, new ValueKind[0], new int[0]); + int method_info = abc.addMethodInfo(mi); + tm.method_info = method_info; + MethodBody body = new MethodBody(); + body.method_info = method_info; + body.init_scope_depth = 1; + body.max_regs = 1; + body.max_scope_depth = 1; + body.max_stack = 1; + body.exceptions = new ABCException[0]; + AVM2Code code = new AVM2Code(); + body.code = code; + Traits traits = new Traits(); + traits.traits = new Trait[0]; + body.traits = traits; + abc.addMethodBody(body); + t = tm; + break; + case Trait.TRAIT_SLOT: + case Trait.TRAIT_CONST: + TraitSlotConst ts = new TraitSlotConst(); + ts.type_index = int_type; + ts.value_kind = ValueKind.CONSTANT_Int; + ts.value_index = abc.constants.getIntId(0, true); + t = ts; + break; + } + if (t != null) { + t.kindType = kind; + t.name_index = abc.constants.getMultinameId(m, true); + int traitId; + if (isStatic) { + traitId = abc.class_info[class_index].static_traits.addTrait(t); + } else { + traitId = abc.class_info[class_index].static_traits.traits.length + abc.instance_info[class_index].instance_traits.addTrait(t); + } + reload(); + decompiledTextArea.gotoTrait(traitId); + } + + break; + case "FILTERSCRIPT": + doFilter(); + break; + case "SEARCHCANCEL": + foundPos = 0; + searchPanel.setVisible(false); + found = new ArrayList<>(); + searchFor = null; + break; + case "SEARCHPREV": + foundPos--; + if (foundPos < 0) { + foundPos += found.size(); + } + updateSearchPos(); + break; + case "SEARCHNEXT": + foundPos = (foundPos + 1) % found.size(); + updateSearchPos(); + break; } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index dc8fb0b83..059db05b2 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -460,6 +460,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL } public void setScript(ScriptPack scriptLeaf, List abcList) { + abcPanel.scriptNameLabel.setText(scriptLeaf.getPath().toString()); int scriptIndex = scriptLeaf.scriptIndex; ScriptInfo script = null; ABC abc = scriptLeaf.abc; diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java index 84f0fed31..60468c3ea 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/DetailPanel.java @@ -53,7 +53,7 @@ public class DetailPanel extends JPanel implements ActionListener { private boolean editMode = false; private JPanel buttonsPanel; private ABCPanel abcPanel; - private JTextArea traitNameLabel; + private JLabel traitNameLabel; public DetailPanel(ABCPanel abcPanel) { this.abcPanel = abcPanel; @@ -105,10 +105,10 @@ public class DetailPanel extends JPanel implements ActionListener { selectedLabel.setHorizontalAlignment(SwingConstants.CENTER); JPanel topPanel = new JPanel(new BorderLayout()); topPanel.add(selectedLabel, BorderLayout.NORTH); - traitNameLabel = new JTextArea(""); + traitNameLabel = new JLabel(""); JPanel traitInfoPanel = new JPanel(); traitInfoPanel.setLayout(new BoxLayout(traitInfoPanel, BoxLayout.LINE_AXIS)); - traitInfoPanel.add(new JLabel(" " + translate("abc.detail.traitname"))); + //traitInfoPanel.add(new JLabel(" " + translate("abc.detail.traitname"))); traitInfoPanel.add(traitNameLabel); topPanel.add(traitInfoPanel, BorderLayout.CENTER); add(topPanel, BorderLayout.NORTH); @@ -155,7 +155,7 @@ public class DetailPanel extends JPanel implements ActionListener { if (trait == null) { traitNameLabel.setText("-"); } else { - traitNameLabel.setText(" " + trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, new ArrayList()) + " Index: " + trait.name_index); + traitNameLabel.setText(trait.getName(abcPanel.abc).getName(abcPanel.abc.constants, new ArrayList())); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/NewTraitDialog.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/NewTraitDialog.java new file mode 100644 index 000000000..f26bda0d7 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/NewTraitDialog.java @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2013 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 . + */ +package com.jpexs.decompiler.flash.gui.abc; + +import com.jpexs.decompiler.flash.abc.types.Namespace; +import com.jpexs.decompiler.flash.abc.types.traits.Trait; +import com.jpexs.decompiler.flash.gui.AppDialog; +import com.jpexs.decompiler.flash.gui.AppStrings; +import com.jpexs.decompiler.flash.gui.View; +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JComponent; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.event.AncestorEvent; +import javax.swing.event.AncestorListener; + +/** + * + * @author JPEXS + */ +public class NewTraitDialog extends AppDialog implements ActionListener { + + private static int modifiers[] = new int[]{ + Namespace.KIND_PACKAGE, + Namespace.KIND_PRIVATE, + Namespace.KIND_PROTECTED, + Namespace.KIND_NAMESPACE, + Namespace.KIND_PACKAGE_INTERNAL, + Namespace.KIND_EXPLICIT, + Namespace.KIND_STATIC_PROTECTED + }; + private static int types[] = new int[]{ + Trait.TRAIT_METHOD, + Trait.TRAIT_GETTER, + Trait.TRAIT_SETTER, + Trait.TRAIT_CONST, + Trait.TRAIT_SLOT + }; + private JComboBox accessComboBox; + private JComboBox typeComboBox; + private JCheckBox staticCheckbox; + private JTextField nameField; + + public boolean getStatic() { + return staticCheckbox.isSelected(); + } + + public int getNamespaceKind() { + return modifiers[accessComboBox.getSelectedIndex()]; + } + + public int getTraitType() { + return types[typeComboBox.getSelectedIndex()]; + } + + public String getTraitName() { + return nameField.getText(); + } + + public NewTraitDialog() { + setSize(500, 300); + setTitle(translate("dialog.title")); + View.centerScreen(this); + View.setWindowIcon(this); + Container cnt = getContentPane(); + cnt.setLayout(new BorderLayout()); + JPanel optionsPanel = new JPanel(new FlowLayout()); + //optionsPanel.add(new JLabel(translate("label.type"))); + typeComboBox = new JComboBox<>(new String[]{ + translate("type.method"), + translate("type.getter"), + translate("type.setter"), + translate("type.const"), + translate("type.slot"),}); + staticCheckbox = new JCheckBox(translate("checkbox.static")); + optionsPanel.add(staticCheckbox); + String accessStrings[] = new String[modifiers.length]; + for (int i = 0; i < accessStrings.length; i++) { + String pref = Namespace.kindToPrefix(modifiers[i]); + String name = Namespace.kindToStr(modifiers[i]); + accessStrings[i] = (pref.equals("") ? "" : pref + " ") + "(" + name + ")"; + } + + + //optionsPanel.add(new JLabel(translate("label.access"))); + accessComboBox = new JComboBox<>(accessStrings); + optionsPanel.add(accessComboBox); + + optionsPanel.add(typeComboBox); + + + //optionsPanel.add(new JLabel(translate("label.name"))); + + nameField = new JTextField(); + nameField.setPreferredSize(new Dimension(300, nameField.getPreferredSize().height)); + optionsPanel.add(nameField); + + cnt.add(optionsPanel, BorderLayout.CENTER); + JPanel buttonsPanel = new JPanel(new FlowLayout()); + JButton buttonOk = new JButton(AppStrings.translate("button.ok")); + buttonOk.setActionCommand("OK"); + buttonOk.addActionListener(this); + JButton buttonCancel = new JButton(AppStrings.translate("button.cancel")); + buttonCancel.setActionCommand("CANCEL"); + buttonCancel.addActionListener(this); + buttonsPanel.add(buttonOk); + buttonsPanel.add(buttonCancel); + cnt.add(buttonsPanel, BorderLayout.SOUTH); + pack(); + setDefaultCloseOperation(HIDE_ON_CLOSE); + setModalityType(ModalityType.APPLICATION_MODAL); + + nameField.addAncestorListener(new AncestorListener() { + @Override + public void ancestorAdded(AncestorEvent event) { + JComponent component = event.getComponent(); + component.requestFocusInWindow(); + } + + @Override + public void ancestorRemoved(AncestorEvent event) { + } + + @Override + public void ancestorMoved(AncestorEvent event) { + } + }); + getRootPane().setDefaultButton(buttonOk); + } + + public boolean display() { + nameField.setText(""); + setVisible(true); + return result; + } + private boolean result = false; + + @Override + public void actionPerformed(ActionEvent e) { + switch (e.getActionCommand()) { + case "OK": + if (nameField.getText().trim().equals("")) { + View.showMessageDialog(null, translate("error.name"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE); + return; + } + result = true; + setVisible(false); + break; + case "CANCEL": + result = false; + setVisible(false); + break; + } + + } +} diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java b/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java index abbd71f15..b2170157a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/abc/TraitsListItem.java @@ -64,15 +64,18 @@ public class TraitsListItem { @Override public String toString() { + String s = ""; if ((type != Type.INITIALIZER) && isStatic) { - return abc.class_info[classIndex].static_traits.traits[index].convertHeader(null, "", abcTags, abc, true, false, scriptIndex, classIndex, false, new ArrayList(), false); + s = abc.class_info[classIndex].static_traits.traits[index].convertHeader(null, "", abcTags, abc, true, false, scriptIndex, classIndex, false, new ArrayList(), false); } else if ((type != Type.INITIALIZER) && (!isStatic)) { - return abc.instance_info[classIndex].instance_traits.traits[index].convertHeader(null, "", abcTags, abc, false, false, scriptIndex, classIndex, false, new ArrayList(), false); + s = abc.instance_info[classIndex].instance_traits.traits[index].convertHeader(null, "", abcTags, abc, false, false, scriptIndex, classIndex, false, new ArrayList(), false); } else if (!isStatic) { - return STR_INSTANCE_INITIALIZER; + s = STR_INSTANCE_INITIALIZER; } else { - return STR_CLASS_INITIALIZER; + s = STR_CLASS_INITIALIZER; } + s = s.replaceAll("[ \r\n]+", " "); + return s; } public Type getType() { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/graphics/traitadd16.png b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/traitadd16.png new file mode 100644 index 000000000..f135248f8 Binary files /dev/null and b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/traitadd16.png differ diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index 808b8f41c..90d038090 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -355,3 +355,7 @@ preview.stop = Stop message.confirm.removemultiple = Are you sure you want to remove %count% items\n and all objects which depend on it? menu.tools.searchcache = Search browsers cache + +#after version 1.7.2u2 +error.trait.exists = Trait with name "%name%" already exists. +button.addtrait = Add trait \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index 4beb23f05..1590a3b8f 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -359,4 +359,8 @@ preview.stop = Zastavit message.confirm.removemultiple = Opravdu chcete odebrat %count% polo\u017eek\n a v\u0161echny objekty kter\u00e9 na nich z\u00e1vis\u00ed? -menu.tools.searchcache = Prohledat cache prohl\u00ed\u017ee\u010d\u016f \ No newline at end of file +menu.tools.searchcache = Prohledat cache prohl\u00ed\u017ee\u010d\u016f + +#after version 1.7.2u2 +error.trait.exists = Vlastnost s n\u00e1zvem "%name%" ji\u017e existuje. +button.addtrait = P\u0159idat vlastnost \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/abc/NewTraitDialog.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/abc/NewTraitDialog.properties new file mode 100644 index 000000000..fd03faffd --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/abc/NewTraitDialog.properties @@ -0,0 +1,24 @@ +# Copyright (C) 2013 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 . + +type.method = Method +type.getter = Getter +type.setter = Setter +type.const = Const +type.slot = Slot (var) +checkbox.static = Static +dialog.title = New trait + +error.name = You must specify trait name \ No newline at end of file diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/locales/abc/NewTraitDialog_cs.properties b/trunk/src/com/jpexs/decompiler/flash/gui/locales/abc/NewTraitDialog_cs.properties new file mode 100644 index 000000000..0f0c5b431 --- /dev/null +++ b/trunk/src/com/jpexs/decompiler/flash/gui/locales/abc/NewTraitDialog_cs.properties @@ -0,0 +1,24 @@ +# Copyright (C) 2013 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 . + +type.method = Metoda +type.getter = Getter +type.setter = Setter +type.const = Konstanta +type.slot = Slot (var) +checkbox.static = Static +dialog.title = Nov\u00e1 vlastnost + +error.name = Mus\u00edte uv\u00e9st n\u00e1zev vlastnosti \ No newline at end of file