From 9825eb1e9b617af41759e5727ae0105c4e791a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=F8=EDk?= Date: Sun, 19 May 2013 15:50:40 +0200 Subject: [PATCH] Issue #85 - AS3 Text search --- .../decompiler/flash/abc/gui/ABCPanel.java | 104 +++++++++++++++++- .../flash/abc/gui/ClassesListTreeModel.java | 6 + .../flash/abc/gui/DecompiledEditorPane.java | 75 ++++++++----- .../jpexs/decompiler/flash/gui/MainFrame.java | 29 +++++ .../decompiler/flash/gui/graphics/next16.png | Bin 0 -> 736 bytes .../decompiler/flash/gui/graphics/prev16.png | Bin 0 -> 745 bytes 6 files changed, 181 insertions(+), 33 deletions(-) create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/graphics/next16.png create mode 100644 trunk/src/com/jpexs/decompiler/flash/gui/graphics/prev16.png diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/gui/ABCPanel.java b/trunk/src/com/jpexs/decompiler/flash/abc/gui/ABCPanel.java index 88448dc11..60bcaa40d 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/gui/ABCPanel.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/gui/ABCPanel.java @@ -18,15 +18,18 @@ package com.jpexs.decompiler.flash.abc.gui; 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.View; import com.jpexs.decompiler.flash.tags.ABCContainerTag; import java.awt.BorderLayout; import java.awt.Component; +import java.awt.FlowLayout; import java.awt.Font; import java.awt.Insets; import java.awt.event.*; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -36,6 +39,7 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.table.*; import jsyntaxpane.DefaultSyntaxKit; +import jsyntaxpane.actions.DocumentSearchData; public class ABCPanel extends JPanel implements ItemListener, ActionListener { @@ -58,6 +62,36 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener { public JTextField filterField = new JTextField(""); public JPanel navPanel; public JTabbedPane tabbedPane; + public JPanel searchPanel; + public JLabel searchPos; + private List found = new ArrayList(); + private int foundPos = 0; + private JLabel searchForLabel; + private String searchFor; + + public boolean search(String txt) { + if ((txt != null) && (!txt.equals(""))) { + ClassesListTreeModel clModel = (ClassesListTreeModel) classTree.getModel(); + HashMap allpacks = clModel.getList(); + for (ScriptPack p : allpacks.values()) { + decompiledTextArea.cacheScriptPack(p, list); + } + found = decompiledTextArea.searchCache(txt); + if (found.isEmpty()) { + searchPanel.setVisible(false); + return false; + } else { + foundPos = 0; + decompiledTextArea.setScript(found.get(foundPos), list); + searchPanel.setVisible(true); + searchFor = txt; + updateSearchPos(); + searchForLabel.setText("Search for \"" + txt + "\" : "); + } + return true; + } + return false; + } private JTable autoResizeColWidth(JTable table, TableModel model) { table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); @@ -189,11 +223,19 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener { decompiledTextArea = new DecompiledEditorPane(this); + + + searchPanel = new JPanel(new FlowLayout()); + decompiledScrollPane = new JScrollPane(decompiledTextArea); + + JPanel decPanel = new JPanel(new BorderLayout()); + decPanel.add(searchPanel, BorderLayout.NORTH); + decPanel.add(decompiledScrollPane, BorderLayout.CENTER); detailPanel = new DetailPanel(this); JPanel panB = new JPanel(); panB.setLayout(new BorderLayout()); - panB.add(decompiledScrollPane, BorderLayout.CENTER); + panB.add(decPanel, BorderLayout.CENTER); panB.add(decLabel, BorderLayout.NORTH); decLabel.setHorizontalAlignment(SwingConstants.CENTER); decLabel.setBorder(new BevelBorder(BevelBorder.RAISED)); @@ -259,12 +301,36 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener { JPanel treePanel = new JPanel(); treePanel.setLayout(new BorderLayout()); treePanel.add(new JScrollPane(classTree = new ClassesListTree(list, this)), BorderLayout.CENTER); - JPanel searchPanel = new JPanel(); - searchPanel.setLayout(new BorderLayout()); - searchPanel.add(filterField, BorderLayout.CENTER); + JPanel filterPanel = new JPanel(); + filterPanel.setLayout(new BorderLayout()); + filterPanel.add(filterField, BorderLayout.CENTER); + 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); + + + + searchPanel.setVisible(false); JLabel picLabel = new JLabel(View.getIcon("search16")); - searchPanel.add(picLabel, BorderLayout.EAST); - treePanel.add(searchPanel, BorderLayout.NORTH); + filterPanel.add(picLabel, BorderLayout.EAST); + treePanel.add(filterPanel, BorderLayout.NORTH); splitPaneTreeVSNavigator = new JSplitPane(JSplitPane.VERTICAL_SPLIT, treePanel, @@ -360,10 +426,36 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener { setVisible(true); } + public void updateSearchPos() { + searchPos.setText((foundPos + 1) + "/" + found.size()); + decompiledTextArea.setScript(found.get(foundPos), list); + decompiledTextArea.setCaretPosition(0); + DocumentSearchData dsd = DocumentSearchData.getFromEditor(decompiledTextArea); + dsd.setPattern(searchFor, false, false); + dsd.showQuickFindDialog(decompiledTextArea); + } + @Override public void actionPerformed(ActionEvent e) { if (e.getActionCommand().equals("FILTERSCRIPT")) { doFilter(); } + if (e.getActionCommand().equals("SEARCHCANCEL")) { + foundPos = 0; + searchPanel.setVisible(false); + found = new ArrayList(); + searchFor = null; + } + if (e.getActionCommand().equals("SEARCHPREV")) { + foundPos--; + if (foundPos < 0) { + foundPos += found.size(); + } + updateSearchPos(); + } + if (e.getActionCommand().equals("SEARCHNEXT")) { + foundPos = (foundPos + 1) % found.size(); + updateSearchPos(); + } } } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/gui/ClassesListTreeModel.java b/trunk/src/com/jpexs/decompiler/flash/abc/gui/ClassesListTreeModel.java index 69f9e7227..cde87024c 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/gui/ClassesListTreeModel.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/gui/ClassesListTreeModel.java @@ -75,6 +75,11 @@ class ClassIndexVisitor implements TreeVisitor { public class ClassesListTreeModel implements TreeModel { private Tree classTree = new Tree(); + private HashMap list; + + public HashMap getList() { + return list; + } public ClassesListTreeModel(HashMap list) { this(list, null); @@ -93,6 +98,7 @@ public class ClassesListTreeModel implements TreeModel { String packageName = path.substring(0, path.lastIndexOf(".")); classTree.add(nsName, packageName, list.get(path)); } + this.list = list; } diff --git a/trunk/src/com/jpexs/decompiler/flash/abc/gui/DecompiledEditorPane.java b/trunk/src/com/jpexs/decompiler/flash/abc/gui/DecompiledEditorPane.java index e116691b0..f2e6cf35a 100644 --- a/trunk/src/com/jpexs/decompiler/flash/abc/gui/DecompiledEditorPane.java +++ b/trunk/src/com/jpexs/decompiler/flash/abc/gui/DecompiledEditorPane.java @@ -212,7 +212,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL } } - private class BufferedClass { + private class CachedDecompilation { public String text; public List highlights; @@ -220,7 +220,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL public List methodHighlights; public List classHighlights; - public BufferedClass(String text, List highlights, List traitHighlights, List methodHighlights, List classHighlights) { + public CachedDecompilation(String text, List highlights, List traitHighlights, List methodHighlights, List classHighlights) { this.text = text; this.highlights = highlights; this.traitHighlights = traitHighlights; @@ -228,7 +228,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL this.classHighlights = classHighlights; } } - private HashMap bufferedClasses = new HashMap(); + private HashMap decompilationCache = new HashMap(); public void gotoLastTrait() { gotoTrait(lastTraitIndex); @@ -283,7 +283,41 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL private List abcList; public void clearScriptCache() { - bufferedClasses.clear(); + decompilationCache.clear(); + } + + public List searchCache(String str) { + List found = new ArrayList(); + for (ScriptPack pack : decompilationCache.keySet()) { + CachedDecompilation cs = decompilationCache.get(pack); + if (cs.text.contains(str)) { + found.add(pack); + } + } + return found; + } + + public void cacheScriptPack(ScriptPack scriptLeaf, List abcList) { + int scriptIndex = scriptLeaf.scriptIndex; + StringBuilder hilightedCodeBuf = new StringBuilder(); + String hilightedCode = ""; + ScriptInfo script = null; + ABC abc = scriptLeaf.abc; + if (scriptIndex > -1) { + script = abc.script_info[scriptIndex]; + } + if (!decompilationCache.containsKey(scriptLeaf)) { + for (int scriptTraitIndex : scriptLeaf.traitIndices) { + hilightedCodeBuf.append(script.traits.traits[scriptTraitIndex].convertPackaged("", abcList, abc, false, false, scriptIndex, -1, true, new ArrayList())); + } + hilightedCode = hilightedCodeBuf.toString(); + List highlights = Highlighting.getInstrHighlights(hilightedCode); + List traitHighlights = Highlighting.getTraitHighlights(hilightedCode); + List methodHighlights = Highlighting.getMethodHighlights(hilightedCode); + List classHighlights = Highlighting.getClassHighlights(hilightedCode); + hilightedCode = Highlighting.stripHilights(hilightedCode); + decompilationCache.put(scriptLeaf, new CachedDecompilation(hilightedCode, highlights, traitHighlights, methodHighlights, classHighlights)); + } } public void setScript(ScriptPack scriptLeaf, List abcList) { @@ -302,27 +336,14 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL } setText("//Please wait..."); - StringBuilder hilightedCodeBuf = new StringBuilder(); String hilightedCode = ""; - if (!bufferedClasses.containsKey(scriptLeaf)) { - for (int scriptTraitIndex : scriptLeaf.traitIndices) { - hilightedCodeBuf.append(script.traits.traits[scriptTraitIndex].convertPackaged("", abcList, abc, false, false, scriptIndex, -1, true, new ArrayList())); - } - hilightedCode = hilightedCodeBuf.toString(); - highlights = Highlighting.getInstrHighlights(hilightedCode); - traitHighlights = Highlighting.getTraitHighlights(hilightedCode); - methodHighlights = Highlighting.getMethodHighlights(hilightedCode); - classHighlights = Highlighting.getClassHighlights(hilightedCode); - hilightedCode = Highlighting.stripHilights(hilightedCode); - bufferedClasses.put(scriptLeaf, new BufferedClass(hilightedCode, highlights, traitHighlights, methodHighlights, classHighlights)); - } else { - BufferedClass bc = bufferedClasses.get(scriptLeaf); - hilightedCode = bc.text; - highlights = bc.highlights; - traitHighlights = bc.traitHighlights; - methodHighlights = bc.methodHighlights; - classHighlights = bc.classHighlights; - } + cacheScriptPack(scriptLeaf, abcList); + CachedDecompilation cd = decompilationCache.get(scriptLeaf); + hilightedCode = cd.text; + highlights = cd.highlights; + traitHighlights = cd.traitHighlights; + methodHighlights = cd.methodHighlights; + classHighlights = cd.classHighlights; this.abc = abc; this.abcList = abcList; this.script = scriptLeaf; @@ -331,8 +352,8 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL public void reloadClass() { int ci = classIndex; - if (bufferedClasses.containsKey(script)) { - bufferedClasses.remove(script); + if (decompilationCache.containsKey(script)) { + decompilationCache.remove(script); } if ((script != null) && (abc != null)) { setScript(script, abcList); @@ -347,7 +368,7 @@ public class DecompiledEditorPane extends LineMarkedEditorPane implements CaretL public void setABC(ABC abc) { this.abc = abc; - bufferedClasses.clear(); + decompilationCache.clear(); setText(""); } } diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java index 350e0d149..97b905506 100644 --- a/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java +++ b/trunk/src/com/jpexs/decompiler/flash/gui/MainFrame.java @@ -354,6 +354,13 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi miProxy.setActionCommand("SHOWPROXY"); miProxy.setIcon(View.getIcon("proxy16")); miProxy.addActionListener(this); + + JMenuItem miSearchScript = new JMenuItem("Search ActionScript..."); + miSearchScript.addActionListener(this); + miSearchScript.setActionCommand("SEARCHAS"); + miSearchScript.setIcon(View.getIcon("search16")); + + menuTools.add(miSearchScript); menuTools.add(miProxy); //menuTools.add(menuDeobfuscation); @@ -1128,6 +1135,28 @@ public class MainFrame extends JFrame implements ActionListener, TreeSelectionLi @Override public void actionPerformed(ActionEvent e) { + + if (e.getActionCommand().equals("SEARCHAS")) { + if (abcPanel != null) { + final String txt = JOptionPane.showInputDialog("Search text:"); + if (txt != null) { + 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); + } + Main.stopWork(); + } + }).start(); + + } + } + } if (e.getActionCommand().equals("REPLACEIMAGE")) { Object tagObj = tagTree.getLastSelectedPathComponent(); if (tagObj == null) { diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/graphics/next16.png b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/next16.png new file mode 100644 index 0000000000000000000000000000000000000000..4a2f9d4e4a81857f509d85bbe46936c99709cd6f GIT binary patch literal 736 zcmV<60w4W}P)_TF$F*h9sL-j zNpc$weSXQZ6Gag%5kOy9HfA1@g zVA*&|VjFHeVhIV!`DzQM7F-a@NRTNvNlYYp4z%6NAQuJno^MeOJ!7dzy8e(=;etr6 z4q2h83Vb36o=G4!6u79$u)6u4LoN!;_)kItHmh9g5CP1HxVh+sSiS*Mlqx_uVfwL~ z+}p|}Y*;r1{g* z9DE4_W&SW~qUN5hWN@-RUJ#q3Ngxr&iJp;+4aEd;HM{A>I)B?7>yL4`Nc6h^we^ve z3YC6fwXTqAQWr8=Cd?emR={YnNptkhuSFVP{Q?6Lt^ zqF4A?)Arx1JpP&Pyh<4sUhXnam)AJ@xmkE-VuVGbg_|=vm|INb-=FD!zVlDxJ_uiv SXLQ>D0000yhD literal 0 HcmV?d00001 diff --git a/trunk/src/com/jpexs/decompiler/flash/gui/graphics/prev16.png b/trunk/src/com/jpexs/decompiler/flash/gui/graphics/prev16.png new file mode 100644 index 0000000000000000000000000000000000000000..15d1584bdbb2c26a9fc4c8269aa54615a58a4657 GIT binary patch literal 745 zcmV1hlor z)=Ec^h7>5J3?Bj(D6|X+0|UcQj&m*_Qg!D|-c07sd7pF6opXl(U}#WhWg0W$d_xV%ATb~UcS*dC+@kfS*m{?64KBH-eM78JQAu#&2c z7TM!?0X98;&a@msh@1ehFDx4~_smCS0rm@Z$dv@5Y^ec>Jl}_`uDh5!i#cpZh5&_) z{y|~cgJzZ1d%`?CxkdJIg%by0u(~PqB0%Zdj?maMmYO=M!=;B#0>~5_5YO>&?w*4H z@LRbi!eNPrxg`gUUIeK8JG(3%R{o~|7so$K+8_qZe0Iz($pKd%d&oOhA&AGYXkKE` zO8~w=kN^smCS05H!-WT*2mpbXAJK6B{s*`+;U?8|s%XO8{Hs1d`DH6am$(L0coEX9 z)c+Ho)WS9-4?6~g4NrO@c2FaKCYmmR!DQ~YpfIn+s8pr^?KThtmU&}3Kr*7R^y^Rk z5Xsb_*=oc3w-9KI@B4=+yK6a8uQ@#oTkf1PnlL+NjAm=Zh)+xqld|idFEF=^(avw| z4U*w)Kx6;tnV0ZXQD@SHtHr7{`Y12 bpX>Y!%!CO%>C8GV00000NkvXXu0mjfJYGkQ literal 0 HcmV?d00001