From c9216538be7528beb03bf9245084df588818ffe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 1 Jun 2025 13:09:09 +0200 Subject: [PATCH] Added: AS3 - navigation to definition in other SWF file and also player/airglobal --- CHANGELOG.md | 1 + lib/jsyntaxpane-0.9.5.jar | Bin 607495 -> 607458 bytes .../src/com/jpexs/decompiler/flash/SWF.java | 6 +- .../abc/avm2/parser/script/AbcIndexing.java | 23 +- .../script/ActionScript3SimpleParser.java | 53 ++-- .../script/ActionScript2SimpleParser.java | 9 +- .../flash/configuration/Configuration.java | 10 +- .../flash/simpleparser/SimpleParser.java | 68 +++-- src/com/jpexs/decompiler/flash/gui/Main.java | 8 +- .../jpexs/decompiler/flash/gui/MainPanel.java | 100 ++++--- .../flash/gui/OpenableListLoaded.java | 27 ++ .../decompiler/flash/gui/abc/ABCPanel.java | 100 ++++++- .../flash/gui/abc/DecompiledEditorPane.java | 16 +- .../gui/editor/LineMarkedEditorPane.java | 15 +- .../flash/gui/editor/LinkHandler.java | 6 +- .../flash/gui/editor/VariableMarker.java | 248 +++++++++++++++--- .../locales/AdvancedSettingsDialog.properties | 4 + .../AdvancedSettingsDialog_cs.properties | 5 + .../flash/gui/locales/MainFrame.properties | 12 +- .../flash/gui/locales/MainFrame_cs.properties | 16 +- 20 files changed, 575 insertions(+), 152 deletions(-) create mode 100644 src/com/jpexs/decompiler/flash/gui/OpenableListLoaded.java diff --git a/CHANGELOG.md b/CHANGELOG.md index b22501a40..9bccd101a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to this project will be documented in this file. - AS1/2/3 - highlight variables and errors on panel next to vertical scrollbar - AS1/2 direct editation - hide P-code panel when editing - Disable AS1/2/3 direct editation when editing P-code +- AS3 - navigation to definition in other SWF file and also player/airglobal ### Changed - AS1/2 - Single DoAction tag inside frame is now displayed directly as frame node diff --git a/lib/jsyntaxpane-0.9.5.jar b/lib/jsyntaxpane-0.9.5.jar index 9841945df193b6433b8870bd905601fc6f39b6a2..f390b1cc90a0390768daf855cdd8c4e43052ea6b 100644 GIT binary patch delta 17983 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 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 33275ffab..ca5c88572 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -797,7 +797,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { if (Configuration.getPlayerSWC() != null) { SWC swc = new SWC(Configuration.getPlayerSWC()); //set allowRenameIdentifiers parameter to FALSE otherwise there will be an infinite loop - SWF swf = new SWF(swc.getOpenable("library.swf"), null, null, null, true, false, true, null, "WINDOWS-1252", false); + SWF swf = new SWF(swc.getOpenable("library.swf"), null, "__playerglobal", null, true, false, true, null, "WINDOWS-1252", false); playerGlobalAbcIndex = new AbcIndexing(swf); } } @@ -805,12 +805,12 @@ public final class SWF implements SWFContainerItem, Timelined, Openable { if (Configuration.getAirSWC() != null) { SWC swc = new SWC(Configuration.getAirSWC()); //set allowRenameIdentifiers to FALSE - SWF swf = new SWF(swc.getOpenable("library.swf"), null, null, null, true, false, true, null, "WINDOWS-1252", false); + SWF swf = new SWF(swc.getOpenable("library.swf"), null, "__airglobal", null, true, false, true, null, "WINDOWS-1252", false); airGlobalAbcIndex = new AbcIndexing(swf); } } } - + /** * Gets SWF charset. SWF version 5 or lower were non-unicode. SWF object has * assigned charset. diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java index f1553a623..a0821bb5f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AbcIndexing.java @@ -384,6 +384,11 @@ public final class AbcIndexing { * Object type */ public GraphTargetItem objType; + + /** + * Script index + */ + public int scriptIndex; /** * Constructs trait index @@ -393,14 +398,16 @@ public final class AbcIndexing { * @param callType Call type * @param value Value * @param objType Object type + * @param scriptIndex Script index */ - public TraitIndex(Trait trait, ABC abc, GraphTargetItem type, GraphTargetItem callType, ValueKind value, GraphTargetItem objType) { + public TraitIndex(Trait trait, ABC abc, GraphTargetItem type, GraphTargetItem callType, ValueKind value, GraphTargetItem objType, int scriptIndex) { this.trait = trait; this.abc = abc; this.returnType = type; this.callReturnType = callType; this.value = value; this.objType = objType; + this.scriptIndex = scriptIndex; } } @@ -775,7 +782,7 @@ public final class AbcIndexing { */ //search all static first if (findStatic && classProperties.containsKey(prop)) { - TraitIndex ti = classProperties.get(prop); + TraitIndex ti = classProperties.get(prop); if (ti != null) { foundStatic.setVal(true); return ti; @@ -933,7 +940,7 @@ public final class AbcIndexing { * @param map Map to index * @param mapNs Map to index */ - protected void indexTraits(ABC abc, int name_index, Traits ts, Map map, Map mapNs) { + protected void indexTraits(ABC abc, int name_index, Traits ts, Map map, Map mapNs, int scriptIndex) { for (Trait t : ts.traits) { ValueKind propValue = null; if (t instanceof TraitSlotConst) { @@ -942,12 +949,12 @@ public final class AbcIndexing { } if (map != null) { PropertyDef dp = new PropertyDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true, false), multinameToType(name_index, abc.constants), abc, abc.constants.getMultiname(t.name_index).namespace_index); - map.put(dp, new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants))); + map.put(dp, new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants), scriptIndex)); } if (mapNs != null) { Multiname m = abc.constants.getMultiname(t.name_index); PropertyNsDef ndp = new PropertyNsDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true, true/*FIXME ???*/), m == null || m.namespace_index == 0 ? DottedChain.EMPTY : m.getNamespace(abc.constants).getName(abc.constants), abc, m == null ? 0 : m.namespace_index); - TraitIndex ti = new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants)); + TraitIndex ti = new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants), scriptIndex); if (!mapNs.containsKey(ndp)) { mapNs.put(ndp, ti); } @@ -1038,7 +1045,7 @@ public final class AbcIndexing { List addedClasses = new ArrayList<>(); for (int i = 0; i < abc.script_info.size(); i++) { - indexTraits(abc, 0, abc.script_info.get(i).traits, null, scriptProperties); + indexTraits(abc, 0, abc.script_info.get(i).traits, null, scriptProperties, i); for (int t = 0; t < abc.script_info.get(i).traits.traits.size(); t++) { Trait tr = abc.script_info.get(i).traits.traits.get(t); if (tr instanceof TraitClass) { @@ -1055,8 +1062,8 @@ public final class AbcIndexing { GraphTargetItem cname = multinameToType(ii.name_index, abc.constants); classes.put(new ClassDef(cname, abc, classScriptIndex), cindex); - indexTraits(abc, ii.name_index, ii.instance_traits, instanceProperties, instanceNsProperties); - indexTraits(abc, ii.name_index, ci.static_traits, classProperties, classNsProperties); + indexTraits(abc, ii.name_index, ii.instance_traits, instanceProperties, instanceNsProperties, i); + indexTraits(abc, ii.name_index, ci.static_traits, classProperties, classNsProperties, i); } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java index 584fe9239..8e1b36bbe 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ActionScript3SimpleParser.java @@ -811,7 +811,8 @@ public class ActionScript3SimpleParser implements SimpleParser { List> allOpenedNamespaces, ABC abc, Reference sinitNeedsActivation, - List sinitVariables + List sinitVariables, + List externalTypes ) throws AVM2ParseException, SimpleParseException, IOException, CompilationException, InterruptedException { Stack sinitLoops = new Stack<>(); @@ -828,7 +829,8 @@ public class ActionScript3SimpleParser implements SimpleParser { sinitLoops, sinitLoopLabels, sinitRegisterVars, - sinitVariables + sinitVariables, + externalTypes )) { //empty } @@ -844,7 +846,8 @@ public class ActionScript3SimpleParser implements SimpleParser { Stack sinitLoops, Map sinitLoopLabels, HashMap sinitRegisterVars, - List sinitVariables + List sinitVariables, + List externalTypes ) throws AVM2ParseException, SimpleParseException, SimpleParseException, IOException, CompilationException, InterruptedException { ParsedSymbol s; boolean inPackage = false; @@ -872,7 +875,13 @@ public class ActionScript3SimpleParser implements SimpleParser { allOpenedNamespaces.add(openedNamespaces); - parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc); + for (String name : abc.getSwf().getAbcIndex().getPackageObjects(pkgName)) { + externalTypes.add(pkgName.add(name, "").toRawString()); + } + + + + parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc, externalTypes); boolean isEmpty = true; @@ -1061,7 +1070,7 @@ public class ActionScript3SimpleParser implements SimpleParser { lexer.pushback(preSymbols.get(i)); } - if (parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc)) { + if (parseImportsUsages(errors, sinitVariables, importedClasses, openedNamespaces, abc, externalTypes)) { break; } boolean cmd = command(errors, null, sinitNeedsActivation, importedClasses, openedNamespaces, sinitLoops, sinitLoopLabels, sinitRegisterVars, true, false, true, 0, false, sinitVariables, abc); @@ -2006,7 +2015,7 @@ public class ActionScript3SimpleParser implements SimpleParser { private ActionScriptLexer lexer = null; - private boolean parseImportsUsages(List errors, List variables, List importedClasses, List openedNamespaces, ABC abc) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { + private boolean parseImportsUsages(List errors, List variables, List importedClasses, List openedNamespaces, ABC abc, List externalTypes) throws IOException, AVM2ParseException, SimpleParseException, InterruptedException { boolean isEmpty = true; ParsedSymbol s; @@ -2023,6 +2032,8 @@ public class ActionScript3SimpleParser implements SimpleParser { s = lex(); boolean isStar = false; int varPos = -1; + List nameParts = new ArrayList<>(); + nameParts.add(lastName); while (s.type == SymbolType.DOT) { s = lex(); if (s.type == SymbolType.MULTIPLY) { @@ -2034,13 +2045,16 @@ public class ActionScript3SimpleParser implements SimpleParser { fullName = fullName + "." + s.value.toString(); lastName = s.value.toString(); varPos = s.position; + nameParts.add(lastName); s = lex(); } if (isStar) { - //openedNamespaces.add(new NamespaceItem(fullName, Namespace.KIND_PACKAGE)); + for (String n : abc.getSwf().getAbcIndex().getPackageObjects(new DottedChain(nameParts))) { + externalTypes.add(fullName + "." + n); + } } else { - //importedClasses.add(fullName); + externalTypes.add(fullName); variables.add(new Import(fullName, lastName, varPos)); } expected(errors, s, lexer.yyline(), SymbolType.SEMICOLON); @@ -2128,9 +2142,10 @@ public class ActionScript3SimpleParser implements SimpleParser { List> allOpenedNamespaces, ABC abc, Reference sinitNeedsActivation, - List sinitVariables + List sinitVariables, + List externalTypes ) throws IOException, AVM2ParseException, SimpleParseException, CompilationException, InterruptedException { - scriptTraits(errors, importedClasses, openedNamespaces, allOpenedNamespaces, abc, sinitNeedsActivation, sinitVariables); + scriptTraits(errors, importedClasses, openedNamespaces, allOpenedNamespaces, abc, sinitNeedsActivation, sinitVariables, externalTypes); } /** @@ -2157,11 +2172,12 @@ public class ActionScript3SimpleParser implements SimpleParser { String str, ABC abc, Reference sinitNeedsActivation, - List sinitVariables + List sinitVariables, + List externalTypes ) throws AVM2ParseException, SimpleParseException, IOException, CompilationException, InterruptedException { lexer = new ActionScriptLexer(str); - parseScript(errors, importedClasses, openedNamespaces, allOpenedNamespaces, abc, sinitNeedsActivation, sinitVariables); + parseScript(errors, importedClasses, openedNamespaces, allOpenedNamespaces, abc, sinitNeedsActivation, sinitVariables, externalTypes); ParsedSymbol s = lexer.lex(); if (s.type != SymbolType.EOF) { errors.add(new SimpleParseException("Parsing finished before end of the file", lexer.yyline(), s.position)); @@ -2173,15 +2189,22 @@ public class ActionScript3SimpleParser implements SimpleParser { String str, Map> definitionPosToReferences, Map referenceToDefinition, - List errors + List errors, + List externalTypes, + Map referenceToExternalTypeIndex, + Map> externalTypeIndexToReference ) throws SimpleParseException, IOException, InterruptedException { List> allOpenedNamespaces = new ArrayList<>(); Reference sinitNeedsActivation = new Reference<>(false); List vars = new ArrayList<>(); List importedClasses = new ArrayList<>(); List openedNamespaces = new ArrayList<>(); + for (String name : abc.getSwf().getAbcIndex().getPackageObjects(DottedChain.TOPLEVEL)) { + externalTypes.add(name); + } + externalTypes.add("__AS3__.vec.Vector"); try { - scriptTraitsFromString(errors, importedClasses, openedNamespaces, allOpenedNamespaces, str, abc, sinitNeedsActivation, vars); + scriptTraitsFromString(errors, importedClasses, openedNamespaces, allOpenedNamespaces, str, abc, sinitNeedsActivation, vars, externalTypes); } catch (AVM2ParseException ex) { //Logger.getLogger(ActionScript3SimpleParser.class.getName()).log(Level.SEVERE, null, ex); throw new SimpleParseException(str, ex.line, ex.position); @@ -2189,7 +2212,7 @@ public class ActionScript3SimpleParser implements SimpleParser { //Logger.getLogger(ActionScript3SimpleParser.class.getName()).log(Level.SEVERE, null, ex); throw new SimpleParseException(str, ex.line); } - SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, true); + SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, true, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference); } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java index 8d04f0d94..8d7f8ec5b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/parser/script/ActionScript2SimpleParser.java @@ -1570,9 +1570,12 @@ public class ActionScript2SimpleParser implements SimpleParser { String str, Map> definitionPosToReferences, Map referenceToDefinition, - List errors + List errors, + List externalTypes, + Map referenceToExternalTypeIndex, + Map> externalTypeIndexToReference ) throws SimpleParseException, IOException, InterruptedException { - + List vars = new ArrayList<>(); try { lexer = new ActionScriptLexer(new StringReader(str)); @@ -1661,7 +1664,7 @@ public class ActionScript2SimpleParser implements SimpleParser { } catch (ActionParseException ex) { errors.add(new SimpleParseException(ex.getMessage(), ex.line, ex.position)); } - SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, false); + SimpleParser.parseVariablesList(new ArrayList<>(), vars, definitionPosToReferences, referenceToDefinition, errors, false, externalTypes, referenceToExternalTypeIndex, externalTypeIndexToReference); } private void versionRequired(List errors, ParsedSymbol s, int min) throws SimpleParseException { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java index 1289b0ba4..452868f6a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/configuration/Configuration.java @@ -27,14 +27,9 @@ import com.jpexs.helpers.Helper; import com.jpexs.helpers.Path; import java.awt.Color; import java.awt.Font; -import java.io.BufferedOutputStream; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; import java.io.FilenameFilter; import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.net.URISyntaxException; import java.util.ArrayList; @@ -1145,6 +1140,11 @@ public final class Configuration { @ConfigurationDefaultBoolean(false) @ConfigurationCategory("display") public static ConfigurationItem snapAlignCenterAlignmentVertical = null; + + @ConfigurationDefaultBoolean(true) + @ConfigurationName("warning.linkTypes") + @ConfigurationCategory("script") + public static ConfigurationItem warningLinkTypes = null; private static Map configurationDescriptions = new LinkedHashMap<>(); private static Map configurationTitles = new LinkedHashMap<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java index 44b209fa9..6f03cf193 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/simpleparser/SimpleParser.java @@ -45,7 +45,10 @@ public interface SimpleParser { String str, Map> definitionPosToReferences, Map referenceToDefinition, - List errors + List errors, + List externalTypes, + Map referenceToExternalTypeIndex, + Map> externalTypeIndexToReference ) throws SimpleParseException, IOException, InterruptedException; public static void parseVariablesList( @@ -54,9 +57,22 @@ public interface SimpleParser { Map> definitionPosToReferences, Map referenceToDefinition, List errors, - boolean innerFunctionCanUseTraits + boolean innerFunctionCanUseTraits, + List externalTypes, + Map referenceToExternalTypeIndex, + Map> externalTypeIndexToReference ) { - parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), new LinkedHashMap<>(), true, errors, null, innerFunctionCanUseTraits); + List externalSimpleTypes = new ArrayList<>(); + for (String type : externalTypes) { + externalSimpleTypes.add(type.contains(".") ? type.substring(type.lastIndexOf(".") + 1) : type); + } + parseVariablesList(privateVariables, sharedVariables, definitionPosToReferences, referenceToDefinition, new LinkedHashMap<>(), new LinkedHashMap<>(), new LinkedHashMap<>(), true, errors, null, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex); + for (Map.Entry entry : referenceToExternalTypeIndex.entrySet()) { + if (!externalTypeIndexToReference.containsKey(entry.getValue())) { + externalTypeIndexToReference.put(entry.getValue(), new ArrayList<>()); + } + externalTypeIndexToReference.get(entry.getValue()).add(entry.getKey()); + } } public static void parseVariablesList( @@ -70,7 +86,9 @@ public interface SimpleParser { boolean isStatic, List errors, Scope scope, - boolean innerFunctionCanUseTraits + boolean innerFunctionCanUseTraits, + List externalSimpleTypes, + Map referenceToExternalTypeIndex ) { Map privateVarNameToDefinitionPosition = new LinkedHashMap<>(); privateVarNameToDefinitionPosition.putAll(parentVarNameToDefinitionPosition); @@ -89,13 +107,18 @@ public interface SimpleParser { } else { if (!privateVarFullNameToDefinitionPosition.containsKey(v.name) && !privateVarNameToDefinitionPosition.containsKey(v.name)) { - parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); - parentVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1); - privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); - privateVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1); - definitionPosToReferences.put(-v.position - 1, new ArrayList<>()); - definitionPosToReferences.get(-v.position - 1).add(v.position); - referenceToDefinition.put(v.position, -v.position - 1); + + if (externalSimpleTypes.contains(v.name)) { + referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name)); + } else { + parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); + parentVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1); + privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); + privateVarNameToDefinitionPosition.put(v.getLastName(), -v.position - 1); + definitionPosToReferences.put(-v.position - 1, new ArrayList<>()); + definitionPosToReferences.get(-v.position - 1).add(v.position); + referenceToDefinition.put(v.position, -v.position - 1); + } } else { if ("this".equals(v.name) && isStatic) { @@ -149,7 +172,7 @@ public interface SimpleParser { } } - parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits); + parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, subPrivateVarFullNameToDefinitionPosition, subPrivateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex); } } for (VariableOrScope vt : sharedVariables) { @@ -165,13 +188,18 @@ public interface SimpleParser { } else { if (!privateVarFullNameToDefinitionPosition.containsKey(v.name) && !privateVarNameToDefinitionPosition.containsKey(v.name)) { - parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); - parentVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1); - privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); - privateVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1); - definitionPosToReferences.put(-v.position - 1, new ArrayList<>()); - definitionPosToReferences.get(-v.position - 1).add(v.position); - referenceToDefinition.put(v.position, -v.position - 1); + + if (externalSimpleTypes.contains(v.name)) { + referenceToExternalTypeIndex.put(v.position, externalSimpleTypes.indexOf(v.name)); + } else { + parentVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); + parentVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1); + privateVarFullNameToDefinitionPosition.put(v.name, -v.position - 1); + privateVarNameToDefinitionPosition.put(v.getFirstName(), -v.position - 1); + definitionPosToReferences.put(-v.position - 1, new ArrayList<>()); + definitionPosToReferences.get(-v.position - 1).add(v.position); + referenceToDefinition.put(v.position, -v.position - 1); + } } else { if ("this".equals(v.name) && isStatic) { @@ -225,7 +253,7 @@ public interface SimpleParser { } } - parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits); + parseVariablesList(vs.getPrivateItems(), vs.getSharedItems(), definitionPosToReferences, referenceToDefinition, privateVarFullNameToDefinitionPosition, privateVarNameToDefinitionPosition, positionToStatic, subStatic, errors, vs, innerFunctionCanUseTraits, externalSimpleTypes, referenceToExternalTypeIndex); } } } diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java index 4773d8426..e0d21ae5d 100644 --- a/src/com/jpexs/decompiler/flash/gui/Main.java +++ b/src/com/jpexs/decompiler/flash/gui/Main.java @@ -1998,7 +1998,13 @@ public class Main { } swfFile = file.getCanonicalPath(); OpenableSourceInfo sourceInfo = new OpenableSourceInfo(null, swfFile, fileTitle); - OpenFileResult openResult = openFile(sourceInfo); + OpenFileResult openResult = openFile(sourceInfo, new OpenableOpened() { + @Override + public void opened(Openable openable) { + executeAfterOpen.run(); + } + } + ); return openResult; } catch (IOException ex) { ViewMessages.showMessageDialog(getDefaultMessagesComponent(), AppStrings.translate("open.error.cannotOpen"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index c2bbf2413..c5bda142c 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -238,6 +238,7 @@ import java.awt.event.KeyEvent; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -322,7 +323,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se private ClipboardPanel resourcesClipboardPanel; private ClipboardPanel tagListClipboardPanel; - + private final JPanel contentPanel; private final JPanel displayPanel; @@ -435,13 +436,13 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se private Map abcExplorerDialogs = new WeakHashMap<>(); private Map breakpointsListDialogs = new WeakHashMap<>(); - + private boolean loadingScrollPosEnabled = true; public synchronized void setLoadingScrollPosEnabled(boolean loadingScrollPosEnabled) { this.loadingScrollPosEnabled = loadingScrollPosEnabled; - } - + } + public void savePins() { pinsPanel.save(); } @@ -1489,7 +1490,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se easyPanel.setSwfs(new ArrayList<>(getAllSwfs())); hideWelcomeScreen(); - + gcClipboard(); reload(false); @@ -1556,7 +1557,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se break; } } - + private void hideWelcomeScreen() { if (isWelcomeScreen) { if (currentView == VIEW_EASY) { @@ -1567,9 +1568,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se isWelcomeScreen = false; } } - + private void updateUi(final Openable openable) { - View.checkAccess(); + View.checkAccess(); SWF swf = null; if (openable instanceof SWF) { swf = (SWF) openable; @@ -1602,7 +1603,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se Thread t = new Thread() { @Override public void run() { - while (!Thread.currentThread().isInterrupted()) { + while (!Thread.currentThread().isInterrupted()) { DecompilerPool d = fSwf.getDecompilerPool(); statusPanel.setStatus(fSwf.getFileTitle() + " " + d.getStat()); try { @@ -1627,14 +1628,14 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se isWelcomeScreen = true; quickTagListFindPanel.setVisible(false); quickTreeFindPanel.setVisible(false); - doFilter(); + doFilter(); } mainFrame.setTitle(ApplicationInfo.applicationVerName); mainMenu.updateComponents(null); showView(getCurrentView()); - + if (taskThread != null) { taskThread.interrupt(); taskThread = null; @@ -1736,7 +1737,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se mainMenu.updateComponents(null); folderPreviewPanel.clear(); folderListPanel.clear(); - previewPanel.clear(); + previewPanel.clear(); tagInfoPanel.clear(); dumpPreviewPanel.clear(); @@ -1808,45 +1809,44 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (breakpointsListDialog != null) { breakpointsListDialog.setVisible(false); breakpointsListDialogs.remove(swf); - } + } int index = easyPanel.indexOf(swf); if (index < minEasyIndex) { minEasyIndex = index; } - } - + } + minEasyIndex--; if (minEasyIndex < 0) { minEasyIndex = 0; SWF s = easyPanel.getSwfAtIndex(minEasyIndex); while (s != null && swfsToClose.contains(s)) { minEasyIndex++; - s = easyPanel.getSwfAtIndex(minEasyIndex); + s = easyPanel.getSwfAtIndex(minEasyIndex); } } - + openables.remove(openableList); oldItem = null; clear(); - + Set newSwfs = getAllSwfs(); - + SWF newEasySwf = null; if (minEasyIndex < newSwfs.size()) { easyPanel.setSwfIndex(minEasyIndex); newEasySwf = easyPanel.getSwf(); } - + easyPanel.setSwfs(new ArrayList<>(newSwfs)); easyPanel.setSwf(newEasySwf); - - if (currentView == VIEW_EASY) { + + if (currentView == VIEW_EASY) { updateUi(newEasySwf); - } else { + } else { updateUi(); } - - + for (SWF swf : swfsToClose) { swf.clearTagSwfs(); } @@ -1863,21 +1863,21 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se folderPreviewPanel.clear(); folderListPanel.clear(); - previewPanel.clear(); + previewPanel.clear(); tagInfoPanel.clear(); dumpPreviewPanel.clear(); - + List> nodes; - + //To properly clear cached TreePaths nodes = View.getExpandedNodes(tagTree); tagTree.setModel(tagTree.getFullModel()); View.expandTreeNodes(tagTree, nodes); - + nodes = View.getExpandedNodes(tagListTree); tagListTree.setModel(tagListTree.getFullModel()); View.expandTreeNodes(tagListTree, nodes); - + doFilter(); return true; } @@ -2699,6 +2699,25 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se gotoScriptName(swf, scriptName); } + public void findOrLoadOpanableListByFilePath(String filePath, OpenableListLoaded executeAfterOpen) { + for (OpenableList ol : openables) { + String existingFilePath = ol.sourceInfo.getFile(); + if (existingFilePath == null) { + continue; + } + if (new File(filePath).getAbsolutePath().equals(new File(existingFilePath).getAbsolutePath())) { + executeAfterOpen.openableListLoaded(ol); + return; + } + } + Main.openFile(filePath, null, new Runnable() { + @Override + public void run() { + findOrLoadOpanableListByFilePath(filePath, executeAfterOpen); + } + }); + } + public void gotoScriptLine(SWF swf, String scriptName, int line, int classIndex, int traitIndex, int methodIndex, boolean pcode) { View.checkAccess(); @@ -5508,9 +5527,8 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } else { /*if (openable == null && openables.get(0) != null) { openable = openables.get(0).get(0); - }*/ - - /*if (openable != null) { + } + if (openable != null) { updateUi(openable); }*/ updateUi(openable); @@ -5545,7 +5563,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se @Override public void valueChanged(TreeSelectionEvent e) { - JTree source = (JTree) e.getSource(); + JTree source = (JTree) e.getSource(); valueChanged(source, source.getSelectionPath()); } @@ -5601,7 +5619,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } } return null; - } + } public void clearDebuggerColors() { if (abcPanel != null) { @@ -5612,7 +5630,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se actionPanel.decompiledEditor.removeColorMarkerOnAllLines(DecompiledEditorPane.IP_MARKER); actionPanel.editor.removeColorMarkerOnAllLines(DecompiledEditorPane.IP_MARKER); } - } + } public static final int VIEW_RESOURCES = 0; @@ -5869,7 +5887,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (treeItem instanceof SWF) { SWF swf = (SWF) treeItem; - previewPanel.showImagePanel(swf, swf, -1, true, Configuration.autoPlaySwfs.get() && Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false, true, false, true); + previewPanel.showImagePanel(swf, swf, -1, true, Configuration.autoPlaySwfs.get() && Configuration.autoPlayPreviews.get(), !Configuration.animateSubsprites.get(), false, !Configuration.playFrameSounds.get(), true, false, true, false, true); } else if ((treeItem instanceof PlaceObjectTypeTag)) { previewPanel.showDisplayEditTagPanel((PlaceObjectTypeTag) treeItem, frame); } else if (treeItem instanceof ShapeTag) { @@ -6164,7 +6182,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se treeItem = ((TagScript) treeItem).getTag(); preferScript = true; } - + if (treeItem instanceof FrameScript) { FrameScript fs = (FrameScript) treeItem; DoActionTag doAction = fs.getSingleDoActionTag(); @@ -6175,7 +6193,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se folderPreviewPanel.clear(); folderListPanel.clear(); - previewPanel.clear(); + previewPanel.clear(); tagInfoPanel.clear(); previewPanel.setImageReplaceButtonVisible(false, false, false, false, false, false, false); @@ -6367,7 +6385,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se folderPreviewPanel.setSelectedItems(folderItems); folderPreviewScrollBar.setValue(scrollValue); } - + if (loadingScrollPosEnabled) { View.execInEventDispatchLater(new Runnable() { @Override @@ -6378,8 +6396,6 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se } } - - public void repaintTree() { tagTree.repaint(); tagListTree.repaint(); diff --git a/src/com/jpexs/decompiler/flash/gui/OpenableListLoaded.java b/src/com/jpexs/decompiler/flash/gui/OpenableListLoaded.java new file mode 100644 index 000000000..69748ce63 --- /dev/null +++ b/src/com/jpexs/decompiler/flash/gui/OpenableListLoaded.java @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2025 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; + +import com.jpexs.decompiler.flash.treeitems.OpenableList; + +/** + * + * @author JPEXS + */ +public interface OpenableListLoaded { + public void openableListLoaded(OpenableList openableList); +} diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 9068e849e..7e2975acc 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -20,6 +20,7 @@ import com.jpexs.debugger.flash.Variable; import com.jpexs.debugger.flash.VariableFlags; import com.jpexs.debugger.flash.VariableType; import com.jpexs.debugger.flash.messages.in.InGetVariable; +import com.jpexs.decompiler.flash.SWC; import com.jpexs.decompiler.flash.SWF; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.ClassPath; @@ -27,6 +28,7 @@ import com.jpexs.decompiler.flash.abc.ScriptPack; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instructions; +import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.avm2.parser.script.ActionScript3SimpleParser; import com.jpexs.decompiler.flash.abc.types.ABCException; import com.jpexs.decompiler.flash.abc.types.MethodBody; @@ -58,6 +60,8 @@ import com.jpexs.decompiler.flash.gui.FasterScrollPane; import com.jpexs.decompiler.flash.gui.HeaderLabel; import com.jpexs.decompiler.flash.gui.Main; import com.jpexs.decompiler.flash.gui.MainPanel; +import com.jpexs.decompiler.flash.gui.OpenableListLoaded; +import com.jpexs.decompiler.flash.gui.OpenableOpened; import com.jpexs.decompiler.flash.gui.PopupButton; import com.jpexs.decompiler.flash.gui.SearchListener; import com.jpexs.decompiler.flash.gui.SearchPanel; @@ -71,6 +75,7 @@ import com.jpexs.decompiler.flash.gui.editor.VariableMarker; import com.jpexs.decompiler.flash.gui.tagtree.AbstractTagTree; import com.jpexs.decompiler.flash.gui.tagtree.AbstractTagTreeModel; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.helpers.hilight.Highlighting; import com.jpexs.decompiler.flash.importers.As3ScriptReplaceException; import com.jpexs.decompiler.flash.importers.As3ScriptReplaceExceptionItem; import com.jpexs.decompiler.flash.importers.As3ScriptReplacerInterface; @@ -86,6 +91,7 @@ import com.jpexs.decompiler.flash.treeitems.AS3ClassTreeItem; import com.jpexs.decompiler.flash.treeitems.Openable; import com.jpexs.decompiler.flash.treeitems.OpenableList; import com.jpexs.decompiler.flash.treeitems.TreeItem; +import com.jpexs.decompiler.graph.TypeItem; import com.jpexs.helpers.CancellableWorker; import com.jpexs.helpers.Helper; import com.jpexs.helpers.Reference; @@ -207,7 +213,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener swfRef = new Reference<>(null); + Runnable gotoScriptRunnable = new Runnable() { + @Override + public void run() { + hilightScript(swfRef.getVal(), scriptName); + } + }; + + OpenableListLoaded afterOpen = new OpenableListLoaded() { + @Override + public void openableListLoaded(OpenableList openableList) { + for (Openable op : openableList.items) { + if (op instanceof SWF) { + SWF swf = (SWF) op; + if ("library.swf".equals(swf.getFileTitle())) { + swfRef.setVal(swf); + gotoScriptRunnable.run(); + return; + } + } + } + } + }; + + SWF swf = ci.abc.getSwf(); + if (swf.getFile() == null && "__playerglobal".equals(swf.getFileTitle())) { + mainPanel.findOrLoadOpanableListByFilePath(Configuration.getPlayerSWC().getAbsolutePath(), afterOpen); + } else if (swf.getFile() == null && "__airglobal".equals(swf.getFileTitle())) { + mainPanel.findOrLoadOpanableListByFilePath(Configuration.getAirSWC().getAbsolutePath(), afterOpen); + } else { + swfRef.setVal(swf); + gotoScriptRunnable.run(); + } + + //other file + } }); decompiledTextArea.addScriptListener(new Runnable() { @Override @@ -1180,7 +1252,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener multinameIndexRef = new Reference<>(0); Reference classTrait = new Reference<>(false); Reference usedAbcRef = new Reference<>(null); + Reference scriptIndexRef = new Reference<>(-1); if (getSwf() == null) { return LinkType.NO_LINK; } - LinkType propLinkType = decompiledTextArea.getPropertyTypeAtPos(getSwf().getAbcIndex(), pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef, usedAbcRef, false); + LinkType propLinkType = decompiledTextArea.getPropertyTypeAtPos(getSwf().getAbcIndex(), pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef, usedAbcRef, false, scriptIndexRef); if (propLinkType != LinkType.NO_LINK) { - return propLinkType; - } + if (usedAbcRef.getVal() == abc && scriptIndexRef.getVal() == decompiledTextArea.getScriptIndex()) { + return LinkType.LINK_THIS_SCRIPT; + } + return propLinkType; + } ABC usedAbc = usedAbcRef.getVal(); int multinameIndex = decompiledTextArea.getMultinameAtPos(pos, usedAbcRef); if (multinameIndex > -1) { @@ -1294,7 +1370,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener(null)) != -1 ? LinkType.LINK_OTHER_SCRIPT : LinkType.NO_LINK; + Reference linkTypeRef = new Reference<>(null); + decompiledTextArea.getLocalDeclarationOfPos(pos, new Reference<>(null), linkTypeRef); + + return linkTypeRef.getVal(); } private void gotoDeclaration(int pos) { @@ -1305,8 +1384,9 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener traitIndex = new Reference<>(0); Reference classTrait = new Reference<>(false); Reference multinameIndexRef = new Reference<>(0); + Reference scriptIndexRef = new Reference<>(-1); Reference usedAbcRef = new Reference<>(null); - if (decompiledTextArea.getPropertyTypeAtPos(getSwf().getAbcIndex(), pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef, usedAbcRef, false) != LinkType.NO_LINK) { + if (decompiledTextArea.getPropertyTypeAtPos(getSwf().getAbcIndex(), pos, abcIndex, classIndex, traitIndex, classTrait, multinameIndexRef, usedAbcRef, false, scriptIndexRef) != LinkType.NO_LINK) { UsageFrame.gotoUsage(ABCPanel.this, new TraitMultinameUsage(getAbcList().get(abcIndex.getVal()).getABC(), multinameIndexRef.getVal(), decompiledTextArea.getScriptLeaf().scriptIndex, classIndex.getVal(), traitIndex.getVal(), classTrait.getVal() ? TraitMultinameUsage.TRAITS_TYPE_CLASS : TraitMultinameUsage.TRAITS_TYPE_INSTANCE, null, -1) { }); return; @@ -1348,7 +1428,7 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener(null)); + int dpos = decompiledTextArea.getLocalDeclarationOfPos(pos, new Reference<>(null), new Reference<>(null)); if (dpos > -1) { decompiledTextArea.setCaretPosition(dpos); } diff --git a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java index 1cd3c45c7..143c65ad9 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/DecompiledEditorPane.java @@ -285,16 +285,18 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL return getMultinameAtPos(getCaretPosition(), abcUsed); } - public int getLocalDeclarationOfPos(int pos, Reference type) { + public int getLocalDeclarationOfPos(int pos, Reference type, Reference linkTypeRef) { Highlighting sh = Highlighting.searchPos(highlightedText.getSpecialHighlights(), pos); Highlighting h = Highlighting.searchPos(highlightedText.getInstructionHighlights(), pos); if (h == null) { + linkTypeRef.setVal(LinkType.NO_LINK); return -1; } List tms = Highlighting.searchAllPos(highlightedText.getMethodHighlights(), pos); if (tms.isEmpty()) { + linkTypeRef.setVal(LinkType.NO_LINK); return -1; } for (Highlighting tm : tms) { @@ -302,6 +304,7 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL List tm_tms = Highlighting.searchAllIndexes(highlightedText.getMethodHighlights(), tm.getProperties().index); //is it already declaration? if (h.getProperties().declaration || (sh != null && sh.getProperties().declaration)) { + linkTypeRef.setVal(LinkType.NO_LINK); return -1; //no jump } @@ -311,6 +314,7 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL int cindex = (int) ch.getProperties().index; ABC abc = getABC(); type.setVal(abc.instance_info.get(cindex).getName(abc.constants).getNameWithNamespace(abc.constants, true)); + linkTypeRef.setVal(LinkType.LINK_THIS_SCRIPT); return ch.startPos; } @@ -321,6 +325,7 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL search.localName = hData.localName; search.specialValue = hData.specialValue; if (search.isEmpty()) { + linkTypeRef.setVal(LinkType.NO_LINK); return -1; } search.declaration = true; @@ -332,15 +337,17 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL } if (rh != null) { type.setVal(rh.getProperties().declaredType); + linkTypeRef.setVal(LinkType.LINK_OTHER_SCRIPT); return rh.startPos; } } } + linkTypeRef.setVal(LinkType.NO_LINK); return -1; } - public LinkType getPropertyTypeAtPos(AbcIndexing indexing, int pos, Reference abcIndex, Reference classIndex, Reference traitIndex, Reference classTrait, Reference multinameIndex, Reference abcUsed, boolean currentSwfOnly) { + public LinkType getPropertyTypeAtPos(AbcIndexing indexing, int pos, Reference abcIndex, Reference classIndex, Reference traitIndex, Reference classTrait, Reference multinameIndex, Reference abcUsed, boolean currentSwfOnly, Reference scriptIndexRef) { int m = getMultinameAtPos(pos, true, abcUsed); @@ -353,7 +360,7 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL }*/ SyntaxDocument sd = (SyntaxDocument) getDocument(); Token t = sd.getTokenAt(pos + 1); - Token lastToken = t; + Token lastToken = t; Token prev; String propName = t.getString(sd); if (!(t.type == TokenType.IDENTIFIER || t.type == TokenType.KEYWORD || t.type == TokenType.REGEX)) { @@ -382,7 +389,8 @@ public class DecompiledEditorPane extends DebuggableEditorPane implements CaretL if (propertyTraitIndex == null) { return LinkType.NO_LINK; } - + scriptIndexRef.setVal(propertyTraitIndex.scriptIndex); + List abcs = getABC().getSwf().getAbcList(); int index = 0; boolean isCurrentSwf = false; diff --git a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java index cc836204f..504de7bab 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java @@ -67,13 +67,20 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan private boolean error = false; - private Token lastUnderlined = null; - private LinkHandler linkHandler = this; - private Point lastCursorPos = new Point(0, 0); private SimpleParser parser; + + @Override + public LinkType getExternalTypeLinkType(String className) { + return LinkType.NO_LINK; + } + + @Override + public void handleExternalTypeLink(String className) { + + } public static class LineMarker implements Comparable { @@ -383,7 +390,7 @@ public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHan } @Override - public LinkType isLink(Token token) { + public LinkType getLinkType(Token token) { return LinkType.NO_LINK; } diff --git a/src/com/jpexs/decompiler/flash/gui/editor/LinkHandler.java b/src/com/jpexs/decompiler/flash/gui/editor/LinkHandler.java index 100f8ddf4..72d78c3f6 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/LinkHandler.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/LinkHandler.java @@ -24,9 +24,13 @@ import jsyntaxpane.Token; */ public interface LinkHandler { - public LinkType isLink(Token token); + public LinkType getLinkType(Token token); + + public LinkType getExternalTypeLinkType(String className); public void handleLink(Token token); + public void handleExternalTypeLink(String className); + public Highlighter.HighlightPainter linkPainter(); } diff --git a/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java b/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java index c524d5839..f1b57685f 100644 --- a/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java +++ b/src/com/jpexs/decompiler/flash/gui/editor/VariableMarker.java @@ -17,12 +17,21 @@ package com.jpexs.decompiler.flash.gui.editor; 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.ViewMessages; import com.jpexs.decompiler.flash.simpleparser.SimpleParseException; import com.jpexs.decompiler.flash.simpleparser.SimpleParser; +import com.sun.java.swing.action.ViewMenu; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Cursor; +import java.awt.FontMetrics; +import java.awt.Graphics; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; import java.awt.KeyEventPostProcessor; import java.awt.KeyboardFocusManager; import java.awt.Point; @@ -46,7 +55,12 @@ import java.util.Timer; import java.util.TimerTask; import java.util.logging.Logger; import javax.swing.AbstractAction; +import javax.swing.BorderFactory; +import javax.swing.BoxLayout; +import javax.swing.JCheckBox; import javax.swing.JEditorPane; +import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollBar; import javax.swing.JScrollPane; @@ -60,6 +74,7 @@ import javax.swing.plaf.ScrollPaneUI; import javax.swing.plaf.basic.BasicScrollPaneUI; import javax.swing.text.BadLocationException; import javax.swing.text.Highlighter; +import javax.swing.text.Segment; import jsyntaxpane.SyntaxDocument; import jsyntaxpane.Token; import jsyntaxpane.TokenType; @@ -81,8 +96,6 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC private static final Color DEFAULT_COLOR = new Color(0xffeedd); private static final Color DEFAULT_ERRORCOLOR = new Color(0xff0000); - private static final Color SCROLLBAR_VARIABLE_COLOR = new Color(0xb59070); - private static final Color SCROLLBAR_ERROR_COLOR = new Color(0xff0000); private JEditorPane pane; private final Set tokenTypes = new HashSet<>(); private OccurencesMarker marker; @@ -94,6 +107,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC private Map> definitionPosToReferences = new LinkedHashMap<>(); private Map referenceToDefinition = new LinkedHashMap<>(); + private List externalTypes = new ArrayList<>(); + private Map referenceToExternalTypeIndex = new LinkedHashMap<>(); + private Map> externalTypeIndexToReference = new LinkedHashMap<>(); private MouseMotionAdapter mouseMotionAdapter; @@ -109,13 +125,23 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC private Set occurencesPositions = new HashSet<>(); - private UnderlinePainter underLinePainter = new UnderlinePainter(new Color(0, 0, 255), null); - private UnderlinePainter underLineMarkOccurencesPainter = new UnderlinePainter(new Color(0, 0, 255), DEFAULT_COLOR); - private UnderlinePainter underLineExternalPainter = new UnderlinePainter(new Color(0, 255, 0), null); - private UnderlinePainter underLineExternalMarkOccurencesPainter = new UnderlinePainter(new Color(0, 255, 0), DEFAULT_COLOR); + private Color basicUnderlineColor = new Color(0, 0, 255); + private Color otherScriptUnderlineColor = new Color(0, 255, 0); + private Color otherFileUnderlineColor = new Color(255, 0, 255); + + private UnderlinePainter underLinePainter = new UnderlinePainter(basicUnderlineColor, null); + private UnderlinePainter underLineMarkOccurencesPainter = new UnderlinePainter(basicUnderlineColor, DEFAULT_COLOR); + + private UnderlinePainter underLineOtherScriptPainter = new UnderlinePainter(otherScriptUnderlineColor, null); + private UnderlinePainter underLineOtherScriptMarkOccurencesPainter = new UnderlinePainter(otherScriptUnderlineColor, DEFAULT_COLOR); + + private UnderlinePainter underLineOtherFilePainter = new UnderlinePainter(otherFileUnderlineColor, null); + private UnderlinePainter underLineOtherFileMarkOccurencesPainter = new UnderlinePainter(otherFileUnderlineColor, DEFAULT_COLOR); private Token lastUnderlined; - private LinkType lastUnderlinedLinkType = LinkType.NO_LINK; + private LinkType lastUnderlinedLinkType = LinkType.NO_LINK; + + private boolean goingOut = false; /** * Constructs a new Token highlighter @@ -131,12 +157,6 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC public void markTokenAt(int pos) { SyntaxDocument doc = ActionUtils.getSyntaxDocument(pane); if (doc != null) { - Token everyToken = getNearestTokenAt(doc, pos); - if (everyToken != null) { - if (errors.containsKey(everyToken.start)) { - //System.err.println(errors.get(everyToken.start)); - } - } Token token = getIdentifierTokenAt(doc, pos); removeMarkers(); if (token != null && tokenTypes.contains(token.type)) { @@ -153,8 +173,10 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC Markers.removeMarkers(pane, marker); Markers.removeMarkers(pane, underLinePainter); Markers.removeMarkers(pane, underLineMarkOccurencesPainter); - Markers.removeMarkers(pane, underLineExternalPainter); - Markers.removeMarkers(pane, underLineExternalMarkOccurencesPainter); + Markers.removeMarkers(pane, underLineOtherScriptPainter); + Markers.removeMarkers(pane, underLineOtherScriptMarkOccurencesPainter); + Markers.removeMarkers(pane, underLineOtherFilePainter); + Markers.removeMarkers(pane, underLineOtherFileMarkOccurencesPainter); occurencesPositions.clear(); } @@ -241,15 +263,38 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC int definitionPos = tok.start; if (referenceToDefinition.containsKey(tok.start)) { definitionPos = referenceToDefinition.get(tok.start); + } else { + if (referenceToExternalTypeIndex.containsKey(tok.start)) { + int typeIndex = referenceToExternalTypeIndex.get(tok.start); + for (int i : externalTypeIndexToReference.get(typeIndex)) { + Token referenceToken = getIdentifierTokenAt(sDoc, i); + if (referenceToken != null) { + Markers.SimpleMarker markerKind = marker; + if (lastUnderlined == referenceToken) { + if (lastUnderlinedLinkType == LinkType.LINK_OTHER_SCRIPT) { + markerKind = underLineOtherScriptMarkOccurencesPainter; + } else if (lastUnderlinedLinkType == LinkType.LINK_OTHER_FILE) { + markerKind = underLineOtherFileMarkOccurencesPainter; + } else { + markerKind = underLineMarkOccurencesPainter; + } + } + Markers.markToken(pane, referenceToken, markerKind); + occurencesPositions.add(referenceToken.start); + } + } + sDoc.readUnlock(); + return; + } } Token definitionToken = getIdentifierTokenAt(sDoc, definitionPos < 0 ? -(definitionPos + 1) : definitionPos); if (definitionToken != null) { if (definitionPosToReferences.containsKey(definitionPos)) { - + Markers.SimpleMarker markerKind = marker; if (lastUnderlined == definitionToken) { if (lastUnderlinedLinkType == LinkType.LINK_OTHER_SCRIPT) { - markerKind = underLineExternalMarkOccurencesPainter; + markerKind = underLineOtherScriptMarkOccurencesPainter; } else { markerKind = underLineMarkOccurencesPainter; } @@ -264,7 +309,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC markerKind = marker; if (lastUnderlined == referenceToken) { if (lastUnderlinedLinkType == LinkType.LINK_OTHER_SCRIPT) { - markerKind = underLineExternalMarkOccurencesPainter; + markerKind = underLineOtherScriptMarkOccurencesPainter; + } else if (lastUnderlinedLinkType == LinkType.LINK_OTHER_FILE) { + markerKind = underLineOtherFileMarkOccurencesPainter; } else { markerKind = underLineMarkOccurencesPainter; } @@ -364,8 +411,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC handleLink(token); } }, "find-declaration", AppStrings.translate("abc.action.find-declaration"), "control B"); - - + documentUpdated(); markTokenAt(editor.getCaretPosition()); status = Status.INSTALLING; @@ -399,6 +445,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC } private void update() { + if (goingOut) { + return; + } if (lastCursorPos == null) { return; } @@ -409,9 +458,11 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC if (t == null || lastUnderlined == null || !t.equals(lastUnderlined)) { MyMarkers.removeMarkers(pane, underLinePainter); MyMarkers.removeMarkers(pane, underLineMarkOccurencesPainter); - MyMarkers.removeMarkers(pane, underLineExternalPainter); - MyMarkers.removeMarkers(pane, underLineExternalMarkOccurencesPainter); - + MyMarkers.removeMarkers(pane, underLineOtherScriptPainter); + MyMarkers.removeMarkers(pane, underLineOtherScriptMarkOccurencesPainter); + MyMarkers.removeMarkers(pane, underLineOtherFilePainter); + MyMarkers.removeMarkers(pane, underLineOtherFileMarkOccurencesPainter); + lastUnderlinedLinkType = t == null ? LinkType.NO_LINK : getLinkType(t); if (t != null && lastUnderlinedLinkType != LinkType.NO_LINK) { lastUnderlined = t; @@ -432,7 +483,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC Highlighter.HighlightPainter painter = underLinePainter; if (occurencesPositions.contains(lastUnderlined.start)) { if (lastUnderlinedLinkType == LinkType.LINK_OTHER_SCRIPT) { - painter = underLineExternalMarkOccurencesPainter; + painter = underLineOtherScriptMarkOccurencesPainter; + } else if (lastUnderlinedLinkType == LinkType.LINK_OTHER_FILE) { + painter = underLineOtherFileMarkOccurencesPainter; } else { painter = underLineMarkOccurencesPainter; } @@ -440,9 +493,11 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC markTokenAt(pane.getCaretPosition()); } else { if (lastUnderlinedLinkType == LinkType.LINK_OTHER_SCRIPT) { - painter = underLineExternalPainter; - } - MyMarkers.markToken(pane, lastUnderlined, painter); + painter = underLineOtherScriptPainter; + } else if (lastUnderlinedLinkType == LinkType.LINK_OTHER_FILE) { + painter = underLineOtherFilePainter; + } + MyMarkers.markToken(pane, lastUnderlined, painter); } } else { pane.setCursor(Cursor.getDefaultCursor()); @@ -452,10 +507,11 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC lastUnderlined = null; MyMarkers.removeMarkers(pane, underLinePainter); MyMarkers.removeMarkers(pane, underLineMarkOccurencesPainter); - MyMarkers.removeMarkers(pane, underLineExternalPainter); - MyMarkers.removeMarkers(pane, underLineExternalMarkOccurencesPainter); - - + MyMarkers.removeMarkers(pane, underLineOtherScriptPainter); + MyMarkers.removeMarkers(pane, underLineOtherScriptMarkOccurencesPainter); + MyMarkers.removeMarkers(pane, underLineOtherFilePainter); + MyMarkers.removeMarkers(pane, underLineOtherFileMarkOccurencesPainter); + removeMarkers(); markTokenAt(pane.getCaretPosition()); } @@ -465,6 +521,9 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC @Override public void mouseClicked(MouseEvent e) { + if (lastCursorPos == null) { + return; + } if (ctrlDown) { Token t = ((LineMarkedEditorPane) pane).tokenAtPos(lastCursorPos); if (t != null && getLinkType(t) != LinkType.NO_LINK) { @@ -476,7 +535,6 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC @Override public void mouseMoved(MouseEvent e) { - ctrlDown = (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0; lastCursorPos = e.getPoint(); update(); @@ -533,6 +591,7 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getPropertyName().equals("document")) { + goingOut = false; pane.removeCaretListener(this); pane.getDocument().removeDocumentListener(this); if (status.equals(Status.INSTALLING)) { @@ -564,9 +623,15 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC Map> newDefinitionPosToReferences = new LinkedHashMap<>(); Map newReferenceToDefinition = new LinkedHashMap<>(); List newErrors = new ArrayList<>(); - parser.parse(fullText, newDefinitionPosToReferences, newReferenceToDefinition, newErrors); + List newExternalTypes = new ArrayList<>(); + Map newReferenceToExternalTypeIndex = new LinkedHashMap<>(); + Map> newExternalTypeIndexToReference = new LinkedHashMap<>(); + parser.parse(fullText, newDefinitionPosToReferences, newReferenceToDefinition, newErrors, newExternalTypes, newReferenceToExternalTypeIndex, newExternalTypeIndexToReference); definitionPosToReferences = newDefinitionPosToReferences; referenceToDefinition = newReferenceToDefinition; + externalTypes = newExternalTypes; + referenceToExternalTypeIndex = newReferenceToExternalTypeIndex; + externalTypeIndexToReference = newExternalTypeIndexToReference; for (SimpleParseException ex : newErrors) { errors.put((int) ex.position, ex.getMessage()); } @@ -619,10 +684,41 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC if (linkThisScript) { return LinkType.LINK_THIS_SCRIPT; } + if (pane.isEditable()) { return LinkType.NO_LINK; } - return ((LineMarkedEditorPane) pane).getLinkHandler().isLink(token); + if (referenceToExternalTypeIndex.containsKey(token.start)) { + String externalType = externalTypes.get(referenceToExternalTypeIndex.get(token.start)); + return ((LineMarkedEditorPane) pane).getLinkHandler().getExternalTypeLinkType(externalType); + } + return ((LineMarkedEditorPane) pane).getLinkHandler().getLinkType(token); + } + + private class UnderlinedLabel extends JLabel { + + private final Color underlineColor; + + public UnderlinedLabel(String text, Color underlineColor) { + super(text); + this.underlineColor = underlineColor; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + FontMetrics fm = g.getFontMetrics(); + g.setColor(underlineColor); + g.drawLine(0, fm.getHeight() - 3, fm.stringWidth(getText()), fm.getHeight() - 3); + } + } + + private class CommentLabel extends JLabel { + + public CommentLabel(String text) { + super(text); + setForeground(new Color(0x339933)); + } } public void handleLink(Token token) { @@ -630,10 +726,94 @@ public class VariableMarker implements SyntaxComponent, CaretListener, PropertyC if (definition != null && definition >= 0) { pane.setCaretPosition(definition); } else if (!pane.isEditable()) { + + if (referenceToExternalTypeIndex.containsKey(token.start) + && com.jpexs.decompiler.flash.configuration.Configuration.warningLinkTypes.get()) { + + String externalType = externalTypes.get(referenceToExternalTypeIndex.get(token.start)); + LinkType lt = ((LineMarkedEditorPane) pane).getLinkHandler().getExternalTypeLinkType(externalType); + + if (lt == LinkType.LINK_OTHER_FILE) { + JPanel msgPanel = new JPanel(); + msgPanel.setLayout(new BoxLayout(msgPanel, BoxLayout.Y_AXIS)); + JLabel bewareLabel = new JLabel(AppStrings.translate("message.link.clicked")); + bewareLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + msgPanel.add(bewareLabel); + + JLabel beware2Label = new JLabel(AppStrings.translate("message.link.bewareTypes")); + beware2Label.setAlignmentX(Component.CENTER_ALIGNMENT); + msgPanel.add(beware2Label); + + JPanel linksPanel = new JPanel(new GridBagLayout()); + linksPanel.setBorder(BorderFactory.createLineBorder(Color.BLACK)); + linksPanel.setBackground(Color.white); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.anchor = GridBagConstraints.FIRST_LINE_START; + gbc.insets = new Insets(2, 2, 2, 2); + gbc.gridx = 0; + gbc.gridy = 0; + + linksPanel.add(new UnderlinedLabel(AppStrings.translate("message.link.type.currentScript.sample"), basicUnderlineColor), gbc); + gbc.gridx++; + linksPanel.add(new CommentLabel("//" + AppStrings.translate("message.link.type.currentScript")), gbc); + gbc.gridx = 0; + gbc.gridy++; + linksPanel.add(new UnderlinedLabel(AppStrings.translate("message.link.type.otherScript.sample"), otherScriptUnderlineColor), gbc); + gbc.gridx++; + linksPanel.add(new CommentLabel("//" + AppStrings.translate("message.link.type.otherScript")), gbc); + gbc.gridx = 0; + gbc.gridy++; + linksPanel.add(new UnderlinedLabel(AppStrings.translate("message.link.type.otherFile.sample"), otherFileUnderlineColor), gbc); + gbc.gridx++; + linksPanel.add(new CommentLabel("//" + AppStrings.translate("message.link.type.otherFile")), gbc); + + gbc.gridx = 2; + gbc.gridy = 0; + gbc.gridheight = 3; + gbc.weightx = 1; + gbc.weighty = 1; + JPanel finalPanel = new JPanel(); + finalPanel.setOpaque(false); + linksPanel.add(finalPanel); + + linksPanel.setAlignmentX(Component.CENTER_ALIGNMENT); + + msgPanel.add(linksPanel); + JLabel reallyLabel = new JLabel(AppStrings.translate("message.link.reallyGo")); + reallyLabel.setAlignmentX(Component.CENTER_ALIGNMENT); + msgPanel.add(reallyLabel); + JCheckBox doNotShowAgainCheckbox = new JCheckBox(AppStrings.translate("message.confirm.donotshowagain")); + doNotShowAgainCheckbox.setAlignmentX(Component.CENTER_ALIGNMENT); + msgPanel.add(doNotShowAgainCheckbox); + + int result = ViewMessages.showOptionDialog(Main.getDefaultMessagesComponent(), + msgPanel, + AppStrings.translate("message.warning"), + JOptionPane.OK_CANCEL_OPTION, + JOptionPane.WARNING_MESSAGE, + null, null, null); + if (doNotShowAgainCheckbox.isSelected()) { + com.jpexs.decompiler.flash.configuration.Configuration.warningLinkTypes.set(false); + } + if (result != JOptionPane.OK_OPTION) { + return; + } + } + + } lastUnderlined = null; removeErrorMarkers(); removeMarkers(); pane.repaint(); + + if (referenceToExternalTypeIndex.containsKey(token.start)) { + goingOut = true; + pane.setCursor(Cursor.getDefaultCursor()); + String externalType = externalTypes.get(referenceToExternalTypeIndex.get(token.start)); + ((LineMarkedEditorPane) pane).getLinkHandler().handleExternalTypeLink(externalType); + return; + } + ((LineMarkedEditorPane) pane).getLinkHandler().handleLink(token); } } diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties index b9cc5767b..2b1f6cbcd 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog.properties @@ -619,3 +619,7 @@ config.description.snapAlignCenterAlignmentHorizontal = Enables snap align of ob config.name.snapAlignCenterAlignmentVertical = Snap align vertical center alignment config.description.snapAlignCenterAlignmentVertical = Enables snap align of object center vertically. + +#after 23.0.1 +config.name.warning.linkTypes = Show warning when clicking external file link +config.name.warning.linkTypes = Warn on clicking a link in the script editor which leads to another SWF file. \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties index b48f80a78..d09d90bb4 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_cs.properties @@ -619,3 +619,8 @@ config.description.snapAlignCenterAlignmentHorizontal = Povol\u00ed p\u0159ichyc config.name.snapAlignCenterAlignmentVertical = Vertik\u00e1ln\u00ed zarovn\u00e1n\u00ed st\u0159edu v p\u0159ichycen\u00ed k zarovn\u00e1n\u00ed config.description.snapAlignCenterAlignmentVertical = Povol\u00ed p\u0159ichycen\u00ed k zarovn\u00e1n\u00ed st\u0159edu objektu vertik\u00e1ln\u011b. + +#after 23.0.1 +config.name.warning.linkTypes = Varovat p\u0159i kliknut\u00ed na link na extern\u00ed soubor +config.description.warning.linkTypes = Zobrazovat varov\u00e1n\u00ed p\u0159i kliknut\u00ed na odkaz v editoru skript\u016f, kter\u00fd vede do jin\u00e9ho SWF souboru. + diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties index c31c20f83..7bbe3c418 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame.properties @@ -1061,4 +1061,14 @@ contextmenu.showDetail = Show detail highlighter.occurences = Mark occurences highlighter.currentLine = Current line -highlighter.error = Error: %error% \ No newline at end of file +highlighter.error = Error: %error% + +message.link.clicked = You clicked a link to other SWF file. +message.link.bewareTypes = Beware that there are multiple link types: +message.link.type.currentScript = Link to current script +message.link.type.currentScript.sample = myVar +message.link.type.otherScript = Link to other script in this SWF +message.link.type.otherScript.sample = OtherClass +message.link.type.otherFile = Link to other SWF file (usually playerglobal.swc) +message.link.type.otherFile.sample = String +message.link.reallyGo = Do you really want to go to another SWF? \ No newline at end of file diff --git a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties index c3c77dfaa..1f0f59a62 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/MainFrame_cs.properties @@ -1056,4 +1056,18 @@ contextmenu.showInEasy = Zobrazit v Jednoduch\u00e9m editoru work.debugging.start = Spou\u0161t\u00ed se Flash content debugger menu.file.view.alwaysOnTop = V\u017edy navrchu -contextmenu.showDetail = Zobrazit detail \ No newline at end of file +contextmenu.showDetail = Zobrazit detail + +highlighter.occurences = Ozna\u010dit v\u00fdskyty +highlighter.currentLine = Aktu\u00e1ln\u00ed \u0159\u00e1dek +highlighter.error = Chyba: %error% + +message.link.clicked = Kliknul(a) jste na odkaz do jin\u00e9ho SWF souboru. +message.link.bewareTypes = D\u00e1vejte pozor na to, \u017ee existuje v\u00edce druh\u016f odkaz\u016f: +message.link.type.currentScript = Odkaz do aktu\u00e1ln\u00edho skriptu +message.link.type.currentScript.sample = mojePromenna +message.link.type.otherScript = Odkaz na jin\u00fd skript v tomto SWF +message.link.type.otherScript.sample = JinaTrida +message.link.type.otherFile = Odkaz do jin\u00e9ho SWF souboru (obvykle playerglobal.swc) +message.link.type.otherFile.sample = String +message.link.reallyGo = Opravdu chcete p\u0159ej\u00edt do jin\u00e9ho SWF? \ No newline at end of file