mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-11 16:21:54 +00:00
Issue #85 - AS3 Text search
This commit is contained in:
@@ -536,8 +536,8 @@ public class SWFInputStream extends InputStream {
|
||||
if (visited.contains(ip)) {
|
||||
break;
|
||||
}
|
||||
for (DisassemblyListener listener : listeners) {
|
||||
listener.progress("constantpool", ip + 1, code.size());
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
listeners.get(i).progress("constantpool", ip + 1, code.size());
|
||||
}
|
||||
lastIp = ip;
|
||||
GraphSourceItem ins = code.get(ip);
|
||||
@@ -806,8 +806,8 @@ public class SWFInputStream extends InputStream {
|
||||
Scanner sc = new Scanner(System.in);
|
||||
int prevIp = ip;
|
||||
while (((endip == -1) || (endip > ip)) && (a = sis.readAction(rri)) != null) {
|
||||
for (DisassemblyListener listener : listeners) {
|
||||
listener.progress("Reading", rri.getCount(), rri.length());
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
listeners.get(i).progress("Reading", rri.getCount(), rri.length());
|
||||
}
|
||||
if ((ip < ret.size()) && (!(ret.get(ip) instanceof ActionNop))) {
|
||||
a = ret.get(ip);
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.Main;
|
||||
import com.jpexs.decompiler.flash.abc.ABC;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.gui.tablemodels.*;
|
||||
import com.jpexs.decompiler.flash.gui.TagTreeModel;
|
||||
import com.jpexs.decompiler.flash.gui.View;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
import java.awt.BorderLayout;
|
||||
@@ -33,13 +34,16 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.BevelBorder;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import javax.swing.table.*;
|
||||
import javax.swing.tree.TreePath;
|
||||
import jsyntaxpane.DefaultSyntaxKit;
|
||||
import jsyntaxpane.actions.DocumentSearchData;
|
||||
import jsyntaxpane.actions.gui.QuickFindDialog;
|
||||
|
||||
public class ABCPanel extends JPanel implements ItemListener, ActionListener {
|
||||
|
||||
@@ -68,15 +72,29 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener {
|
||||
private int foundPos = 0;
|
||||
private JLabel searchForLabel;
|
||||
private String searchFor;
|
||||
private boolean searchIgnoreCase;
|
||||
private boolean searchRegexp;
|
||||
|
||||
public boolean search(String txt) {
|
||||
public boolean search(String txt, boolean ignoreCase, boolean regexp) {
|
||||
if ((txt != null) && (!txt.equals(""))) {
|
||||
searchIgnoreCase = ignoreCase;
|
||||
searchRegexp = regexp;
|
||||
ClassesListTreeModel clModel = (ClassesListTreeModel) classTree.getModel();
|
||||
HashMap<String, ScriptPack> allpacks = clModel.getList();
|
||||
found = new ArrayList<ScriptPack>();
|
||||
Pattern pat = null;
|
||||
if (regexp) {
|
||||
pat = Pattern.compile(txt, ignoreCase ? Pattern.CASE_INSENSITIVE : 0);
|
||||
} else {
|
||||
pat = Pattern.compile(Pattern.quote(txt), ignoreCase ? Pattern.CASE_INSENSITIVE : 0);
|
||||
}
|
||||
for (ScriptPack p : allpacks.values()) {
|
||||
decompiledTextArea.cacheScriptPack(p, list);
|
||||
if (pat.matcher(decompiledTextArea.getCachedText(p)).find()) {
|
||||
found.add(p);
|
||||
}
|
||||
}
|
||||
found = decompiledTextArea.searchCache(txt);
|
||||
//found = decompiledTextArea.searchCache(txt, ignoreCase, regexp);
|
||||
if (found.isEmpty()) {
|
||||
searchPanel.setVisible(false);
|
||||
return false;
|
||||
@@ -324,9 +342,6 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener {
|
||||
searchPanel.add(searchPos);
|
||||
searchPanel.add(nextSearchButton);
|
||||
searchPanel.add(cancelSearchButton);
|
||||
|
||||
|
||||
|
||||
searchPanel.setVisible(false);
|
||||
JLabel picLabel = new JLabel(View.getIcon("search16"));
|
||||
filterPanel.add(picLabel, BorderLayout.EAST);
|
||||
@@ -429,10 +444,22 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener {
|
||||
public void updateSearchPos() {
|
||||
searchPos.setText((foundPos + 1) + "/" + found.size());
|
||||
decompiledTextArea.setScript(found.get(foundPos), list);
|
||||
TagTreeModel ttm = (TagTreeModel) Main.mainFrame.tagTree.getModel();
|
||||
TreePath tp = ttm.getTagPath(found.get(foundPos));
|
||||
Main.mainFrame.tagTree.setSelectionPath(tp);
|
||||
Main.mainFrame.tagTree.scrollPathToVisible(tp);
|
||||
decompiledTextArea.setCaretPosition(0);
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(ABCPanel.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
DocumentSearchData dsd = DocumentSearchData.getFromEditor(decompiledTextArea);
|
||||
dsd.setPattern(searchFor, false, false);
|
||||
dsd.showQuickFindDialog(decompiledTextArea);
|
||||
dsd.setPattern(searchFor, searchRegexp, searchIgnoreCase);
|
||||
QuickFindDialog quickFindDlg = new QuickFindDialog(decompiledTextArea, dsd);
|
||||
quickFindDlg.setRegularExpression(searchRegexp);
|
||||
quickFindDlg.setIgnoreCase(searchIgnoreCase);
|
||||
quickFindDlg.showFor(decompiledTextArea);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,9 +25,13 @@ import com.jpexs.decompiler.flash.helpers.Highlighting;
|
||||
import com.jpexs.decompiler.flash.tags.ABCContainerTag;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.swing.event.CaretEvent;
|
||||
import javax.swing.event.CaretListener;
|
||||
|
||||
@@ -215,20 +219,59 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
private class CachedDecompilation {
|
||||
|
||||
public String text;
|
||||
public List<Highlighting> highlights;
|
||||
public List<Highlighting> traitHighlights;
|
||||
public List<Highlighting> methodHighlights;
|
||||
public List<Highlighting> classHighlights;
|
||||
public String hilightedText;
|
||||
|
||||
public CachedDecompilation(String text, List<Highlighting> highlights, List<Highlighting> traitHighlights, List<Highlighting> methodHighlights, List<Highlighting> classHighlights) {
|
||||
this.text = text;
|
||||
this.highlights = highlights;
|
||||
this.traitHighlights = traitHighlights;
|
||||
this.methodHighlights = methodHighlights;
|
||||
this.classHighlights = classHighlights;
|
||||
public List<Highlighting> getHighlights() {
|
||||
return Highlighting.getInstrHighlights(hilightedText);
|
||||
}
|
||||
|
||||
public List<Highlighting> getTraitHighlights() {
|
||||
return Highlighting.getTraitHighlights(hilightedText);
|
||||
}
|
||||
|
||||
public List<Highlighting> getMethodHighlights() {
|
||||
return Highlighting.getMethodHighlights(hilightedText);
|
||||
}
|
||||
|
||||
public List<Highlighting> getClassHighlights() {
|
||||
return Highlighting.getClassHighlights(hilightedText);
|
||||
}
|
||||
|
||||
public CachedDecompilation(String hilightedText) {
|
||||
this.hilightedText = hilightedText;
|
||||
this.text = Highlighting.stripHilights(hilightedText);
|
||||
}
|
||||
}
|
||||
private HashMap<ScriptPack, CachedDecompilation> decompilationCache = new HashMap<ScriptPack, CachedDecompilation>();
|
||||
private List<ScriptPack> cacheKeys = new LinkedList<ScriptPack>();
|
||||
private List<CachedDecompilation> cacheValues = new LinkedList<CachedDecompilation>();
|
||||
|
||||
private void uncache(ScriptPack pack) {
|
||||
for (int i = 0; i < cacheKeys.size(); i++) {
|
||||
if (cacheKeys.get(i) == pack) {
|
||||
cacheValues.remove(i);
|
||||
cacheKeys.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CachedDecompilation getCached(ScriptPack pack) {
|
||||
for (int i = 0; i < cacheKeys.size(); i++) {
|
||||
if (cacheKeys.get(i) == pack) {
|
||||
return cacheValues.get(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getCachedText(ScriptPack pack) {
|
||||
for (int i = 0; i < cacheKeys.size(); i++) {
|
||||
if (cacheKeys.get(i) == pack) {
|
||||
return cacheValues.get(i).text;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void gotoLastTrait() {
|
||||
gotoTrait(lastTraitIndex);
|
||||
@@ -283,21 +326,12 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
private List<ABCContainerTag> abcList;
|
||||
|
||||
public void clearScriptCache() {
|
||||
decompilationCache.clear();
|
||||
}
|
||||
|
||||
public List<ScriptPack> searchCache(String str) {
|
||||
List<ScriptPack> found = new ArrayList<ScriptPack>();
|
||||
for (ScriptPack pack : decompilationCache.keySet()) {
|
||||
CachedDecompilation cs = decompilationCache.get(pack);
|
||||
if (cs.text.contains(str)) {
|
||||
found.add(pack);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
cacheKeys.clear();
|
||||
cacheValues.clear();
|
||||
}
|
||||
|
||||
public void cacheScriptPack(ScriptPack scriptLeaf, List<ABCContainerTag> abcList) {
|
||||
int maxCacheSize = 50;
|
||||
int scriptIndex = scriptLeaf.scriptIndex;
|
||||
StringBuilder hilightedCodeBuf = new StringBuilder();
|
||||
String hilightedCode = "";
|
||||
@@ -306,17 +340,24 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
if (scriptIndex > -1) {
|
||||
script = abc.script_info[scriptIndex];
|
||||
}
|
||||
if (!decompilationCache.containsKey(scriptLeaf)) {
|
||||
boolean found = false;
|
||||
for (int i = 0; i < cacheKeys.size(); i++) {
|
||||
if (cacheKeys.get(i) == scriptLeaf) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
cacheKeys.add(scriptLeaf);
|
||||
for (int scriptTraitIndex : scriptLeaf.traitIndices) {
|
||||
hilightedCodeBuf.append(script.traits.traits[scriptTraitIndex].convertPackaged("", abcList, abc, false, false, scriptIndex, -1, true, new ArrayList<String>()));
|
||||
}
|
||||
hilightedCode = hilightedCodeBuf.toString();
|
||||
List<Highlighting> highlights = Highlighting.getInstrHighlights(hilightedCode);
|
||||
List<Highlighting> traitHighlights = Highlighting.getTraitHighlights(hilightedCode);
|
||||
List<Highlighting> methodHighlights = Highlighting.getMethodHighlights(hilightedCode);
|
||||
List<Highlighting> classHighlights = Highlighting.getClassHighlights(hilightedCode);
|
||||
hilightedCode = Highlighting.stripHilights(hilightedCode);
|
||||
decompilationCache.put(scriptLeaf, new CachedDecompilation(hilightedCode, highlights, traitHighlights, methodHighlights, classHighlights));
|
||||
cacheValues.add(new CachedDecompilation(hilightedCode));
|
||||
}
|
||||
if (cacheKeys.size() > maxCacheSize) {
|
||||
cacheKeys.remove(0);
|
||||
cacheValues.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,12 +379,12 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
|
||||
String hilightedCode = "";
|
||||
cacheScriptPack(scriptLeaf, abcList);
|
||||
CachedDecompilation cd = decompilationCache.get(scriptLeaf);
|
||||
CachedDecompilation cd = getCached(scriptLeaf);
|
||||
hilightedCode = cd.text;
|
||||
highlights = cd.highlights;
|
||||
traitHighlights = cd.traitHighlights;
|
||||
methodHighlights = cd.methodHighlights;
|
||||
classHighlights = cd.classHighlights;
|
||||
highlights = cd.getHighlights();
|
||||
traitHighlights = cd.getTraitHighlights();
|
||||
methodHighlights = cd.getMethodHighlights();
|
||||
classHighlights = cd.getClassHighlights();
|
||||
this.abc = abc;
|
||||
this.abcList = abcList;
|
||||
this.script = scriptLeaf;
|
||||
@@ -352,9 +393,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
|
||||
public void reloadClass() {
|
||||
int ci = classIndex;
|
||||
if (decompilationCache.containsKey(script)) {
|
||||
decompilationCache.remove(script);
|
||||
}
|
||||
uncache(script);
|
||||
if ((script != null) && (abc != null)) {
|
||||
setScript(script, abcList);
|
||||
}
|
||||
@@ -368,7 +407,8 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL
|
||||
|
||||
public void setABC(ABC abc) {
|
||||
this.abc = abc;
|
||||
decompilationCache.clear();
|
||||
cacheKeys.clear();
|
||||
cacheValues.clear();
|
||||
setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,8 +402,8 @@ public class Action implements GraphSourceItem {
|
||||
boolean lastPush = false;
|
||||
StringBuilder ret = new StringBuilder();
|
||||
for (GraphSourceItem s : srcList) {
|
||||
for (DisassemblyListener l : listeners) {
|
||||
l.progress("toString", pos + 2, srcList.size());
|
||||
for (int i = 0; i < listeners.size(); i++) {
|
||||
listeners.get(i).progress("toString", pos + 2, srcList.size());
|
||||
}
|
||||
Action a = null;
|
||||
if (s instanceof Action) {
|
||||
|
||||
@@ -19,13 +19,18 @@ package com.jpexs.decompiler.flash.action.gui;
|
||||
import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.Main;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.abc.ScriptPack;
|
||||
import com.jpexs.decompiler.flash.abc.gui.DecompiledEditorPane;
|
||||
import com.jpexs.decompiler.flash.abc.gui.LineMarkedEditorPane;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.action.ActionGraph;
|
||||
import com.jpexs.decompiler.flash.action.parser.ParseException;
|
||||
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParser;
|
||||
import com.jpexs.decompiler.flash.action.parser.script.ActionScriptParser;
|
||||
import com.jpexs.decompiler.flash.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.flash.gui.GraphFrame;
|
||||
import com.jpexs.decompiler.flash.gui.TagNode;
|
||||
import com.jpexs.decompiler.flash.gui.TagTreeModel;
|
||||
import com.jpexs.decompiler.flash.gui.View;
|
||||
import com.jpexs.decompiler.flash.helpers.Helper;
|
||||
import com.jpexs.decompiler.flash.helpers.Highlighting;
|
||||
@@ -41,14 +46,27 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import javax.swing.*;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSplitPane;
|
||||
import javax.swing.JToggleButton;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.BevelBorder;
|
||||
import javax.swing.event.CaretEvent;
|
||||
import javax.swing.event.CaretListener;
|
||||
import javax.swing.tree.TreePath;
|
||||
import jsyntaxpane.DefaultSyntaxKit;
|
||||
import jsyntaxpane.actions.DocumentSearchData;
|
||||
import jsyntaxpane.actions.gui.QuickFindDialog;
|
||||
|
||||
public class ActionPanel extends JPanel implements ActionListener {
|
||||
|
||||
@@ -83,6 +101,108 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
private String srcWithHex;
|
||||
private String srcNoHex;
|
||||
private String lastDecompiled = "";
|
||||
public JPanel searchPanel;
|
||||
public JLabel searchPos;
|
||||
private List<ASMSource> found = new ArrayList<ASMSource>();
|
||||
private int foundPos = 0;
|
||||
private JLabel searchForLabel;
|
||||
private String searchFor;
|
||||
private List<ASMSource> cacheKeys = new LinkedList<ASMSource>();
|
||||
private List<CachedScript> cacheValues = new LinkedList<CachedScript>();
|
||||
//private HashMap<ASMSource, CachedScript> cache = new HashMap<ASMSource, CachedScript>();
|
||||
private boolean searchIgnoreCase;
|
||||
private boolean searchRegexp;
|
||||
|
||||
private CachedScript getCached(ASMSource pack) {
|
||||
for (int i = 0; i < cacheKeys.size(); i++) {
|
||||
if (cacheKeys.get(i) == pack) {
|
||||
return cacheValues.get(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void cacheScript(ASMSource src) {
|
||||
int maxCacheSize = 20;
|
||||
for (int i = 0; i < cacheKeys.size(); i++) {
|
||||
if (cacheKeys.get(i) == src) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
List<Action> as = src.getActions(SWF.DEFAULT_VERSION);
|
||||
String s = com.jpexs.decompiler.flash.action.Action.actionsToSource(as, SWF.DEFAULT_VERSION);
|
||||
List<Highlighting> hilights = Highlighting.getInstrHighlights(s);
|
||||
String srcNoHex = Highlighting.stripHilights(s);
|
||||
cacheKeys.add(src);
|
||||
cacheValues.add(new CachedScript(srcNoHex, hilights, as));
|
||||
if (cacheKeys.size() > maxCacheSize) {
|
||||
cacheKeys.remove(0);
|
||||
cacheValues.remove(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class CachedScript {
|
||||
|
||||
public String text;
|
||||
List<Highlighting> hilights;
|
||||
List<com.jpexs.decompiler.flash.action.Action> actions;
|
||||
|
||||
public CachedScript(String text, List<Highlighting> hilights, List<Action> actions) {
|
||||
this.text = text;
|
||||
this.hilights = hilights;
|
||||
this.actions = actions;
|
||||
}
|
||||
}
|
||||
|
||||
private List<ASMSource> getASMs(List<TagNode> nodes) {
|
||||
List<ASMSource> ret = new ArrayList<ASMSource>();
|
||||
for (TagNode n : nodes) {
|
||||
if (n.tag instanceof ASMSource) {
|
||||
//cacheScript((ASMSource) n.tag);
|
||||
ret.add((ASMSource) n.tag);
|
||||
}
|
||||
ret.addAll(getASMs(n.subItems));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean search(String txt, boolean ignoreCase, boolean regexp) {
|
||||
if ((txt != null) && (!txt.equals(""))) {
|
||||
searchIgnoreCase = ignoreCase;
|
||||
searchRegexp = regexp;
|
||||
List<Object> tags = new ArrayList<Object>(Main.swf.tags);
|
||||
List<TagNode> list = Main.swf.createASTagList(tags, null);
|
||||
List<ASMSource> asms = getASMs(list);
|
||||
found = new ArrayList<ASMSource>();
|
||||
Pattern pat = null;
|
||||
if (regexp) {
|
||||
pat = Pattern.compile(txt, ignoreCase ? Pattern.CASE_INSENSITIVE : 0);
|
||||
} else {
|
||||
pat = Pattern.compile(Pattern.quote(txt), ignoreCase ? Pattern.CASE_INSENSITIVE : 0);
|
||||
}
|
||||
for (ASMSource s : asms) {
|
||||
cacheScript(s);
|
||||
if (pat.matcher(getCached(s).text).find()) {
|
||||
found.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
if (found.isEmpty()) {
|
||||
searchPanel.setVisible(false);
|
||||
return false;
|
||||
} else {
|
||||
foundPos = 0;
|
||||
setSource(found.get(foundPos), true);
|
||||
searchPanel.setVisible(true);
|
||||
searchFor = txt;
|
||||
updateSearchPos();
|
||||
searchForLabel.setText("Search for \"" + txt + "\" : ");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
int pos = editor.getCaretPosition();
|
||||
@@ -116,7 +236,7 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
setText(hex ? srcWithHex : srcNoHex);
|
||||
}
|
||||
|
||||
public void setSource(ASMSource src) {
|
||||
public void setSource(ASMSource src, final boolean useCache) {
|
||||
this.src = src;
|
||||
Main.startWork("Decompiling...");
|
||||
final ASMSource asm = (ASMSource) src;
|
||||
@@ -154,32 +274,21 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
setHex(hexButton.isSelected());
|
||||
if (Main.DO_DECOMPILE) {
|
||||
decompiledEditor.setText("//Decompiling...");
|
||||
List<com.jpexs.decompiler.flash.action.Action> as = asm.getActions(SWF.DEFAULT_VERSION);
|
||||
lastCode = as;
|
||||
//com.jpexs.decompiler.flash.action.Action.setActionsAddresses(as, 0, SWF.DEFAULT_VERSION);
|
||||
String s = com.jpexs.decompiler.flash.action.Action.actionsToSource(as, SWF.DEFAULT_VERSION);
|
||||
decompiledHilights = Highlighting.getInstrHighlights(s);
|
||||
String stripped = Highlighting.stripHilights(s);
|
||||
/*try {
|
||||
ActionScriptParser.parse(stripped);
|
||||
} catch (ParseException ex) {
|
||||
JOptionPane.showMessageDialog(null, ex.getMessage());
|
||||
Logger.getLogger(ActionPanel.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(ActionPanel.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}*/
|
||||
lastDecompiled = stripped;
|
||||
/*if(lastDecompiled.length()>30000){
|
||||
decompiledEditor.setContentType("text/plain");
|
||||
}else{
|
||||
decompiledEditor.setContentType("text/actionscript");
|
||||
}*/
|
||||
String stripped = "";
|
||||
if (!useCache) {
|
||||
uncache(asm);
|
||||
}
|
||||
cacheScript(asm);
|
||||
CachedScript sc = getCached(asm);
|
||||
lastCode = sc.actions;
|
||||
decompiledHilights = sc.hilights;
|
||||
lastDecompiled = sc.text;
|
||||
stripped = lastDecompiled;
|
||||
decompiledEditor.setText(lastDecompiled);
|
||||
|
||||
if (debugRecompile) {
|
||||
try {
|
||||
ActionScriptParser ps = new ActionScriptParser();
|
||||
|
||||
recompiledEditor.setText(Highlighting.stripHilights(com.jpexs.decompiler.flash.action.Action.actionsToString(new ArrayList<DisassemblyListener>(), 0, ps.parse(stripped), null, SWF.DEFAULT_VERSION, false, 0)));
|
||||
} catch (ParseException ex) {
|
||||
Logger.getLogger(ActionPanel.class.getName()).log(Level.SEVERE, null, ex);
|
||||
@@ -199,7 +308,6 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
}
|
||||
|
||||
public ActionPanel() {
|
||||
this.list = list;
|
||||
DefaultSyntaxKit.initKit();
|
||||
editor = new LineMarkedEditorPane();
|
||||
editor.setEditable(false);
|
||||
@@ -209,6 +317,30 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
recompiledEditor = new LineMarkedEditorPane();
|
||||
recompiledEditor.setEditable(false);
|
||||
|
||||
searchPanel = new JPanel(new FlowLayout());
|
||||
|
||||
JButton prevSearchButton = new JButton(View.getIcon("prev16"));
|
||||
prevSearchButton.setMargin(new Insets(3, 3, 3, 3));
|
||||
prevSearchButton.addActionListener(this);
|
||||
prevSearchButton.setActionCommand("SEARCHPREV");
|
||||
JButton nextSearchButton = new JButton(View.getIcon("next16"));
|
||||
nextSearchButton.setMargin(new Insets(3, 3, 3, 3));
|
||||
nextSearchButton.addActionListener(this);
|
||||
nextSearchButton.setActionCommand("SEARCHNEXT");
|
||||
JButton cancelSearchButton = new JButton(View.getIcon("cancel16"));
|
||||
cancelSearchButton.setMargin(new Insets(3, 3, 3, 3));
|
||||
cancelSearchButton.addActionListener(this);
|
||||
cancelSearchButton.setActionCommand("SEARCHCANCEL");
|
||||
searchPos = new JLabel("0/0");
|
||||
searchForLabel = new JLabel("Search for \"\": ");
|
||||
searchPanel.add(searchForLabel);
|
||||
searchPanel.add(prevSearchButton);
|
||||
searchPanel.add(new JLabel("Script "));
|
||||
searchPanel.add(searchPos);
|
||||
searchPanel.add(nextSearchButton);
|
||||
searchPanel.add(cancelSearchButton);
|
||||
|
||||
|
||||
JButton graphButton = new JButton(View.getIcon("graph16"));
|
||||
graphButton.setActionCommand("GRAPH");
|
||||
graphButton.addActionListener(this);
|
||||
@@ -289,9 +421,14 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
saveDecompiledButton.setVisible(false);
|
||||
cancelDecompiledButton.setVisible(false);
|
||||
|
||||
JPanel decPanel = new JPanel(new BorderLayout());
|
||||
decPanel.add(new JScrollPane(decompiledEditor), BorderLayout.CENTER);
|
||||
decPanel.add(searchPanel, BorderLayout.NORTH);
|
||||
|
||||
searchPanel.setVisible(false);
|
||||
JPanel panA = new JPanel();
|
||||
panA.setLayout(new BorderLayout());
|
||||
panA.add(new JScrollPane(decompiledEditor), BorderLayout.CENTER);
|
||||
panA.add(decPanel, BorderLayout.CENTER);
|
||||
panA.add(decLabel, BorderLayout.NORTH);
|
||||
panA.add(decButtonsPan, BorderLayout.SOUTH);
|
||||
decLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
@@ -366,7 +503,9 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
for (Highlighting h2 : disassembledHilights) {
|
||||
if (h2.offset == h.offset) {
|
||||
ignoreCarret = true;
|
||||
editor.setCaretPosition(h2.startPos);
|
||||
if (h2.startPos > 0 && h2.startPos < editor.getText().length()) {
|
||||
editor.setCaretPosition(h2.startPos);
|
||||
}
|
||||
editor.getCaret().setVisible(true);
|
||||
ignoreCarret = false;
|
||||
break;
|
||||
@@ -437,6 +576,23 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (e.getActionCommand().equals("SEARCHCANCEL")) {
|
||||
foundPos = 0;
|
||||
searchPanel.setVisible(false);
|
||||
found = new ArrayList<ASMSource>();
|
||||
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();
|
||||
}
|
||||
if (e.getActionCommand().equals("GRAPH")) {
|
||||
if (lastCode != null) {
|
||||
GraphFrame gf = new GraphFrame(new ActionGraph(lastCode, new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>(), SWF.DEFAULT_VERSION), "");
|
||||
@@ -452,7 +608,7 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
} else if (e.getActionCommand().equals("SAVEACTION")) {
|
||||
try {
|
||||
src.setActions(ASMParser.parse(0, src.getPos(), true, new ByteArrayInputStream(editor.getText().getBytes()), SWF.DEFAULT_VERSION), SWF.DEFAULT_VERSION);
|
||||
setSource(this.src);
|
||||
setSource(this.src, false);
|
||||
JOptionPane.showMessageDialog(this, "Code successfully saved");
|
||||
saveButton.setVisible(false);
|
||||
cancelButton.setVisible(false);
|
||||
@@ -472,7 +628,7 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
try {
|
||||
ActionScriptParser par = new ActionScriptParser();
|
||||
src.setActions(par.parse(decompiledEditor.getText()), SWF.DEFAULT_VERSION);
|
||||
setSource(this.src);
|
||||
setSource(this.src, false);
|
||||
JOptionPane.showMessageDialog(this, "Code successfully saved");
|
||||
saveDecompiledButton.setVisible(false);
|
||||
cancelDecompiledButton.setVisible(false);
|
||||
@@ -487,4 +643,35 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSearchPos() {
|
||||
searchPos.setText((foundPos + 1) + "/" + found.size());
|
||||
setSource(found.get(foundPos), true);
|
||||
TagTreeModel ttm = (TagTreeModel) Main.mainFrame.tagTree.getModel();
|
||||
TreePath tp = ttm.getTagPath(found.get(foundPos));
|
||||
Main.mainFrame.tagTree.setSelectionPath(tp);
|
||||
Main.mainFrame.tagTree.scrollPathToVisible(tp);
|
||||
decompiledEditor.setCaretPosition(0);
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(ActionPanel.class.getName()).log(Level.SEVERE, null, ex);
|
||||
}
|
||||
DocumentSearchData dsd = DocumentSearchData.getFromEditor(decompiledEditor);
|
||||
dsd.setPattern(searchFor, searchRegexp, searchIgnoreCase);
|
||||
QuickFindDialog quickFindDlg = new QuickFindDialog(decompiledEditor, dsd);
|
||||
quickFindDlg.setRegularExpression(searchRegexp);
|
||||
quickFindDlg.setIgnoreCase(searchIgnoreCase);
|
||||
quickFindDlg.showFor(decompiledEditor);
|
||||
}
|
||||
|
||||
private void uncache(ASMSource pack) {
|
||||
for (int i = 0; i < cacheKeys.size(); i++) {
|
||||
if (cacheKeys.get(i) == pack) {
|
||||
cacheValues.remove(i);
|
||||
cacheKeys.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
|
||||
miProxy.setIcon(View.getIcon("proxy16"));
|
||||
miProxy.addActionListener(this);
|
||||
|
||||
JMenuItem miSearchScript = new JMenuItem("Search ActionScript...");
|
||||
JMenuItem miSearchScript = new JMenuItem("Search All ActionScript...");
|
||||
miSearchScript.addActionListener(this);
|
||||
miSearchScript.setActionCommand("SEARCHAS");
|
||||
miSearchScript.setIcon(View.getIcon("search16"));
|
||||
@@ -1132,28 +1132,46 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
|
||||
public boolean confirmExperimental() {
|
||||
return JOptionPane.showConfirmDialog(null, "Following procedure can damage SWF file which can be then unplayable.\r\nUSE IT ON YOUR OWN RISK. Do you want to continue?", "Warning", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE) == JOptionPane.OK_OPTION;
|
||||
}
|
||||
private SearchDialog searchDialog;
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
if (e.getActionCommand().equals("SEARCHAS")) {
|
||||
if (abcPanel != null) {
|
||||
final String txt = JOptionPane.showInputDialog("Search text:");
|
||||
if (txt != null) {
|
||||
if (searchDialog == null) {
|
||||
searchDialog = new SearchDialog();
|
||||
}
|
||||
searchDialog.setVisible(true);
|
||||
if (searchDialog.result) {
|
||||
final String txt = searchDialog.searchField.getText();
|
||||
if (!txt.equals("")) {
|
||||
Main.startWork("Searching \"" + txt + "\"...");
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (abcPanel.search(txt)) {
|
||||
showDetail(DETAILCARDAS3NAVIGATOR);
|
||||
showCard(CARDACTIONSCRIPTPANEL);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null, "String \"" + txt + "\" not found.", "Not found", JOptionPane.INFORMATION_MESSAGE);
|
||||
if (abcPanel != null) {
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (abcPanel.search(txt, searchDialog.ignoreCaseCheckBox.isSelected(), searchDialog.regexpCheckBox.isSelected())) {
|
||||
showDetail(DETAILCARDAS3NAVIGATOR);
|
||||
showCard(CARDACTIONSCRIPTPANEL);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null, "String \"" + txt + "\" not found.", "Not found", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
Main.stopWork();
|
||||
}
|
||||
Main.stopWork();
|
||||
}
|
||||
}).start();
|
||||
|
||||
}).start();
|
||||
} else {
|
||||
(new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (actionPanel.search(txt, searchDialog.ignoreCaseCheckBox.isSelected(), searchDialog.regexpCheckBox.isSelected())) {
|
||||
showCard(CARDACTIONSCRIPTPANEL);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null, "String \"" + txt + "\" not found.", "Not found", JOptionPane.INFORMATION_MESSAGE);
|
||||
}
|
||||
Main.stopWork();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1787,7 +1805,7 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi
|
||||
showCard(CARDEMPTYPANEL);
|
||||
} else if (tagObj instanceof ASMSource) {
|
||||
showCard(CARDACTIONSCRIPTPANEL);
|
||||
actionPanel.setSource((ASMSource) tagObj);
|
||||
actionPanel.setSource((ASMSource) tagObj, true);
|
||||
} else if (tagObj instanceof ImageTag) {
|
||||
imageButtonsPanel.setVisible(((ImageTag) tagObj).importSupported());
|
||||
showCard(CARDIMAGEPANEL);
|
||||
|
||||
103
trunk/src/com/jpexs/decompiler/flash/gui/SearchDialog.java
Normal file
103
trunk/src/com/jpexs/decompiler/flash/gui/SearchDialog.java
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.gui;
|
||||
|
||||
import java.awt.Container;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class SearchDialog extends JDialog implements ActionListener {
|
||||
|
||||
public JTextField searchField = new JTextField();
|
||||
public JCheckBox ignoreCaseCheckBox = new JCheckBox("Ignore case");
|
||||
public JCheckBox regexpCheckBox = new JCheckBox("Regular expression");
|
||||
public boolean result = false;
|
||||
|
||||
public SearchDialog() {
|
||||
setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
|
||||
Container cnt = getContentPane();
|
||||
setSize(400, 150);
|
||||
cnt.setLayout(new BoxLayout(cnt, BoxLayout.PAGE_AXIS));
|
||||
JPanel panButtons = new JPanel(new FlowLayout());
|
||||
JButton okButton = new JButton("OK");
|
||||
okButton.setActionCommand("OK");
|
||||
okButton.addActionListener(this);
|
||||
JButton cancelButton = new JButton("Cancel");
|
||||
cancelButton.setActionCommand("CANCEL");
|
||||
cancelButton.addActionListener(this);
|
||||
panButtons.add(okButton);
|
||||
panButtons.add(cancelButton);
|
||||
JPanel panField = new JPanel(new FlowLayout());
|
||||
searchField.setPreferredSize(new Dimension(250, 25));
|
||||
panField.add(new JLabel("Search text:"));
|
||||
panField.add(searchField);
|
||||
cnt.add(panField);
|
||||
JPanel checkPanel = new JPanel(new FlowLayout());
|
||||
checkPanel.add(ignoreCaseCheckBox);
|
||||
checkPanel.add(regexpCheckBox);
|
||||
cnt.add(checkPanel);
|
||||
cnt.add(panButtons);
|
||||
getRootPane().setDefaultButton(okButton);
|
||||
View.centerScreen(this);
|
||||
View.setWindowIcon(this);
|
||||
setTitle("ActionScript search");
|
||||
setModalityType(ModalityType.APPLICATION_MODAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b) {
|
||||
if (b) {
|
||||
result = false;
|
||||
searchField.requestFocusInWindow();
|
||||
}
|
||||
super.setVisible(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (e.getActionCommand().equals("OK")) {
|
||||
if (regexpCheckBox.isSelected()) {
|
||||
try {
|
||||
Pattern pat = Pattern.compile(searchField.getText());
|
||||
} catch (PatternSyntaxException ex) {
|
||||
JOptionPane.showMessageDialog(null, "Invalid pattern", "Error", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,44 @@ public class TagTreeModel implements TreeModel {
|
||||
this.list = list;
|
||||
}
|
||||
|
||||
private List<Object> searchTag(Object obj, Object parent, List<Object> path) {
|
||||
List<Object> ret = null;
|
||||
int cnt = getChildCount(parent);
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
Object n = getChild(parent, i);
|
||||
List<Object> newPath = new ArrayList<Object>();
|
||||
newPath.addAll(path);
|
||||
newPath.add(n);
|
||||
|
||||
if (n instanceof TreeElement) {
|
||||
TreeElement te = (TreeElement) n;
|
||||
Object it = te.getItem();
|
||||
if (obj == it) {
|
||||
return newPath;
|
||||
}
|
||||
}
|
||||
if (n instanceof TagNode) {
|
||||
TagNode nd = (TagNode) n;
|
||||
if (nd.tag == obj) {
|
||||
return newPath;
|
||||
}
|
||||
}
|
||||
ret = searchTag(obj, n, newPath);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public TreePath getTagPath(Object obj) {
|
||||
List<Object> path = new ArrayList<Object>();
|
||||
path.add(getRoot());
|
||||
path = searchTag(obj, getRoot(), path);
|
||||
TreePath tp = new TreePath(path.toArray(new Object[path.size()]));
|
||||
return tp;
|
||||
}
|
||||
|
||||
public List<TagNode> getNodeList() {
|
||||
return list;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user