/*
* Copyright (C) 2010-2013 JPEXS
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.jpexs.decompiler.flash.gui.action;
import com.jpexs.decompiler.flash.Configuration;
import com.jpexs.decompiler.flash.DisassemblyListener;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.TagNode;
import com.jpexs.decompiler.flash.gui.abc.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.action.swf4.ActionPush;
import com.jpexs.decompiler.flash.action.swf4.ConstantIndex;
import com.jpexs.decompiler.flash.graph.GraphTargetItem;
import com.jpexs.decompiler.flash.gui.GraphFrame;
import com.jpexs.decompiler.flash.gui.Main;
import com.jpexs.decompiler.flash.gui.TagTreeModel;
import com.jpexs.decompiler.flash.gui.View;
import com.jpexs.decompiler.flash.helpers.Cache;
import com.jpexs.decompiler.flash.helpers.Helper;
import com.jpexs.decompiler.flash.helpers.Highlighting;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
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.SwingUtilities;
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 static com.jpexs.decompiler.flash.gui.AppStrings.translate;
public class ActionPanel extends JPanel implements ActionListener {
public LineMarkedEditorPane editor;
public LineMarkedEditorPane decompiledEditor;
public List list;
public JSplitPane splitPane;
public JButton saveButton = new JButton(translate("button.save"), View.getIcon("save16"));
public JButton editButton = new JButton(translate("button.edit"), View.getIcon("edit16"));
public JButton cancelButton = new JButton(translate("button.cancel"), View.getIcon("cancel16"));
public JLabel experimentalLabel = new JLabel(translate("action.edit.experimental"));
public JButton editDecompiledButton = new JButton(translate("button.edit"), View.getIcon("edit16"));
public JButton saveDecompiledButton = new JButton(translate("button.save"), View.getIcon("save16"));
public JButton cancelDecompiledButton = new JButton(translate("button.cancel"), View.getIcon("cancel16"));
public JToggleButton hexButton;
public JLabel asmLabel = new JLabel(translate("panel.disassembled"));
public JLabel decLabel = new JLabel(translate("panel.decompiled"));
public List decompiledHilights = new ArrayList<>();
public List disassembledHilights = new ArrayList<>();
public String lastDisasm = "";
private boolean ignoreCarret = false;
private boolean editMode = false;
private boolean editDecompiledMode = false;
private List lastCode;
private ASMSource src;
public JPanel topButtonsPan;
private String srcWithHex;
private String srcNoHex;
private String lastDecompiled = "";
public JPanel searchPanel;
public JLabel searchPos;
private List found = new ArrayList<>();
private int foundPos = 0;
private JLabel searchForLabel;
private String searchFor;
private boolean searchIgnoreCase;
private boolean searchRegexp;
private Cache cache = new Cache(true);
public void clearCache() {
cache.clear();
}
public String getStringUnderCursor() {
int pos = decompiledEditor.getCaretPosition();
for (Highlighting h : decompiledHilights) {
if ((pos >= h.startPos) && (pos < h.startPos + h.len)) {
List list = lastCode;
Action lastIns = null;
int inspos = 0;
Action selIns = null;
for (Action ins : list) {
if (h.offset == ins.getOffset()) {
selIns = ins;
break;
}
if (ins.getOffset() > h.offset) {
inspos = (int) (h.offset - lastIns.getAddress());
selIns = lastIns;
break;
}
lastIns = ins;
}
if (selIns != null) {
if (selIns instanceof ActionPush) {
ActionPush ap = (ActionPush) selIns;
Object var = ap.values.get(inspos - 1);
String identifier = null;
if (var instanceof String) {
identifier = (String) var;
}
if (var instanceof ConstantIndex) {
identifier = ap.constantPool.get(((ConstantIndex) var).index);
}
return identifier;
}
}
}
}
return null;
}
private CachedScript getCached(ASMSource pack) {
return (CachedScript) cache.get(pack);
}
private void cacheScript(ASMSource src) {
if (!cache.contains(src)) {
List as = src.getActions(SWF.DEFAULT_VERSION);
String s = com.jpexs.decompiler.flash.action.Action.actionsToSource(as, SWF.DEFAULT_VERSION);
List hilights = Highlighting.getInstrHighlights(s);
String srcNoHex = Highlighting.stripHilights(s);
cache.put(src, new CachedScript(srcNoHex, hilights));
}
}
private List getASMs(List nodes) {
List ret = new ArrayList<>();
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