diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index a624ef97f..3b1d201c1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -311,7 +311,7 @@ public final class SWF implements SWFContainerItem, Timelined { return jtt; } - + public void fixCharactersOrder(boolean checkAll) { Set addedCharacterIds = new HashSet<>(); Set movedTags = new HashSet<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java index ea0796e4a..a174c823c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/TextExporter.java @@ -86,7 +86,7 @@ public class TextExporter { if (settings.singleFile) { String fileName = Configuration.overrideTextExportFileName.get(); - if (fileName != null) { + if (fileName != null && !fileName.isEmpty()) { String swfName = Path.getFileNameWithoutExtension(new File(tags.get(0).getSwf().getShortFileName())); fileName = fileName.replace("{fileName}", swfName); } else { @@ -104,7 +104,10 @@ public class TextExporter { if (settings.mode == TextExportMode.FORMATTED) { fos.write(Utf8Helper.getBytes(textTag.getFormattedText())); } else { - fos.write(Utf8Helper.getBytes(textTag.getText(Configuration.textExportSingleFileRecordSeparator.get()))); + String separator = Configuration.textExportSingleFileRecordSeparator.get(); + separator = Helper.newLine + separator + Helper.newLine; + List texts = textTag.getTexts(); + fos.write(Utf8Helper.getBytes(String.join(separator, texts))); } fos.write(Utf8Helper.getBytes(Helper.newLine + Configuration.textExportSingleFileSeparator.get() + Helper.newLine)); } @@ -125,7 +128,10 @@ public class TextExporter { if (settings.mode == TextExportMode.FORMATTED) { fos.write(Utf8Helper.getBytes(textTag.getFormattedText())); } else { - fos.write(Utf8Helper.getBytes(textTag.getText(Configuration.textExportSingleFileRecordSeparator.get()))); + String separator = Configuration.textExportSingleFileRecordSeparator.get(); + separator = Helper.newLine + separator + Helper.newLine; + List texts = textTag.getTexts(); + fos.write(Utf8Helper.getBytes(String.join(separator, texts))); } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java index f6fac9c0b..f2497e229 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineEditTextTag.java @@ -56,6 +56,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.StringReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -191,7 +192,7 @@ public class DefineEditTextTag extends TextTag { } @Override - public String getText(String separator) { + public List getTexts() { String ret = ""; if (hasText) { ret = initialText; @@ -200,7 +201,7 @@ public class DefineEditTextTag extends TextTag { ret = stripTags(ret); ret = entitiesReplace(ret); } - return ret; + return Arrays.asList(ret); } private List getTextWithStyle() { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java index 93bc2b245..3c756c885 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineText2Tag.java @@ -85,15 +85,10 @@ public class DefineText2Tag extends TextTag { } @Override - public String getText(String separator) { + public List getTexts() { FontTag fnt = null; - String ret = ""; - boolean first = true; + List ret = new ArrayList<>(); for (TEXTRECORD rec : textRecords) { - if (!first) { - ret += Helper.newLine + separator + Helper.newLine; - } - first = false; if (rec.styleFlagsHasFont) { for (Tag t : swf.tags) { if (t instanceof FontTag) { @@ -109,7 +104,7 @@ public class DefineText2Tag extends TextTag { ret += "\r\n"; }*/ } - ret += rec.getText(fnt); + ret.add(rec.getText(fnt)); } return ret; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java index 28a44e17f..c4b08c0ac 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineTextTag.java @@ -86,15 +86,10 @@ public class DefineTextTag extends TextTag { } @Override - public String getText(String separator) { + public List getTexts() { FontTag fnt = null; - String ret = ""; - boolean first = true; + List ret = new ArrayList<>(); for (TEXTRECORD rec : textRecords) { - if (!first) { - ret += Helper.newLine + separator + Helper.newLine; - } - first = false; if (rec.styleFlagsHasFont) { for (Tag t : swf.tags) { if (t instanceof FontTag) { @@ -110,7 +105,7 @@ public class DefineTextTag extends TextTag { ret += "\r\n"; }*/ } - ret += rec.getText(fnt); + ret.add(rec.getText(fnt)); } return ret; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/TextTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/TextTag.java index a21728be8..eadd4fa33 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/TextTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/base/TextTag.java @@ -77,7 +77,7 @@ public abstract class TextTag extends CharacterTag implements DrawableTag { public abstract MATRIX getTextMatrix(); - public abstract String getText(String separator); + public abstract List getTexts(); public abstract List getFontIds(); diff --git a/src/com/jpexs/decompiler/flash/gui/ErrorLogFrame.java b/src/com/jpexs/decompiler/flash/gui/ErrorLogFrame.java index c2ae53922..189df8e38 100644 --- a/src/com/jpexs/decompiler/flash/gui/ErrorLogFrame.java +++ b/src/com/jpexs/decompiler/flash/gui/ErrorLogFrame.java @@ -49,7 +49,6 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JToggleButton; -import javax.swing.SwingUtilities; /** * @@ -200,7 +199,7 @@ public class ErrorLogFrame extends AppFrame { private void log(final Level level, final String msg, final String detail) { if (logItemCount.getAndIncrement() < MAX_LOG_ITEM_COUNT) { - SwingUtilities.invokeLater(new Runnable() { + View.execInEventDispatchLater(new Runnable() { @Override public void run() { notifyMainFrame(level); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index b82dc45da..7d057aa86 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -174,7 +174,6 @@ import javax.swing.JSplitPane; import javax.swing.JTabbedPane; import javax.swing.JTextField; import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; @@ -766,7 +765,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec final MainPanel t = this; - SwingUtilities.invokeLater(new Runnable() { + View.execInEventDispatchLater(new Runnable() { @Override public void run() { splitPane1.setDividerLocation(Configuration.guiSplitPane1DividerLocation.get(getWidth() / 3)); @@ -1173,20 +1172,40 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec if (replaceDialog.result) { final String txt = replaceDialog.searchField.getText(); if (!txt.isEmpty()) { + final String replacement = replaceDialog.replaceField.getText(); final SWF swf = getCurrentSwf(); new CancellableWorker() { @Override protected Void doInBackground() throws Exception { - boolean found = false; - if (searchText(txt, replaceDialog.ignoreCaseCheckBox.isSelected(), replaceDialog.regexpCheckBox.isSelected(), swf)) { - found = true; + int findCount = 0; + Pattern pat = Pattern.compile(Pattern.quote(txt), replaceDialog.ignoreCaseCheckBox.isSelected() ? Pattern.CASE_INSENSITIVE : 0); + List textTags = new ArrayList<>(); + for (Tag tag : swf.tags) { + if (tag instanceof TextTag) { + textTags.add((TextTag) tag); + } + } + for (TextTag textTag : textTags) { + List texts = textTag.getTexts(); + boolean found = false; + for (int i = 0; i < texts.size(); i++) { + String text = texts.get(i); + if (pat.matcher(text).find()) { + texts.set(i, text.replaceAll(txt, replacement)); + found = true; + findCount++; + } + } + if (found) { + String[] textArray = texts.toArray(new String[texts.size()]); + textTag.setFormattedText(getMissingCharacterHandler(), textTag.getFormattedText(), textArray); + } } - if (!found) { - View.showMessageDialog(null, translate("message.search.notfound").replace("%searchtext%", txt), translate("message.search.notfound.title"), JOptionPane.INFORMATION_MESSAGE); + if (findCount > 0) { + refreshTree(); } - return null; } }.execute(); @@ -1195,7 +1214,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } private boolean searchText(String txt, boolean ignoreCase, boolean regexp, SWF swf) { - if ((txt != null) && (!txt.isEmpty())) { + if (txt != null && !txt.isEmpty()) { SearchPanel textSearchPanel = previewPanel.getTextPanel().getSearchPanel(); textSearchPanel.setOptions(ignoreCase, regexp); List found = new ArrayList<>(); @@ -1430,7 +1449,7 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec private String getTextTagInfo(TextTag textTag) { String ret = ""; if (textTag != null) { - ret += " TextId: " + textTag.getCharacterId() + " (" + textTag.getText(", ") + ")"; + ret += " TextId: " + textTag.getCharacterId() + " (" + String.join(", ", textTag.getTexts()) + ")"; } return ret; @@ -1770,12 +1789,12 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec } @Override - public boolean handle(TextTag textTag, FontTag font, char character) { + public boolean handle(TextTag textTag, final FontTag font, final char character) { String fontName = font.getSwf().sourceFontNamesMap.get(font.getFontId()); if (fontName == null) { fontName = font.getFontName(); } - Font f = FontTag.installedFontsByName.get(fontName); + final Font f = FontTag.installedFontsByName.get(fontName); if (f == null || !f.canDisplay(character)) { String msg = translate("error.font.nocharacter").replace("%char%", "" + character); logger.log(Level.SEVERE, msg + " FontId: " + font.getCharacterId() + " TextId: " + textTag.getCharacterId()); @@ -1785,7 +1804,14 @@ public final class MainPanel extends JPanel implements ActionListener, TreeSelec ignoreMissingCharacters ? JOptionPane.OK_OPTION : JOptionPane.CANCEL_OPTION) == JOptionPane.OK_OPTION; return false; } - font.addCharacter(character, f); + View.execInEventDispatch(new Runnable() { + + @Override + public void run() { + font.addCharacter(character, f); + } + }); + return true; } }; diff --git a/src/com/jpexs/decompiler/flash/gui/ReplaceDialog.java b/src/com/jpexs/decompiler/flash/gui/ReplaceDialog.java deleted file mode 100644 index 5809856f6..000000000 --- a/src/com/jpexs/decompiler/flash/gui/ReplaceDialog.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2010-2014 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; - -import java.awt.Container; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Image; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Pattern; -import java.util.regex.PatternSyntaxException; -import javax.swing.BoxLayout; -import javax.swing.ButtonGroup; -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.JRadioButton; -import javax.swing.JTextField; - -/** - * - * @author JPEXS - */ -public class ReplaceDialog extends AppDialog implements ActionListener { - - private static final String ACTION_OK = "OK"; - private static final String ACTION_CANCEL = "CANCEL"; - - public JTextField searchField = new MyTextField(); - public JCheckBox ignoreCaseCheckBox = new JCheckBox(translate("checkbox.ignorecase")); - //public JCheckBox regexpCheckBox = new JCheckBox(translate("checkbox.regexp")); - public boolean result = false; - - public ReplaceDialog(Window owner) { - super(owner); - setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE); - ignoreCaseCheckBox.setSelected(true); - Container cnt = getContentPane(); - setSize(400, 150); - cnt.setLayout(new BoxLayout(cnt, BoxLayout.PAGE_AXIS)); - JPanel panButtons = new JPanel(new FlowLayout()); - JButton okButton = new JButton(translate("button.ok")); - okButton.setActionCommand(ACTION_OK); - okButton.addActionListener(this); - JButton cancelButton = new JButton(translate("button.cancel")); - cancelButton.setActionCommand(ACTION_CANCEL); - cancelButton.addActionListener(this); - panButtons.add(okButton); - panButtons.add(cancelButton); - JPanel panField = new JPanel(new FlowLayout()); - searchField.setPreferredSize(new Dimension(250, searchField.getPreferredSize().height)); - panField.add(new JLabel(translate("label.searchtext"))); - 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); - setIconImage(View.loadImage("search16")); - setTitle(translate("dialog.title")); - setModalityType(ModalityType.APPLICATION_MODAL); - pack(); - List images = new ArrayList<>(); - images.add(View.loadImage("search16")); - images.add(View.loadImage("search32")); - setIconImages(images); - } - - @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(ACTION_OK)) { - /*if (regexpCheckBox.isSelected()) { - try { - Pattern pat = Pattern.compile(searchField.getText()); - } catch (PatternSyntaxException ex) { - View.showMessageDialog(null, translate("error.invalidregexp"), translate("error"), JOptionPane.ERROR_MESSAGE); - return; - } - }*/ - result = true; - } else { - result = false; - } - setVisible(false); - } -} diff --git a/src/com/jpexs/decompiler/flash/gui/SearchDialog.java b/src/com/jpexs/decompiler/flash/gui/SearchDialog.java index 87e5fab59..9905cc38d 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchDialog.java @@ -87,7 +87,10 @@ public class SearchDialog extends AppDialog implements ActionListener { JPanel checkPanel = new JPanel(new FlowLayout()); checkPanel.add(ignoreCaseCheckBox); - checkPanel.add(regexpCheckBox); + if (!replace) { + checkPanel.add(regexpCheckBox); + } + cnt.add(checkPanel); if (!replace) { diff --git a/src/com/jpexs/decompiler/flash/gui/SearchPanel.java b/src/com/jpexs/decompiler/flash/gui/SearchPanel.java index 8ec457eea..56b48de16 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchPanel.java @@ -25,7 +25,6 @@ import java.util.List; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.SwingUtilities; import javax.swing.text.JTextComponent; import jsyntaxpane.actions.DocumentSearchData; @@ -117,7 +116,7 @@ public class SearchPanel extends JPanel implements ActionListener { } private void doUpdate() { - SwingUtilities.invokeLater(new Runnable() { + View.execInEventDispatchLater(new Runnable() { @Override public void run() { searchPos.setText((foundPos + 1) + "/" + found.size()); diff --git a/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java b/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java index dffa81496..c28014d19 100644 --- a/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java +++ b/src/com/jpexs/decompiler/flash/gui/SearchResultsDialog.java @@ -31,7 +31,6 @@ import javax.swing.JButton; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; -import javax.swing.SwingUtilities; /** * @@ -109,7 +108,7 @@ public class SearchResultsDialog extends AppDialog implements ActionListener private void gotoElement() { if (resultsList.getSelectedIndex() != -1) { - SwingUtilities.invokeLater(new Runnable() { + View.execInEventDispatchLater(new Runnable() { @Override public void run() { diff --git a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java index 460d69ea7..75fc1dfaa 100644 --- a/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/abc/ABCPanel.java @@ -102,7 +102,6 @@ import javax.swing.JTabbedPane; import javax.swing.JTable; import javax.swing.JToggleButton; import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; import javax.swing.border.BevelBorder; import javax.swing.table.DefaultTableModel; import javax.swing.text.Highlighter; @@ -686,7 +685,7 @@ public class ABCPanel extends JPanel implements ItemListener, ActionListener, Se public void hilightScript(ScriptPack pack) { TagTreeModel ttm = (TagTreeModel) mainPanel.tagTree.getModel(); final TreePath tp = ttm.getTagPath(pack); - SwingUtilities.invokeLater(new Runnable() { + View.execInEventDispatchLater(new Runnable() { @Override public void run() { mainPanel.tagTree.setSelectionPath(tp); diff --git a/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java b/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java index f0d179e29..64f78c2d0 100644 --- a/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java +++ b/src/com/jpexs/decompiler/flash/gui/helpers/CheckResources.java @@ -30,7 +30,6 @@ import com.jpexs.decompiler.flash.gui.MainFrame; import com.jpexs.decompiler.flash.gui.ModeFrame; import com.jpexs.decompiler.flash.gui.NewVersionDialog; import com.jpexs.decompiler.flash.gui.RenameDialog; -import com.jpexs.decompiler.flash.gui.ReplaceDialog; import com.jpexs.decompiler.flash.gui.SearchDialog; import com.jpexs.decompiler.flash.gui.SearchResultsDialog; import com.jpexs.decompiler.flash.gui.SelectLanguageDialog; @@ -71,7 +70,6 @@ public class CheckResources { NewVersionDialog.class, RenameDialog.class, SearchDialog.class, - ReplaceDialog.class, SearchResultsDialog.class, SelectLanguageDialog.class, ProxyFrame.class, diff --git a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java index fdfa7bcfa..273e0d897 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java +++ b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java @@ -56,7 +56,6 @@ import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JTextField; import javax.swing.SwingConstants; -import javax.swing.SwingUtilities; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; @@ -429,7 +428,7 @@ public class PlayerControls extends JPanel implements ActionListener { @Override public void ancestorAdded(AncestorEvent event) { final AncestorListener al = this; - SwingUtilities.invokeLater(new Runnable() { + View.execInEventDispatchLater(new Runnable() { @Override public void run() {