diff --git a/automation/automation-lua.txt b/automation/auto3/automation-lua.txt
similarity index 100%
rename from automation/automation-lua.txt
rename to automation/auto3/automation-lua.txt
diff --git a/automation/demos/1-minimal.lua b/automation/auto3/demos/1-minimal.lua
similarity index 100%
rename from automation/demos/1-minimal.lua
rename to automation/auto3/demos/1-minimal.lua
diff --git a/automation/demos/10-furigana.ass b/automation/auto3/demos/10-furigana.ass
similarity index 100%
rename from automation/demos/10-furigana.ass
rename to automation/auto3/demos/10-furigana.ass
diff --git a/automation/demos/10-furigana.lua b/automation/auto3/demos/10-furigana.lua
similarity index 100%
rename from automation/demos/10-furigana.lua
rename to automation/auto3/demos/10-furigana.lua
diff --git a/automation/demos/2-dump.lua b/automation/auto3/demos/2-dump.lua
similarity index 100%
rename from automation/demos/2-dump.lua
rename to automation/auto3/demos/2-dump.lua
diff --git a/automation/demos/3-include.lua b/automation/auto3/demos/3-include.lua
similarity index 100%
rename from automation/demos/3-include.lua
rename to automation/auto3/demos/3-include.lua
diff --git a/automation/demos/4-text_extents.lua b/automation/auto3/demos/4-text_extents.lua
similarity index 100%
rename from automation/demos/4-text_extents.lua
rename to automation/auto3/demos/4-text_extents.lua
diff --git a/automation/demos/5-configuration.lua b/automation/auto3/demos/5-configuration.lua
similarity index 100%
rename from automation/demos/5-configuration.lua
rename to automation/auto3/demos/5-configuration.lua
diff --git a/automation/demos/6-simple-effect.lua b/automation/auto3/demos/6-simple-effect.lua
similarity index 100%
rename from automation/demos/6-simple-effect.lua
rename to automation/auto3/demos/6-simple-effect.lua
diff --git a/automation/demos/7-advanced-effect.lua b/automation/auto3/demos/7-advanced-effect.lua
similarity index 100%
rename from automation/demos/7-advanced-effect.lua
rename to automation/auto3/demos/7-advanced-effect.lua
diff --git a/automation/demos/8-skeleton.lua b/automation/auto3/demos/8-skeleton.lua
similarity index 100%
rename from automation/demos/8-skeleton.lua
rename to automation/auto3/demos/8-skeleton.lua
diff --git a/automation/demos/9-advanced-skeleton.lua b/automation/auto3/demos/9-advanced-skeleton.lua
similarity index 100%
rename from automation/demos/9-advanced-skeleton.lua
rename to automation/auto3/demos/9-advanced-skeleton.lua
diff --git a/automation/demos/readme.txt b/automation/auto3/demos/readme.txt
similarity index 100%
rename from automation/demos/readme.txt
rename to automation/auto3/demos/readme.txt
diff --git a/automation/factorybrew/line-per-syllable.lua b/automation/auto3/factorybrew/line-per-syllable.lua
similarity index 100%
rename from automation/factorybrew/line-per-syllable.lua
rename to automation/auto3/factorybrew/line-per-syllable.lua
diff --git a/automation/factorybrew/multi-template.lua b/automation/auto3/factorybrew/multi-template.lua
similarity index 100%
rename from automation/factorybrew/multi-template.lua
rename to automation/auto3/factorybrew/multi-template.lua
diff --git a/automation/factorybrew/readme.txt b/automation/auto3/factorybrew/readme.txt
similarity index 100%
rename from automation/factorybrew/readme.txt
rename to automation/auto3/factorybrew/readme.txt
diff --git a/automation/factorybrew/simple-k-replacer.lua b/automation/auto3/factorybrew/simple-k-replacer.lua
similarity index 100%
rename from automation/factorybrew/simple-k-replacer.lua
rename to automation/auto3/factorybrew/simple-k-replacer.lua
diff --git a/automation/include/karaskel-adv.lua b/automation/auto3/include/karaskel-adv.lua
similarity index 100%
rename from automation/include/karaskel-adv.lua
rename to automation/auto3/include/karaskel-adv.lua
diff --git a/automation/include/karaskel-base.lua b/automation/auto3/include/karaskel-base.lua
similarity index 100%
rename from automation/include/karaskel-base.lua
rename to automation/auto3/include/karaskel-base.lua
diff --git a/automation/include/karaskel.lua b/automation/auto3/include/karaskel.lua
similarity index 100%
rename from automation/include/karaskel.lua
rename to automation/auto3/include/karaskel.lua
diff --git a/automation/include/readme.txt b/automation/auto3/include/readme.txt
similarity index 100%
rename from automation/include/readme.txt
rename to automation/auto3/include/readme.txt
diff --git a/automation/include/utils.lua b/automation/auto3/include/utils.lua
similarity index 100%
rename from automation/include/utils.lua
rename to automation/auto3/include/utils.lua
diff --git a/automation/autoload/test1.lua b/automation/autoload/test1.lua
new file mode 100644
index 000000000..ba50becaf
--- /dev/null
+++ b/automation/autoload/test1.lua
@@ -0,0 +1,15 @@
+-- Automation 4 test file
+-- Create a Macro feature, that displays some text
+
+script_name = "Automation 4 test 1"
+script_description = "Hello World in Automation 4/Lua"
+script_author = "Niels Martin Hansen"
+script_version = "1"
+
+
+function macro_test1(subtitles, selected_lines, active_line)
+ --aegisub.debug.out(3, "Hello World from %s", "Automation 4/Lua")
+ aegisub.debug.out("Hello Automation 4 World!")
+end
+
+aegisub.register_macro("Hello", "Shows a message", "tools", macro_test1)
diff --git a/automation/autoload/test2.lua b/automation/autoload/test2.lua
new file mode 100644
index 000000000..87ae52026
--- /dev/null
+++ b/automation/autoload/test2.lua
@@ -0,0 +1,50 @@
+-- Automation 4 test file
+-- Create a Macro feature, that displays some text
+
+script_name = "Automation 4 test 2"
+script_description = "Some additional non-hello-world tests"
+script_author = "Niels Martin Hansen"
+script_version = "2"
+
+
+function macro_test2(subtitles, selected_lines, active_line)
+ aegisub.debug.out(subtitles.n .. " and " .. #subtitles .. " should be the same value")
+ aegisub.debug.out(subtitles[selected_lines[1]].raw)
+end
+
+function dumper(subtitles, selected_lines, active_line)
+ for i = 1, #subtitles do
+ local l = subtitles[i]
+ local s = l.raw .. "\n"
+ s = s .. l.class .. "\n"
+ if l.class == "comment" then
+ s = s .. "text: " .. l.text .. "\n"
+ elseif l.class == "info" then
+ s = s .. string.format("key: %s\nvalue:%s\n", l.key, l.value)
+ elseif l.class == "format" then
+ -- skip
+ elseif l.class == "style" then
+ s = s .. string.format("name: %s\nfont: %s %d\ncolors: %s %s %s %s\n", l.name, l.fontname, l.fontsize, l.color1, l.color2, l.color3, l.color4)
+ elseif l.class == "dialogue" then
+ s = s .. string.format("layer: %d\nstyle: %s\ntext: %s\n", l.layer, l.style, l.text)
+ end
+ aegisub.debug.out(s)
+ end
+end
+
+function inserttest(subtitles, selected_lines, active_line)
+ local lid = selected_lines[1]
+ subtitles[-lid] = subtitles[lid]
+ subtitles[0] = subtitles[lid]
+ local l = subtitles[lid]
+ l.text = "A4 was here!"
+ subtitles[lid] = l
+ aegisub.set_undo_point("Insert Stuff")
+end
+
+
+aegisub.register_macro("File line count", "Count the number of lines in the ASS file", "tools", macro_test2, nil)
+
+aegisub.register_macro("Dump", "Dumps info on every line in the file", "tools", dumper, nil)
+
+aegisub.register_macro("Insert stuff", "Inserts some lines near the active line", "edit", inserttest, nil)
diff --git a/automation/autoload/test3.lua b/automation/autoload/test3.lua
new file mode 100644
index 000000000..af3bcca34
--- /dev/null
+++ b/automation/autoload/test3.lua
@@ -0,0 +1,33 @@
+-- Automation 4 test file
+-- Create a Macro feature, that displays some text
+
+script_name = "Automation 4 test 3"
+script_description = "Test parse_karaoke_data"
+script_author = "Niels Martin Hansen"
+script_version = "1"
+
+
+function copy_table(tab)
+ local res = {}
+ for key, val in pairs(tab) do
+ res[key] = val
+ end
+ return res
+end
+
+function karatest(subtitles, selected_lines, active_line)
+ for i = #selected_lines, 1, -1 do
+ local ri = selected_lines[i]
+ local l = subtitles[ri]
+ local k = aegisub.parse_karaoke_data(l)
+ for j = 1, #k do
+ local nl = copy_table(l)
+ l.text = string.format("{\\t(%d,%d,\\fscx50)}%s", k[j].start_time, k[j].end_time, k[j].text_stripped)
+ subtitles.insert(ri+j, l)
+ end
+ end
+ aegisub.set_undo_point("karaoke-like stuff")
+end
+
+
+aegisub.register_macro("Karaoke fun", "Makes karaoke-like stuff", "edit", karatest, nil)
diff --git a/automation/autoload/test4.lua b/automation/autoload/test4.lua
new file mode 100644
index 000000000..e55f678d9
--- /dev/null
+++ b/automation/autoload/test4.lua
@@ -0,0 +1,40 @@
+-- Automation 4 test file
+-- Create a Macro feature, that displays some text
+
+script_name = "Automation 4 test 4"
+script_description = "Test progress reporting"
+script_author = "Niels Martin Hansen"
+script_version = "1"
+
+
+function wait()
+ local s = ""
+ for i = 0, 500 do
+ s = s .. i
+ end
+ return s
+end
+
+function progression(subtitles, selected_lines, active_line)
+ while not aegisub.progress.is_cancelled() do
+ aegisub.progress.task("Counting up...")
+ for i = 0, 100, 0.2 do
+ aegisub.progress.set(i)
+ if aegisub.progress.is_cancelled() then
+ break
+ end
+ wait()
+ end
+ if aegisub.progress.is_cancelled() then
+ break
+ end
+ aegisub.progress.task("Counting down...")
+ for i = 0, 100 do
+ aegisub.progress.set(100-i)
+ wait()
+ end
+ end
+end
+
+
+aegisub.register_macro("Progress fun", "Does absolutely nothing", "video", progression, nil)
diff --git a/automation/autoload/test5.lua b/automation/autoload/test5.lua
new file mode 100644
index 000000000..fb29b53e8
--- /dev/null
+++ b/automation/autoload/test5.lua
@@ -0,0 +1,40 @@
+-- Automation 4 test file
+-- Create a Macro feature, that displays some text
+
+script_name = "Automation 4 test 5"
+script_description = "Test include and text_extents"
+script_author = "Niels Martin Hansen"
+script_version = "1"
+
+include("utils.lua")
+
+
+function test5(subtitles, selected_lines, active_line)
+ local styles = {}
+ for i = 1, #subtitles do
+ local l = subtitles[i]
+ if l.class == "dialogue" then
+ break
+ end
+ if l.class == "style" then
+ styles[l.name] = l
+ end
+ end
+
+ for i = #selected_lines, 1, -1 do
+ local ri = selected_lines[i]
+ local l = subtitles[ri]
+ local k = aegisub.parse_karaoke_data(l)
+ local left = 0
+ for j = 1, #k do
+ local nl = table.copy(l)
+ l.text = string.format("{\\t(%d,%d,\\fscx50)\\pos(%d,20)}%s", k[j].start_time, k[j].end_time, left, k[j].text_stripped)
+ left = left + (aegisub.text_extents(styles[l.style], k[j].text_stripped))
+ subtitles.insert(ri+j, l)
+ end
+ end
+ aegisub.set_undo_point("karaoke-like stuff")
+end
+
+
+aegisub.register_macro("More karaoke fun", "Makes some more karaoke-like stuff", "tools", test5, nil)
diff --git a/automation/autoload/test6.lua b/automation/autoload/test6.lua
new file mode 100644
index 000000000..997d68a9a
--- /dev/null
+++ b/automation/autoload/test6.lua
@@ -0,0 +1,82 @@
+-- Automation 4 test file
+-- Create a Filter feature that does some kara stuff
+
+script_name = "Automation 4 test 6"
+script_description = "Test basic export filters"
+script_author = "Niels Martin Hansen"
+script_version = "1"
+
+include("utils.lua")
+
+
+function test6_2(subtitles, config)
+ --[[for i = 1, #subtitles do
+ local l = subtitles[i]
+ if l.class == "dialogue" then
+ local nl = table.copy(l)
+ nl.text = "Copied!"
+ subtitles.insert(i, nl)
+ break
+ end
+ end]]
+end
+
+
+function test6(subtitles, config)
+ aegisub.progress.task("Collecting style data")
+ local styles = {}
+ for i = 1, #subtitles do
+ aegisub.debug.out("finding styles, line " .. i)
+ local l = subtitles[i]
+ if l.class == "dialogue" then
+ break
+ end
+ if l.class == "style" then
+ aegisub.debug.out(" found style: " .. l.name)
+ styles[l.name] = l
+ end
+ aegisub.progress.set(100 * i / #subtitles)
+ end
+
+ local res = {}
+
+ local i = 1
+ while i <= #subtitles do
+ aegisub.debug.out("producing effect, line " .. i)
+ local l = subtitles[i]
+ if l.class == "dialogue" then
+ aegisub.debug.out(" found dialogue: " .. l.text)
+ local res = {}
+ do_line(styles, l, config, res)
+ aegisub.debug.out(" lines returned by do_line: " .. #res)
+ for j,nl in ipairs(res) do
+ subtitles.insert(i+j, nl)
+ end
+ aegisub.debug.out(" done inserting generated lines")
+ subtitles.delete(i)
+ i = i + #res
+ else
+ aegisub.debug.out(" not dialogue")
+ i = i + 1
+ end
+ aegisub.progress.task(string.format("Producing effect (%d/%d)", i, #subtitles))
+ aegisub.progress.set(100 * i / #subtitles)
+ end
+end
+
+function do_line(styles, line, config, res)
+ local k = aegisub.parse_karaoke_data(line)
+ aegisub.debug.out(" syllables generated from line: " .. #k)
+ local left = 0
+ for j = 1, #k do
+ aegisub.debug.out(" syllable " .. j .. " is: " .. k[j].text)
+ local nl = table.copy(line)
+ nl.text = string.format("{\\t(%d,%d,\\fscx50)\\pos(%d,20)}%s", k[j].start_time, k[j].end_time, left, k[j].text_stripped)
+ left = left + (aegisub.text_extents(styles[nl.style], k[j].text_stripped))
+ table.insert(res, nl)
+ end
+end
+
+
+aegisub.register_filter("Stupid karaoke", "Makes some more karaoke-like stuff", 2000, test6, nil)
+aegisub.register_filter("Lame test", "Simple test of filters, just inserting a new line", 2000, test6_2)
diff --git a/automation/autoload/test7.lua b/automation/autoload/test7.lua
new file mode 100644
index 000000000..5fa4e2448
--- /dev/null
+++ b/automation/autoload/test7.lua
@@ -0,0 +1,92 @@
+-- Automation 4 test file
+-- Create a Filter feature that does some kara stuff
+
+script_name = "Automation 4 test 7"
+script_description = "Test config dialogs"
+script_author = "Niels Martin Hansen"
+script_version = "1"
+
+include("utils.lua")
+
+function test7(subtitles, selected_lines, active_line)
+ local a, b = aegisub.dialog.display({{class="label", label="Test..."}}, {})
+ report_dialog_result(a, b)
+ aegisub.progress.set(50)
+ a, b = aegisub.dialog.display({{class="edit", name="foo", text=""}}, {"foo", "bar"})
+ report_dialog_result(a, b)
+end
+
+function report_dialog_result(button, controls)
+ aegisub.debug.out("Dialog closed: ")
+ if button == false then
+ aegisub.debug.out("cancelled\n")
+ elseif button == true then
+ aegisub.debug.out("clicked Ok\n")
+ else
+ aegisub.debug.out("clicked '" .. button .. "'\n")
+ end
+ for key, val in pairs(controls) do
+ aegisub.debug.out(key .. ': ' .. val .. '\n')
+ end
+ aegisub.debug.out(" - - - - -\n")
+end
+
+
+function exporter(subs, config)
+ for i = 1, #subs do
+ local l = subs[i]
+ if l.class == "dialogue" and not l.comment then
+ if config.style == "" or l.style == config.style then
+ l.text = config.text .. l.text
+ subs[i] = l
+ end
+ end
+ end
+end
+
+function export_config_dialog(subs, store)
+ local styles = {""}
+ for i = 1, #subs do
+ local l = subs[i]
+ if l.class == "style" then
+ table.insert(styles, l.name)
+ end
+ end
+
+ return {
+ {
+ class = "label",
+ label = "This will insert a given text in\n" ..
+ "front of all dialogue lines of\n" ..
+ "the given style, or every line\n" ..
+ "if no specific style is selected.",
+ x = 0, y = 0, width = 2, height = 1
+ },
+ {
+ class = "label",
+ label = "Text to insert:",
+ x = 0, y = 1, width = 1, height = 1
+ },
+ {
+ class = "edit",
+ name = "text",
+ x = 1, y = 1, width = 1, height = 1
+ },
+ {
+ class = "label",
+ label = "Style to apply on:",
+ x = 0, y = 2, width = 1, height = 1
+ },
+ {
+ class = "dropdown",
+ name = "style",
+ value = "",
+ items = styles,
+ x = 1, y = 2, width = 1, height = 1
+ }
+ }
+end
+
+
+aegisub.register_macro("Config Dialog 1", "Show a stupid config dialog", "video", test7, nil)
+aegisub.register_filter("Export Config", "Test export filter config dialog stuff", 500, exporter, export_config_dialog)
diff --git a/automation/v4-docs/basic-function-interface.txt b/automation/v4-docs/basic-function-interface.txt
deleted file mode 100644
index 0d11b8acd..000000000
--- a/automation/v4-docs/basic-function-interface.txt
+++ /dev/null
@@ -1,351 +0,0 @@
-Automation 4 Basic Interface
-
-This document described the basic functions needed to define an Automation 4
-script. This covers Feature registration and the prototypes of functions used
-to implement the various features.
-
----
-
-Macro Registation Function
-
-This is a function called from top-level of an Automation script to register
-a new Macro Feature.
-
-function aegisub.register_macro(
- name,
- description,
- menu,
- processing_function,
- validation_function)
-
-@name (string)
- The displayed name of the menu item this macro will generate.
-
-@description (string)
- A longer description of the function of this macro. This will appear
- on the status bar when hovering over the menu item.
-
-@menu (string)
- The menu this macro will appear in. Must be one of:
- o "edit"
- o "video"
- o "audio"
- o "tools"
- o "right" (the subtitles grid right-click menu)
- The menu chosen should be relevant to the function of the macro.
-
-@processing_function (function)
- The actual function called for the macro execution.
- This function must be an instance of the Macro Processing Function
- described below.
-
-@validation_function (function)
- Optional. A function called when it is to be determined whether the
- macro can act on the current subtitles.
- This function, if provided, must execute very quickly to avoid lag
- in the GUI.
- This function must be an instance of the Macro Validation Function
- described below.
-
-Returns: nothing.
-
----
-
-Filter Registration Function
-
-This is a function called from top level of an Automation script to register
-a new Export Filter Feature.
-
-function aegisub.register_filter(
- name,
- description,
- priority,
- processing_function,
- options_window_provider)
-
-@name (string)
- The name of the filter, as presented to the user.
-
-@description (string)
- A longer description of the filter presented to the user.
-
-@priority (number)
- A number determining the default order the enabled filters will be
- processed. The order can be overridden by the user.
- Priorities of some built-in filters:
- o Clean Script Info = 0
- o Fix Styles = -5000
- o Transform Framerate = 1000
- Filters with higher priority will be executed earlier by default.
-
-@processing_function (function)
- The function called to do the actual filter processing.
- This function must be an instance of the Filter Processing Function
- described below.
-
-@options_window_provider (function)
- Optional. A function providing a dialog template for setting options
- prior to filter processing.
- This function must be an instance of the Filter Options Window Provider
- function described below.
-
-Returns: nothing.
-
----
-
-Format Reader Registration
-
-This is a function called from top level in an Automation script to register
-a new File Format Reader Feature.
-
-function aegisub.register_reader(
- name,
- extension,
- is_text_format,
- processing_function)
-
-@name (string)
- The name of the file format.
-
-@extension (string)
- The file extension usually given to this file format. This must not
- include any wildcards. (Ie. extension could be "srt", "sub", "ssa" and
- so on.)
-
-@is_text_format (boolean)
- Determines whether the user can select a default encoding for reading text
- from the file. This only affects whether a default encoding is chosen or not,
- even with this argument set to false, you can still read text. You should set
- this to true, if the format allows storing in different encodings, and doesn't
- explicitly store the used encoding anywhere.
-
-@processing_function (function)
- The function called to do the actual file import.
- This function must be an instance of the Format Reader Function described
- below.
-
-Returns: nothing.
-
----
-
-Format Writer Registration
-
-This is a function called from top level in an Automation script to register
-a new File Format Writer Feature.
-
-function aegisub.register_writer(
- name,
- extension,
- is_text_format,
- processing_function)
-
-@name (string)
- Name of the file format, as presented to the user.
-
-@extension (string)
- The usual file extension given to this file format. This is automatically
- be attached to the file name on export, unless the user chooses to
- override it.
-
-@is_text_format (boolean)
- Determines whether the user can select a target encoding or not. This
- option should be true if the format written allows choosing between
- different encodings, and the user should be able to select which one to
- use. This option doesn't affect whether you can write text to the file or
- not, but only whether the user can select an encoding or not.
-
-@processing_function (function)
- The function doing the actual file export.
- This function must be an instance of the Format Writer Function described
- below.
-
-Returns: nothing.
-
----
-
-Macro Processing Function
-
-This function is called by Aegisub to execute a macro.
-
-function process_macro(
- subtitles,
- selected_lines,
- active_line)
-
-The name of the function is script-defined. (It doesn't have to be
-process_macro.)
-
-@subtitles (user data)
- A Subtitles Object, that can be used to retrieve information about the
- subtitle file the macro is being applied on.
-
-@selected_lines (table)
- An Array Table of numbers, each entry being an index into the file
- represented by @subtitles. Each of the entries in this table describe that
- a line is marked as selected by the user.
-
-@active_line (number)
- Index of the currently active line in the subtitle file.
-
-Returns: nothing.
-
----
-
-Macro Validation Function
-
-This function is called by Aegisub to determine whether a macro can be applied
-to the current state of the subtitles and selection.
-
-This function needs to execute very fast, since it may be called for several
-macros whenever a menu is opened. It is suggested not to use @subtitles at all
-in this function.
-
-This function does not have to be defined. If it's undefined, it's taken as if
-it always returned true.
-
-function validate_macro(
- subtitles,
- selected_lines,
- active_line)
-
-The name of the function is script-defined. (It doesn't have to be
-validate_macro.)
-
-@subtitles (user data)
- A Subtitles Object, that can be used to retrieve information about the
- subtitle file the macro is to be be applied on.
-
-@selected_lines (table)
- An Array Table of numbers, each entry being an index into the file
- represented by @subtitles. Each of the entries in this table describe that
- a line is marked as selected by the user.
-
-@active_line (number)
- Index of the currently active line in the subtitle file.
-
-Returns: Boolean.
- true is the macro can be applied to the current state of the subtitles,
- false if not.
-
----
-
-Filter Processing Function
-
-This function is called by Aegisub to filter the subtitles during an export
-operation.
-
-function process_filter(
- subtitles,
- config)
-
-The name of the function is script-defined. (It doesn't have to be
-process_filter.)
-
-@subtitles (user data)
- A Subtitles Object, that can be used to retrieve information about the
- subtitle file the filter is being applied on.
-
-@config (table)
- A Dialog Result table representing the options the user selected for the
- filter before starting the export operation. The fields present in this
- table are defined by the dialog provided by the Filter Options Window
- Provider function.
-
-Returns: nothing.
-
----
-
-Filter Options Window Provider function
-
-This function is called by Aegisub to get a Dialog Window definition to prompt
-the user for input before an export operation.
-The data input into the dialog returned by this function are automatically
-stored into the original subtitle file when an export operation is started.
-
-function filter_options_dialog(
- subtitles,
- stored_options)
-
-The name of the function is script-defined. (It doesn't have to be
-filter_options_dialog.)
-
-@subtitles (user data)
- A Subtitles Object, that can be used to retrieve information about the
- subtitle file the filter is to be applied on.
-
-@stored_options (table)
- The currently stored options for this export filter. The keys in this table
- are the option names, and the values are the values stored for those options.
-
-Returns: A Dialog Window table.
-
----
-
-Format Reader Function
-
-This function is called by Aegisub to import a file from a foreign file
-format.
-
-function read_format(
- input_file,
- output_subs)
-
-The name of the function is script-defined. (It doesn't have to be
-read_format.)
-
-@input_file (user data)
- An Input File Stream, representing the file selected for import.
-
-@output_subs (user data)
- An empty Subtitles Object the imported data should be added to.
-
-Returns: Boolean.
- True if the import succeeded, false if it failed.
-
----
-
-Format Writer Function
-
-This function is called by Aegisub to export a file to a foreign file format.
-
-function write_format(
- input_subs,
- output_file)
-
-The name of the function is script-defined. (It doesn't have to be
-write_format.)
-
-@input_subs (user data)
- A Subtitles Object representing the subtitles to be exported.
-
-@output_file (user data)
- An Ouput File Stream, representing the file the exported data should be
- written to.
-
-Returns: Boolean.
- True if the export succeeded, false if it failed.
- If this function returns false, the output file is deleted from disk.
-
----
-
-Script information globals
-
-These are a series of global variables, the script author can set. They are
-purely informational, and won't have any actual influence on how the script
-is treated.
-
-script_name (string)
- A short, descriptive name for the script, used for presenting it to the
- user in the UI.
-
-script_description (string)
- A longer description of the purpose of the script, presented to the user
- in the UI.
-
-script_author (string)
- Name(s) of the author(s) of the script.
-
-script_version (string)
- Version number of the script.
-
----
diff --git a/automation/v4-docs/configuration-dialogs.txt b/automation/v4-docs/configuration-dialogs.txt
deleted file mode 100644
index 4cd7e9b10..000000000
--- a/automation/v4-docs/configuration-dialogs.txt
+++ /dev/null
@@ -1,180 +0,0 @@
-Automation 4 Configuration Dialog interface
-
-This file describes the functions and data structures used for the
-Configuration Dialog functionality in Automation 4.
-
----
-
-Dialog Control table format
-
-A Dialog Control table describes a single control in a configuration dialog,
-which can display information to the user and allow them to change it.
-
-There are a number of different classes of controls, and the keys a Dialog
-Control table must contain depends on the control class.
-
-
-Common keys for all control classes:
-
-class (string)
- Defines which class this control has. Must be one of:
- "label",
- "edit", "intedit", "floatedit", "textbox",
- "dropdown",
- "checkbox",
- "color", "coloralpha", "alpha"
-
-name (string)
- A name that uniquely identifies the control. This is recommended to be a
- string easily used as an identifier in Lua, since it will be used to access
- the value input into the control.
-
-x (number)
-y (number)
-width (number)
-height (number)
- Determines the position and size of the control in the dialog. These values
- are used to create a grid containing the controls. They should all be
- integer. The top left corner is x,y=0,0.
- If any of width and height are set to zero or less, it will be set to one
- instead.
-
-
-Key defined for all classes except "label":
-
-hint (string)
- A string displayed to the
-
-
-Keys defined only for "label" and "checkbox" classes:
-
-label (string)
- The text displayed to the user on the control.
-
-
-Key defined only for the "edit" and "textbox" classes:
-
-text (string)
- The contents of the control when the dialog is first displayed.
- This can contain newlines if the control is of the "textbox" class.
-
-
-Keys defined only for the "intedit" and "floatedit" classes:
-
-value (number)
- The value in the control when the dialog is first displayed. For the
- "intedit" class, if this is a non-integer point number it is truncated
- before being used.
-
-min (number or nil)
-max (number or nil)
-step (number or nil)
- If one of these are nil, the other must also be nil. (Ie. undefined.)
- If all are present, the control gets a spin button, the user can click to
- update the value of the control. The value is changed by "step" amount
- every time, up to "max" or down to "min". The user won't be able to close
- the dialog if the value is outside the range between "min" and "max" either.
-
-
-Keys defined only for the "dropdown" class:
-
-items (table)
- This is an Array Table containing only strings. They are used for the
- options displayed to the user in the dropdown box.
- All strings in the array table should be unique. (There is not way to
- distinguish non-unique strings from each other.)
-
-value (string)
- Determines which item is selected when the dialog id first displayed. If
- this is not one of the items specified, no item is selected. This is case-
- sensitive.
-
-
-Key defined only for the "checkbox" class:
-
-value (boolean)
- Determines whether the checkbox is checked or not when the dialog is first
- displayed.
-
-
-Keys defined only for the "color", "coloralpha" and "alpha" classes:
-
-value (string)
- A color value in VB or HTML hexadecimal format.
- For the "color" class, this should be a 3 byte value, ie. "#RRGGBB".
- For the "coloralpha" class, this should be a 4 byte value, ie. "#RRGGBBAA".
- For the "alpha" class, this should be a one-byte value, ie. "#AA".
-
----
-
-Dialog Definition table format
-
-The Dialog Definition table is simply an Array Table of Dialog Control tables.
-Note, however, that while the visual ordering of the controls are decided
-entirely by the "x", "y", "width" and "height" of the controls, the
-"tab order" of the controls are decided by their ordering in the Dialog
-Definition table.
-
----
-
-Dialog Result table format
-
-A Dialog Result table contains the user input from a configuration dialog.
-
-The control "name" properties are used as keys in this table.
-
-The type of the value for each entry in the table depends on the class of the
-control. The control classes map to types in the following manner:
-
-"label"
- None. Since the user cannot change a label, they do not produce any value.
-
-"edit", "textbox"
- String. The text input in the box. This can contain newlines in the case of
- a "textbox" class control.
-
-"intedit", "floatedit"
- Number. The number input into the control, guaranteed to be within the
- constraints set by the class (integer or float) and the min/max properties.
-
-"dropdown"
- String. The case-exact text of the selected item.
-
-"checkbox",
- Boolean. The checked-state of the checkbox.
-
-"color", "coloralpha", "alpha"
- String. A VB colorstring following the same scheme as for setting the
- "value" property.
-
----
-
-Display Configuration Dialog function
-
-This function displays a configuration dialog to the user and waits for it to
-close. It then returns whether the user accepted or cancelled the dialog, and
-what values were input.
-
-function aegisub.dialog.display(dialog, buttons)
-
-@dialog (table)
- A Dialog Definition table containing the controls to be in the dialog.
-
-@buttons (table)
- Optional. This is an Array Table of strings defining the buttons that appear
- in the dialog. If this is left out or is otherwise not a table, the standard
- Ok and Cancel buttons appear.
- The strings in this Array Table are used as labels on the buttons, and for
- identifying them in the return values of the function.
-
-Returns: Two values.
- 1. Boolean or string.
- If no custom buttons were specified, this is a boolean telling whether Ok
- (true) or Cancel (false) were clicked in the dialog.
- If custom buttons were specified, this is the text on the button clicked
- by the user.
- 2. Table.
- The Dialog Result table corresponding to the values the user input in the
- dialog.
-
----
diff --git a/automation/v4-docs/file-streams.txt b/automation/v4-docs/file-streams.txt
deleted file mode 100644
index 1fe259061..000000000
--- a/automation/v4-docs/file-streams.txt
+++ /dev/null
@@ -1,216 +0,0 @@
-Automation 4 File Stream interface
-
-This file describes the interface used for reading and writing files in
-Automation 4. This includes text encoding conversion routines.
-
----
-
-About encodings
-
-All file streams always have a text encoding. By default, this is 'utf-8',
-unless the file format reader/writer was registered as a text format. In
-that case, the default encoding will be the one set by the user before the
-reader or writer is invoked.
-
-All string operations on a stream follow the current encoding. You can
-change the encoding during reading/writing, and the change will only take
-effect from that point on.
-
-You can perform binary IO by setting the encoding to 'binary' and using
-strings consisting only of codepoints 0 to 255.
-
----
-
-Output File Stream user data object
-
-This object is passed to functions operating on an Output File Stream.
-
----
-
-Input File Stream user data object
-
-This object is passed to functions operating on an Input File Stream.
-
----
-
-Getting text encoding
-
-This function returns a string describing the current text encoding used for
-a file stream.
-
-function aegisub.fstream.get_encoding(stream)
-
-@stream (user data)
- The Input File Stream or Output File Stream to get the encoding for.
-
-Returns: String describing the encoding. This string can be used for setting
- the encoding later.
-
----
-
-Setting text encoding
-
-This function changes the current text encoding used for a file stream.
-
-function aegisub.fstream.set_encoding(stream, encoding)
-
-@stream (user data)
- The Input File Stream or Output File Stream to change the encoding for.
-
-@encoding (string)
- The new encoding to use.
-
-Returns: String describing the old encoding.
-
----
-
-File Pointer operations
-
-function aegisub.fstream.tell(stream)
-
-@stream (user data)
- The Input File Stream or Output File Stream get position of.
-
-Returns: Number, the number of bytes since the beginning of the file.
-
-
-function aegisub.fstream.seek(stream, length)
-
-@stream (user data)
- The Input File Stream or Output File Stream to seek in.
-
-@length (number)
- Number of bytes to skip. This can be negative.
- You can only seek backwards in an Output File Stream, and doing so truncates
- the file.
-
-Returns: nothing.
-
-
-function aegisub.fstream.reset(stream)
-
-Resets the file pointer to the start of the file. Truncates an Output File
-Stream to zero bytes.
-
-@stream (user data)
- The Input File Stream or Output File Stream to seek in.
-
-Returns: nothing.
-
----
-
-Reading text
-
-All these functions assume the file is in the current encoding specified.
-
-
-function aegisub.fstream.skip_utf_bom(stream, change_encoding)
-
-This function has undefined behaviour unless called as the first
-read-operation on the stream.
-
-It detects whether the file stream starts with an UTF Byte Order Mark, skips
-the number of bytes used by that BOM, and optionally changes the current file
-encoding to match the detected BOM.
-
-@stream (user data)
- The Input File Stream to read from.
-
-@change_encoding (boolean)
- If true, change encoding to match the detected BOM.
-
-Returns: Boolean, whether a BOM was detected or not.
-
-
-function aegisub.fstream.read(stream, length)
-
-Read a number of characters from a file.
-
-@stream (user data)
- The Input File Stream to read from.
-
-@length (number)
- Number of characters to read. If this is zero, no data are read. If this
- is larger than the number of characters available, data are read until the
- end of file.
-
-Returns: String, the string read from the file.
-
-
-function aegisub.fstream.read_bytes(stream, length)
-
-Read a number of bytes from a file and convert to a string.
-
-@stream (user data)
- The Input File Stream to read from.
-
-@length (number)
- The number of bytes to read.
-
-Returns: String, best-effort converted from the bytes read.
-
-
-function aegisub.fstream.read_line(stream, include_newline)
-
-Read until next newline in the file. A newline is defined asone of these
-sequences of Unicode codepoints in the decoded text:
- 0x0A ("\n")
- 0x0D ("\r")
- 0x0D 0x0A ("\r\n")
-The sequence "\n\r" is interpreted as two newlines, ie. a newline, a blank
-line and yet another newline.
-
-@stream (user data)
- The Input File Stream to read from.
-
-@include_newline (boolean)
- If true, include the newline character(s) in the returned string.
-
-Returns: String.
-
----
-
-Writing text
-
-All these functions assume the file is in the current encoding specified.
-
-
-function aegisub.fstream.write_utf_bom(stream)
-
-This function will corrupt your file if used anywhere else than on position 0.
-
-Write the correct UTF BOM character to the file, or nothing if not currently
-in an UTF encoding.
-
-@stream (user data)
- The Output File Stream to write the BOM to.
-
-Returns: nothing.
-
-
-function aegisub.fstream.write(stream, text)
-
-Write a string to a file.
-
-@stream (user data)
- The Output File Stream to write to.
-
-@text (string)
- The text to write.
-
-Returns: nothing.
-
-
-function aegisub.fstream.write_line(stream, text)
-
-Write a string to a file, followed by an "\r\n" newline.
-
-@stream (user data)
- The Output File Stream to write to.
-
-@text (string)
- The text to write.
-
-Returns: nothing.
-
----
diff --git a/automation/v4-docs/misc.txt b/automation/v4-docs/misc.txt
deleted file mode 100644
index 5f9050f4d..000000000
--- a/automation/v4-docs/misc.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-Miscellaneous functions in Automation 4
-
-This document describes various functions that couldn't be placed in any of
-the other Automation 4 documents.
-
----
-
-Getting the rendered size of a string
-
-This function might later on be part of a full rendering-interface for
-creating actual bitmaps of text.
-
-This function does NOT attempt to handle line breaks, automatic line breaking,
-fomatting override tags, vector drawings or anything else to that effect.
-If you need such functionality, you need to implement it yourself. (For now,
-at least.)
-
-function aegisub.text_extents(style, text)
-
-@style (table)
- A "style" class Subtitle Line table. This
-
-@text (string)
- The text to calculate the rendered size of.
-
-Returns: 4 values, all numbers.
- 1. Width of text in pixels.
- 2. Height of text in pixels.
- 3. Descent of text in pixels.
- 4. External leading of text in pixels.
-
----
diff --git a/automation/v4-docs/overview.txt b/automation/v4-docs/overview.txt
deleted file mode 100644
index 5479af0e9..000000000
--- a/automation/v4-docs/overview.txt
+++ /dev/null
@@ -1,176 +0,0 @@
-Aegisub Automation documentation
-Version 4
-Copyright 2005-2006 Niels Martin Hansen
-
-THIS IS OUT OF DATE COMPARED TO THE REST OF THE DOCS!
-
----
-
-This document describes version 4 of the automation system used in Aegisub.
-The automation system uses the Lua language for scripting engine.
-See for more information.
-
----
-
-Overview
-
-Aegisub Automation is a scripting environment that allows you to automate
-almost any task working with subtitles in Aegisub, ie. a macro environment.
-
-Automation allows you to:
- - Create macros (adding extra menu items to the main menu)
- o Those macros can optionally also display dialog boxes to the user
- o Allows adding new features to Aegisub without recompiling the entire
- program!
- - Write export filters
- o This is what Automation 3 did, but with more options
- o Useful for adding complicated special effects to a script
- - Write file-format importers and exporters
- o Load every strange subtitle format you come by
- o Save in those formats as well
- o Exporters write directly to a file stream, allowing you to generate
- those huge karaoke effects much faster!
-
-Automation runs in a true Unicode environment, meaning strings are internally
-represented as UTF-32, so you, as programmer, don't have to worry about text
-encodings, prefix encodings etc. to write scripts that can handle text in
-mostly any language of the world.
-
----
-
-Scripts, files functions
-
-An automation script is a Lua script following certain conventions described
-in this document. A script consists of one or more files, with one of them
-being the master script, and the others being include files.
-
-Every script runs in a separate Lua interpreter, so separate scripts cannot
-communicate directly with each other. Scripts can share code by having common
-include files. Scripts can share data by storing data in the subtitle files,
-either in the dialogue lines or in the Script Info headers.
-
-Files containing Automation scripts must in UTF-8 encoding, with or without
-BOM (Byte Order Mark). Compiled Lua scripts should also work, as long as all
-strings are UTF-8 encoded, but this is untested and unsupported.
-
-Automation scripts implement one or more of four possible features. A feature
-is implemented by filling a specially named global table with certain values.
-See below for a discussion about the various features and how they differ.
-
----
-
-Scriptable features
-
-The following four features can be implemented by an Automation script:
-
- - Macro
- A macro is presented as a new menu item in the Automation menu on the menu
- bar in Aegisub. When the user select the menu item, a function in the
- Automation script is called to do processing. Features are present to allow
- direct interaction with the subtitle data.
-
- The macro can create and display dialog windows to the user.
-
- A macro can provide a function, that determines whether the macro cen be
- run, based on the current selection in the program, and the contents of
- the subtitles.
-
- - Export filter
- An export filter is presented as a filter in the Export dialog accessed
- from the File menu. The export filter is called when the user uses the
- Export feature. The export filter is given access every line (including
- Styles and Script Info lines) in the subtitle file, and can add/modify/
- remove lines in those.
-
- The export filter can provide a function, that returns a configuration
- dialog, which is presented to the user before the export is run. This
- function can access the subtitle data in order to customise the
- configuration dialog, before it's presented to the user.
-
- - File format reader
- It is not yet decided how the file format reader is accessed.
-
- Current ideas:
- o It provides two functions, one to test whether it can handle a given
- file and one to actually convert that file to ASS. Which import filter
- to use is decided by Aegisub, based on the result of the first function.
- o The user selects an import filter and a file. The import filter is
- applied to the selected file.
-
- The file format reader can present dialog windows to the user.
-
- The file format reader is given access to the raw file stream.
-
- - File format writer
- The file format writer is selected in the Export dialog access from the
- File menu. The file format writer is handed all the lines of the subtitles
- file and a file stream to write to.
-
- The file format writer can report itself as writing a binary format or a
- text format. In the case of a text format, all output is passed through the
- character set conversion routines in Aegisub.
-
- The file format writer can present dialog windows to the user.
-
-Every feature is given access to the following in addition to what's described
-above:
-
- - Displaying/hiding/updating a progress bar.
- - Outputting messages to the user.
- - Accessing framerate data
- - (Not fully decided yet) Raw video frame data (RGB and/or YUV)
- - (Not fully decided yet) Raw and FFT transformed wave data
- - (Not fully decided yet) Utilising FexTracker functions
- - Calculating the rendered size of a text string, given a style definition
-
----
-
-Script registration
-
-Scripts can be loaded in two ways, through autoload or by assigning them to
-a subtitle file.
-
-Autoloading of scripts happens by placing the master script file into the
-"automation/autoload" directory under the Aegisub installation directory.
-
-Assining scripts to a subtitle file is done through the Automation Manager
-GUI. Scripts assigned to a subtitle file are stored in the ASS Script Info
-line "Automation Scripts", using a pipe character as separator between the
-master script filenames.
-
-The automatic loading/storing of configuration options from Automation 3 has
-been removed, but can still be implemented in an Export Filter feature using
-the initialisation function.
-
----
-
-Actual documentation for functions, data structures and other interfaces is
-yet to be written.
-
----
-
-
-Versions of the scripting interface
-
-Here's a quick history of the scripting interface:
-
-Version 1
- Using Lua as engine.
- The scripts used in the Karaoke Effector application, avaible at:
- (currently down)
-
-Version 2
- Using Python as engine.
- The first draft for an Aegisub automation engine.
- Never implemented.
-
-Version 3
- Using Lua as engine.
- Aegisub 1.09 was the last release-version to use Automation 3.
- (Tentative release date only!)
-
-Version 4
- Using Lua as engine
- Present in Aegisub 1.10 and later (tentative!)
- Heavily expanded feature set, allowing a much wider range of modifications,
- and more direct integration into the Aegisub user interface.
diff --git a/automation/v4-docs/progress-reporting.txt b/automation/v4-docs/progress-reporting.txt
deleted file mode 100644
index 3fd1e6093..000000000
--- a/automation/v4-docs/progress-reporting.txt
+++ /dev/null
@@ -1,102 +0,0 @@
-Automation 4 Progress Reporting and Debugging interface
-
-This document describes the functions used for reporting progress and
-outputting debug information during the running of a script.
-
----
-
-Showing/hiding the progress dialog
-
-This function is used to show or hide the progress dialog.
-
-function aegisub.progress.show(do_show, can_cancel)
-
-@do_show (boolean)
- True if the dialog should be shown, false if it should be hidden.
-
-@can_cancel (boolean)
- Determines whether the Cancel button is shown. If you set this to true,
- you should remember to periodically test whether the script has been
- cancelled.
-
-Returns: nothing.
-
----
-
-Setting the progress bar position
-
-function aegisub.progress.set(precent)
-
-@percent (number)
- The percentage completed.
-
-Returns: nothing.
-
----
-
-Showing the current task
-
-Used to set a message describing the current task being done.
-
-function aegisub.progress.task(msg, ...)
-
-@msg (string)
- A format string used for the message.
-
-@...
- Parameters to the format string.
-
-Returns: nothing.
-
----
-
-Setting the progress dialog title
-
-function aegisub.progress.title(title, ...)
-
-@title (string)
- A format string used for the title.
-
-@...
- Parameters to the format string.
-
-Returns: nothing.
-
----
-
-Getting the "cancelled" status
-
-Call this function to determine whether the Cancel button in the progress
-dialog has been clicked.
-
-function aegisub.progress.is_cancelled()
-
-Returns: Boolean. True is the user has clicked the Cancel button, false if it
- has not been clicked, nil if there is no Cancel button.
-
----
-
-Outputting text to the debug log
-
-function aegisub.debug.out(level, msg, ...)
-
-@level (number)
- Integer describing the verbosity of this message. Here are some suggested
- values you can use:
- 0: Fatal, this is really an error that can't be ignored.
- 1: Error, this kind of error can be recovered from, but might result in a
- fatal error later on.
- 2: Warning, something might be going wrong.
- 3: Hint, something isn't entirely sane, but nothing wrong.
- 4: Debug, some additional data only needed for development.
- 5: Trace, extremely verbose data showing every tiny step during execution.
-
-@msg (string)
- A format string used for the message.
-
-@...
- Parameters for the format string.
-
-Returns: nothing.
-
----
diff --git a/automation/v4-docs/subtitle-data.txt b/automation/v4-docs/subtitle-data.txt
deleted file mode 100644
index 5b192d977..000000000
--- a/automation/v4-docs/subtitle-data.txt
+++ /dev/null
@@ -1,398 +0,0 @@
-Automation 4 Subtitle Data format and functions API
-
-This file describes the API for retrieving and manipulating subtitle data in
-Automation 4, as well as the data structures generated and accepted by these
-APIs.
-
----
-
-Subtitle Line table
-
-A Subtitle Line table contains various information about a line in the
-subtitle file being processed. There are several classes of subtitle lines,
-which all have a few fields in common, but otherwise have different fields.
-
-
-Common keys for all Subtitle Line classes:
-
-class (string)
- The class of the Subtitle Line. Must be one of:
- "clear", (empty line)
- "comment", (semicolon-style comment line)
- "head", (section heading)
- "info", (key/value pair in Script Info section)
- "format", (line format definition)
- "style", (style definition line)
- "stylex", (style extension line, tentative AS5 feature)
- "dialogue", (dialogue line or dialogue-style comment line)
- "unknown" (unknown kind of line)
- Lines of the "unknown" class should never appear in well-formed subtitle
- scripts. They will usually be a result of a line being outside the section
- it belongs in.
-
-raw (string)
- The raw text of the line.
- You should not change this field directly, since the data in it will never
- be used for generating lines in internal representation. It will, however,
- be updated from the remaining data in the line whenever it is required for
- one thing or another by an internal function.
-
-section (string)
- The section this line is placed in. If it is placed before the first section
- heading, this field is nil.
-
-
-Key defined only for the "comment" class:
-
-text (string)
- The text of the comment line, ie. everything after the initial semicolon,
- including any spaces.
-
-
-Key defined only for the "head" class:
-
-No special keys are defined for this class, but the "section" field will be
-the name of the new section started.
-
-
-Keys defined only for the "info" class:
-
-key (string)
- The "key" part of the line, ie. everything before the first colon.
-
-value (string)
- The "value" part of the line, ie. everything after the first colon,
- discarding any leading whitespace.
-
-
-Keys defined only for the "format" class:
-
-fields (table)
- An Array Table of strings, each being the name of a field on the line.
-
-
-Keys defined only for the "style" class:
-
-name (string)
- Name of the style.
-
-fontname (string)
- Name of the font used.
-
-fontsize (string)
- Size of the font used, in pixels.
-
-color1 (string)
-color2 (string)
-color3 (string)
-color4 (string)
- The four colors for the style. (Fill, pre-karaoke fill, border, shadow)
- In VB hexadecimal, ie. "&HAABBGGRR&"
-
-bold (boolean/number)
- The boldness/weight of the font. This will usually be a boolean, but it
- can be a number, in which case it must be one of 0, 100, 200, ..., 900.
-
-italic (boolean)
-underline (boolean)
-strikeout (boolean)
- Other properties of the font.
-
-scale_x (number)
-scale_y (number)
- Scaling of the text, in percent.
-
-spacing (number)
- Additional spacing between letters. Always integer.
-
-angle (number)
- Rotation of the text on the Z axis in degrees.
-
-borderstyle (number)
- 1 = outline and drop shadow; 3 = opaque box.
-
-outline (number)
- Width of the outline.
-
-shadow (number)
- Distance between shadow and text.
-
-align (number)
- Numpad alignment of the text.
-
-margin_l (number)
-margin_r (number)
-margin_t (number)
-margin_b (number)
- Left/right/top/bottom margins of the text in pixels.
- If using a format without support for separate top and bottom margins, the
- margin_t value will be used for vertical margin when converting back to
- textual representation.
-
-encoding (number)
- Font encoding used for text. This follows the MS Windows font encoding
- constants.
-
-relative_to (number)
- From STS.h: "0: window, 1: video, 2: undefined (~window)"
-
-vertical (boolean)
- Whether vertical text semantics is used or not.
-
-
-Keys defined only for the "stylex" class:
-
-Remember that this class is only for the tentative AS5 format.
-
-name (string)
- Name of the new style defined.
-
-basename (string)
- Name of the style the new style is based on.
-
-overrides (string)
- String of override tags defining the new style.
-
-
-Keys only defined for the "dialogue" class:
-
-comment (boolean)
- True if the line is a comment line, otherwise false.
-
-layer (number)
- The layer the line is rendered in.
-
-start_time (number)
-end_time (number)
- Start/end time of the line in milliseconds.
-
-style (string)
- Name of the style assigned to this line.
-
-actor (string)
- Name of the actor performing this line.
-
-margin_l (number)
-margin_r (number)
-margin_t (number)
-margin_b (number)
- Left/right/top/bottom margins of the text in pixels.
- If any of these are zero, it's considered "not overriding".
- Same comment as for style lines applies.
-
-effect (string)
- Effect to apply to the line.
-
-userdata (string)
- Authoring-application defined data. (Tentative AS5 field.)
-
-text (string)
- The text for this line.
-
----
-
-Subtitle File user data object
-
-The Subtitle File object is a user data object with some of the metatable
-methods overridden to provide table-like access to the subtitle lines, as
-well as some functions to modify the subtitles.
-
-The following operations are supported.
-
-n = #subs
-n = subs.n
- Retrieve the number of lines in total.
- The first syntax is preferred.
-
-line = subs[i]
- Retrieve line i, assuming 1 <= i <= n.
-
-subs[i] = line
- Replace line i with new data.
-
-subs[i] = nil
-subs.delete(i[, i2, ...])
- Delete line i, pushing all following lines up an index. (Ie. by repeatedly
- deleting line 1 this way, the file will eventually end up empty.)
- The function syntax for this function can also take multiple line indexes,
- in which case it deletes each of those lines. All indexes are relative to
- the line numbering before the function is called.
-
-subs.deleterange(a, b)
- Deletes all lines from index a to index b, both inclusive. If b < a,
- nothing is done.
-
-subs[0] = line
-subs.append(line[, line2, ...])
- Append one or more lines to a file.
-
-subs[-i] = line
-subs.insert(i, line[, line2, ...])
- Insert one or more lines before index i.
-
-Note that the array-style accessors are most likely faster for any case only
-involving one line at a time, while the function syntax versions are probably
-faster if operating on multiple lines at a time.
-
----
-
-Parsing tag data
-
-This function uses the Aegisub SSA parser to split a string into override
-blocks and text, and give separate access to each tag in override blocks.
-
-function aegisub.parse_tag_data(text)
-
-@text (string)
- The SSA format string to parse.
-
-Returns: A Parsed Tag Data table.
-
----
-
-Recreating a line from tag data
-
-This function takes a Parsed Tag Data table and creates an SSA string from it.
-
-function aegisub.unparse_tag_data(tagdata)
-
-@tagdata (table)
- The Parsed Tag Data table to "unparse".
-
-Returns: A string, being the "unparsed" data.
-
----
-
-Parsing karaoke data
-
-Tihs function uses the Aegisub SSA parser to split a string into karaoke
-syllables with additional calculated information added.
-
-function aegisub.parse_karaoke_data(text)
-
-@text (string)
- The SSA format string to parse.
-
-Returns: A Parsed Karaoke Data table.
-
----
-
-Parsed Tag Data table
-
-The Parsed Tag Data table is an Array Table containing a number of Parsed Line
-Block tables.
-
-
-Parsed Line Block table
-
-A Parsed Line Block describes part of a line. (See ass_dialogue.cpp:70 for a
-more complete description of this.
-There are several classes of Parsed Line Block tables, which have slightly
-varying fields.
-
-
-Base Parsed Line Block table class
-
-class (string)
- One of:
- "plain",
- "override",
- "drawing"
-
-
-"plain" and "drawing" Parsed Line Block table classes
-
-text (string)
- The text contained in this block.
-
-
-"override" Parsed Line Block table class
-
-This class doesn't have any new, specifically named fields. It does, however,
-have multiple integer indexed fields, ie. acts as an Array Table.
-Each of these indexes refer to a table of type Parsed Override Tag.
-
-
-Parsed Override Tag table
-
-This table describes a single override-tag in an SSA line.
-
-valid (boolean)
- Whether this tag was parsed as a valid tag, or is just used for representing
- junk in the middle of the line.
-
-name (string)
- Name of the tag, including leading backslash character. (In the case of
- invalid tags, the leading backslash might not be present.)
-
-paran (boolean)
- Whether this tag has parantheses in its textual representation.
-
-params (table)
- This is an Array Table containing the parameters for this tag. It will
- always have the maximum number of entries that can be supported by the tag,
- but in case of omitted parameters, the parameters omitted will have 'false'
- for value in this table.
-
----
-
-Parsed Karaoke Data table
-
-The Parsed Karaoke Data table is simply an Array Table of Karaoke Syllable
-Data tables. However, the Parsed Karaoke Data table will always have one more
-item than its count shows, which is numbered 0 (zero). This item contains
-everything before the first syllable.
-
-
-Karaoke Syllable Data table
-
-This table contains information about a single karaoke syllable.
-
-duration (number)
- Duration of the syllable in milliseconds.
- (In case of syllable zero, this is always zero.)
-
-start_time (number)
-end_time (number)
- Start and end times of the syllable, relative to the start of the line,
- given in milliseconds.
- (While these can technically easily be calculated from the duration data,
- they are too convenient to leave out from the standard interface.)
-
-tag (string)
- The tag used for marking up this syllable. Usually one of:
- "k", "K", "kf", "ko"
- (In case of syllable zero, this is always the empty string.)
-
-text (string)
- The text of the syllable, including all additional override tags.
-
-text_stripped (string)
- The text of the syllable, stripped of any override tags.
-
----
-
-Setting undo points
-
-This function can only be used in macro features, it will have no effect when
-used in any other feature.
-It sets an undo point.
-
-You should always call this function after every operation that must be
-undoable as a separate step. It is considered very bad practice to modify
-the subtitles in a macro without setting at least one undo-point, which must
-be at the end.
-
-Furthermore, this function also marks the subtitles as "modified". No other
-function does this.
-
-function aegisub.set_undo_point(description)
-
-@description (string)
- A short description of the operation that will be undone, if this undo-point
- is used. Note that this is currently unused in Aegisub, and this parameter
- is simply ignored.
-
-Returns: nothing.
-
----
diff --git a/core/auto4-status.txt b/core/auto4-status.txt
new file mode 100644
index 000000000..98139c85d
--- /dev/null
+++ b/core/auto4-status.txt
@@ -0,0 +1,77 @@
+Aegisub Automation 4 branch build
+Alpha-quality
+
+Please install in a folder separate from your main Aegisub installation.
+
+What works:
+- UI-wise:
+ o Scanning the automation/autoload/ dir for scripts and loading them
+ o Rescanning said dir
+ o Macros not in right-click menu
+ o Reloading scripts on command
+ o Adding arbitrary other scripts to the local-scripts list (ie. bound to
+ subtitles rather than the application)
+ o Storing locally loaded scripts into subtiles on save
+ o Restoring locally loaded scripts from subtitle file on load
+ o Graceful recovery from (most) errors
+ o Scripts with errors are not retained, but marked as "has errors"
+ o Nice presentation of script debug-output
+- Scripting-wise
+ o Global script info variables are read
+ o Macros:
+ # Registration function
+ # Processing function
+ # Validation function
+ # Config dialogs
+ o Export filters:
+ # Registration function
+ # Processing function
+ o Basic subtitle manipulation:
+ # Getting subtitle data from a line
+ # Storing subtitle data back into a line
+ # Appending lines to script
+ # Inserting lines at random positions in the script
+ # Deleting lines and (UNTESTED) ranges of lines
+ # All of the above needs more testing
+ o Setting undo-points
+ o Table of selected lines is correctly filled
+ o Parsing karaoke tags
+ o Modifying subtitles/setting undo points *should* be impossible in
+ Validation functions
+ o text_extents (currently identical to Auto3 version, meaning it also has
+ the same strange inaccuracies)
+ o include() function
+ o Making debug-output
+
+What's broken:
+- UI-wise:
+ o No support for right-click menu macros
+ o Macro appearance in menus doesn't look too nice (needs a separator before
+ the macros)
+ o All functions in the program (including stuff unrelated to Automation)
+ should mark what kind of operation is put into the undo/redo buffer, but
+ this seems to be lost somewhere and isn't properly displayed.
+- Scripting-wise
+ o active_line parameter to macro validation and processing functions seems
+ to not be filled correctly
+ o Lua needs a string library for processing UTF-8 strings natively, as well
+ as a regex library for working with Unicode strings. Perhaps even
+ introduce a new userdata type for storing widestrings?
+ o Stored options for export script config dialogs aren't supported yet.
+
+What's missing:
+- UI wise:
+ o Apart from things relying on other Features being implemented in
+ scripting, nothing I can think of.
+- Scripting-wise:
+ o Override (un)parsing of tags
+ o Subtitle Format reader/writer features
+ o File streams (required for subtitle format features)
+
+Things to try:
+- Test, test, TEST!
+ Write some scripts that do more or less useful things.
+ Try to break stuff.
+ Report bugs.
+- Config dialogs definately need more testing, whether all controls
+ behave sensibly etc.
diff --git a/core/auto4_base.cpp b/core/auto4_base.cpp
new file mode 100644
index 000000000..53dcc7367
--- /dev/null
+++ b/core/auto4_base.cpp
@@ -0,0 +1,704 @@
+// Copyright (c) 2006, Niels Martin Hansen
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of the Aegisub Group nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// -----------------------------------------------------------------------------
+//
+// AEGISUB
+//
+// Website: http://aegisub.cellosoft.com
+// Contact: mailto:jiifurusu@gmail.com
+//
+
+#include "auto4_base.h"
+#include "ass_style.h"
+#include "options.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef WIN32
+#include
+#include
+#else
+#include
+#include FT_FREETYPE_H
+#endif
+
+namespace Automation4 {
+
+ bool CalculateTextExtents(AssStyle *style, wxString &text, int &width, int &height, int &descent, int &extlead)
+ {
+ width = height = descent = extlead = 0;
+
+ double fontsize = style->fontsize;
+
+#ifdef WIN32
+ // This is almost copypasta from TextSub
+ HDC thedc = CreateCompatibleDC(0);
+ if (!thedc) return false;
+ SetMapMode(thedc, MM_TEXT);
+
+ HDC dczero = GetDC(0);
+ fontsize = -MulDiv((int)(fontsize+0.5), GetDeviceCaps(dczero, LOGPIXELSY), 72);
+ ReleaseDC(0, dczero);
+
+ LOGFONT lf;
+ ZeroMemory(&lf, sizeof(lf));
+ lf.lfHeight = fontsize;
+ lf.lfWeight = style->bold ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = style->italic;
+ lf.lfUnderline = style->underline;
+ lf.lfStrikeOut = style->strikeout;
+ lf.lfCharSet = style->encoding;
+ lf.lfOutPrecision = OUT_TT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = ANTIALIASED_QUALITY;
+ lf.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
+ wcsncpy(lf.lfFaceName, style->font.wc_str(), 32);
+
+ HFONT thefont = CreateFontIndirect(&lf);
+ if (!thefont) return false;
+ SelectObject(thedc, thefont);
+
+ SIZE sz;
+ size_t thetextlen = text.length();
+ const wchar_t *thetext = text.wc_str();
+ if (style->spacing) {
+ width = 0;
+ for (unsigned int i = 0; i < thetextlen; i++) {
+ GetTextExtentPoint32(thedc, &thetext[i], 1, &sz);
+ width += sz.cx + (int)style->spacing;
+ height = sz.cy;
+ }
+ } else {
+ GetTextExtentPoint32(thedc, thetext, (int)thetextlen, &sz);
+ width = sz.cx;
+ height = sz.cy;
+ }
+
+ // HACKISH FIX! This seems to work, but why? It shouldn't be needed?!?
+ fontsize = style->fontsize;
+ width = (int)(width * fontsize/height + 0.5);
+ height = (int)(fontsize + 0.5);
+
+ TEXTMETRIC tm;
+ GetTextMetrics(thedc, &tm);
+ descent = tm.tmDescent;
+ extlead= tm.tmExternalLeading;
+
+ DeleteObject(thedc);
+ DeleteObject(thefont);
+
+#else // not WIN32
+ wxMemoryDC thedc;
+
+ // fix fontsize to be 72 DPI
+ fontsize = -FT_MulDiv((int)(fontsize+0.5), 72, thedc.GetPPI().y);
+
+ // now try to get a font!
+ // use the font list to get some caching... (chance is the script will need the same font very often)
+ // USING wxTheFontList SEEMS TO CAUSE BAD LEAKS!
+ //wxFont *thefont = wxTheFontList->FindOrCreateFont(
+ wxFont thefont(
+ fontsize,
+ wxFONTFAMILY_DEFAULT,
+ style->italic ? wxFONTSTYLE_ITALIC : wxFONTSTYLE_NORMAL,
+ style->bold ? wxFONTWEIGHT_BOLD : wxFONTWEIGHT_NORMAL,
+ style->underline,
+ style->font,
+ wxFONTENCODING_SYSTEM); // FIXME! make sure to get the right encoding here, make some translation table between windows and wx encodings
+ thedc.SetFont(thefont);
+
+ if (style->spacing) {
+ // If there's inter-character spacing, kerning info must not be used, so calculate width per character
+ // NOTE: Is kerning actually done either way?!
+ for (unsigned int i = 0; i < intext.length(); i++) {
+ int a, b, c, d;
+ thedc.GetTextExtent(intext[i], &a, &b, &c, &d);
+ width += a + spacing;
+ height = b > height ? b : height;
+ descent = c > descent ? c : descent;
+ extlead= d > extlead ? d : extlead;
+ }
+ } else {
+ // If the inter-character spacing should be zero, kerning info can (and must) be used, so calculate everything in one go
+ thedc.GetTextExtent(intext, &width, &height, &descent, &extlead);
+ }
+#endif
+
+ // Compensate for scaling
+ width = (int)(style->scalex / 100 * width + 0.5);
+ height = (int)(style->scaley / 100 * height + 0.5);
+ descent = (int)(style->scaley / 100 * descent + 0.5);
+ extlead = (int)(style->scaley / 100 * extlead + 0.5);
+
+ return true;
+ }
+
+
+ // Feature
+
+ Feature::Feature(ScriptFeatureClass _featureclass, const wxString &_name)
+ : featureclass(_featureclass)
+ , name(_name)
+ {
+ // nothing to do
+ }
+
+ ScriptFeatureClass Feature::GetClass() const
+ {
+ return featureclass;
+ }
+
+ FeatureMacro* Feature::AsMacro()
+ {
+ if (featureclass == SCRIPTFEATURE_MACRO)
+ // For VS, remember to enable building with RTTI, otherwise dynamic_cast<> won't work
+ return dynamic_cast(this);
+ return 0;
+ }
+
+ FeatureFilter* Feature::AsFilter()
+ {
+ if (featureclass == SCRIPTFEATURE_FILTER)
+ return dynamic_cast(this);
+ return 0;
+ }
+
+ FeatureSubtitleFormat* Feature::AsSubFormat()
+ {
+ if (featureclass == SCRIPTFEATURE_SUBFORMAT)
+ return dynamic_cast(this);
+ return 0;
+ }
+
+ const wxString& Feature::GetName() const
+ {
+ return name;
+ }
+
+
+ // FeatureMacro
+
+ FeatureMacro::FeatureMacro(const wxString &_name, const wxString &_description, MacroMenu _menu)
+ : Feature(SCRIPTFEATURE_MACRO, _name)
+ , description(_description)
+ , menu(_menu)
+ {
+ // nothing to do
+ }
+
+ const wxString& FeatureMacro::GetDescription() const
+ {
+ return description;
+ }
+
+ MacroMenu FeatureMacro::GetMenu() const
+ {
+ return menu;
+ }
+
+
+ // FeatureFilter
+
+ FeatureFilter::FeatureFilter(const wxString &_name, const wxString &_description, int _priority)
+ : Feature(SCRIPTFEATURE_FILTER, _name)
+ , AssExportFilter()
+ , config_dialog(0)
+ {
+ description = _description; // from AssExportFilter
+ Register(_name, _priority);
+ }
+
+ FeatureFilter::~FeatureFilter()
+ {
+ Unregister();
+ }
+
+ wxWindow* FeatureFilter::GetConfigDialogWindow(wxWindow *parent) {
+ if (config_dialog) {
+ delete config_dialog;
+ config_dialog = 0;
+ }
+ if (config_dialog = GenerateConfigDialog(parent)) {
+ return config_dialog->GetWindow(parent);
+ } else {
+ return 0;
+ }
+ }
+
+ void FeatureFilter::LoadSettings(bool IsDefault) {
+ if (config_dialog) {
+ config_dialog->ReadBack();
+ }
+ }
+
+
+ // FeatureSubtitleFormat
+
+ FeatureSubtitleFormat::FeatureSubtitleFormat(const wxString &_name, const wxString &_extension)
+ : Feature(SCRIPTFEATURE_SUBFORMAT, _name)
+ , extension(_extension)
+ {
+ // nothing to do
+ }
+
+ const wxString& FeatureSubtitleFormat::GetExtension() const
+ {
+ return extension;
+ }
+
+ bool FeatureSubtitleFormat::CanWriteFile(wxString filename)
+ {
+ return !filename.Right(extension.Length()).CmpNoCase(extension);
+ }
+
+ bool FeatureSubtitleFormat::CanReadFile(wxString filename)
+ {
+ return !filename.Right(extension.Length()).CmpNoCase(extension);
+ }
+
+
+ // ShowConfigDialogEvent
+
+ const wxEventType EVT_SHOW_CONFIG_DIALOG_t = wxNewEventType();
+
+
+ // ScriptConfigDialog
+
+ wxWindow* ScriptConfigDialog::GetWindow(wxWindow *parent)
+ {
+ if (win) return win;
+ return win = CreateWindow(parent);
+ }
+
+ void ScriptConfigDialog::DeleteWindow()
+ {
+ if (win) delete win;
+ win = 0;
+ }
+
+
+ // ProgressSink
+
+ ProgressSink::ProgressSink(wxWindow *parent)
+ : wxDialog(parent, -1, _T("Automation"), wxDefaultPosition, wxDefaultSize, wxDOUBLE_BORDER)
+ , cancelled(false)
+ , has_inited(false)
+ , script_finished(false)
+ , debug_visible(false)
+ {
+ // make the controls
+ progress_display = new wxGauge(this, -1, 1000, wxDefaultPosition, wxSize(300, 20));
+ title_display = new wxStaticText(this, -1, _T(""), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE|wxST_NO_AUTORESIZE);
+ task_display = new wxStaticText(this, -1, _T(""), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE|wxST_NO_AUTORESIZE);
+ cancel_button = new wxButton(this, wxID_CANCEL);
+ debug_output = new wxTextCtrl(this, -1, _T(""), wxDefaultPosition, wxSize(300, 120), wxTE_MULTILINE|wxTE_READONLY);
+
+ // put it in a sizer
+ sizer = new wxBoxSizer(wxVERTICAL);
+ sizer->Add(title_display, 0, wxEXPAND | wxALL, 5);
+ sizer->Add(progress_display, 0, wxALL&~wxTOP, 5);
+ sizer->Add(task_display, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
+ sizer->Add(cancel_button, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT | wxBOTTOM, 5);
+ sizer->Add(debug_output, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
+ sizer->Show(debug_output, false);
+
+ // make the title a slightly larger font
+ wxFont title_font = title_display->GetFont();
+ int fontsize = title_font.GetPointSize();
+ title_font.SetPointSize(fontsize + fontsize/4 + fontsize/8);
+ title_font.SetWeight(wxFONTWEIGHT_BOLD);
+ title_display->SetFont(title_font);
+
+ sizer->SetSizeHints(this);
+ SetSizer(sizer);
+ Center();
+ }
+
+ ProgressSink::~ProgressSink()
+ {
+ }
+
+ void ProgressSink::OnIdle(wxIdleEvent &evt)
+ {
+ // The big glossy "update display" event
+ DoUpdateDisplay();
+
+ if (script_finished) {
+ if (!debug_visible) {
+ EndModal(0);
+ } else {
+ cancel_button->Enable(true);
+ cancel_button->SetLabel(_("Close"));
+ SetProgress(100.0);
+ SetTask(_("Script completed"));
+ }
+ }
+ }
+
+ void ProgressSink::DoUpdateDisplay()
+ {
+ // If debug output isn't handled before the test for script_finished later,
+ // there might actually be some debug output but the debug_visible flag won't
+ // be set before the dialog closes itself.
+ wxMutexLocker lock(data_mutex);
+ if (!pending_debug_output.IsEmpty()) {
+ if (!debug_visible) {
+ sizer->Show(debug_output, true);
+ Layout();
+ sizer->Fit(this);
+
+ debug_visible = true;
+ }
+
+ *debug_output << pending_debug_output;
+ debug_output->SetInsertionPointEnd();
+
+ pending_debug_output = _T("");
+ }
+
+ progress_display->SetValue((int)(progress*10));
+ task_display->SetLabel(task);
+ title_display->SetLabel(title);
+ }
+
+ void ProgressSink::SetProgress(float _progress)
+ {
+ wxMutexLocker lock(data_mutex);
+ progress = _progress;
+ }
+
+ void ProgressSink::SetTask(const wxString &_task)
+ {
+ wxMutexLocker lock(data_mutex);
+ task = _task;
+ }
+
+ void ProgressSink::SetTitle(const wxString &_title)
+ {
+ wxMutexLocker lock(data_mutex);
+ title = _title;
+ }
+
+ void ProgressSink::AddDebugOutput(const wxString &msg)
+ {
+ wxMutexLocker lock(data_mutex);
+ pending_debug_output << msg;
+ }
+
+ BEGIN_EVENT_TABLE(ProgressSink, wxWindow)
+ EVT_INIT_DIALOG(ProgressSink::OnInit)
+ EVT_BUTTON(wxID_CANCEL, ProgressSink::OnCancel)
+ EVT_IDLE(ProgressSink::OnIdle)
+ EVT_SHOW_CONFIG_DIALOG(ProgressSink::OnConfigDialog)
+ END_EVENT_TABLE()
+
+ void ProgressSink::OnInit(wxInitDialogEvent &evt)
+ {
+ has_inited = true;
+ }
+
+ void ProgressSink::OnCancel(wxCommandEvent &evt)
+ {
+ if (!script_finished) {
+ cancelled = true;
+ cancel_button->Enable(false);
+ } else {
+ EndModal(0);
+ }
+ }
+
+ void ProgressSink::OnConfigDialog(ShowConfigDialogEvent &evt)
+ {
+ // assume we're in the GUI thread here
+
+ DoUpdateDisplay();
+
+ if (evt.config_dialog) {
+ wxDialog *w = new wxDialog(this, -1, title); // container dialog box
+ wxBoxSizer *s = new wxBoxSizer(wxHORIZONTAL); // sizer for putting contents in
+ wxWindow *ww = evt.config_dialog->GetWindow(w); // get/generate actual dialog contents
+ s->Add(ww, 0, wxALL, 5); // add contents to dialog
+ w->SetSizerAndFit(s);
+ w->CenterOnParent();
+ w->ShowModal();
+ evt.config_dialog->ReadBack();
+ evt.config_dialog->DeleteWindow();
+ delete w;
+ } else {
+ wxMessageBox(_T("Uh... no config dialog?"));
+ }
+
+ // See note in auto4_base.h
+ if (evt.sync_sema) {
+ evt.sync_sema->Post();
+ }
+ }
+
+
+ // Script
+
+ Script::Script(const wxString &_filename)
+ : filename(_filename)
+ , name(_T(""))
+ , description(_T(""))
+ , author(_T(""))
+ , version(_T(""))
+ , loaded(false)
+ {
+ // copied from auto3
+ include_path.clear();
+ include_path.EnsureFileAccessible(filename);
+ wxStringTokenizer toker(Options.AsText(_T("Automation Include Path")), _T("|"), false);
+ while (toker.HasMoreTokens()) {
+ // todo? make some error reporting here
+ wxFileName path(toker.GetNextToken());
+ if (!path.IsOk()) continue;
+ if (path.IsRelative()) continue;
+ if (!path.DirExists()) continue;
+ if (include_path.Member(path.GetLongPath())) continue;
+ include_path.Add(path.GetLongPath());
+ }
+ }
+
+ Script::~Script()
+ {
+ for (std::vector::iterator f = features.begin(); f != features.end(); ++f) {
+ delete *f;
+ }
+ }
+
+ const wxString& Script::GetFilename() const
+ {
+ return filename;
+ }
+
+ const wxString& Script::GetName() const
+ {
+ return name;
+ }
+
+ const wxString& Script::GetDescription() const
+ {
+ return description;
+ }
+
+ const wxString& Script::GetAuthor() const
+ {
+ return author;
+ }
+
+ const wxString& Script::GetVersion() const
+ {
+ return version;
+ }
+
+ bool Script::GetLoadedState() const
+ {
+ return loaded;
+ }
+
+ std::vector& Script::GetFeatures()
+ {
+ return features;
+ }
+
+
+ // ScriptManager
+
+ ScriptManager::ScriptManager()
+ {
+ // do nothing...?
+ }
+
+ ScriptManager::~ScriptManager()
+ {
+ RemoveAll();
+ }
+
+ void ScriptManager::Add(Script *script)
+ {
+ for (std::vector