Added Remembering breakpoints

Added #2131 Breakpoint list dialog
Fixed AS1/2 Debugger - script was cleared on stop button
This commit is contained in:
Jindra Petřík
2023-11-25 22:25:04 +01:00
parent a74196ddf4
commit 8ceb44f25e
18 changed files with 658 additions and 190 deletions

View File

@@ -21,6 +21,8 @@ All notable changes to this project will be documented in this file.
- Multilevel binary data unpacking is possible
- [#2131] AS1/2 Debugger - show _root variable
- [#2124] Copy tags to other SWFs and replace same classes / export names
- Remembering breakpoints
- [#2131] Breakpoint list dialog
### Fixed
- [#2021], [#2000] Caret position in editors when using tabs and / or unicode
@@ -53,6 +55,7 @@ All notable changes to this project will be documented in this file.
- [#2131] Debugger - Correct walking variables tree
- [#2131] Debugger - Breakpoints can be added while SWF is running (not just on pause)
- AS3 Direct editation - types on instance variable values not properly resolved
- AS1/2 Debugger - script was cleared on stop button
### Changed
- [#2120] Exported assets no longer take names from assigned classes if there is more than 1 assigned class

View File

@@ -215,6 +215,7 @@ import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.CancellationException;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -3459,6 +3460,8 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
return list;
} catch (InterruptedException ex) {
throw ex;
} catch (CancellationException ex) {
throw ex;
} catch (Exception ex) {
logger.log(Level.SEVERE, null, ex);
return new ActionList(src.getSwf().getCharset());

View File

@@ -66,9 +66,7 @@ public final class Configuration {
public static final Level logLevel;
public static boolean showStat;
public static final String ABC_DEPS_SEPARATOR = "{*sep*}";
@ConfigurationDefaultBoolean(true)
@ConfigurationCategory("ui")
public static ConfigurationItem<Boolean> openMultipleFiles = null;

View File

@@ -20,12 +20,13 @@ package com.jpexs.decompiler.flash.configuration;
*
* @author JPEXS
*/
public class CustomConfigurationKeys {
public class CustomConfigurationKeys {
public static final String KEY_LAST_SELECTED_PATH_RESOURCES = "lastSelectedPath.resources";
public static final String KEY_LAST_SELECTED_PATH_TAGLIST = "lastSelectedPath.taglist";
public static final String KEY_CHARSET = "charset";
public static final String KEY_LIBRARY = "library";
public static final String KEY_LOADED_IMPORT_ASSETS = "loadedImportAssets";
public static final String KEY_ABC_DEPENDENCIES = "abcDependencies";
public static final String KEY_BREAKPOINTS = "breakpoints";
}

View File

@@ -17,8 +17,11 @@
package com.jpexs.decompiler.flash.configuration;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
/**
*
@@ -29,7 +32,22 @@ public class SwfSpecificCustomConfiguration implements Serializable {
private static final long serialVersionUID = 0x2acb421da57f5eb4L;
private Map<String, String> customData = new HashMap<>();
public static final String LIST_SEPARATOR = "{*sep*}";
public List<String> getCustomDataAsList(String key) {
String data = getCustomData(key, "");
String[] parts = (data + LIST_SEPARATOR).split(Pattern.quote(LIST_SEPARATOR));
List<String> result = new ArrayList<>();
for (String part : parts) {
if (!part.isEmpty()) {
result.add(part);
}
}
return result;
}
public String getCustomData(String key, String defaultValue) {
if (customData.containsKey(key)) {
return customData.get(key);
@@ -41,4 +59,8 @@ public class SwfSpecificCustomConfiguration implements Serializable {
public void setCustomData(String key, String value) {
customData.put(key, value);
}
public void setCustomData(String key, Iterable<? extends CharSequence> value) {
customData.put(key, String.join(LIST_SEPARATOR, value));
}
}

View File

@@ -0,0 +1,253 @@
/*
* Copyright (C) 2022-2023 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 com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Image;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
/**
*
* @author JPEXS
*/
public class BreakpointListDialog extends AppDialog {
private SWF swf;
private JTable table = new JTable();
private List<Breakpoint> breakpointList = new ArrayList<>();
private Timer refreshTimer = null;
private static final int REFRESH_TIMEOUT = 1000;
private class Breakpoint {
public String scriptName;
public int line;
public Breakpoint(String scriptName, int line) {
this.scriptName = scriptName;
this.line = line;
}
}
public BreakpointListDialog(Window owner, SWF swf) {
super(owner);
setDefaultCloseOperation(HIDE_ON_CLOSE);
setTitle(translate("dialog.title") + " - " + swf.getShortFileName());
this.swf = swf;
table.setCellSelectionEnabled(false);
table.setRowSelectionAllowed(true);
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
int row = table.rowAtPoint(e.getPoint());
if (table.getSelectedRow() != -1 && row != -1) {
gotoButtonActionPerformed(null);
}
}
}
});
Container cnt = getContentPane();
cnt.setLayout(new BorderLayout());
cnt.add(new JScrollPane(table), BorderLayout.CENTER);
JPanel buttonsPanel = new JPanel(new FlowLayout());
JButton gotoButton = new JButton(translate("button.goto"));
gotoButton.addActionListener(this::gotoButtonActionPerformed);
buttonsPanel.add(gotoButton);
JButton removeButton = new JButton(translate("button.remove"));
removeButton.addActionListener(this::removeButtonActionPerformed);
buttonsPanel.add(removeButton);
JButton removeAllButton = new JButton(translate("button.removeAll"));
removeAllButton.addActionListener(this::removeAllButtonActionPerformed);
buttonsPanel.add(removeAllButton);
JButton closeButton = new JButton(translate("button.close"));
closeButton.addActionListener(this::closeButtonActionPerformed);
buttonsPanel.add(closeButton);
cnt.add(buttonsPanel, BorderLayout.SOUTH);
refresh();
setSize(500, 300);
//View.setWindowIcon(this);
List<Image> images = new ArrayList<>();
images.add(View.loadImage("breakpointlist16"));
setIconImages(images);
View.centerScreen(this);
}
private Breakpoint getSelected() {
int row = table.getSelectedRow();
if (row == -1) {
return null;
}
return breakpointList.get(row);
}
private void closeButtonActionPerformed(ActionEvent evt) {
setVisible(false);
}
private void removeButtonActionPerformed(ActionEvent evt) {
Breakpoint breakpoint = getSelected();
if (breakpoint == null) {
return;
}
Main.getDebugHandler().removeBreakPoint(swf, breakpoint.scriptName, breakpoint.line);
refreshMarkers();
refresh();
}
private void refreshMarkers() {
if (swf.isAS3()) {
Main.getMainFrame().getPanel().getABCPanel().decompiledTextArea.refreshMarkers();
Main.getMainFrame().getPanel().getABCPanel().detailPanel.methodTraitPanel.methodCodePanel.refreshMarkers();
} else {
Main.getMainFrame().getPanel().getActionPanel().decompiledEditor.refreshMarkers();
Main.getMainFrame().getPanel().getActionPanel().editor.refreshMarkers();
}
}
private void removeAllButtonActionPerformed(ActionEvent evt) {
Main.getDebugHandler().clearBreakPoints(swf);
refreshMarkers();
refresh();
}
private void gotoButtonActionPerformed(ActionEvent evt) {
Breakpoint breakpoint = getSelected();
if (breakpoint == null) {
return;
}
int classIndex = -1;
int traitIndex = -1;
int methodIndex = -1;
/*if (Main.getDebugHandler().getDebuggedSwf() == swf) {
int f = Main.getDebugHandler().moduleIdOf(breakpoint.scriptName);
if (f != -1) {
Integer newClassIndex = Main.getDebugHandler().moduleToClassIndex(f);
classIndex = newClassIndex == null ? -1 : newClassIndex;
Integer newMethodIndex = Main.getDebugHandler().moduleToMethodIndex(f);
methodIndex = newMethodIndex == null ? -1 : newMethodIndex;
Integer newTraitIndex = Main.getDebugHandler().moduleToTraitIndex(f);;
traitIndex = newTraitIndex == null ? -1 : newTraitIndex;
}
}*/
Pattern abcPcodePattern = Pattern.compile("^#PCODE abc:(?<abc>[0-9]+),body:(?<body>[0-9]+);.*");
Matcher m = abcPcodePattern.matcher(breakpoint.scriptName);
if (m.matches()) {
int abcIndex = Integer.parseInt(m.group("abc"));
int bodyIndex = Integer.parseInt(m.group("body"));
ABC abc = swf.getAbcList().get(abcIndex).getABC();
methodIndex = abc.bodies.get(bodyIndex).method_info;
}
Main.getMainFrame().getPanel().gotoScriptLine(swf, breakpoint.scriptName, breakpoint.line, classIndex, traitIndex, methodIndex, breakpoint.scriptName.startsWith("#PCODE"));
}
public void refresh() {
DefaultTableModel defaultTableModel = new DefaultTableModel() {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
defaultTableModel.addColumn(translate("breakpoint.scriptName"));
defaultTableModel.addColumn(translate("breakpoint.line"));
defaultTableModel.addColumn(translate("breakpoint.status"));
Map<String, Set<Integer>> breakpoints = Main.getDebugHandler().getAllBreakPoints(swf, false);
List<Breakpoint> newBreakpointList = new ArrayList<>();
for (String scriptName : breakpoints.keySet()) {
for (int line : breakpoints.get(scriptName)) {
newBreakpointList.add(new Breakpoint(scriptName, line));
String status = "unknown";
if (Main.getDebugHandler().isBreakpointInvalid(swf, scriptName, line)) {
status = "invalid";
} else if (Main.getDebugHandler().isBreakpointConfirmed(swf, scriptName, line)) {
status = "confirmed";
}
defaultTableModel.addRow(new Object[]{scriptName, line, translate("breakpoint.status." + status)});
}
}
breakpointList = newBreakpointList;
int selectedRow = table.getSelectedRow();
table.setModel(defaultTableModel);
if (selectedRow >= 0 && selectedRow < defaultTableModel.getRowCount()) {
table.setRowSelectionInterval(selectedRow, selectedRow);
}
table.getColumnModel().getColumn(1).setMaxWidth(50);
table.getColumnModel().getColumn(2).setMaxWidth(75);
}
@Override
public void setVisible(boolean b) {
if (refreshTimer != null) {
refreshTimer.cancel();
refreshTimer = null;
}
if (b) {
refreshTimer = new Timer();
refreshTimer.schedule(new TimerTask() {
@Override
public void run() {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
refresh();
}
});
}
}, REFRESH_TIMEOUT, REFRESH_TIMEOUT);
}
super.setVisible(b);
}
}

View File

@@ -95,7 +95,7 @@ public class DebugStackPanel extends JPanel {
String scriptName = (String) stackTable.getModel().getValueAt(row, 0);
int line = (int) (Integer) stackTable.getModel().getValueAt(row, 1);
Main.getMainFrame().getPanel().gotoScriptLine(Main.getMainFrame().getPanel().getCurrentSwf(),
scriptName, line, classIndices[row], traitIndices[row], methodIndices[row]);
scriptName, line, classIndices[row], traitIndices[row], methodIndices[row], Main.isDebugPCode());
Main.getDebugHandler().setDepth(row);
}
}

View File

@@ -51,6 +51,7 @@ import com.jpexs.debugger.flash.messages.out.OutPlay;
import com.jpexs.debugger.flash.messages.out.OutProcessedTag;
import com.jpexs.debugger.flash.messages.out.OutRewind;
import com.jpexs.debugger.flash.messages.out.OutSwfInfo;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.configuration.Configuration;
import com.jpexs.decompiler.graph.DottedChain;
import java.io.IOException;
@@ -60,8 +61,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
@@ -93,13 +94,13 @@ public class DebuggerHandler implements DebugConnectionListener {
private Map<Integer, Integer> moduleToMethodIndex = new HashMap<>();
private Map<String, Set<Integer>> toAddBPointMap = new HashMap<>();
private Map<SWF, Map<String, Set<Integer>>> toAddBPointMap = new WeakHashMap<>();
private Map<String, Set<Integer>> confirmedPointMap = new HashMap<>();
private Map<SWF, Map<String, Set<Integer>>> confirmedPointMap = new WeakHashMap<>();
private Map<String, Set<Integer>> invalidBreakPointMap = new HashMap<>();
private Map<SWF, Map<String, Set<Integer>>> invalidBreakPointMap = new WeakHashMap<>();
private Map<String, Set<Integer>> toRemoveBPointMap = new HashMap<>();
private Map<SWF, Map<String, Set<Integer>>> toRemoveBPointMap = new WeakHashMap<>();
private int breakIp = -1;
@@ -108,6 +109,8 @@ public class DebuggerHandler implements DebugConnectionListener {
private List<String> stackScriptNames = new ArrayList<>();
private List<Integer> stackLines = new ArrayList<>();
private SWF debuggedSwf = null;
public static class ActionScriptException extends Exception {
@@ -127,6 +130,14 @@ public class DebuggerHandler implements DebugConnectionListener {
}
}
public void setDebuggedSwf(SWF debuggedSwf) {
this.debuggedSwf = debuggedSwf;
}
public SWF getDebuggedSwf() {
return debuggedSwf;
}
public int getBreakIp() {
if (!isPaused()) {
return -1;
@@ -193,24 +204,27 @@ public class DebuggerHandler implements DebugConnectionListener {
}
}
public synchronized void removeBreakPoint(String scriptName, int line) {
if (isBreakpointInvalid(scriptName, line)) {
invalidBreakPointMap.get(scriptName).remove(line);
if (invalidBreakPointMap.get(scriptName).isEmpty()) {
invalidBreakPointMap.remove(scriptName);
public synchronized void removeBreakPoint(SWF swf, String scriptName, int line) {
if (isBreakpointInvalid(swf, scriptName, line)) {
invalidBreakPointMap.get(swf).get(scriptName).remove(line);
if (invalidBreakPointMap.get(swf).get(scriptName).isEmpty()) {
invalidBreakPointMap.get(swf).remove(scriptName);
}
return;
}
if (isBreakpointToAdd(scriptName, line)) {
toAddBPointMap.get(scriptName).remove(line);
if (toAddBPointMap.get(scriptName).isEmpty()) {
toAddBPointMap.remove(scriptName);
if (isBreakpointToAdd(swf, scriptName, line)) {
toAddBPointMap.get(swf).get(scriptName).remove(line);
if (toAddBPointMap.get(swf).get(scriptName).isEmpty()) {
toAddBPointMap.get(swf).remove(scriptName);
}
} else if (isBreakpointConfirmed(scriptName, line)) {
if (!toRemoveBPointMap.containsKey(scriptName)) {
toRemoveBPointMap.put(scriptName, new TreeSet<>());
} else if (isBreakpointConfirmed(swf, scriptName, line)) {
if (!toRemoveBPointMap.containsKey(swf)) {
toRemoveBPointMap.put(swf, new HashMap<>());
}
toRemoveBPointMap.get(scriptName).add(line);
if (!toRemoveBPointMap.get(swf).containsKey(scriptName)) {
toRemoveBPointMap.get(swf).put(scriptName, new TreeSet<>());
}
toRemoveBPointMap.get(swf).get(scriptName).add(line);
}
try {
sendBreakPoints();
@@ -230,86 +244,114 @@ public class DebuggerHandler implements DebugConnectionListener {
}
}
public synchronized Set<Integer> getBreakPoints(String scriptName, boolean onlyValid) {
Set<Integer> lines = new TreeSet<>();
if (confirmedPointMap.containsKey(scriptName)) {
lines.addAll(confirmedPointMap.get(scriptName));
public synchronized Set<Integer> getBreakPoints(SWF swf, String scriptName, boolean onlyValid) {
Set<Integer> lines = new TreeSet<>();
if (confirmedPointMap.containsKey(swf) && confirmedPointMap.get(swf).containsKey(scriptName)) {
lines.addAll(confirmedPointMap.get(swf).get(scriptName));
}
if (toAddBPointMap.containsKey(scriptName)) {
lines.addAll(toAddBPointMap.get(scriptName));
if (toAddBPointMap.containsKey(swf) && toAddBPointMap.get(swf).containsKey(scriptName)) {
lines.addAll(toAddBPointMap.get(swf).get(scriptName));
}
if (!onlyValid && invalidBreakPointMap.containsKey(scriptName)) {
lines.addAll(invalidBreakPointMap.get(scriptName));
if (!onlyValid && invalidBreakPointMap.containsKey(swf) && invalidBreakPointMap.get(swf).containsKey(scriptName)) {
lines.addAll(invalidBreakPointMap.get(swf).get(scriptName));
}
return lines;
}
public synchronized void clearBreakPoints() {
for (String scriptName : confirmedPointMap.keySet()) {
if (!toAddBPointMap.containsKey(scriptName)) {
toAddBPointMap.put(scriptName, new TreeSet<>());
public synchronized void clearBreakPoints(SWF swf) {
Map<String, Set<Integer>> breakpoints = getAllBreakPoints(swf, false);
for (String scriptName : breakpoints.keySet()) {
for (int line : breakpoints.get(scriptName)) {
removeBreakPoint(swf, scriptName, line);
}
toAddBPointMap.get(scriptName).addAll(confirmedPointMap.get(scriptName));
}
for (String scriptName : invalidBreakPointMap.keySet()) {
if (!toAddBPointMap.containsKey(scriptName)) {
toAddBPointMap.put(scriptName, new TreeSet<>());
}
toAddBPointMap.get(scriptName).addAll(invalidBreakPointMap.get(scriptName));
}
confirmedPointMap.clear();
invalidBreakPointMap.clear();
}
public synchronized Map<String, Set<Integer>> getAllBreakPoints(boolean validOnly) {
Map<String, Set<Integer>> ret = new HashMap<>();
for (String scriptName : confirmedPointMap.keySet()) {
Set<Integer> lines = new TreeSet<>();
lines.addAll(confirmedPointMap.get(scriptName));
ret.put(scriptName, lines);
}
for (String scriptName : toAddBPointMap.keySet()) {
if (!ret.containsKey(scriptName)) {
ret.put(scriptName, new TreeSet<>());
public synchronized void makeBreakPointsUnconfirmed(SWF swf) {
if (confirmedPointMap.containsKey(swf)) {
for (String scriptName : confirmedPointMap.get(swf).keySet()) {
if (!toAddBPointMap.containsKey(swf)) {
toAddBPointMap.put(swf, new HashMap<>());
}
if (!toAddBPointMap.get(swf).containsKey(scriptName)) {
toAddBPointMap.get(swf).put(scriptName, new TreeSet<>());
}
toAddBPointMap.get(swf).get(scriptName).addAll(confirmedPointMap.get(swf).get(scriptName));
}
ret.get(scriptName).addAll(toAddBPointMap.get(scriptName));
confirmedPointMap.get(swf).clear();
}
if (!validOnly) {
for (String scriptName : invalidBreakPointMap.keySet()) {
if (invalidBreakPointMap.containsKey(swf)) {
for (String scriptName : invalidBreakPointMap.get(swf).keySet()) {
if (!toAddBPointMap.containsKey(swf)) {
toAddBPointMap.put(swf, new HashMap<>());
}
if (!toAddBPointMap.get(swf).containsKey(scriptName)) {
toAddBPointMap.get(swf).put(scriptName, new TreeSet<>());
}
toAddBPointMap.get(swf).get(scriptName).addAll(invalidBreakPointMap.get(swf).get(scriptName));
}
invalidBreakPointMap.get(swf).clear();
}
}
public synchronized Map<String, Set<Integer>> getAllBreakPoints(SWF swf, boolean validOnly) {
Map<String, Set<Integer>> ret = new HashMap<>();
if (confirmedPointMap.containsKey(swf)) {
for (String scriptName : confirmedPointMap.get(swf).keySet()) {
Set<Integer> lines = new TreeSet<>();
lines.addAll(confirmedPointMap.get(swf).get(scriptName));
ret.put(scriptName, lines);
}
}
if (toAddBPointMap.containsKey(swf)) {
for (String scriptName : toAddBPointMap.get(swf).keySet()) {
if (!ret.containsKey(scriptName)) {
ret.put(scriptName, new TreeSet<>());
}
ret.get(scriptName).addAll(invalidBreakPointMap.get(scriptName));
ret.get(scriptName).addAll(toAddBPointMap.get(swf).get(scriptName));
}
}
if (!validOnly) {
if (invalidBreakPointMap.containsKey(swf)) {
for (String scriptName : invalidBreakPointMap.get(swf).keySet()) {
if (!ret.containsKey(scriptName)) {
ret.put(scriptName, new TreeSet<>());
}
ret.get(scriptName).addAll(invalidBreakPointMap.get(swf).get(scriptName));
}
}
}
return ret;
}
public boolean addBreakPoint(String scriptName, int line) {
public boolean addBreakPoint(SWF swf, String scriptName, int line) {
synchronized (this) {
Logger.getLogger(DebuggerHandler.class
.getName()).log(Level.FINE, "adding bp {0}:{1}", new Object[]{scriptName, line});
if (isBreakpointToRemove(scriptName, line)) {
toRemoveBPointMap.get(scriptName).remove(line);
if (toRemoveBPointMap.get(scriptName).isEmpty()) {
toRemoveBPointMap.remove(scriptName);
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "adding bp {0}:{1}", new Object[]{scriptName, line});
if (isBreakpointToRemove(swf, scriptName, line)) {
toRemoveBPointMap.get(swf).get(scriptName).remove(line);
if (toRemoveBPointMap.get(swf).get(scriptName).isEmpty()) {
toRemoveBPointMap.get(swf).remove(scriptName);
}
}
if (isBreakpointConfirmed(scriptName, line)) {
if (isBreakpointConfirmed(swf, scriptName, line)) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "bp {0}:{1} already confirmed", new Object[]{scriptName, line});
return true;
}
if (isBreakpointInvalid(scriptName, line)) {
if (isBreakpointInvalid(swf, scriptName, line)) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "bp {0}:{1} already invalid", new Object[]{scriptName, line});
return false;
}
if (!toAddBPointMap.containsKey(scriptName)) {
toAddBPointMap.put(scriptName, new TreeSet<>());
if (!toAddBPointMap.containsKey(swf)) {
toAddBPointMap.put(swf, new HashMap<>());
}
toAddBPointMap.get(scriptName).add(line);
if (!toAddBPointMap.get(swf).containsKey(scriptName)) {
toAddBPointMap.get(swf).put(scriptName, new TreeSet<>());
}
toAddBPointMap.get(swf).get(scriptName).add(line);
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "bp {0}:{1} added to todo", new Object[]{scriptName, line});
}
try {
@@ -321,27 +363,30 @@ public class DebuggerHandler implements DebugConnectionListener {
return true;
}
public synchronized boolean isBreakpointConfirmed(String scriptName, int line) {
return confirmedPointMap.containsKey(scriptName) && confirmedPointMap.get(scriptName).contains(line);
public synchronized boolean isBreakpointConfirmed(SWF swf, String scriptName, int line) {
return confirmedPointMap.containsKey(swf) && confirmedPointMap.get(swf).containsKey(scriptName) && confirmedPointMap.get(swf).get(scriptName).contains(line);
}
public synchronized boolean isBreakpointToAdd(String scriptName, int line) {
return toAddBPointMap.containsKey(scriptName) && toAddBPointMap.get(scriptName).contains(line);
public synchronized boolean isBreakpointToAdd(SWF swf, String scriptName, int line) {
return toAddBPointMap.containsKey(swf) && toAddBPointMap.get(swf).containsKey(scriptName) && toAddBPointMap.get(swf).get(scriptName).contains(line);
}
public synchronized boolean isBreakpointToRemove(String scriptName, int line) {
return toRemoveBPointMap.containsKey(scriptName) && toRemoveBPointMap.get(scriptName).contains(line);
public synchronized boolean isBreakpointToRemove(SWF swf, String scriptName, int line) {
return toRemoveBPointMap.containsKey(swf) && toRemoveBPointMap.get(swf).containsKey(scriptName) && toRemoveBPointMap.get(swf).get(scriptName).contains(line);
}
public synchronized boolean isBreakpointInvalid(String scriptName, int line) {
return invalidBreakPointMap.containsKey(scriptName) && invalidBreakPointMap.get(scriptName).contains(line);
public synchronized boolean isBreakpointInvalid(SWF swf, String scriptName, int line) {
return invalidBreakPointMap.containsKey(swf) && invalidBreakPointMap.get(swf).containsKey(scriptName) && invalidBreakPointMap.get(swf).get(scriptName).contains(line);
}
private synchronized void markBreakPointInvalid(String scriptName, int line) {
if (!invalidBreakPointMap.containsKey(scriptName)) {
invalidBreakPointMap.put(scriptName, new TreeSet<>());
private synchronized void markBreakPointInvalid(SWF swf, String scriptName, int line) {
if (!invalidBreakPointMap.containsKey(swf)) {
invalidBreakPointMap.put(swf, new HashMap<>());
}
invalidBreakPointMap.get(scriptName).add(line);
if (!invalidBreakPointMap.get(swf).containsKey(scriptName)) {
invalidBreakPointMap.get(swf).put(scriptName, new TreeSet<>());
}
invalidBreakPointMap.get(swf).get(scriptName).add(line);
}
private InFrame frame;
@@ -523,20 +568,31 @@ public class DebuggerHandler implements DebugConnectionListener {
}
commands = null;
synchronized (this) {
for (String scriptName : confirmedPointMap.keySet()) {
if (!toAddBPointMap.containsKey(scriptName)) {
toAddBPointMap.put(scriptName, new TreeSet<>());
if (confirmedPointMap.containsKey(debuggedSwf)) {
for (String scriptName : confirmedPointMap.get(debuggedSwf).keySet()) {
if (!toAddBPointMap.containsKey(debuggedSwf)) {
toAddBPointMap.put(debuggedSwf, new HashMap<>());
}
if (!toAddBPointMap.get(debuggedSwf).containsKey(scriptName)) {
toAddBPointMap.get(debuggedSwf).put(scriptName, new TreeSet<>());
}
toAddBPointMap.get(debuggedSwf).get(scriptName).addAll(confirmedPointMap.get(debuggedSwf).get(scriptName));
}
toAddBPointMap.get(scriptName).addAll(confirmedPointMap.get(scriptName));
confirmedPointMap.get(debuggedSwf).clear();
}
confirmedPointMap.clear();
for (String scriptName : invalidBreakPointMap.keySet()) {
if (!toAddBPointMap.containsKey(scriptName)) {
toAddBPointMap.put(scriptName, new TreeSet<>());
if (invalidBreakPointMap.containsKey(debuggedSwf)) {
for (String scriptName : invalidBreakPointMap.get(debuggedSwf).keySet()) {
if (!toAddBPointMap.containsKey(debuggedSwf)) {
toAddBPointMap.put(debuggedSwf, new HashMap<>());
}
if (!toAddBPointMap.get(debuggedSwf).containsKey(scriptName)) {
toAddBPointMap.get(debuggedSwf).put(scriptName, new TreeSet<>());
}
toAddBPointMap.get(debuggedSwf).get(scriptName).addAll(invalidBreakPointMap.get(debuggedSwf).get(scriptName));
}
toAddBPointMap.get(scriptName).addAll(invalidBreakPointMap.get(scriptName));
}
invalidBreakPointMap.clear();
invalidBreakPointMap.get(debuggedSwf).clear();
}
}
for (ConnectionListener l : clisteners) {
l.disconnected();
@@ -552,17 +608,7 @@ public class DebuggerHandler implements DebugConnectionListener {
throw new IOException("Not connected");
}
return commands;
}
private static void enlog(Class<?> cls) {
Level level = Level.FINEST;
Logger mylog = Logger.getLogger(cls.getName());
mylog.setLevel(level);
ConsoleHandler ch = new ConsoleHandler();
ch.setLevel(level);
mylog.addHandler(ch);
}
}
@Override
public void failedListen(IOException ex) {
@@ -581,7 +627,7 @@ public class DebuggerHandler implements DebugConnectionListener {
@Override
public void connected(DebuggerConnection con) {
clearBreakPoints();
makeBreakPointsUnconfirmed(debuggedSwf);
Main.startWork(AppStrings.translate("work.debugging"), null);
@@ -655,6 +701,8 @@ public class DebuggerHandler implements DebugConnectionListener {
name = name.replaceAll("\\[(invalid_utf8=[0-9]+)\\]", "{$1}");
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINE, "Received script added - index {0} name: {1}", new Object[]{file, name});
Matcher m;
if ((m = patAS3.matcher(name)).matches()) {
String clsNameWithSuffix = m.group(3).replace("{{semicolon}}", ";");
@@ -734,16 +782,21 @@ public class DebuggerHandler implements DebugConnectionListener {
synchronized (this) {
for (int i = 0; i < isb.files.size(); i++) {
String sname = moduleNames.get(isb.files.get(i));
if (!confirmedPointMap.containsKey(sname)) {
confirmedPointMap.put(sname, new TreeSet<>());
if (!confirmedPointMap.containsKey(debuggedSwf)) {
confirmedPointMap.put(debuggedSwf, new HashMap<>());
}
if (toAddBPointMap.containsKey(sname)) {
toAddBPointMap.get(sname).remove(isb.lines.get(i));
if (toAddBPointMap.get(sname).isEmpty()) {
toAddBPointMap.remove(sname);
if (!confirmedPointMap.get(debuggedSwf).containsKey(sname)) {
confirmedPointMap.get(debuggedSwf).put(sname, new TreeSet<>());
}
if (toAddBPointMap.containsKey(debuggedSwf)) {
if (toAddBPointMap.get(debuggedSwf).containsKey(sname)) {
toAddBPointMap.get(debuggedSwf).get(sname).remove(isb.lines.get(i));
if (toAddBPointMap.get(debuggedSwf).get(sname).isEmpty()) {
toAddBPointMap.get(debuggedSwf).remove(sname);
}
}
}
confirmedPointMap.get(sname).add(isb.lines.get(i));
confirmedPointMap.get(debuggedSwf).get(sname).add(isb.lines.get(i));
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} submitted successfully", new Object[]{sname, isb.lines.get(i)});
}
}
@@ -880,46 +933,53 @@ public class DebuggerHandler implements DebugConnectionListener {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINEST, "not sending bps, not connected");
return;
}
synchronized (this) {
for (String scriptName : toRemoveBPointMap.keySet()) {
int file = moduleIdOf(scriptName);
if (file > -1) {
for (int line : toRemoveBPointMap.get(scriptName)) {
if (isBreakpointConfirmed(scriptName, line)) {
commands.removeBreakPoint(file, line);
confirmedPointMap.get(scriptName).remove(line);
if (confirmedPointMap.get(scriptName).isEmpty()) {
confirmedPointMap.remove(scriptName);
synchronized (this) {
if (toRemoveBPointMap.containsKey(debuggedSwf)) {
for (String scriptName : toRemoveBPointMap.get(debuggedSwf).keySet()) {
int file = moduleIdOf(scriptName);
if (file > -1) {
for (int line : toRemoveBPointMap.get(debuggedSwf).get(scriptName)) {
if (isBreakpointConfirmed(debuggedSwf, scriptName, line)) {
commands.removeBreakPoint(file, line);
confirmedPointMap.get(debuggedSwf).get(scriptName).remove(line);
if (confirmedPointMap.get(debuggedSwf).get(scriptName).isEmpty()) {
confirmedPointMap.get(debuggedSwf).remove(scriptName);
}
}
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} removed", new Object[]{scriptName, line});
}
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} removed", new Object[]{scriptName, line});
}
}
toRemoveBPointMap.clear();
}
toRemoveBPointMap.clear();
for (String scriptName : toAddBPointMap.keySet()) {
int file = moduleIdOf(scriptName);
if (file > -1) {
for (int line : toAddBPointMap.get(scriptName)) {
if (commands.addBreakPoint(file, line)) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} submitted successfully", new Object[]{scriptName, line});
if (!confirmedPointMap.containsKey(scriptName)) {
confirmedPointMap.put(scriptName, new TreeSet<>());
if (toAddBPointMap.containsKey(debuggedSwf)) {
for (String scriptName : toAddBPointMap.get(debuggedSwf).keySet()) {
int file = moduleIdOf(scriptName);
if (file > -1) {
for (int line : toAddBPointMap.get(debuggedSwf).get(scriptName)) {
if (commands.addBreakPoint(file, line)) {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} submitted successfully", new Object[]{scriptName, line});
if (!confirmedPointMap.containsKey(debuggedSwf)) {
confirmedPointMap.put(debuggedSwf, new HashMap<>());
}
if (!confirmedPointMap.get(debuggedSwf).containsKey(scriptName)) {
confirmedPointMap.get(debuggedSwf).put(scriptName, new TreeSet<>());
}
confirmedPointMap.get(debuggedSwf).get(scriptName).add(line);
} else {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} unable to submit", new Object[]{scriptName, line});
markBreakPointInvalid(debuggedSwf, scriptName, line);
}
confirmedPointMap.get(scriptName).add(line);
} else {
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.INFO, "Breakpoint {0}:{1} unable to submit", new Object[]{scriptName, line});
markBreakPointInvalid(scriptName, line);
}
} else {
for (int line : toAddBPointMap.get(debuggedSwf).get(scriptName)) {
markBreakPointInvalid(debuggedSwf, scriptName, line);
}
}
} else {
for (int line : toAddBPointMap.get(scriptName)) {
markBreakPointInvalid(scriptName, line);
}
}
toAddBPointMap.clear();
}
toAddBPointMap.clear();
}
Logger.getLogger(DebuggerHandler.class.getName()).log(Level.FINEST, "sending bps finished");

View File

@@ -647,6 +647,7 @@ public class Main {
if (swf == null) {
return;
}
debugHandler.setDebuggedSwf(swf);
File tempFile = null;
try {
@@ -726,33 +727,39 @@ public class Main {
}
public static synchronized boolean isBreakPointValid(String scriptName, int line) {
return !getDebugHandler().isBreakpointInvalid(scriptName, line);
SWF swf = getMainFrame().getPanel().getCurrentSwf();
return !getDebugHandler().isBreakpointInvalid(swf, scriptName, line);
}
public static synchronized void addBreakPoint(String scriptName, int line) {
getDebugHandler().addBreakPoint(scriptName, line);
SWF swf = getMainFrame().getPanel().getCurrentSwf();
getDebugHandler().addBreakPoint(swf, scriptName, line);
}
public static synchronized void removeBreakPoint(String scriptName, int line) {
getDebugHandler().removeBreakPoint(scriptName, line);
SWF swf = getMainFrame().getPanel().getCurrentSwf();
getDebugHandler().removeBreakPoint(swf, scriptName, line);
}
public static synchronized boolean toggleBreakPoint(String scriptName, int line) {
if (getDebugHandler().isBreakpointToAdd(scriptName, line) || getDebugHandler().isBreakpointConfirmed(scriptName, line) || getDebugHandler().isBreakpointInvalid(scriptName, line)) {
getDebugHandler().removeBreakPoint(scriptName, line);
SWF swf = getMainFrame().getPanel().getCurrentSwf();
if (getDebugHandler().isBreakpointToAdd(swf, scriptName, line) || getDebugHandler().isBreakpointConfirmed(swf, scriptName, line) || getDebugHandler().isBreakpointInvalid(swf, scriptName, line)) {
getDebugHandler().removeBreakPoint(swf, scriptName, line);
return false;
} else {
getDebugHandler().addBreakPoint(scriptName, line);
getDebugHandler().addBreakPoint(swf, scriptName, line);
return true;
}
}
public static synchronized Map<String, Set<Integer>> getPackBreakPoints(boolean validOnly) {
return getDebugHandler().getAllBreakPoints(validOnly);
SWF swf = getMainFrame().getPanel().getCurrentSwf();
return getDebugHandler().getAllBreakPoints(swf, validOnly);
}
public static synchronized Set<Integer> getScriptBreakPoints(String pack, boolean onlyValid) {
return getDebugHandler().getBreakPoints(pack, onlyValid);
SWF swf = getMainFrame().getPanel().getCurrentSwf();
return getDebugHandler().getBreakPoints(swf, pack, onlyValid);
}
public static DebuggerHandler getDebugHandler() {
@@ -1640,15 +1647,8 @@ public class Main {
SWF swf = (SWF) openable;
SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle());
if (conf != null) {
String abcDependencies = conf.getCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, "");
if (!abcDependencies.isEmpty()) {
String[] parts = (abcDependencies + Configuration.ABC_DEPS_SEPARATOR).split(Pattern.quote(Configuration.ABC_DEPS_SEPARATOR));
List<String> preselectedNames = new ArrayList<>();
for (String part : parts) {
if (!part.isEmpty()) {
preselectedNames.add(part);
}
}
List<String> preselectedNames = conf.getCustomDataAsList(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES);
if (!preselectedNames.isEmpty()) {
swf.setAbcIndexDependencies(namesToSwfs(preselectedNames));
if (mainFrame != null && mainFrame.getPanel() != null && mainFrame.getPanel().getABCPanel() != null) {
mainFrame.getPanel().getABCPanel().updateLinksLabel();
@@ -1687,6 +1687,14 @@ public class Main {
if (swfCustomConf != null) {
resourcesPathStr = swfCustomConf.getCustomData(CustomConfigurationKeys.KEY_LAST_SELECTED_PATH_RESOURCES, resourcesPathStr);
tagListPathStr = swfCustomConf.getCustomData(CustomConfigurationKeys.KEY_LAST_SELECTED_PATH_TAGLIST, null);
List<String> breakpointsList = swfCustomConf.getCustomDataAsList(CustomConfigurationKeys.KEY_BREAKPOINTS);
for (String breakpoint : breakpointsList) {
if (breakpoint.matches("^.*:[0-9]+$")) {
int line = Integer.parseInt(breakpoint.substring(breakpoint.lastIndexOf(":") + 1));
String scriptName = breakpoint.substring(0, breakpoint.lastIndexOf(":"));
getDebugHandler().addBreakPoint(fswf, scriptName, line);
}
}
}
if (isInited()) {
@@ -2457,7 +2465,7 @@ public class Main {
View.execInEventDispatch(new Runnable() {
@Override
public void run() {
mainFrame.getPanel().gotoScriptLine(getMainFrame().getPanel().getCurrentSwf(), scriptName, line, classIndex, traitIndex, methodIndex);
mainFrame.getPanel().gotoScriptLine(getMainFrame().getPanel().getCurrentSwf(), scriptName, line, classIndex, traitIndex, methodIndex, Main.isDebugPCode());
}
});
}
@@ -3315,18 +3323,16 @@ public class Main {
SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle());
List<SWF> dependencies = new ArrayList<>();
if (conf != null) {
String abcDependencies = conf.getCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, "");
if (!abcDependencies.isEmpty()) {
String[] parts = (abcDependencies + Configuration.ABC_DEPS_SEPARATOR).split(Pattern.quote(Configuration.ABC_DEPS_SEPARATOR));
List<String> preselectedNames = new ArrayList<>();
for (String part : parts) {
if (!part.isEmpty()) {
preselectedNames.add(part);
}
}
List<String> preselectedNames = conf.getCustomDataAsList(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES);
if (!preselectedNames.isEmpty()) {
dependencies = Main.namesToSwfs(preselectedNames);
}
}
return dependencies;
}
public static void showBreakpointsList() {
SWF swf = getMainFrame().getPanel().getCurrentSwf();
getMainFrame().getPanel().showBreakpointlistDialog(swf);
}
}

View File

@@ -453,6 +453,9 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
public ScrollPosStorage scrollPosStorage;
private Map<Openable, ABCExplorerDialog> abcExplorerDialogs = new WeakHashMap<>();
private Map<SWF, BreakpointListDialog> breakpointsListDialogs = new WeakHashMap<>();
public void savePins() {
pinsPanel.save();
@@ -1685,7 +1688,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
if (abcExportDialog != null) {
abcExportDialog.setVisible(false);
abcExplorerDialogs.remove(openable);
}
}
}
}
for (Openable openable : openableList) {
@@ -1697,11 +1700,17 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
for (SWF swf : swfsToClose) {
swf.clearTagSwfs();
saveBreakpoints(swf);
ABCExplorerDialog abcExportDialog = abcExplorerDialogs.get(swf);
if (abcExportDialog != null) {
abcExportDialog.setVisible(false);
abcExplorerDialogs.remove(swf);
}
BreakpointListDialog breakpointsListDialog = breakpointsListDialogs.get(swf);
if (breakpointsListDialog != null) {
breakpointsListDialog.setVisible(false);
breakpointsListDialogs.remove(swf);
}
if (!onExit) {
SwfSpecificCustomConfiguration cc = Configuration.getSwfSpecificCustomConfiguration(swf.getShortPathTitle());
if (cc != null) {
@@ -1771,11 +1780,19 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
if (cc != null) {
cc.setCustomData(CustomConfigurationKeys.KEY_LOADED_IMPORT_ASSETS, "");
}
saveBreakpoints(swf);
ABCExplorerDialog abcExportDialog = abcExplorerDialogs.get(swf);
if (abcExportDialog != null) {
abcExportDialog.setVisible(false);
}
BreakpointListDialog breakpointsListDialog = breakpointsListDialogs.get(swf);
if (breakpointsListDialog != null) {
breakpointsListDialog.setVisible(false);
breakpointsListDialogs.remove(swf);
}
}
openables.remove(openableList);
@@ -2596,7 +2613,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
gotoScriptName(swf, scriptName);
}
public void gotoScriptLine(SWF swf, String scriptName, int line, int classIndex, int traitIndex, int methodIndex) {
public void gotoScriptLine(SWF swf, String scriptName, int line, int classIndex, int traitIndex, int methodIndex, boolean pcode) {
View.checkAccess();
if (abcPanel != null && swf.isAS3()) {
@@ -2607,7 +2624,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
if (Main.isDebugPCode()) {
if (pcode) {
if (classIndex != -1) {
if (abcPanel.decompiledTextArea.getClassIndex() != classIndex) {
abcPanel.decompiledTextArea.setClassIndex(classIndex);
@@ -2638,7 +2655,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
View.execInEventDispatchLater(new Runnable() {
@Override
public void run() {
if (Main.isDebugPCode()) {
if (pcode) {
actionPanel.editor.gotoLine(line);
} else {
actionPanel.decompiledEditor.gotoLine(line);
@@ -5613,10 +5630,25 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
showCard(CARDEMPTYPANEL);
}
public void reload(boolean forceReload) {
reload(forceReload, true);
private void saveBreakpoints(Openable openable) {
if (openable instanceof SWF) {
SwfSpecificCustomConfiguration swfCustomConf = Configuration.getOrCreateSwfSpecificCustomConfiguration(openable.getShortPathTitle());
SWF swf = (SWF) openable;
Map<String, Set<Integer>> breakpoints = Main.getDebugHandler().getAllBreakPoints(swf, false);
List<String> breakpointList = new ArrayList<>();
for (String scriptName : breakpoints.keySet()) {
for (int line : breakpoints.get(scriptName)) {
breakpointList.add(scriptName + ":" + line);
}
}
swfCustomConf.setCustomData(CustomConfigurationKeys.KEY_BREAKPOINTS, breakpointList);
}
}
public void reload(boolean forceReload) {
reload(forceReload, true);
}
public void reload(boolean forceReload, boolean scrollToVisible) {
View.checkAccess();
@@ -5656,6 +5688,7 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
SwfSpecificCustomConfiguration swfCustomConf = Configuration.getOrCreateSwfSpecificCustomConfiguration(openable.getShortPathTitle());
swfCustomConf.setCustomData(CustomConfigurationKeys.KEY_LAST_SELECTED_PATH_RESOURCES, tagTree.getSelectionPathString());
swfCustomConf.setCustomData(CustomConfigurationKeys.KEY_LAST_SELECTED_PATH_TAGLIST, tagListTree.getSelectionPathString());
saveBreakpoints(openable);
}
}
@@ -6501,6 +6534,23 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se
}
return dialog;
}
public BreakpointListDialog showBreakpointlistDialog(SWF swf) {
BreakpointListDialog dialog = breakpointsListDialogs.get(swf);
if (dialog != null) {
dialog.refresh();
if (!dialog.isVisible()) {
dialog.setVisible(true);
} else {
dialog.toFront();
}
} else {
dialog = new BreakpointListDialog(mainFrame.getWindow(), swf);
breakpointsListDialogs.put(swf, dialog);
dialog.setVisible(true);
}
return dialog;
}
public boolean fontEmbed(TreeItem item, boolean create) {
return previewPanel.getFontPanel().fontEmbed(item, create);

View File

@@ -51,6 +51,7 @@ import com.jpexs.decompiler.flash.configuration.SwfSpecificCustomConfiguration;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.gui.AppDialog;
import com.jpexs.decompiler.flash.gui.AppStrings;
import com.jpexs.decompiler.flash.gui.BreakpointListDialog;
import com.jpexs.decompiler.flash.gui.DebugPanel;
import com.jpexs.decompiler.flash.gui.DebuggerHandler;
import com.jpexs.decompiler.flash.gui.FasterScrollPane;
@@ -962,6 +963,12 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
iconsPanel.add(deobfuscateButton);
iconsPanel.add(deobfuscateOptionsButton);
JButton breakpointListButton = new JButton(View.getIcon("breakpointlist16"));
breakpointListButton.setMargin(new Insets(5, 5, 5, 5));
breakpointListButton.addActionListener(this::breakPointListButtonActionPerformed);
breakpointListButton.setToolTipText(AppStrings.translate("button.breakpointList"));
iconsPanel.add(breakpointListButton);
scriptNameLabel = new JLabel("-");
@@ -1891,6 +1898,10 @@ public class ABCPanel extends JPanel implements ItemListener, SearchListener<Scr
}
}
private void breakPointListButtonActionPerformed(ActionEvent evt) {
Main.showBreakpointsList();
}
private void addTraitButtonActionPerformed(ActionEvent evt) {
int class_index = decompiledTextArea.getClassIndex();

View File

@@ -118,15 +118,8 @@ public class LinkDialog extends JDialog {
List<SWF> selectedSWFs = new ArrayList<>();
if (conf != null) {
String abcDependencies = conf.getCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, "");
if (!abcDependencies.isEmpty()) {
String[] parts = (abcDependencies + Configuration.ABC_DEPS_SEPARATOR).split(Pattern.quote(Configuration.ABC_DEPS_SEPARATOR));
List<String> preselectedNames = new ArrayList<>();
for (String part : parts) {
if (!part.isEmpty()) {
preselectedNames.add(part);
}
}
List<String> preselectedNames = conf.getCustomDataAsList(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES);
if (!preselectedNames.isEmpty()) {
selectedSWFs = Main.namesToSwfs(preselectedNames);
}
}
@@ -142,8 +135,8 @@ public class LinkDialog extends JDialog {
public void save(SWF swf, boolean force) {
Map<String, SWF> map = getSelectedSwfs();
SwfSpecificCustomConfiguration conf = Configuration.getOrCreateSwfSpecificCustomConfiguration(swf.getShortPathTitle());
String oldValue = conf.getCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, "");
String newValue = String.join(Configuration.ABC_DEPS_SEPARATOR, map.keySet());
List<String> oldValue = conf.getCustomDataAsList(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES);
List<String> newValue = new ArrayList<>(map.keySet());
conf.setCustomData(CustomConfigurationKeys.KEY_ABC_DEPENDENCIES, newValue);
List<SWF> swfs = new ArrayList<>(map.values());
if (!Objects.equals(oldValue, newValue) || force) {

View File

@@ -559,7 +559,7 @@ public class ActionPanel extends JPanel implements SearchListener<ScriptSearchRe
return null;
}
@Override
protected void done() {
View.execInEventDispatch(() -> {
@@ -934,6 +934,12 @@ public class ActionPanel extends JPanel implements SearchListener<ScriptSearchRe
iconsPanel.add(deobfuscateButton);
iconsPanel.add(deobfuscateOptionsButton);
JButton breakpointListButton = new JButton(View.getIcon("breakpointlist16"));
breakpointListButton.setMargin(new Insets(5, 5, 5, 5));
breakpointListButton.addActionListener(this::breakPointListButtonActionPerformed);
breakpointListButton.setToolTipText(AppStrings.translate("button.breakpointList"));
iconsPanel.add(breakpointListButton);
JPanel panelWithToolbar = new JPanel(new BorderLayout());
panelWithToolbar.add(iconsPanel, BorderLayout.NORTH);
@@ -1073,6 +1079,10 @@ public class ActionPanel extends JPanel implements SearchListener<ScriptSearchRe
Configuration.deobfuscateAs12RemoveInvalidNamesAssignments.set(menuItem.isSelected());
mainPanel.autoDeobfuscateChanged();
}
private void breakPointListButtonActionPerformed(ActionEvent evt) {
Main.showBreakpointsList();
}
private void editorTextChanged() {
setModified(true);

Binary file not shown.

After

Width:  |  Height:  |  Size: 488 B

View File

@@ -0,0 +1,27 @@
# Copyright (C) 2023 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/>.
dialog.title = List of breakpoints
button.goto = Go to
button.remove = Remove
button.removeAll = Remove all
button.close = Close
breakpoint.scriptName = Script name
breakpoint.line = Line
breakpoint.status = Status
breakpoint.status.invalid = invalid
breakpoint.status.confirmed = confirmed
breakpoint.status.unknown = unknown

View File

@@ -0,0 +1,27 @@
# Copyright (C) 2023 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/>.
dialog.title = Seznam breakpoint\u016f
button.goto = P\u0159ej\u00edt na
button.remove = Odebrat
button.removeAll = Odebrat v\u0161e
button.close = Zav\u0159\u00edt
breakpoint.scriptName = N\u00e1zev skriptu
breakpoint.line = \u0158\u00e1dek
breakpoint.status = Stav
breakpoint.status.invalid = neplatn\u00fd
breakpoint.status.confirmed = potvrzen\u00fd
breakpoint.status.unknown = nezn\u00e1m\u00fd

View File

@@ -1248,4 +1248,6 @@ binarydata.dataInside.packer = It looks like this binary data is packed with %pa
error.wrong.packer = %item%\r\nCannot unpack binary data with %packer%.\r\nThe data is probably not packed with this packer.
contextmenu.copyTagToReplaceByClass = Copy tag to (replace by class name)
contextmenu.copyTagToReplaceByExportName = Copy tag to (replace by export name)
contextmenu.copyTagToReplaceByExportName = Copy tag to (replace by export name)
button.breakpointList = Show breakpoint list

View File

@@ -1223,4 +1223,6 @@ binarydata.dataInside.packer = Vypad\u00e1 to, \u017ee tato bin\u00e1rn\u00ed da
error.wrong.packer = %item%\r\nNelze rozbalit bin\u00e1rn\u00ed data pomoc\u00ed %packer%.\r\nTato data pravd\u011bpodobn\u011b nebyla zabalena t\u00edmto packerem.
contextmenu.copyTagToReplaceByClass = Kop\u00edrovat tag do (nahradit podle n\u00e1zvu t\u0159\u00eddy)
contextmenu.copyTagToReplaceByExportName = Kop\u00edrovat tag do (nahradit podle exportovan\u00e9ho n\u00e1zvu)
contextmenu.copyTagToReplaceByExportName = Kop\u00edrovat tag do (nahradit podle exportovan\u00e9ho n\u00e1zvu)
button.breakpointList = Zobrazit seznam breakpoint\u016f