diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8487817ba..1ce1c08bb 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,2291 +1,2291 @@
-# Change Log
-All notable changes to this project will be documented in this file.
-
-## [Unreleased]
-### Added
-- [#1240] AS search using multiple threads when parallel speedup is enabled
-- [#1308] Search by all P-code files in AS3
-- [#1333] Exporting sprites as swf files
-- [#1365] Allow to configure all types of configuration settings from command line
-- [#1369] Allow zoom in sprite (and button) export
-- Debug tooltips on hover
-
-### Fixed
-- [#1327] P-code editing: error message and syntax highlighting fixed when instruction name contains upper cased letter
-- [#1343] AS 1/2 direct editation critical bug
-- [#1348] Cannot properly export frame with cyrillic symbols to SVG
-- [#1354] Various FLA export problem fixes
-- [#1367] Raw edit conditional type fix.
-- [#1401] SVG export: duplicate pattern IDs fixed
-- [#1402] SVG export: certain font characters not exported properly fixed
-- [#1430] AS 1/2 deobfuscation fixes
-- Opening loaded SWF files during run fixed
-- Not opening first script when clicked on app startup
-
-## [10.0.0] - 2016-12-24
-### Added
-- Iggy Files support - reading and (limited) editation of fonts, texts and AS3 - 64 bit variant only
-- optional AS3 direct editation with Flex SDK
-- AS3 p-code editing - metadata read/write support
-- AS3 p-code editing - end of the block command like in RABCDasm
-- AS3 p-code editing - popup docs for more than instructions
-- Debugger - New columns for variable details - scope, flags, trait
-- Debugger - Add watch feature
-- AS3 decompilation - colliding trait/class names handling - show hash suffix with namespace index on such cases
-- Deobfuscation Tool - Fix colliding trait/classes via toolbar command
-- Auto rename identifiers option now fixes colliding trait/classes aswell
-- [#1254] FLA export - detecting scripts on AS3 timeline
-- [#907] FFDec Library JAR file has version inside it.
-- [#1311], [#1313] actionScript source font size
-- Display warning when library version and GUI version mismatch
-- Changelog file
-- [#1308] Search by all P-code files (AS 1/2 only)
-
-### Changed
-- [#1189] AS3 - sort imports to have same order always
-- GUI: AS3 P-code header show actual trait type and method type
-- GUI: Script editing buttons now named "Edit ActionScript" and "Edit P-code"
-- Set advance values button has confirm dialog with information
-- [#1274] Linux package no longer requires Oracle Java only
-- Library now packaged inside ZIP file
-
-### Fixed
-- P-code docs formatting fix
-- Export dialog - handling sprite and SWF frames correctly
-- [#1275] debugger - show local variables fixes
-- AS3 p-code editing - popup docs correctly displayed when label on line start
-- [#1278] replacing DefineBits error
-- [#1281] DefineFont 2/3 getting character advance value when replacing fix
-- Set advance values button - Do not set advance if the char cannot be displayed in source font
-- AS3 Goto declaration for single character names
-- Identifier renaming for top level classes
-- AS3 direct editation not correctly saving local register names
-- [#1254] FLA export - placing AS3 classes to FLA directory instead of scripts dir
-- Mac OS X installer fix (.pkg)
-- [#1289] AS1/2 direct editation - variables used in inner functions must not be stored in local registers
-- [#1283] AS3 Unbounded Vector - Vector<*> decompilation and direct editation fix
-- [#1294] Font editation (DefineFont2/3) - correct switching of wide character codes
-- [#1302] Callpropvoid instruction docblock not correct
-- [#1309] recent files not getting updates
-- [#1312] faster colliding usages finder
-- [#1303] garbled text when exporting frame with text
-- [#1314] user interface: button order
-- Internal viewer shows red image when bitmap fill is not available (see issue [#1320])
-- [#1323] Audio playback fails
-
-## [9.0.0] - 2016-08-12
-### Added
-- Instance metadata (AMF3) editing in PlaceObject4
-- [#1156] Flash Viewer - DefineScalingGrid support (9-slice scaling)
-- [#1171] Export stroke scale to FLA
-- FLA export - check invalid unicode characters
-- [#1170] Extract from memory in commandline
-- Reload one vs Reload all buttons
-- ABC: Float and Float4 support
-- AS3 p-code instruction documentation in GUI
-- [#1241] Settings to show original bytes in hex view
-- Search in dump view
-- Jump to resources view from hex view
-- Show warning on 32bit JRE
-
-### Changed
-- [#1162] improved opening loaded SWF files
-- Flash Viewer - skip frames when not on time
-- [#1199] Automatically import alpha channel to JPEG3/4 from PNG
-
-### Fixed
-- [#1151] Filters on texts fixed
-- [#1128] Adding characters to font fixed (FontAlignZones not removed)
-- [#1163] Clicking open->file makes program buggy
-- Refresh tree after raw edit
-- [#1172] Text double escape fix
-- [#1174] Change language fix
-- some AS2 deobfuscation fixes
-- [#1183] Index out of bounds fix
-- Implicit coersion on binary/unary opfix
-- debugger: corect display variable values through getters
-- Multiple XLF export fix
-- [#1193] FLA export - text tag advance fix, one layer shape fix
-- [#1193] FLA export - smoothed image detection, export raw JPEG data
-- [#1193] Export space character to TTF correctly
-- [#1200] Previous search text selected when quick find
-- Flash viewer: aspect ratio on startup fix
-- [#1198] Saving trait slot const value
-- Zoom parameter commandline fixed
-- [#1205] clipping fixed
-- [#1194] Wrong sound effects in FLA
-- [#1210] Frame Export fix
-- Improved/fixed go to declaration in AS3
-- [#1217] PCode window not in same position as AS
-- Hide memor search on non windows platform
-- [#1244] Incorrect showing of NOP instructions
-- [#1244] Remove unknown actions when deobfuscation is enabled, compole unknown instructions back
-- [#1241] File content is different from hex view
-- [#1247] Incorrectly handling remainingbytes for DefineCompactedFont
-- [#1236] won't open fixed
-- [#1251] SWF not same after export XML and import back
-- [#1265] Error during export
-- [#1268] Font export - Using second glyph when two glyphs for one character found
-- [#1268] GFX compacted font - fixed advance values on export
-
-## [8.0.1] - 2016-02-20
-### Changed
-- FFDec debug tab in advanced settings moved to other tabs
-
-### Fixed
-- [#1161] AS1/2 deobfuscation broken
-- AS1/2 Simplify expressions fix
-
-## [8.0.0] - 2016-02-18
-### Added
-- Debugger - AS1/2 Show registers
-- Debugger - display variables in the tree structure
-- Debugger - set value of variable
-- Debugger - AS1/2 View constantpool
-- Debugger - P-code level debugging for both AS1/2 and AS3
-- Basic SVG import for shapes
-- Simplify expression setting
-- [#1118] Loading characters through ImportAssets - show as readonly
-- [#409], [#1132], [SkinPart] metadata support - decompilation and direct editation in AS3
-- [#1134] compiling §§ instructions back while direct editation (§§goto is still missing)
-- [#1121] Ability to save binary data by its name
-- [#1052] Add object to existing frame
-- Allow adding tag to main timeline
-- AS1/2: Ctrl+click to declaration of variables, registers
-- Allow trait specification in pcode import
-- Icons for tag types in Dump view
-- Show error message when a text tag is invalid (glyph index problem)
-- AS3 direct editation - store local register names in debug info = allow to rename them
-
-### Changed
-- New application icon and splash screen
-- [#1145] AS3 better declaration type detection, better convert_x instruction handling
-- Binary export - use .swf extension for swf files
-- Better tree labels in generic tag editor (Raw edit)
-- [#758] Allow zooming more than preview area in internal viewer
-
-### Fixed
-- [#1096] FLA export - pretty print
-- [#1104] AS1/2/3 Script Importat not working
-- [#1107] Text Offset Incorrect fixed
-- [#1106] New Shapes replace function fix
-- [#1113] It takes too long to switch between rendered sprite
-- [#1075] Lenght of DefineText in some cases
-- [#1127] autoRenameIdentifiers is not supported in CLI mode
-- [#1128] Letterspacing bug (after font embed): ignore letterspacing when character changed
-- [#1103] Foreach variables fixes
-- AS3 Switch fixes
-- Default clause position in switch
-- [#1133] Incorrect frame order for nested sprite
-- [#1135] Handle try "to" in p-code correctly
-- Font wideOffsets,wideCodes fixed in DefineFont2/3
-- AS3: super method call
-- [#1138] All exported videos are the same file which may be broken
-- [#1139],[#930] Windows Installer: Correct ActiveX download link, Download latest java from webpages
-- [#1137] running flashplayer(debugger) executable in Linux/MacOs
-- [#1144] Command line argument renameInvalidIdentifiers
-- [#1145] double not (!!) not removed
-- [#1147] Sprite is exported incorrectly
-- [#1148] handing end of stream exception in abc reader, loc exception
-- [#1152] Font info tag modified tag was not set => saved swf was corrupt
-- [#1154] Some 32bit JRE problems - program won't start
-- [#1145] Correct precedence handling on binary operators
-- [#116] not resolving unusual tags in DefineSprite
-
-## [7.1.2] - 2015-12-03
-### Fixed
-- AS3 debugger start halt fix
-- AS1/2 debugger fix on nondebug enabled SWFs
-- AS1/2 debugger fix for functions
-- Debug menu item enabled fix
-- AS3 local reg index fix
-- Advanced settings calendar
-- AVM2 instructions in hex view
-- [#1070] Incorrect switch decompilation
-- [#1098] Import XML fix
-
-## [7.1.1] - 2015-11-23
-### Fixed
-- Critical debugger fix - widelines
-
-## [7.1.0] - 2015-11-23
-### Added
-- AS1/2 debugger
-- Breakpoint/IP marker on line beginning
-
-### Changed
-- Starting debugger on demand
-- Installer message about playerglobal is only warning now
-
-### Fixed
-- [#1033], [#1083] AS3 deobfuscation issues
-- [#1091] AS 1/2 direct editation saving
-
-## [7.0.1] - 2015-11-18
-### Fixed
-- Debugger: Adding breakpoint if script initializer not displayed
-
-## [7.0.0] - 2015-11-18
-### Added
-- AS3 Debugger - breakpoints, stepping, show variables
-- Faster AS3 direct editation
-
-### Changed
-- Better Configuration of flashplayer paths
-
-### Removed
-- Removed old "debugger" buttons
-- Removed search from browsers cache - inactual code
-
-### Fixed
-- Many AS3 direct editation related bugs
-- [#1076] export fix
-
-## [6.1.1] - 2015-10-30
-### Fixed
-- Deobfuscate AS3 metadata
-- [#1068] MorphShape with focal gradient fix, FLA XML export formatting fix
-- [#1063] AS3 direct edit - script initializer fix, generating method names
-- XML export/import fixes
-- [#1019] Namespace imports fix
-- AVM2 code execution fix
-- [#1016] AS3 direct editation fixes
-- [#1010] AS2 direct editation - internal and override is not a reserved word
-- [#1008] pushshort instruction diassembly
-- [#1004] this/super can be AS1/2 variable
-- [#933] AS3 allow numbers as object literal keys
-
-## [6.1.0] - 2015-10-26
-### Added
-- Open other loaded SWFs during playback (useful for loaders)
-- Export uncompressed data from dump tree
-- Print performance statistics from commandline
-- [#1062] Editing/displaying script initializers
-- Enable debugging on SWF file (commandline)
-
-### Changed
-- Faster syntax highlighting
-- Better AS1/2 deobfuscator
-- [#418] AS3 deobfuscator improved
-
-### Fixed
-- AS call method fix (first parameter is "this")
-- [#1047] open all scripts folders
-- [#812] decompile fail
-- [#1056] deltaY missing when adding a new StraightEdgeRecord
-- [#1057] Editing as in editor results in package name moving
-- [#991] GUI export
-- [#689] Ignore Case not correctly toggled
-- [#1060] reversed and/or detection in some cases
-- [#1037] isXML call
-
-## [6.0.2] - 2015-09-12
-### Added
-- AS3: Display and direct edit trait Metadata
-- Allow to specify tag type on image or shape import
-- Convert image tags from commandline
-- [#489] Hex decode very large integers
-- Add new tags without show empty folders
-- Dependent characters in basic tag info
-- [#1007] replace bytearray in raw editing
-- Italian translation
-
-### Changed
-- AS2 parser - add string to constant pool if there is not enough space
-- [#1044] AS2 - order scripts by physical location, name by offset
-
-### Removed
-- Deprecated commandline parameters removed
-
-### Fixed
-- JNA problems on some JDKs
-- [#947] Marklevels errors ignored 17a94b7
-- [#953] Mac application permission fix (maybe)
-- [#954] IndexOutOfBounds fix
-- [#950] AddTrait setting modified fix
-- [#945] AS1/2 directeditation fix - member named as global function
-- [#957] AS1/2 IndexOutOfBounds fix
-- [#956] Invalid jump offsets warning
-- [#968] Sprites export with wrong coloring
-- [#978] case sensitivity of filenames
-- [#955] AS2 decompilation problem
-- Image alpha fixes
-- [#966] Go to document class
-- [#991] scripts exporting
-- [#999] save as fla
-- [#1000] image export for malformed JPEG3 tags
-- [#1017] store alchemy opcodes with wrong order
-- [#1030] stack overflow fix
-
-## [6.0.1] - 2015-07-06
-### Added
-- Special §§ instructions marked as red
-- [#949] Replace alpha channel from commandline
-- AS3 deobfuscation from commandline
-- Option to ignore FlashCC/Alchemy packages
-
-### Changed
-- [#944],[#991],[#939],[#942] AS3 deobfuscation improvements
-
-### Fixed
-- AS1/2 deobfuscation fixed
-- [#952] Not loading SWF without extension
-
-## [6.0.0] - 2015-07-04
-### Added
-- New AS3 deobfuscation method
-- Internal "preprocessor" §§ actions introduced - §§pop,§§push,...
-- Allow reload FFDec when no SWF is opened
-- [#858] Allow to set compression type in header
-- [#905] Show codec details for sound items
-- Better alchemy/DomainMemory instruction handling
-- Better obfuscated names handling
-- [#920] Export instance name to SVG
-- [#921] Export html DefineEditText to SVG
-- Open multiple files with drag and drop
-- Better "multi packs" handling (Alchemy)
-- SWF version 29 to flash player 18 mapping
-- ImportAssets2 sha1 field
-- [#924] Sprites to image from commandline
-- AS1/2 direct editation big numbers fix
-- Allow to add FILTERs and SHAPERECORDs in generic tag editor
-- Enable close all menu when no swf is selected
-- Restore modified state even when something goes wrong
-- Some old tags added
-
-### Changed
-- AS decompilation highly improved
-- Better &&, || handling
-- DoABCDefine renamed to DoABC2
-- Separated Sprite export settings
-
-### Deprecated
-- Old AS1/2/3 deobfuscation method marked as deprecated (can be enabled back deep in the configuration)
-
-### Fixed
-- Many decompilation problems - EmptyStack exception, Maximum recursion level reached, etc.
-- Few menu issues
-- [#895] Correct handling CMYK JPEG
-- [#884] AS direct edit assignment
-- [#899] Show script after AS3 direct editation
-- Some AS1/2 parser problems
-- [#903] FLA export - fix for missing fontname, lastframe
-- [#855] AS3 direct edit - for..in variable declaration fix
-- [#850] Constant initialization for same multinames
-- [#832] AS3 direct edit - other ABCs resolving fix
-- [#904] Cannot export images
-- [#910] Missing instructions
-- Opening not existent files on restoring last session
-- [#922] Edit text leading
-- Put image before shape on shape replace
-- [#916] Replacing Shape corrupts SWF
-- JRE setup parameters fixed
-- [#938] Parallel speedup limit fix
-
-## [5.3.0] - 2015-05-25
-### Added
-- Generic tag editor: improved table editing (import/export assets tags, etc.)
-
-### Changed
-- Classic (nonribbon) UI improved - has same items as Ribbon UI
-- Icons improvements
-- Disabling menu items when work in progress
-
-### Fixed
-- [#897] Classic UI fix
-
-## [5.2.0] - 2015-05-22
-### Added
-- UI8 editbox for swf version in header panel
-- Basic tag information panel
-
-### Changed
-- AS1/2: Shown only the constant pool(s) in pcode editor
-- Do not allow to chage tag tree selection, when current tag is under editing
-- Faster bitmap export
-- Using less memory when playing sounds
-- Error message changed when the opened file is not swf
-
-### Fixed
-- [#470] panels size after resizing from/to full screen
-- [#877] A small glitch after search in AS
-- [#878] small glitch after saving P-code or swf file
-- [#470] glitch
-- [#845] If frame consist 2 DoAction then it imports only first one
-- pdf export (when no frame exists)
-- text rendering (alpha channel was ignored),
-- bmp export (paddings when width%2==1)
-- [#883] -dumpSWF option does not work anymore
-- [#882] Canvas export border size
-- [#760] Internal viewer line linear gradient fill is not working
-- [#887] error on export a special swf's P-CODE
-- Extensions of exported images fixed
-
-## [5.1.0] - 2015-05-04
-### Added
-- Allow to copy/move multiple tags, and dependencies
-- [#842] For reconstruction if debug line info present
-- [#841] Loop control for sound preview
-- [#845] Import exported AS1/2 (DefineButton2&DefineSprite) button
-- Scrollbar added to fontpanel
-- SWF header editor
-- Configure what object types to export in exportdialog
-
-### Changed
-- Better gif exporter
-- [#772]: closing loading dialog now cancels the loading of the swf
-- [#762] export pcode with different extension
-
-### Fixed
-- CRITICAL: Update System Bug causing updates not working
-- [#862] AS3 asm: do not read beyond return/throw instructions
-- [#865], [#613]: ribbon prefered width fix
-- [#868] export path fix, allow to export buttons
-- [#865] TagTree font size problem on high resolution screens
-- [#713],[#807] Installer for 4.0+ fails to access Adobe Website
-- [#728] Large fonts, [#857] add scroll on DefineFont3
-
-## [5.0.2] - 2015-04-18
-### Added
-- Reopen last session
-
-### Fixed
-- ffdec.sh file line endings fixed
-
-## [5.0.1] - 2015-04-18
-### Fixed
-- [#860]: Opening bundle (zip, swc, any binary file) files fixed
-
-## [5.0.0] - 2015-04-18
-### Added
-- Color skins
-- [#824] Mac OS X package
-- [#809] Move left,right buttons for DefineTexts using translatex parameter
-- [#805] Editor mode for DefineTexts
-- [#825] Hotkeys for next/previous DefineText
-- Export/Import symbol classes/export asset tags
-- Frame export progress
-- [#737] Single file script export
-- Displaying changed AS3 scripts in GUI as bold
-- Additional character info tags placed under character node
-- New icons for other tags (metadata,fileattributes,setbackground,place/remove)
-- Metadata tag editor
-
-### Changed
-- Default color skin altered
-- [#350] Allow only one running instance (Windows only, can be turned off)
-- SWFs in zip based bundles (SWC for example) can be modified & saved
-- Performace improvements
-- More compact SWF-XML format
-- Marking changed parentnodes as bold too
-
-### Fixed
-- [#814] Exporting with scale problem
-- [#816] P-code not shown after class initializer trait selection
-- [#835] Static initializer improvements
-- AS3 direct editing - local register decrement fix
-- AS3 direct editing - maintain register order/names
-- [#836] AS1/2/3 Correct expression precedence handling
-- AS3 preincrement
-- [#848] Correct toggling text switches
-- [#817] AS1/2 for..in variable declaration
-- [#849] Attribute member
-- [#852] Ignore case for russian characters
-- [#837] AS3 try..finally without catch
-
-## [4.1.1] - 2015-02-21
-### Added
-- Export/Import XML added to ribbon menu
-- Few GUI enhancements
-- Undo tag changes context menu
-
-### Changed
-- Java 8 now required
-
-### Removed
-- Removed support for Java below 8
-
-### Fixed
-- [#811] export ActionScript
-
-## [4.1.0] - 2015-02-18
-### Added
-- XML export/import
-- confirmation dialogs added
-- Add support for non-standard ABC-compressed SWF file
-- [#745] Copy tag to another SWF
-- [#803] Align text in DefineText
-
-### Changed
-- performance improvements
-- [#758] Zoom to fit is dynamic
-
-### Fixed
-- [#738] Frame export
-- [#742] Can't edit frames
-- [#747] Move tag to adds extra frame
-- [#749] Internal viewer Sprite fill color
-- [#752] Sound is not stopped
-- [#753] Reload swf
-- [#759] Decompilation § symbol
-- [#766] Can't extract all resources
-- [#768] Super calls not being correctly recognized
-- [#773] Scripts associated with ClipActions are not shown
-- [#776] Stop working after setting "number of threads" to 0
-- [#783] No OK box when edited script or text was saved
-- [#785] Text search. Remember last choise, Unicode case insensitive search
-- [#787] Search in AS bug (when navigating to searched results)
-- [#788] Add DefineCompactedFont Tag to gfx file
-- [#790] Impossible to change letters under a font
-- [#794] Font extraction fails sometimes
-- [#798] Close file streams after export, exporting progress
-- [#800] Unexpected deleted carrier return in DefineEditText
-- Build fix on Linux
-- Fis Startup Script for OpenJDK
-- Other minor fixes
-
-## [4.0.5] - 2014-12-01
-### Added
-- Escape control characters in strings, identifier names
-- [#676] import text error messages / logging enhancement
-- [#734] \xAB escapes, \uABCD escapes
-- [#687] AS3 - allowing p-code comments on separate line
-- [#709] Text Export to Single File with custom filename
-
-### Fixed
-- [#732] Random freezing - JavactiveX library updated.
-- [#730] Not working without ActiveX fix on Windows
-- [#735] Automatic deobfuscation not correctly switched (required restart)
-
-## [4.0.4] - 2014-11-23
-### Changed
-- better file cache, removing unneccessary temp files
-
-### Fixed
-- obfuscated identifiers
-
-## [4.0.3] - 2014-11-23
-### Added
-- [#722] Go to next/previous frame
-- BMP file format export (images,frames,shapes) and import(images)
-
-### Fixed
-- [#725] various AS direct editation bug fixes - namespace compilation, AS 1/2 strict equals, submethod scope, unbounded type
-- [#715] namespace resolving fix
-- [#635],[#726] placing cursor inside Unicode characters
-
-## [4.0.2] - 2014-11-22
-### Added
-- show frame number during play
-- flashplayer - show controls for DefineSprite
-- goto frame
-- [#716],[#717],[#718] Proxy - save SWF, replace, copy URL, filesizes, table design
-
-### Changed
-- [#720]: edited shape tag is not marked as modified after replacing
-- reorganized about dialog
-
-### Fixed
-- [#719] null swf name in Proxy after cancelling rename dialog
-- flashplayer - font display
-- [#723]: saving swf with invalid referenced characters
-- DefineCompactedFont paging
-- [#288] Less memory usage during FLA export
-- Corrected syntax hilighting for AS3 P-code
-
-## [4.0.1] - 2014-11-12
-### Fixed
-- [#713] Installer can continue when no file can be downloaded
-- Fixed shapes
-- Checking for updates moved to separate thread
-
-## [4.0.0] - 2014-11-11
-### Added
-- [#677] Zoom level in export settings
-- internal viewer: linear/srgb gradients
-- zooming buttons for flashplayer/internal viewer
-- stroke scaling modes for canvas export
-- create snapshot button
-- [#389] Selecting font face on import
-- [#701] Importing font from TTF file
-- Reorganized font panel
-- [#707] Debugger for logging messages
-- [#302] AS3: Better Ctrl+Click handling with underline, more declaration targets
-- [#685] Getting local register names from debug info can be disabled
-- Adding new tags
-- [#698] Allowing unicode letters in identifiers
-- [#710] Information about deobfuscation in error comments
-- One EXE for 32/64 bit, uses percentage memory.
-- EXE SplashScreen
-- New Improved Windows Installer (NSIS) - can install Java and FlashPlayer, download playerglobal.swc
-- Config setting to load inner SWFs automatically
-- Replace shape with image
-
-### Changed
-- better FlashPlayer integration using JavactiveX library
-- Faster building tag tree
-- Faster timeline construction
-- [#711] Improved folder view - faster and with correct context menu
-
-### Fixed
-- AS2 deobfuscation fixes
-- AS2 loops fix
-- [#681] Linux script fixes
-- AS2 constructor name fix
-- [#688] AS3 direct edit fixes
-- [#691] AS3 p-code reading/saving fix
-- AS3 direct edit -submethod name resolve fix
-- frames to html canvas fix
-- [#524] Mask layer not applied when nonempty script layer
-- [#663] AS3 imports fixes
-- Font export of dot character
-- Font panel Yes button fixed
-- [#702] GFX font reading fix
-- Better obfuscated names handling
-- [#539] for(each) in declaration fixes
-
-## [3.0.0] - 2014-09-20
-### Added
-- Separated GUI (GPL) and library (now LGPL)
-- Editing obfuscated identifiers via new paragraph(§) syntax
-- Timeline View with preview and object hilighting
-- Show GFX data in dump view
-- [#650] New parameter to replace binarydata, images, sounds, scripts from commandline
-- Dump view - selecting node
-- [#680] Loading subSWFs from binaryTags now optional (button/context menu) to avoid unnecessary memory consumption
-
-### Removed
-- Removed deprecated commandline export formats (see --help)
-
-### Fixed
-- FileAttributes tag reading fix
-- [#649] GFX reading fixed
-- [#656] Search in memory - 64 bit processes fix
-- [#661] scripts not showing
-- [#664] expanding fillStyles in raw edit
-- [#668] add missing character fix, text tags fix
-- [#674] texts hilighting initialization fix
-- [#675] AS1/2 and/or operator compilation
-- [#632] Locking file after opening (cannot save, etc.)
-- [#651] Unnecessary removing expression killed in unreachable part
-- [#678] Windows batch file paths fixed
-- [#672] Disabling transparency slider on RGB only selection
-- [#684] Sound streams inside DefineSprites, soundstream handling
-
-## [2.1.4] - 2014-08-23
-### Added
-- AS1/2: New method for deobfuscation (can be switched off in settings)
-- AS1/2: Using eval/set on invalid identifiers, quotes in function names/parameters
-
-### Fixed
-- [#647] Skipping FileAttributesTag with Parallel speedup on
-- [#648] Export from embedded SWF
-
-## [2.1.3] - 2014-08-18
-### Added
-- Show "save" and "saveas" in application menu
-- Saving data range in dump view
-- Show actions, abcdata in dumpview (context menu on the tree node)
-- [#612] show color in hex format
-
-### Changed
-- Faster dump info collecting (less memory)
-- Allow selecting multiple files in open file dialog
-
-### Fixed
-- [#623] ffdec.sh UNIX file endings, executable
-- [#624] search in embedded swf files
-- [#632] AS1/2 Unnecessary GetVariable before NewObject
-- [#627] filter swf not working
-- LZMA saving
-- Export pcode&hex from commandline
-- [#640] text import fixed, ignore BOM
-
-## [2.1.2] - 2014-07-20
-### Added
-- Dump view
-- Context menu: Jump to character, raw edit all tags
-- Catalan translation
-- SWF header display
-
-### Fixed
-- [#595] AS3 direct edit - Getter/Setter generation - caused FlashPlayer crashes
-- [#592] AS3 Multiname resolving in P-code causing different bytecode
-- [#585] AS3 moving popped values to output
-- [#578] Always on top fixed on search results
-- [#501] GotoFrame2 fix
-- [#616] Frames to PNG export
-- Export context menu
-- [#559] Bitmap export opacity
-- [#401] Placeobject 3/4 fix
-- [#593] Return object newline
-- [#594] Setting for curly brace
-
-## [2.1.1] - 2014-06-05
-### Added
-- [#302] Find declaration (Ctrl+click, Ctrl+B), Find usages (Ctrl+U) - Works only for exactly same multinames, not local registers
-- AS1/2 direct edit - global functions improvements
-- AS1/2 negate operator, unary minus operator
-- Opening SWFs in BinaryData tags
-- AS1: Old string operators support, and/or, <> operator (editation)
-- Statusbar loading animation improved
-- [#579] AS3 direct editation - removing old class/methods from ABC
-- remove character without the dependencies (remove only the place/remove tags)
-- Running on system with no home directory
-- [#428] PDF export (as images only)
-- Commandline FlashPaper to PDF export
-- Select frames / Characters commandline options
-
-### Changed
-- [#337] quickfind visibility improved
-- [#584] commandline script export - select whole packages (use .+ at the end of -selectas3class)
-
-### Fixed
-- [#576] AS1/2 direct editation: DefineFunction2 fix
-- AS1/2 property fix
-- AS1/2 typeof operator fix
-- [#250] line spacing fix
-- PlaceObject 3-4 className
-- [#579] AS3 direct editation bugfixes - property resolving, integer values
-- Morphshape canvas export fix
-- Canvas export fix - closing path
-- [#580] Rename invalid identifiers commandline fix
-- [#510] JSyntaxPane find and replace dialog wrap around fix
-- No more frame caching during export => memory saving (like [#583])
-- [#586] DropShadow filter fix
-- Canvas export colortransform fix
-
-## [2.1.0 update 2] - 2014-05-08
-### Added
-- AS3 decompilation/editation: Vector initializers
-- AS3 direct editation: more classes in one file
-
-### Fixed
-- [#574] DefineSprite editing fix
-- Various AS3 direct editation fixes
-
-## [2.1.0 update 1] - 2014-05-05
-### Added
-- Portugese-brasilian translation
-
-### Changed
-- HTML Canvas export improvements
-
-### Fixed
-- Various AS3 direct editation bugs, like [#570]
-
-## [2.1.0] - 2014-05-01
-### Added
-- AS3 direct editation (Experimental!)
-- Frames SVG Export
-- Shape/MorphShape/Frames HTML 5 Canvas Export
-- [#559] morphshapes as animated SVG
-- [#563] Single file text export/import
-- Font WOFF export
-- Advanced settings dialog with tabs, config names, descriptions
-
-### Fixed
-- [#561], [#509], [#433]: AS3 EmptyStackException fix - correct hasnext2 arguments
-- Internal viewer: Filters fix
-
-## [2.0.1 update 2] - 2014-04-05
-### Fixed
-- [#557] AS3 null namespace fix - p-code not working
-
-## [2.0.1 update 1] - 2014-04-04
-### Fixed
-- [#556] Goto main class on startup fix
-- [#557] Nullpointer fix (private namespaces)
-
-## [2.0.1] - 2014-04-03
-### Added
-- Thumbnail view
-- Font TTF export
-- Exporting frames: PNGs, AVI, GIF (via Internal flash viewer)
-- Expand all context menu
-- Internal viewer: Button mouse move and click handling
-- Playing sounds without flash player
-- Internal viewer: Sounds on stage
-- All sounds to WAV export
-- Internal viewer: Showing texts, dynamic text border/fill
-- [#504]: Unicode characters in JSyntaxPane
-- Internal viewer: showing object under cursor
-- Folder icons
-- Sound/Image format on command line.
-- Removing placeobject tags
-- Removing frames
-- AS: "elseif" statements
-- Code formatting: space before parenthesis
-
-### Changed
-- Single frames animated.
-
-### Fixed
-- [#529] limit the number of displayed binaryData bytes
-- [#538] Interface are sometimes dynamic
-- [#537] super is sometime preceded by a dot
-- [#540] Saving SWF changes very large static uint values
-- [#387] Frames preview bugged
-- AS:loop mismatch fix on parallel speedup
-- [#552] Some timeout exceptions
-- [#494] Fixed nightly builds updates
-
-## [2.0.0] - 2014-03-02
-### Added
-- Generic tag tree editor
-- Timeline view (stub only)
-- FLA export to CS5, CS5.5, CC format (previously only CS6 was supported)
-- [#513]: command line option to extract swf from binary file
-- Configurable code formatting (Indentation + brace position)
-- [#262] Export FLA: Font character ranges export
-- Configurable checking for updates
-
-### Changed
-- Improved Internal Flash viewer - better shapes, morphshapes, DefineEditText tag, clipping, blend modes
-- Improved commandline usage
-- Automatic deobfuscation default value set to False (See News on webpages)
-- Check for updates can be configured to inform about Nightly builds aswell
-
-### Deprecated
-- Some commandline options are now deprecated, see --help
-
-### Fixed
-- [#499] Cannot save via Proxy fixed
-- [#504] font name reading fixed
-- [#508] Support for OS without GUI
-- [#305] Export FLA: empty sound layers
-- [#312] Export FLA: Improved Shape/MorphShape fix
-- [#503] Export FLA: Smoothing invalid shapes
-- [#401] Invalid GFX tags in non GFX files
-- [#304],[#306],[#507],[#424],[#425],[#478],[#485],[#517],[#518] Many direct AS1/2 editing issues
-- [#361] FFDec icon is not visible on application start
-- [#392] Video stream data fix
-- [#516] AS3 P-code editor - Null name namespace handling
-
-## [1.8.1 update 1] - 2014-02-02
-### Fixed
-- [#495] font embedding fix
-- [#496] date format in new version dialog
-- cosmetic changes
-
-## [1.8.1] - 2014-01-30
-### Added
-- [#299] replace DefineBits images
-- [#303] open folder with exported FLA
-- [#324],[#346] SWC/zip/other binary file support
-- [#371] detailed logging
-- [#426] command line switch to rename identifiers
-- [#457] clear recent opened files list
-- [#458] save selected system font for swf fonts
-- [#460] text editor: do not scroll to the end automatically
-- [#462] font embedding dialog: show more sample characters
-- [#463] global search in texts
-- [#465] make font properties editable
-- [#466] font preview
-
-### Changed
-- [#369] new SVG and preview image rendering
-- [#390] refresh font list without reloading the application
-- [#453] update texts aftert adding new character to a font tag
-- [#459] remember text panel splitter position
-- [#461] font panel gui redesigned
-
-### Fixed
-- [#451] dialog windows are not on the center of the screen
-- [#454] Text syntax highlighting
-- [#455],[#465] classic interface issues
-- [#474] changeing language only available one time
-- [#477] log window localization
-- [#481] SVG export fix
-- [#484] Oversized advance value after editing DefineText with DefineFont2 font
-- [#493] missing search results
-
-## [1.8.0 update 1] - 2013-12-27
-### Added
-- [#453] refresh (edit+save action) all texts button
-
-### Fixed
-- Flash panel and font panel fixed
-
-## [1.8.0] - 2013-12-27
-### Added
-- [#350] Allow to open multiple SWFs
-- [#365] Filter fake SWFs during memory search
-- [#366] Allow to sort the result list in memory search window
-- [#429] Auto rename invalid identifiers setting
-- [#447] Non-ribbon interface
-
-### Fixed
-- [#354] Infinite decompilation fixed
-- [#438] Case sensitive Command line arguments fixed
-- [#436] Saving actionscript fixed
-- [#446] Precedence issue fixed
-- [#451] Dialogue window positions on a multi-monitor configuration fixed
-
-## [1.7.4 update 1] - 2013-12-05
-### Added
-- [#426] Command line parameter for renaming invalid identifiers
-
-### Fixed
-- [#427] Exception on linux fixed
-- [#405], [#420], [#421] Some decompilation issues fixed
-- [#430] Configuration default value problem fixed
-- [#397], [#431] Deobfuscation stucked sometimes problem fixed
-
-## [1.7.4] - 2013-11-10
-### Added
-- [#169] hexedit method body bytes
-- [#335] last opened files
-- [#404] Exporting P-code and Hex + console parameters
-- [#407] register name is configurable
-- Advanced settings
-- Cancellable decompiling, exporting and searching
-
-### Fixed
-- [#399], [#400] performance optimizations
-
-## [1.7.3 update 2] - 2013-09-29
-### Fixed
-- [#398] AS3 p-code values with index 0 (null)
-
-## [1.7.3 update 1] - 2013-09-28
-### Added
-- [#382] AS3: Adding new method
-
-## [1.7.3] - 2013-09-27
-### Added
-- AS3: Multiname and namespace editing.
-- [#382],[#396] AS3: Adding new trait (method/slot/const)
-- AS3: Highlighting pair parenthesis/bracket
-- AS3: Editing various new P-code parameters
-- AS3: Highligting of trait names/types/parameters
-- AS3: Global rename identifier for traits
-- [#357] Playback controls for DefineSound
-- [#391] AS3: Native methods mark
-- [#395] Support for GFx ScaleForm SWFs (with fonts editing)
-- Displaying fonts in internal viewer
-- [#334], [#395] New Embed font dialog - selecting character ranges with preview
-- Replacing characters in font (Yes/No to all dialog)
-
-### Changed
-- AS3: New p-code syntax inspired by RABCDasm
-- AS3: Editing whole trait in one textarea
-- AS3: Removed messages about adding new constants
-- AS3: Modified colors in editor
-- [#301] Clearing error log causes icon to reset
-
-## [1.7.2 update 2] - 2013-09-13
-### Changed
-- Updated translations
-
-### Fixed
-- [#383] Firefox browser cache handling
-- [#386] SWF resizing
-
-## [1.7.2 update 1] - 2013-09-11
-### Changed
-- updated translations
-
-### Fixed
-- [#383] Fixed cache loading when Firefox not used
-
-## [1.7.2] - 2013-09-11
-### Added
-- [#357] Sounds Preview (Windows only)
-- Movies preview (Windows only)
-- Whole SWF display
-- Preview controls (Play,Pause,Stop)
-- Search SWFs in browsers cache (Firefox, Chrome)
-- [#367] Memory search: Save selected files to disk
-- Portugese translation
-
-### Changed
-- [#380] Faster displaying DefineBitsLossless(2) images
-
-### Fixed
-- [#292] Background color for Fonts preview fixed
-- [#375] Replacing DefineBitsLossless image tag
-- [#378] Refreshing language of JSyntaxPane
-- MORPHGRADIENT reading fix
-
-## [1.7.1] - 2013-08-25
-### Added
-- Loading SWFs from other processes memory (Windows only, sorry)
-- [#325] Spanish translation
-- [#210] Ukrainian and Dutch translation
-- [#355] Chinese translation
-- [#292] Change background color in SWF preview
-- [#301] Clear errors log button
-- [#313] Command line parameter for ignore all errors
-- [#330] Protection agains adding same characters
-- [#332] AS1/2 Showing elapsed times during commandline export
-- [#344] Reload opened SWF
-- Decompilation timeouts
-
-### Fixed
-- [#295] Export FLA: wrong font
-- [#297] Too bright titlebar button colors
-- [#307] Export FLA: fixed empty textfields
-- [#309] Export FLA: static text letter spacing detection
-- [#310] Export FLA: Strokes
-- [#311] Export FLA: BitmapFill
-- [#327] AS1/2 Disassembly error stop application
-- [#328] Fixed replacing images in DefineBitsJPEGX
-- [#333] AS1/2 action reading
-- [#336] Graph window is too small
-- [#337] Quick search panel barely visible in same cases
-- [#338] Expand/collapse icon in errorlog
-
-## [1.7.0 update 1] - 2013-08-11
-### Added
-- [#315] German translation (partial)
-
-### Fixed
-- [#123] Better context menu integration
-- [#243],[#326] Better deobfuscation
-- [#287] Typo in parallelSpeedUp parameter
-- [#290],[#291] improved select language dialog
-- [#294] minor GUI fixes
-- [#298] Progressbar positition issues
-- [#296] better export directory remembering
-- [#314] Better deobfuscating filenames
-- [#316] Readonly editor panes accepted Ctrl+Z/Y
-- [#318] Export FLA: Shapes export fix
-- [#319] AS3: Improved try..catch..finally decompilation
-- [#323] AS3: Fixed default switch part
-
-## [1.7.0] - 2013-08-03
-### Added
-- Listing contributors on about page
-- [#223] AS2: Detecting uninitialized class fields
-- [#250] Export FLA: Detecting static fields margin and spacing
-- [#261] Export FLA: AS1/2 Frame scripts on first layer
-- [#269] Commandline parameters for switching configuration
-- [#274] AS3 Displaying elapsed time during commandline export
-- [#275] AS3 Removing returnvoid as last statement
-
-### Changed
-- New GUI based on Substance look and feel
-- Menu changed to ribbon panel
-- New round icon
-- [#258] AS1/2: Improved chained assignments
-- [#267] Starting program without choosing a file
-- [#286] Saving to temp file first
-
-### Fixed
-- [#123] Improved context menu integration on Windows
-- [#233] Globally rename identifier deselects item in the tree
-- [#235] Export FLA: Dynamic text fields coordinates
-- [#243],[#263],[#264],[#265],[#266],[#281] Improved deobfuscation
-- [#251] Export FLA: Fixed filter strength rounding
-- [#257] Export FLA: Text field color and size issues
-- [#259] Fixed images alpha
-- [#260] Export FLA: Labels position
-- [#268] AS1/2 Function parameter shown as register instead loc
-- [#272] AS3 Class initializer editation fix
-- [#276] Fixed anonymous/inline functions handling
-- [#220] Improved editing fonts / texts
-- [#284],... other small fixes
-
-## [1.6.7] - 2013-07-20
-### Added
-- [#220] Selection of font to import characters from
-- [#232] Automatically add .swf extension in saveas dialog
-- [#253] Abort/Retry/Ignore dialog on errors with file saving
-
-### Changed
-- Improved translations
-
-### Fixed
-- [#137],[#242], [#243], [#244] AS1/2/3 fixed deobfuscation
-- [#203] AS1/2 improved direct editing
-- [#220] Adding characters to font fix
-- [#225] AS1/2 object literal without name quotes
-- [#236] AS1/2 Rename invalid identifiers issues
-- [#245] AS3 Double space around "as" keyword
-- [#247] AS3 Scrolling to main class at startup
-- [#248] Memory issues (slowdown)
-- [#254] Expressions as commands
-- [#255] Windows 7 loading issues
-- [#256] AS3 Object literal in return clause
-- SWF text parsing (new lines)
-- Labels size by locales
-
-## [1.6.6 update 2] - 2013-07-16
-### Fixed
-- [#241] Program could not be started
-
-## [1.6.6 update 1] - 2013-07-16
-### Changed
-- Better localization support
-
-### Fixed
-- [#238],[#239],[#240] Fixed deobfuscation related problems
-- [#237] Parentheses in AS1/2 add,subtract
-
-## [1.6.6] - 2013-07-16
-### Added
-- [#217] Russian translation (focus)
-- [#219] Hungarian translation (honfika)
-- [#224] Swedish translation (Capasha)
-- [#220] Adding characters to Fonts, displaying font info
-- [#121] Search progress indication
-- Error log
-
-### Changed
-- [#203] Improved direct editing of AS1/2
-- [#207] Update SWF preview after switching external/internal flash player
-
-### Fixed
-- [#151] Memory caching
-- [#171] Skipping invalid AS3 code - newobject, newarray
-- [#206] AS3 switch problem
-- [#208] Renaming anonymous functions
-- [#209],[#229] FLA export texts positions
-- [#213],[#221] other decompilation issues
-- [#225] AS object literal broken with ternar operator
-- [#226] onClip indentation in FLA export
-- [#227] gotoAndStop wrong frame index
-- [#230] FLA export missing strokes
-- Shapes viewer - missing strokes
-
-## [1.6.5 update 1] - 2013-07-09
-### Fixed
-- [#151] Fixed caching in memory
-- [#172] AS1/2 constant detection fix
-- [#174] Renaming SymbolClass fix
-- [#175],[#212] Fixed create directory issues on export
-- [#185],[#186] on-clip actions indentation
-- [#197] AS1/2 Missing storeregister before switch
-- [#216] AS2 Fixed field order
-- [#213] AS2 Fixed var fields quotes, switch nullpointer
-
-## [1.6.5] - 2013-07-08
-### Added
-- Multilanguage support (currently English and Czech)
-- [#151] Option for caching in memory instead of files
-- [#168] Export selection in tree context menu
-- [#176] option to show main class on startup
-- [#177] saving window maximized state
-- [#202] Removing tags other than DefineSprite
-
-### Changed
-- [#173],[#190] Better renaming
-- [#129], [#153] Better deobfuscation
-- [#180] better error handling
-- [#185],[#186] better displaying and exporting onclip actions
-
-### Fixed
-- [#123] Better context menu integration
-- [#136] FLA export - text sizes
-- [#137],[#179] foreach issues (hasNext)
-- [#144] Plain text export - empty line fix
-- [#144] Not displaying texts
-- [#164] DefineMorphShape issues
-- [#167] Sprite tag appearing twice in export filename
-- [#170] AS3 Try in loop
-- [#172] loop detection fix
-- [#175] use empty namespace
-- [#178] AS subtract with negate
-- [#181] AS3 missing quotes in object field
-- [#182] missing namespace imports
-- [#183] wrong stage size
-- [#184] wrong video link
-- [#189] Fixed three dots in tree
-- [#191] Focalgradient fill fix
-- [#195] AS2 issues
-- [#196],[#197] switch issues
-- [#198] DefineFont2 empty check
-- [#200] DefineBitsLossLess fix
-- [#201] Nonworking main window in Linux/MacOS (due toAssociation)
-
-## [1.6.4 update 1] - 2013-06-30
-### Fixed
-- [#166] For loops detection
-- [#165] AS3:direct lookupswitch support
-
-## [1.6.4] - 2013-06-30
-### Added
-- [#63] Globally rename identifier
-- [#67] Deobfuscation - rename identifiers according to type
-- [#117] Drag & Drop SWF file to main window opens it
-- [#123] Context menu integration on Windows
-- [#127] Drag & Drop items from tree outside of application
-- [#134] AS3: Find document class
-- [#144] New lines in plain text export
-- [#155] Remembering window size + splitbar positions between runs
-
-### Changed
-- [#142] Using exportassets tag for tag names
-- [#146] Display AS2 classes as tree of packages
-- Better loop detection
-
-### Fixed
-- [#129] AS1/2: not refreshing decompiled after rename
-- [#130] Renaming SymbolClass identifiers too
-- [#132] Renaming identifiers renamed strings
-- [#136] Invalid text positions in FLA export
-- [#145] Unicode support
-- [#147] Escape filenames during obfuscated AS3 export
-- [#148] Better package vs classname handling
-- [#152] Empty if branches not inverted
-- [#156] Better search handling (not freezing)
-- [#157] AS3: Try statements in loops
-- [#158] Graph repaint problem
-- [#159] AS3: Improper rest parameter handling
-- [#160] Commandline binaryData export
-- [#162] DefineBitsJPEG2 image replacing
-- [#163] Closing SWF file after loading
-- other minor fixes
-
-## [1.6.3 update 2] - 2013-06-21
-### Changed
-- [#149] Ifs with empty onTrue branches now inverted
-
-### Fixed
-- [#150] Long line restriction removed
-
-## [1.6.3 update 1] - 2013-06-21
-### Fixed
-- Memory limit decreased - FFDec was not working on 32 bit JVM.
-
-## [1.6.3] - 2013-06-20
-### Changed
-- Parallel SpeedUp can be disabled in menu
-- Better loop detection
-
-### Fixed
-- [#119] Replacements file not found issue
-- [#101] AS1/2 postincrement fix
-- [#114],[#116],[#135],[#141] Fixed loop detection
-- [#102] Fixed loop highlighting in export
-- [#124] Flash player file path detection
-- [#128] Improved imports
-- [#135] CommentItem fix
-- [#129],[#131] Better deobfuscation
-- [#104] AS3 inc/dec local deobfuscation fix
-- [#113],[#133],[#140] Memory limit increased
-
-## [1.6.2] - 2013-06-09
-### Added
-- New loop detection algorithm
-
-### Changed
-- [#108] - Faster loading and decompiling (Parallelism)
-- Improved Internal flash viewer - shapes and morphshapes
-
-### Fixed
-- Ternar operator fix
-- [#102] Fixed Shapes to FLA export
-- AS1/2 class detection fix
-- [#105],[#104],[#101] fixed via new loop detection
-
-## [1.6.1] - 2013-06-03
-### Added
-- Internal Flash Viewer - preview of flash parts (shapes,sprites,frames) without need of Flash Player. (Used on nonWindows platforms by default)
-- [#109], [#106], [#107] some code improvements
-
-### Changed
-- Application needs Java 1.7 to run
-
-### Removed
-- Support for Java before 1.7
-
-### Fixed
-- [#102], [#110] AS3: Class highlight fix
-- [#103] AS3:Fixed setslot handling
-- [#104] AS3:Inc/Declocal nullpointer fix
-- [#104] Multiple conditions in loop fix
-- [#111] AS3:Object literal truncates line
-- [#105] Better do while..break handling
-- loop fixes
-
-## [1.6.0 update 1] - 2013-05-25
-### Added
-- better FLA export
-
-### Fixed
-- Many FLA export related bugs (like [#96])
-- [#98] Empty initializers do not cause empty lines now
-- [#99] small logging issues
-- [#100] large obfuscated code support
-
-## [1.6.0] - 2013-05-20
-### Added
-- Export to FLA (Experimental BETA!)
-- [#85] Search text in all ActionScripts
-- SWF 11 support
-
-### Fixed
-- [#79] ActionStartDrag constraint fix
-- [#92] Inversed GreaterThan/LessThan
-- [#93] AS1/2 fixed switch detection
-- [#94] AS1/2 ActionTry - register cast fix
-- [#95] Better script end handling
-
-## [1.5.2] - 2013-05-05
-### Added
-- Improved automatic update system (changes log).
-- Handling script traits as separate objects.
-- [#86] open/save file dialog now accepts absolute paths in quotes
-
-### Fixed
-- [#87] Not displaying image changes in DefineBitsLossLess1 & 2
-- [#88] Fixed graph building
-- [#89] AS3: bracket in property name lead to missing dot
-- [#82] printgraph issue
-
-## [1.5.1 update 1] - 2013-05-04
-### Added
-- Exporting texts via commandline
-- Exporting all via commandline
-
-### Fixed
-- DefineText2 color parameter
-- AS3 GetSlot,SetSlot
-- [#78],[#81],[#82],[#84] Fixed deobfuscation, exceptions during printgraph,...
-- [#83] Fixed images transparency (zlib fix)
-- Fixed graphparts with only jump in it (obfuscators)
-- MORPHGRADIENT FIX
-- Trasparency in DefineBitsJPEG3 and 4
-- Displaying shapes,morphshapes and sprites with bitmaps
-
-## [1.5.1] - 2013-05-01
-### Added
-- Support for larger switches (10+cases)
-- Editing text tags
-- [#65] Exporting text tags
-- Removing sprites
-- Replacing images
-
-### Fixed
-- DefineMorphShape2 fix
-- [#79] - AS1/2 class detection fix, wrong printgraph fix
-- [#78] - script trait slots fix
-
-## [1.5.0 update 1] - 2013-04-21
-### Fixed
-- Automatic deobfuscation config defaulted to Off for AS1/2.
-
-## [1.5.0] - 2013-04-20
-### Added
-- Direct editing of ActionScript 1/2 code (Beta)
-- AS1/2: ifFrameLoaded support
-- Automatic deobfuscation can be disabled in the menu
-- [#48] - Decompile only specified class (commandline option)
-- [#53] - AS3: Displaying multiname indices in trait detail, displaying method indices
-- [#66] - Decompressing LZMA via commandline
-- [#68] - Exporting DefineBinaryData tags, assigning class names to characters (SymbolClass tag)
-- [#69] - DoABC vs DoABCDefine tags decompilation
-- [#75] - Comma separator in while/do..while conditions, better if..return handling
-- AS1/2: parsing NaN,Infinity value (Fix for [#73])
-
-### Changed
-- New icons (edit/save/cancel and main menu)
-
-### Fixed
-- [#62] - Errors on not defined character tags (import tag)
-- [#72] - First ternary operator expression was always true
-- Fixed many deobfuscation related bugs
-
-## [1.4.3 update 2] - 2013-04-10
-### Fixed
-- [#64] - AS1/2 Resolving registers in ActionDefineFunction2 (super,this,...and parameters shown as registerxx)
-- Try to fix lib/FlashPlayer.exe issue
-
-## [1.4.3 update 1] - 2013-04-06
-### Fixed
-- [#38] - Indentation in const/var initializers, missing semicolon
-- [#56] - Test output left in last release
-- [#57] - Unknown instructions now do not log an exception (obfuscators do this)
-- [#58] - Index out of bounds exception fix on methodinfo indices in imports detection.
-- AS3 loops fix
-- While true fix
-
-## [1.4.3] - 2013-04-04
-### Added
-- AS1/2 Better deobfuscation
-
-### Fixed
-- [#45] - Unicode characters fix
-- [#50] - AS1/2 Function body deobfuscation fix
-- [#51] - Displaying java class names instead of expressions
-- [#52] - AS1/2 Better constantpool detection (deobfuscation)
-- [#38] - AS3 indentation in initialized const/var value for newobject
-- Fixed ImportAssets2 tag id
-
-## [1.4.2 update 1] - 2013-03-25
-### Fixed
-- [#47] - wrong AS3 deobfuscation
-- AS3 deobfuscation issues
-- AS3 switch
-
-## [1.4.2] - 2013-03-24
-### Added
-- [#42] - Displaying code as hex
-- AS1/2: Renaming identifiers (deobfuscation)
-- AS1/2,AS3: Better deobfuscation
-- Storing configuration to user home
-- Installer for Windows systems
-
-### Changed
-- Graph button changed to icon.
-
-### Fixed
-- [#39] - AS1/2 NewMethod..Pop fix
-- [#40] - No logging + For..in..return decompilation
-- [#44] - DefineFont2 fix
-- [#36] - Multiname with invalid index
-- [#43] - Ternary operator and more
-- [#46] - Ifs with empty branches got ignored
-- [#3] - Ignoring unknown opcodes
-- Logging exceptions during export
-
-## [1.4.1] - 2013-03-10
-### Added
-- Exporting sounds
-- Better AS1/2 deobfuscation (disassembly & decompilation)
-
-### Fixed
-- Exporting only first 1000 frames of the movie
-- Decompiled code was not refreshed on AS1/2 changes
-- Application no longer creates empty directories on export
-
-## [1.4.0 update 1] - 2013-03-04
-### Fixed
-- [#37] - AS3: Reversed loop conditions
-
-## [1.4.0] - 2013-03-03
-### Added
-- AS3: ignoring return void at the end of methods
-- New icons - Silk icons
-- AS3: Traits list sort button
-- Better Graph display
-- Frames view
-- Exporting of movies (No audio)
-- Some AS3 related Tests
-- Homepage & Donate link in the menu
-
-### Changed
-- Tree view instead of tabs
-- AS1/2 and AS3 now share same decompiling method.
-
-### Fixed
-- [#34] - Reversed loop conditions
-- [#35] - Fixed unicode strings (Japanese)
-
-## [1.3.1] - 2013-02-23
-### Changed
-- Flash player no longer uses SWT library
-
-### Fixed
-- [#32] - AS2: Action255 bug
-- [#31] - Erorrneous tags are now ignored
-- DefineBitsLossLess 1&2 on 8bit colormapped images
-
-## [1.3.0] - 2013-02-17
-### Added
-- Decompilation is more resistant to obfuscation
-- Shapes SVG export
-- AS2: Decompiling classes & interfaces
-- Click&go feature - clicking actionscript source displays appropriate P-code instruction and vice-versa (both AS1/2 and AS3)
-- AS3: Deobfuscation menu
-- Graph button for displaying code flow Graph
-
-### Changed
-- Complete new decompiling method in both AS1/2 and AS3
-- Application renamed from "JP ActionScript Decompiler" to "JPEXS Free Flash Decompiler".
-- To edit source, Edit button must be pressed first (Due to click&go feature)
-
-### Fixed
-- AS3: Method info editor fixed
-- Edittext & Button displaying
-
-## [1.2.0] - 2013-01-19
-### Added
-- Displaying various SWF objects (shapes, sprites,...) with flash player library (Windows only, sorry).
-- Images display and export
-- AS2: Exporting selection
-- Progressbar during loading
-
-### Changed
-- One merged window for AS1/2 and 3.
-- Updated icons
-
-### Fixed
-- AS3: xml attrib, switch in anonymous function (in AS2 too)
-
-## [1.1.0] - 2013-01-02
-### Added
-- Checking for updates
-- AS2: Exporting
-- AS3: Decompiling whole scripts instead of just classes
-- AS3: Exporting selected scripts
-- AS3: Script search bar
-- AS3: List of DoABCTags now has default "- all -" item
-- AS3: Better imports, use namespaces
-- AS3: XML related instructions
-- AS3: Anonymous functions with names
-- AS3: Better initialization of const values
-- Logging exceptions to log.txt file
-
-### Fixed
-- AS3: set_local..get_local, dup, chained assignments, highlighting, callsupervoid, typenames, with statement, loops
-
-## [1.0.1] - 2012-12-26
-### Added
-- AS3: Runtime namespace resolving
-- AS3: Arguments variable
-- AS3: Better recognizing Pre/Post Increments/Decrements
-- AS3: Better declarations
-
-### Fixed
-- AS3: Fixed static variables
-
-## [1.0.0] - 2012-12-24
-### Added
-- Support for LZMA compressed files
-- AS3: Detecting local register types for declaration.
-- AS3: Displaying inline functions
-- AS3: Last save/open dir is remembered
-- AS3: Better usage detection for multinames
-- AS3: Commandline arguments for exporting
-- AS3: Better chained assignments
-- AS2: FSCommand2 instruction support
-- Proxy: Mimetype application/octet-stream added
-- Added executable for Windows users.
-
-### Changed
-- AS3: GUI - Constants tab moved to the top
-- AS3: Deobfuscation is now optional, can be accessed via menu
-
-### Fixed
-- AS3: rest parameter, for..in, fail on large classes (due to sub limiter)
-- Other minor fixes
-
-## [beta 1] - 2011-07-30
-### Added
-- AS3: Automatic computing method body parameters (EXPERIMENTAL)
-- AS3: Editing return type of methods
-- AS3: Editing type and default value for variables/constants (Slot/Const traits)
-- AS1/2: Few enhancements
-- About dialog
-
-### Changed
-- Gui: Updated Icons
-
-### Fixed
-- AS 1/2: Fixed large bug causing Ifs to not decompile properly
-- Proxy: Some minor fixes
-
-## [alpha 10] - 2011-07-13
-### Added
-- AS3:Highlighting actual line
-- AS3:Completing instruction names via Ctrl+Space
-- AS3:Editing method parameters, method body parameters via tab panel
-- AS3:ByteCode minor_version 17 supported - decimal datatypes
-- AS3:Local variables and method parameters take name from debug information if present
-- AS3:Automatic renaming of classes/methods when obfuscated names
-- AS3:Better error messages (When cannot decompile obfuscated code)
-
-### Fixed
-- AS3:Fixed Vector datatypes (TypeName multiname, applytype instruction)
-- AS3:Hilighting fixes
-- AS3:Fixed decrement/increment statements decompilation
-- AS3:Decompiler now adds variable declarations on the beginning of decompiled method
-- AS3:Try/catch statements fixed when debug information present
-- AS3:Fixed for each statements
-- AS3:Other minor fixes
-
-## [alpha 9] - 2011-07-02
-### Added
-- AS3: Added disassembling of some new types of instructions
-- AS3: Exporting source as PCode
-
-### Fixed
-- AS3: Many other bugfixes...
-
-## [alpha 8] - 2010-09-19
-### Added
-- AS3: Editing exceptions
-- AS3: Finding usage of multinames from constant table
-
-### Changed
-- AS1/2: Better GUI
-- AS1/2: Better decompiling of Ifs, For..in
-
-## [alpha 7] - 2010-09-04
-### Added
-- Initial public release
-
-[Unreleased]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version9.0.0...dev
-[9.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version8.0.1...version9.0.0
-[8.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version8.0.0...version8.0.1
-[8.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.1.2...version8.0.0
-[7.1.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.1.1...version7.1.2
-[7.1.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.1.0...version7.1.1
-[7.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.0.1...version7.1.0
-[7.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.0.0...version7.0.1
-[7.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.1.1...version7.0.0
-[6.1.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.1.0...version6.1.1
-[6.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.0.2...version6.1.0
-[6.0.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.0.1...version6.0.2
-[6.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.0.0...version6.0.1
-[6.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.3.0...version6.0.0
-[5.3.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.2.0...version5.3.0
-[5.2.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.1.0...version5.2.0
-[5.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.0.2...version5.1.0
-[5.0.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.0.1...version5.0.2
-[5.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.0.0...version5.0.1
-[5.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.1.1...version5.0.0
-[4.1.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.1.0...version4.1.1
-[4.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.5...version4.1.0
-[4.0.5]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.4...version4.0.5
-[4.0.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.3...version4.0.4
-[4.0.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.2...version4.0.3
-[4.0.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.1...version4.0.2
-[4.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.0...version4.0.1
-[4.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version3.0.0...version4.0.0
-[3.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.4...version3.0.0
-[2.1.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.3...version2.1.4
-[2.1.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.2...version2.1.3
-[2.1.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.1...version2.1.2
-[2.1.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.0u2...version2.1.1
-[2.1.0 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.0u1...version2.1.0u2
-[2.1.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.0...version2.1.0u1
-[2.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.0.1u2...version2.1.0
-[2.0.1 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.0.1u1...version2.0.1u2
-[2.0.1 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.0.1...version2.0.1u1
-[2.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.0.0...version2.0.1
-[2.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.8.1u1...version2.0.0
-[1.8.1 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.8.1...version1.8.1u1
-[1.8.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.8.0u1...version1.8.1
-[1.8.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.8.0...version1.8.0u1
-[1.8.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.4u1...version1.8.0
-[1.7.4 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.4...version1.7.4u1
-[1.7.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.3u2...version1.7.4
-[1.7.3 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.3u1...version1.7.3u2
-[1.7.3 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.3...version1.7.3u1
-[1.7.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.2u2...version1.7.3
-[1.7.2 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.2u1...version1.7.2u2
-[1.7.2 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.2...version1.7.2u1
-[1.7.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.1...version1.7.2
-[1.7.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.0u1...version1.7.1
-[1.7.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.0...version1.7.0u1
-[1.7.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.7...version1.7.0
-[1.6.7]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.6u2...version1.6.7
-[1.6.6 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.6u1...version1.6.6u2
-[1.6.6 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.6...version1.6.6u1
-[1.6.6]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.5u1...version1.6.6
-[1.6.5 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.5...version1.6.5u1
-[1.6.5]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.4u1...version1.6.5
-[1.6.4 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.4...version1.6.4u1
-[1.6.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.3u2...version1.6.4
-[1.6.3 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.3u1...version1.6.3u2
-[1.6.3 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.3...version1.6.3u1
-[1.6.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.2...version1.6.3
-[1.6.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.1...version1.6.2
-[1.6.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.0u1...version1.6.1
-[1.6.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.0...version1.6.0u1
-[1.6.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.2...version1.6.0
-[1.5.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.1u1...version1.5.2
-[1.5.1 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.1...version1.5.1u1
-[1.5.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.0u1...version1.5.1
-[1.5.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.0...version1.5.0u1
-[1.5.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.3u2...version1.5.0
-[1.4.3 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.3u1...version1.4.3u2
-[1.4.3 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.3...version1.4.3u1
-[1.4.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.2u1...version1.4.3
-[1.4.2 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.2...version1.4.2u1
-[1.4.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.1...version1.4.2
-[1.4.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.0u1...version1.4.1
-[1.4.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.0...version1.4.0u1
-[1.4.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.3.1...version1.4.0
-[1.3.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.3.0...version1.3.1
-[1.3.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.2.0...version1.3.0
-[1.2.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.1.0...version1.2.0
-[1.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.0.1...version1.1.0
-[1.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.0.0...version1.0.1
-[1.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/beta1...version1.0.0
-[beta 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha10...beta1
-[alpha 10]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha9...alpha10
-[alpha 9]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha8...alpha9
-[alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8
-[alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7
-[#1156]: https://www.free-decompiler.com/flash/issues/1156
-[#1171]: https://www.free-decompiler.com/flash/issues/1171
-[#1170]: https://www.free-decompiler.com/flash/issues/1170
-[#1241]: https://www.free-decompiler.com/flash/issues/1241
-[#1162]: https://www.free-decompiler.com/flash/issues/1162
-[#1199]: https://www.free-decompiler.com/flash/issues/1199
-[#1151]: https://www.free-decompiler.com/flash/issues/1151
-[#1128]: https://www.free-decompiler.com/flash/issues/1128
-[#1163]: https://www.free-decompiler.com/flash/issues/1163
-[#1172]: https://www.free-decompiler.com/flash/issues/1172
-[#1174]: https://www.free-decompiler.com/flash/issues/1174
-[#1183]: https://www.free-decompiler.com/flash/issues/1183
-[#1193]: https://www.free-decompiler.com/flash/issues/1193
-[#1200]: https://www.free-decompiler.com/flash/issues/1200
-[#1198]: https://www.free-decompiler.com/flash/issues/1198
-[#1205]: https://www.free-decompiler.com/flash/issues/1205
-[#1194]: https://www.free-decompiler.com/flash/issues/1194
-[#1210]: https://www.free-decompiler.com/flash/issues/1210
-[#1217]: https://www.free-decompiler.com/flash/issues/1217
-[#1244]: https://www.free-decompiler.com/flash/issues/1244
-[#1247]: https://www.free-decompiler.com/flash/issues/1247
-[#1236]: https://www.free-decompiler.com/flash/issues/1236
-[#1251]: https://www.free-decompiler.com/flash/issues/1251
-[#1265]: https://www.free-decompiler.com/flash/issues/1265
-[#1268]: https://www.free-decompiler.com/flash/issues/1268
-[#1161]: https://www.free-decompiler.com/flash/issues/1161
-[#1118]: https://www.free-decompiler.com/flash/issues/1118
-[#409]: https://www.free-decompiler.com/flash/issues/409
-[#1132]: https://www.free-decompiler.com/flash/issues/1132
-[#1134]: https://www.free-decompiler.com/flash/issues/1134
-[#1121]: https://www.free-decompiler.com/flash/issues/1121
-[#1052]: https://www.free-decompiler.com/flash/issues/1052
-[#1145]: https://www.free-decompiler.com/flash/issues/1145
-[#758]: https://www.free-decompiler.com/flash/issues/758
-[#1096]: https://www.free-decompiler.com/flash/issues/1096
-[#1104]: https://www.free-decompiler.com/flash/issues/1104
-[#1107]: https://www.free-decompiler.com/flash/issues/1107
-[#1106]: https://www.free-decompiler.com/flash/issues/1106
-[#1113]: https://www.free-decompiler.com/flash/issues/1113
-[#1075]: https://www.free-decompiler.com/flash/issues/1075
-[#1127]: https://www.free-decompiler.com/flash/issues/1127
-[#1103]: https://www.free-decompiler.com/flash/issues/1103
-[#1133]: https://www.free-decompiler.com/flash/issues/1133
-[#1135]: https://www.free-decompiler.com/flash/issues/1135
-[#1138]: https://www.free-decompiler.com/flash/issues/1138
-[#1139]: https://www.free-decompiler.com/flash/issues/1139
-[#930]: https://www.free-decompiler.com/flash/issues/930
-[#1137]: https://www.free-decompiler.com/flash/issues/1137
-[#1144]: https://www.free-decompiler.com/flash/issues/1144
-[#1147]: https://www.free-decompiler.com/flash/issues/1147
-[#1148]: https://www.free-decompiler.com/flash/issues/1148
-[#1152]: https://www.free-decompiler.com/flash/issues/1152
-[#1154]: https://www.free-decompiler.com/flash/issues/1154
-[#116]: https://www.free-decompiler.com/flash/issues/116
-[#1070]: https://www.free-decompiler.com/flash/issues/1070
-[#1098]: https://www.free-decompiler.com/flash/issues/1098
-[#1033]: https://www.free-decompiler.com/flash/issues/1033
-[#1083]: https://www.free-decompiler.com/flash/issues/1083
-[#1091]: https://www.free-decompiler.com/flash/issues/1091
-[#1076]: https://www.free-decompiler.com/flash/issues/1076
-[#1068]: https://www.free-decompiler.com/flash/issues/1068
-[#1063]: https://www.free-decompiler.com/flash/issues/1063
-[#1019]: https://www.free-decompiler.com/flash/issues/1019
-[#1016]: https://www.free-decompiler.com/flash/issues/1016
-[#1010]: https://www.free-decompiler.com/flash/issues/1010
-[#1008]: https://www.free-decompiler.com/flash/issues/1008
-[#1004]: https://www.free-decompiler.com/flash/issues/1004
-[#933]: https://www.free-decompiler.com/flash/issues/933
-[#1062]: https://www.free-decompiler.com/flash/issues/1062
-[#418]: https://www.free-decompiler.com/flash/issues/418
-[#1047]: https://www.free-decompiler.com/flash/issues/1047
-[#812]: https://www.free-decompiler.com/flash/issues/812
-[#1056]: https://www.free-decompiler.com/flash/issues/1056
-[#1057]: https://www.free-decompiler.com/flash/issues/1057
-[#991]: https://www.free-decompiler.com/flash/issues/991
-[#689]: https://www.free-decompiler.com/flash/issues/689
-[#1060]: https://www.free-decompiler.com/flash/issues/1060
-[#1037]: https://www.free-decompiler.com/flash/issues/1037
-[#489]: https://www.free-decompiler.com/flash/issues/489
-[#1007]: https://www.free-decompiler.com/flash/issues/1007
-[#1044]: https://www.free-decompiler.com/flash/issues/1044
-[#947]: https://www.free-decompiler.com/flash/issues/947
-[#953]: https://www.free-decompiler.com/flash/issues/953
-[#954]: https://www.free-decompiler.com/flash/issues/954
-[#950]: https://www.free-decompiler.com/flash/issues/950
-[#945]: https://www.free-decompiler.com/flash/issues/945
-[#957]: https://www.free-decompiler.com/flash/issues/957
-[#956]: https://www.free-decompiler.com/flash/issues/956
-[#968]: https://www.free-decompiler.com/flash/issues/968
-[#978]: https://www.free-decompiler.com/flash/issues/978
-[#955]: https://www.free-decompiler.com/flash/issues/955
-[#966]: https://www.free-decompiler.com/flash/issues/966
-[#999]: https://www.free-decompiler.com/flash/issues/999
-[#1000]: https://www.free-decompiler.com/flash/issues/1000
-[#1017]: https://www.free-decompiler.com/flash/issues/1017
-[#1030]: https://www.free-decompiler.com/flash/issues/1030
-[#949]: https://www.free-decompiler.com/flash/issues/949
-[#944]: https://www.free-decompiler.com/flash/issues/944
-[#939]: https://www.free-decompiler.com/flash/issues/939
-[#942]: https://www.free-decompiler.com/flash/issues/942
-[#952]: https://www.free-decompiler.com/flash/issues/952
-[#858]: https://www.free-decompiler.com/flash/issues/858
-[#905]: https://www.free-decompiler.com/flash/issues/905
-[#920]: https://www.free-decompiler.com/flash/issues/920
-[#921]: https://www.free-decompiler.com/flash/issues/921
-[#924]: https://www.free-decompiler.com/flash/issues/924
-[#895]: https://www.free-decompiler.com/flash/issues/895
-[#884]: https://www.free-decompiler.com/flash/issues/884
-[#899]: https://www.free-decompiler.com/flash/issues/899
-[#903]: https://www.free-decompiler.com/flash/issues/903
-[#855]: https://www.free-decompiler.com/flash/issues/855
-[#850]: https://www.free-decompiler.com/flash/issues/850
-[#832]: https://www.free-decompiler.com/flash/issues/832
-[#904]: https://www.free-decompiler.com/flash/issues/904
-[#910]: https://www.free-decompiler.com/flash/issues/910
-[#922]: https://www.free-decompiler.com/flash/issues/922
-[#916]: https://www.free-decompiler.com/flash/issues/916
-[#938]: https://www.free-decompiler.com/flash/issues/938
-[#897]: https://www.free-decompiler.com/flash/issues/897
-[#470]: https://www.free-decompiler.com/flash/issues/470
-[#877]: https://www.free-decompiler.com/flash/issues/877
-[#878]: https://www.free-decompiler.com/flash/issues/878
-[#845]: https://www.free-decompiler.com/flash/issues/845
-[#883]: https://www.free-decompiler.com/flash/issues/883
-[#882]: https://www.free-decompiler.com/flash/issues/882
-[#760]: https://www.free-decompiler.com/flash/issues/760
-[#887]: https://www.free-decompiler.com/flash/issues/887
-[#842]: https://www.free-decompiler.com/flash/issues/842
-[#841]: https://www.free-decompiler.com/flash/issues/841
-[#772]: https://www.free-decompiler.com/flash/issues/772
-[#762]: https://www.free-decompiler.com/flash/issues/762
-[#862]: https://www.free-decompiler.com/flash/issues/862
-[#865]: https://www.free-decompiler.com/flash/issues/865
-[#613]: https://www.free-decompiler.com/flash/issues/613
-[#868]: https://www.free-decompiler.com/flash/issues/868
-[#713]: https://www.free-decompiler.com/flash/issues/713
-[#807]: https://www.free-decompiler.com/flash/issues/807
-[#728]: https://www.free-decompiler.com/flash/issues/728
-[#857]: https://www.free-decompiler.com/flash/issues/857
-[#860]: https://www.free-decompiler.com/flash/issues/860
-[#824]: https://www.free-decompiler.com/flash/issues/824
-[#809]: https://www.free-decompiler.com/flash/issues/809
-[#805]: https://www.free-decompiler.com/flash/issues/805
-[#825]: https://www.free-decompiler.com/flash/issues/825
-[#737]: https://www.free-decompiler.com/flash/issues/737
-[#350]: https://www.free-decompiler.com/flash/issues/350
-[#814]: https://www.free-decompiler.com/flash/issues/814
-[#816]: https://www.free-decompiler.com/flash/issues/816
-[#835]: https://www.free-decompiler.com/flash/issues/835
-[#836]: https://www.free-decompiler.com/flash/issues/836
-[#848]: https://www.free-decompiler.com/flash/issues/848
-[#817]: https://www.free-decompiler.com/flash/issues/817
-[#849]: https://www.free-decompiler.com/flash/issues/849
-[#852]: https://www.free-decompiler.com/flash/issues/852
-[#837]: https://www.free-decompiler.com/flash/issues/837
-[#811]: https://www.free-decompiler.com/flash/issues/811
-[#745]: https://www.free-decompiler.com/flash/issues/745
-[#803]: https://www.free-decompiler.com/flash/issues/803
-[#738]: https://www.free-decompiler.com/flash/issues/738
-[#742]: https://www.free-decompiler.com/flash/issues/742
-[#747]: https://www.free-decompiler.com/flash/issues/747
-[#749]: https://www.free-decompiler.com/flash/issues/749
-[#752]: https://www.free-decompiler.com/flash/issues/752
-[#753]: https://www.free-decompiler.com/flash/issues/753
-[#759]: https://www.free-decompiler.com/flash/issues/759
-[#766]: https://www.free-decompiler.com/flash/issues/766
-[#768]: https://www.free-decompiler.com/flash/issues/768
-[#773]: https://www.free-decompiler.com/flash/issues/773
-[#776]: https://www.free-decompiler.com/flash/issues/776
-[#783]: https://www.free-decompiler.com/flash/issues/783
-[#785]: https://www.free-decompiler.com/flash/issues/785
-[#787]: https://www.free-decompiler.com/flash/issues/787
-[#788]: https://www.free-decompiler.com/flash/issues/788
-[#790]: https://www.free-decompiler.com/flash/issues/790
-[#794]: https://www.free-decompiler.com/flash/issues/794
-[#798]: https://www.free-decompiler.com/flash/issues/798
-[#800]: https://www.free-decompiler.com/flash/issues/800
-[#676]: https://www.free-decompiler.com/flash/issues/676
-[#734]: https://www.free-decompiler.com/flash/issues/734
-[#687]: https://www.free-decompiler.com/flash/issues/687
-[#709]: https://www.free-decompiler.com/flash/issues/709
-[#732]: https://www.free-decompiler.com/flash/issues/732
-[#730]: https://www.free-decompiler.com/flash/issues/730
-[#735]: https://www.free-decompiler.com/flash/issues/735
-[#722]: https://www.free-decompiler.com/flash/issues/722
-[#725]: https://www.free-decompiler.com/flash/issues/725
-[#715]: https://www.free-decompiler.com/flash/issues/715
-[#635]: https://www.free-decompiler.com/flash/issues/635
-[#726]: https://www.free-decompiler.com/flash/issues/726
-[#716]: https://www.free-decompiler.com/flash/issues/716
-[#717]: https://www.free-decompiler.com/flash/issues/717
-[#718]: https://www.free-decompiler.com/flash/issues/718
-[#720]: https://www.free-decompiler.com/flash/issues/720
-[#719]: https://www.free-decompiler.com/flash/issues/719
-[#723]: https://www.free-decompiler.com/flash/issues/723
-[#288]: https://www.free-decompiler.com/flash/issues/288
-[#677]: https://www.free-decompiler.com/flash/issues/677
-[#389]: https://www.free-decompiler.com/flash/issues/389
-[#701]: https://www.free-decompiler.com/flash/issues/701
-[#707]: https://www.free-decompiler.com/flash/issues/707
-[#302]: https://www.free-decompiler.com/flash/issues/302
-[#685]: https://www.free-decompiler.com/flash/issues/685
-[#698]: https://www.free-decompiler.com/flash/issues/698
-[#710]: https://www.free-decompiler.com/flash/issues/710
-[#711]: https://www.free-decompiler.com/flash/issues/711
-[#681]: https://www.free-decompiler.com/flash/issues/681
-[#688]: https://www.free-decompiler.com/flash/issues/688
-[#691]: https://www.free-decompiler.com/flash/issues/691
-[#524]: https://www.free-decompiler.com/flash/issues/524
-[#663]: https://www.free-decompiler.com/flash/issues/663
-[#702]: https://www.free-decompiler.com/flash/issues/702
-[#539]: https://www.free-decompiler.com/flash/issues/539
-[#650]: https://www.free-decompiler.com/flash/issues/650
-[#680]: https://www.free-decompiler.com/flash/issues/680
-[#649]: https://www.free-decompiler.com/flash/issues/649
-[#656]: https://www.free-decompiler.com/flash/issues/656
-[#661]: https://www.free-decompiler.com/flash/issues/661
-[#664]: https://www.free-decompiler.com/flash/issues/664
-[#668]: https://www.free-decompiler.com/flash/issues/668
-[#674]: https://www.free-decompiler.com/flash/issues/674
-[#675]: https://www.free-decompiler.com/flash/issues/675
-[#632]: https://www.free-decompiler.com/flash/issues/632
-[#651]: https://www.free-decompiler.com/flash/issues/651
-[#678]: https://www.free-decompiler.com/flash/issues/678
-[#672]: https://www.free-decompiler.com/flash/issues/672
-[#684]: https://www.free-decompiler.com/flash/issues/684
-[#647]: https://www.free-decompiler.com/flash/issues/647
-[#648]: https://www.free-decompiler.com/flash/issues/648
-[#612]: https://www.free-decompiler.com/flash/issues/612
-[#623]: https://www.free-decompiler.com/flash/issues/623
-[#624]: https://www.free-decompiler.com/flash/issues/624
-[#627]: https://www.free-decompiler.com/flash/issues/627
-[#640]: https://www.free-decompiler.com/flash/issues/640
-[#595]: https://www.free-decompiler.com/flash/issues/595
-[#592]: https://www.free-decompiler.com/flash/issues/592
-[#585]: https://www.free-decompiler.com/flash/issues/585
-[#578]: https://www.free-decompiler.com/flash/issues/578
-[#501]: https://www.free-decompiler.com/flash/issues/501
-[#616]: https://www.free-decompiler.com/flash/issues/616
-[#559]: https://www.free-decompiler.com/flash/issues/559
-[#401]: https://www.free-decompiler.com/flash/issues/401
-[#593]: https://www.free-decompiler.com/flash/issues/593
-[#594]: https://www.free-decompiler.com/flash/issues/594
-[#579]: https://www.free-decompiler.com/flash/issues/579
-[#428]: https://www.free-decompiler.com/flash/issues/428
-[#337]: https://www.free-decompiler.com/flash/issues/337
-[#584]: https://www.free-decompiler.com/flash/issues/584
-[#576]: https://www.free-decompiler.com/flash/issues/576
-[#250]: https://www.free-decompiler.com/flash/issues/250
-[#580]: https://www.free-decompiler.com/flash/issues/580
-[#510]: https://www.free-decompiler.com/flash/issues/510
-[#583]: https://www.free-decompiler.com/flash/issues/583
-[#586]: https://www.free-decompiler.com/flash/issues/586
-[#574]: https://www.free-decompiler.com/flash/issues/574
-[#570]: https://www.free-decompiler.com/flash/issues/570
-[#563]: https://www.free-decompiler.com/flash/issues/563
-[#561]: https://www.free-decompiler.com/flash/issues/561
-[#509]: https://www.free-decompiler.com/flash/issues/509
-[#433]: https://www.free-decompiler.com/flash/issues/433
-[#557]: https://www.free-decompiler.com/flash/issues/557
-[#556]: https://www.free-decompiler.com/flash/issues/556
-[#504]: https://www.free-decompiler.com/flash/issues/504
-[#529]: https://www.free-decompiler.com/flash/issues/529
-[#538]: https://www.free-decompiler.com/flash/issues/538
-[#537]: https://www.free-decompiler.com/flash/issues/537
-[#540]: https://www.free-decompiler.com/flash/issues/540
-[#387]: https://www.free-decompiler.com/flash/issues/387
-[#552]: https://www.free-decompiler.com/flash/issues/552
-[#494]: https://www.free-decompiler.com/flash/issues/494
-[#513]: https://www.free-decompiler.com/flash/issues/513
-[#262]: https://www.free-decompiler.com/flash/issues/262
-[#499]: https://www.free-decompiler.com/flash/issues/499
-[#508]: https://www.free-decompiler.com/flash/issues/508
-[#305]: https://www.free-decompiler.com/flash/issues/305
-[#312]: https://www.free-decompiler.com/flash/issues/312
-[#503]: https://www.free-decompiler.com/flash/issues/503
-[#304]: https://www.free-decompiler.com/flash/issues/304
-[#306]: https://www.free-decompiler.com/flash/issues/306
-[#507]: https://www.free-decompiler.com/flash/issues/507
-[#424]: https://www.free-decompiler.com/flash/issues/424
-[#425]: https://www.free-decompiler.com/flash/issues/425
-[#478]: https://www.free-decompiler.com/flash/issues/478
-[#485]: https://www.free-decompiler.com/flash/issues/485
-[#517]: https://www.free-decompiler.com/flash/issues/517
-[#518]: https://www.free-decompiler.com/flash/issues/518
-[#361]: https://www.free-decompiler.com/flash/issues/361
-[#392]: https://www.free-decompiler.com/flash/issues/392
-[#516]: https://www.free-decompiler.com/flash/issues/516
-[#495]: https://www.free-decompiler.com/flash/issues/495
-[#496]: https://www.free-decompiler.com/flash/issues/496
-[#299]: https://www.free-decompiler.com/flash/issues/299
-[#303]: https://www.free-decompiler.com/flash/issues/303
-[#324]: https://www.free-decompiler.com/flash/issues/324
-[#346]: https://www.free-decompiler.com/flash/issues/346
-[#371]: https://www.free-decompiler.com/flash/issues/371
-[#426]: https://www.free-decompiler.com/flash/issues/426
-[#457]: https://www.free-decompiler.com/flash/issues/457
-[#458]: https://www.free-decompiler.com/flash/issues/458
-[#460]: https://www.free-decompiler.com/flash/issues/460
-[#462]: https://www.free-decompiler.com/flash/issues/462
-[#463]: https://www.free-decompiler.com/flash/issues/463
-[#465]: https://www.free-decompiler.com/flash/issues/465
-[#466]: https://www.free-decompiler.com/flash/issues/466
-[#369]: https://www.free-decompiler.com/flash/issues/369
-[#390]: https://www.free-decompiler.com/flash/issues/390
-[#453]: https://www.free-decompiler.com/flash/issues/453
-[#459]: https://www.free-decompiler.com/flash/issues/459
-[#461]: https://www.free-decompiler.com/flash/issues/461
-[#451]: https://www.free-decompiler.com/flash/issues/451
-[#454]: https://www.free-decompiler.com/flash/issues/454
-[#455]: https://www.free-decompiler.com/flash/issues/455
-[#474]: https://www.free-decompiler.com/flash/issues/474
-[#477]: https://www.free-decompiler.com/flash/issues/477
-[#481]: https://www.free-decompiler.com/flash/issues/481
-[#484]: https://www.free-decompiler.com/flash/issues/484
-[#493]: https://www.free-decompiler.com/flash/issues/493
-[#365]: https://www.free-decompiler.com/flash/issues/365
-[#366]: https://www.free-decompiler.com/flash/issues/366
-[#429]: https://www.free-decompiler.com/flash/issues/429
-[#447]: https://www.free-decompiler.com/flash/issues/447
-[#354]: https://www.free-decompiler.com/flash/issues/354
-[#438]: https://www.free-decompiler.com/flash/issues/438
-[#436]: https://www.free-decompiler.com/flash/issues/436
-[#446]: https://www.free-decompiler.com/flash/issues/446
-[#427]: https://www.free-decompiler.com/flash/issues/427
-[#405]: https://www.free-decompiler.com/flash/issues/405
-[#420]: https://www.free-decompiler.com/flash/issues/420
-[#421]: https://www.free-decompiler.com/flash/issues/421
-[#430]: https://www.free-decompiler.com/flash/issues/430
-[#397]: https://www.free-decompiler.com/flash/issues/397
-[#431]: https://www.free-decompiler.com/flash/issues/431
-[#169]: https://www.free-decompiler.com/flash/issues/169
-[#335]: https://www.free-decompiler.com/flash/issues/335
-[#404]: https://www.free-decompiler.com/flash/issues/404
-[#407]: https://www.free-decompiler.com/flash/issues/407
-[#399]: https://www.free-decompiler.com/flash/issues/399
-[#400]: https://www.free-decompiler.com/flash/issues/400
-[#398]: https://www.free-decompiler.com/flash/issues/398
-[#382]: https://www.free-decompiler.com/flash/issues/382
-[#396]: https://www.free-decompiler.com/flash/issues/396
-[#357]: https://www.free-decompiler.com/flash/issues/357
-[#391]: https://www.free-decompiler.com/flash/issues/391
-[#395]: https://www.free-decompiler.com/flash/issues/395
-[#334]: https://www.free-decompiler.com/flash/issues/334
-[#301]: https://www.free-decompiler.com/flash/issues/301
-[#383]: https://www.free-decompiler.com/flash/issues/383
-[#386]: https://www.free-decompiler.com/flash/issues/386
-[#367]: https://www.free-decompiler.com/flash/issues/367
-[#380]: https://www.free-decompiler.com/flash/issues/380
-[#292]: https://www.free-decompiler.com/flash/issues/292
-[#375]: https://www.free-decompiler.com/flash/issues/375
-[#378]: https://www.free-decompiler.com/flash/issues/378
-[#325]: https://www.free-decompiler.com/flash/issues/325
-[#210]: https://www.free-decompiler.com/flash/issues/210
-[#355]: https://www.free-decompiler.com/flash/issues/355
-[#313]: https://www.free-decompiler.com/flash/issues/313
-[#330]: https://www.free-decompiler.com/flash/issues/330
-[#332]: https://www.free-decompiler.com/flash/issues/332
-[#344]: https://www.free-decompiler.com/flash/issues/344
-[#295]: https://www.free-decompiler.com/flash/issues/295
-[#297]: https://www.free-decompiler.com/flash/issues/297
-[#307]: https://www.free-decompiler.com/flash/issues/307
-[#309]: https://www.free-decompiler.com/flash/issues/309
-[#310]: https://www.free-decompiler.com/flash/issues/310
-[#311]: https://www.free-decompiler.com/flash/issues/311
-[#327]: https://www.free-decompiler.com/flash/issues/327
-[#328]: https://www.free-decompiler.com/flash/issues/328
-[#333]: https://www.free-decompiler.com/flash/issues/333
-[#336]: https://www.free-decompiler.com/flash/issues/336
-[#338]: https://www.free-decompiler.com/flash/issues/338
-[#315]: https://www.free-decompiler.com/flash/issues/315
-[#123]: https://www.free-decompiler.com/flash/issues/123
-[#243]: https://www.free-decompiler.com/flash/issues/243
-[#326]: https://www.free-decompiler.com/flash/issues/326
-[#287]: https://www.free-decompiler.com/flash/issues/287
-[#290]: https://www.free-decompiler.com/flash/issues/290
-[#291]: https://www.free-decompiler.com/flash/issues/291
-[#294]: https://www.free-decompiler.com/flash/issues/294
-[#298]: https://www.free-decompiler.com/flash/issues/298
-[#296]: https://www.free-decompiler.com/flash/issues/296
-[#314]: https://www.free-decompiler.com/flash/issues/314
-[#316]: https://www.free-decompiler.com/flash/issues/316
-[#318]: https://www.free-decompiler.com/flash/issues/318
-[#319]: https://www.free-decompiler.com/flash/issues/319
-[#323]: https://www.free-decompiler.com/flash/issues/323
-[#223]: https://www.free-decompiler.com/flash/issues/223
-[#261]: https://www.free-decompiler.com/flash/issues/261
-[#269]: https://www.free-decompiler.com/flash/issues/269
-[#274]: https://www.free-decompiler.com/flash/issues/274
-[#275]: https://www.free-decompiler.com/flash/issues/275
-[#258]: https://www.free-decompiler.com/flash/issues/258
-[#267]: https://www.free-decompiler.com/flash/issues/267
-[#286]: https://www.free-decompiler.com/flash/issues/286
-[#233]: https://www.free-decompiler.com/flash/issues/233
-[#235]: https://www.free-decompiler.com/flash/issues/235
-[#263]: https://www.free-decompiler.com/flash/issues/263
-[#264]: https://www.free-decompiler.com/flash/issues/264
-[#265]: https://www.free-decompiler.com/flash/issues/265
-[#266]: https://www.free-decompiler.com/flash/issues/266
-[#281]: https://www.free-decompiler.com/flash/issues/281
-[#251]: https://www.free-decompiler.com/flash/issues/251
-[#257]: https://www.free-decompiler.com/flash/issues/257
-[#259]: https://www.free-decompiler.com/flash/issues/259
-[#260]: https://www.free-decompiler.com/flash/issues/260
-[#268]: https://www.free-decompiler.com/flash/issues/268
-[#272]: https://www.free-decompiler.com/flash/issues/272
-[#276]: https://www.free-decompiler.com/flash/issues/276
-[#220]: https://www.free-decompiler.com/flash/issues/220
-[#284]: https://www.free-decompiler.com/flash/issues/284
-[#232]: https://www.free-decompiler.com/flash/issues/232
-[#253]: https://www.free-decompiler.com/flash/issues/253
-[#137]: https://www.free-decompiler.com/flash/issues/137
-[#242]: https://www.free-decompiler.com/flash/issues/242
-[#244]: https://www.free-decompiler.com/flash/issues/244
-[#203]: https://www.free-decompiler.com/flash/issues/203
-[#225]: https://www.free-decompiler.com/flash/issues/225
-[#236]: https://www.free-decompiler.com/flash/issues/236
-[#245]: https://www.free-decompiler.com/flash/issues/245
-[#247]: https://www.free-decompiler.com/flash/issues/247
-[#248]: https://www.free-decompiler.com/flash/issues/248
-[#254]: https://www.free-decompiler.com/flash/issues/254
-[#255]: https://www.free-decompiler.com/flash/issues/255
-[#256]: https://www.free-decompiler.com/flash/issues/256
-[#241]: https://www.free-decompiler.com/flash/issues/241
-[#238]: https://www.free-decompiler.com/flash/issues/238
-[#239]: https://www.free-decompiler.com/flash/issues/239
-[#240]: https://www.free-decompiler.com/flash/issues/240
-[#237]: https://www.free-decompiler.com/flash/issues/237
-[#217]: https://www.free-decompiler.com/flash/issues/217
-[#219]: https://www.free-decompiler.com/flash/issues/219
-[#224]: https://www.free-decompiler.com/flash/issues/224
-[#121]: https://www.free-decompiler.com/flash/issues/121
-[#207]: https://www.free-decompiler.com/flash/issues/207
-[#151]: https://www.free-decompiler.com/flash/issues/151
-[#171]: https://www.free-decompiler.com/flash/issues/171
-[#206]: https://www.free-decompiler.com/flash/issues/206
-[#208]: https://www.free-decompiler.com/flash/issues/208
-[#209]: https://www.free-decompiler.com/flash/issues/209
-[#229]: https://www.free-decompiler.com/flash/issues/229
-[#213]: https://www.free-decompiler.com/flash/issues/213
-[#221]: https://www.free-decompiler.com/flash/issues/221
-[#226]: https://www.free-decompiler.com/flash/issues/226
-[#227]: https://www.free-decompiler.com/flash/issues/227
-[#230]: https://www.free-decompiler.com/flash/issues/230
-[#172]: https://www.free-decompiler.com/flash/issues/172
-[#174]: https://www.free-decompiler.com/flash/issues/174
-[#175]: https://www.free-decompiler.com/flash/issues/175
-[#212]: https://www.free-decompiler.com/flash/issues/212
-[#185]: https://www.free-decompiler.com/flash/issues/185
-[#186]: https://www.free-decompiler.com/flash/issues/186
-[#197]: https://www.free-decompiler.com/flash/issues/197
-[#216]: https://www.free-decompiler.com/flash/issues/216
-[#168]: https://www.free-decompiler.com/flash/issues/168
-[#176]: https://www.free-decompiler.com/flash/issues/176
-[#177]: https://www.free-decompiler.com/flash/issues/177
-[#202]: https://www.free-decompiler.com/flash/issues/202
-[#173]: https://www.free-decompiler.com/flash/issues/173
-[#190]: https://www.free-decompiler.com/flash/issues/190
-[#129]: https://www.free-decompiler.com/flash/issues/129
-[#153]: https://www.free-decompiler.com/flash/issues/153
-[#180]: https://www.free-decompiler.com/flash/issues/180
-[#136]: https://www.free-decompiler.com/flash/issues/136
-[#179]: https://www.free-decompiler.com/flash/issues/179
-[#144]: https://www.free-decompiler.com/flash/issues/144
-[#164]: https://www.free-decompiler.com/flash/issues/164
-[#167]: https://www.free-decompiler.com/flash/issues/167
-[#170]: https://www.free-decompiler.com/flash/issues/170
-[#178]: https://www.free-decompiler.com/flash/issues/178
-[#181]: https://www.free-decompiler.com/flash/issues/181
-[#182]: https://www.free-decompiler.com/flash/issues/182
-[#183]: https://www.free-decompiler.com/flash/issues/183
-[#184]: https://www.free-decompiler.com/flash/issues/184
-[#189]: https://www.free-decompiler.com/flash/issues/189
-[#191]: https://www.free-decompiler.com/flash/issues/191
-[#195]: https://www.free-decompiler.com/flash/issues/195
-[#196]: https://www.free-decompiler.com/flash/issues/196
-[#198]: https://www.free-decompiler.com/flash/issues/198
-[#200]: https://www.free-decompiler.com/flash/issues/200
-[#201]: https://www.free-decompiler.com/flash/issues/201
-[#166]: https://www.free-decompiler.com/flash/issues/166
-[#165]: https://www.free-decompiler.com/flash/issues/165
-[#63]: https://www.free-decompiler.com/flash/issues/63
-[#67]: https://www.free-decompiler.com/flash/issues/67
-[#117]: https://www.free-decompiler.com/flash/issues/117
-[#127]: https://www.free-decompiler.com/flash/issues/127
-[#134]: https://www.free-decompiler.com/flash/issues/134
-[#155]: https://www.free-decompiler.com/flash/issues/155
-[#142]: https://www.free-decompiler.com/flash/issues/142
-[#146]: https://www.free-decompiler.com/flash/issues/146
-[#130]: https://www.free-decompiler.com/flash/issues/130
-[#132]: https://www.free-decompiler.com/flash/issues/132
-[#145]: https://www.free-decompiler.com/flash/issues/145
-[#147]: https://www.free-decompiler.com/flash/issues/147
-[#148]: https://www.free-decompiler.com/flash/issues/148
-[#152]: https://www.free-decompiler.com/flash/issues/152
-[#156]: https://www.free-decompiler.com/flash/issues/156
-[#157]: https://www.free-decompiler.com/flash/issues/157
-[#158]: https://www.free-decompiler.com/flash/issues/158
-[#159]: https://www.free-decompiler.com/flash/issues/159
-[#160]: https://www.free-decompiler.com/flash/issues/160
-[#162]: https://www.free-decompiler.com/flash/issues/162
-[#163]: https://www.free-decompiler.com/flash/issues/163
-[#149]: https://www.free-decompiler.com/flash/issues/149
-[#150]: https://www.free-decompiler.com/flash/issues/150
-[#119]: https://www.free-decompiler.com/flash/issues/119
-[#101]: https://www.free-decompiler.com/flash/issues/101
-[#114]: https://www.free-decompiler.com/flash/issues/114
-[#135]: https://www.free-decompiler.com/flash/issues/135
-[#141]: https://www.free-decompiler.com/flash/issues/141
-[#102]: https://www.free-decompiler.com/flash/issues/102
-[#124]: https://www.free-decompiler.com/flash/issues/124
-[#128]: https://www.free-decompiler.com/flash/issues/128
-[#131]: https://www.free-decompiler.com/flash/issues/131
-[#104]: https://www.free-decompiler.com/flash/issues/104
-[#113]: https://www.free-decompiler.com/flash/issues/113
-[#133]: https://www.free-decompiler.com/flash/issues/133
-[#140]: https://www.free-decompiler.com/flash/issues/140
-[#108]: https://www.free-decompiler.com/flash/issues/108
-[#105]: https://www.free-decompiler.com/flash/issues/105
-[#109]: https://www.free-decompiler.com/flash/issues/109
-[#106]: https://www.free-decompiler.com/flash/issues/106
-[#107]: https://www.free-decompiler.com/flash/issues/107
-[#110]: https://www.free-decompiler.com/flash/issues/110
-[#103]: https://www.free-decompiler.com/flash/issues/103
-[#111]: https://www.free-decompiler.com/flash/issues/111
-[#96]: https://www.free-decompiler.com/flash/issues/96
-[#98]: https://www.free-decompiler.com/flash/issues/98
-[#99]: https://www.free-decompiler.com/flash/issues/99
-[#100]: https://www.free-decompiler.com/flash/issues/100
-[#85]: https://www.free-decompiler.com/flash/issues/85
-[#79]: https://www.free-decompiler.com/flash/issues/79
-[#92]: https://www.free-decompiler.com/flash/issues/92
-[#93]: https://www.free-decompiler.com/flash/issues/93
-[#94]: https://www.free-decompiler.com/flash/issues/94
-[#95]: https://www.free-decompiler.com/flash/issues/95
-[#86]: https://www.free-decompiler.com/flash/issues/86
-[#87]: https://www.free-decompiler.com/flash/issues/87
-[#88]: https://www.free-decompiler.com/flash/issues/88
-[#89]: https://www.free-decompiler.com/flash/issues/89
-[#82]: https://www.free-decompiler.com/flash/issues/82
-[#78]: https://www.free-decompiler.com/flash/issues/78
-[#81]: https://www.free-decompiler.com/flash/issues/81
-[#84]: https://www.free-decompiler.com/flash/issues/84
-[#83]: https://www.free-decompiler.com/flash/issues/83
-[#65]: https://www.free-decompiler.com/flash/issues/65
-[#48]: https://www.free-decompiler.com/flash/issues/48
-[#53]: https://www.free-decompiler.com/flash/issues/53
-[#66]: https://www.free-decompiler.com/flash/issues/66
-[#68]: https://www.free-decompiler.com/flash/issues/68
-[#69]: https://www.free-decompiler.com/flash/issues/69
-[#75]: https://www.free-decompiler.com/flash/issues/75
-[#73]: https://www.free-decompiler.com/flash/issues/73
-[#62]: https://www.free-decompiler.com/flash/issues/62
-[#72]: https://www.free-decompiler.com/flash/issues/72
-[#64]: https://www.free-decompiler.com/flash/issues/64
-[#38]: https://www.free-decompiler.com/flash/issues/38
-[#56]: https://www.free-decompiler.com/flash/issues/56
-[#57]: https://www.free-decompiler.com/flash/issues/57
-[#58]: https://www.free-decompiler.com/flash/issues/58
-[#45]: https://www.free-decompiler.com/flash/issues/45
-[#50]: https://www.free-decompiler.com/flash/issues/50
-[#51]: https://www.free-decompiler.com/flash/issues/51
-[#52]: https://www.free-decompiler.com/flash/issues/52
-[#47]: https://www.free-decompiler.com/flash/issues/47
-[#42]: https://www.free-decompiler.com/flash/issues/42
-[#39]: https://www.free-decompiler.com/flash/issues/39
-[#40]: https://www.free-decompiler.com/flash/issues/40
-[#44]: https://www.free-decompiler.com/flash/issues/44
-[#36]: https://www.free-decompiler.com/flash/issues/36
-[#43]: https://www.free-decompiler.com/flash/issues/43
-[#46]: https://www.free-decompiler.com/flash/issues/46
-[#3]: https://www.free-decompiler.com/flash/issues/3
-[#37]: https://www.free-decompiler.com/flash/issues/37
-[#34]: https://www.free-decompiler.com/flash/issues/34
-[#35]: https://www.free-decompiler.com/flash/issues/35
-[#32]: https://www.free-decompiler.com/flash/issues/32
+# Change Log
+All notable changes to this project will be documented in this file.
+
+## [Unreleased]
+### Added
+- [#1240] AS search using multiple threads when parallel speedup is enabled
+- [#1308] Search by all P-code files in AS3
+- [#1333] Exporting sprites as swf files
+- [#1365] Allow to configure all types of configuration settings from command line
+- [#1369] Allow zoom in sprite (and button) export
+- Debug tooltips on hover
+
+### Fixed
+- [#1327] P-code editing: error message and syntax highlighting fixed when instruction name contains upper cased letter
+- [#1343] AS 1/2 direct editation critical bug
+- [#1348] Cannot properly export frame with cyrillic symbols to SVG
+- [#1354] Various FLA export problem fixes
+- [#1367] Raw edit conditional type fix.
+- [#1401] SVG export: duplicate pattern IDs fixed
+- [#1402] SVG export: certain font characters not exported properly fixed
+- [#1430] AS 1/2 deobfuscation fixes
+- Opening loaded SWF files during run fixed
+- Not opening first script when clicked on app startup
+
+## [10.0.0] - 2016-12-24
+### Added
+- Iggy Files support - reading and (limited) editation of fonts, texts and AS3 - 64 bit variant only
+- optional AS3 direct editation with Flex SDK
+- AS3 p-code editing - metadata read/write support
+- AS3 p-code editing - end of the block command like in RABCDasm
+- AS3 p-code editing - popup docs for more than instructions
+- Debugger - New columns for variable details - scope, flags, trait
+- Debugger - Add watch feature
+- AS3 decompilation - colliding trait/class names handling - show hash suffix with namespace index on such cases
+- Deobfuscation Tool - Fix colliding trait/classes via toolbar command
+- Auto rename identifiers option now fixes colliding trait/classes aswell
+- [#1254] FLA export - detecting scripts on AS3 timeline
+- [#907] FFDec Library JAR file has version inside it.
+- [#1311], [#1313] actionScript source font size
+- Display warning when library version and GUI version mismatch
+- Changelog file
+- [#1308] Search by all P-code files (AS 1/2 only)
+
+### Changed
+- [#1189] AS3 - sort imports to have same order always
+- GUI: AS3 P-code header show actual trait type and method type
+- GUI: Script editing buttons now named "Edit ActionScript" and "Edit P-code"
+- Set advance values button has confirm dialog with information
+- [#1274] Linux package no longer requires Oracle Java only
+- Library now packaged inside ZIP file
+
+### Fixed
+- P-code docs formatting fix
+- Export dialog - handling sprite and SWF frames correctly
+- [#1275] debugger - show local variables fixes
+- AS3 p-code editing - popup docs correctly displayed when label on line start
+- [#1278] replacing DefineBits error
+- [#1281] DefineFont 2/3 getting character advance value when replacing fix
+- Set advance values button - Do not set advance if the char cannot be displayed in source font
+- AS3 Goto declaration for single character names
+- Identifier renaming for top level classes
+- AS3 direct editation not correctly saving local register names
+- [#1254] FLA export - placing AS3 classes to FLA directory instead of scripts dir
+- Mac OS X installer fix (.pkg)
+- [#1289] AS1/2 direct editation - variables used in inner functions must not be stored in local registers
+- [#1283] AS3 Unbounded Vector - Vector<*> decompilation and direct editation fix
+- [#1294] Font editation (DefineFont2/3) - correct switching of wide character codes
+- [#1302] Callpropvoid instruction docblock not correct
+- [#1309] recent files not getting updates
+- [#1312] faster colliding usages finder
+- [#1303] garbled text when exporting frame with text
+- [#1314] user interface: button order
+- Internal viewer shows red image when bitmap fill is not available (see issue [#1320])
+- [#1323] Audio playback fails
+
+## [9.0.0] - 2016-08-12
+### Added
+- Instance metadata (AMF3) editing in PlaceObject4
+- [#1156] Flash Viewer - DefineScalingGrid support (9-slice scaling)
+- [#1171] Export stroke scale to FLA
+- FLA export - check invalid unicode characters
+- [#1170] Extract from memory in commandline
+- Reload one vs Reload all buttons
+- ABC: Float and Float4 support
+- AS3 p-code instruction documentation in GUI
+- [#1241] Settings to show original bytes in hex view
+- Search in dump view
+- Jump to resources view from hex view
+- Show warning on 32bit JRE
+
+### Changed
+- [#1162] improved opening loaded SWF files
+- Flash Viewer - skip frames when not on time
+- [#1199] Automatically import alpha channel to JPEG3/4 from PNG
+
+### Fixed
+- [#1151] Filters on texts fixed
+- [#1128] Adding characters to font fixed (FontAlignZones not removed)
+- [#1163] Clicking open->file makes program buggy
+- Refresh tree after raw edit
+- [#1172] Text double escape fix
+- [#1174] Change language fix
+- some AS2 deobfuscation fixes
+- [#1183] Index out of bounds fix
+- Implicit coersion on binary/unary opfix
+- debugger: corect display variable values through getters
+- Multiple XLF export fix
+- [#1193] FLA export - text tag advance fix, one layer shape fix
+- [#1193] FLA export - smoothed image detection, export raw JPEG data
+- [#1193] Export space character to TTF correctly
+- [#1200] Previous search text selected when quick find
+- Flash viewer: aspect ratio on startup fix
+- [#1198] Saving trait slot const value
+- Zoom parameter commandline fixed
+- [#1205] clipping fixed
+- [#1194] Wrong sound effects in FLA
+- [#1210] Frame Export fix
+- Improved/fixed go to declaration in AS3
+- [#1217] PCode window not in same position as AS
+- Hide memor search on non windows platform
+- [#1244] Incorrect showing of NOP instructions
+- [#1244] Remove unknown actions when deobfuscation is enabled, compole unknown instructions back
+- [#1241] File content is different from hex view
+- [#1247] Incorrectly handling remainingbytes for DefineCompactedFont
+- [#1236] won't open fixed
+- [#1251] SWF not same after export XML and import back
+- [#1265] Error during export
+- [#1268] Font export - Using second glyph when two glyphs for one character found
+- [#1268] GFX compacted font - fixed advance values on export
+
+## [8.0.1] - 2016-02-20
+### Changed
+- FFDec debug tab in advanced settings moved to other tabs
+
+### Fixed
+- [#1161] AS1/2 deobfuscation broken
+- AS1/2 Simplify expressions fix
+
+## [8.0.0] - 2016-02-18
+### Added
+- Debugger - AS1/2 Show registers
+- Debugger - display variables in the tree structure
+- Debugger - set value of variable
+- Debugger - AS1/2 View constantpool
+- Debugger - P-code level debugging for both AS1/2 and AS3
+- Basic SVG import for shapes
+- Simplify expression setting
+- [#1118] Loading characters through ImportAssets - show as readonly
+- [#409], [#1132], [SkinPart] metadata support - decompilation and direct editation in AS3
+- [#1134] compiling §§ instructions back while direct editation (§§goto is still missing)
+- [#1121] Ability to save binary data by its name
+- [#1052] Add object to existing frame
+- Allow adding tag to main timeline
+- AS1/2: Ctrl+click to declaration of variables, registers
+- Allow trait specification in pcode import
+- Icons for tag types in Dump view
+- Show error message when a text tag is invalid (glyph index problem)
+- AS3 direct editation - store local register names in debug info = allow to rename them
+
+### Changed
+- New application icon and splash screen
+- [#1145] AS3 better declaration type detection, better convert_x instruction handling
+- Binary export - use .swf extension for swf files
+- Better tree labels in generic tag editor (Raw edit)
+- [#758] Allow zooming more than preview area in internal viewer
+
+### Fixed
+- [#1096] FLA export - pretty print
+- [#1104] AS1/2/3 Script Importat not working
+- [#1107] Text Offset Incorrect fixed
+- [#1106] New Shapes replace function fix
+- [#1113] It takes too long to switch between rendered sprite
+- [#1075] Lenght of DefineText in some cases
+- [#1127] autoRenameIdentifiers is not supported in CLI mode
+- [#1128] Letterspacing bug (after font embed): ignore letterspacing when character changed
+- [#1103] Foreach variables fixes
+- AS3 Switch fixes
+- Default clause position in switch
+- [#1133] Incorrect frame order for nested sprite
+- [#1135] Handle try "to" in p-code correctly
+- Font wideOffsets,wideCodes fixed in DefineFont2/3
+- AS3: super method call
+- [#1138] All exported videos are the same file which may be broken
+- [#1139],[#930] Windows Installer: Correct ActiveX download link, Download latest java from webpages
+- [#1137] running flashplayer(debugger) executable in Linux/MacOs
+- [#1144] Command line argument renameInvalidIdentifiers
+- [#1145] double not (!!) not removed
+- [#1147] Sprite is exported incorrectly
+- [#1148] handing end of stream exception in abc reader, loc exception
+- [#1152] Font info tag modified tag was not set => saved swf was corrupt
+- [#1154] Some 32bit JRE problems - program won't start
+- [#1145] Correct precedence handling on binary operators
+- [#116] not resolving unusual tags in DefineSprite
+
+## [7.1.2] - 2015-12-03
+### Fixed
+- AS3 debugger start halt fix
+- AS1/2 debugger fix on nondebug enabled SWFs
+- AS1/2 debugger fix for functions
+- Debug menu item enabled fix
+- AS3 local reg index fix
+- Advanced settings calendar
+- AVM2 instructions in hex view
+- [#1070] Incorrect switch decompilation
+- [#1098] Import XML fix
+
+## [7.1.1] - 2015-11-23
+### Fixed
+- Critical debugger fix - widelines
+
+## [7.1.0] - 2015-11-23
+### Added
+- AS1/2 debugger
+- Breakpoint/IP marker on line beginning
+
+### Changed
+- Starting debugger on demand
+- Installer message about playerglobal is only warning now
+
+### Fixed
+- [#1033], [#1083] AS3 deobfuscation issues
+- [#1091] AS 1/2 direct editation saving
+
+## [7.0.1] - 2015-11-18
+### Fixed
+- Debugger: Adding breakpoint if script initializer not displayed
+
+## [7.0.0] - 2015-11-18
+### Added
+- AS3 Debugger - breakpoints, stepping, show variables
+- Faster AS3 direct editation
+
+### Changed
+- Better Configuration of flashplayer paths
+
+### Removed
+- Removed old "debugger" buttons
+- Removed search from browsers cache - inactual code
+
+### Fixed
+- Many AS3 direct editation related bugs
+- [#1076] export fix
+
+## [6.1.1] - 2015-10-30
+### Fixed
+- Deobfuscate AS3 metadata
+- [#1068] MorphShape with focal gradient fix, FLA XML export formatting fix
+- [#1063] AS3 direct edit - script initializer fix, generating method names
+- XML export/import fixes
+- [#1019] Namespace imports fix
+- AVM2 code execution fix
+- [#1016] AS3 direct editation fixes
+- [#1010] AS2 direct editation - internal and override is not a reserved word
+- [#1008] pushshort instruction diassembly
+- [#1004] this/super can be AS1/2 variable
+- [#933] AS3 allow numbers as object literal keys
+
+## [6.1.0] - 2015-10-26
+### Added
+- Open other loaded SWFs during playback (useful for loaders)
+- Export uncompressed data from dump tree
+- Print performance statistics from commandline
+- [#1062] Editing/displaying script initializers
+- Enable debugging on SWF file (commandline)
+
+### Changed
+- Faster syntax highlighting
+- Better AS1/2 deobfuscator
+- [#418] AS3 deobfuscator improved
+
+### Fixed
+- AS call method fix (first parameter is "this")
+- [#1047] open all scripts folders
+- [#812] decompile fail
+- [#1056] deltaY missing when adding a new StraightEdgeRecord
+- [#1057] Editing as in editor results in package name moving
+- [#991] GUI export
+- [#689] Ignore Case not correctly toggled
+- [#1060] reversed and/or detection in some cases
+- [#1037] isXML call
+
+## [6.0.2] - 2015-09-12
+### Added
+- AS3: Display and direct edit trait Metadata
+- Allow to specify tag type on image or shape import
+- Convert image tags from commandline
+- [#489] Hex decode very large integers
+- Add new tags without show empty folders
+- Dependent characters in basic tag info
+- [#1007] replace bytearray in raw editing
+- Italian translation
+
+### Changed
+- AS2 parser - add string to constant pool if there is not enough space
+- [#1044] AS2 - order scripts by physical location, name by offset
+
+### Removed
+- Deprecated commandline parameters removed
+
+### Fixed
+- JNA problems on some JDKs
+- [#947] Marklevels errors ignored 17a94b7
+- [#953] Mac application permission fix (maybe)
+- [#954] IndexOutOfBounds fix
+- [#950] AddTrait setting modified fix
+- [#945] AS1/2 directeditation fix - member named as global function
+- [#957] AS1/2 IndexOutOfBounds fix
+- [#956] Invalid jump offsets warning
+- [#968] Sprites export with wrong coloring
+- [#978] case sensitivity of filenames
+- [#955] AS2 decompilation problem
+- Image alpha fixes
+- [#966] Go to document class
+- [#991] scripts exporting
+- [#999] save as fla
+- [#1000] image export for malformed JPEG3 tags
+- [#1017] store alchemy opcodes with wrong order
+- [#1030] stack overflow fix
+
+## [6.0.1] - 2015-07-06
+### Added
+- Special §§ instructions marked as red
+- [#949] Replace alpha channel from commandline
+- AS3 deobfuscation from commandline
+- Option to ignore FlashCC/Alchemy packages
+
+### Changed
+- [#944],[#991],[#939],[#942] AS3 deobfuscation improvements
+
+### Fixed
+- AS1/2 deobfuscation fixed
+- [#952] Not loading SWF without extension
+
+## [6.0.0] - 2015-07-04
+### Added
+- New AS3 deobfuscation method
+- Internal "preprocessor" §§ actions introduced - §§pop,§§push,...
+- Allow reload FFDec when no SWF is opened
+- [#858] Allow to set compression type in header
+- [#905] Show codec details for sound items
+- Better alchemy/DomainMemory instruction handling
+- Better obfuscated names handling
+- [#920] Export instance name to SVG
+- [#921] Export html DefineEditText to SVG
+- Open multiple files with drag and drop
+- Better "multi packs" handling (Alchemy)
+- SWF version 29 to flash player 18 mapping
+- ImportAssets2 sha1 field
+- [#924] Sprites to image from commandline
+- AS1/2 direct editation big numbers fix
+- Allow to add FILTERs and SHAPERECORDs in generic tag editor
+- Enable close all menu when no swf is selected
+- Restore modified state even when something goes wrong
+- Some old tags added
+
+### Changed
+- AS decompilation highly improved
+- Better &&, || handling
+- DoABCDefine renamed to DoABC2
+- Separated Sprite export settings
+
+### Deprecated
+- Old AS1/2/3 deobfuscation method marked as deprecated (can be enabled back deep in the configuration)
+
+### Fixed
+- Many decompilation problems - EmptyStack exception, Maximum recursion level reached, etc.
+- Few menu issues
+- [#895] Correct handling CMYK JPEG
+- [#884] AS direct edit assignment
+- [#899] Show script after AS3 direct editation
+- Some AS1/2 parser problems
+- [#903] FLA export - fix for missing fontname, lastframe
+- [#855] AS3 direct edit - for..in variable declaration fix
+- [#850] Constant initialization for same multinames
+- [#832] AS3 direct edit - other ABCs resolving fix
+- [#904] Cannot export images
+- [#910] Missing instructions
+- Opening not existent files on restoring last session
+- [#922] Edit text leading
+- Put image before shape on shape replace
+- [#916] Replacing Shape corrupts SWF
+- JRE setup parameters fixed
+- [#938] Parallel speedup limit fix
+
+## [5.3.0] - 2015-05-25
+### Added
+- Generic tag editor: improved table editing (import/export assets tags, etc.)
+
+### Changed
+- Classic (nonribbon) UI improved - has same items as Ribbon UI
+- Icons improvements
+- Disabling menu items when work in progress
+
+### Fixed
+- [#897] Classic UI fix
+
+## [5.2.0] - 2015-05-22
+### Added
+- UI8 editbox for swf version in header panel
+- Basic tag information panel
+
+### Changed
+- AS1/2: Shown only the constant pool(s) in pcode editor
+- Do not allow to chage tag tree selection, when current tag is under editing
+- Faster bitmap export
+- Using less memory when playing sounds
+- Error message changed when the opened file is not swf
+
+### Fixed
+- [#470] panels size after resizing from/to full screen
+- [#877] A small glitch after search in AS
+- [#878] small glitch after saving P-code or swf file
+- [#470] glitch
+- [#845] If frame consist 2 DoAction then it imports only first one
+- pdf export (when no frame exists)
+- text rendering (alpha channel was ignored),
+- bmp export (paddings when width%2==1)
+- [#883] -dumpSWF option does not work anymore
+- [#882] Canvas export border size
+- [#760] Internal viewer line linear gradient fill is not working
+- [#887] error on export a special swf's P-CODE
+- Extensions of exported images fixed
+
+## [5.1.0] - 2015-05-04
+### Added
+- Allow to copy/move multiple tags, and dependencies
+- [#842] For reconstruction if debug line info present
+- [#841] Loop control for sound preview
+- [#845] Import exported AS1/2 (DefineButton2&DefineSprite) button
+- Scrollbar added to fontpanel
+- SWF header editor
+- Configure what object types to export in exportdialog
+
+### Changed
+- Better gif exporter
+- [#772]: closing loading dialog now cancels the loading of the swf
+- [#762] export pcode with different extension
+
+### Fixed
+- CRITICAL: Update System Bug causing updates not working
+- [#862] AS3 asm: do not read beyond return/throw instructions
+- [#865], [#613]: ribbon prefered width fix
+- [#868] export path fix, allow to export buttons
+- [#865] TagTree font size problem on high resolution screens
+- [#713],[#807] Installer for 4.0+ fails to access Adobe Website
+- [#728] Large fonts, [#857] add scroll on DefineFont3
+
+## [5.0.2] - 2015-04-18
+### Added
+- Reopen last session
+
+### Fixed
+- ffdec.sh file line endings fixed
+
+## [5.0.1] - 2015-04-18
+### Fixed
+- [#860]: Opening bundle (zip, swc, any binary file) files fixed
+
+## [5.0.0] - 2015-04-18
+### Added
+- Color skins
+- [#824] Mac OS X package
+- [#809] Move left,right buttons for DefineTexts using translatex parameter
+- [#805] Editor mode for DefineTexts
+- [#825] Hotkeys for next/previous DefineText
+- Export/Import symbol classes/export asset tags
+- Frame export progress
+- [#737] Single file script export
+- Displaying changed AS3 scripts in GUI as bold
+- Additional character info tags placed under character node
+- New icons for other tags (metadata,fileattributes,setbackground,place/remove)
+- Metadata tag editor
+
+### Changed
+- Default color skin altered
+- [#350] Allow only one running instance (Windows only, can be turned off)
+- SWFs in zip based bundles (SWC for example) can be modified & saved
+- Performace improvements
+- More compact SWF-XML format
+- Marking changed parentnodes as bold too
+
+### Fixed
+- [#814] Exporting with scale problem
+- [#816] P-code not shown after class initializer trait selection
+- [#835] Static initializer improvements
+- AS3 direct editing - local register decrement fix
+- AS3 direct editing - maintain register order/names
+- [#836] AS1/2/3 Correct expression precedence handling
+- AS3 preincrement
+- [#848] Correct toggling text switches
+- [#817] AS1/2 for..in variable declaration
+- [#849] Attribute member
+- [#852] Ignore case for russian characters
+- [#837] AS3 try..finally without catch
+
+## [4.1.1] - 2015-02-21
+### Added
+- Export/Import XML added to ribbon menu
+- Few GUI enhancements
+- Undo tag changes context menu
+
+### Changed
+- Java 8 now required
+
+### Removed
+- Removed support for Java below 8
+
+### Fixed
+- [#811] export ActionScript
+
+## [4.1.0] - 2015-02-18
+### Added
+- XML export/import
+- confirmation dialogs added
+- Add support for non-standard ABC-compressed SWF file
+- [#745] Copy tag to another SWF
+- [#803] Align text in DefineText
+
+### Changed
+- performance improvements
+- [#758] Zoom to fit is dynamic
+
+### Fixed
+- [#738] Frame export
+- [#742] Can't edit frames
+- [#747] Move tag to adds extra frame
+- [#749] Internal viewer Sprite fill color
+- [#752] Sound is not stopped
+- [#753] Reload swf
+- [#759] Decompilation § symbol
+- [#766] Can't extract all resources
+- [#768] Super calls not being correctly recognized
+- [#773] Scripts associated with ClipActions are not shown
+- [#776] Stop working after setting "number of threads" to 0
+- [#783] No OK box when edited script or text was saved
+- [#785] Text search. Remember last choise, Unicode case insensitive search
+- [#787] Search in AS bug (when navigating to searched results)
+- [#788] Add DefineCompactedFont Tag to gfx file
+- [#790] Impossible to change letters under a font
+- [#794] Font extraction fails sometimes
+- [#798] Close file streams after export, exporting progress
+- [#800] Unexpected deleted carrier return in DefineEditText
+- Build fix on Linux
+- Fis Startup Script for OpenJDK
+- Other minor fixes
+
+## [4.0.5] - 2014-12-01
+### Added
+- Escape control characters in strings, identifier names
+- [#676] import text error messages / logging enhancement
+- [#734] \xAB escapes, \uABCD escapes
+- [#687] AS3 - allowing p-code comments on separate line
+- [#709] Text Export to Single File with custom filename
+
+### Fixed
+- [#732] Random freezing - JavactiveX library updated.
+- [#730] Not working without ActiveX fix on Windows
+- [#735] Automatic deobfuscation not correctly switched (required restart)
+
+## [4.0.4] - 2014-11-23
+### Changed
+- better file cache, removing unneccessary temp files
+
+### Fixed
+- obfuscated identifiers
+
+## [4.0.3] - 2014-11-23
+### Added
+- [#722] Go to next/previous frame
+- BMP file format export (images,frames,shapes) and import(images)
+
+### Fixed
+- [#725] various AS direct editation bug fixes - namespace compilation, AS 1/2 strict equals, submethod scope, unbounded type
+- [#715] namespace resolving fix
+- [#635],[#726] placing cursor inside Unicode characters
+
+## [4.0.2] - 2014-11-22
+### Added
+- show frame number during play
+- flashplayer - show controls for DefineSprite
+- goto frame
+- [#716],[#717],[#718] Proxy - save SWF, replace, copy URL, filesizes, table design
+
+### Changed
+- [#720]: edited shape tag is not marked as modified after replacing
+- reorganized about dialog
+
+### Fixed
+- [#719] null swf name in Proxy after cancelling rename dialog
+- flashplayer - font display
+- [#723]: saving swf with invalid referenced characters
+- DefineCompactedFont paging
+- [#288] Less memory usage during FLA export
+- Corrected syntax hilighting for AS3 P-code
+
+## [4.0.1] - 2014-11-12
+### Fixed
+- [#713] Installer can continue when no file can be downloaded
+- Fixed shapes
+- Checking for updates moved to separate thread
+
+## [4.0.0] - 2014-11-11
+### Added
+- [#677] Zoom level in export settings
+- internal viewer: linear/srgb gradients
+- zooming buttons for flashplayer/internal viewer
+- stroke scaling modes for canvas export
+- create snapshot button
+- [#389] Selecting font face on import
+- [#701] Importing font from TTF file
+- Reorganized font panel
+- [#707] Debugger for logging messages
+- [#302] AS3: Better Ctrl+Click handling with underline, more declaration targets
+- [#685] Getting local register names from debug info can be disabled
+- Adding new tags
+- [#698] Allowing unicode letters in identifiers
+- [#710] Information about deobfuscation in error comments
+- One EXE for 32/64 bit, uses percentage memory.
+- EXE SplashScreen
+- New Improved Windows Installer (NSIS) - can install Java and FlashPlayer, download playerglobal.swc
+- Config setting to load inner SWFs automatically
+- Replace shape with image
+
+### Changed
+- better FlashPlayer integration using JavactiveX library
+- Faster building tag tree
+- Faster timeline construction
+- [#711] Improved folder view - faster and with correct context menu
+
+### Fixed
+- AS2 deobfuscation fixes
+- AS2 loops fix
+- [#681] Linux script fixes
+- AS2 constructor name fix
+- [#688] AS3 direct edit fixes
+- [#691] AS3 p-code reading/saving fix
+- AS3 direct edit -submethod name resolve fix
+- frames to html canvas fix
+- [#524] Mask layer not applied when nonempty script layer
+- [#663] AS3 imports fixes
+- Font export of dot character
+- Font panel Yes button fixed
+- [#702] GFX font reading fix
+- Better obfuscated names handling
+- [#539] for(each) in declaration fixes
+
+## [3.0.0] - 2014-09-20
+### Added
+- Separated GUI (GPL) and library (now LGPL)
+- Editing obfuscated identifiers via new paragraph(§) syntax
+- Timeline View with preview and object hilighting
+- Show GFX data in dump view
+- [#650] New parameter to replace binarydata, images, sounds, scripts from commandline
+- Dump view - selecting node
+- [#680] Loading subSWFs from binaryTags now optional (button/context menu) to avoid unnecessary memory consumption
+
+### Removed
+- Removed deprecated commandline export formats (see --help)
+
+### Fixed
+- FileAttributes tag reading fix
+- [#649] GFX reading fixed
+- [#656] Search in memory - 64 bit processes fix
+- [#661] scripts not showing
+- [#664] expanding fillStyles in raw edit
+- [#668] add missing character fix, text tags fix
+- [#674] texts hilighting initialization fix
+- [#675] AS1/2 and/or operator compilation
+- [#632] Locking file after opening (cannot save, etc.)
+- [#651] Unnecessary removing expression killed in unreachable part
+- [#678] Windows batch file paths fixed
+- [#672] Disabling transparency slider on RGB only selection
+- [#684] Sound streams inside DefineSprites, soundstream handling
+
+## [2.1.4] - 2014-08-23
+### Added
+- AS1/2: New method for deobfuscation (can be switched off in settings)
+- AS1/2: Using eval/set on invalid identifiers, quotes in function names/parameters
+
+### Fixed
+- [#647] Skipping FileAttributesTag with Parallel speedup on
+- [#648] Export from embedded SWF
+
+## [2.1.3] - 2014-08-18
+### Added
+- Show "save" and "saveas" in application menu
+- Saving data range in dump view
+- Show actions, abcdata in dumpview (context menu on the tree node)
+- [#612] show color in hex format
+
+### Changed
+- Faster dump info collecting (less memory)
+- Allow selecting multiple files in open file dialog
+
+### Fixed
+- [#623] ffdec.sh UNIX file endings, executable
+- [#624] search in embedded swf files
+- [#632] AS1/2 Unnecessary GetVariable before NewObject
+- [#627] filter swf not working
+- LZMA saving
+- Export pcode&hex from commandline
+- [#640] text import fixed, ignore BOM
+
+## [2.1.2] - 2014-07-20
+### Added
+- Dump view
+- Context menu: Jump to character, raw edit all tags
+- Catalan translation
+- SWF header display
+
+### Fixed
+- [#595] AS3 direct edit - Getter/Setter generation - caused FlashPlayer crashes
+- [#592] AS3 Multiname resolving in P-code causing different bytecode
+- [#585] AS3 moving popped values to output
+- [#578] Always on top fixed on search results
+- [#501] GotoFrame2 fix
+- [#616] Frames to PNG export
+- Export context menu
+- [#559] Bitmap export opacity
+- [#401] Placeobject 3/4 fix
+- [#593] Return object newline
+- [#594] Setting for curly brace
+
+## [2.1.1] - 2014-06-05
+### Added
+- [#302] Find declaration (Ctrl+click, Ctrl+B), Find usages (Ctrl+U) - Works only for exactly same multinames, not local registers
+- AS1/2 direct edit - global functions improvements
+- AS1/2 negate operator, unary minus operator
+- Opening SWFs in BinaryData tags
+- AS1: Old string operators support, and/or, <> operator (editation)
+- Statusbar loading animation improved
+- [#579] AS3 direct editation - removing old class/methods from ABC
+- remove character without the dependencies (remove only the place/remove tags)
+- Running on system with no home directory
+- [#428] PDF export (as images only)
+- Commandline FlashPaper to PDF export
+- Select frames / Characters commandline options
+
+### Changed
+- [#337] quickfind visibility improved
+- [#584] commandline script export - select whole packages (use .+ at the end of -selectas3class)
+
+### Fixed
+- [#576] AS1/2 direct editation: DefineFunction2 fix
+- AS1/2 property fix
+- AS1/2 typeof operator fix
+- [#250] line spacing fix
+- PlaceObject 3-4 className
+- [#579] AS3 direct editation bugfixes - property resolving, integer values
+- Morphshape canvas export fix
+- Canvas export fix - closing path
+- [#580] Rename invalid identifiers commandline fix
+- [#510] JSyntaxPane find and replace dialog wrap around fix
+- No more frame caching during export => memory saving (like [#583])
+- [#586] DropShadow filter fix
+- Canvas export colortransform fix
+
+## [2.1.0 update 2] - 2014-05-08
+### Added
+- AS3 decompilation/editation: Vector initializers
+- AS3 direct editation: more classes in one file
+
+### Fixed
+- [#574] DefineSprite editing fix
+- Various AS3 direct editation fixes
+
+## [2.1.0 update 1] - 2014-05-05
+### Added
+- Portugese-brasilian translation
+
+### Changed
+- HTML Canvas export improvements
+
+### Fixed
+- Various AS3 direct editation bugs, like [#570]
+
+## [2.1.0] - 2014-05-01
+### Added
+- AS3 direct editation (Experimental!)
+- Frames SVG Export
+- Shape/MorphShape/Frames HTML 5 Canvas Export
+- [#559] morphshapes as animated SVG
+- [#563] Single file text export/import
+- Font WOFF export
+- Advanced settings dialog with tabs, config names, descriptions
+
+### Fixed
+- [#561], [#509], [#433]: AS3 EmptyStackException fix - correct hasnext2 arguments
+- Internal viewer: Filters fix
+
+## [2.0.1 update 2] - 2014-04-05
+### Fixed
+- [#557] AS3 null namespace fix - p-code not working
+
+## [2.0.1 update 1] - 2014-04-04
+### Fixed
+- [#556] Goto main class on startup fix
+- [#557] Nullpointer fix (private namespaces)
+
+## [2.0.1] - 2014-04-03
+### Added
+- Thumbnail view
+- Font TTF export
+- Exporting frames: PNGs, AVI, GIF (via Internal flash viewer)
+- Expand all context menu
+- Internal viewer: Button mouse move and click handling
+- Playing sounds without flash player
+- Internal viewer: Sounds on stage
+- All sounds to WAV export
+- Internal viewer: Showing texts, dynamic text border/fill
+- [#504]: Unicode characters in JSyntaxPane
+- Internal viewer: showing object under cursor
+- Folder icons
+- Sound/Image format on command line.
+- Removing placeobject tags
+- Removing frames
+- AS: "elseif" statements
+- Code formatting: space before parenthesis
+
+### Changed
+- Single frames animated.
+
+### Fixed
+- [#529] limit the number of displayed binaryData bytes
+- [#538] Interface are sometimes dynamic
+- [#537] super is sometime preceded by a dot
+- [#540] Saving SWF changes very large static uint values
+- [#387] Frames preview bugged
+- AS:loop mismatch fix on parallel speedup
+- [#552] Some timeout exceptions
+- [#494] Fixed nightly builds updates
+
+## [2.0.0] - 2014-03-02
+### Added
+- Generic tag tree editor
+- Timeline view (stub only)
+- FLA export to CS5, CS5.5, CC format (previously only CS6 was supported)
+- [#513]: command line option to extract swf from binary file
+- Configurable code formatting (Indentation + brace position)
+- [#262] Export FLA: Font character ranges export
+- Configurable checking for updates
+
+### Changed
+- Improved Internal Flash viewer - better shapes, morphshapes, DefineEditText tag, clipping, blend modes
+- Improved commandline usage
+- Automatic deobfuscation default value set to False (See News on webpages)
+- Check for updates can be configured to inform about Nightly builds aswell
+
+### Deprecated
+- Some commandline options are now deprecated, see --help
+
+### Fixed
+- [#499] Cannot save via Proxy fixed
+- [#504] font name reading fixed
+- [#508] Support for OS without GUI
+- [#305] Export FLA: empty sound layers
+- [#312] Export FLA: Improved Shape/MorphShape fix
+- [#503] Export FLA: Smoothing invalid shapes
+- [#401] Invalid GFX tags in non GFX files
+- [#304],[#306],[#507],[#424],[#425],[#478],[#485],[#517],[#518] Many direct AS1/2 editing issues
+- [#361] FFDec icon is not visible on application start
+- [#392] Video stream data fix
+- [#516] AS3 P-code editor - Null name namespace handling
+
+## [1.8.1 update 1] - 2014-02-02
+### Fixed
+- [#495] font embedding fix
+- [#496] date format in new version dialog
+- cosmetic changes
+
+## [1.8.1] - 2014-01-30
+### Added
+- [#299] replace DefineBits images
+- [#303] open folder with exported FLA
+- [#324],[#346] SWC/zip/other binary file support
+- [#371] detailed logging
+- [#426] command line switch to rename identifiers
+- [#457] clear recent opened files list
+- [#458] save selected system font for swf fonts
+- [#460] text editor: do not scroll to the end automatically
+- [#462] font embedding dialog: show more sample characters
+- [#463] global search in texts
+- [#465] make font properties editable
+- [#466] font preview
+
+### Changed
+- [#369] new SVG and preview image rendering
+- [#390] refresh font list without reloading the application
+- [#453] update texts aftert adding new character to a font tag
+- [#459] remember text panel splitter position
+- [#461] font panel gui redesigned
+
+### Fixed
+- [#451] dialog windows are not on the center of the screen
+- [#454] Text syntax highlighting
+- [#455],[#465] classic interface issues
+- [#474] changeing language only available one time
+- [#477] log window localization
+- [#481] SVG export fix
+- [#484] Oversized advance value after editing DefineText with DefineFont2 font
+- [#493] missing search results
+
+## [1.8.0 update 1] - 2013-12-27
+### Added
+- [#453] refresh (edit+save action) all texts button
+
+### Fixed
+- Flash panel and font panel fixed
+
+## [1.8.0] - 2013-12-27
+### Added
+- [#350] Allow to open multiple SWFs
+- [#365] Filter fake SWFs during memory search
+- [#366] Allow to sort the result list in memory search window
+- [#429] Auto rename invalid identifiers setting
+- [#447] Non-ribbon interface
+
+### Fixed
+- [#354] Infinite decompilation fixed
+- [#438] Case sensitive Command line arguments fixed
+- [#436] Saving actionscript fixed
+- [#446] Precedence issue fixed
+- [#451] Dialogue window positions on a multi-monitor configuration fixed
+
+## [1.7.4 update 1] - 2013-12-05
+### Added
+- [#426] Command line parameter for renaming invalid identifiers
+
+### Fixed
+- [#427] Exception on linux fixed
+- [#405], [#420], [#421] Some decompilation issues fixed
+- [#430] Configuration default value problem fixed
+- [#397], [#431] Deobfuscation stucked sometimes problem fixed
+
+## [1.7.4] - 2013-11-10
+### Added
+- [#169] hexedit method body bytes
+- [#335] last opened files
+- [#404] Exporting P-code and Hex + console parameters
+- [#407] register name is configurable
+- Advanced settings
+- Cancellable decompiling, exporting and searching
+
+### Fixed
+- [#399], [#400] performance optimizations
+
+## [1.7.3 update 2] - 2013-09-29
+### Fixed
+- [#398] AS3 p-code values with index 0 (null)
+
+## [1.7.3 update 1] - 2013-09-28
+### Added
+- [#382] AS3: Adding new method
+
+## [1.7.3] - 2013-09-27
+### Added
+- AS3: Multiname and namespace editing.
+- [#382],[#396] AS3: Adding new trait (method/slot/const)
+- AS3: Highlighting pair parenthesis/bracket
+- AS3: Editing various new P-code parameters
+- AS3: Highligting of trait names/types/parameters
+- AS3: Global rename identifier for traits
+- [#357] Playback controls for DefineSound
+- [#391] AS3: Native methods mark
+- [#395] Support for GFx ScaleForm SWFs (with fonts editing)
+- Displaying fonts in internal viewer
+- [#334], [#395] New Embed font dialog - selecting character ranges with preview
+- Replacing characters in font (Yes/No to all dialog)
+
+### Changed
+- AS3: New p-code syntax inspired by RABCDasm
+- AS3: Editing whole trait in one textarea
+- AS3: Removed messages about adding new constants
+- AS3: Modified colors in editor
+- [#301] Clearing error log causes icon to reset
+
+## [1.7.2 update 2] - 2013-09-13
+### Changed
+- Updated translations
+
+### Fixed
+- [#383] Firefox browser cache handling
+- [#386] SWF resizing
+
+## [1.7.2 update 1] - 2013-09-11
+### Changed
+- updated translations
+
+### Fixed
+- [#383] Fixed cache loading when Firefox not used
+
+## [1.7.2] - 2013-09-11
+### Added
+- [#357] Sounds Preview (Windows only)
+- Movies preview (Windows only)
+- Whole SWF display
+- Preview controls (Play,Pause,Stop)
+- Search SWFs in browsers cache (Firefox, Chrome)
+- [#367] Memory search: Save selected files to disk
+- Portugese translation
+
+### Changed
+- [#380] Faster displaying DefineBitsLossless(2) images
+
+### Fixed
+- [#292] Background color for Fonts preview fixed
+- [#375] Replacing DefineBitsLossless image tag
+- [#378] Refreshing language of JSyntaxPane
+- MORPHGRADIENT reading fix
+
+## [1.7.1] - 2013-08-25
+### Added
+- Loading SWFs from other processes memory (Windows only, sorry)
+- [#325] Spanish translation
+- [#210] Ukrainian and Dutch translation
+- [#355] Chinese translation
+- [#292] Change background color in SWF preview
+- [#301] Clear errors log button
+- [#313] Command line parameter for ignore all errors
+- [#330] Protection agains adding same characters
+- [#332] AS1/2 Showing elapsed times during commandline export
+- [#344] Reload opened SWF
+- Decompilation timeouts
+
+### Fixed
+- [#295] Export FLA: wrong font
+- [#297] Too bright titlebar button colors
+- [#307] Export FLA: fixed empty textfields
+- [#309] Export FLA: static text letter spacing detection
+- [#310] Export FLA: Strokes
+- [#311] Export FLA: BitmapFill
+- [#327] AS1/2 Disassembly error stop application
+- [#328] Fixed replacing images in DefineBitsJPEGX
+- [#333] AS1/2 action reading
+- [#336] Graph window is too small
+- [#337] Quick search panel barely visible in same cases
+- [#338] Expand/collapse icon in errorlog
+
+## [1.7.0 update 1] - 2013-08-11
+### Added
+- [#315] German translation (partial)
+
+### Fixed
+- [#123] Better context menu integration
+- [#243],[#326] Better deobfuscation
+- [#287] Typo in parallelSpeedUp parameter
+- [#290],[#291] improved select language dialog
+- [#294] minor GUI fixes
+- [#298] Progressbar positition issues
+- [#296] better export directory remembering
+- [#314] Better deobfuscating filenames
+- [#316] Readonly editor panes accepted Ctrl+Z/Y
+- [#318] Export FLA: Shapes export fix
+- [#319] AS3: Improved try..catch..finally decompilation
+- [#323] AS3: Fixed default switch part
+
+## [1.7.0] - 2013-08-03
+### Added
+- Listing contributors on about page
+- [#223] AS2: Detecting uninitialized class fields
+- [#250] Export FLA: Detecting static fields margin and spacing
+- [#261] Export FLA: AS1/2 Frame scripts on first layer
+- [#269] Commandline parameters for switching configuration
+- [#274] AS3 Displaying elapsed time during commandline export
+- [#275] AS3 Removing returnvoid as last statement
+
+### Changed
+- New GUI based on Substance look and feel
+- Menu changed to ribbon panel
+- New round icon
+- [#258] AS1/2: Improved chained assignments
+- [#267] Starting program without choosing a file
+- [#286] Saving to temp file first
+
+### Fixed
+- [#123] Improved context menu integration on Windows
+- [#233] Globally rename identifier deselects item in the tree
+- [#235] Export FLA: Dynamic text fields coordinates
+- [#243],[#263],[#264],[#265],[#266],[#281] Improved deobfuscation
+- [#251] Export FLA: Fixed filter strength rounding
+- [#257] Export FLA: Text field color and size issues
+- [#259] Fixed images alpha
+- [#260] Export FLA: Labels position
+- [#268] AS1/2 Function parameter shown as register instead loc
+- [#272] AS3 Class initializer editation fix
+- [#276] Fixed anonymous/inline functions handling
+- [#220] Improved editing fonts / texts
+- [#284],... other small fixes
+
+## [1.6.7] - 2013-07-20
+### Added
+- [#220] Selection of font to import characters from
+- [#232] Automatically add .swf extension in saveas dialog
+- [#253] Abort/Retry/Ignore dialog on errors with file saving
+
+### Changed
+- Improved translations
+
+### Fixed
+- [#137],[#242], [#243], [#244] AS1/2/3 fixed deobfuscation
+- [#203] AS1/2 improved direct editing
+- [#220] Adding characters to font fix
+- [#225] AS1/2 object literal without name quotes
+- [#236] AS1/2 Rename invalid identifiers issues
+- [#245] AS3 Double space around "as" keyword
+- [#247] AS3 Scrolling to main class at startup
+- [#248] Memory issues (slowdown)
+- [#254] Expressions as commands
+- [#255] Windows 7 loading issues
+- [#256] AS3 Object literal in return clause
+- SWF text parsing (new lines)
+- Labels size by locales
+
+## [1.6.6 update 2] - 2013-07-16
+### Fixed
+- [#241] Program could not be started
+
+## [1.6.6 update 1] - 2013-07-16
+### Changed
+- Better localization support
+
+### Fixed
+- [#238],[#239],[#240] Fixed deobfuscation related problems
+- [#237] Parentheses in AS1/2 add,subtract
+
+## [1.6.6] - 2013-07-16
+### Added
+- [#217] Russian translation (focus)
+- [#219] Hungarian translation (honfika)
+- [#224] Swedish translation (Capasha)
+- [#220] Adding characters to Fonts, displaying font info
+- [#121] Search progress indication
+- Error log
+
+### Changed
+- [#203] Improved direct editing of AS1/2
+- [#207] Update SWF preview after switching external/internal flash player
+
+### Fixed
+- [#151] Memory caching
+- [#171] Skipping invalid AS3 code - newobject, newarray
+- [#206] AS3 switch problem
+- [#208] Renaming anonymous functions
+- [#209],[#229] FLA export texts positions
+- [#213],[#221] other decompilation issues
+- [#225] AS object literal broken with ternar operator
+- [#226] onClip indentation in FLA export
+- [#227] gotoAndStop wrong frame index
+- [#230] FLA export missing strokes
+- Shapes viewer - missing strokes
+
+## [1.6.5 update 1] - 2013-07-09
+### Fixed
+- [#151] Fixed caching in memory
+- [#172] AS1/2 constant detection fix
+- [#174] Renaming SymbolClass fix
+- [#175],[#212] Fixed create directory issues on export
+- [#185],[#186] on-clip actions indentation
+- [#197] AS1/2 Missing storeregister before switch
+- [#216] AS2 Fixed field order
+- [#213] AS2 Fixed var fields quotes, switch nullpointer
+
+## [1.6.5] - 2013-07-08
+### Added
+- Multilanguage support (currently English and Czech)
+- [#151] Option for caching in memory instead of files
+- [#168] Export selection in tree context menu
+- [#176] option to show main class on startup
+- [#177] saving window maximized state
+- [#202] Removing tags other than DefineSprite
+
+### Changed
+- [#173],[#190] Better renaming
+- [#129], [#153] Better deobfuscation
+- [#180] better error handling
+- [#185],[#186] better displaying and exporting onclip actions
+
+### Fixed
+- [#123] Better context menu integration
+- [#136] FLA export - text sizes
+- [#137],[#179] foreach issues (hasNext)
+- [#144] Plain text export - empty line fix
+- [#144] Not displaying texts
+- [#164] DefineMorphShape issues
+- [#167] Sprite tag appearing twice in export filename
+- [#170] AS3 Try in loop
+- [#172] loop detection fix
+- [#175] use empty namespace
+- [#178] AS subtract with negate
+- [#181] AS3 missing quotes in object field
+- [#182] missing namespace imports
+- [#183] wrong stage size
+- [#184] wrong video link
+- [#189] Fixed three dots in tree
+- [#191] Focalgradient fill fix
+- [#195] AS2 issues
+- [#196],[#197] switch issues
+- [#198] DefineFont2 empty check
+- [#200] DefineBitsLossLess fix
+- [#201] Nonworking main window in Linux/MacOS (due toAssociation)
+
+## [1.6.4 update 1] - 2013-06-30
+### Fixed
+- [#166] For loops detection
+- [#165] AS3:direct lookupswitch support
+
+## [1.6.4] - 2013-06-30
+### Added
+- [#63] Globally rename identifier
+- [#67] Deobfuscation - rename identifiers according to type
+- [#117] Drag & Drop SWF file to main window opens it
+- [#123] Context menu integration on Windows
+- [#127] Drag & Drop items from tree outside of application
+- [#134] AS3: Find document class
+- [#144] New lines in plain text export
+- [#155] Remembering window size + splitbar positions between runs
+
+### Changed
+- [#142] Using exportassets tag for tag names
+- [#146] Display AS2 classes as tree of packages
+- Better loop detection
+
+### Fixed
+- [#129] AS1/2: not refreshing decompiled after rename
+- [#130] Renaming SymbolClass identifiers too
+- [#132] Renaming identifiers renamed strings
+- [#136] Invalid text positions in FLA export
+- [#145] Unicode support
+- [#147] Escape filenames during obfuscated AS3 export
+- [#148] Better package vs classname handling
+- [#152] Empty if branches not inverted
+- [#156] Better search handling (not freezing)
+- [#157] AS3: Try statements in loops
+- [#158] Graph repaint problem
+- [#159] AS3: Improper rest parameter handling
+- [#160] Commandline binaryData export
+- [#162] DefineBitsJPEG2 image replacing
+- [#163] Closing SWF file after loading
+- other minor fixes
+
+## [1.6.3 update 2] - 2013-06-21
+### Changed
+- [#149] Ifs with empty onTrue branches now inverted
+
+### Fixed
+- [#150] Long line restriction removed
+
+## [1.6.3 update 1] - 2013-06-21
+### Fixed
+- Memory limit decreased - FFDec was not working on 32 bit JVM.
+
+## [1.6.3] - 2013-06-20
+### Changed
+- Parallel SpeedUp can be disabled in menu
+- Better loop detection
+
+### Fixed
+- [#119] Replacements file not found issue
+- [#101] AS1/2 postincrement fix
+- [#114],[#116],[#135],[#141] Fixed loop detection
+- [#102] Fixed loop highlighting in export
+- [#124] Flash player file path detection
+- [#128] Improved imports
+- [#135] CommentItem fix
+- [#129],[#131] Better deobfuscation
+- [#104] AS3 inc/dec local deobfuscation fix
+- [#113],[#133],[#140] Memory limit increased
+
+## [1.6.2] - 2013-06-09
+### Added
+- New loop detection algorithm
+
+### Changed
+- [#108] - Faster loading and decompiling (Parallelism)
+- Improved Internal flash viewer - shapes and morphshapes
+
+### Fixed
+- Ternar operator fix
+- [#102] Fixed Shapes to FLA export
+- AS1/2 class detection fix
+- [#105],[#104],[#101] fixed via new loop detection
+
+## [1.6.1] - 2013-06-03
+### Added
+- Internal Flash Viewer - preview of flash parts (shapes,sprites,frames) without need of Flash Player. (Used on nonWindows platforms by default)
+- [#109], [#106], [#107] some code improvements
+
+### Changed
+- Application needs Java 1.7 to run
+
+### Removed
+- Support for Java before 1.7
+
+### Fixed
+- [#102], [#110] AS3: Class highlight fix
+- [#103] AS3:Fixed setslot handling
+- [#104] AS3:Inc/Declocal nullpointer fix
+- [#104] Multiple conditions in loop fix
+- [#111] AS3:Object literal truncates line
+- [#105] Better do while..break handling
+- loop fixes
+
+## [1.6.0 update 1] - 2013-05-25
+### Added
+- better FLA export
+
+### Fixed
+- Many FLA export related bugs (like [#96])
+- [#98] Empty initializers do not cause empty lines now
+- [#99] small logging issues
+- [#100] large obfuscated code support
+
+## [1.6.0] - 2013-05-20
+### Added
+- Export to FLA (Experimental BETA!)
+- [#85] Search text in all ActionScripts
+- SWF 11 support
+
+### Fixed
+- [#79] ActionStartDrag constraint fix
+- [#92] Inversed GreaterThan/LessThan
+- [#93] AS1/2 fixed switch detection
+- [#94] AS1/2 ActionTry - register cast fix
+- [#95] Better script end handling
+
+## [1.5.2] - 2013-05-05
+### Added
+- Improved automatic update system (changes log).
+- Handling script traits as separate objects.
+- [#86] open/save file dialog now accepts absolute paths in quotes
+
+### Fixed
+- [#87] Not displaying image changes in DefineBitsLossLess1 & 2
+- [#88] Fixed graph building
+- [#89] AS3: bracket in property name lead to missing dot
+- [#82] printgraph issue
+
+## [1.5.1 update 1] - 2013-05-04
+### Added
+- Exporting texts via commandline
+- Exporting all via commandline
+
+### Fixed
+- DefineText2 color parameter
+- AS3 GetSlot,SetSlot
+- [#78],[#81],[#82],[#84] Fixed deobfuscation, exceptions during printgraph,...
+- [#83] Fixed images transparency (zlib fix)
+- Fixed graphparts with only jump in it (obfuscators)
+- MORPHGRADIENT FIX
+- Trasparency in DefineBitsJPEG3 and 4
+- Displaying shapes,morphshapes and sprites with bitmaps
+
+## [1.5.1] - 2013-05-01
+### Added
+- Support for larger switches (10+cases)
+- Editing text tags
+- [#65] Exporting text tags
+- Removing sprites
+- Replacing images
+
+### Fixed
+- DefineMorphShape2 fix
+- [#79] - AS1/2 class detection fix, wrong printgraph fix
+- [#78] - script trait slots fix
+
+## [1.5.0 update 1] - 2013-04-21
+### Fixed
+- Automatic deobfuscation config defaulted to Off for AS1/2.
+
+## [1.5.0] - 2013-04-20
+### Added
+- Direct editing of ActionScript 1/2 code (Beta)
+- AS1/2: ifFrameLoaded support
+- Automatic deobfuscation can be disabled in the menu
+- [#48] - Decompile only specified class (commandline option)
+- [#53] - AS3: Displaying multiname indices in trait detail, displaying method indices
+- [#66] - Decompressing LZMA via commandline
+- [#68] - Exporting DefineBinaryData tags, assigning class names to characters (SymbolClass tag)
+- [#69] - DoABC vs DoABCDefine tags decompilation
+- [#75] - Comma separator in while/do..while conditions, better if..return handling
+- AS1/2: parsing NaN,Infinity value (Fix for [#73])
+
+### Changed
+- New icons (edit/save/cancel and main menu)
+
+### Fixed
+- [#62] - Errors on not defined character tags (import tag)
+- [#72] - First ternary operator expression was always true
+- Fixed many deobfuscation related bugs
+
+## [1.4.3 update 2] - 2013-04-10
+### Fixed
+- [#64] - AS1/2 Resolving registers in ActionDefineFunction2 (super,this,...and parameters shown as registerxx)
+- Try to fix lib/FlashPlayer.exe issue
+
+## [1.4.3 update 1] - 2013-04-06
+### Fixed
+- [#38] - Indentation in const/var initializers, missing semicolon
+- [#56] - Test output left in last release
+- [#57] - Unknown instructions now do not log an exception (obfuscators do this)
+- [#58] - Index out of bounds exception fix on methodinfo indices in imports detection.
+- AS3 loops fix
+- While true fix
+
+## [1.4.3] - 2013-04-04
+### Added
+- AS1/2 Better deobfuscation
+
+### Fixed
+- [#45] - Unicode characters fix
+- [#50] - AS1/2 Function body deobfuscation fix
+- [#51] - Displaying java class names instead of expressions
+- [#52] - AS1/2 Better constantpool detection (deobfuscation)
+- [#38] - AS3 indentation in initialized const/var value for newobject
+- Fixed ImportAssets2 tag id
+
+## [1.4.2 update 1] - 2013-03-25
+### Fixed
+- [#47] - wrong AS3 deobfuscation
+- AS3 deobfuscation issues
+- AS3 switch
+
+## [1.4.2] - 2013-03-24
+### Added
+- [#42] - Displaying code as hex
+- AS1/2: Renaming identifiers (deobfuscation)
+- AS1/2,AS3: Better deobfuscation
+- Storing configuration to user home
+- Installer for Windows systems
+
+### Changed
+- Graph button changed to icon.
+
+### Fixed
+- [#39] - AS1/2 NewMethod..Pop fix
+- [#40] - No logging + For..in..return decompilation
+- [#44] - DefineFont2 fix
+- [#36] - Multiname with invalid index
+- [#43] - Ternary operator and more
+- [#46] - Ifs with empty branches got ignored
+- [#3] - Ignoring unknown opcodes
+- Logging exceptions during export
+
+## [1.4.1] - 2013-03-10
+### Added
+- Exporting sounds
+- Better AS1/2 deobfuscation (disassembly & decompilation)
+
+### Fixed
+- Exporting only first 1000 frames of the movie
+- Decompiled code was not refreshed on AS1/2 changes
+- Application no longer creates empty directories on export
+
+## [1.4.0 update 1] - 2013-03-04
+### Fixed
+- [#37] - AS3: Reversed loop conditions
+
+## [1.4.0] - 2013-03-03
+### Added
+- AS3: ignoring return void at the end of methods
+- New icons - Silk icons
+- AS3: Traits list sort button
+- Better Graph display
+- Frames view
+- Exporting of movies (No audio)
+- Some AS3 related Tests
+- Homepage & Donate link in the menu
+
+### Changed
+- Tree view instead of tabs
+- AS1/2 and AS3 now share same decompiling method.
+
+### Fixed
+- [#34] - Reversed loop conditions
+- [#35] - Fixed unicode strings (Japanese)
+
+## [1.3.1] - 2013-02-23
+### Changed
+- Flash player no longer uses SWT library
+
+### Fixed
+- [#32] - AS2: Action255 bug
+- [#31] - Erorrneous tags are now ignored
+- DefineBitsLossLess 1&2 on 8bit colormapped images
+
+## [1.3.0] - 2013-02-17
+### Added
+- Decompilation is more resistant to obfuscation
+- Shapes SVG export
+- AS2: Decompiling classes & interfaces
+- Click&go feature - clicking actionscript source displays appropriate P-code instruction and vice-versa (both AS1/2 and AS3)
+- AS3: Deobfuscation menu
+- Graph button for displaying code flow Graph
+
+### Changed
+- Complete new decompiling method in both AS1/2 and AS3
+- Application renamed from "JP ActionScript Decompiler" to "JPEXS Free Flash Decompiler".
+- To edit source, Edit button must be pressed first (Due to click&go feature)
+
+### Fixed
+- AS3: Method info editor fixed
+- Edittext & Button displaying
+
+## [1.2.0] - 2013-01-19
+### Added
+- Displaying various SWF objects (shapes, sprites,...) with flash player library (Windows only, sorry).
+- Images display and export
+- AS2: Exporting selection
+- Progressbar during loading
+
+### Changed
+- One merged window for AS1/2 and 3.
+- Updated icons
+
+### Fixed
+- AS3: xml attrib, switch in anonymous function (in AS2 too)
+
+## [1.1.0] - 2013-01-02
+### Added
+- Checking for updates
+- AS2: Exporting
+- AS3: Decompiling whole scripts instead of just classes
+- AS3: Exporting selected scripts
+- AS3: Script search bar
+- AS3: List of DoABCTags now has default "- all -" item
+- AS3: Better imports, use namespaces
+- AS3: XML related instructions
+- AS3: Anonymous functions with names
+- AS3: Better initialization of const values
+- Logging exceptions to log.txt file
+
+### Fixed
+- AS3: set_local..get_local, dup, chained assignments, highlighting, callsupervoid, typenames, with statement, loops
+
+## [1.0.1] - 2012-12-26
+### Added
+- AS3: Runtime namespace resolving
+- AS3: Arguments variable
+- AS3: Better recognizing Pre/Post Increments/Decrements
+- AS3: Better declarations
+
+### Fixed
+- AS3: Fixed static variables
+
+## [1.0.0] - 2012-12-24
+### Added
+- Support for LZMA compressed files
+- AS3: Detecting local register types for declaration.
+- AS3: Displaying inline functions
+- AS3: Last save/open dir is remembered
+- AS3: Better usage detection for multinames
+- AS3: Commandline arguments for exporting
+- AS3: Better chained assignments
+- AS2: FSCommand2 instruction support
+- Proxy: Mimetype application/octet-stream added
+- Added executable for Windows users.
+
+### Changed
+- AS3: GUI - Constants tab moved to the top
+- AS3: Deobfuscation is now optional, can be accessed via menu
+
+### Fixed
+- AS3: rest parameter, for..in, fail on large classes (due to sub limiter)
+- Other minor fixes
+
+## [beta 1] - 2011-07-30
+### Added
+- AS3: Automatic computing method body parameters (EXPERIMENTAL)
+- AS3: Editing return type of methods
+- AS3: Editing type and default value for variables/constants (Slot/Const traits)
+- AS1/2: Few enhancements
+- About dialog
+
+### Changed
+- Gui: Updated Icons
+
+### Fixed
+- AS 1/2: Fixed large bug causing Ifs to not decompile properly
+- Proxy: Some minor fixes
+
+## [alpha 10] - 2011-07-13
+### Added
+- AS3:Highlighting actual line
+- AS3:Completing instruction names via Ctrl+Space
+- AS3:Editing method parameters, method body parameters via tab panel
+- AS3:ByteCode minor_version 17 supported - decimal datatypes
+- AS3:Local variables and method parameters take name from debug information if present
+- AS3:Automatic renaming of classes/methods when obfuscated names
+- AS3:Better error messages (When cannot decompile obfuscated code)
+
+### Fixed
+- AS3:Fixed Vector datatypes (TypeName multiname, applytype instruction)
+- AS3:Hilighting fixes
+- AS3:Fixed decrement/increment statements decompilation
+- AS3:Decompiler now adds variable declarations on the beginning of decompiled method
+- AS3:Try/catch statements fixed when debug information present
+- AS3:Fixed for each statements
+- AS3:Other minor fixes
+
+## [alpha 9] - 2011-07-02
+### Added
+- AS3: Added disassembling of some new types of instructions
+- AS3: Exporting source as PCode
+
+### Fixed
+- AS3: Many other bugfixes...
+
+## [alpha 8] - 2010-09-19
+### Added
+- AS3: Editing exceptions
+- AS3: Finding usage of multinames from constant table
+
+### Changed
+- AS1/2: Better GUI
+- AS1/2: Better decompiling of Ifs, For..in
+
+## [alpha 7] - 2010-09-04
+### Added
+- Initial public release
+
+[Unreleased]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version9.0.0...dev
+[9.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version8.0.1...version9.0.0
+[8.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version8.0.0...version8.0.1
+[8.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.1.2...version8.0.0
+[7.1.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.1.1...version7.1.2
+[7.1.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.1.0...version7.1.1
+[7.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.0.1...version7.1.0
+[7.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version7.0.0...version7.0.1
+[7.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.1.1...version7.0.0
+[6.1.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.1.0...version6.1.1
+[6.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.0.2...version6.1.0
+[6.0.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.0.1...version6.0.2
+[6.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version6.0.0...version6.0.1
+[6.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.3.0...version6.0.0
+[5.3.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.2.0...version5.3.0
+[5.2.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.1.0...version5.2.0
+[5.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.0.2...version5.1.0
+[5.0.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.0.1...version5.0.2
+[5.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version5.0.0...version5.0.1
+[5.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.1.1...version5.0.0
+[4.1.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.1.0...version4.1.1
+[4.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.5...version4.1.0
+[4.0.5]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.4...version4.0.5
+[4.0.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.3...version4.0.4
+[4.0.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.2...version4.0.3
+[4.0.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.1...version4.0.2
+[4.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version4.0.0...version4.0.1
+[4.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version3.0.0...version4.0.0
+[3.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.4...version3.0.0
+[2.1.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.3...version2.1.4
+[2.1.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.2...version2.1.3
+[2.1.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.1...version2.1.2
+[2.1.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.0u2...version2.1.1
+[2.1.0 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.0u1...version2.1.0u2
+[2.1.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.1.0...version2.1.0u1
+[2.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.0.1u2...version2.1.0
+[2.0.1 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.0.1u1...version2.0.1u2
+[2.0.1 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.0.1...version2.0.1u1
+[2.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version2.0.0...version2.0.1
+[2.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.8.1u1...version2.0.0
+[1.8.1 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.8.1...version1.8.1u1
+[1.8.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.8.0u1...version1.8.1
+[1.8.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.8.0...version1.8.0u1
+[1.8.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.4u1...version1.8.0
+[1.7.4 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.4...version1.7.4u1
+[1.7.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.3u2...version1.7.4
+[1.7.3 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.3u1...version1.7.3u2
+[1.7.3 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.3...version1.7.3u1
+[1.7.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.2u2...version1.7.3
+[1.7.2 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.2u1...version1.7.2u2
+[1.7.2 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.2...version1.7.2u1
+[1.7.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.1...version1.7.2
+[1.7.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.0u1...version1.7.1
+[1.7.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.7.0...version1.7.0u1
+[1.7.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.7...version1.7.0
+[1.6.7]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.6u2...version1.6.7
+[1.6.6 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.6u1...version1.6.6u2
+[1.6.6 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.6...version1.6.6u1
+[1.6.6]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.5u1...version1.6.6
+[1.6.5 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.5...version1.6.5u1
+[1.6.5]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.4u1...version1.6.5
+[1.6.4 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.4...version1.6.4u1
+[1.6.4]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.3u2...version1.6.4
+[1.6.3 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.3u1...version1.6.3u2
+[1.6.3 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.3...version1.6.3u1
+[1.6.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.2...version1.6.3
+[1.6.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.1...version1.6.2
+[1.6.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.0u1...version1.6.1
+[1.6.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.6.0...version1.6.0u1
+[1.6.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.2...version1.6.0
+[1.5.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.1u1...version1.5.2
+[1.5.1 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.1...version1.5.1u1
+[1.5.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.0u1...version1.5.1
+[1.5.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.5.0...version1.5.0u1
+[1.5.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.3u2...version1.5.0
+[1.4.3 update 2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.3u1...version1.4.3u2
+[1.4.3 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.3...version1.4.3u1
+[1.4.3]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.2u1...version1.4.3
+[1.4.2 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.2...version1.4.2u1
+[1.4.2]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.1...version1.4.2
+[1.4.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.0u1...version1.4.1
+[1.4.0 update 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.4.0...version1.4.0u1
+[1.4.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.3.1...version1.4.0
+[1.3.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.3.0...version1.3.1
+[1.3.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.2.0...version1.3.0
+[1.2.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.1.0...version1.2.0
+[1.1.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.0.1...version1.1.0
+[1.0.1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/version1.0.0...version1.0.1
+[1.0.0]: https://github.com/jindrapetrik/jpexs-decompiler/compare/beta1...version1.0.0
+[beta 1]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha10...beta1
+[alpha 10]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha9...alpha10
+[alpha 9]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha8...alpha9
+[alpha 8]: https://github.com/jindrapetrik/jpexs-decompiler/compare/alpha7...alpha8
+[alpha 7]: https://github.com/jindrapetrik/jpexs-decompiler/releases/tag/alpha7
+[#1156]: https://www.free-decompiler.com/flash/issues/1156
+[#1171]: https://www.free-decompiler.com/flash/issues/1171
+[#1170]: https://www.free-decompiler.com/flash/issues/1170
+[#1241]: https://www.free-decompiler.com/flash/issues/1241
+[#1162]: https://www.free-decompiler.com/flash/issues/1162
+[#1199]: https://www.free-decompiler.com/flash/issues/1199
+[#1151]: https://www.free-decompiler.com/flash/issues/1151
+[#1128]: https://www.free-decompiler.com/flash/issues/1128
+[#1163]: https://www.free-decompiler.com/flash/issues/1163
+[#1172]: https://www.free-decompiler.com/flash/issues/1172
+[#1174]: https://www.free-decompiler.com/flash/issues/1174
+[#1183]: https://www.free-decompiler.com/flash/issues/1183
+[#1193]: https://www.free-decompiler.com/flash/issues/1193
+[#1200]: https://www.free-decompiler.com/flash/issues/1200
+[#1198]: https://www.free-decompiler.com/flash/issues/1198
+[#1205]: https://www.free-decompiler.com/flash/issues/1205
+[#1194]: https://www.free-decompiler.com/flash/issues/1194
+[#1210]: https://www.free-decompiler.com/flash/issues/1210
+[#1217]: https://www.free-decompiler.com/flash/issues/1217
+[#1244]: https://www.free-decompiler.com/flash/issues/1244
+[#1247]: https://www.free-decompiler.com/flash/issues/1247
+[#1236]: https://www.free-decompiler.com/flash/issues/1236
+[#1251]: https://www.free-decompiler.com/flash/issues/1251
+[#1265]: https://www.free-decompiler.com/flash/issues/1265
+[#1268]: https://www.free-decompiler.com/flash/issues/1268
+[#1161]: https://www.free-decompiler.com/flash/issues/1161
+[#1118]: https://www.free-decompiler.com/flash/issues/1118
+[#409]: https://www.free-decompiler.com/flash/issues/409
+[#1132]: https://www.free-decompiler.com/flash/issues/1132
+[#1134]: https://www.free-decompiler.com/flash/issues/1134
+[#1121]: https://www.free-decompiler.com/flash/issues/1121
+[#1052]: https://www.free-decompiler.com/flash/issues/1052
+[#1145]: https://www.free-decompiler.com/flash/issues/1145
+[#758]: https://www.free-decompiler.com/flash/issues/758
+[#1096]: https://www.free-decompiler.com/flash/issues/1096
+[#1104]: https://www.free-decompiler.com/flash/issues/1104
+[#1107]: https://www.free-decompiler.com/flash/issues/1107
+[#1106]: https://www.free-decompiler.com/flash/issues/1106
+[#1113]: https://www.free-decompiler.com/flash/issues/1113
+[#1075]: https://www.free-decompiler.com/flash/issues/1075
+[#1127]: https://www.free-decompiler.com/flash/issues/1127
+[#1103]: https://www.free-decompiler.com/flash/issues/1103
+[#1133]: https://www.free-decompiler.com/flash/issues/1133
+[#1135]: https://www.free-decompiler.com/flash/issues/1135
+[#1138]: https://www.free-decompiler.com/flash/issues/1138
+[#1139]: https://www.free-decompiler.com/flash/issues/1139
+[#930]: https://www.free-decompiler.com/flash/issues/930
+[#1137]: https://www.free-decompiler.com/flash/issues/1137
+[#1144]: https://www.free-decompiler.com/flash/issues/1144
+[#1147]: https://www.free-decompiler.com/flash/issues/1147
+[#1148]: https://www.free-decompiler.com/flash/issues/1148
+[#1152]: https://www.free-decompiler.com/flash/issues/1152
+[#1154]: https://www.free-decompiler.com/flash/issues/1154
+[#116]: https://www.free-decompiler.com/flash/issues/116
+[#1070]: https://www.free-decompiler.com/flash/issues/1070
+[#1098]: https://www.free-decompiler.com/flash/issues/1098
+[#1033]: https://www.free-decompiler.com/flash/issues/1033
+[#1083]: https://www.free-decompiler.com/flash/issues/1083
+[#1091]: https://www.free-decompiler.com/flash/issues/1091
+[#1076]: https://www.free-decompiler.com/flash/issues/1076
+[#1068]: https://www.free-decompiler.com/flash/issues/1068
+[#1063]: https://www.free-decompiler.com/flash/issues/1063
+[#1019]: https://www.free-decompiler.com/flash/issues/1019
+[#1016]: https://www.free-decompiler.com/flash/issues/1016
+[#1010]: https://www.free-decompiler.com/flash/issues/1010
+[#1008]: https://www.free-decompiler.com/flash/issues/1008
+[#1004]: https://www.free-decompiler.com/flash/issues/1004
+[#933]: https://www.free-decompiler.com/flash/issues/933
+[#1062]: https://www.free-decompiler.com/flash/issues/1062
+[#418]: https://www.free-decompiler.com/flash/issues/418
+[#1047]: https://www.free-decompiler.com/flash/issues/1047
+[#812]: https://www.free-decompiler.com/flash/issues/812
+[#1056]: https://www.free-decompiler.com/flash/issues/1056
+[#1057]: https://www.free-decompiler.com/flash/issues/1057
+[#991]: https://www.free-decompiler.com/flash/issues/991
+[#689]: https://www.free-decompiler.com/flash/issues/689
+[#1060]: https://www.free-decompiler.com/flash/issues/1060
+[#1037]: https://www.free-decompiler.com/flash/issues/1037
+[#489]: https://www.free-decompiler.com/flash/issues/489
+[#1007]: https://www.free-decompiler.com/flash/issues/1007
+[#1044]: https://www.free-decompiler.com/flash/issues/1044
+[#947]: https://www.free-decompiler.com/flash/issues/947
+[#953]: https://www.free-decompiler.com/flash/issues/953
+[#954]: https://www.free-decompiler.com/flash/issues/954
+[#950]: https://www.free-decompiler.com/flash/issues/950
+[#945]: https://www.free-decompiler.com/flash/issues/945
+[#957]: https://www.free-decompiler.com/flash/issues/957
+[#956]: https://www.free-decompiler.com/flash/issues/956
+[#968]: https://www.free-decompiler.com/flash/issues/968
+[#978]: https://www.free-decompiler.com/flash/issues/978
+[#955]: https://www.free-decompiler.com/flash/issues/955
+[#966]: https://www.free-decompiler.com/flash/issues/966
+[#999]: https://www.free-decompiler.com/flash/issues/999
+[#1000]: https://www.free-decompiler.com/flash/issues/1000
+[#1017]: https://www.free-decompiler.com/flash/issues/1017
+[#1030]: https://www.free-decompiler.com/flash/issues/1030
+[#949]: https://www.free-decompiler.com/flash/issues/949
+[#944]: https://www.free-decompiler.com/flash/issues/944
+[#939]: https://www.free-decompiler.com/flash/issues/939
+[#942]: https://www.free-decompiler.com/flash/issues/942
+[#952]: https://www.free-decompiler.com/flash/issues/952
+[#858]: https://www.free-decompiler.com/flash/issues/858
+[#905]: https://www.free-decompiler.com/flash/issues/905
+[#920]: https://www.free-decompiler.com/flash/issues/920
+[#921]: https://www.free-decompiler.com/flash/issues/921
+[#924]: https://www.free-decompiler.com/flash/issues/924
+[#895]: https://www.free-decompiler.com/flash/issues/895
+[#884]: https://www.free-decompiler.com/flash/issues/884
+[#899]: https://www.free-decompiler.com/flash/issues/899
+[#903]: https://www.free-decompiler.com/flash/issues/903
+[#855]: https://www.free-decompiler.com/flash/issues/855
+[#850]: https://www.free-decompiler.com/flash/issues/850
+[#832]: https://www.free-decompiler.com/flash/issues/832
+[#904]: https://www.free-decompiler.com/flash/issues/904
+[#910]: https://www.free-decompiler.com/flash/issues/910
+[#922]: https://www.free-decompiler.com/flash/issues/922
+[#916]: https://www.free-decompiler.com/flash/issues/916
+[#938]: https://www.free-decompiler.com/flash/issues/938
+[#897]: https://www.free-decompiler.com/flash/issues/897
+[#470]: https://www.free-decompiler.com/flash/issues/470
+[#877]: https://www.free-decompiler.com/flash/issues/877
+[#878]: https://www.free-decompiler.com/flash/issues/878
+[#845]: https://www.free-decompiler.com/flash/issues/845
+[#883]: https://www.free-decompiler.com/flash/issues/883
+[#882]: https://www.free-decompiler.com/flash/issues/882
+[#760]: https://www.free-decompiler.com/flash/issues/760
+[#887]: https://www.free-decompiler.com/flash/issues/887
+[#842]: https://www.free-decompiler.com/flash/issues/842
+[#841]: https://www.free-decompiler.com/flash/issues/841
+[#772]: https://www.free-decompiler.com/flash/issues/772
+[#762]: https://www.free-decompiler.com/flash/issues/762
+[#862]: https://www.free-decompiler.com/flash/issues/862
+[#865]: https://www.free-decompiler.com/flash/issues/865
+[#613]: https://www.free-decompiler.com/flash/issues/613
+[#868]: https://www.free-decompiler.com/flash/issues/868
+[#713]: https://www.free-decompiler.com/flash/issues/713
+[#807]: https://www.free-decompiler.com/flash/issues/807
+[#728]: https://www.free-decompiler.com/flash/issues/728
+[#857]: https://www.free-decompiler.com/flash/issues/857
+[#860]: https://www.free-decompiler.com/flash/issues/860
+[#824]: https://www.free-decompiler.com/flash/issues/824
+[#809]: https://www.free-decompiler.com/flash/issues/809
+[#805]: https://www.free-decompiler.com/flash/issues/805
+[#825]: https://www.free-decompiler.com/flash/issues/825
+[#737]: https://www.free-decompiler.com/flash/issues/737
+[#350]: https://www.free-decompiler.com/flash/issues/350
+[#814]: https://www.free-decompiler.com/flash/issues/814
+[#816]: https://www.free-decompiler.com/flash/issues/816
+[#835]: https://www.free-decompiler.com/flash/issues/835
+[#836]: https://www.free-decompiler.com/flash/issues/836
+[#848]: https://www.free-decompiler.com/flash/issues/848
+[#817]: https://www.free-decompiler.com/flash/issues/817
+[#849]: https://www.free-decompiler.com/flash/issues/849
+[#852]: https://www.free-decompiler.com/flash/issues/852
+[#837]: https://www.free-decompiler.com/flash/issues/837
+[#811]: https://www.free-decompiler.com/flash/issues/811
+[#745]: https://www.free-decompiler.com/flash/issues/745
+[#803]: https://www.free-decompiler.com/flash/issues/803
+[#738]: https://www.free-decompiler.com/flash/issues/738
+[#742]: https://www.free-decompiler.com/flash/issues/742
+[#747]: https://www.free-decompiler.com/flash/issues/747
+[#749]: https://www.free-decompiler.com/flash/issues/749
+[#752]: https://www.free-decompiler.com/flash/issues/752
+[#753]: https://www.free-decompiler.com/flash/issues/753
+[#759]: https://www.free-decompiler.com/flash/issues/759
+[#766]: https://www.free-decompiler.com/flash/issues/766
+[#768]: https://www.free-decompiler.com/flash/issues/768
+[#773]: https://www.free-decompiler.com/flash/issues/773
+[#776]: https://www.free-decompiler.com/flash/issues/776
+[#783]: https://www.free-decompiler.com/flash/issues/783
+[#785]: https://www.free-decompiler.com/flash/issues/785
+[#787]: https://www.free-decompiler.com/flash/issues/787
+[#788]: https://www.free-decompiler.com/flash/issues/788
+[#790]: https://www.free-decompiler.com/flash/issues/790
+[#794]: https://www.free-decompiler.com/flash/issues/794
+[#798]: https://www.free-decompiler.com/flash/issues/798
+[#800]: https://www.free-decompiler.com/flash/issues/800
+[#676]: https://www.free-decompiler.com/flash/issues/676
+[#734]: https://www.free-decompiler.com/flash/issues/734
+[#687]: https://www.free-decompiler.com/flash/issues/687
+[#709]: https://www.free-decompiler.com/flash/issues/709
+[#732]: https://www.free-decompiler.com/flash/issues/732
+[#730]: https://www.free-decompiler.com/flash/issues/730
+[#735]: https://www.free-decompiler.com/flash/issues/735
+[#722]: https://www.free-decompiler.com/flash/issues/722
+[#725]: https://www.free-decompiler.com/flash/issues/725
+[#715]: https://www.free-decompiler.com/flash/issues/715
+[#635]: https://www.free-decompiler.com/flash/issues/635
+[#726]: https://www.free-decompiler.com/flash/issues/726
+[#716]: https://www.free-decompiler.com/flash/issues/716
+[#717]: https://www.free-decompiler.com/flash/issues/717
+[#718]: https://www.free-decompiler.com/flash/issues/718
+[#720]: https://www.free-decompiler.com/flash/issues/720
+[#719]: https://www.free-decompiler.com/flash/issues/719
+[#723]: https://www.free-decompiler.com/flash/issues/723
+[#288]: https://www.free-decompiler.com/flash/issues/288
+[#677]: https://www.free-decompiler.com/flash/issues/677
+[#389]: https://www.free-decompiler.com/flash/issues/389
+[#701]: https://www.free-decompiler.com/flash/issues/701
+[#707]: https://www.free-decompiler.com/flash/issues/707
+[#302]: https://www.free-decompiler.com/flash/issues/302
+[#685]: https://www.free-decompiler.com/flash/issues/685
+[#698]: https://www.free-decompiler.com/flash/issues/698
+[#710]: https://www.free-decompiler.com/flash/issues/710
+[#711]: https://www.free-decompiler.com/flash/issues/711
+[#681]: https://www.free-decompiler.com/flash/issues/681
+[#688]: https://www.free-decompiler.com/flash/issues/688
+[#691]: https://www.free-decompiler.com/flash/issues/691
+[#524]: https://www.free-decompiler.com/flash/issues/524
+[#663]: https://www.free-decompiler.com/flash/issues/663
+[#702]: https://www.free-decompiler.com/flash/issues/702
+[#539]: https://www.free-decompiler.com/flash/issues/539
+[#650]: https://www.free-decompiler.com/flash/issues/650
+[#680]: https://www.free-decompiler.com/flash/issues/680
+[#649]: https://www.free-decompiler.com/flash/issues/649
+[#656]: https://www.free-decompiler.com/flash/issues/656
+[#661]: https://www.free-decompiler.com/flash/issues/661
+[#664]: https://www.free-decompiler.com/flash/issues/664
+[#668]: https://www.free-decompiler.com/flash/issues/668
+[#674]: https://www.free-decompiler.com/flash/issues/674
+[#675]: https://www.free-decompiler.com/flash/issues/675
+[#632]: https://www.free-decompiler.com/flash/issues/632
+[#651]: https://www.free-decompiler.com/flash/issues/651
+[#678]: https://www.free-decompiler.com/flash/issues/678
+[#672]: https://www.free-decompiler.com/flash/issues/672
+[#684]: https://www.free-decompiler.com/flash/issues/684
+[#647]: https://www.free-decompiler.com/flash/issues/647
+[#648]: https://www.free-decompiler.com/flash/issues/648
+[#612]: https://www.free-decompiler.com/flash/issues/612
+[#623]: https://www.free-decompiler.com/flash/issues/623
+[#624]: https://www.free-decompiler.com/flash/issues/624
+[#627]: https://www.free-decompiler.com/flash/issues/627
+[#640]: https://www.free-decompiler.com/flash/issues/640
+[#595]: https://www.free-decompiler.com/flash/issues/595
+[#592]: https://www.free-decompiler.com/flash/issues/592
+[#585]: https://www.free-decompiler.com/flash/issues/585
+[#578]: https://www.free-decompiler.com/flash/issues/578
+[#501]: https://www.free-decompiler.com/flash/issues/501
+[#616]: https://www.free-decompiler.com/flash/issues/616
+[#559]: https://www.free-decompiler.com/flash/issues/559
+[#401]: https://www.free-decompiler.com/flash/issues/401
+[#593]: https://www.free-decompiler.com/flash/issues/593
+[#594]: https://www.free-decompiler.com/flash/issues/594
+[#579]: https://www.free-decompiler.com/flash/issues/579
+[#428]: https://www.free-decompiler.com/flash/issues/428
+[#337]: https://www.free-decompiler.com/flash/issues/337
+[#584]: https://www.free-decompiler.com/flash/issues/584
+[#576]: https://www.free-decompiler.com/flash/issues/576
+[#250]: https://www.free-decompiler.com/flash/issues/250
+[#580]: https://www.free-decompiler.com/flash/issues/580
+[#510]: https://www.free-decompiler.com/flash/issues/510
+[#583]: https://www.free-decompiler.com/flash/issues/583
+[#586]: https://www.free-decompiler.com/flash/issues/586
+[#574]: https://www.free-decompiler.com/flash/issues/574
+[#570]: https://www.free-decompiler.com/flash/issues/570
+[#563]: https://www.free-decompiler.com/flash/issues/563
+[#561]: https://www.free-decompiler.com/flash/issues/561
+[#509]: https://www.free-decompiler.com/flash/issues/509
+[#433]: https://www.free-decompiler.com/flash/issues/433
+[#557]: https://www.free-decompiler.com/flash/issues/557
+[#556]: https://www.free-decompiler.com/flash/issues/556
+[#504]: https://www.free-decompiler.com/flash/issues/504
+[#529]: https://www.free-decompiler.com/flash/issues/529
+[#538]: https://www.free-decompiler.com/flash/issues/538
+[#537]: https://www.free-decompiler.com/flash/issues/537
+[#540]: https://www.free-decompiler.com/flash/issues/540
+[#387]: https://www.free-decompiler.com/flash/issues/387
+[#552]: https://www.free-decompiler.com/flash/issues/552
+[#494]: https://www.free-decompiler.com/flash/issues/494
+[#513]: https://www.free-decompiler.com/flash/issues/513
+[#262]: https://www.free-decompiler.com/flash/issues/262
+[#499]: https://www.free-decompiler.com/flash/issues/499
+[#508]: https://www.free-decompiler.com/flash/issues/508
+[#305]: https://www.free-decompiler.com/flash/issues/305
+[#312]: https://www.free-decompiler.com/flash/issues/312
+[#503]: https://www.free-decompiler.com/flash/issues/503
+[#304]: https://www.free-decompiler.com/flash/issues/304
+[#306]: https://www.free-decompiler.com/flash/issues/306
+[#507]: https://www.free-decompiler.com/flash/issues/507
+[#424]: https://www.free-decompiler.com/flash/issues/424
+[#425]: https://www.free-decompiler.com/flash/issues/425
+[#478]: https://www.free-decompiler.com/flash/issues/478
+[#485]: https://www.free-decompiler.com/flash/issues/485
+[#517]: https://www.free-decompiler.com/flash/issues/517
+[#518]: https://www.free-decompiler.com/flash/issues/518
+[#361]: https://www.free-decompiler.com/flash/issues/361
+[#392]: https://www.free-decompiler.com/flash/issues/392
+[#516]: https://www.free-decompiler.com/flash/issues/516
+[#495]: https://www.free-decompiler.com/flash/issues/495
+[#496]: https://www.free-decompiler.com/flash/issues/496
+[#299]: https://www.free-decompiler.com/flash/issues/299
+[#303]: https://www.free-decompiler.com/flash/issues/303
+[#324]: https://www.free-decompiler.com/flash/issues/324
+[#346]: https://www.free-decompiler.com/flash/issues/346
+[#371]: https://www.free-decompiler.com/flash/issues/371
+[#426]: https://www.free-decompiler.com/flash/issues/426
+[#457]: https://www.free-decompiler.com/flash/issues/457
+[#458]: https://www.free-decompiler.com/flash/issues/458
+[#460]: https://www.free-decompiler.com/flash/issues/460
+[#462]: https://www.free-decompiler.com/flash/issues/462
+[#463]: https://www.free-decompiler.com/flash/issues/463
+[#465]: https://www.free-decompiler.com/flash/issues/465
+[#466]: https://www.free-decompiler.com/flash/issues/466
+[#369]: https://www.free-decompiler.com/flash/issues/369
+[#390]: https://www.free-decompiler.com/flash/issues/390
+[#453]: https://www.free-decompiler.com/flash/issues/453
+[#459]: https://www.free-decompiler.com/flash/issues/459
+[#461]: https://www.free-decompiler.com/flash/issues/461
+[#451]: https://www.free-decompiler.com/flash/issues/451
+[#454]: https://www.free-decompiler.com/flash/issues/454
+[#455]: https://www.free-decompiler.com/flash/issues/455
+[#474]: https://www.free-decompiler.com/flash/issues/474
+[#477]: https://www.free-decompiler.com/flash/issues/477
+[#481]: https://www.free-decompiler.com/flash/issues/481
+[#484]: https://www.free-decompiler.com/flash/issues/484
+[#493]: https://www.free-decompiler.com/flash/issues/493
+[#365]: https://www.free-decompiler.com/flash/issues/365
+[#366]: https://www.free-decompiler.com/flash/issues/366
+[#429]: https://www.free-decompiler.com/flash/issues/429
+[#447]: https://www.free-decompiler.com/flash/issues/447
+[#354]: https://www.free-decompiler.com/flash/issues/354
+[#438]: https://www.free-decompiler.com/flash/issues/438
+[#436]: https://www.free-decompiler.com/flash/issues/436
+[#446]: https://www.free-decompiler.com/flash/issues/446
+[#427]: https://www.free-decompiler.com/flash/issues/427
+[#405]: https://www.free-decompiler.com/flash/issues/405
+[#420]: https://www.free-decompiler.com/flash/issues/420
+[#421]: https://www.free-decompiler.com/flash/issues/421
+[#430]: https://www.free-decompiler.com/flash/issues/430
+[#397]: https://www.free-decompiler.com/flash/issues/397
+[#431]: https://www.free-decompiler.com/flash/issues/431
+[#169]: https://www.free-decompiler.com/flash/issues/169
+[#335]: https://www.free-decompiler.com/flash/issues/335
+[#404]: https://www.free-decompiler.com/flash/issues/404
+[#407]: https://www.free-decompiler.com/flash/issues/407
+[#399]: https://www.free-decompiler.com/flash/issues/399
+[#400]: https://www.free-decompiler.com/flash/issues/400
+[#398]: https://www.free-decompiler.com/flash/issues/398
+[#382]: https://www.free-decompiler.com/flash/issues/382
+[#396]: https://www.free-decompiler.com/flash/issues/396
+[#357]: https://www.free-decompiler.com/flash/issues/357
+[#391]: https://www.free-decompiler.com/flash/issues/391
+[#395]: https://www.free-decompiler.com/flash/issues/395
+[#334]: https://www.free-decompiler.com/flash/issues/334
+[#301]: https://www.free-decompiler.com/flash/issues/301
+[#383]: https://www.free-decompiler.com/flash/issues/383
+[#386]: https://www.free-decompiler.com/flash/issues/386
+[#367]: https://www.free-decompiler.com/flash/issues/367
+[#380]: https://www.free-decompiler.com/flash/issues/380
+[#292]: https://www.free-decompiler.com/flash/issues/292
+[#375]: https://www.free-decompiler.com/flash/issues/375
+[#378]: https://www.free-decompiler.com/flash/issues/378
+[#325]: https://www.free-decompiler.com/flash/issues/325
+[#210]: https://www.free-decompiler.com/flash/issues/210
+[#355]: https://www.free-decompiler.com/flash/issues/355
+[#313]: https://www.free-decompiler.com/flash/issues/313
+[#330]: https://www.free-decompiler.com/flash/issues/330
+[#332]: https://www.free-decompiler.com/flash/issues/332
+[#344]: https://www.free-decompiler.com/flash/issues/344
+[#295]: https://www.free-decompiler.com/flash/issues/295
+[#297]: https://www.free-decompiler.com/flash/issues/297
+[#307]: https://www.free-decompiler.com/flash/issues/307
+[#309]: https://www.free-decompiler.com/flash/issues/309
+[#310]: https://www.free-decompiler.com/flash/issues/310
+[#311]: https://www.free-decompiler.com/flash/issues/311
+[#327]: https://www.free-decompiler.com/flash/issues/327
+[#328]: https://www.free-decompiler.com/flash/issues/328
+[#333]: https://www.free-decompiler.com/flash/issues/333
+[#336]: https://www.free-decompiler.com/flash/issues/336
+[#338]: https://www.free-decompiler.com/flash/issues/338
+[#315]: https://www.free-decompiler.com/flash/issues/315
+[#123]: https://www.free-decompiler.com/flash/issues/123
+[#243]: https://www.free-decompiler.com/flash/issues/243
+[#326]: https://www.free-decompiler.com/flash/issues/326
+[#287]: https://www.free-decompiler.com/flash/issues/287
+[#290]: https://www.free-decompiler.com/flash/issues/290
+[#291]: https://www.free-decompiler.com/flash/issues/291
+[#294]: https://www.free-decompiler.com/flash/issues/294
+[#298]: https://www.free-decompiler.com/flash/issues/298
+[#296]: https://www.free-decompiler.com/flash/issues/296
+[#314]: https://www.free-decompiler.com/flash/issues/314
+[#316]: https://www.free-decompiler.com/flash/issues/316
+[#318]: https://www.free-decompiler.com/flash/issues/318
+[#319]: https://www.free-decompiler.com/flash/issues/319
+[#323]: https://www.free-decompiler.com/flash/issues/323
+[#223]: https://www.free-decompiler.com/flash/issues/223
+[#261]: https://www.free-decompiler.com/flash/issues/261
+[#269]: https://www.free-decompiler.com/flash/issues/269
+[#274]: https://www.free-decompiler.com/flash/issues/274
+[#275]: https://www.free-decompiler.com/flash/issues/275
+[#258]: https://www.free-decompiler.com/flash/issues/258
+[#267]: https://www.free-decompiler.com/flash/issues/267
+[#286]: https://www.free-decompiler.com/flash/issues/286
+[#233]: https://www.free-decompiler.com/flash/issues/233
+[#235]: https://www.free-decompiler.com/flash/issues/235
+[#263]: https://www.free-decompiler.com/flash/issues/263
+[#264]: https://www.free-decompiler.com/flash/issues/264
+[#265]: https://www.free-decompiler.com/flash/issues/265
+[#266]: https://www.free-decompiler.com/flash/issues/266
+[#281]: https://www.free-decompiler.com/flash/issues/281
+[#251]: https://www.free-decompiler.com/flash/issues/251
+[#257]: https://www.free-decompiler.com/flash/issues/257
+[#259]: https://www.free-decompiler.com/flash/issues/259
+[#260]: https://www.free-decompiler.com/flash/issues/260
+[#268]: https://www.free-decompiler.com/flash/issues/268
+[#272]: https://www.free-decompiler.com/flash/issues/272
+[#276]: https://www.free-decompiler.com/flash/issues/276
+[#220]: https://www.free-decompiler.com/flash/issues/220
+[#284]: https://www.free-decompiler.com/flash/issues/284
+[#232]: https://www.free-decompiler.com/flash/issues/232
+[#253]: https://www.free-decompiler.com/flash/issues/253
+[#137]: https://www.free-decompiler.com/flash/issues/137
+[#242]: https://www.free-decompiler.com/flash/issues/242
+[#244]: https://www.free-decompiler.com/flash/issues/244
+[#203]: https://www.free-decompiler.com/flash/issues/203
+[#225]: https://www.free-decompiler.com/flash/issues/225
+[#236]: https://www.free-decompiler.com/flash/issues/236
+[#245]: https://www.free-decompiler.com/flash/issues/245
+[#247]: https://www.free-decompiler.com/flash/issues/247
+[#248]: https://www.free-decompiler.com/flash/issues/248
+[#254]: https://www.free-decompiler.com/flash/issues/254
+[#255]: https://www.free-decompiler.com/flash/issues/255
+[#256]: https://www.free-decompiler.com/flash/issues/256
+[#241]: https://www.free-decompiler.com/flash/issues/241
+[#238]: https://www.free-decompiler.com/flash/issues/238
+[#239]: https://www.free-decompiler.com/flash/issues/239
+[#240]: https://www.free-decompiler.com/flash/issues/240
+[#237]: https://www.free-decompiler.com/flash/issues/237
+[#217]: https://www.free-decompiler.com/flash/issues/217
+[#219]: https://www.free-decompiler.com/flash/issues/219
+[#224]: https://www.free-decompiler.com/flash/issues/224
+[#121]: https://www.free-decompiler.com/flash/issues/121
+[#207]: https://www.free-decompiler.com/flash/issues/207
+[#151]: https://www.free-decompiler.com/flash/issues/151
+[#171]: https://www.free-decompiler.com/flash/issues/171
+[#206]: https://www.free-decompiler.com/flash/issues/206
+[#208]: https://www.free-decompiler.com/flash/issues/208
+[#209]: https://www.free-decompiler.com/flash/issues/209
+[#229]: https://www.free-decompiler.com/flash/issues/229
+[#213]: https://www.free-decompiler.com/flash/issues/213
+[#221]: https://www.free-decompiler.com/flash/issues/221
+[#226]: https://www.free-decompiler.com/flash/issues/226
+[#227]: https://www.free-decompiler.com/flash/issues/227
+[#230]: https://www.free-decompiler.com/flash/issues/230
+[#172]: https://www.free-decompiler.com/flash/issues/172
+[#174]: https://www.free-decompiler.com/flash/issues/174
+[#175]: https://www.free-decompiler.com/flash/issues/175
+[#212]: https://www.free-decompiler.com/flash/issues/212
+[#185]: https://www.free-decompiler.com/flash/issues/185
+[#186]: https://www.free-decompiler.com/flash/issues/186
+[#197]: https://www.free-decompiler.com/flash/issues/197
+[#216]: https://www.free-decompiler.com/flash/issues/216
+[#168]: https://www.free-decompiler.com/flash/issues/168
+[#176]: https://www.free-decompiler.com/flash/issues/176
+[#177]: https://www.free-decompiler.com/flash/issues/177
+[#202]: https://www.free-decompiler.com/flash/issues/202
+[#173]: https://www.free-decompiler.com/flash/issues/173
+[#190]: https://www.free-decompiler.com/flash/issues/190
+[#129]: https://www.free-decompiler.com/flash/issues/129
+[#153]: https://www.free-decompiler.com/flash/issues/153
+[#180]: https://www.free-decompiler.com/flash/issues/180
+[#136]: https://www.free-decompiler.com/flash/issues/136
+[#179]: https://www.free-decompiler.com/flash/issues/179
+[#144]: https://www.free-decompiler.com/flash/issues/144
+[#164]: https://www.free-decompiler.com/flash/issues/164
+[#167]: https://www.free-decompiler.com/flash/issues/167
+[#170]: https://www.free-decompiler.com/flash/issues/170
+[#178]: https://www.free-decompiler.com/flash/issues/178
+[#181]: https://www.free-decompiler.com/flash/issues/181
+[#182]: https://www.free-decompiler.com/flash/issues/182
+[#183]: https://www.free-decompiler.com/flash/issues/183
+[#184]: https://www.free-decompiler.com/flash/issues/184
+[#189]: https://www.free-decompiler.com/flash/issues/189
+[#191]: https://www.free-decompiler.com/flash/issues/191
+[#195]: https://www.free-decompiler.com/flash/issues/195
+[#196]: https://www.free-decompiler.com/flash/issues/196
+[#198]: https://www.free-decompiler.com/flash/issues/198
+[#200]: https://www.free-decompiler.com/flash/issues/200
+[#201]: https://www.free-decompiler.com/flash/issues/201
+[#166]: https://www.free-decompiler.com/flash/issues/166
+[#165]: https://www.free-decompiler.com/flash/issues/165
+[#63]: https://www.free-decompiler.com/flash/issues/63
+[#67]: https://www.free-decompiler.com/flash/issues/67
+[#117]: https://www.free-decompiler.com/flash/issues/117
+[#127]: https://www.free-decompiler.com/flash/issues/127
+[#134]: https://www.free-decompiler.com/flash/issues/134
+[#155]: https://www.free-decompiler.com/flash/issues/155
+[#142]: https://www.free-decompiler.com/flash/issues/142
+[#146]: https://www.free-decompiler.com/flash/issues/146
+[#130]: https://www.free-decompiler.com/flash/issues/130
+[#132]: https://www.free-decompiler.com/flash/issues/132
+[#145]: https://www.free-decompiler.com/flash/issues/145
+[#147]: https://www.free-decompiler.com/flash/issues/147
+[#148]: https://www.free-decompiler.com/flash/issues/148
+[#152]: https://www.free-decompiler.com/flash/issues/152
+[#156]: https://www.free-decompiler.com/flash/issues/156
+[#157]: https://www.free-decompiler.com/flash/issues/157
+[#158]: https://www.free-decompiler.com/flash/issues/158
+[#159]: https://www.free-decompiler.com/flash/issues/159
+[#160]: https://www.free-decompiler.com/flash/issues/160
+[#162]: https://www.free-decompiler.com/flash/issues/162
+[#163]: https://www.free-decompiler.com/flash/issues/163
+[#149]: https://www.free-decompiler.com/flash/issues/149
+[#150]: https://www.free-decompiler.com/flash/issues/150
+[#119]: https://www.free-decompiler.com/flash/issues/119
+[#101]: https://www.free-decompiler.com/flash/issues/101
+[#114]: https://www.free-decompiler.com/flash/issues/114
+[#135]: https://www.free-decompiler.com/flash/issues/135
+[#141]: https://www.free-decompiler.com/flash/issues/141
+[#102]: https://www.free-decompiler.com/flash/issues/102
+[#124]: https://www.free-decompiler.com/flash/issues/124
+[#128]: https://www.free-decompiler.com/flash/issues/128
+[#131]: https://www.free-decompiler.com/flash/issues/131
+[#104]: https://www.free-decompiler.com/flash/issues/104
+[#113]: https://www.free-decompiler.com/flash/issues/113
+[#133]: https://www.free-decompiler.com/flash/issues/133
+[#140]: https://www.free-decompiler.com/flash/issues/140
+[#108]: https://www.free-decompiler.com/flash/issues/108
+[#105]: https://www.free-decompiler.com/flash/issues/105
+[#109]: https://www.free-decompiler.com/flash/issues/109
+[#106]: https://www.free-decompiler.com/flash/issues/106
+[#107]: https://www.free-decompiler.com/flash/issues/107
+[#110]: https://www.free-decompiler.com/flash/issues/110
+[#103]: https://www.free-decompiler.com/flash/issues/103
+[#111]: https://www.free-decompiler.com/flash/issues/111
+[#96]: https://www.free-decompiler.com/flash/issues/96
+[#98]: https://www.free-decompiler.com/flash/issues/98
+[#99]: https://www.free-decompiler.com/flash/issues/99
+[#100]: https://www.free-decompiler.com/flash/issues/100
+[#85]: https://www.free-decompiler.com/flash/issues/85
+[#79]: https://www.free-decompiler.com/flash/issues/79
+[#92]: https://www.free-decompiler.com/flash/issues/92
+[#93]: https://www.free-decompiler.com/flash/issues/93
+[#94]: https://www.free-decompiler.com/flash/issues/94
+[#95]: https://www.free-decompiler.com/flash/issues/95
+[#86]: https://www.free-decompiler.com/flash/issues/86
+[#87]: https://www.free-decompiler.com/flash/issues/87
+[#88]: https://www.free-decompiler.com/flash/issues/88
+[#89]: https://www.free-decompiler.com/flash/issues/89
+[#82]: https://www.free-decompiler.com/flash/issues/82
+[#78]: https://www.free-decompiler.com/flash/issues/78
+[#81]: https://www.free-decompiler.com/flash/issues/81
+[#84]: https://www.free-decompiler.com/flash/issues/84
+[#83]: https://www.free-decompiler.com/flash/issues/83
+[#65]: https://www.free-decompiler.com/flash/issues/65
+[#48]: https://www.free-decompiler.com/flash/issues/48
+[#53]: https://www.free-decompiler.com/flash/issues/53
+[#66]: https://www.free-decompiler.com/flash/issues/66
+[#68]: https://www.free-decompiler.com/flash/issues/68
+[#69]: https://www.free-decompiler.com/flash/issues/69
+[#75]: https://www.free-decompiler.com/flash/issues/75
+[#73]: https://www.free-decompiler.com/flash/issues/73
+[#62]: https://www.free-decompiler.com/flash/issues/62
+[#72]: https://www.free-decompiler.com/flash/issues/72
+[#64]: https://www.free-decompiler.com/flash/issues/64
+[#38]: https://www.free-decompiler.com/flash/issues/38
+[#56]: https://www.free-decompiler.com/flash/issues/56
+[#57]: https://www.free-decompiler.com/flash/issues/57
+[#58]: https://www.free-decompiler.com/flash/issues/58
+[#45]: https://www.free-decompiler.com/flash/issues/45
+[#50]: https://www.free-decompiler.com/flash/issues/50
+[#51]: https://www.free-decompiler.com/flash/issues/51
+[#52]: https://www.free-decompiler.com/flash/issues/52
+[#47]: https://www.free-decompiler.com/flash/issues/47
+[#42]: https://www.free-decompiler.com/flash/issues/42
+[#39]: https://www.free-decompiler.com/flash/issues/39
+[#40]: https://www.free-decompiler.com/flash/issues/40
+[#44]: https://www.free-decompiler.com/flash/issues/44
+[#36]: https://www.free-decompiler.com/flash/issues/36
+[#43]: https://www.free-decompiler.com/flash/issues/43
+[#46]: https://www.free-decompiler.com/flash/issues/46
+[#3]: https://www.free-decompiler.com/flash/issues/3
+[#37]: https://www.free-decompiler.com/flash/issues/37
+[#34]: https://www.free-decompiler.com/flash/issues/34
+[#35]: https://www.free-decompiler.com/flash/issues/35
+[#32]: https://www.free-decompiler.com/flash/issues/32
[#31]: https://www.free-decompiler.com/flash/issues/31
\ No newline at end of file
diff --git a/src/com/jpexs/decompiler/flash/gui/Main.java b/src/com/jpexs/decompiler/flash/gui/Main.java
index fc81cf0ee..34b7473ff 100644
--- a/src/com/jpexs/decompiler/flash/gui/Main.java
+++ b/src/com/jpexs/decompiler/flash/gui/Main.java
@@ -1,2418 +1,2418 @@
-/*
- * Copyright (C) 2010-2016 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 com.jpexs.debugger.flash.Debugger;
-import com.jpexs.debugger.flash.DebuggerCommands;
-import com.jpexs.debugger.flash.Variable;
-import com.jpexs.debugger.flash.VariableType;
-import com.jpexs.debugger.flash.messages.in.InCallFunction;
-import com.jpexs.decompiler.flash.ApplicationInfo;
-import com.jpexs.decompiler.flash.EventListener;
-import com.jpexs.decompiler.flash.SWF;
-import com.jpexs.decompiler.flash.SWFBundle;
-import com.jpexs.decompiler.flash.SWFSourceInfo;
-import com.jpexs.decompiler.flash.SearchMode;
-import com.jpexs.decompiler.flash.SwfOpenException;
-import com.jpexs.decompiler.flash.UrlResolver;
-import com.jpexs.decompiler.flash.Version;
-import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
-import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
-import com.jpexs.decompiler.flash.configuration.Configuration;
-import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration;
-import com.jpexs.decompiler.flash.console.CommandLineArgumentParser;
-import com.jpexs.decompiler.flash.console.ContextMenuTools;
-import com.jpexs.decompiler.flash.exporters.modes.ExeExportMode;
-import com.jpexs.decompiler.flash.gui.debugger.DebugListener;
-import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools;
-import com.jpexs.decompiler.flash.gui.pipes.FirstInstance;
-import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame;
-import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
-import com.jpexs.decompiler.flash.tags.Tag;
-import com.jpexs.decompiler.flash.tags.base.FontTag;
-import com.jpexs.decompiler.flash.tags.base.ImportTag;
-import com.jpexs.decompiler.flash.treeitems.SWFList;
-import com.jpexs.helpers.Cache;
-import com.jpexs.helpers.CancellableWorker;
-import com.jpexs.helpers.Helper;
-import com.jpexs.helpers.Path;
-import com.jpexs.helpers.ProgressListener;
-import com.jpexs.helpers.Stopwatch;
-import com.jpexs.helpers.streams.SeekableInputStream;
-import com.sun.jna.Platform;
-import com.sun.jna.platform.win32.Advapi32Util;
-import com.sun.jna.platform.win32.Kernel32;
-import com.sun.jna.platform.win32.WinReg;
-import java.awt.AWTException;
-import java.awt.Frame;
-import java.awt.GraphicsEnvironment;
-import java.awt.MenuItem;
-import java.awt.PopupMenu;
-import java.awt.SystemTray;
-import java.awt.TrayIcon;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.lang.reflect.Field;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.URL;
-import java.net.URLConnection;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.ExecutionException;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.FileHandler;
-import java.util.logging.Formatter;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.logging.SimpleFormatter;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.swing.JFileChooser;
-import javax.swing.JFrame;
-import javax.swing.JOptionPane;
-import javax.swing.SwingWorker;
-import javax.swing.UIManager;
-import javax.swing.UnsupportedLookAndFeelException;
-import javax.swing.filechooser.FileFilter;
-import org.pushingpixels.substance.api.SubstanceLookAndFeel;
-
-/**
- * Main executable class
- *
- * @author JPEXS
- */
-public class Main {
-
- protected static ProxyFrame proxyFrame;
-
- private static List sourceInfos = new ArrayList<>();
-
- public static LoadingDialog loadingDialog;
-
- private static boolean working = false;
-
- private static TrayIcon trayIcon;
-
- private static MenuItem stopMenuItem;
-
- private static volatile MainFrame mainFrame;
-
- public static final int UPDATE_SYSTEM_MAJOR = 1;
-
- public static final int UPDATE_SYSTEM_MINOR = 3;
-
- private static LoadFromMemoryFrame loadFromMemoryFrame;
-
- private static LoadFromCacheFrame loadFromCacheFrame;
-
- private static final Logger logger = Logger.getLogger(Main.class.getName());
-
- public static DebugLogDialog debugDialog;
-
- public static boolean shouldCloseWhenClosingLoadingDialog;
-
- private static Debugger flashDebugger;
-
- private static DebuggerHandler debugHandler = null;
-
- //private static int ip = 0;
- //private static String ipClass = null;
- private static Process runProcess;
-
- private static boolean runProcessDebug;
-
- private static boolean runProcessDebugPCode;
-
- private static boolean inited = false;
-
- private static File runTempFile;
-
- private static List runTempFiles = new ArrayList<>();
-
- public static void freeRun() {
- synchronized (Main.class) {
- if (runTempFile != null) {
- runTempFile.delete();
- runTempFile = null;
- }
- for (File f : runTempFiles) {
- f.delete();
- }
- runTempFiles.clear();
-
- runProcess = null;
- }
- if (mainFrame != null && mainFrame.getPanel() != null) {
- mainFrame.getPanel().clearDebuggerColors();
- }
- if (runProcessDebug) {
- Main.getDebugHandler().disconnect();
- }
- }
-
- public static synchronized boolean isDebugPaused() {
- return runProcess != null && runProcessDebug && getDebugHandler().isPaused();
- }
-
- public static synchronized boolean isDebugRunning() {
- return runProcess != null && runProcessDebug;
- }
-
- public static synchronized boolean isDebugPCode() {
- return runProcessDebugPCode;
- }
-
- public static synchronized boolean isDebugConnected() {
- return getDebugHandler().isConnected();
- }
-
- public static synchronized boolean isRunning() {
- return runProcess != null && !runProcessDebug;
- }
-
- /**
- * FIXME!
- *
- * @param v
- */
- public static synchronized void dumpBytes(Variable v) {
- InCallFunction icf;
- try {
- long objectId = 0l;
- if ((v.vType == VariableType.OBJECT || v.vType == VariableType.MOVIECLIP)) {
- objectId = (Long) v.value;
- }
- Object oldPos = getDebugHandler().getVariable(objectId, "position", true).parent.value;
- getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, 0);
- icf = getDebugHandler().callFunction(false, "readUTF", v, new ArrayList<>());
- System.out.println("Result=" + icf.variables.get(0).value);
- getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, oldPos);
- } catch (DebuggerHandler.ActionScriptException ex) {
- Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
- }
-
- }
-
- public static synchronized boolean addWatch(Variable v, long v_id, boolean watchRead, boolean watchWrite) {
- DebuggerCommands.Watch w = getDebugHandler().addWatch(v, v_id, watchRead, watchWrite);
- return w != null;
- }
-
- public static void runPlayer(String title, final String exePath, String file, String flashVars) {
- if (!new File(file).exists()) {
- return;
- }
- if (flashVars != null && !flashVars.isEmpty()) {
- file += "?" + flashVars;
- }
- final String ffile = file;
-
- CancellableWorker runWorker = new CancellableWorker() {
- @Override
- protected Object doInBackground() throws Exception {
- Process proc;
- try {
- proc = Runtime.getRuntime().exec(new String[]{exePath, ffile});
- } catch (IOException ex) {
- logger.log(Level.SEVERE, null, ex);
- return null;
- }
- boolean isDebug;
-
- synchronized (Main.class) {
- runProcess = proc;
- isDebug = runProcessDebug;
- }
- if (isDebug) {
- mainFrame.getMenu().hilightPath("/debugging");
- }
- mainFrame.getMenu().updateComponents();
- try {
- if (proc != null) {
- proc.waitFor();
- }
- } catch (InterruptedException ex) {
- if (proc != null) {
- try {
- proc.destroy();
- } catch (Exception ex2) {
- //ignore
- }
- }
- }
- freeRun();
- stopDebugger();
- mainFrame.getMenu().updateComponents();
- return null;
- }
-
- @Override
- protected void done() {
- Main.stopWork();
- }
-
- @Override
- public void workerCancelled() {
- Main.stopWork();
- synchronized (Main.class) {
- if (runProcess != null) {
- try {
- runProcess.destroy();
- } catch (Exception ex) {
-
- }
- }
- }
- freeRun();
- mainFrame.getMenu().updateComponents();
- }
- };
-
- mainFrame.getMenu().updateComponents();
- Main.startWork(title + "...", runWorker);
- runWorker.execute();
- }
-
- public static void stopRun() {
-
- synchronized (Main.class) {
- if (runProcess != null) {
- runProcess.destroy();
- }
- }
- freeRun();
- stopDebugger();
- mainFrame.getMenu().updateComponents();
- }
-
- private static interface SwfPreparation {
-
- public SWF prepare(SWF swf);
- }
-
- private static class SwfRunPrepare implements SwfPreparation {
-
- @Override
- public SWF prepare(SWF swf) {
- if (Configuration.autoOpenLoadedSWFs.get()) {
- if (!DebuggerTools.hasDebugger(swf)) {
- DebuggerTools.switchDebugger(swf);
- }
- DebuggerTools.injectDebugLoader(swf);
- }
- return swf;
- }
- }
-
- private static class SwfDebugPrepare extends SwfRunPrepare {
-
- private boolean doPCode;
-
- public SwfDebugPrepare(boolean doPCode) {
- this.doPCode = doPCode;
- }
-
- @Override
- public SWF prepare(SWF instrSWF) {
- instrSWF = super.prepare(instrSWF);
- try {
- File fTempFile = new File(instrSWF.getFile());
- instrSWF.enableDebugging(true, new File("."), true, doPCode);
- FileOutputStream fos = new FileOutputStream(fTempFile);
- instrSWF.saveTo(fos);
- fos.close();
- if (!instrSWF.isAS3()) {
- //Read again, because line file offsets changed with adding debug tags
- //TODO: handle somehow without rereading?
- instrSWF = null;
- try (FileInputStream fis = new FileInputStream(fTempFile)) {
- instrSWF = new SWF(fis, false, false);
- } catch (InterruptedException ex) {
- logger.log(Level.SEVERE, null, ex);
- }
- if (instrSWF != null) {
- String swfFileName = fTempFile.getAbsolutePath();
- if (swfFileName.toLowerCase().endsWith(".swf")) {
- swfFileName = swfFileName.substring(0, swfFileName.length() - 4) + ".swd";
- } else {
- swfFileName = swfFileName + ".swd";
- }
- File swdFile = new File(swfFileName);
- if (doPCode) {
- instrSWF.generatePCodeSwdFile(swdFile, getPackBreakPoints(true));
- } else {
- instrSWF.generateSwdFile(swdFile, getPackBreakPoints(true));
- }
- }
- }
- } catch (IOException ex) {
- //ignore, return instrSWF
- }
- return instrSWF;
- }
- }
-
- private static void prepareSwf(SwfPreparation prep, File toPrepareFile, File origFile, List tempFiles) throws IOException {
- SWF instrSWF = null;
- try (FileInputStream fis = new FileInputStream(toPrepareFile)) {
- instrSWF = new SWF(fis, toPrepareFile.getAbsolutePath(), origFile.getName(), false);
- } catch (InterruptedException ex) {
- logger.log(Level.SEVERE, null, ex);
- }
- if (instrSWF != null) {
- for (Tag t : instrSWF.getLocalTags()) {
- if (t instanceof ImportTag) {
- ImportTag it = (ImportTag) t;
- String url = it.getUrl();
- File importedFile = new File(origFile.getParentFile(), url);
- if (importedFile.exists()) {
- File newTempFile = File.createTempFile("ffdec_run_import_", ".swf");
- it.setUrl("./" + newTempFile.getName());
- byte[] impData = Helper.readFile(importedFile.getAbsolutePath());
- Helper.writeFile(newTempFile.getAbsolutePath(), impData);
- tempFiles.add(newTempFile);
- prepareSwf(prep, newTempFile, importedFile, tempFiles);
- }
- }
- }
- if (prep != null) {
- instrSWF = prep.prepare(instrSWF);
- }
- try (FileOutputStream fos = new FileOutputStream(toPrepareFile)) {
- instrSWF.saveTo(fos);
- }
- }
- }
-
- public static void run(SWF swf) {
- String flashVars = "";//key=val&key2=val2
- String playerLocation = Configuration.playerLocation.get();
- if (playerLocation.isEmpty() || (!new File(playerLocation).exists())) {
- View.showMessageDialog(null, AppStrings.translate("message.playerpath.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
- advancedSettings("paths");
- return;
- }
- if (swf == null) {
- return;
- }
- File tempFile;
- List tempFiles = new ArrayList<>();
- try {
- tempFile = File.createTempFile("ffdec_run_", ".swf");
-
- try (FileOutputStream fos = new FileOutputStream(tempFile)) {
- swf.saveTo(fos);
- }
-
- prepareSwf(new SwfRunPrepare(), tempFile, new File(swf.getFile()), tempFiles);
-
- } catch (IOException ex) {
- return;
-
- }
- if (tempFile != null) {
- synchronized (Main.class) {
- runTempFile = tempFile;
- runTempFiles = tempFiles;
- runProcessDebug = false;
- }
- runPlayer(AppStrings.translate("work.running"), playerLocation, tempFile.getAbsolutePath(), flashVars);
- }
- }
-
- public static void runDebug(SWF swf, final boolean doPCode) {
- String flashVars = "";//key=val&key2=val2
- String playerLocation = Configuration.playerDebugLocation.get();
- if (playerLocation.isEmpty() || (!new File(playerLocation).exists())) {
- View.showMessageDialog(null, AppStrings.translate("message.playerpath.debug.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
- Main.advancedSettings("paths");
- return;
- }
- if (swf == null) {
- return;
- }
- File tempFile = null;
-
- try {
- tempFile = File.createTempFile("ffdec_debug_", ".swf");
- } catch (Exception ex) {
-
- }
-
- if (tempFile != null) {
- final File fTempFile = tempFile;
- final List tempFiles = new ArrayList<>();
- CancellableWorker instrumentWorker = new CancellableWorker() {
- @Override
- protected Object doInBackground() throws Exception {
-
- try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fTempFile))) {
- swf.saveTo(fos);
- }
- prepareSwf(new SwfDebugPrepare(doPCode), fTempFile, new File(swf.getFile()), tempFiles);
- return null;
- }
-
- @Override
- public void workerCancelled() {
- Main.stopWork();
- }
-
- @Override
- protected void done() {
- synchronized (Main.class) {
- runTempFile = fTempFile;
- runProcessDebug = true;
- runProcessDebugPCode = doPCode;
- runTempFiles = tempFiles;
- }
- Main.stopWork();
- Main.startDebugger();
- runPlayer(AppStrings.translate("work.debugging.wait"), playerLocation, fTempFile.getAbsolutePath(), flashVars);
- }
- };
-
- Main.startWork(AppStrings.translate("work.debugging.instrumenting"), instrumentWorker);
- instrumentWorker.execute();
- }
- }
-
- /* public static void debuggerNotSuspended() {
-
- }*/
- public static boolean isDebugging() {
- return isDebugRunning();
- }
-
- public synchronized static int getIp(Object pack) {
- return getDebugHandler().getBreakIp();
- }
-
- public synchronized static String getIpClass() {
- return getDebugHandler().getBreakScriptName();
- }
-
- public static synchronized boolean isBreakPointValid(String scriptName, int line) {
- return !getDebugHandler().isBreakpointInvalid(scriptName, line);
- }
-
- public synchronized static void addBreakPoint(String scriptName, int line) {
- getDebugHandler().addBreakPoint(scriptName, line);
- }
-
- public synchronized static void removeBreakPoint(String scriptName, int line) {
- getDebugHandler().removeBreakPoint(scriptName, line);
- }
-
- public synchronized static boolean toggleBreakPoint(String scriptName, int line) {
- if (getDebugHandler().isBreakpointToAdd(scriptName, line) || getDebugHandler().isBreakpointConfirmed(scriptName, line) || getDebugHandler().isBreakpointInvalid(scriptName, line)) {
- getDebugHandler().removeBreakPoint(scriptName, line);
- return false;
- } else {
- getDebugHandler().addBreakPoint(scriptName, line);
- return true;
- }
- }
-
- public synchronized static Map> getPackBreakPoints(boolean validOnly) {
- return getDebugHandler().getAllBreakPoints(validOnly);
- }
-
- public synchronized static Set getScriptBreakPoints(String pack, boolean onlyValid) {
- return getDebugHandler().getBreakPoints(pack, onlyValid);
- }
-
- public static DebuggerHandler getDebugHandler() {
- return debugHandler;
- }
-
- public static void ensureMainFrame() {
- if (mainFrame == null) {
- synchronized (Main.class) {
- if (mainFrame == null) {
- MainFrame frame;
- if (Configuration.useRibbonInterface.get()) {
- frame = new MainFrameRibbon();
- } else {
- frame = new MainFrameClassic();
- }
- frame.getPanel().setErrorState(ErrorLogFrame.getInstance().getErrorState());
- mainFrame = frame;
- }
- }
- }
- }
-
- public static MainFrame getMainFrame() {
- return mainFrame;
- }
-
- public static void loadFromCache() {
- if (loadFromCacheFrame == null) {
- loadFromCacheFrame = new LoadFromCacheFrame();
- }
- loadFromCacheFrame.setVisible(true);
- }
-
- public static void loadFromMemory() {
- if (loadFromMemoryFrame == null) {
- loadFromMemoryFrame = new LoadFromMemoryFrame(mainFrame);
- }
- loadFromMemoryFrame.setVisible(true);
- }
-
- public static void setVariable(long parentId, String varName, int valueType, Object value) {
- getDebugHandler().setVariable(parentId, varName, valueType, value);
- }
-
- public static void setSubLimiter(boolean value) {
- if (value) {
- AVM2Code.toSourceLimit = Configuration.sublimiter.get();
- } else {
- AVM2Code.toSourceLimit = -1;
- }
- }
-
- public synchronized static boolean isInited() {
- return inited;
- }
-
- public synchronized static void setSessionLoaded(boolean v) {
- inited = v;
- }
-
- public static boolean isWorking() {
- return working;
- }
-
- public static void startProxy(int port) {
- if (proxyFrame == null) {
- proxyFrame = new ProxyFrame(mainFrame);
- }
-
- proxyFrame.setPort(port);
- addTrayIcon();
- switchProxy();
- }
-
- public static void showProxy() {
- if (proxyFrame == null) {
- proxyFrame = new ProxyFrame(mainFrame);
- }
- proxyFrame.setVisible(true);
- proxyFrame.setState(Frame.NORMAL);
- }
-
- public static void startWork(String name, CancellableWorker worker) {
- startWork(name, -1, worker);
- }
-
- public static void startWork(final String name, final int percent, final CancellableWorker worker) {
- working = true;
- View.execInEventDispatchLater(() -> {
- if (mainFrame != null) {
- mainFrame.getPanel().setWorkStatus(name, worker);
- if (percent == -1) {
- mainFrame.getPanel().hidePercent();
- } else {
- mainFrame.getPanel().setPercent(percent);
- }
- }
- if (loadingDialog != null) {
- loadingDialog.setDetail(name);
- loadingDialog.setPercent(percent);
- }
- if (CommandLineArgumentParser.isCommandLineMode()) {
- System.out.println(name);
- }
- });
- }
-
- public static void stopWork() {
- working = false;
- View.execInEventDispatchLater(() -> {
- if (mainFrame != null) {
- mainFrame.getPanel().setWorkStatus("", null);
- }
- if (loadingDialog != null) {
- loadingDialog.setDetail("");
- }
- });
- }
-
- public static SWFList parseSWF(SWFSourceInfo sourceInfo) throws Exception {
- SWFList result = new SWFList();
-
- InputStream inputStream = sourceInfo.getInputStream();
- SWFBundle bundle = null;
- FileInputStream fis = null;
- if (inputStream == null) {
- inputStream = new BufferedInputStream(fis = new FileInputStream(sourceInfo.getFile()));
- bundle = sourceInfo.getBundle(false, SearchMode.ALL);
- logger.log(Level.INFO, "Load file: {0}", sourceInfo.getFile());
- } else if (inputStream instanceof SeekableInputStream
- || inputStream instanceof BufferedInputStream) {
- try {
- inputStream.reset();
- } catch (IOException ex) {
- logger.log(Level.SEVERE, null, ex);
- }
- logger.log(Level.INFO, "Load stream: {0}", sourceInfo.getFileTitle());
- }
-
- Stopwatch sw = Stopwatch.startNew();
- if (bundle != null) {
- result.bundle = bundle;
- result.name = new File(sourceInfo.getFileTitleOrName()).getName();
- for (Entry streamEntry : bundle.getAll().entrySet()) {
- InputStream stream = streamEntry.getValue();
- stream.reset();
- CancellableWorker worker = new CancellableWorker() {
- @Override
- public SWF doInBackground() throws Exception {
- final CancellableWorker worker = this;
- SWF swf = new SWF(stream, null, streamEntry.getKey(), new ProgressListener() {
- @Override
- public void progress(int p) {
- startWork(AppStrings.translate("work.reading.swf"), p, worker);
- }
- }, Configuration.parallelSpeedUp.get());
- return swf;
- }
- };
- loadingDialog.setWroker(worker);
- worker.execute();
-
- try {
- result.add(worker.get());
- } catch (CancellationException ex) {
- logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", streamEntry.getKey());
- }
- }
- } else {
- InputStream fInputStream = inputStream;
-
- final String[] yesno = new String[]{AppStrings.translate("button.yes"), AppStrings.translate("button.no"), AppStrings.translate("button.yes.all"), AppStrings.translate("button.no.all")};
-
- CancellableWorker worker = new CancellableWorker() {
- private boolean yestoall = false;
-
- private boolean notoall = false;
-
- private SWF open(InputStream is, String file, String fileTitle) throws IOException, InterruptedException {
- final CancellableWorker worker = this;
-
- SWF swf = new SWF(is, file, fileTitle, new ProgressListener() {
- @Override
- public void progress(int p) {
- startWork(AppStrings.translate("work.reading.swf"), p, worker);
- }
- }, Configuration.parallelSpeedUp.get(), false, true, new UrlResolver() {
- @Override
- public SWF resolveUrl(final String url) {
- int opt = -1;
- if (!(yestoall || notoall)) {
- opt = View.showOptionDialog(null, AppStrings.translate("message.imported.swf").replace("%url%", url), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, AppStrings.translate("button.yes"));
- if (opt == 2) {
- yestoall = true;
- }
- if (opt == 3) {
- notoall = true;
- }
- }
-
- if (yestoall) {
- opt = 0; // yes
- } else if (notoall) {
- opt = 1; // no
- }
-
- if (opt == 1) //no
- {
- return null;
- }
-
- if (url.startsWith("http://") || url.startsWith("https://")) {
- try {
- URL u = new URL(url);
- return open(u.openStream(), null, url); //?
- } catch (Exception ex) {
- //ignore
- }
- } else {
- File f = new File(new File(file).getParentFile(), url);
- if (f.exists()) {
- try {
- return open(new FileInputStream(f), f.getAbsolutePath(), f.getName());
- } catch (Exception ex) {
- //ignore
- }
- }
- }
- Reference ret = new Reference<>(null);
- View.execInEventDispatch(new Runnable() {
- @Override
- public void run() {
-
- while (JOptionPane.YES_OPTION == View.showConfirmDialog(null, AppStrings.translate("message.imported.swf.manually").replace("%url%", url), AppStrings.translate("error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE)) {
-
- JFileChooser fc = new JFileChooser();
- fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get()));
- FileFilter allSupportedFilter = new FileFilter() {
- private final String[] supportedExtensions = new String[]{".swf", ".gfx"};
-
- @Override
- public boolean accept(File f) {
- String name = f.getName().toLowerCase();
- for (String ext : supportedExtensions) {
- if (name.endsWith(ext)) {
- return true;
- }
- }
- return f.isDirectory();
- }
-
- @Override
- public String getDescription() {
- String exts = Helper.joinStrings(supportedExtensions, "*%s", "; ");
- return AppStrings.translate("filter.supported") + " (" + exts + ")";
- }
- };
- fc.setFileFilter(allSupportedFilter);
- FileFilter swfFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.swf");
- }
- };
- fc.addChoosableFileFilter(swfFilter);
-
- FileFilter gfxFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.gfx");
- }
- };
- fc.addChoosableFileFilter(gfxFilter);
- fc.setAcceptAllFileFilterUsed(false);
- JFrame f = new JFrame();
- View.setWindowIcon(f);
- int returnVal = fc.showOpenDialog(f);
- if (returnVal == JFileChooser.APPROVE_OPTION) {
- Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath());
- File selFile = Helper.fixDialogFile(fc.getSelectedFile());
- try {
- ret.setVal(open(new FileInputStream(selFile), selFile.getAbsolutePath(), selFile.getName()));
- break;
- } catch (Exception ex) {
- //ignore;
- }
- } else {
- break;
- }
- }
- }
- });
- return ret.getVal();
- }
- });
- return swf;
- }
-
- @Override
- public SWF doInBackground() throws Exception {
- return open(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle());
- }
- };
- if (loadingDialog != null) {
- loadingDialog.setWroker(worker);
- }
- worker.execute();
-
- try {
- result.add(worker.get());
- } catch (CancellationException ex) {
- logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", sourceInfo.getFileTitleOrName());
- }
- }
-
- if (fis != null) {
- logger.log(Level.INFO, "File loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000));
- fis.close();
- } else {
- logger.log(Level.INFO, "Stream loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000));
- }
-
- result.sourceInfo = sourceInfo;
- for (SWF swf : result) {
- logger.log(Level.INFO, "");
- logger.log(Level.INFO, "== File information ==");
- logger.log(Level.INFO, "Size: {0}", Helper.formatFileSize(swf.fileSize));
- logger.log(Level.INFO, "Flash version: {0}", swf.version);
- int width = (int) ((swf.displayRect.Xmax - swf.displayRect.Xmin) / SWF.unitDivisor);
- int height = (int) ((swf.displayRect.Ymax - swf.displayRect.Ymin) / SWF.unitDivisor);
- logger.log(Level.INFO, "Width: {0}", width);
- logger.log(Level.INFO, "Height: {0}", height);
-
- swf.swfList = result;
- swf.addEventListener(new EventListener() {
- @Override
- public void handleExportingEvent(String type, int index, int count, Object data) {
- String text = AppStrings.translate("work.exporting");
- if (type != null && type.length() > 0) {
- text += " " + type;
- }
-
- startWork(text + " " + index + "/" + count + " " + data, null);
- }
-
- @Override
- public void handleExportedEvent(String type, int index, int count, Object data) {
- String text = AppStrings.translate("work.exported");
- if (type != null && type.length() > 0) {
- text += " " + type;
- }
-
- startWork(text + " " + index + "/" + count + " " + data, null);
- }
-
- @Override
- public void handleEvent(String event, Object data) {
- if (event.equals("exporting") || event.equals("exported")) {
- throw new Error("Event is not supported by this handler.");
- }
- if (event.equals("getVariables")) {
- startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data, null);
- }
- if (event.equals("deobfuscate")) {
- startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data, null);
- }
- if (event.equals("rename")) {
- startWork(AppStrings.translate("work.renaming") + "..." + (String) data, null);
- }
- }
- });
- }
-
- return result;
- }
-
- public static void saveFile(SWF swf, String outfile) throws IOException {
- saveFile(swf, outfile, SaveFileMode.SAVE, null);
- }
-
- public static void saveFile(SWF swf, String outfile, SaveFileMode mode, ExeExportMode exeExportMode) throws IOException {
- if (mode == SaveFileMode.SAVEAS && !swf.swfList.isBundle()) {
- swf.setFile(outfile);
- swf.swfList.sourceInfo.setFile(outfile);
- }
- File outfileF = new File(outfile);
- File tmpFile = new File(outfile + ".tmp");
- try (FileOutputStream fos = new FileOutputStream(tmpFile);
- BufferedOutputStream bos = new BufferedOutputStream(fos)) {
- if (mode == SaveFileMode.EXE) {
- switch (exeExportMode) {
- case WRAPPER:
- InputStream exeStream = View.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/Swf2Exe.bin");
- Helper.copyStream(exeStream, bos);
- int width = swf.displayRect.Xmax - swf.displayRect.Xmin;
- int height = swf.displayRect.Ymax - swf.displayRect.Ymin;
- bos.write(width & 0xff);
- bos.write((width >> 8) & 0xff);
- bos.write((width >> 16) & 0xff);
- bos.write((width >> 24) & 0xff);
- bos.write(height & 0xff);
- bos.write((height >> 8) & 0xff);
- bos.write((height >> 16) & 0xff);
- bos.write((height >> 24) & 0xff);
- bos.write(Configuration.saveAsExeScaleMode.get());
- break;
- case PROJECTOR_WIN:
- case PROJECTOR_MAC:
- case PROJECTOR_LINUX:
- File projectorFile = Configuration.getProjectorFile(exeExportMode);
- if (projectorFile == null) {
- String message = "Projector not found, please place it to " + Configuration.getProjectorPath();
- logger.log(Level.SEVERE, message);
- throw new IOException(message);
- }
- Helper.copyStream(new FileInputStream(projectorFile), bos);
- bos.flush();
- break;
- }
- }
-
- long pos = fos.getChannel().position();
- swf.saveTo(bos);
-
- if (mode == SaveFileMode.EXE) {
- switch (exeExportMode) {
- case PROJECTOR_WIN:
- case PROJECTOR_MAC:
- case PROJECTOR_LINUX:
- bos.flush();
- int swfSize = (int) (fos.getChannel().position() - pos);
-
- // write magic number
- bos.write(0x56);
- bos.write(0x34);
- bos.write(0x12);
- bos.write(0xfa);
-
- bos.write(swfSize & 0xff);
- bos.write((swfSize >> 8) & 0xff);
- bos.write((swfSize >> 16) & 0xff);
- bos.write((swfSize >> 24) & 0xff);
- }
- }
- }
- if (tmpFile.exists()) {
- if (tmpFile.length() > 0) {
- outfileF.delete();
- if (!tmpFile.renameTo(outfileF)) {
- tmpFile.delete();
- throw new IOException("Cannot access " + outfile);
- }
- } else {
- throw new IOException("Output is empty");
- }
- } else {
- throw new IOException("Output not found");
- }
- }
-
- private static class OpenFileWorker extends SwingWorker {
-
- private final SWFSourceInfo[] sourceInfos;
-
- private final Runnable executeAfterOpen;
-
- private final int[] reloadIndices;
-
- public OpenFileWorker(SWFSourceInfo sourceInfo) {
- this(sourceInfo, -1);
- }
-
- public OpenFileWorker(SWFSourceInfo sourceInfo, int reloadIndex) {
- this(sourceInfo, null, reloadIndex);
- }
-
- public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) {
- this(sourceInfo, executeAfterOpen, -1);
- }
-
- public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen, int reloadIndex) {
- this.sourceInfos = new SWFSourceInfo[]{sourceInfo};
- this.executeAfterOpen = executeAfterOpen;
- this.reloadIndices = new int[]{reloadIndex};
- }
-
- public OpenFileWorker(SWFSourceInfo[] sourceInfos) {
- this(sourceInfos, null, null);
- }
-
- public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen) {
- this(sourceInfos, executeAfterOpen, null);
- }
-
- public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen, int[] reloadIndices) {
- this.sourceInfos = sourceInfos;
- this.executeAfterOpen = executeAfterOpen;
- int[] indices = new int[sourceInfos.length];
- for (int i = 0; i < indices.length; i++) {
- indices[i] = -1;
- }
- this.reloadIndices = reloadIndices == null ? indices : reloadIndices;
- }
-
- @Override
- protected Object doInBackground() throws Exception {
- boolean first = true;
- SWF firstSWF = null;
- for (int index = 0; index < sourceInfos.length; index++) {
- SWFSourceInfo sourceInfo = sourceInfos[index];
- SWFList swfs = null;
- try {
- Main.startWork(AppStrings.translate("work.reading.swf") + "...", null);
- try {
- swfs = parseSWF(sourceInfo);
- } catch (ExecutionException ex) {
- Throwable cause = ex.getCause();
- if (cause instanceof SwfOpenException) {
- throw (SwfOpenException) cause;
- }
-
- throw ex;
- }
- } catch (OutOfMemoryError ex) {
- logger.log(Level.SEVERE, null, ex);
- View.showMessageDialog(null, "Cannot load SWF file. Out of memory.");
- continue;
- } catch (SwfOpenException ex) {
- logger.log(Level.SEVERE, null, ex);
- View.showMessageDialog(null, ex.getMessage());
- continue;
- } catch (Exception ex) {
- logger.log(Level.SEVERE, null, ex);
- View.showMessageDialog(null, "Cannot load SWF file.");
- continue;
- }
-
- final SWFList swfs1 = swfs;
- final boolean first1 = first;
- first = false;
- if (firstSWF == null && swfs1.size() > 0) {
- firstSWF = swfs1.get(0);
- }
-
- final int findex = index;
- try {
- View.execInEventDispatch(() -> {
- Main.startWork(AppStrings.translate("work.creatingwindow") + "...", null);
- ensureMainFrame();
- if (reloadIndices[findex] > -1) {
- mainFrame.getPanel().loadSwfAtPos(swfs1, reloadIndices[findex]);
- } else {
- mainFrame.getPanel().load(swfs1, first1);
- }
- });
- } catch (Exception ex) {
- logger.log(Level.SEVERE, null, ex);
- }
- }
-
- loadingDialog.setVisible(false);
- shouldCloseWhenClosingLoadingDialog = false;
-
- final SWF fswf = firstSWF;
- View.execInEventDispatch(() -> {
- if (mainFrame != null) {
- mainFrame.setVisible(true);
- }
-
- Main.stopWork();
-
- if (mainFrame != null && Configuration.gotoMainClassOnStartup.get()) {
- mainFrame.getPanel().gotoDocumentClass(fswf);
- }
-
- if (mainFrame != null && fswf != null) {
- SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(fswf.getShortFileName());
- if (swfConf != null) {
- String pathStr = swfConf.lastSelectedPath;
- mainFrame.getPanel().tagTree.setSelectionPathString(pathStr);
- }
- }
-
- if (executeAfterOpen != null) {
- executeAfterOpen.run();
- }
- });
-
- return true;
- }
- }
-
- public static boolean reloadSWFs() {
- CancellableWorker.cancelBackgroundThreads();
- if (Main.sourceInfos.isEmpty()) {
- Helper.freeMem();
- showModeFrame();
- return true;
- } else {
- SWFSourceInfo[] sourceInfosCopy = new SWFSourceInfo[sourceInfos.size()];
- sourceInfos.toArray(sourceInfosCopy);
- sourceInfos.clear();
- openFile(sourceInfosCopy);
- return true;
- }
- }
-
- public static void reloadApp() {
- if (debugDialog != null) {
- debugDialog.setVisible(false);
- debugDialog.dispose();
- debugDialog = null;
- }
- if (loadingDialog != null) {
- synchronized (Main.class) {
- if (loadingDialog != null) {
- loadingDialog.setVisible(false);
- loadingDialog.dispose();
- loadingDialog = null;
- }
- }
- }
- if (proxyFrame != null) {
- proxyFrame.setVisible(false);
- proxyFrame.dispose();
- proxyFrame = null;
- }
- if (loadFromMemoryFrame != null) {
- loadFromMemoryFrame.setVisible(false);
- loadFromMemoryFrame.dispose();
- loadFromMemoryFrame = null;
- }
- if (loadFromCacheFrame != null) {
- loadFromCacheFrame.setVisible(false);
- loadFromCacheFrame.dispose();
- loadFromCacheFrame = null;
- }
- if (mainFrame != null) {
- mainFrame.setVisible(false);
- mainFrame.getPanel().closeAll(false);
- mainFrame.dispose();
- mainFrame = null;
- }
- FontTag.reload();
- Cache.clearAll();
- initGui();
- reloadSWFs();
- }
-
- public static OpenFileResult openFile(String swfFile, String fileTitle) {
- View.checkAccess();
-
- return openFile(swfFile, fileTitle, null);
- }
-
- public static OpenFileResult openFile(String swfFile, String fileTitle, Runnable executeAfterOpen) {
- View.checkAccess();
-
- try {
- File file = new File(swfFile);
- if (!file.exists()) {
- View.showMessageDialog(null, AppStrings.translate("open.error.fileNotFound"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE);
- return OpenFileResult.NOT_FOUND;
- }
- swfFile = file.getCanonicalPath();
- SWFSourceInfo sourceInfo = new SWFSourceInfo(null, swfFile, fileTitle);
- OpenFileResult openResult = openFile(sourceInfo);
- return openResult;
- } catch (IOException ex) {
- View.showMessageDialog(null, AppStrings.translate("open.error.cannotOpen"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE);
- return OpenFileResult.ERROR;
- }
- }
-
- public static OpenFileResult openFile(SWFSourceInfo sourceInfo) {
- View.checkAccess();
-
- return openFile(new SWFSourceInfo[]{sourceInfo});
- }
-
- public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) {
- View.checkAccess();
-
- return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen);
- }
-
- public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen, int reloadIndex) {
- View.checkAccess();
-
- return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen, new int[]{reloadIndex});
- }
-
- public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos) {
- View.checkAccess();
-
- return openFile(newSourceInfos, null);
- }
-
- public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen) {
- View.checkAccess();
-
- return openFile(newSourceInfos, executeAfterOpen, null);
- }
-
- public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen, int[] reloadIndices) {
- View.checkAccess();
-
- if (mainFrame != null && !Configuration.openMultipleFiles.get()) {
- sourceInfos.clear();
- mainFrame.getPanel().closeAll(false);
- mainFrame.setVisible(false);
- Helper.freeMem();
- reloadIndices = null;
- }
-
- loadingDialog.setVisible(true);
-
- for (int i = 0; i < newSourceInfos.length; i++) {
- SWFSourceInfo si = newSourceInfos[i];
- String fileName = si.getFile();
- if (fileName != null) {
- Configuration.addRecentFile(fileName);
- }
- }
-
- OpenFileWorker wrk = new OpenFileWorker(newSourceInfos, executeAfterOpen, reloadIndices);
- wrk.execute();
- if (reloadIndices == null) {
- sourceInfos.addAll(Arrays.asList(newSourceInfos));
- } else {
- for (int i = 0; i < reloadIndices.length; i++) {
- sourceInfos.set(reloadIndices[i], newSourceInfos[i]);
- }
- }
- return OpenFileResult.OK;
- }
-
- public static void closeFile(SWFList swf) {
- View.checkAccess();
-
- sourceInfos.remove(swf.sourceInfo);
- mainFrame.getPanel().close(swf);
- }
-
- public static void reloadFile(SWFList swf) {
- View.checkAccess();
-
- openFile(swf.sourceInfo, null, sourceInfos.indexOf(swf.sourceInfo));
- }
-
- public static boolean closeAll() {
- View.checkAccess();
-
- boolean closeResult = mainFrame.getPanel().closeAll(true);
- if (closeResult) {
- sourceInfos.clear();
- }
-
- return closeResult;
- }
-
- public static boolean saveFileDialog(SWF swf, final SaveFileMode mode) {
- JFileChooser fc = new JFileChooser();
- fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get()));
- String ext = ".swf";
- switch (mode) {
- case SAVE:
- case SAVEAS:
- if (swf.getFile() != null) {
- ext = Path.getExtension(swf.getFile());
- }
- break;
- case EXE:
- ext = ".exe";
- break;
- }
-
- FileFilter swfFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.swf");
- }
- };
-
- FileFilter gfxFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.gfx");
- }
- };
-
- ExeExportMode exeExportMode = null;
- if (mode == SaveFileMode.EXE) {
- exeExportMode = Configuration.exeExportMode.get();
- if (exeExportMode == null) {
- exeExportMode = ExeExportMode.WRAPPER;
- }
- String filterDescription = null;
- switch (exeExportMode) {
- case WRAPPER:
- case PROJECTOR_WIN:
- ext = ".exe";
- filterDescription = "filter.exe";
- break;
- case PROJECTOR_MAC:
- ext = ".dmg";
- filterDescription = "filter.dmg";
- break;
- case PROJECTOR_LINUX:
- // linux projector is compressed with tar.gz
- // todo: decompress
- ext = "";
- filterDescription = "filter.linuxExe";
- break;
- }
-
- String fext = ext;
- String ffilterDescription = filterDescription;
- FileFilter exeFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(fext)) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate(ffilterDescription);
- }
- };
- fc.setFileFilter(exeFilter);
- } else if (swf.gfx) {
- fc.addChoosableFileFilter(swfFilter);
- fc.setFileFilter(gfxFilter);
- } else {
- fc.setFileFilter(swfFilter);
- fc.addChoosableFileFilter(gfxFilter);
- }
- final String extension = ext;
- fc.setAcceptAllFileFilterUsed(false);
- JFrame f = new JFrame();
- View.setWindowIcon(f);
- if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) {
- File file = Helper.fixDialogFile(fc.getSelectedFile());
- FileFilter selFilter = fc.getFileFilter();
- try {
- String fileName = file.getAbsolutePath();
- if (selFilter == swfFilter) {
- if (!fileName.toLowerCase().endsWith(extension)) {
- fileName += extension;
- }
- swf.gfx = false;
- }
- if (selFilter == gfxFilter) {
- if (!fileName.toLowerCase().endsWith(".gfx")) {
- fileName += ".gfx";
- }
- swf.gfx = true;
- }
- Main.saveFile(swf, fileName, mode, exeExportMode);
- Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath());
- return true;
- } catch (IOException ex) {
- View.showMessageDialog(null, AppStrings.translate("error.file.write"));
- }
- }
- return false;
- }
-
- public static boolean openFileDialog() {
- View.checkAccess();
-
- JFileChooser fc = new JFileChooser();
- if (Configuration.openMultipleFiles.get()) {
- fc.setMultiSelectionEnabled(true);
- }
- fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get()));
- FileFilter allSupportedFilter = new FileFilter() {
- private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip", ".iggy"};
-
- @Override
- public boolean accept(File f) {
- String name = f.getName().toLowerCase();
- for (String ext : supportedExtensions) {
- if (name.endsWith(ext)) {
- return true;
- }
- }
- return f.isDirectory();
- }
-
- @Override
- public String getDescription() {
- String exts = Helper.joinStrings(supportedExtensions, "*%s", "; ");
- return AppStrings.translate("filter.supported") + " (" + exts + ")";
- }
- };
- fc.setFileFilter(allSupportedFilter);
- FileFilter swfFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.swf");
- }
- };
- fc.addChoosableFileFilter(swfFilter);
-
- FileFilter swcFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".swc")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.swc");
- }
- };
- fc.addChoosableFileFilter(swcFilter);
-
- FileFilter gfxFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.gfx");
- }
- };
- fc.addChoosableFileFilter(gfxFilter);
-
- FileFilter iggyFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".iggy")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.iggy");
- }
- };
- fc.addChoosableFileFilter(iggyFilter);
-
- FileFilter zipFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return (f.getName().toLowerCase().endsWith(".zip")) || (f.isDirectory());
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.zip");
- }
- };
- fc.addChoosableFileFilter(zipFilter);
-
- FileFilter binaryFilter = new FileFilter() {
- @Override
- public boolean accept(File f) {
- return true;
- }
-
- @Override
- public String getDescription() {
- return AppStrings.translate("filter.binary");
- }
- };
- fc.addChoosableFileFilter(binaryFilter);
-
- fc.setAcceptAllFileFilterUsed(false);
- JFrame f = new JFrame();
- View.setWindowIcon(f);
- int returnVal = fc.showOpenDialog(f);
- if (returnVal == JFileChooser.APPROVE_OPTION) {
- Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath());
- File[] selFiles = fc.getSelectedFiles();
- for (File file : selFiles) {
- File selfile = Helper.fixDialogFile(file);
- Main.openFile(selfile.getAbsolutePath(), null);
- }
- return true;
- } else {
- return false;
- }
- }
-
- public static void displayErrorFrame() {
- ErrorLogFrame.getInstance().setVisible(true);
- }
-
- private static String md5(byte data[]) {
- try {
- java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
- byte[] array = md.digest(data);
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < array.length; ++i) {
- sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
- }
- return sb.toString();
- } catch (java.security.NoSuchAlgorithmException e) {
- }
- return null;
- }
-
- private static void initGui() {
- if (GraphicsEnvironment.isHeadless()) {
- System.err.println("Error: Your system does not support Graphic User Interface");
- exit();
- }
-
- System.setProperty("sun.java2d.d3d", "false");
- System.setProperty("sun.java2d.noddraw", "true");
-
- if (Configuration.hwAcceleratedGraphics.get()) {
- System.setProperty("sun.java2d.opengl", Configuration._debugMode.get() ? "True" : "true");
- } else {
- System.setProperty("sun.java2d.opengl", "false");
- }
-
- initUiLang();
-
- if (Configuration.useRibbonInterface.get()) {
- View.setLookAndFeel();
- } else {
- try {
- UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, null);
- UIManager.put("Tree.expandedIcon", null);
- UIManager.put("Tree.collapsedIcon", null);
- UIManager.put("ColorChooserUI", null);
- UIManager.put("ColorChooser.swatchesRecentSwatchSize", null);
- UIManager.put("ColorChooser.swatchesSwatchSize", null);
- UIManager.put("RibbonApplicationMenuPopupPanelUI", null);
- UIManager.put("RibbonApplicationMenuButtonUI", null);
- UIManager.put("ProgressBarUI", null);
- UIManager.put("TextField.background", null);
- UIManager.put("FormattedTextField.background", null);
- UIManager.put("CommandButtonUI", null);
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
- logger.log(Level.SEVERE, null, ex);
- }
- }
-
- View.execInEventDispatch(() -> {
- ErrorLogFrame.createNewInstance();
-
- autoCheckForUpdates();
- offerAssociation();
- loadingDialog = new LoadingDialog();
-
- DebuggerTools.initDebugger().addMessageListener(new DebugListener() {
- @Override
- public void onMessage(String clientId, String msg) {
- }
-
- @Override
- public void onLoaderURL(String clientId, String url) {
- }
-
- @Override
- public void onLoaderBytes(String clientId, byte[] data) {
- String hash = md5(data);
- for (SWFList sl : Main.getMainFrame().getPanel().getSwfs()) {
- for (int s = 0; s < sl.size(); s++) {
- String t = sl.get(s).getFileTitle();
- if (t == null) {
- t = "";
- }
- if (t.endsWith(":" + hash)) { //this one is already opened
- return;
- }
- }
- }
- SWF swf = Main.getMainFrame().getPanel().getCurrentSwf();
-
- String title = swf == null ? "?" : swf.getFileTitle();
- final String titleWithHash = title + ":" + hash;
- try {
- final String tfile = tempFile(titleWithHash);
- Helper.writeFile(tfile, data);
- View.execInEventDispatch(new Runnable() {
- @Override
- public void run() {
- openFile(new SWFSourceInfo(null, tfile, titleWithHash));
- }
- });
- } catch (IOException ex) {
- logger.log(Level.SEVERE, "Cannot create tempfile");
- }
- }
-
- @Override
- public void onFinish(String clientId) {
- }
- });
-
- try {
- flashDebugger = new Debugger();
- debugHandler = new DebuggerHandler();
- debugHandler.addBreakListener(new DebuggerHandler.BreakListener() {
- @Override
- public void doContinue() {
- mainFrame.getPanel().clearDebuggerColors();
- }
-
- @Override
- public void breakAt(String scriptName, int line, final int classIndex, final int traitIndex, final int methodIndex) {
- View.execInEventDispatch(new Runnable() {
- @Override
- public void run() {
- mainFrame.getPanel().gotoScriptLine(getMainFrame().getPanel().getCurrentSwf(), scriptName, line, classIndex, traitIndex, methodIndex);
- }
- });
- }
- });
- debugHandler.addConnectionListener(new DebuggerHandler.ConnectionListener() {
- @Override
- public void connected() {
- Main.mainFrame.getMenu().updateComponents();
- }
-
- @Override
- public void disconnected() {
- if (Main.mainFrame != null && Main.mainFrame.getPanel() != null) {
- Main.mainFrame.getPanel().refreshBreakPoints();
- }
- }
- });
- flashDebugger.addConnectionListener(debugHandler);
- } catch (IOException ex) {
- logger.log(Level.SEVERE, "eeex", ex);
- }
- });
- }
-
- public static void startDebugger() {
- flashDebugger.startDebugger();
- }
-
- public static void stopDebugger() {
- flashDebugger.stopDebugger();
- }
-
- public static void showModeFrame() {
- ensureMainFrame();
- mainFrame.setVisible(true);
- }
-
- private static void offerAssociation() {
- boolean offered = Configuration.offeredAssociation.get();
- if (!offered) {
- if (Platform.isWindows()) {
- if ((!ContextMenuTools.isAddedToContextMenu()) && View.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
- ContextMenuTools.addToContextMenu(true, false);
- }
- }
-
- Configuration.offeredAssociation.set(true);
- }
- }
-
- public static void initUiLang() {
- if (GraphicsEnvironment.isHeadless()) { //No GUI in OS
- return;
- }
- try {
- Class> cl = Class.forName("org.pushingpixels.substance.api.SubstanceLookAndFeel");
- Field field = cl.getDeclaredField("LABEL_BUNDLE");
- field.setAccessible(true);
- field.set(null, null);
- } catch (Throwable ex) {
- logger.log(Level.SEVERE, null, ex);
- }
-
- UIManager.put("OptionPane.okButtonText", AppStrings.translate("button.ok"));
- UIManager.put("OptionPane.yesButtonText", AppStrings.translate("button.yes"));
- UIManager.put("OptionPane.noButtonText", AppStrings.translate("button.no"));
- UIManager.put("OptionPane.cancelButtonText", AppStrings.translate("button.cancel"));
- UIManager.put("OptionPane.messageDialogTitle", AppStrings.translate("dialog.message.title"));
- UIManager.put("OptionPane.titleText", AppStrings.translate("dialog.select.title"));
-
- UIManager.put("FileChooser.acceptAllFileFilterText", AppStrings.translate("FileChooser.acceptAllFileFilterText"));
- UIManager.put("FileChooser.lookInLabelText", AppStrings.translate("FileChooser.lookInLabelText"));
- UIManager.put("FileChooser.cancelButtonText", AppStrings.translate("button.cancel"));
- UIManager.put("FileChooser.cancelButtonToolTipText", AppStrings.translate("button.cancel"));
- UIManager.put("FileChooser.openButtonText", AppStrings.translate("FileChooser.openButtonText"));
- UIManager.put("FileChooser.openButtonToolTipText", AppStrings.translate("FileChooser.openButtonToolTipText"));
- UIManager.put("FileChooser.filesOfTypeLabelText", AppStrings.translate("FileChooser.filesOfTypeLabelText"));
- UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText"));
- UIManager.put("FileChooser.listViewButtonToolTipText", AppStrings.translate("FileChooser.listViewButtonToolTipText"));
- UIManager.put("FileChooser.listViewButtonAccessibleName", AppStrings.translate("FileChooser.listViewButtonAccessibleName"));
- UIManager.put("FileChooser.detailsViewButtonToolTipText", AppStrings.translate("FileChooser.detailsViewButtonToolTipText"));
- UIManager.put("FileChooser.detailsViewButtonAccessibleName", AppStrings.translate("FileChooser.detailsViewButtonAccessibleName"));
- UIManager.put("FileChooser.upFolderToolTipText", AppStrings.translate("FileChooser.upFolderToolTipText"));
- UIManager.put("FileChooser.upFolderAccessibleName", AppStrings.translate("FileChooser.upFolderAccessibleName"));
- UIManager.put("FileChooser.homeFolderToolTipText", AppStrings.translate("FileChooser.homeFolderToolTipText"));
- UIManager.put("FileChooser.homeFolderAccessibleName", AppStrings.translate("FileChooser.homeFolderAccessibleName"));
- UIManager.put("FileChooser.fileNameHeaderText", AppStrings.translate("FileChooser.fileNameHeaderText"));
- UIManager.put("FileChooser.fileSizeHeaderText", AppStrings.translate("FileChooser.fileSizeHeaderText"));
- UIManager.put("FileChooser.fileTypeHeaderText", AppStrings.translate("FileChooser.fileTypeHeaderText"));
- UIManager.put("FileChooser.fileDateHeaderText", AppStrings.translate("FileChooser.fileDateHeaderText"));
- UIManager.put("FileChooser.fileAttrHeaderText", AppStrings.translate("FileChooser.fileAttrHeaderText"));
- UIManager.put("FileChooser.openDialogTitleText", AppStrings.translate("FileChooser.openDialogTitleText"));
- UIManager.put("FileChooser.directoryDescriptionText", AppStrings.translate("FileChooser.directoryDescriptionText"));
- UIManager.put("FileChooser.directoryOpenButtonText", AppStrings.translate("FileChooser.directoryOpenButtonText"));
- UIManager.put("FileChooser.directoryOpenButtonToolTipText", AppStrings.translate("FileChooser.directoryOpenButtonToolTipText"));
- UIManager.put("FileChooser.fileDescriptionText", AppStrings.translate("FileChooser.fileDescriptionText"));
- UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText"));
- UIManager.put("FileChooser.helpButtonText", AppStrings.translate("FileChooser.helpButtonText"));
- UIManager.put("FileChooser.helpButtonToolTipText", AppStrings.translate("FileChooser.helpButtonToolTipText"));
- UIManager.put("FileChooser.newFolderAccessibleName", AppStrings.translate("FileChooser.newFolderAccessibleName"));
- UIManager.put("FileChooser.newFolderErrorText", AppStrings.translate("FileChooser.newFolderErrorText"));
- UIManager.put("FileChooser.newFolderToolTipText", AppStrings.translate("FileChooser.newFolderToolTipText"));
- UIManager.put("FileChooser.other.newFolder", AppStrings.translate("FileChooser.other.newFolder"));
- UIManager.put("FileChooser.other.newFolder.subsequent", AppStrings.translate("FileChooser.other.newFolder.subsequent"));
- UIManager.put("FileChooser.win32.newFolder", AppStrings.translate("FileChooser.win32.newFolder"));
- UIManager.put("FileChooser.win32.newFolder.subsequent", AppStrings.translate("FileChooser.win32.newFolder.subsequent"));
- UIManager.put("FileChooser.saveButtonText", AppStrings.translate("FileChooser.saveButtonText"));
- UIManager.put("FileChooser.saveButtonToolTipText", AppStrings.translate("FileChooser.saveButtonToolTipText"));
- UIManager.put("FileChooser.saveDialogTitleText", AppStrings.translate("FileChooser.saveDialogTitleText"));
- UIManager.put("FileChooser.saveInLabelText", AppStrings.translate("FileChooser.saveInLabelText"));
- UIManager.put("FileChooser.updateButtonText", AppStrings.translate("FileChooser.updateButtonText"));
- UIManager.put("FileChooser.updateButtonToolTipText", AppStrings.translate("FileChooser.updateButtonToolTipText"));
-
- UIManager.put("FileChooser.detailsViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewActionLabel.textAndMnemonic"));
- UIManager.put("FileChooser.detailsViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewButtonToolTip.textAndMnemonic"));
- UIManager.put("FileChooser.fileAttrHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileAttrHeader.textAndMnemonic"));
- UIManager.put("FileChooser.fileDateHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileDateHeader.textAndMnemonic"));
- UIManager.put("FileChooser.fileNameHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileNameHeader.textAndMnemonic"));
- UIManager.put("FileChooser.fileNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.fileNameLabel.textAndMnemonic"));
- UIManager.put("FileChooser.fileSizeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileSizeHeader.textAndMnemonic"));
- UIManager.put("FileChooser.fileTypeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileTypeHeader.textAndMnemonic"));
- UIManager.put("FileChooser.filesOfTypeLabel.textAndMnemonic", AppStrings.translate("FileChooser.filesOfTypeLabel.textAndMnemonic"));
- UIManager.put("FileChooser.folderNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.folderNameLabel.textAndMnemonic"));
- UIManager.put("FileChooser.homeFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.homeFolderToolTip.textAndMnemonic"));
- UIManager.put("FileChooser.listViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.listViewActionLabel.textAndMnemonic"));
- UIManager.put("FileChooser.listViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.listViewButtonToolTip.textAndMnemonic"));
- UIManager.put("FileChooser.lookInLabel.textAndMnemonic", AppStrings.translate("FileChooser.lookInLabel.textAndMnemonic"));
- UIManager.put("FileChooser.newFolderActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.newFolderActionLabel.textAndMnemonic"));
- UIManager.put("FileChooser.newFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.newFolderToolTip.textAndMnemonic"));
- UIManager.put("FileChooser.refreshActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.refreshActionLabel.textAndMnemonic"));
- UIManager.put("FileChooser.saveInLabel.textAndMnemonic", AppStrings.translate("FileChooser.saveInLabel.textAndMnemonic"));
- UIManager.put("FileChooser.upFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.upFolderToolTip.textAndMnemonic"));
- UIManager.put("FileChooser.viewMenuButtonAccessibleName", AppStrings.translate("FileChooser.viewMenuButtonAccessibleName"));
- UIManager.put("FileChooser.viewMenuButtonToolTipText", AppStrings.translate("FileChooser.viewMenuButtonToolTipText"));
- UIManager.put("FileChooser.viewMenuLabel.textAndMnemonic", AppStrings.translate("FileChooser.viewMenuLabel.textAndMnemonic"));
- UIManager.put("FileChooser.newFolderActionLabelText", AppStrings.translate("FileChooser.newFolderActionLabelText"));
- UIManager.put("FileChooser.listViewActionLabelText", AppStrings.translate("FileChooser.listViewActionLabelText"));
- UIManager.put("FileChooser.detailsViewActionLabelText", AppStrings.translate("FileChooser.detailsViewActionLabelText"));
- UIManager.put("FileChooser.refreshActionLabelText", AppStrings.translate("FileChooser.refreshActionLabelText"));
- UIManager.put("FileChooser.sortMenuLabelText", AppStrings.translate("FileChooser.sortMenuLabelText"));
- UIManager.put("FileChooser.viewMenuLabelText", AppStrings.translate("FileChooser.viewMenuLabelText"));
- UIManager.put("FileChooser.fileSizeKiloBytes", AppStrings.translate("FileChooser.fileSizeKiloBytes"));
- UIManager.put("FileChooser.fileSizeMegaBytes", AppStrings.translate("FileChooser.fileSizeMegaBytes"));
- UIManager.put("FileChooser.fileSizeGigaBytes", AppStrings.translate("FileChooser.fileSizeGigaBytes"));
- UIManager.put("FileChooser.folderNameLabelText", AppStrings.translate("FileChooser.folderNameLabelText"));
-
- UIManager.put("ColorChooser.okText", AppStrings.translate("ColorChooser.okText"));
- UIManager.put("ColorChooser.cancelText", AppStrings.translate("ColorChooser.cancelText"));
- UIManager.put("ColorChooser.resetText", AppStrings.translate("ColorChooser.resetText"));
- UIManager.put("ColorChooser.previewText", AppStrings.translate("ColorChooser.previewText"));
- UIManager.put("ColorChooser.swatchesNameText", AppStrings.translate("ColorChooser.swatchesNameText"));
- UIManager.put("ColorChooser.swatchesRecentText", AppStrings.translate("ColorChooser.swatchesRecentText"));
- UIManager.put("ColorChooser.sampleText", AppStrings.translate("ColorChooser.sampleText"));
-
- }
-
- public static void initLang() {
- if (!Configuration.locale.hasValue()) {
- if (Platform.isWindows()) {
- //Load from Installer
- String uninstKey = "{E618D276-6596-41F4-8A98-447D442A77DB}_is1";
- uninstKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uninstKey;
- try {
- if (Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey)) {
- if (Advapi32Util.registryValueExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language")) {
- String installedLoc = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language");
- int lcid = Integer.parseInt(installedLoc);
- char[] buf = new char[9];
- int cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO639LANGNAME, buf, 9);
- String langCode = new String(buf, 0, cnt).trim().toLowerCase();
-
- cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO3166CTRYNAME, buf, 9);
- String countryCode = new String(buf, 0, cnt).trim().toLowerCase();
-
- List langs = Arrays.asList(SelectLanguageDialog.getAvailableLanguages());
- for (int i = 0; i < langs.size(); i++) {
- langs.set(i, langs.get(i).toLowerCase());
- }
-
- String selectedLang = null;
-
- if (langs.contains(langCode + "-" + countryCode)) {
- selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode + "-" + countryCode)];
- } else if (langs.contains(langCode)) {
- selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode)];
- }
- if (selectedLang != null) {
- Configuration.locale.set(selectedLang);
- }
- }
- }
- } catch (Exception ex) {
- //ignore
- }
- }
- }
- Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get()));
- AppStrings.updateLanguage();
-
- Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable");
- }
-
- /**
- * Clear old FFDec/JavactiveX temp files
- */
- private static void clearTemp() {
- String tempDirPath = System.getProperty("java.io.tmpdir");
- if (tempDirPath == null) {
- return;
- }
- File tempDir = new File(tempDirPath);
- if (!tempDir.exists()) {
- return;
- }
- File[] delFiles = tempDir.listFiles(new FilenameFilter() {
- @Override
- public boolean accept(File dir, String name) {
- return name.matches("ffdec_cache.*\\.tmp") || name.matches("javactivex_.*\\.exe") || name.matches("temp[0-9]+\\.swf") || name.matches("ffdec_view_.*\\.swf");
- }
- });
-
- if (delFiles != null) {
- for (File f : delFiles) {
- try {
- f.delete();
- } catch (Exception ex) {
- //ignore
- }
- }
- }
- }
-
- /**
- * @param args the command line arguments
- * @throws IOException On error
- */
- public static void main(String[] args) throws IOException {
- setSessionLoaded(false);
-
- clearTemp();
-
- try {
- SWFDecompilerPlugin.loadPlugins();
- } catch (Throwable ex) {
- logger.log(Level.SEVERE, "Failed to load plugins", ex);
- }
-
- AppStrings.setResourceClass(MainFrame.class);
- initLogging(Configuration._debugMode.get());
-
- initLang();
-
- if (Configuration.cacheOnDisk.get()) {
- Cache.setStorageType(Cache.STORAGE_FILES);
- } else {
- Cache.setStorageType(Cache.STORAGE_MEMORY);
- }
-
- if (args.length == 0) {
- initGui();
- checkLibraryVersion();
- View.execInEventDispatch(() -> {
- if (Configuration.allowOnlyOneInstance.get() && FirstInstance.focus()) { //Try to focus first instance
- Main.exit();
- } else {
- showModeFrame();
- reloadLastSession();
- }
- });
- } else {
- checkLibraryVersion();
- setSessionLoaded(true);
- String[] filesToOpen = CommandLineArgumentParser.parseArguments(args);
- if (filesToOpen != null && filesToOpen.length > 0) {
- View.execInEventDispatch(() -> {
- initGui();
- shouldCloseWhenClosingLoadingDialog = true;
- if (Configuration.allowOnlyOneInstance.get() && FirstInstance.openFiles(Arrays.asList(filesToOpen))) { //Try to open in first instance
- Main.exit();
- } else {
- for (String fileToOpen : filesToOpen) {
- openFile(fileToOpen, null);
- }
- }
- });
- }
- }
- }
-
- private static void checkLibraryVersion() {
- if (!ApplicationInfo.version.equals("unknown") && !ApplicationInfo.libraryVersion.equals("unknown")
- && !Objects.equals(ApplicationInfo.version, ApplicationInfo.libraryVersion)) {
- logger.log(Level.WARNING, "Application version is different from library version. FFDec may not work properly.");
- }
- }
-
- private static void reloadLastSession() {
- boolean openingFiles = false;
- if (Configuration.saveSessionOnExit.get()) {
- String lastSession = Configuration.lastSessionFiles.get();
- if (lastSession != null && lastSession.length() > 0) {
- String[] filesToOpen = lastSession.split(File.pathSeparator, -1);
- List exfiles = new ArrayList<>();
- List extitles = new ArrayList<>();
- String lastSessionTitles = Configuration.lastSessionFileTitles.get();
- String[] fileTitles = new String[0];
- if (lastSessionTitles != null && !lastSessionTitles.isEmpty()) {
- fileTitles = lastSessionTitles.split(File.pathSeparator, -1);
- }
- for (int i = 0; i < filesToOpen.length; i++) {
- if (new File(filesToOpen[i]).exists()) {
- exfiles.add(filesToOpen[i]);
- if (fileTitles.length > i) {
- extitles.add(fileTitles[i]);
- } else {
- extitles.add(null);
- }
- }
- }
- SWFSourceInfo[] sourceInfos = new SWFSourceInfo[exfiles.size()];
- for (int i = 0; i < exfiles.size(); i++) {
- String extitle = extitles.get(i);
- sourceInfos[i] = new SWFSourceInfo(null, exfiles.get(i), extitle == null || extitle.isEmpty() ? null : extitle);
- }
- if (sourceInfos.length > 0) {
- openingFiles = true;
- openFile(sourceInfos, () -> {
- mainFrame.getPanel().tagTree.setSelectionPathString(Configuration.lastSessionSelection.get());
- setSessionLoaded(true);
- });
- }
- }
- }
-
- if (!openingFiles) {
- setSessionLoaded(true);
- }
- }
-
- public static String tempFile(String url) throws IOException {
- File f = new File(Configuration.getFFDecHome() + "saved" + File.separator);
- Path.createDirectorySafe(f);
- return Configuration.getFFDecHome() + "saved" + File.separator + "asdec_" + Integer.toHexString(url.hashCode()) + ".tmp";
- }
-
- public static void removeTrayIcon() {
- if (SystemTray.isSupported()) {
- SystemTray tray = SystemTray.getSystemTray();
- if (trayIcon != null) {
- tray.remove(trayIcon);
- trayIcon = null;
- }
- }
- }
-
- public static void switchProxy() {
- proxyFrame.switchState();
- if (stopMenuItem != null) {
- if (proxyFrame.isRunning()) {
- stopMenuItem.setLabel(AppStrings.translate("proxy.stop"));
- } else {
- stopMenuItem.setLabel(AppStrings.translate("proxy.start"));
- }
- }
- }
-
- public static void addTrayIcon() {
- if (trayIcon != null) {
- return;
- }
- if (SystemTray.isSupported()) {
- SystemTray tray = SystemTray.getSystemTray();
- trayIcon = new TrayIcon(View.loadImage("proxy16"), ApplicationInfo.VENDOR + " " + ApplicationInfo.SHORT_APPLICATION_NAME + " " + AppStrings.translate("proxy"));
- trayIcon.setImageAutoSize(true);
- PopupMenu trayPopup = new PopupMenu();
-
- ActionListener trayListener = new ActionListener() {
- /**
- * Invoked when an action occurs.
- */
- @Override
- public void actionPerformed(ActionEvent e) {
- if (e.getActionCommand().equals("EXIT")) {
- Main.exit();
- }
- if (e.getActionCommand().equals("SHOW")) {
- Main.showProxy();
- }
- if (e.getActionCommand().equals("SWITCH")) {
- Main.switchProxy();
- }
- }
- };
-
- MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show"));
- showMenuItem.setActionCommand("SHOW");
- showMenuItem.addActionListener(trayListener);
- trayPopup.add(showMenuItem);
- stopMenuItem = new MenuItem(AppStrings.translate("proxy.start"));
- stopMenuItem.setActionCommand("SWITCH");
- stopMenuItem.addActionListener(trayListener);
- trayPopup.add(stopMenuItem);
- trayPopup.addSeparator();
- MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit"));
- exitMenuItem.setActionCommand("EXIT");
- exitMenuItem.addActionListener(trayListener);
- trayPopup.add(exitMenuItem);
-
- trayIcon.setPopupMenu(trayPopup);
- trayIcon.addMouseListener(new MouseAdapter() {
- /**
- * {@inheritDoc}
- */
- @Override
- public void mouseClicked(MouseEvent e) {
- if (e.getButton() == MouseEvent.BUTTON1) {
- Main.showProxy();
- }
- }
- });
- try {
- tray.add(trayIcon);
- } catch (AWTException ex) {
- }
- }
- }
-
- public static void exit() {
- Configuration.saveConfig();
- if (mainFrame != null && mainFrame.getPanel() != null) {
- mainFrame.getPanel().unloadFlashPlayer();
- mainFrame.dispose();
- }
- if (fileTxt != null) {
- try {
- fileTxt.flush();
- fileTxt.close();
- } catch (Exception ex) {
- //ignore
- }
- }
- System.exit(0);
- }
-
- public static void about() {
- (new AboutDialog()).setVisible(true);
- }
-
- public static void advancedSettings() {
- advancedSettings(null);
- }
-
- public static void advancedSettings(String category) {
- (new AdvancedSettingsDialog(category)).setVisible(true);
- }
-
- public static void autoCheckForUpdates() {
- if (Configuration.checkForUpdatesAuto.get()) {
- Calendar lastUpdatesCheckDate = Configuration.lastUpdatesCheckDate.get();
- if ((lastUpdatesCheckDate == null) || (lastUpdatesCheckDate.getTime().getTime() < Calendar.getInstance().getTime().getTime() - Configuration.checkForUpdatesDelay.get())) {
- new SwingWorker() {
- @Override
- protected Object doInBackground() throws Exception {
- checkForUpdates();
- return null;
- }
- }.execute();
- }
- }
- }
-
- public static boolean checkForUpdates() {
- String currentVersion = ApplicationInfo.version;
- if (currentVersion.equals("unknown")) {
- // sometimes during development the version information is not available
- return false;
- }
-
- List accepted = new ArrayList<>();
- if (Configuration.checkForUpdatesStable.get()) {
- accepted.add("stable");
- }
- if (Configuration.checkForUpdatesNightly.get()) {
- accepted.add("nightly");
- }
-
- if (accepted.isEmpty()) {
- return false;
- }
-
- String acceptVersions = String.join(",", accepted);
- try {
- String proxyAddress = Configuration.updateProxyAddress.get();
- URL url = new URL(ApplicationInfo.updateCheckUrl);
-
- URLConnection uc;
- if (proxyAddress != null && !proxyAddress.isEmpty()) {
- int port = 8080;
- if (proxyAddress.contains(":")) {
- String[] parts = proxyAddress.split(":");
- port = Integer.parseInt(parts[1]);
- proxyAddress = parts[0];
- }
-
- uc = url.openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, port)));
- } else {
- uc = url.openConnection();
- }
- uc.setRequestProperty("X-Accept-Versions", acceptVersions);
- uc.setRequestProperty("X-Update-Major", "" + UPDATE_SYSTEM_MAJOR);
- uc.setRequestProperty("X-Update-Minor", "" + UPDATE_SYSTEM_MINOR);
- uc.setRequestProperty("User-Agent", ApplicationInfo.shortApplicationVerName);
- String currentLoc = Configuration.locale.get("en");
- uc.setRequestProperty("Accept-Language", currentLoc + ("en".equals(currentLoc) ? "" : ", en;q=0.8"));
-
- uc.connect();
-
- BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
- String s;
- final java.util.List versions = new ArrayList<>();
- String header = "";
- Pattern headerPat = Pattern.compile("\\[([a-zA-Z0-9]+)\\]");
- int updateMajor;
- int updateMinor;
- Version ver = null;
- while ((s = br.readLine()) != null) {
-
- Matcher m = headerPat.matcher(s);
- if (m.matches()) {
- header = m.group(1);
- if (header.equals("version")) {
- ver = new Version();
- versions.add(ver);
- }
- if (header.equals("noversion")) {
- break;
- }
- } else if (s.contains("=")) {
- String key = s.substring(0, s.indexOf('='));
- String val = s.substring(s.indexOf('=') + 1);
- if ("updateSystem".equals(header)) {
- if (key.equals("majorVersion")) {
- updateMajor = Integer.parseInt(val);
- if (updateMajor > UPDATE_SYSTEM_MAJOR) {
- break;
- }
- }
- if (key.equals("minorVersion")) {
- updateMinor = Integer.parseInt(val);
- }
- }
- if ("version".equals(header) && (ver != null)) {
- if (key.equals("versionId")) {
- ver.versionId = Integer.parseInt(val);
- }
- if (key.equals("versionName")) {
- ver.versionName = val;
- }
- if (key.equals("nightly")) {
- ver.nightly = val.equals("true");
- }
- if (key.equals("revision")) {
- ver.revision = val;
- }
- if (key.equals("build")) {
- ver.build = Integer.parseInt(val);
- }
- if (key.equals("major")) {
- ver.major = Integer.parseInt(val);
- }
- if (key.equals("minor")) {
- ver.minor = Integer.parseInt(val);
- }
- if (key.equals("release")) {
- ver.release = Integer.parseInt(val);
- }
- if (key.equals("longVersionName")) {
- ver.longVersionName = val;
- }
- if (key.equals("releaseDate")) {
- ver.releaseDate = val;
- }
- if (key.equals("appName")) {
- ver.appName = val;
- }
- if (key.equals("appFullName")) {
- ver.appFullName = val;
- }
- if (key.equals("updateLink")) {
- ver.updateLink = val;
- }
- if (key.equals("change[]")) {
- String changeType = val.substring(0, val.indexOf('|'));
- String change = val.substring(val.indexOf('|') + 1);
- if (!ver.changes.containsKey(changeType)) {
- ver.changes.put(changeType, new ArrayList<>());
- }
- List chlist = ver.changes.get(changeType);
- chlist.add(change);
- }
- }
- }
- }
-
- if (!versions.isEmpty()) {
- View.execInEventDispatch(() -> {
- NewVersionDialog newVersionDialog = new NewVersionDialog(versions);
- newVersionDialog.setVisible(true);
- Configuration.lastUpdatesCheckDate.set(Calendar.getInstance());
- });
-
- return true;
- }
- } catch (IOException | NumberFormatException ex) {
- return false;
- }
- Configuration.lastUpdatesCheckDate.set(Calendar.getInstance());
- return false;
- }
-
- private static FileHandler fileTxt;
-
- public static void clearLogFile() {
- Logger logger = Logger.getLogger("");
-
- FileHandler oldFileTxt = fileTxt;
- fileTxt = null;
- if (oldFileTxt != null) {
- logger.removeHandler(fileTxt);
- oldFileTxt.flush();
- oldFileTxt.close();
- }
-
- String fileName = null;
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
-
- try {
- fileName = Configuration.getFFDecHome() + "logs" + File.separator;
- if (Configuration.useDetailedLogging.get()) {
- fileName += "log-" + sdf.format(new Date()) + ".txt";
- } else {
- fileName += "log.txt";
- }
- File f = new File(fileName).getParentFile();
- if (!f.exists()) {
- f.mkdir();
- }
- fileTxt = new FileHandler(fileName);
- } catch (IOException | SecurityException ex) {
- //cannot get lock error
- if (ex.getMessage().contains("lock for")) {
- //remove all old log files and their .lck
- for (int i = 0; i <= 100; i++) {
- File flog = new File(fileName + (i == 0 ? "" : "." + i));
- File flog_lock = new File(fileName + (i == 0 ? "" : "." + i) + ".lck");
- flog.delete();
- flog_lock.delete();
- }
- try {
- fileTxt = new FileHandler(fileName);
- } catch (IOException | SecurityException ex1) {
- logger.log(Level.SEVERE, "Cannot initialize logging", ex);
- }
- } else {
- logger.log(Level.SEVERE, "Cannot initialize logging", ex);
- }
- }
-
- Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- logger.log(Level.SEVERE, "Uncaught exception in thread: " + t.getName(), e);
- if (e instanceof OutOfMemoryError && !Helper.is64BitJre() && Helper.is64BitOs()) {
- View.showMessageDialog(null, AppStrings.translate("message.warning.outOfMemory32BitJre"), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE);
- }
- }
- });
-
- Formatter formatterTxt = new LogFormatter();
- if (fileTxt != null) {
- fileTxt.setFormatter(formatterTxt);
- logger.addHandler(fileTxt);
- }
-
- if (!GraphicsEnvironment.isHeadless() && ErrorLogFrame.hasInstance()) {
- ErrorLogFrame.getInstance().clearErrorState();
- }
-
- sdf = new SimpleDateFormat("yyyy-MM-dd");
- logger.log(Level.INFO, "Date: {0}", sdf.format(new Date()));
- logger.log(Level.INFO, ApplicationInfo.applicationVerName);
- logger.log(Level.INFO, "{0} {1} {2}", new Object[]{
- System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")});
- logger.log(Level.INFO, "{0} {1} {2}", new Object[]{
- System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("os.arch")});
- }
-
- public static void initLogging(boolean debug) {
- try {
- Logger logger = Logger.getLogger("");
- logger.setLevel(Configuration.logLevel);
-
- Handler[] handlers = logger.getHandlers();
- for (int i = handlers.length - 1; i >= 0; i--) {
- logger.removeHandler(handlers[i]);
- }
-
- ConsoleHandler conHan = new ConsoleHandler();
- conHan.setLevel(debug ? Level.CONFIG : Level.WARNING);
- SimpleFormatter formatterTxt = new SimpleFormatter();
- conHan.setFormatter(formatterTxt);
- logger.addHandler(conHan);
- clearLogFile();
-
- } catch (Exception ex) {
- throw new RuntimeException("Problems with creating the log files");
- }
- }
-}
+/*
+ * Copyright (C) 2010-2016 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 com.jpexs.debugger.flash.Debugger;
+import com.jpexs.debugger.flash.DebuggerCommands;
+import com.jpexs.debugger.flash.Variable;
+import com.jpexs.debugger.flash.VariableType;
+import com.jpexs.debugger.flash.messages.in.InCallFunction;
+import com.jpexs.decompiler.flash.ApplicationInfo;
+import com.jpexs.decompiler.flash.EventListener;
+import com.jpexs.decompiler.flash.SWF;
+import com.jpexs.decompiler.flash.SWFBundle;
+import com.jpexs.decompiler.flash.SWFSourceInfo;
+import com.jpexs.decompiler.flash.SearchMode;
+import com.jpexs.decompiler.flash.SwfOpenException;
+import com.jpexs.decompiler.flash.UrlResolver;
+import com.jpexs.decompiler.flash.Version;
+import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
+import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
+import com.jpexs.decompiler.flash.configuration.Configuration;
+import com.jpexs.decompiler.flash.configuration.SwfSpecificConfiguration;
+import com.jpexs.decompiler.flash.console.CommandLineArgumentParser;
+import com.jpexs.decompiler.flash.console.ContextMenuTools;
+import com.jpexs.decompiler.flash.exporters.modes.ExeExportMode;
+import com.jpexs.decompiler.flash.gui.debugger.DebugListener;
+import com.jpexs.decompiler.flash.gui.debugger.DebuggerTools;
+import com.jpexs.decompiler.flash.gui.pipes.FirstInstance;
+import com.jpexs.decompiler.flash.gui.proxy.ProxyFrame;
+import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
+import com.jpexs.decompiler.flash.tags.Tag;
+import com.jpexs.decompiler.flash.tags.base.FontTag;
+import com.jpexs.decompiler.flash.tags.base.ImportTag;
+import com.jpexs.decompiler.flash.treeitems.SWFList;
+import com.jpexs.helpers.Cache;
+import com.jpexs.helpers.CancellableWorker;
+import com.jpexs.helpers.Helper;
+import com.jpexs.helpers.Path;
+import com.jpexs.helpers.ProgressListener;
+import com.jpexs.helpers.Stopwatch;
+import com.jpexs.helpers.streams.SeekableInputStream;
+import com.sun.jna.Platform;
+import com.sun.jna.platform.win32.Advapi32Util;
+import com.sun.jna.platform.win32.Kernel32;
+import com.sun.jna.platform.win32.WinReg;
+import java.awt.AWTException;
+import java.awt.Frame;
+import java.awt.GraphicsEnvironment;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.URL;
+import java.net.URLConnection;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.FileHandler;
+import java.util.logging.Formatter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.SwingWorker;
+import javax.swing.UIManager;
+import javax.swing.UnsupportedLookAndFeelException;
+import javax.swing.filechooser.FileFilter;
+import org.pushingpixels.substance.api.SubstanceLookAndFeel;
+
+/**
+ * Main executable class
+ *
+ * @author JPEXS
+ */
+public class Main {
+
+ protected static ProxyFrame proxyFrame;
+
+ private static List sourceInfos = new ArrayList<>();
+
+ public static LoadingDialog loadingDialog;
+
+ private static boolean working = false;
+
+ private static TrayIcon trayIcon;
+
+ private static MenuItem stopMenuItem;
+
+ private static volatile MainFrame mainFrame;
+
+ public static final int UPDATE_SYSTEM_MAJOR = 1;
+
+ public static final int UPDATE_SYSTEM_MINOR = 3;
+
+ private static LoadFromMemoryFrame loadFromMemoryFrame;
+
+ private static LoadFromCacheFrame loadFromCacheFrame;
+
+ private static final Logger logger = Logger.getLogger(Main.class.getName());
+
+ public static DebugLogDialog debugDialog;
+
+ public static boolean shouldCloseWhenClosingLoadingDialog;
+
+ private static Debugger flashDebugger;
+
+ private static DebuggerHandler debugHandler = null;
+
+ //private static int ip = 0;
+ //private static String ipClass = null;
+ private static Process runProcess;
+
+ private static boolean runProcessDebug;
+
+ private static boolean runProcessDebugPCode;
+
+ private static boolean inited = false;
+
+ private static File runTempFile;
+
+ private static List runTempFiles = new ArrayList<>();
+
+ public static void freeRun() {
+ synchronized (Main.class) {
+ if (runTempFile != null) {
+ runTempFile.delete();
+ runTempFile = null;
+ }
+ for (File f : runTempFiles) {
+ f.delete();
+ }
+ runTempFiles.clear();
+
+ runProcess = null;
+ }
+ if (mainFrame != null && mainFrame.getPanel() != null) {
+ mainFrame.getPanel().clearDebuggerColors();
+ }
+ if (runProcessDebug) {
+ Main.getDebugHandler().disconnect();
+ }
+ }
+
+ public static synchronized boolean isDebugPaused() {
+ return runProcess != null && runProcessDebug && getDebugHandler().isPaused();
+ }
+
+ public static synchronized boolean isDebugRunning() {
+ return runProcess != null && runProcessDebug;
+ }
+
+ public static synchronized boolean isDebugPCode() {
+ return runProcessDebugPCode;
+ }
+
+ public static synchronized boolean isDebugConnected() {
+ return getDebugHandler().isConnected();
+ }
+
+ public static synchronized boolean isRunning() {
+ return runProcess != null && !runProcessDebug;
+ }
+
+ /**
+ * FIXME!
+ *
+ * @param v
+ */
+ public static synchronized void dumpBytes(Variable v) {
+ InCallFunction icf;
+ try {
+ long objectId = 0l;
+ if ((v.vType == VariableType.OBJECT || v.vType == VariableType.MOVIECLIP)) {
+ objectId = (Long) v.value;
+ }
+ Object oldPos = getDebugHandler().getVariable(objectId, "position", true).parent.value;
+ getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, 0);
+ icf = getDebugHandler().callFunction(false, "readUTF", v, new ArrayList<>());
+ System.out.println("Result=" + icf.variables.get(0).value);
+ getDebugHandler().setVariable(objectId, "position", VariableType.NUMBER, oldPos);
+ } catch (DebuggerHandler.ActionScriptException ex) {
+ Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
+ }
+
+ }
+
+ public static synchronized boolean addWatch(Variable v, long v_id, boolean watchRead, boolean watchWrite) {
+ DebuggerCommands.Watch w = getDebugHandler().addWatch(v, v_id, watchRead, watchWrite);
+ return w != null;
+ }
+
+ public static void runPlayer(String title, final String exePath, String file, String flashVars) {
+ if (!new File(file).exists()) {
+ return;
+ }
+ if (flashVars != null && !flashVars.isEmpty()) {
+ file += "?" + flashVars;
+ }
+ final String ffile = file;
+
+ CancellableWorker runWorker = new CancellableWorker() {
+ @Override
+ protected Object doInBackground() throws Exception {
+ Process proc;
+ try {
+ proc = Runtime.getRuntime().exec(new String[]{exePath, ffile});
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, null, ex);
+ return null;
+ }
+ boolean isDebug;
+
+ synchronized (Main.class) {
+ runProcess = proc;
+ isDebug = runProcessDebug;
+ }
+ if (isDebug) {
+ mainFrame.getMenu().hilightPath("/debugging");
+ }
+ mainFrame.getMenu().updateComponents();
+ try {
+ if (proc != null) {
+ proc.waitFor();
+ }
+ } catch (InterruptedException ex) {
+ if (proc != null) {
+ try {
+ proc.destroy();
+ } catch (Exception ex2) {
+ //ignore
+ }
+ }
+ }
+ freeRun();
+ stopDebugger();
+ mainFrame.getMenu().updateComponents();
+ return null;
+ }
+
+ @Override
+ protected void done() {
+ Main.stopWork();
+ }
+
+ @Override
+ public void workerCancelled() {
+ Main.stopWork();
+ synchronized (Main.class) {
+ if (runProcess != null) {
+ try {
+ runProcess.destroy();
+ } catch (Exception ex) {
+
+ }
+ }
+ }
+ freeRun();
+ mainFrame.getMenu().updateComponents();
+ }
+ };
+
+ mainFrame.getMenu().updateComponents();
+ Main.startWork(title + "...", runWorker);
+ runWorker.execute();
+ }
+
+ public static void stopRun() {
+
+ synchronized (Main.class) {
+ if (runProcess != null) {
+ runProcess.destroy();
+ }
+ }
+ freeRun();
+ stopDebugger();
+ mainFrame.getMenu().updateComponents();
+ }
+
+ private static interface SwfPreparation {
+
+ public SWF prepare(SWF swf);
+ }
+
+ private static class SwfRunPrepare implements SwfPreparation {
+
+ @Override
+ public SWF prepare(SWF swf) {
+ if (Configuration.autoOpenLoadedSWFs.get()) {
+ if (!DebuggerTools.hasDebugger(swf)) {
+ DebuggerTools.switchDebugger(swf);
+ }
+ DebuggerTools.injectDebugLoader(swf);
+ }
+ return swf;
+ }
+ }
+
+ private static class SwfDebugPrepare extends SwfRunPrepare {
+
+ private boolean doPCode;
+
+ public SwfDebugPrepare(boolean doPCode) {
+ this.doPCode = doPCode;
+ }
+
+ @Override
+ public SWF prepare(SWF instrSWF) {
+ instrSWF = super.prepare(instrSWF);
+ try {
+ File fTempFile = new File(instrSWF.getFile());
+ instrSWF.enableDebugging(true, new File("."), true, doPCode);
+ FileOutputStream fos = new FileOutputStream(fTempFile);
+ instrSWF.saveTo(fos);
+ fos.close();
+ if (!instrSWF.isAS3()) {
+ //Read again, because line file offsets changed with adding debug tags
+ //TODO: handle somehow without rereading?
+ instrSWF = null;
+ try (FileInputStream fis = new FileInputStream(fTempFile)) {
+ instrSWF = new SWF(fis, false, false);
+ } catch (InterruptedException ex) {
+ logger.log(Level.SEVERE, null, ex);
+ }
+ if (instrSWF != null) {
+ String swfFileName = fTempFile.getAbsolutePath();
+ if (swfFileName.toLowerCase().endsWith(".swf")) {
+ swfFileName = swfFileName.substring(0, swfFileName.length() - 4) + ".swd";
+ } else {
+ swfFileName = swfFileName + ".swd";
+ }
+ File swdFile = new File(swfFileName);
+ if (doPCode) {
+ instrSWF.generatePCodeSwdFile(swdFile, getPackBreakPoints(true));
+ } else {
+ instrSWF.generateSwdFile(swdFile, getPackBreakPoints(true));
+ }
+ }
+ }
+ } catch (IOException ex) {
+ //ignore, return instrSWF
+ }
+ return instrSWF;
+ }
+ }
+
+ private static void prepareSwf(SwfPreparation prep, File toPrepareFile, File origFile, List tempFiles) throws IOException {
+ SWF instrSWF = null;
+ try (FileInputStream fis = new FileInputStream(toPrepareFile)) {
+ instrSWF = new SWF(fis, toPrepareFile.getAbsolutePath(), origFile.getName(), false);
+ } catch (InterruptedException ex) {
+ logger.log(Level.SEVERE, null, ex);
+ }
+ if (instrSWF != null) {
+ for (Tag t : instrSWF.getLocalTags()) {
+ if (t instanceof ImportTag) {
+ ImportTag it = (ImportTag) t;
+ String url = it.getUrl();
+ File importedFile = new File(origFile.getParentFile(), url);
+ if (importedFile.exists()) {
+ File newTempFile = File.createTempFile("ffdec_run_import_", ".swf");
+ it.setUrl("./" + newTempFile.getName());
+ byte[] impData = Helper.readFile(importedFile.getAbsolutePath());
+ Helper.writeFile(newTempFile.getAbsolutePath(), impData);
+ tempFiles.add(newTempFile);
+ prepareSwf(prep, newTempFile, importedFile, tempFiles);
+ }
+ }
+ }
+ if (prep != null) {
+ instrSWF = prep.prepare(instrSWF);
+ }
+ try (FileOutputStream fos = new FileOutputStream(toPrepareFile)) {
+ instrSWF.saveTo(fos);
+ }
+ }
+ }
+
+ public static void run(SWF swf) {
+ String flashVars = "";//key=val&key2=val2
+ String playerLocation = Configuration.playerLocation.get();
+ if (playerLocation.isEmpty() || (!new File(playerLocation).exists())) {
+ View.showMessageDialog(null, AppStrings.translate("message.playerpath.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
+ advancedSettings("paths");
+ return;
+ }
+ if (swf == null) {
+ return;
+ }
+ File tempFile;
+ List tempFiles = new ArrayList<>();
+ try {
+ tempFile = File.createTempFile("ffdec_run_", ".swf");
+
+ try (FileOutputStream fos = new FileOutputStream(tempFile)) {
+ swf.saveTo(fos);
+ }
+
+ prepareSwf(new SwfRunPrepare(), tempFile, new File(swf.getFile()), tempFiles);
+
+ } catch (IOException ex) {
+ return;
+
+ }
+ if (tempFile != null) {
+ synchronized (Main.class) {
+ runTempFile = tempFile;
+ runTempFiles = tempFiles;
+ runProcessDebug = false;
+ }
+ runPlayer(AppStrings.translate("work.running"), playerLocation, tempFile.getAbsolutePath(), flashVars);
+ }
+ }
+
+ public static void runDebug(SWF swf, final boolean doPCode) {
+ String flashVars = "";//key=val&key2=val2
+ String playerLocation = Configuration.playerDebugLocation.get();
+ if (playerLocation.isEmpty() || (!new File(playerLocation).exists())) {
+ View.showMessageDialog(null, AppStrings.translate("message.playerpath.debug.notset"), AppStrings.translate("error"), JOptionPane.ERROR_MESSAGE);
+ Main.advancedSettings("paths");
+ return;
+ }
+ if (swf == null) {
+ return;
+ }
+ File tempFile = null;
+
+ try {
+ tempFile = File.createTempFile("ffdec_debug_", ".swf");
+ } catch (Exception ex) {
+
+ }
+
+ if (tempFile != null) {
+ final File fTempFile = tempFile;
+ final List tempFiles = new ArrayList<>();
+ CancellableWorker instrumentWorker = new CancellableWorker() {
+ @Override
+ protected Object doInBackground() throws Exception {
+
+ try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(fTempFile))) {
+ swf.saveTo(fos);
+ }
+ prepareSwf(new SwfDebugPrepare(doPCode), fTempFile, new File(swf.getFile()), tempFiles);
+ return null;
+ }
+
+ @Override
+ public void workerCancelled() {
+ Main.stopWork();
+ }
+
+ @Override
+ protected void done() {
+ synchronized (Main.class) {
+ runTempFile = fTempFile;
+ runProcessDebug = true;
+ runProcessDebugPCode = doPCode;
+ runTempFiles = tempFiles;
+ }
+ Main.stopWork();
+ Main.startDebugger();
+ runPlayer(AppStrings.translate("work.debugging.wait"), playerLocation, fTempFile.getAbsolutePath(), flashVars);
+ }
+ };
+
+ Main.startWork(AppStrings.translate("work.debugging.instrumenting"), instrumentWorker);
+ instrumentWorker.execute();
+ }
+ }
+
+ /* public static void debuggerNotSuspended() {
+
+ }*/
+ public static boolean isDebugging() {
+ return isDebugRunning();
+ }
+
+ public synchronized static int getIp(Object pack) {
+ return getDebugHandler().getBreakIp();
+ }
+
+ public synchronized static String getIpClass() {
+ return getDebugHandler().getBreakScriptName();
+ }
+
+ public static synchronized boolean isBreakPointValid(String scriptName, int line) {
+ return !getDebugHandler().isBreakpointInvalid(scriptName, line);
+ }
+
+ public synchronized static void addBreakPoint(String scriptName, int line) {
+ getDebugHandler().addBreakPoint(scriptName, line);
+ }
+
+ public synchronized static void removeBreakPoint(String scriptName, int line) {
+ getDebugHandler().removeBreakPoint(scriptName, line);
+ }
+
+ public synchronized static boolean toggleBreakPoint(String scriptName, int line) {
+ if (getDebugHandler().isBreakpointToAdd(scriptName, line) || getDebugHandler().isBreakpointConfirmed(scriptName, line) || getDebugHandler().isBreakpointInvalid(scriptName, line)) {
+ getDebugHandler().removeBreakPoint(scriptName, line);
+ return false;
+ } else {
+ getDebugHandler().addBreakPoint(scriptName, line);
+ return true;
+ }
+ }
+
+ public synchronized static Map> getPackBreakPoints(boolean validOnly) {
+ return getDebugHandler().getAllBreakPoints(validOnly);
+ }
+
+ public synchronized static Set getScriptBreakPoints(String pack, boolean onlyValid) {
+ return getDebugHandler().getBreakPoints(pack, onlyValid);
+ }
+
+ public static DebuggerHandler getDebugHandler() {
+ return debugHandler;
+ }
+
+ public static void ensureMainFrame() {
+ if (mainFrame == null) {
+ synchronized (Main.class) {
+ if (mainFrame == null) {
+ MainFrame frame;
+ if (Configuration.useRibbonInterface.get()) {
+ frame = new MainFrameRibbon();
+ } else {
+ frame = new MainFrameClassic();
+ }
+ frame.getPanel().setErrorState(ErrorLogFrame.getInstance().getErrorState());
+ mainFrame = frame;
+ }
+ }
+ }
+ }
+
+ public static MainFrame getMainFrame() {
+ return mainFrame;
+ }
+
+ public static void loadFromCache() {
+ if (loadFromCacheFrame == null) {
+ loadFromCacheFrame = new LoadFromCacheFrame();
+ }
+ loadFromCacheFrame.setVisible(true);
+ }
+
+ public static void loadFromMemory() {
+ if (loadFromMemoryFrame == null) {
+ loadFromMemoryFrame = new LoadFromMemoryFrame(mainFrame);
+ }
+ loadFromMemoryFrame.setVisible(true);
+ }
+
+ public static void setVariable(long parentId, String varName, int valueType, Object value) {
+ getDebugHandler().setVariable(parentId, varName, valueType, value);
+ }
+
+ public static void setSubLimiter(boolean value) {
+ if (value) {
+ AVM2Code.toSourceLimit = Configuration.sublimiter.get();
+ } else {
+ AVM2Code.toSourceLimit = -1;
+ }
+ }
+
+ public synchronized static boolean isInited() {
+ return inited;
+ }
+
+ public synchronized static void setSessionLoaded(boolean v) {
+ inited = v;
+ }
+
+ public static boolean isWorking() {
+ return working;
+ }
+
+ public static void startProxy(int port) {
+ if (proxyFrame == null) {
+ proxyFrame = new ProxyFrame(mainFrame);
+ }
+
+ proxyFrame.setPort(port);
+ addTrayIcon();
+ switchProxy();
+ }
+
+ public static void showProxy() {
+ if (proxyFrame == null) {
+ proxyFrame = new ProxyFrame(mainFrame);
+ }
+ proxyFrame.setVisible(true);
+ proxyFrame.setState(Frame.NORMAL);
+ }
+
+ public static void startWork(String name, CancellableWorker worker) {
+ startWork(name, -1, worker);
+ }
+
+ public static void startWork(final String name, final int percent, final CancellableWorker worker) {
+ working = true;
+ View.execInEventDispatchLater(() -> {
+ if (mainFrame != null) {
+ mainFrame.getPanel().setWorkStatus(name, worker);
+ if (percent == -1) {
+ mainFrame.getPanel().hidePercent();
+ } else {
+ mainFrame.getPanel().setPercent(percent);
+ }
+ }
+ if (loadingDialog != null) {
+ loadingDialog.setDetail(name);
+ loadingDialog.setPercent(percent);
+ }
+ if (CommandLineArgumentParser.isCommandLineMode()) {
+ System.out.println(name);
+ }
+ });
+ }
+
+ public static void stopWork() {
+ working = false;
+ View.execInEventDispatchLater(() -> {
+ if (mainFrame != null) {
+ mainFrame.getPanel().setWorkStatus("", null);
+ }
+ if (loadingDialog != null) {
+ loadingDialog.setDetail("");
+ }
+ });
+ }
+
+ public static SWFList parseSWF(SWFSourceInfo sourceInfo) throws Exception {
+ SWFList result = new SWFList();
+
+ InputStream inputStream = sourceInfo.getInputStream();
+ SWFBundle bundle = null;
+ FileInputStream fis = null;
+ if (inputStream == null) {
+ inputStream = new BufferedInputStream(fis = new FileInputStream(sourceInfo.getFile()));
+ bundle = sourceInfo.getBundle(false, SearchMode.ALL);
+ logger.log(Level.INFO, "Load file: {0}", sourceInfo.getFile());
+ } else if (inputStream instanceof SeekableInputStream
+ || inputStream instanceof BufferedInputStream) {
+ try {
+ inputStream.reset();
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, null, ex);
+ }
+ logger.log(Level.INFO, "Load stream: {0}", sourceInfo.getFileTitle());
+ }
+
+ Stopwatch sw = Stopwatch.startNew();
+ if (bundle != null) {
+ result.bundle = bundle;
+ result.name = new File(sourceInfo.getFileTitleOrName()).getName();
+ for (Entry streamEntry : bundle.getAll().entrySet()) {
+ InputStream stream = streamEntry.getValue();
+ stream.reset();
+ CancellableWorker worker = new CancellableWorker() {
+ @Override
+ public SWF doInBackground() throws Exception {
+ final CancellableWorker worker = this;
+ SWF swf = new SWF(stream, null, streamEntry.getKey(), new ProgressListener() {
+ @Override
+ public void progress(int p) {
+ startWork(AppStrings.translate("work.reading.swf"), p, worker);
+ }
+ }, Configuration.parallelSpeedUp.get());
+ return swf;
+ }
+ };
+ loadingDialog.setWroker(worker);
+ worker.execute();
+
+ try {
+ result.add(worker.get());
+ } catch (CancellationException ex) {
+ logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", streamEntry.getKey());
+ }
+ }
+ } else {
+ InputStream fInputStream = inputStream;
+
+ final String[] yesno = new String[]{AppStrings.translate("button.yes"), AppStrings.translate("button.no"), AppStrings.translate("button.yes.all"), AppStrings.translate("button.no.all")};
+
+ CancellableWorker worker = new CancellableWorker() {
+ private boolean yestoall = false;
+
+ private boolean notoall = false;
+
+ private SWF open(InputStream is, String file, String fileTitle) throws IOException, InterruptedException {
+ final CancellableWorker worker = this;
+
+ SWF swf = new SWF(is, file, fileTitle, new ProgressListener() {
+ @Override
+ public void progress(int p) {
+ startWork(AppStrings.translate("work.reading.swf"), p, worker);
+ }
+ }, Configuration.parallelSpeedUp.get(), false, true, new UrlResolver() {
+ @Override
+ public SWF resolveUrl(final String url) {
+ int opt = -1;
+ if (!(yestoall || notoall)) {
+ opt = View.showOptionDialog(null, AppStrings.translate("message.imported.swf").replace("%url%", url), AppStrings.translate("message.warning"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, yesno, AppStrings.translate("button.yes"));
+ if (opt == 2) {
+ yestoall = true;
+ }
+ if (opt == 3) {
+ notoall = true;
+ }
+ }
+
+ if (yestoall) {
+ opt = 0; // yes
+ } else if (notoall) {
+ opt = 1; // no
+ }
+
+ if (opt == 1) //no
+ {
+ return null;
+ }
+
+ if (url.startsWith("http://") || url.startsWith("https://")) {
+ try {
+ URL u = new URL(url);
+ return open(u.openStream(), null, url); //?
+ } catch (Exception ex) {
+ //ignore
+ }
+ } else {
+ File f = new File(new File(file).getParentFile(), url);
+ if (f.exists()) {
+ try {
+ return open(new FileInputStream(f), f.getAbsolutePath(), f.getName());
+ } catch (Exception ex) {
+ //ignore
+ }
+ }
+ }
+ Reference ret = new Reference<>(null);
+ View.execInEventDispatch(new Runnable() {
+ @Override
+ public void run() {
+
+ while (JOptionPane.YES_OPTION == View.showConfirmDialog(null, AppStrings.translate("message.imported.swf.manually").replace("%url%", url), AppStrings.translate("error"), JOptionPane.YES_NO_OPTION, JOptionPane.ERROR_MESSAGE)) {
+
+ JFileChooser fc = new JFileChooser();
+ fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get()));
+ FileFilter allSupportedFilter = new FileFilter() {
+ private final String[] supportedExtensions = new String[]{".swf", ".gfx"};
+
+ @Override
+ public boolean accept(File f) {
+ String name = f.getName().toLowerCase();
+ for (String ext : supportedExtensions) {
+ if (name.endsWith(ext)) {
+ return true;
+ }
+ }
+ return f.isDirectory();
+ }
+
+ @Override
+ public String getDescription() {
+ String exts = Helper.joinStrings(supportedExtensions, "*%s", "; ");
+ return AppStrings.translate("filter.supported") + " (" + exts + ")";
+ }
+ };
+ fc.setFileFilter(allSupportedFilter);
+ FileFilter swfFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.swf");
+ }
+ };
+ fc.addChoosableFileFilter(swfFilter);
+
+ FileFilter gfxFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.gfx");
+ }
+ };
+ fc.addChoosableFileFilter(gfxFilter);
+ fc.setAcceptAllFileFilterUsed(false);
+ JFrame f = new JFrame();
+ View.setWindowIcon(f);
+ int returnVal = fc.showOpenDialog(f);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath());
+ File selFile = Helper.fixDialogFile(fc.getSelectedFile());
+ try {
+ ret.setVal(open(new FileInputStream(selFile), selFile.getAbsolutePath(), selFile.getName()));
+ break;
+ } catch (Exception ex) {
+ //ignore;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+ });
+ return ret.getVal();
+ }
+ });
+ return swf;
+ }
+
+ @Override
+ public SWF doInBackground() throws Exception {
+ return open(fInputStream, sourceInfo.getFile(), sourceInfo.getFileTitle());
+ }
+ };
+ if (loadingDialog != null) {
+ loadingDialog.setWroker(worker);
+ }
+ worker.execute();
+
+ try {
+ result.add(worker.get());
+ } catch (CancellationException ex) {
+ logger.log(Level.WARNING, "Loading SWF {0} was cancelled.", sourceInfo.getFileTitleOrName());
+ }
+ }
+
+ if (fis != null) {
+ logger.log(Level.INFO, "File loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000));
+ fis.close();
+ } else {
+ logger.log(Level.INFO, "Stream loaded in {0} seconds.", (sw.getElapsedMilliseconds() / 1000));
+ }
+
+ result.sourceInfo = sourceInfo;
+ for (SWF swf : result) {
+ logger.log(Level.INFO, "");
+ logger.log(Level.INFO, "== File information ==");
+ logger.log(Level.INFO, "Size: {0}", Helper.formatFileSize(swf.fileSize));
+ logger.log(Level.INFO, "Flash version: {0}", swf.version);
+ int width = (int) ((swf.displayRect.Xmax - swf.displayRect.Xmin) / SWF.unitDivisor);
+ int height = (int) ((swf.displayRect.Ymax - swf.displayRect.Ymin) / SWF.unitDivisor);
+ logger.log(Level.INFO, "Width: {0}", width);
+ logger.log(Level.INFO, "Height: {0}", height);
+
+ swf.swfList = result;
+ swf.addEventListener(new EventListener() {
+ @Override
+ public void handleExportingEvent(String type, int index, int count, Object data) {
+ String text = AppStrings.translate("work.exporting");
+ if (type != null && type.length() > 0) {
+ text += " " + type;
+ }
+
+ startWork(text + " " + index + "/" + count + " " + data, null);
+ }
+
+ @Override
+ public void handleExportedEvent(String type, int index, int count, Object data) {
+ String text = AppStrings.translate("work.exported");
+ if (type != null && type.length() > 0) {
+ text += " " + type;
+ }
+
+ startWork(text + " " + index + "/" + count + " " + data, null);
+ }
+
+ @Override
+ public void handleEvent(String event, Object data) {
+ if (event.equals("exporting") || event.equals("exported")) {
+ throw new Error("Event is not supported by this handler.");
+ }
+ if (event.equals("getVariables")) {
+ startWork(AppStrings.translate("work.gettingvariables") + "..." + (String) data, null);
+ }
+ if (event.equals("deobfuscate")) {
+ startWork(AppStrings.translate("work.deobfuscating") + "..." + (String) data, null);
+ }
+ if (event.equals("rename")) {
+ startWork(AppStrings.translate("work.renaming") + "..." + (String) data, null);
+ }
+ }
+ });
+ }
+
+ return result;
+ }
+
+ public static void saveFile(SWF swf, String outfile) throws IOException {
+ saveFile(swf, outfile, SaveFileMode.SAVE, null);
+ }
+
+ public static void saveFile(SWF swf, String outfile, SaveFileMode mode, ExeExportMode exeExportMode) throws IOException {
+ if (mode == SaveFileMode.SAVEAS && !swf.swfList.isBundle()) {
+ swf.setFile(outfile);
+ swf.swfList.sourceInfo.setFile(outfile);
+ }
+ File outfileF = new File(outfile);
+ File tmpFile = new File(outfile + ".tmp");
+ try (FileOutputStream fos = new FileOutputStream(tmpFile);
+ BufferedOutputStream bos = new BufferedOutputStream(fos)) {
+ if (mode == SaveFileMode.EXE) {
+ switch (exeExportMode) {
+ case WRAPPER:
+ InputStream exeStream = View.class.getClassLoader().getResourceAsStream("com/jpexs/helpers/resource/Swf2Exe.bin");
+ Helper.copyStream(exeStream, bos);
+ int width = swf.displayRect.Xmax - swf.displayRect.Xmin;
+ int height = swf.displayRect.Ymax - swf.displayRect.Ymin;
+ bos.write(width & 0xff);
+ bos.write((width >> 8) & 0xff);
+ bos.write((width >> 16) & 0xff);
+ bos.write((width >> 24) & 0xff);
+ bos.write(height & 0xff);
+ bos.write((height >> 8) & 0xff);
+ bos.write((height >> 16) & 0xff);
+ bos.write((height >> 24) & 0xff);
+ bos.write(Configuration.saveAsExeScaleMode.get());
+ break;
+ case PROJECTOR_WIN:
+ case PROJECTOR_MAC:
+ case PROJECTOR_LINUX:
+ File projectorFile = Configuration.getProjectorFile(exeExportMode);
+ if (projectorFile == null) {
+ String message = "Projector not found, please place it to " + Configuration.getProjectorPath();
+ logger.log(Level.SEVERE, message);
+ throw new IOException(message);
+ }
+ Helper.copyStream(new FileInputStream(projectorFile), bos);
+ bos.flush();
+ break;
+ }
+ }
+
+ long pos = fos.getChannel().position();
+ swf.saveTo(bos);
+
+ if (mode == SaveFileMode.EXE) {
+ switch (exeExportMode) {
+ case PROJECTOR_WIN:
+ case PROJECTOR_MAC:
+ case PROJECTOR_LINUX:
+ bos.flush();
+ int swfSize = (int) (fos.getChannel().position() - pos);
+
+ // write magic number
+ bos.write(0x56);
+ bos.write(0x34);
+ bos.write(0x12);
+ bos.write(0xfa);
+
+ bos.write(swfSize & 0xff);
+ bos.write((swfSize >> 8) & 0xff);
+ bos.write((swfSize >> 16) & 0xff);
+ bos.write((swfSize >> 24) & 0xff);
+ }
+ }
+ }
+ if (tmpFile.exists()) {
+ if (tmpFile.length() > 0) {
+ outfileF.delete();
+ if (!tmpFile.renameTo(outfileF)) {
+ tmpFile.delete();
+ throw new IOException("Cannot access " + outfile);
+ }
+ } else {
+ throw new IOException("Output is empty");
+ }
+ } else {
+ throw new IOException("Output not found");
+ }
+ }
+
+ private static class OpenFileWorker extends SwingWorker {
+
+ private final SWFSourceInfo[] sourceInfos;
+
+ private final Runnable executeAfterOpen;
+
+ private final int[] reloadIndices;
+
+ public OpenFileWorker(SWFSourceInfo sourceInfo) {
+ this(sourceInfo, -1);
+ }
+
+ public OpenFileWorker(SWFSourceInfo sourceInfo, int reloadIndex) {
+ this(sourceInfo, null, reloadIndex);
+ }
+
+ public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) {
+ this(sourceInfo, executeAfterOpen, -1);
+ }
+
+ public OpenFileWorker(SWFSourceInfo sourceInfo, Runnable executeAfterOpen, int reloadIndex) {
+ this.sourceInfos = new SWFSourceInfo[]{sourceInfo};
+ this.executeAfterOpen = executeAfterOpen;
+ this.reloadIndices = new int[]{reloadIndex};
+ }
+
+ public OpenFileWorker(SWFSourceInfo[] sourceInfos) {
+ this(sourceInfos, null, null);
+ }
+
+ public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen) {
+ this(sourceInfos, executeAfterOpen, null);
+ }
+
+ public OpenFileWorker(SWFSourceInfo[] sourceInfos, Runnable executeAfterOpen, int[] reloadIndices) {
+ this.sourceInfos = sourceInfos;
+ this.executeAfterOpen = executeAfterOpen;
+ int[] indices = new int[sourceInfos.length];
+ for (int i = 0; i < indices.length; i++) {
+ indices[i] = -1;
+ }
+ this.reloadIndices = reloadIndices == null ? indices : reloadIndices;
+ }
+
+ @Override
+ protected Object doInBackground() throws Exception {
+ boolean first = true;
+ SWF firstSWF = null;
+ for (int index = 0; index < sourceInfos.length; index++) {
+ SWFSourceInfo sourceInfo = sourceInfos[index];
+ SWFList swfs = null;
+ try {
+ Main.startWork(AppStrings.translate("work.reading.swf") + "...", null);
+ try {
+ swfs = parseSWF(sourceInfo);
+ } catch (ExecutionException ex) {
+ Throwable cause = ex.getCause();
+ if (cause instanceof SwfOpenException) {
+ throw (SwfOpenException) cause;
+ }
+
+ throw ex;
+ }
+ } catch (OutOfMemoryError ex) {
+ logger.log(Level.SEVERE, null, ex);
+ View.showMessageDialog(null, "Cannot load SWF file. Out of memory.");
+ continue;
+ } catch (SwfOpenException ex) {
+ logger.log(Level.SEVERE, null, ex);
+ View.showMessageDialog(null, ex.getMessage());
+ continue;
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, null, ex);
+ View.showMessageDialog(null, "Cannot load SWF file.");
+ continue;
+ }
+
+ final SWFList swfs1 = swfs;
+ final boolean first1 = first;
+ first = false;
+ if (firstSWF == null && swfs1.size() > 0) {
+ firstSWF = swfs1.get(0);
+ }
+
+ final int findex = index;
+ try {
+ View.execInEventDispatch(() -> {
+ Main.startWork(AppStrings.translate("work.creatingwindow") + "...", null);
+ ensureMainFrame();
+ if (reloadIndices[findex] > -1) {
+ mainFrame.getPanel().loadSwfAtPos(swfs1, reloadIndices[findex]);
+ } else {
+ mainFrame.getPanel().load(swfs1, first1);
+ }
+ });
+ } catch (Exception ex) {
+ logger.log(Level.SEVERE, null, ex);
+ }
+ }
+
+ loadingDialog.setVisible(false);
+ shouldCloseWhenClosingLoadingDialog = false;
+
+ final SWF fswf = firstSWF;
+ View.execInEventDispatch(() -> {
+ if (mainFrame != null) {
+ mainFrame.setVisible(true);
+ }
+
+ Main.stopWork();
+
+ if (mainFrame != null && Configuration.gotoMainClassOnStartup.get()) {
+ mainFrame.getPanel().gotoDocumentClass(fswf);
+ }
+
+ if (mainFrame != null && fswf != null) {
+ SwfSpecificConfiguration swfConf = Configuration.getSwfSpecificConfiguration(fswf.getShortFileName());
+ if (swfConf != null) {
+ String pathStr = swfConf.lastSelectedPath;
+ mainFrame.getPanel().tagTree.setSelectionPathString(pathStr);
+ }
+ }
+
+ if (executeAfterOpen != null) {
+ executeAfterOpen.run();
+ }
+ });
+
+ return true;
+ }
+ }
+
+ public static boolean reloadSWFs() {
+ CancellableWorker.cancelBackgroundThreads();
+ if (Main.sourceInfos.isEmpty()) {
+ Helper.freeMem();
+ showModeFrame();
+ return true;
+ } else {
+ SWFSourceInfo[] sourceInfosCopy = new SWFSourceInfo[sourceInfos.size()];
+ sourceInfos.toArray(sourceInfosCopy);
+ sourceInfos.clear();
+ openFile(sourceInfosCopy);
+ return true;
+ }
+ }
+
+ public static void reloadApp() {
+ if (debugDialog != null) {
+ debugDialog.setVisible(false);
+ debugDialog.dispose();
+ debugDialog = null;
+ }
+ if (loadingDialog != null) {
+ synchronized (Main.class) {
+ if (loadingDialog != null) {
+ loadingDialog.setVisible(false);
+ loadingDialog.dispose();
+ loadingDialog = null;
+ }
+ }
+ }
+ if (proxyFrame != null) {
+ proxyFrame.setVisible(false);
+ proxyFrame.dispose();
+ proxyFrame = null;
+ }
+ if (loadFromMemoryFrame != null) {
+ loadFromMemoryFrame.setVisible(false);
+ loadFromMemoryFrame.dispose();
+ loadFromMemoryFrame = null;
+ }
+ if (loadFromCacheFrame != null) {
+ loadFromCacheFrame.setVisible(false);
+ loadFromCacheFrame.dispose();
+ loadFromCacheFrame = null;
+ }
+ if (mainFrame != null) {
+ mainFrame.setVisible(false);
+ mainFrame.getPanel().closeAll(false);
+ mainFrame.dispose();
+ mainFrame = null;
+ }
+ FontTag.reload();
+ Cache.clearAll();
+ initGui();
+ reloadSWFs();
+ }
+
+ public static OpenFileResult openFile(String swfFile, String fileTitle) {
+ View.checkAccess();
+
+ return openFile(swfFile, fileTitle, null);
+ }
+
+ public static OpenFileResult openFile(String swfFile, String fileTitle, Runnable executeAfterOpen) {
+ View.checkAccess();
+
+ try {
+ File file = new File(swfFile);
+ if (!file.exists()) {
+ View.showMessageDialog(null, AppStrings.translate("open.error.fileNotFound"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE);
+ return OpenFileResult.NOT_FOUND;
+ }
+ swfFile = file.getCanonicalPath();
+ SWFSourceInfo sourceInfo = new SWFSourceInfo(null, swfFile, fileTitle);
+ OpenFileResult openResult = openFile(sourceInfo);
+ return openResult;
+ } catch (IOException ex) {
+ View.showMessageDialog(null, AppStrings.translate("open.error.cannotOpen"), AppStrings.translate("open.error"), JOptionPane.ERROR_MESSAGE);
+ return OpenFileResult.ERROR;
+ }
+ }
+
+ public static OpenFileResult openFile(SWFSourceInfo sourceInfo) {
+ View.checkAccess();
+
+ return openFile(new SWFSourceInfo[]{sourceInfo});
+ }
+
+ public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen) {
+ View.checkAccess();
+
+ return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen);
+ }
+
+ public static OpenFileResult openFile(SWFSourceInfo sourceInfo, Runnable executeAfterOpen, int reloadIndex) {
+ View.checkAccess();
+
+ return openFile(new SWFSourceInfo[]{sourceInfo}, executeAfterOpen, new int[]{reloadIndex});
+ }
+
+ public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos) {
+ View.checkAccess();
+
+ return openFile(newSourceInfos, null);
+ }
+
+ public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen) {
+ View.checkAccess();
+
+ return openFile(newSourceInfos, executeAfterOpen, null);
+ }
+
+ public static OpenFileResult openFile(SWFSourceInfo[] newSourceInfos, Runnable executeAfterOpen, int[] reloadIndices) {
+ View.checkAccess();
+
+ if (mainFrame != null && !Configuration.openMultipleFiles.get()) {
+ sourceInfos.clear();
+ mainFrame.getPanel().closeAll(false);
+ mainFrame.setVisible(false);
+ Helper.freeMem();
+ reloadIndices = null;
+ }
+
+ loadingDialog.setVisible(true);
+
+ for (int i = 0; i < newSourceInfos.length; i++) {
+ SWFSourceInfo si = newSourceInfos[i];
+ String fileName = si.getFile();
+ if (fileName != null) {
+ Configuration.addRecentFile(fileName);
+ }
+ }
+
+ OpenFileWorker wrk = new OpenFileWorker(newSourceInfos, executeAfterOpen, reloadIndices);
+ wrk.execute();
+ if (reloadIndices == null) {
+ sourceInfos.addAll(Arrays.asList(newSourceInfos));
+ } else {
+ for (int i = 0; i < reloadIndices.length; i++) {
+ sourceInfos.set(reloadIndices[i], newSourceInfos[i]);
+ }
+ }
+ return OpenFileResult.OK;
+ }
+
+ public static void closeFile(SWFList swf) {
+ View.checkAccess();
+
+ sourceInfos.remove(swf.sourceInfo);
+ mainFrame.getPanel().close(swf);
+ }
+
+ public static void reloadFile(SWFList swf) {
+ View.checkAccess();
+
+ openFile(swf.sourceInfo, null, sourceInfos.indexOf(swf.sourceInfo));
+ }
+
+ public static boolean closeAll() {
+ View.checkAccess();
+
+ boolean closeResult = mainFrame.getPanel().closeAll(true);
+ if (closeResult) {
+ sourceInfos.clear();
+ }
+
+ return closeResult;
+ }
+
+ public static boolean saveFileDialog(SWF swf, final SaveFileMode mode) {
+ JFileChooser fc = new JFileChooser();
+ fc.setCurrentDirectory(new File(Configuration.lastSaveDir.get()));
+ String ext = ".swf";
+ switch (mode) {
+ case SAVE:
+ case SAVEAS:
+ if (swf.getFile() != null) {
+ ext = Path.getExtension(swf.getFile());
+ }
+ break;
+ case EXE:
+ ext = ".exe";
+ break;
+ }
+
+ FileFilter swfFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.swf");
+ }
+ };
+
+ FileFilter gfxFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.gfx");
+ }
+ };
+
+ ExeExportMode exeExportMode = null;
+ if (mode == SaveFileMode.EXE) {
+ exeExportMode = Configuration.exeExportMode.get();
+ if (exeExportMode == null) {
+ exeExportMode = ExeExportMode.WRAPPER;
+ }
+ String filterDescription = null;
+ switch (exeExportMode) {
+ case WRAPPER:
+ case PROJECTOR_WIN:
+ ext = ".exe";
+ filterDescription = "filter.exe";
+ break;
+ case PROJECTOR_MAC:
+ ext = ".dmg";
+ filterDescription = "filter.dmg";
+ break;
+ case PROJECTOR_LINUX:
+ // linux projector is compressed with tar.gz
+ // todo: decompress
+ ext = "";
+ filterDescription = "filter.linuxExe";
+ break;
+ }
+
+ String fext = ext;
+ String ffilterDescription = filterDescription;
+ FileFilter exeFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(fext)) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate(ffilterDescription);
+ }
+ };
+ fc.setFileFilter(exeFilter);
+ } else if (swf.gfx) {
+ fc.addChoosableFileFilter(swfFilter);
+ fc.setFileFilter(gfxFilter);
+ } else {
+ fc.setFileFilter(swfFilter);
+ fc.addChoosableFileFilter(gfxFilter);
+ }
+ final String extension = ext;
+ fc.setAcceptAllFileFilterUsed(false);
+ JFrame f = new JFrame();
+ View.setWindowIcon(f);
+ if (fc.showSaveDialog(f) == JFileChooser.APPROVE_OPTION) {
+ File file = Helper.fixDialogFile(fc.getSelectedFile());
+ FileFilter selFilter = fc.getFileFilter();
+ try {
+ String fileName = file.getAbsolutePath();
+ if (selFilter == swfFilter) {
+ if (!fileName.toLowerCase().endsWith(extension)) {
+ fileName += extension;
+ }
+ swf.gfx = false;
+ }
+ if (selFilter == gfxFilter) {
+ if (!fileName.toLowerCase().endsWith(".gfx")) {
+ fileName += ".gfx";
+ }
+ swf.gfx = true;
+ }
+ Main.saveFile(swf, fileName, mode, exeExportMode);
+ Configuration.lastSaveDir.set(file.getParentFile().getAbsolutePath());
+ return true;
+ } catch (IOException ex) {
+ View.showMessageDialog(null, AppStrings.translate("error.file.write"));
+ }
+ }
+ return false;
+ }
+
+ public static boolean openFileDialog() {
+ View.checkAccess();
+
+ JFileChooser fc = new JFileChooser();
+ if (Configuration.openMultipleFiles.get()) {
+ fc.setMultiSelectionEnabled(true);
+ }
+ fc.setCurrentDirectory(new File(Configuration.lastOpenDir.get()));
+ FileFilter allSupportedFilter = new FileFilter() {
+ private final String[] supportedExtensions = new String[]{".swf", ".gfx", ".swc", ".zip", ".iggy"};
+
+ @Override
+ public boolean accept(File f) {
+ String name = f.getName().toLowerCase();
+ for (String ext : supportedExtensions) {
+ if (name.endsWith(ext)) {
+ return true;
+ }
+ }
+ return f.isDirectory();
+ }
+
+ @Override
+ public String getDescription() {
+ String exts = Helper.joinStrings(supportedExtensions, "*%s", "; ");
+ return AppStrings.translate("filter.supported") + " (" + exts + ")";
+ }
+ };
+ fc.setFileFilter(allSupportedFilter);
+ FileFilter swfFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".swf")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.swf");
+ }
+ };
+ fc.addChoosableFileFilter(swfFilter);
+
+ FileFilter swcFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".swc")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.swc");
+ }
+ };
+ fc.addChoosableFileFilter(swcFilter);
+
+ FileFilter gfxFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".gfx")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.gfx");
+ }
+ };
+ fc.addChoosableFileFilter(gfxFilter);
+
+ FileFilter iggyFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".iggy")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.iggy");
+ }
+ };
+ fc.addChoosableFileFilter(iggyFilter);
+
+ FileFilter zipFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return (f.getName().toLowerCase().endsWith(".zip")) || (f.isDirectory());
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.zip");
+ }
+ };
+ fc.addChoosableFileFilter(zipFilter);
+
+ FileFilter binaryFilter = new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return true;
+ }
+
+ @Override
+ public String getDescription() {
+ return AppStrings.translate("filter.binary");
+ }
+ };
+ fc.addChoosableFileFilter(binaryFilter);
+
+ fc.setAcceptAllFileFilterUsed(false);
+ JFrame f = new JFrame();
+ View.setWindowIcon(f);
+ int returnVal = fc.showOpenDialog(f);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ Configuration.lastOpenDir.set(Helper.fixDialogFile(fc.getSelectedFile()).getParentFile().getAbsolutePath());
+ File[] selFiles = fc.getSelectedFiles();
+ for (File file : selFiles) {
+ File selfile = Helper.fixDialogFile(file);
+ Main.openFile(selfile.getAbsolutePath(), null);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static void displayErrorFrame() {
+ ErrorLogFrame.getInstance().setVisible(true);
+ }
+
+ private static String md5(byte data[]) {
+ try {
+ java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
+ byte[] array = md.digest(data);
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < array.length; ++i) {
+ sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).substring(1, 3));
+ }
+ return sb.toString();
+ } catch (java.security.NoSuchAlgorithmException e) {
+ }
+ return null;
+ }
+
+ private static void initGui() {
+ if (GraphicsEnvironment.isHeadless()) {
+ System.err.println("Error: Your system does not support Graphic User Interface");
+ exit();
+ }
+
+ System.setProperty("sun.java2d.d3d", "false");
+ System.setProperty("sun.java2d.noddraw", "true");
+
+ if (Configuration.hwAcceleratedGraphics.get()) {
+ System.setProperty("sun.java2d.opengl", Configuration._debugMode.get() ? "True" : "true");
+ } else {
+ System.setProperty("sun.java2d.opengl", "false");
+ }
+
+ initUiLang();
+
+ if (Configuration.useRibbonInterface.get()) {
+ View.setLookAndFeel();
+ } else {
+ try {
+ UIManager.put(SubstanceLookAndFeel.COLORIZATION_FACTOR, null);
+ UIManager.put("Tree.expandedIcon", null);
+ UIManager.put("Tree.collapsedIcon", null);
+ UIManager.put("ColorChooserUI", null);
+ UIManager.put("ColorChooser.swatchesRecentSwatchSize", null);
+ UIManager.put("ColorChooser.swatchesSwatchSize", null);
+ UIManager.put("RibbonApplicationMenuPopupPanelUI", null);
+ UIManager.put("RibbonApplicationMenuButtonUI", null);
+ UIManager.put("ProgressBarUI", null);
+ UIManager.put("TextField.background", null);
+ UIManager.put("FormattedTextField.background", null);
+ UIManager.put("CommandButtonUI", null);
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
+ logger.log(Level.SEVERE, null, ex);
+ }
+ }
+
+ View.execInEventDispatch(() -> {
+ ErrorLogFrame.createNewInstance();
+
+ autoCheckForUpdates();
+ offerAssociation();
+ loadingDialog = new LoadingDialog();
+
+ DebuggerTools.initDebugger().addMessageListener(new DebugListener() {
+ @Override
+ public void onMessage(String clientId, String msg) {
+ }
+
+ @Override
+ public void onLoaderURL(String clientId, String url) {
+ }
+
+ @Override
+ public void onLoaderBytes(String clientId, byte[] data) {
+ String hash = md5(data);
+ for (SWFList sl : Main.getMainFrame().getPanel().getSwfs()) {
+ for (int s = 0; s < sl.size(); s++) {
+ String t = sl.get(s).getFileTitle();
+ if (t == null) {
+ t = "";
+ }
+ if (t.endsWith(":" + hash)) { //this one is already opened
+ return;
+ }
+ }
+ }
+ SWF swf = Main.getMainFrame().getPanel().getCurrentSwf();
+
+ String title = swf == null ? "?" : swf.getFileTitle();
+ final String titleWithHash = title + ":" + hash;
+ try {
+ final String tfile = tempFile(titleWithHash);
+ Helper.writeFile(tfile, data);
+ View.execInEventDispatch(new Runnable() {
+ @Override
+ public void run() {
+ openFile(new SWFSourceInfo(null, tfile, titleWithHash));
+ }
+ });
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, "Cannot create tempfile");
+ }
+ }
+
+ @Override
+ public void onFinish(String clientId) {
+ }
+ });
+
+ try {
+ flashDebugger = new Debugger();
+ debugHandler = new DebuggerHandler();
+ debugHandler.addBreakListener(new DebuggerHandler.BreakListener() {
+ @Override
+ public void doContinue() {
+ mainFrame.getPanel().clearDebuggerColors();
+ }
+
+ @Override
+ public void breakAt(String scriptName, int line, final int classIndex, final int traitIndex, final int methodIndex) {
+ View.execInEventDispatch(new Runnable() {
+ @Override
+ public void run() {
+ mainFrame.getPanel().gotoScriptLine(getMainFrame().getPanel().getCurrentSwf(), scriptName, line, classIndex, traitIndex, methodIndex);
+ }
+ });
+ }
+ });
+ debugHandler.addConnectionListener(new DebuggerHandler.ConnectionListener() {
+ @Override
+ public void connected() {
+ Main.mainFrame.getMenu().updateComponents();
+ }
+
+ @Override
+ public void disconnected() {
+ if (Main.mainFrame != null && Main.mainFrame.getPanel() != null) {
+ Main.mainFrame.getPanel().refreshBreakPoints();
+ }
+ }
+ });
+ flashDebugger.addConnectionListener(debugHandler);
+ } catch (IOException ex) {
+ logger.log(Level.SEVERE, "eeex", ex);
+ }
+ });
+ }
+
+ public static void startDebugger() {
+ flashDebugger.startDebugger();
+ }
+
+ public static void stopDebugger() {
+ flashDebugger.stopDebugger();
+ }
+
+ public static void showModeFrame() {
+ ensureMainFrame();
+ mainFrame.setVisible(true);
+ }
+
+ private static void offerAssociation() {
+ boolean offered = Configuration.offeredAssociation.get();
+ if (!offered) {
+ if (Platform.isWindows()) {
+ if ((!ContextMenuTools.isAddedToContextMenu()) && View.showConfirmDialog(null, "Do you want to add FFDec to context menu of SWF files?\n(Can be changed later from main menu)", "Context menu", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
+ ContextMenuTools.addToContextMenu(true, false);
+ }
+ }
+
+ Configuration.offeredAssociation.set(true);
+ }
+ }
+
+ public static void initUiLang() {
+ if (GraphicsEnvironment.isHeadless()) { //No GUI in OS
+ return;
+ }
+ try {
+ Class> cl = Class.forName("org.pushingpixels.substance.api.SubstanceLookAndFeel");
+ Field field = cl.getDeclaredField("LABEL_BUNDLE");
+ field.setAccessible(true);
+ field.set(null, null);
+ } catch (Throwable ex) {
+ logger.log(Level.SEVERE, null, ex);
+ }
+
+ UIManager.put("OptionPane.okButtonText", AppStrings.translate("button.ok"));
+ UIManager.put("OptionPane.yesButtonText", AppStrings.translate("button.yes"));
+ UIManager.put("OptionPane.noButtonText", AppStrings.translate("button.no"));
+ UIManager.put("OptionPane.cancelButtonText", AppStrings.translate("button.cancel"));
+ UIManager.put("OptionPane.messageDialogTitle", AppStrings.translate("dialog.message.title"));
+ UIManager.put("OptionPane.titleText", AppStrings.translate("dialog.select.title"));
+
+ UIManager.put("FileChooser.acceptAllFileFilterText", AppStrings.translate("FileChooser.acceptAllFileFilterText"));
+ UIManager.put("FileChooser.lookInLabelText", AppStrings.translate("FileChooser.lookInLabelText"));
+ UIManager.put("FileChooser.cancelButtonText", AppStrings.translate("button.cancel"));
+ UIManager.put("FileChooser.cancelButtonToolTipText", AppStrings.translate("button.cancel"));
+ UIManager.put("FileChooser.openButtonText", AppStrings.translate("FileChooser.openButtonText"));
+ UIManager.put("FileChooser.openButtonToolTipText", AppStrings.translate("FileChooser.openButtonToolTipText"));
+ UIManager.put("FileChooser.filesOfTypeLabelText", AppStrings.translate("FileChooser.filesOfTypeLabelText"));
+ UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText"));
+ UIManager.put("FileChooser.listViewButtonToolTipText", AppStrings.translate("FileChooser.listViewButtonToolTipText"));
+ UIManager.put("FileChooser.listViewButtonAccessibleName", AppStrings.translate("FileChooser.listViewButtonAccessibleName"));
+ UIManager.put("FileChooser.detailsViewButtonToolTipText", AppStrings.translate("FileChooser.detailsViewButtonToolTipText"));
+ UIManager.put("FileChooser.detailsViewButtonAccessibleName", AppStrings.translate("FileChooser.detailsViewButtonAccessibleName"));
+ UIManager.put("FileChooser.upFolderToolTipText", AppStrings.translate("FileChooser.upFolderToolTipText"));
+ UIManager.put("FileChooser.upFolderAccessibleName", AppStrings.translate("FileChooser.upFolderAccessibleName"));
+ UIManager.put("FileChooser.homeFolderToolTipText", AppStrings.translate("FileChooser.homeFolderToolTipText"));
+ UIManager.put("FileChooser.homeFolderAccessibleName", AppStrings.translate("FileChooser.homeFolderAccessibleName"));
+ UIManager.put("FileChooser.fileNameHeaderText", AppStrings.translate("FileChooser.fileNameHeaderText"));
+ UIManager.put("FileChooser.fileSizeHeaderText", AppStrings.translate("FileChooser.fileSizeHeaderText"));
+ UIManager.put("FileChooser.fileTypeHeaderText", AppStrings.translate("FileChooser.fileTypeHeaderText"));
+ UIManager.put("FileChooser.fileDateHeaderText", AppStrings.translate("FileChooser.fileDateHeaderText"));
+ UIManager.put("FileChooser.fileAttrHeaderText", AppStrings.translate("FileChooser.fileAttrHeaderText"));
+ UIManager.put("FileChooser.openDialogTitleText", AppStrings.translate("FileChooser.openDialogTitleText"));
+ UIManager.put("FileChooser.directoryDescriptionText", AppStrings.translate("FileChooser.directoryDescriptionText"));
+ UIManager.put("FileChooser.directoryOpenButtonText", AppStrings.translate("FileChooser.directoryOpenButtonText"));
+ UIManager.put("FileChooser.directoryOpenButtonToolTipText", AppStrings.translate("FileChooser.directoryOpenButtonToolTipText"));
+ UIManager.put("FileChooser.fileDescriptionText", AppStrings.translate("FileChooser.fileDescriptionText"));
+ UIManager.put("FileChooser.fileNameLabelText", AppStrings.translate("FileChooser.fileNameLabelText"));
+ UIManager.put("FileChooser.helpButtonText", AppStrings.translate("FileChooser.helpButtonText"));
+ UIManager.put("FileChooser.helpButtonToolTipText", AppStrings.translate("FileChooser.helpButtonToolTipText"));
+ UIManager.put("FileChooser.newFolderAccessibleName", AppStrings.translate("FileChooser.newFolderAccessibleName"));
+ UIManager.put("FileChooser.newFolderErrorText", AppStrings.translate("FileChooser.newFolderErrorText"));
+ UIManager.put("FileChooser.newFolderToolTipText", AppStrings.translate("FileChooser.newFolderToolTipText"));
+ UIManager.put("FileChooser.other.newFolder", AppStrings.translate("FileChooser.other.newFolder"));
+ UIManager.put("FileChooser.other.newFolder.subsequent", AppStrings.translate("FileChooser.other.newFolder.subsequent"));
+ UIManager.put("FileChooser.win32.newFolder", AppStrings.translate("FileChooser.win32.newFolder"));
+ UIManager.put("FileChooser.win32.newFolder.subsequent", AppStrings.translate("FileChooser.win32.newFolder.subsequent"));
+ UIManager.put("FileChooser.saveButtonText", AppStrings.translate("FileChooser.saveButtonText"));
+ UIManager.put("FileChooser.saveButtonToolTipText", AppStrings.translate("FileChooser.saveButtonToolTipText"));
+ UIManager.put("FileChooser.saveDialogTitleText", AppStrings.translate("FileChooser.saveDialogTitleText"));
+ UIManager.put("FileChooser.saveInLabelText", AppStrings.translate("FileChooser.saveInLabelText"));
+ UIManager.put("FileChooser.updateButtonText", AppStrings.translate("FileChooser.updateButtonText"));
+ UIManager.put("FileChooser.updateButtonToolTipText", AppStrings.translate("FileChooser.updateButtonToolTipText"));
+
+ UIManager.put("FileChooser.detailsViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewActionLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.detailsViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.detailsViewButtonToolTip.textAndMnemonic"));
+ UIManager.put("FileChooser.fileAttrHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileAttrHeader.textAndMnemonic"));
+ UIManager.put("FileChooser.fileDateHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileDateHeader.textAndMnemonic"));
+ UIManager.put("FileChooser.fileNameHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileNameHeader.textAndMnemonic"));
+ UIManager.put("FileChooser.fileNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.fileNameLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.fileSizeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileSizeHeader.textAndMnemonic"));
+ UIManager.put("FileChooser.fileTypeHeader.textAndMnemonic", AppStrings.translate("FileChooser.fileTypeHeader.textAndMnemonic"));
+ UIManager.put("FileChooser.filesOfTypeLabel.textAndMnemonic", AppStrings.translate("FileChooser.filesOfTypeLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.folderNameLabel.textAndMnemonic", AppStrings.translate("FileChooser.folderNameLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.homeFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.homeFolderToolTip.textAndMnemonic"));
+ UIManager.put("FileChooser.listViewActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.listViewActionLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.listViewButtonToolTip.textAndMnemonic", AppStrings.translate("FileChooser.listViewButtonToolTip.textAndMnemonic"));
+ UIManager.put("FileChooser.lookInLabel.textAndMnemonic", AppStrings.translate("FileChooser.lookInLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.newFolderActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.newFolderActionLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.newFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.newFolderToolTip.textAndMnemonic"));
+ UIManager.put("FileChooser.refreshActionLabel.textAndMnemonic", AppStrings.translate("FileChooser.refreshActionLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.saveInLabel.textAndMnemonic", AppStrings.translate("FileChooser.saveInLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.upFolderToolTip.textAndMnemonic", AppStrings.translate("FileChooser.upFolderToolTip.textAndMnemonic"));
+ UIManager.put("FileChooser.viewMenuButtonAccessibleName", AppStrings.translate("FileChooser.viewMenuButtonAccessibleName"));
+ UIManager.put("FileChooser.viewMenuButtonToolTipText", AppStrings.translate("FileChooser.viewMenuButtonToolTipText"));
+ UIManager.put("FileChooser.viewMenuLabel.textAndMnemonic", AppStrings.translate("FileChooser.viewMenuLabel.textAndMnemonic"));
+ UIManager.put("FileChooser.newFolderActionLabelText", AppStrings.translate("FileChooser.newFolderActionLabelText"));
+ UIManager.put("FileChooser.listViewActionLabelText", AppStrings.translate("FileChooser.listViewActionLabelText"));
+ UIManager.put("FileChooser.detailsViewActionLabelText", AppStrings.translate("FileChooser.detailsViewActionLabelText"));
+ UIManager.put("FileChooser.refreshActionLabelText", AppStrings.translate("FileChooser.refreshActionLabelText"));
+ UIManager.put("FileChooser.sortMenuLabelText", AppStrings.translate("FileChooser.sortMenuLabelText"));
+ UIManager.put("FileChooser.viewMenuLabelText", AppStrings.translate("FileChooser.viewMenuLabelText"));
+ UIManager.put("FileChooser.fileSizeKiloBytes", AppStrings.translate("FileChooser.fileSizeKiloBytes"));
+ UIManager.put("FileChooser.fileSizeMegaBytes", AppStrings.translate("FileChooser.fileSizeMegaBytes"));
+ UIManager.put("FileChooser.fileSizeGigaBytes", AppStrings.translate("FileChooser.fileSizeGigaBytes"));
+ UIManager.put("FileChooser.folderNameLabelText", AppStrings.translate("FileChooser.folderNameLabelText"));
+
+ UIManager.put("ColorChooser.okText", AppStrings.translate("ColorChooser.okText"));
+ UIManager.put("ColorChooser.cancelText", AppStrings.translate("ColorChooser.cancelText"));
+ UIManager.put("ColorChooser.resetText", AppStrings.translate("ColorChooser.resetText"));
+ UIManager.put("ColorChooser.previewText", AppStrings.translate("ColorChooser.previewText"));
+ UIManager.put("ColorChooser.swatchesNameText", AppStrings.translate("ColorChooser.swatchesNameText"));
+ UIManager.put("ColorChooser.swatchesRecentText", AppStrings.translate("ColorChooser.swatchesRecentText"));
+ UIManager.put("ColorChooser.sampleText", AppStrings.translate("ColorChooser.sampleText"));
+
+ }
+
+ public static void initLang() {
+ if (!Configuration.locale.hasValue()) {
+ if (Platform.isWindows()) {
+ //Load from Installer
+ String uninstKey = "{E618D276-6596-41F4-8A98-447D442A77DB}_is1";
+ uninstKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + uninstKey;
+ try {
+ if (Advapi32Util.registryKeyExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey)) {
+ if (Advapi32Util.registryValueExists(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language")) {
+ String installedLoc = Advapi32Util.registryGetStringValue(WinReg.HKEY_LOCAL_MACHINE, uninstKey, "NSIS: Language");
+ int lcid = Integer.parseInt(installedLoc);
+ char[] buf = new char[9];
+ int cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO639LANGNAME, buf, 9);
+ String langCode = new String(buf, 0, cnt).trim().toLowerCase();
+
+ cnt = Kernel32.INSTANCE.GetLocaleInfo(lcid, Kernel32.LOCALE_SISO3166CTRYNAME, buf, 9);
+ String countryCode = new String(buf, 0, cnt).trim().toLowerCase();
+
+ List langs = Arrays.asList(SelectLanguageDialog.getAvailableLanguages());
+ for (int i = 0; i < langs.size(); i++) {
+ langs.set(i, langs.get(i).toLowerCase());
+ }
+
+ String selectedLang = null;
+
+ if (langs.contains(langCode + "-" + countryCode)) {
+ selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode + "-" + countryCode)];
+ } else if (langs.contains(langCode)) {
+ selectedLang = SelectLanguageDialog.getAvailableLanguages()[langs.indexOf(langCode)];
+ }
+ if (selectedLang != null) {
+ Configuration.locale.set(selectedLang);
+ }
+ }
+ }
+ } catch (Exception ex) {
+ //ignore
+ }
+ }
+ }
+ Locale.setDefault(Locale.forLanguageTag(Configuration.locale.get()));
+ AppStrings.updateLanguage();
+
+ Helper.decompilationErrorAdd = AppStrings.translate(Configuration.autoDeobfuscate.get() ? "deobfuscation.comment.failed" : "deobfuscation.comment.tryenable");
+ }
+
+ /**
+ * Clear old FFDec/JavactiveX temp files
+ */
+ private static void clearTemp() {
+ String tempDirPath = System.getProperty("java.io.tmpdir");
+ if (tempDirPath == null) {
+ return;
+ }
+ File tempDir = new File(tempDirPath);
+ if (!tempDir.exists()) {
+ return;
+ }
+ File[] delFiles = tempDir.listFiles(new FilenameFilter() {
+ @Override
+ public boolean accept(File dir, String name) {
+ return name.matches("ffdec_cache.*\\.tmp") || name.matches("javactivex_.*\\.exe") || name.matches("temp[0-9]+\\.swf") || name.matches("ffdec_view_.*\\.swf");
+ }
+ });
+
+ if (delFiles != null) {
+ for (File f : delFiles) {
+ try {
+ f.delete();
+ } catch (Exception ex) {
+ //ignore
+ }
+ }
+ }
+ }
+
+ /**
+ * @param args the command line arguments
+ * @throws IOException On error
+ */
+ public static void main(String[] args) throws IOException {
+ setSessionLoaded(false);
+
+ clearTemp();
+
+ try {
+ SWFDecompilerPlugin.loadPlugins();
+ } catch (Throwable ex) {
+ logger.log(Level.SEVERE, "Failed to load plugins", ex);
+ }
+
+ AppStrings.setResourceClass(MainFrame.class);
+ initLogging(Configuration._debugMode.get());
+
+ initLang();
+
+ if (Configuration.cacheOnDisk.get()) {
+ Cache.setStorageType(Cache.STORAGE_FILES);
+ } else {
+ Cache.setStorageType(Cache.STORAGE_MEMORY);
+ }
+
+ if (args.length == 0) {
+ initGui();
+ checkLibraryVersion();
+ View.execInEventDispatch(() -> {
+ if (Configuration.allowOnlyOneInstance.get() && FirstInstance.focus()) { //Try to focus first instance
+ Main.exit();
+ } else {
+ showModeFrame();
+ reloadLastSession();
+ }
+ });
+ } else {
+ checkLibraryVersion();
+ setSessionLoaded(true);
+ String[] filesToOpen = CommandLineArgumentParser.parseArguments(args);
+ if (filesToOpen != null && filesToOpen.length > 0) {
+ View.execInEventDispatch(() -> {
+ initGui();
+ shouldCloseWhenClosingLoadingDialog = true;
+ if (Configuration.allowOnlyOneInstance.get() && FirstInstance.openFiles(Arrays.asList(filesToOpen))) { //Try to open in first instance
+ Main.exit();
+ } else {
+ for (String fileToOpen : filesToOpen) {
+ openFile(fileToOpen, null);
+ }
+ }
+ });
+ }
+ }
+ }
+
+ private static void checkLibraryVersion() {
+ if (!ApplicationInfo.version.equals("unknown") && !ApplicationInfo.libraryVersion.equals("unknown")
+ && !Objects.equals(ApplicationInfo.version, ApplicationInfo.libraryVersion)) {
+ logger.log(Level.WARNING, "Application version is different from library version. FFDec may not work properly.");
+ }
+ }
+
+ private static void reloadLastSession() {
+ boolean openingFiles = false;
+ if (Configuration.saveSessionOnExit.get()) {
+ String lastSession = Configuration.lastSessionFiles.get();
+ if (lastSession != null && lastSession.length() > 0) {
+ String[] filesToOpen = lastSession.split(File.pathSeparator, -1);
+ List exfiles = new ArrayList<>();
+ List extitles = new ArrayList<>();
+ String lastSessionTitles = Configuration.lastSessionFileTitles.get();
+ String[] fileTitles = new String[0];
+ if (lastSessionTitles != null && !lastSessionTitles.isEmpty()) {
+ fileTitles = lastSessionTitles.split(File.pathSeparator, -1);
+ }
+ for (int i = 0; i < filesToOpen.length; i++) {
+ if (new File(filesToOpen[i]).exists()) {
+ exfiles.add(filesToOpen[i]);
+ if (fileTitles.length > i) {
+ extitles.add(fileTitles[i]);
+ } else {
+ extitles.add(null);
+ }
+ }
+ }
+ SWFSourceInfo[] sourceInfos = new SWFSourceInfo[exfiles.size()];
+ for (int i = 0; i < exfiles.size(); i++) {
+ String extitle = extitles.get(i);
+ sourceInfos[i] = new SWFSourceInfo(null, exfiles.get(i), extitle == null || extitle.isEmpty() ? null : extitle);
+ }
+ if (sourceInfos.length > 0) {
+ openingFiles = true;
+ openFile(sourceInfos, () -> {
+ mainFrame.getPanel().tagTree.setSelectionPathString(Configuration.lastSessionSelection.get());
+ setSessionLoaded(true);
+ });
+ }
+ }
+ }
+
+ if (!openingFiles) {
+ setSessionLoaded(true);
+ }
+ }
+
+ public static String tempFile(String url) throws IOException {
+ File f = new File(Configuration.getFFDecHome() + "saved" + File.separator);
+ Path.createDirectorySafe(f);
+ return Configuration.getFFDecHome() + "saved" + File.separator + "asdec_" + Integer.toHexString(url.hashCode()) + ".tmp";
+ }
+
+ public static void removeTrayIcon() {
+ if (SystemTray.isSupported()) {
+ SystemTray tray = SystemTray.getSystemTray();
+ if (trayIcon != null) {
+ tray.remove(trayIcon);
+ trayIcon = null;
+ }
+ }
+ }
+
+ public static void switchProxy() {
+ proxyFrame.switchState();
+ if (stopMenuItem != null) {
+ if (proxyFrame.isRunning()) {
+ stopMenuItem.setLabel(AppStrings.translate("proxy.stop"));
+ } else {
+ stopMenuItem.setLabel(AppStrings.translate("proxy.start"));
+ }
+ }
+ }
+
+ public static void addTrayIcon() {
+ if (trayIcon != null) {
+ return;
+ }
+ if (SystemTray.isSupported()) {
+ SystemTray tray = SystemTray.getSystemTray();
+ trayIcon = new TrayIcon(View.loadImage("proxy16"), ApplicationInfo.VENDOR + " " + ApplicationInfo.SHORT_APPLICATION_NAME + " " + AppStrings.translate("proxy"));
+ trayIcon.setImageAutoSize(true);
+ PopupMenu trayPopup = new PopupMenu();
+
+ ActionListener trayListener = new ActionListener() {
+ /**
+ * Invoked when an action occurs.
+ */
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("EXIT")) {
+ Main.exit();
+ }
+ if (e.getActionCommand().equals("SHOW")) {
+ Main.showProxy();
+ }
+ if (e.getActionCommand().equals("SWITCH")) {
+ Main.switchProxy();
+ }
+ }
+ };
+
+ MenuItem showMenuItem = new MenuItem(AppStrings.translate("proxy.show"));
+ showMenuItem.setActionCommand("SHOW");
+ showMenuItem.addActionListener(trayListener);
+ trayPopup.add(showMenuItem);
+ stopMenuItem = new MenuItem(AppStrings.translate("proxy.start"));
+ stopMenuItem.setActionCommand("SWITCH");
+ stopMenuItem.addActionListener(trayListener);
+ trayPopup.add(stopMenuItem);
+ trayPopup.addSeparator();
+ MenuItem exitMenuItem = new MenuItem(AppStrings.translate("exit"));
+ exitMenuItem.setActionCommand("EXIT");
+ exitMenuItem.addActionListener(trayListener);
+ trayPopup.add(exitMenuItem);
+
+ trayIcon.setPopupMenu(trayPopup);
+ trayIcon.addMouseListener(new MouseAdapter() {
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getButton() == MouseEvent.BUTTON1) {
+ Main.showProxy();
+ }
+ }
+ });
+ try {
+ tray.add(trayIcon);
+ } catch (AWTException ex) {
+ }
+ }
+ }
+
+ public static void exit() {
+ Configuration.saveConfig();
+ if (mainFrame != null && mainFrame.getPanel() != null) {
+ mainFrame.getPanel().unloadFlashPlayer();
+ mainFrame.dispose();
+ }
+ if (fileTxt != null) {
+ try {
+ fileTxt.flush();
+ fileTxt.close();
+ } catch (Exception ex) {
+ //ignore
+ }
+ }
+ System.exit(0);
+ }
+
+ public static void about() {
+ (new AboutDialog()).setVisible(true);
+ }
+
+ public static void advancedSettings() {
+ advancedSettings(null);
+ }
+
+ public static void advancedSettings(String category) {
+ (new AdvancedSettingsDialog(category)).setVisible(true);
+ }
+
+ public static void autoCheckForUpdates() {
+ if (Configuration.checkForUpdatesAuto.get()) {
+ Calendar lastUpdatesCheckDate = Configuration.lastUpdatesCheckDate.get();
+ if ((lastUpdatesCheckDate == null) || (lastUpdatesCheckDate.getTime().getTime() < Calendar.getInstance().getTime().getTime() - Configuration.checkForUpdatesDelay.get())) {
+ new SwingWorker() {
+ @Override
+ protected Object doInBackground() throws Exception {
+ checkForUpdates();
+ return null;
+ }
+ }.execute();
+ }
+ }
+ }
+
+ public static boolean checkForUpdates() {
+ String currentVersion = ApplicationInfo.version;
+ if (currentVersion.equals("unknown")) {
+ // sometimes during development the version information is not available
+ return false;
+ }
+
+ List accepted = new ArrayList<>();
+ if (Configuration.checkForUpdatesStable.get()) {
+ accepted.add("stable");
+ }
+ if (Configuration.checkForUpdatesNightly.get()) {
+ accepted.add("nightly");
+ }
+
+ if (accepted.isEmpty()) {
+ return false;
+ }
+
+ String acceptVersions = String.join(",", accepted);
+ try {
+ String proxyAddress = Configuration.updateProxyAddress.get();
+ URL url = new URL(ApplicationInfo.updateCheckUrl);
+
+ URLConnection uc;
+ if (proxyAddress != null && !proxyAddress.isEmpty()) {
+ int port = 8080;
+ if (proxyAddress.contains(":")) {
+ String[] parts = proxyAddress.split(":");
+ port = Integer.parseInt(parts[1]);
+ proxyAddress = parts[0];
+ }
+
+ uc = url.openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, port)));
+ } else {
+ uc = url.openConnection();
+ }
+ uc.setRequestProperty("X-Accept-Versions", acceptVersions);
+ uc.setRequestProperty("X-Update-Major", "" + UPDATE_SYSTEM_MAJOR);
+ uc.setRequestProperty("X-Update-Minor", "" + UPDATE_SYSTEM_MINOR);
+ uc.setRequestProperty("User-Agent", ApplicationInfo.shortApplicationVerName);
+ String currentLoc = Configuration.locale.get("en");
+ uc.setRequestProperty("Accept-Language", currentLoc + ("en".equals(currentLoc) ? "" : ", en;q=0.8"));
+
+ uc.connect();
+
+ BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
+ String s;
+ final java.util.List versions = new ArrayList<>();
+ String header = "";
+ Pattern headerPat = Pattern.compile("\\[([a-zA-Z0-9]+)\\]");
+ int updateMajor;
+ int updateMinor;
+ Version ver = null;
+ while ((s = br.readLine()) != null) {
+
+ Matcher m = headerPat.matcher(s);
+ if (m.matches()) {
+ header = m.group(1);
+ if (header.equals("version")) {
+ ver = new Version();
+ versions.add(ver);
+ }
+ if (header.equals("noversion")) {
+ break;
+ }
+ } else if (s.contains("=")) {
+ String key = s.substring(0, s.indexOf('='));
+ String val = s.substring(s.indexOf('=') + 1);
+ if ("updateSystem".equals(header)) {
+ if (key.equals("majorVersion")) {
+ updateMajor = Integer.parseInt(val);
+ if (updateMajor > UPDATE_SYSTEM_MAJOR) {
+ break;
+ }
+ }
+ if (key.equals("minorVersion")) {
+ updateMinor = Integer.parseInt(val);
+ }
+ }
+ if ("version".equals(header) && (ver != null)) {
+ if (key.equals("versionId")) {
+ ver.versionId = Integer.parseInt(val);
+ }
+ if (key.equals("versionName")) {
+ ver.versionName = val;
+ }
+ if (key.equals("nightly")) {
+ ver.nightly = val.equals("true");
+ }
+ if (key.equals("revision")) {
+ ver.revision = val;
+ }
+ if (key.equals("build")) {
+ ver.build = Integer.parseInt(val);
+ }
+ if (key.equals("major")) {
+ ver.major = Integer.parseInt(val);
+ }
+ if (key.equals("minor")) {
+ ver.minor = Integer.parseInt(val);
+ }
+ if (key.equals("release")) {
+ ver.release = Integer.parseInt(val);
+ }
+ if (key.equals("longVersionName")) {
+ ver.longVersionName = val;
+ }
+ if (key.equals("releaseDate")) {
+ ver.releaseDate = val;
+ }
+ if (key.equals("appName")) {
+ ver.appName = val;
+ }
+ if (key.equals("appFullName")) {
+ ver.appFullName = val;
+ }
+ if (key.equals("updateLink")) {
+ ver.updateLink = val;
+ }
+ if (key.equals("change[]")) {
+ String changeType = val.substring(0, val.indexOf('|'));
+ String change = val.substring(val.indexOf('|') + 1);
+ if (!ver.changes.containsKey(changeType)) {
+ ver.changes.put(changeType, new ArrayList<>());
+ }
+ List chlist = ver.changes.get(changeType);
+ chlist.add(change);
+ }
+ }
+ }
+ }
+
+ if (!versions.isEmpty()) {
+ View.execInEventDispatch(() -> {
+ NewVersionDialog newVersionDialog = new NewVersionDialog(versions);
+ newVersionDialog.setVisible(true);
+ Configuration.lastUpdatesCheckDate.set(Calendar.getInstance());
+ });
+
+ return true;
+ }
+ } catch (IOException | NumberFormatException ex) {
+ return false;
+ }
+ Configuration.lastUpdatesCheckDate.set(Calendar.getInstance());
+ return false;
+ }
+
+ private static FileHandler fileTxt;
+
+ public static void clearLogFile() {
+ Logger logger = Logger.getLogger("");
+
+ FileHandler oldFileTxt = fileTxt;
+ fileTxt = null;
+ if (oldFileTxt != null) {
+ logger.removeHandler(fileTxt);
+ oldFileTxt.flush();
+ oldFileTxt.close();
+ }
+
+ String fileName = null;
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-hh-mm-ss");
+
+ try {
+ fileName = Configuration.getFFDecHome() + "logs" + File.separator;
+ if (Configuration.useDetailedLogging.get()) {
+ fileName += "log-" + sdf.format(new Date()) + ".txt";
+ } else {
+ fileName += "log.txt";
+ }
+ File f = new File(fileName).getParentFile();
+ if (!f.exists()) {
+ f.mkdir();
+ }
+ fileTxt = new FileHandler(fileName);
+ } catch (IOException | SecurityException ex) {
+ //cannot get lock error
+ if (ex.getMessage().contains("lock for")) {
+ //remove all old log files and their .lck
+ for (int i = 0; i <= 100; i++) {
+ File flog = new File(fileName + (i == 0 ? "" : "." + i));
+ File flog_lock = new File(fileName + (i == 0 ? "" : "." + i) + ".lck");
+ flog.delete();
+ flog_lock.delete();
+ }
+ try {
+ fileTxt = new FileHandler(fileName);
+ } catch (IOException | SecurityException ex1) {
+ logger.log(Level.SEVERE, "Cannot initialize logging", ex);
+ }
+ } else {
+ logger.log(Level.SEVERE, "Cannot initialize logging", ex);
+ }
+ }
+
+ Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ logger.log(Level.SEVERE, "Uncaught exception in thread: " + t.getName(), e);
+ if (e instanceof OutOfMemoryError && !Helper.is64BitJre() && Helper.is64BitOs()) {
+ View.showMessageDialog(null, AppStrings.translate("message.warning.outOfMemory32BitJre"), AppStrings.translate("message.warning"), JOptionPane.WARNING_MESSAGE);
+ }
+ }
+ });
+
+ Formatter formatterTxt = new LogFormatter();
+ if (fileTxt != null) {
+ fileTxt.setFormatter(formatterTxt);
+ logger.addHandler(fileTxt);
+ }
+
+ if (!GraphicsEnvironment.isHeadless() && ErrorLogFrame.hasInstance()) {
+ ErrorLogFrame.getInstance().clearErrorState();
+ }
+
+ sdf = new SimpleDateFormat("yyyy-MM-dd");
+ logger.log(Level.INFO, "Date: {0}", sdf.format(new Date()));
+ logger.log(Level.INFO, ApplicationInfo.applicationVerName);
+ logger.log(Level.INFO, "{0} {1} {2}", new Object[]{
+ System.getProperty("os.name"), System.getProperty("os.version"), System.getProperty("os.arch")});
+ logger.log(Level.INFO, "{0} {1} {2}", new Object[]{
+ System.getProperty("java.version"), System.getProperty("java.vendor"), System.getProperty("os.arch")});
+ }
+
+ public static void initLogging(boolean debug) {
+ try {
+ Logger logger = Logger.getLogger("");
+ logger.setLevel(Configuration.logLevel);
+
+ Handler[] handlers = logger.getHandlers();
+ for (int i = handlers.length - 1; i >= 0; i--) {
+ logger.removeHandler(handlers[i]);
+ }
+
+ ConsoleHandler conHan = new ConsoleHandler();
+ conHan.setLevel(debug ? Level.CONFIG : Level.WARNING);
+ SimpleFormatter formatterTxt = new SimpleFormatter();
+ conHan.setFormatter(formatterTxt);
+ logger.addHandler(conHan);
+ clearLogFile();
+
+ } catch (Exception ex) {
+ throw new RuntimeException("Problems with creating the log files");
+ }
+ }
+}
diff --git a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java
index c947bfde1..eb020c8bd 100644
--- a/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java
+++ b/src/com/jpexs/decompiler/flash/gui/editor/LineMarkedEditorPane.java
@@ -1,693 +1,693 @@
-/*
- * Copyright (C) 2010-2016 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.editor;
-
-import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
-import com.jpexs.decompiler.flash.configuration.Configuration;
-import com.jpexs.decompiler.flash.gui.AppStrings;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.FontMetrics;
-import java.awt.Graphics;
-import java.awt.KeyEventPostProcessor;
-import java.awt.KeyboardFocusManager;
-import java.awt.Point;
-import java.awt.Rectangle;
-import java.awt.Shape;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.awt.event.KeyListener;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import javax.swing.event.CaretEvent;
-import javax.swing.event.CaretListener;
-import javax.swing.plaf.TextUI;
-import javax.swing.text.BadLocationException;
-import javax.swing.text.DefaultHighlighter;
-import javax.swing.text.Document;
-import javax.swing.text.Element;
-import javax.swing.text.Highlighter.HighlightPainter;
-import javax.swing.text.JTextComponent;
-import javax.swing.text.Position;
-import javax.swing.text.Segment;
-import javax.swing.text.View;
-import jsyntaxpane.SyntaxDocument;
-import jsyntaxpane.SyntaxStyle;
-import jsyntaxpane.Token;
-import jsyntaxpane.actions.ActionUtils;
-
-/**
- *
- * @author JPEXS
- */
-public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHandler {
-
- private static final int truncateLimit = 2 * 1024 * 1024;
-
- public static final Color BG_SELECTED_LINE = new Color(0xe9, 0xef, 0xf8);
-
- public static final Color BG_ERROR_LINE = new Color(255, 200, 200);
-
- private int lastLine = -1;
-
- private boolean error = false;
-
- private Token lastUnderlined = null;
-
- private static final HighlightPainter underLinePainter = new UnderLinePainter(new Color(0, 0, 255));
-
- private LinkHandler linkHandler = this;
-
- public static class LineMarker implements Comparable {
-
- private final Color bgColor;
-
- private final Color color;
-
- private FgPainter fgPainter;
-
- //private int line;
- private final int priority;
-
- public FgPainter getForegroundPainter() {
- return fgPainter;
- }
-
- @Override
- public String toString() {
- return bgColor.toString() + " priority:" + priority;
- }
-
- public LineMarker(Color color, Color bgColor, int priority) {
- this.bgColor = bgColor;
- this.color = color;
- this.priority = priority;
- if (color != null) {
- this.fgPainter = new FgPainter(color, bgColor);
- }
- }
-
- @Override
- public int hashCode() {
- int hash = 5;
- hash = 17 * hash + Objects.hashCode(this.bgColor);
- hash = 17 * hash + Objects.hashCode(this.color);
- return hash;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final LineMarker other = (LineMarker) obj;
- if (!Objects.equals(this.bgColor, other.bgColor)) {
- return false;
- }
- return (Objects.equals(this.color, other.color));
- }
-
- public Color getBgColor() {
- return bgColor;
- }
-
- public Color getColor() {
- return color;
- }
-
- @Override
- public int compareTo(LineMarker o) {
- return priority - o.priority;
- }
- }
-//(Map>)
-
- private Map> lineMarkers = Collections.synchronizedMap(new HashMap>());
-
- public void setLineMarkers(Map> colorMarkers) {
- this.lineMarkers = colorMarkers;
- }
-
- public void clearLineColors() {
- lineMarkers.clear();
- repaint();
- }
-
- public boolean hasColorMarker(int line, LineMarker lm) {
- line -= firstLineOffset();
- if (lineMarkers.containsKey(line)) {
- return lineMarkers.get(line).contains(lm);
- }
- return false;
- }
-
- public void removeColorMarker(int line, LineMarker lm) {
- line -= firstLineOffset();
- if (lineMarkers.containsKey(line)) {
- lineMarkers.get(line).remove(lm);
- }
- getParent().repaint();
- }
-
- public void removeColorMarkerOnAllLines(LineMarker lm) {
- for (int line : lineMarkers.keySet()) {
- line += firstLineOffset();
- removeColorMarker(line, lm);
- }
- }
-
- public int firstLineOffset() {
- return 0;
- }
-
- public void toggleColorMarker(int line, LineMarker lm) {
- if (!lineMarkers.containsKey(line - firstLineOffset())) {
- addColorMarker(line, lm);
- } else if (lineMarkers.get(line - firstLineOffset()).contains(lm)) {
- removeColorMarker(line, lm);
- } else {
- addColorMarker(line, lm);
- }
- getParent().repaint();
- }
-
- public void addColorMarker(int line, LineMarker lm) {
- line -= firstLineOffset();
- if (!lineMarkers.containsKey(line)) {
- lineMarkers.put(line, Collections.synchronizedSortedSet(new TreeSet<>()));
- }
- lineMarkers.get(line).add(lm);
- getParent().repaint();
- }
-
- public int getLine() {
- int caretPosition = getCaretPosition();
- Element root = getDocument().getDefaultRootElement();
- int currentLine = root.getElementIndex(caretPosition);
- return currentLine;
- }
-
- public void markError() {
- error = true;
- }
-
- public void gotoLine(int line) {
- int pos = ActionUtils.getDocumentPosition(this, line, 0);
- if (pos != -1) {
- setCaretPosition(pos);
- }
- }
-
- public void gotoLineCol(int line, int column) {
- int pos = ActionUtils.getDocumentPosition(this, line, column);
- if (pos != -1) {
- setCaretPosition(pos);
- }
- }
-
- public Point getLineLocation(int line) {
- int pos = ActionUtils.getDocumentPosition(this, line + 1, 0);
- if (pos < 0) {
- return null;
- }
- try {
- Rectangle r = modelToView(pos);
- return new Point(r.x, r.y);
- } catch (BadLocationException ex) {
- return null;
- }
- }
-
- private void getLineBounds(int line, Reference lineStart, Reference lineEnd) {
- Document d = getDocument();
- String text = "";
- try {
- text = d.getText(0, d.getLength());
- } catch (BadLocationException ex) {
- //ignore
- }
- int lineCnt = 0;
- int lineStartVal = 0;
- int lineEndVal = -1;
- for (int i = 0; i < text.length(); i++) {
- if (text.charAt(i) == '\n') {
- lineCnt++;
- if (lineCnt == line) {
- lineStartVal = i + 1;
- }
- if (lineCnt == line + 1) {
- lineEndVal = i;
- }
- }
- }
- if (lineCnt == 0) {
- lineEndVal = text.length() - 1;
- if (line > 0) {
- lineStartVal = text.length() - 1;
- }
- }
- lineEnd.setVal(lineEndVal);
- lineStart.setVal(lineStartVal);
- }
-
- public void selectLine(int line) {
- Reference lineStart = new Reference<>(0);
- Reference lineEnd = new Reference<>(0);
- getLineBounds(line, lineStart, lineEnd);
-
- select(lineStart.getVal(), lineEnd.getVal());
- requestFocus();
- }
-
- public String getCurrentLineText() {
- return getLineText(getLine());
- }
-
- public String getLineText(int line) {
- Reference lineStart = new Reference<>(0);
- Reference lineEnd = new Reference<>(0);
- getLineBounds(line, lineStart, lineEnd);
- try {
- return getDocument().getText(lineStart.getVal(), lineEnd.getVal() - lineStart.getVal());
- } catch (BadLocationException ex) {
- return null;
- }
- }
-
- public LineMarkedEditorPane() {
- setOpaque(false);
- addCaretListener(new CaretListener() {
- @Override
- public void caretUpdate(CaretEvent e) {
- int caretPosition = getCaretPosition();
- Element root = getDocument().getDefaultRootElement();
- int currentLine = root.getElementIndex(caretPosition);
- if (currentLine != lastLine) {
- lastLine = currentLine;
- error = false;
- repaint();
- }
-
- }
- });
- final LinkAdapter la = new LinkAdapter();
- addMouseMotionListener(la);
- addMouseListener(la);
-
- //No standard AddKeyListener as we want to catch Ctrl globally no matter of focus
- KeyboardFocusManager.getCurrentKeyboardFocusManager()
- .addKeyEventPostProcessor(new KeyEventPostProcessor() {
- @Override
- public boolean postProcessKeyEvent(KeyEvent e) {
- if (e.getID() == KeyEvent.KEY_PRESSED) {
- la.keyPressed(e);
- }
- if (e.getID() == KeyEvent.KEY_RELEASED) {
- la.keyReleased(e);
- }
- if (e.getID() == KeyEvent.KEY_TYPED) {
- la.keyTyped(e);
- }
- return false;
- }
- });
-
- }
-
- public Token tokenAtPos(Point lastPos) {
- Document d = getDocument();
- if (d instanceof SyntaxDocument) {
- SyntaxDocument sd = (SyntaxDocument) d;
-
- //correction of token last character
- int pos = viewToModel(lastPos);
- Rectangle r;
- try {
- r = modelToView(pos);
- if (r != null) {
- if (lastPos.x < r.x) {
- pos--;
- }
- }
- } catch (BadLocationException ex) {
- //ignore
- }
- Token t = sd.getTokenAt(pos);
-
- //Correction of token of length 1 character
- if (pos > 0 && pos < d.getLength() - 1 && t != null && t.length == 1) {
- Token tprev = sd.getTokenAt(pos - 1);
- if (tprev == t) {
- t = sd.getTokenAt(pos + 1);
- }
- }
-
- return t;
- }
- return null;
- }
-
- private class LinkAdapter extends MouseAdapter implements KeyListener {
-
- private Point lastPos = new Point(0, 0);
-
- private boolean ctrlDown = false;
-
- @Override
- public void keyPressed(KeyEvent e) {
- if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
- ctrlDown = true;
- update();
- }
- }
-
- @Override
- public void keyTyped(KeyEvent e) {
-
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
- if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
- ctrlDown = false;
- update();
- }
- }
-
- private void update() {
- if (ctrlDown) {
- Token t = tokenAtPos(lastPos);
-
- if (t != lastUnderlined) {
- if (t == null || lastUnderlined == null || !t.equals(lastUnderlined)) {
- MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter);
-
- if (t != null && linkHandler.isLink(t)) {
- lastUnderlined = t;
- setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
-
- } else {
- lastUnderlined = null;
- }
- } else {
- lastUnderlined = null;
- }
- }
-
- if (lastUnderlined != null) {
- MyMarkers.markToken(LineMarkedEditorPane.this, lastUnderlined, underLinePainter);
- } else {
- setCursor(Cursor.getDefaultCursor());
- }
- repaint();
- } else {
- lastUnderlined = null;
- MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter);
- setCursor(Cursor.getDefaultCursor());
- repaint();
- }
- }
-
- @Override
- public void mouseClicked(MouseEvent e) {
- if (ctrlDown) {
- Token t = tokenAtPos(lastPos);
- if (t != null && linkHandler.isLink(t)) {
- linkHandler.handleLink(t);
- }
- }
- }
-
- @Override
- public void mouseMoved(MouseEvent e) {
-
- ctrlDown = (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0;
- lastPos = e.getPoint();
- update();
-
- }
- }
-
- public void setLinkHandler(LinkHandler linkHandler) {
- if (linkHandler == null) {
- linkHandler = this;
- }
- this.linkHandler = linkHandler;
- }
-
- public LinkHandler getLinkHandler() {
- return linkHandler;
- }
-
- @Override
- public HighlightPainter linkPainter() {
- return underLinePainter;
- }
-
- @Override
- public boolean isLink(Token token) {
- return false;
- }
-
- @Override
- public void handleLink(Token token) {
-
- }
-
- @Override
- public void setText(String t) {
- this.lineMarkers = new HashMap<>();
- lastLine = -1;
- error = false;
- if (Configuration._debugMode.get() && t != null && t.length() > truncateLimit) {
- t = t.substring(0, truncateLimit) + "\r\n" + AppStrings.translate("editorTruncateWarning").replace("%chars%", Integer.toString(truncateLimit));
- }
-
- super.setText(t);
- setCaretPosition(0); //scroll to top
- }
-
- public static class FgPainter extends DefaultHighlighter.DefaultHighlightPainter {
-
- private final SyntaxStyle fgStyle;
-
- public FgPainter(Color color, Color bgColor) {
- super(bgColor);
- this.fgStyle = new SyntaxStyle(color, false, false);
- }
-
- @Override
- public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
- try {
- // --- determine locations ---
- TextUI mapper = c.getUI();
-
- Segment seg = new Segment();
- ((SyntaxDocument) c.getDocument()).getText(offs0, offs1 - offs0, seg);
-
- Rectangle r = mapper.modelToView(c, offs0, Position.Bias.Forward);
- FontMetrics fm = g.getFontMetrics();
- //int fh = fm.getHeight();
- fgStyle.drawText(seg, r.x, r.y + fm.getAscent(), g, null, offs0);
- /*for (int i = offs0; i < offs1; i++) {
-
- Rectangle r = mapper.modelToView(c, i, Position.Bias.Forward);
- Rectangle r1 = mapper.modelToView(c, i + 1, Position.Bias.Forward);
- if (r1.y == r.y) {
- ((SyntaxDocument) c.getDocument()).getText(i, 1, seg);
- fgStyle.drawText(seg, r.x, r.y, g, null, i);
- //g.drawLine(r.x, r.y + r.height - 3, r1.x, r.y + r.height - 3);
- }
- }*/
-
- } catch (BadLocationException e) {
- // can't render
- }
- }
-
- @Override
- public Shape paintLayer(Graphics g, int offs0, int offs1,
- Shape bounds, JTextComponent c, View view) {
-
- g.setColor(c.getSelectionColor());
-
- Rectangle r;
-
- if (offs0 == view.getStartOffset()
- && offs1 == view.getEndOffset()) {
- // Contained in view, can just use bounds.
- if (bounds instanceof Rectangle) {
- r = (Rectangle) bounds;
- } else {
- r = bounds.getBounds();
- }
- } else {
- // Should only render part of View.
- try {
- // --- determine locations ---
- Shape shape = view.modelToView(offs0, Position.Bias.Forward,
- offs1, Position.Bias.Backward,
- bounds);
- r = (shape instanceof Rectangle)
- ? (Rectangle) shape : shape.getBounds();
- } catch (BadLocationException e) {
- // can't render
- r = null;
- }
- }
-
- if (r != null) {
- r.width = Math.max(r.width, 1);
-
- paint(g, offs0, offs1, r, c);
- }
-
- return r;
- }
- }
-
- public static class UnderLinePainter extends DefaultHighlighter.DefaultHighlightPainter {
-
- public UnderLinePainter(Color color) {
- super(color);
- }
-
- @Override
- public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
- try {
- // --- determine locations ---
- TextUI mapper = c.getUI();
-
- Color col = getColor();
- if (col == null) {
- col = Color.black;
- }
- g.setColor(col);
- for (int i = offs0; i < offs1; i++) {
-
- Rectangle r = mapper.modelToView(c, i, Position.Bias.Forward);
- Rectangle r1 = mapper.modelToView(c, i + 1, Position.Bias.Forward);
- if (r1.y == r.y) {
- g.drawLine(r.x, r.y + r.height - 3, r1.x, r.y + r.height - 3);
- }
- }
-
- } catch (BadLocationException e) {
- // can't render
- }
- }
-
- @Override
- public Shape paintLayer(Graphics g, int offs0, int offs1,
- Shape bounds, JTextComponent c, View view) {
-
- g.setColor(c.getSelectionColor());
-
- Rectangle r;
-
- if (offs0 == view.getStartOffset()
- && offs1 == view.getEndOffset()) {
- // Contained in view, can just use bounds.
- if (bounds instanceof Rectangle) {
- r = (Rectangle) bounds;
- } else {
- r = bounds.getBounds();
- }
- } else {
- // Should only render part of View.
- try {
- // --- determine locations ---
- Shape shape = view.modelToView(offs0, Position.Bias.Forward,
- offs1, Position.Bias.Backward,
- bounds);
- r = (shape instanceof Rectangle)
- ? (Rectangle) shape : shape.getBounds();
- } catch (BadLocationException e) {
- // can't render
- r = null;
- }
- }
-
- if (r != null) {
- r.width = Math.max(r.width, 1);
-
- paint(g, offs0, offs1, r, c);
-
- }
-
- return r;
- }
- }
-
- @Override
- public void paint(Graphics g) {
- g.setColor(Color.white);
- g.fillRect(0, 0, getWidth(), getHeight());
- FontMetrics fontMetrics = g.getFontMetrics();
- int lh = fontMetrics.getHeight();
- int d = fontMetrics.getDescent();
-
- if (lastLine > 0) {
- if (error) {
- g.setColor(BG_ERROR_LINE);
- } else {
- g.setColor(BG_SELECTED_LINE);
- }
- g.fillRect(0, d + lh * lastLine - 1, getWidth(), lh);
- }
- for (int line : lineMarkers.keySet()) {
- SortedSet cs = lineMarkers.get(line);
- if (cs.isEmpty()) {
- continue;
- }
- LineMarker lastMarker = cs.first();
- if (lastMarker.getBgColor() == null) {
- continue;
- }
- g.setColor(lastMarker.getBgColor());
- line += firstLineOffset();
- g.fillRect(0, d + lh * (line - 1), getWidth(), lh);
- }
- super.paint(g);
- for (int line : lineMarkers.keySet()) {
-
- SortedSet cs = lineMarkers.get(line);
- if (cs.isEmpty()) {
- continue;
- }
- line += firstLineOffset();
-
- Reference lineStart = new Reference<>(0);
- Reference lineEnd = new Reference<>(0);
-
- getLineBounds(line, lineStart, lineEnd);
- FgPainter fgp = cs.first().getForegroundPainter();
- if (fgp != null) {
- fgp.paint(g, lineStart.getVal(), lineEnd.getVal(), null, this);
- }
- }
- }
-}
+/*
+ * Copyright (C) 2010-2016 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.editor;
+
+import com.jpexs.decompiler.flash.abc.avm2.parser.script.Reference;
+import com.jpexs.decompiler.flash.configuration.Configuration;
+import com.jpexs.decompiler.flash.gui.AppStrings;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.KeyEventPostProcessor;
+import java.awt.KeyboardFocusManager;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Shape;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.swing.event.CaretEvent;
+import javax.swing.event.CaretListener;
+import javax.swing.plaf.TextUI;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.DefaultHighlighter;
+import javax.swing.text.Document;
+import javax.swing.text.Element;
+import javax.swing.text.Highlighter.HighlightPainter;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.Position;
+import javax.swing.text.Segment;
+import javax.swing.text.View;
+import jsyntaxpane.SyntaxDocument;
+import jsyntaxpane.SyntaxStyle;
+import jsyntaxpane.Token;
+import jsyntaxpane.actions.ActionUtils;
+
+/**
+ *
+ * @author JPEXS
+ */
+public class LineMarkedEditorPane extends UndoFixedEditorPane implements LinkHandler {
+
+ private static final int truncateLimit = 2 * 1024 * 1024;
+
+ public static final Color BG_SELECTED_LINE = new Color(0xe9, 0xef, 0xf8);
+
+ public static final Color BG_ERROR_LINE = new Color(255, 200, 200);
+
+ private int lastLine = -1;
+
+ private boolean error = false;
+
+ private Token lastUnderlined = null;
+
+ private static final HighlightPainter underLinePainter = new UnderLinePainter(new Color(0, 0, 255));
+
+ private LinkHandler linkHandler = this;
+
+ public static class LineMarker implements Comparable {
+
+ private final Color bgColor;
+
+ private final Color color;
+
+ private FgPainter fgPainter;
+
+ //private int line;
+ private final int priority;
+
+ public FgPainter getForegroundPainter() {
+ return fgPainter;
+ }
+
+ @Override
+ public String toString() {
+ return bgColor.toString() + " priority:" + priority;
+ }
+
+ public LineMarker(Color color, Color bgColor, int priority) {
+ this.bgColor = bgColor;
+ this.color = color;
+ this.priority = priority;
+ if (color != null) {
+ this.fgPainter = new FgPainter(color, bgColor);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 17 * hash + Objects.hashCode(this.bgColor);
+ hash = 17 * hash + Objects.hashCode(this.color);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final LineMarker other = (LineMarker) obj;
+ if (!Objects.equals(this.bgColor, other.bgColor)) {
+ return false;
+ }
+ return (Objects.equals(this.color, other.color));
+ }
+
+ public Color getBgColor() {
+ return bgColor;
+ }
+
+ public Color getColor() {
+ return color;
+ }
+
+ @Override
+ public int compareTo(LineMarker o) {
+ return priority - o.priority;
+ }
+ }
+//(Map>)
+
+ private Map> lineMarkers = Collections.synchronizedMap(new HashMap>());
+
+ public void setLineMarkers(Map> colorMarkers) {
+ this.lineMarkers = colorMarkers;
+ }
+
+ public void clearLineColors() {
+ lineMarkers.clear();
+ repaint();
+ }
+
+ public boolean hasColorMarker(int line, LineMarker lm) {
+ line -= firstLineOffset();
+ if (lineMarkers.containsKey(line)) {
+ return lineMarkers.get(line).contains(lm);
+ }
+ return false;
+ }
+
+ public void removeColorMarker(int line, LineMarker lm) {
+ line -= firstLineOffset();
+ if (lineMarkers.containsKey(line)) {
+ lineMarkers.get(line).remove(lm);
+ }
+ getParent().repaint();
+ }
+
+ public void removeColorMarkerOnAllLines(LineMarker lm) {
+ for (int line : lineMarkers.keySet()) {
+ line += firstLineOffset();
+ removeColorMarker(line, lm);
+ }
+ }
+
+ public int firstLineOffset() {
+ return 0;
+ }
+
+ public void toggleColorMarker(int line, LineMarker lm) {
+ if (!lineMarkers.containsKey(line - firstLineOffset())) {
+ addColorMarker(line, lm);
+ } else if (lineMarkers.get(line - firstLineOffset()).contains(lm)) {
+ removeColorMarker(line, lm);
+ } else {
+ addColorMarker(line, lm);
+ }
+ getParent().repaint();
+ }
+
+ public void addColorMarker(int line, LineMarker lm) {
+ line -= firstLineOffset();
+ if (!lineMarkers.containsKey(line)) {
+ lineMarkers.put(line, Collections.synchronizedSortedSet(new TreeSet<>()));
+ }
+ lineMarkers.get(line).add(lm);
+ getParent().repaint();
+ }
+
+ public int getLine() {
+ int caretPosition = getCaretPosition();
+ Element root = getDocument().getDefaultRootElement();
+ int currentLine = root.getElementIndex(caretPosition);
+ return currentLine;
+ }
+
+ public void markError() {
+ error = true;
+ }
+
+ public void gotoLine(int line) {
+ int pos = ActionUtils.getDocumentPosition(this, line, 0);
+ if (pos != -1) {
+ setCaretPosition(pos);
+ }
+ }
+
+ public void gotoLineCol(int line, int column) {
+ int pos = ActionUtils.getDocumentPosition(this, line, column);
+ if (pos != -1) {
+ setCaretPosition(pos);
+ }
+ }
+
+ public Point getLineLocation(int line) {
+ int pos = ActionUtils.getDocumentPosition(this, line + 1, 0);
+ if (pos < 0) {
+ return null;
+ }
+ try {
+ Rectangle r = modelToView(pos);
+ return new Point(r.x, r.y);
+ } catch (BadLocationException ex) {
+ return null;
+ }
+ }
+
+ private void getLineBounds(int line, Reference lineStart, Reference lineEnd) {
+ Document d = getDocument();
+ String text = "";
+ try {
+ text = d.getText(0, d.getLength());
+ } catch (BadLocationException ex) {
+ //ignore
+ }
+ int lineCnt = 0;
+ int lineStartVal = 0;
+ int lineEndVal = -1;
+ for (int i = 0; i < text.length(); i++) {
+ if (text.charAt(i) == '\n') {
+ lineCnt++;
+ if (lineCnt == line) {
+ lineStartVal = i + 1;
+ }
+ if (lineCnt == line + 1) {
+ lineEndVal = i;
+ }
+ }
+ }
+ if (lineCnt == 0) {
+ lineEndVal = text.length() - 1;
+ if (line > 0) {
+ lineStartVal = text.length() - 1;
+ }
+ }
+ lineEnd.setVal(lineEndVal);
+ lineStart.setVal(lineStartVal);
+ }
+
+ public void selectLine(int line) {
+ Reference lineStart = new Reference<>(0);
+ Reference lineEnd = new Reference<>(0);
+ getLineBounds(line, lineStart, lineEnd);
+
+ select(lineStart.getVal(), lineEnd.getVal());
+ requestFocus();
+ }
+
+ public String getCurrentLineText() {
+ return getLineText(getLine());
+ }
+
+ public String getLineText(int line) {
+ Reference lineStart = new Reference<>(0);
+ Reference lineEnd = new Reference<>(0);
+ getLineBounds(line, lineStart, lineEnd);
+ try {
+ return getDocument().getText(lineStart.getVal(), lineEnd.getVal() - lineStart.getVal());
+ } catch (BadLocationException ex) {
+ return null;
+ }
+ }
+
+ public LineMarkedEditorPane() {
+ setOpaque(false);
+ addCaretListener(new CaretListener() {
+ @Override
+ public void caretUpdate(CaretEvent e) {
+ int caretPosition = getCaretPosition();
+ Element root = getDocument().getDefaultRootElement();
+ int currentLine = root.getElementIndex(caretPosition);
+ if (currentLine != lastLine) {
+ lastLine = currentLine;
+ error = false;
+ repaint();
+ }
+
+ }
+ });
+ final LinkAdapter la = new LinkAdapter();
+ addMouseMotionListener(la);
+ addMouseListener(la);
+
+ //No standard AddKeyListener as we want to catch Ctrl globally no matter of focus
+ KeyboardFocusManager.getCurrentKeyboardFocusManager()
+ .addKeyEventPostProcessor(new KeyEventPostProcessor() {
+ @Override
+ public boolean postProcessKeyEvent(KeyEvent e) {
+ if (e.getID() == KeyEvent.KEY_PRESSED) {
+ la.keyPressed(e);
+ }
+ if (e.getID() == KeyEvent.KEY_RELEASED) {
+ la.keyReleased(e);
+ }
+ if (e.getID() == KeyEvent.KEY_TYPED) {
+ la.keyTyped(e);
+ }
+ return false;
+ }
+ });
+
+ }
+
+ public Token tokenAtPos(Point lastPos) {
+ Document d = getDocument();
+ if (d instanceof SyntaxDocument) {
+ SyntaxDocument sd = (SyntaxDocument) d;
+
+ //correction of token last character
+ int pos = viewToModel(lastPos);
+ Rectangle r;
+ try {
+ r = modelToView(pos);
+ if (r != null) {
+ if (lastPos.x < r.x) {
+ pos--;
+ }
+ }
+ } catch (BadLocationException ex) {
+ //ignore
+ }
+ Token t = sd.getTokenAt(pos);
+
+ //Correction of token of length 1 character
+ if (pos > 0 && pos < d.getLength() - 1 && t != null && t.length == 1) {
+ Token tprev = sd.getTokenAt(pos - 1);
+ if (tprev == t) {
+ t = sd.getTokenAt(pos + 1);
+ }
+ }
+
+ return t;
+ }
+ return null;
+ }
+
+ private class LinkAdapter extends MouseAdapter implements KeyListener {
+
+ private Point lastPos = new Point(0, 0);
+
+ private boolean ctrlDown = false;
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
+ ctrlDown = true;
+ update();
+ }
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ if (e.getKeyCode() == KeyEvent.VK_CONTROL) {
+ ctrlDown = false;
+ update();
+ }
+ }
+
+ private void update() {
+ if (ctrlDown) {
+ Token t = tokenAtPos(lastPos);
+
+ if (t != lastUnderlined) {
+ if (t == null || lastUnderlined == null || !t.equals(lastUnderlined)) {
+ MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter);
+
+ if (t != null && linkHandler.isLink(t)) {
+ lastUnderlined = t;
+ setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+
+ } else {
+ lastUnderlined = null;
+ }
+ } else {
+ lastUnderlined = null;
+ }
+ }
+
+ if (lastUnderlined != null) {
+ MyMarkers.markToken(LineMarkedEditorPane.this, lastUnderlined, underLinePainter);
+ } else {
+ setCursor(Cursor.getDefaultCursor());
+ }
+ repaint();
+ } else {
+ lastUnderlined = null;
+ MyMarkers.removeMarkers(LineMarkedEditorPane.this, underLinePainter);
+ setCursor(Cursor.getDefaultCursor());
+ repaint();
+ }
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (ctrlDown) {
+ Token t = tokenAtPos(lastPos);
+ if (t != null && linkHandler.isLink(t)) {
+ linkHandler.handleLink(t);
+ }
+ }
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+
+ ctrlDown = (e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0;
+ lastPos = e.getPoint();
+ update();
+
+ }
+ }
+
+ public void setLinkHandler(LinkHandler linkHandler) {
+ if (linkHandler == null) {
+ linkHandler = this;
+ }
+ this.linkHandler = linkHandler;
+ }
+
+ public LinkHandler getLinkHandler() {
+ return linkHandler;
+ }
+
+ @Override
+ public HighlightPainter linkPainter() {
+ return underLinePainter;
+ }
+
+ @Override
+ public boolean isLink(Token token) {
+ return false;
+ }
+
+ @Override
+ public void handleLink(Token token) {
+
+ }
+
+ @Override
+ public void setText(String t) {
+ this.lineMarkers = new HashMap<>();
+ lastLine = -1;
+ error = false;
+ if (Configuration._debugMode.get() && t != null && t.length() > truncateLimit) {
+ t = t.substring(0, truncateLimit) + "\r\n" + AppStrings.translate("editorTruncateWarning").replace("%chars%", Integer.toString(truncateLimit));
+ }
+
+ super.setText(t);
+ setCaretPosition(0); //scroll to top
+ }
+
+ public static class FgPainter extends DefaultHighlighter.DefaultHighlightPainter {
+
+ private final SyntaxStyle fgStyle;
+
+ public FgPainter(Color color, Color bgColor) {
+ super(bgColor);
+ this.fgStyle = new SyntaxStyle(color, false, false);
+ }
+
+ @Override
+ public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
+ try {
+ // --- determine locations ---
+ TextUI mapper = c.getUI();
+
+ Segment seg = new Segment();
+ ((SyntaxDocument) c.getDocument()).getText(offs0, offs1 - offs0, seg);
+
+ Rectangle r = mapper.modelToView(c, offs0, Position.Bias.Forward);
+ FontMetrics fm = g.getFontMetrics();
+ //int fh = fm.getHeight();
+ fgStyle.drawText(seg, r.x, r.y + fm.getAscent(), g, null, offs0);
+ /*for (int i = offs0; i < offs1; i++) {
+
+ Rectangle r = mapper.modelToView(c, i, Position.Bias.Forward);
+ Rectangle r1 = mapper.modelToView(c, i + 1, Position.Bias.Forward);
+ if (r1.y == r.y) {
+ ((SyntaxDocument) c.getDocument()).getText(i, 1, seg);
+ fgStyle.drawText(seg, r.x, r.y, g, null, i);
+ //g.drawLine(r.x, r.y + r.height - 3, r1.x, r.y + r.height - 3);
+ }
+ }*/
+
+ } catch (BadLocationException e) {
+ // can't render
+ }
+ }
+
+ @Override
+ public Shape paintLayer(Graphics g, int offs0, int offs1,
+ Shape bounds, JTextComponent c, View view) {
+
+ g.setColor(c.getSelectionColor());
+
+ Rectangle r;
+
+ if (offs0 == view.getStartOffset()
+ && offs1 == view.getEndOffset()) {
+ // Contained in view, can just use bounds.
+ if (bounds instanceof Rectangle) {
+ r = (Rectangle) bounds;
+ } else {
+ r = bounds.getBounds();
+ }
+ } else {
+ // Should only render part of View.
+ try {
+ // --- determine locations ---
+ Shape shape = view.modelToView(offs0, Position.Bias.Forward,
+ offs1, Position.Bias.Backward,
+ bounds);
+ r = (shape instanceof Rectangle)
+ ? (Rectangle) shape : shape.getBounds();
+ } catch (BadLocationException e) {
+ // can't render
+ r = null;
+ }
+ }
+
+ if (r != null) {
+ r.width = Math.max(r.width, 1);
+
+ paint(g, offs0, offs1, r, c);
+ }
+
+ return r;
+ }
+ }
+
+ public static class UnderLinePainter extends DefaultHighlighter.DefaultHighlightPainter {
+
+ public UnderLinePainter(Color color) {
+ super(color);
+ }
+
+ @Override
+ public void paint(Graphics g, int offs0, int offs1, Shape bounds, JTextComponent c) {
+ try {
+ // --- determine locations ---
+ TextUI mapper = c.getUI();
+
+ Color col = getColor();
+ if (col == null) {
+ col = Color.black;
+ }
+ g.setColor(col);
+ for (int i = offs0; i < offs1; i++) {
+
+ Rectangle r = mapper.modelToView(c, i, Position.Bias.Forward);
+ Rectangle r1 = mapper.modelToView(c, i + 1, Position.Bias.Forward);
+ if (r1.y == r.y) {
+ g.drawLine(r.x, r.y + r.height - 3, r1.x, r.y + r.height - 3);
+ }
+ }
+
+ } catch (BadLocationException e) {
+ // can't render
+ }
+ }
+
+ @Override
+ public Shape paintLayer(Graphics g, int offs0, int offs1,
+ Shape bounds, JTextComponent c, View view) {
+
+ g.setColor(c.getSelectionColor());
+
+ Rectangle r;
+
+ if (offs0 == view.getStartOffset()
+ && offs1 == view.getEndOffset()) {
+ // Contained in view, can just use bounds.
+ if (bounds instanceof Rectangle) {
+ r = (Rectangle) bounds;
+ } else {
+ r = bounds.getBounds();
+ }
+ } else {
+ // Should only render part of View.
+ try {
+ // --- determine locations ---
+ Shape shape = view.modelToView(offs0, Position.Bias.Forward,
+ offs1, Position.Bias.Backward,
+ bounds);
+ r = (shape instanceof Rectangle)
+ ? (Rectangle) shape : shape.getBounds();
+ } catch (BadLocationException e) {
+ // can't render
+ r = null;
+ }
+ }
+
+ if (r != null) {
+ r.width = Math.max(r.width, 1);
+
+ paint(g, offs0, offs1, r, c);
+
+ }
+
+ return r;
+ }
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ g.setColor(Color.white);
+ g.fillRect(0, 0, getWidth(), getHeight());
+ FontMetrics fontMetrics = g.getFontMetrics();
+ int lh = fontMetrics.getHeight();
+ int d = fontMetrics.getDescent();
+
+ if (lastLine > 0) {
+ if (error) {
+ g.setColor(BG_ERROR_LINE);
+ } else {
+ g.setColor(BG_SELECTED_LINE);
+ }
+ g.fillRect(0, d + lh * lastLine - 1, getWidth(), lh);
+ }
+ for (int line : lineMarkers.keySet()) {
+ SortedSet cs = lineMarkers.get(line);
+ if (cs.isEmpty()) {
+ continue;
+ }
+ LineMarker lastMarker = cs.first();
+ if (lastMarker.getBgColor() == null) {
+ continue;
+ }
+ g.setColor(lastMarker.getBgColor());
+ line += firstLineOffset();
+ g.fillRect(0, d + lh * (line - 1), getWidth(), lh);
+ }
+ super.paint(g);
+ for (int line : lineMarkers.keySet()) {
+
+ SortedSet cs = lineMarkers.get(line);
+ if (cs.isEmpty()) {
+ continue;
+ }
+ line += firstLineOffset();
+
+ Reference lineStart = new Reference<>(0);
+ Reference lineEnd = new Reference<>(0);
+
+ getLineBounds(line, lineStart, lineEnd);
+ FgPainter fgp = cs.first().getForegroundPainter();
+ if (fgp != null) {
+ fgp.paint(g, lineStart.getVal(), lineEnd.getVal(), null, this);
+ }
+ }
+ }
+}