Issue #85 - AS3 Text search

This commit is contained in:
Jindra Petk
2013-05-19 21:06:40 +02:00
parent 9825eb1e9b
commit 33505ff308
8 changed files with 510 additions and 97 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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("");
}
}

View File

@@ -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) {

View File

@@ -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;
}
}
}
}

View File

@@ -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);

View 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);
}
}

View File

@@ -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;
}