2007-01-15 23:19:50 +01:00
|
|
|
// Copyright (c) 2006, 2007, Niels Martin Hansen
|
2006-12-28 22:18:35 +01:00
|
|
|
// 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.
|
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
|
|
|
/// @file auto4_lua.cpp
|
|
|
|
/// @brief Lua 5.1-based scripting engine
|
|
|
|
/// @ingroup scripting
|
|
|
|
///
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2009-01-04 07:31:48 +01:00
|
|
|
#include "config.h"
|
|
|
|
|
2008-03-05 00:17:07 +01:00
|
|
|
#ifdef WITH_AUTO4_LUA
|
2007-12-31 07:46:22 +01:00
|
|
|
|
2011-09-28 21:48:37 +02:00
|
|
|
#include "auto4_lua.h"
|
|
|
|
|
2009-09-10 15:06:40 +02:00
|
|
|
#ifndef AGI_PRE
|
2011-09-28 21:48:37 +02:00
|
|
|
#include <cassert>
|
2012-09-25 02:09:42 +02:00
|
|
|
#include <cstdint>
|
2009-09-10 15:06:40 +02:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2012-02-23 20:28:19 +01:00
|
|
|
#include <wx/clipbrd.h>
|
2009-09-10 15:06:40 +02:00
|
|
|
#include <wx/filefn.h>
|
|
|
|
#include <wx/filename.h>
|
|
|
|
#include <wx/log.h>
|
|
|
|
#include <wx/msgdlg.h>
|
2012-02-20 06:15:00 +01:00
|
|
|
#include <wx/regex.h>
|
2010-01-24 20:07:34 +01:00
|
|
|
#include <wx/tokenzr.h>
|
2009-09-10 15:06:40 +02:00
|
|
|
#include <wx/window.h>
|
|
|
|
#endif
|
|
|
|
|
2011-09-28 21:52:02 +02:00
|
|
|
#include <libaegisub/access.h>
|
2010-06-09 01:21:39 +02:00
|
|
|
#include <libaegisub/log.h>
|
2011-09-28 21:48:37 +02:00
|
|
|
#include <libaegisub/scoped_ptr.h>
|
2010-06-09 01:21:39 +02:00
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
#include "ass_dialogue.h"
|
|
|
|
#include "ass_file.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "ass_style.h"
|
|
|
|
#include "auto4_lua_factory.h"
|
|
|
|
#include "auto4_lua_scriptreader.h"
|
2012-01-18 21:08:42 +01:00
|
|
|
#include "compat.h"
|
2011-09-28 21:48:47 +02:00
|
|
|
#include "include/aegisub/context.h"
|
2010-05-21 03:13:36 +02:00
|
|
|
#include "main.h"
|
2011-09-28 21:48:47 +02:00
|
|
|
#include "selection_controller.h"
|
2011-12-22 22:30:05 +01:00
|
|
|
#include "standard_paths.h"
|
2008-09-10 18:53:23 +02:00
|
|
|
#include "video_context.h"
|
2011-09-28 21:48:47 +02:00
|
|
|
#include "utils.h"
|
2008-03-05 05:10:20 +01:00
|
|
|
|
2009-09-10 15:06:40 +02:00
|
|
|
// This must be below the headers above.
|
2008-03-05 05:10:20 +01:00
|
|
|
#ifdef __WINDOWS__
|
2009-03-14 21:52:01 +01:00
|
|
|
#include "../../contrib/lua51/src/lualib.h"
|
|
|
|
#include "../../contrib/lua51/src/lauxlib.h"
|
2008-03-05 05:10:20 +01:00
|
|
|
#else
|
2011-11-08 02:18:16 +01:00
|
|
|
#include <lua.hpp>
|
2008-03-05 05:10:20 +01:00
|
|
|
#endif
|
|
|
|
|
2011-09-28 21:48:37 +02:00
|
|
|
namespace {
|
2011-09-28 21:48:47 +02:00
|
|
|
inline void push_value(lua_State *L, lua_CFunction fn)
|
|
|
|
{
|
2011-09-28 21:48:37 +02:00
|
|
|
lua_pushcfunction(L, fn);
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
inline void push_value(lua_State *L, int n)
|
|
|
|
{
|
2011-09-28 21:48:37 +02:00
|
|
|
lua_pushinteger(L, n);
|
|
|
|
}
|
|
|
|
|
2012-02-15 22:23:42 +01:00
|
|
|
inline void push_value(lua_State *L, void *p)
|
|
|
|
{
|
|
|
|
lua_pushlightuserdata(L, p);
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:37 +02:00
|
|
|
template<class T>
|
2011-09-28 21:48:47 +02:00
|
|
|
inline void set_field(lua_State *L, const char *name, T value)
|
|
|
|
{
|
2011-09-28 21:48:37 +02:00
|
|
|
push_value(L, value);
|
|
|
|
lua_setfield(L, -2, name);
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
inline wxString get_wxstring(lua_State *L, int idx)
|
|
|
|
{
|
|
|
|
return wxString(lua_tostring(L, idx), wxConvUTF8);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline wxString check_wxstring(lua_State *L, int idx)
|
|
|
|
{
|
|
|
|
return wxString(luaL_checkstring(L, idx), wxConvUTF8);
|
|
|
|
}
|
|
|
|
|
|
|
|
wxString get_global_string(lua_State *L, const char *name)
|
|
|
|
{
|
2011-09-28 21:48:37 +02:00
|
|
|
lua_getglobal(L, name);
|
|
|
|
wxString ret;
|
|
|
|
if (lua_isstring(L, -1))
|
2011-09-28 21:48:47 +02:00
|
|
|
ret = get_wxstring(L, -1);
|
2011-09-28 21:48:37 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
return ret;
|
|
|
|
}
|
2011-09-28 21:49:47 +02:00
|
|
|
|
|
|
|
void set_context(lua_State *L, const agi::Context *c)
|
|
|
|
{
|
|
|
|
// Explicit cast is needed to discard the const
|
|
|
|
lua_pushlightuserdata(L, (void *)c);
|
|
|
|
lua_setfield(L, LUA_REGISTRYINDEX, "project_context");
|
|
|
|
}
|
|
|
|
|
|
|
|
const agi::Context *get_context(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, "project_context");
|
2012-01-09 21:31:19 +01:00
|
|
|
if (!lua_islightuserdata(L, -1)) {
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return 0;
|
|
|
|
}
|
2011-09-28 21:49:47 +02:00
|
|
|
const agi::Context * c = static_cast<const agi::Context *>(lua_touserdata(L, -1));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return c;
|
|
|
|
}
|
2012-02-15 22:23:42 +01:00
|
|
|
|
2012-02-22 00:32:58 +01:00
|
|
|
int get_file_name(lua_State *L)
|
|
|
|
{
|
|
|
|
const agi::Context *c = get_context(L);
|
|
|
|
if (c && c->ass->filename.size())
|
|
|
|
lua_pushstring(L, wxFileName(c->ass->filename).GetFullName().utf8_str());
|
|
|
|
else
|
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-03-13 00:35:29 +01:00
|
|
|
int get_translation(lua_State *L)
|
|
|
|
{
|
|
|
|
wxString str(check_wxstring(L, 1));
|
|
|
|
lua_pushstring(L, _(str).utf8_str());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-02-15 22:23:42 +01:00
|
|
|
inline wxRegEx *get_regex(lua_State *L)
|
|
|
|
{
|
|
|
|
return static_cast<wxRegEx*>(luaL_checkudata(L, 1, "aegisub.regex"));
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_matches(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_pushboolean(L, get_regex(L)->Matches(check_wxstring(L, 2)));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_match_count(lua_State *L)
|
|
|
|
{
|
|
|
|
wxRegEx *re = get_regex(L);
|
|
|
|
if (re->Matches(check_wxstring(L, 2)))
|
|
|
|
lua_pushinteger(L, re->GetMatchCount());
|
|
|
|
else
|
|
|
|
lua_pushinteger(L, 0);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t utf8_len(wxString const& w)
|
|
|
|
{
|
|
|
|
#if wxUSE_UNICODE_UTF8
|
|
|
|
return w.utf8_length();
|
|
|
|
#else
|
|
|
|
return w.utf8_str().length();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_get_match(lua_State *L)
|
|
|
|
{
|
|
|
|
wxString str(check_wxstring(L, 2));
|
|
|
|
size_t start, len;
|
|
|
|
get_regex(L)->GetMatch(&start, &len, luaL_checkinteger(L, 3));
|
|
|
|
lua_pushinteger(L, utf8_len(str.Left(start)) + 1);
|
|
|
|
lua_pushinteger(L, utf8_len(str.Left(start + len)));
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_replace(lua_State *L)
|
|
|
|
{
|
|
|
|
wxString str(check_wxstring(L, 3));
|
|
|
|
int reps = get_regex(L)->Replace(&str, check_wxstring(L, 2), luaL_checkinteger(L, 4));
|
|
|
|
lua_pushstring(L, str.utf8_str());
|
|
|
|
lua_pushinteger(L, reps);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_compile(lua_State *L)
|
|
|
|
{
|
|
|
|
wxString pattern(check_wxstring(L, 1));
|
|
|
|
int flags = luaL_checkinteger(L, 2);
|
|
|
|
wxRegEx *re = static_cast<wxRegEx*>(lua_newuserdata(L, sizeof(wxRegEx)));
|
|
|
|
new(re) wxRegEx(pattern, wxRE_ADVANCED | flags);
|
|
|
|
|
|
|
|
luaL_getmetatable(L, "aegisub.regex");
|
|
|
|
lua_setmetatable(L, -2);
|
|
|
|
|
|
|
|
// return nil and handle the error in lua as it's a bit easier to
|
|
|
|
// report the actual call site from there
|
|
|
|
if (!re->IsValid()) {
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_pushnil(L);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_gc(lua_State *L) {
|
|
|
|
get_regex(L)->~wxRegEx();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_process_flags(lua_State *L)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
int nargs = lua_gettop(L);
|
|
|
|
for (int i = 1; i <= nargs; ++i) {
|
|
|
|
if (!lua_islightuserdata(L, i)) {
|
|
|
|
lua_pushstring(L, "Flags must follow all non-flag arguments");
|
|
|
|
return 1;
|
|
|
|
}
|
2012-02-20 06:15:00 +01:00
|
|
|
ret |= (int)(intptr_t)lua_touserdata(L, i);
|
2012-02-15 22:23:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
lua_pushinteger(L, ret);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_init_flags(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
|
|
|
|
set_field(L, "ICASE", (void*)wxRE_ICASE);
|
|
|
|
set_field(L, "NOSUB", (void*)wxRE_NOSUB);
|
|
|
|
set_field(L, "NEWLINE", (void*)wxRE_NEWLINE);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int regex_init(lua_State *L)
|
2012-03-25 06:05:06 +02:00
|
|
|
{
|
2012-02-15 22:23:42 +01:00
|
|
|
if (luaL_newmetatable(L, "aegisub.regex")) {
|
|
|
|
set_field(L, "__gc", regex_gc);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_newtable(L);
|
|
|
|
set_field(L, "matches", regex_matches);
|
|
|
|
set_field(L, "match_count", regex_match_count);
|
|
|
|
set_field(L, "get_match", regex_get_match);
|
|
|
|
set_field(L, "replace", regex_replace);
|
|
|
|
set_field(L, "compile", regex_compile);
|
|
|
|
set_field(L, "process_flags", regex_process_flags);
|
|
|
|
set_field(L, "init_flags", regex_init_flags);
|
|
|
|
return 1;
|
|
|
|
}
|
2012-02-22 21:47:34 +01:00
|
|
|
|
|
|
|
int clipboard_get(lua_State *L)
|
|
|
|
{
|
2012-10-25 17:13:13 +02:00
|
|
|
wxString data = GetClipboard();
|
|
|
|
if (!data)
|
2012-02-22 21:47:34 +01:00
|
|
|
lua_pushnil(L);
|
2012-10-25 17:13:13 +02:00
|
|
|
else
|
|
|
|
lua_pushstring(L, data.utf8_str());
|
2012-02-22 21:47:34 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int clipboard_set(lua_State *L)
|
|
|
|
{
|
|
|
|
wxString str(check_wxstring(L, 1));
|
|
|
|
|
|
|
|
bool succeeded = false;
|
|
|
|
|
|
|
|
#if wxUSE_OLE
|
|
|
|
// OLE needs to be initialized on each thread that wants to write to
|
|
|
|
// the clipboard, which wx does not handle automatically
|
|
|
|
wxClipboard cb;
|
|
|
|
wxClipboard *theCB = &cb;
|
|
|
|
#else
|
|
|
|
wxClipboard *theCB = wxTheClipboard;
|
|
|
|
#endif
|
|
|
|
if (theCB->Open()) {
|
|
|
|
succeeded = theCB->SetData(new wxTextDataObject(str));
|
|
|
|
theCB->Close();
|
|
|
|
theCB->Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_pushboolean(L, succeeded);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int clipboard_init(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_newtable(L);
|
|
|
|
set_field(L, "get", clipboard_get);
|
|
|
|
set_field(L, "set", clipboard_set);
|
|
|
|
return 1;
|
|
|
|
}
|
2011-09-28 21:48:37 +02:00
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
// LuaStackcheck
|
2012-02-10 03:16:49 +01:00
|
|
|
#ifdef _DEBUG
|
2006-12-28 22:18:35 +01:00
|
|
|
struct LuaStackcheck {
|
|
|
|
lua_State *L;
|
|
|
|
int startstack;
|
2008-03-09 22:09:51 +01:00
|
|
|
void check_stack(int additional)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
|
|
|
int top = lua_gettop(L);
|
|
|
|
if (top - additional != startstack) {
|
2010-06-09 01:21:39 +02:00
|
|
|
LOG_D("automation/lua") << "lua stack size mismatch.";
|
2006-12-28 22:18:35 +01:00
|
|
|
dump();
|
|
|
|
assert(top - additional == startstack);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void dump()
|
|
|
|
{
|
|
|
|
int top = lua_gettop(L);
|
2010-06-09 01:21:39 +02:00
|
|
|
LOG_D("automation/lua/stackdump") << "--- dumping lua stack...";
|
2006-12-28 22:18:35 +01:00
|
|
|
for (int i = top; i > 0; i--) {
|
|
|
|
lua_pushvalue(L, i);
|
|
|
|
wxString type(lua_typename(L, lua_type(L, -1)), wxConvUTF8);
|
|
|
|
if (lua_isstring(L, i)) {
|
2012-02-10 02:41:22 +01:00
|
|
|
LOG_D("automation/lua/stackdump") << type << ": " << lua_tostring(L, -1);
|
2006-12-28 22:18:35 +01:00
|
|
|
} else {
|
2010-06-09 01:21:39 +02:00
|
|
|
LOG_D("automation/lua/stackdump") << type;
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2010-06-09 01:21:39 +02:00
|
|
|
LOG_D("automation/lua") << "--- end dump";
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
2011-09-28 21:48:47 +02:00
|
|
|
LuaStackcheck(lua_State *L) : L(L) { startstack = lua_gettop(L); }
|
2008-03-09 22:09:51 +01:00
|
|
|
~LuaStackcheck() { check_stack(0); }
|
2006-12-28 22:18:35 +01:00
|
|
|
};
|
|
|
|
#else
|
|
|
|
struct LuaStackcheck {
|
2011-12-22 22:09:31 +01:00
|
|
|
void check_stack(int) { }
|
2006-12-28 22:18:35 +01:00
|
|
|
void dump() { }
|
2011-09-28 21:48:47 +02:00
|
|
|
LuaStackcheck(lua_State*) { }
|
2006-12-28 22:18:35 +01:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
namespace Automation4 {
|
2006-12-28 22:18:35 +01:00
|
|
|
// LuaScript
|
2011-09-28 21:48:37 +02:00
|
|
|
LuaScript::LuaScript(wxString const& filename)
|
|
|
|
: Script(filename)
|
|
|
|
, L(0)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2007-02-14 01:43:01 +01:00
|
|
|
Create();
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
LuaScript::~LuaScript()
|
|
|
|
{
|
2011-09-28 21:48:37 +02:00
|
|
|
Destroy();
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void LuaScript::Create()
|
|
|
|
{
|
|
|
|
Destroy();
|
|
|
|
|
|
|
|
try {
|
|
|
|
// create lua environment
|
|
|
|
L = lua_open();
|
|
|
|
LuaStackcheck _stackcheck(L);
|
|
|
|
|
|
|
|
// register standard libs
|
|
|
|
lua_pushcfunction(L, luaopen_base); lua_call(L, 0, 0);
|
|
|
|
lua_pushcfunction(L, luaopen_package); lua_call(L, 0, 0);
|
|
|
|
lua_pushcfunction(L, luaopen_string); lua_call(L, 0, 0);
|
|
|
|
lua_pushcfunction(L, luaopen_table); lua_call(L, 0, 0);
|
|
|
|
lua_pushcfunction(L, luaopen_math); lua_call(L, 0, 0);
|
2007-01-19 12:47:37 +01:00
|
|
|
lua_pushcfunction(L, luaopen_io); lua_call(L, 0, 0);
|
|
|
|
lua_pushcfunction(L, luaopen_os); lua_call(L, 0, 0);
|
2008-03-09 22:09:51 +01:00
|
|
|
_stackcheck.check_stack(0);
|
2011-09-28 21:52:20 +02:00
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
// dofile and loadfile are replaced with include
|
|
|
|
lua_pushnil(L);
|
|
|
|
lua_setglobal(L, "dofile");
|
|
|
|
lua_pushnil(L);
|
|
|
|
lua_setglobal(L, "loadfile");
|
|
|
|
lua_pushcfunction(L, LuaInclude);
|
|
|
|
lua_setglobal(L, "include");
|
|
|
|
|
2010-01-24 20:07:34 +01:00
|
|
|
// add include_path to the module load path
|
|
|
|
lua_getglobal(L, "package");
|
|
|
|
lua_pushstring(L, "path");
|
|
|
|
lua_pushstring(L, "path");
|
|
|
|
lua_gettable(L, -3);
|
|
|
|
|
2011-09-28 21:49:09 +02:00
|
|
|
for (size_t i = 0; i < include_path.size(); ++i) {
|
|
|
|
wxCharBuffer p = include_path[i].utf8_str();
|
|
|
|
lua_pushfstring(L, ";%s/?.lua;%s/?/init.lua", p.data(), p.data());
|
|
|
|
lua_concat(L, 2);
|
2010-01-24 20:07:34 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
lua_settable(L, -3);
|
2010-01-28 02:13:13 +01:00
|
|
|
|
2011-09-28 21:48:37 +02:00
|
|
|
// Replace the default lua module loader with our unicode compatible one
|
2010-01-28 02:13:13 +01:00
|
|
|
lua_getfield(L, -1, "loaders");
|
|
|
|
lua_pushcfunction(L, LuaModuleLoader);
|
|
|
|
lua_rawseti(L, -2, 2);
|
|
|
|
lua_pop(L, 2);
|
2010-01-24 20:07:34 +01:00
|
|
|
_stackcheck.check_stack(0);
|
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
// prepare stuff in the registry
|
2011-09-28 21:52:20 +02:00
|
|
|
|
|
|
|
// store the script's filename
|
|
|
|
lua_pushstring(L, wxFileName(GetFilename()).GetName().utf8_str().data());
|
|
|
|
lua_setfield(L, LUA_REGISTRYINDEX, "filename");
|
|
|
|
_stackcheck.check_stack(0);
|
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
// reference to the script object
|
|
|
|
lua_pushlightuserdata(L, this);
|
|
|
|
lua_setfield(L, LUA_REGISTRYINDEX, "aegisub");
|
2008-03-09 22:09:51 +01:00
|
|
|
_stackcheck.check_stack(0);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
// make "aegisub" table
|
|
|
|
lua_pushstring(L, "aegisub");
|
|
|
|
lua_newtable(L);
|
2011-09-28 21:48:37 +02:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
set_field(L, "register_macro", LuaCommand::LuaRegister);
|
|
|
|
set_field(L, "register_filter", LuaExportFilter::LuaRegister);
|
2011-09-28 21:48:37 +02:00
|
|
|
set_field(L, "text_extents", LuaTextExtents);
|
|
|
|
set_field(L, "frame_from_ms", LuaFrameFromMs);
|
|
|
|
set_field(L, "ms_from_frame", LuaMsFromFrame);
|
|
|
|
set_field(L, "video_size", LuaVideoSize);
|
2011-12-22 22:29:56 +01:00
|
|
|
set_field(L, "keyframes", LuaGetKeyframes);
|
2011-12-22 22:30:05 +01:00
|
|
|
set_field(L, "decode_path", LuaDecodePath);
|
2012-01-20 22:33:20 +01:00
|
|
|
set_field(L, "cancel", LuaCancel);
|
2011-09-28 21:48:37 +02:00
|
|
|
set_field(L, "lua_automation_version", 4);
|
2012-02-15 22:23:42 +01:00
|
|
|
set_field(L, "__init_regex", regex_init);
|
2012-02-22 21:47:34 +01:00
|
|
|
set_field(L, "__init_clipboard", clipboard_init);
|
2012-02-22 00:32:58 +01:00
|
|
|
set_field(L, "file_name", get_file_name);
|
2012-03-13 00:35:29 +01:00
|
|
|
set_field(L, "gettext", get_translation);
|
2011-09-28 21:48:37 +02:00
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
// store aegisub table to globals
|
|
|
|
lua_settable(L, LUA_GLOBALSINDEX);
|
2008-03-09 22:09:51 +01:00
|
|
|
_stackcheck.check_stack(0);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
// load user script
|
2007-01-03 04:39:15 +01:00
|
|
|
LuaScriptReader script_reader(GetFilename());
|
2011-09-28 21:48:37 +02:00
|
|
|
if (lua_load(L, script_reader.reader_func, &script_reader, GetPrettyFilename().utf8_str())) {
|
2011-09-28 21:48:47 +02:00
|
|
|
wxString err = wxString::Format("Error loading Lua script \"%s\":\n\n%s", GetPrettyFilename(), get_wxstring(L, -1));
|
2012-08-20 05:32:18 +02:00
|
|
|
lua_pop(L, 1);
|
2011-09-28 21:48:28 +02:00
|
|
|
throw ScriptLoadError(STD_STR(err));
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
2008-03-09 22:09:51 +01:00
|
|
|
_stackcheck.check_stack(1);
|
2011-09-28 21:48:37 +02:00
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
// and execute it
|
|
|
|
// this is where features are registered
|
2007-04-22 17:45:29 +02:00
|
|
|
// don't thread this, as there's no point in it and it seems to break on wx 2.8.3, for some reason
|
|
|
|
if (lua_pcall(L, 0, 0, 0)) {
|
|
|
|
// error occurred, assumed to be on top of Lua stack
|
2011-09-28 21:48:47 +02:00
|
|
|
wxString err = wxString::Format("Error initialising Lua script \"%s\":\n\n%s", GetPrettyFilename(), get_wxstring(L, -1));
|
2012-08-20 05:32:18 +02:00
|
|
|
lua_pop(L, 1);
|
2011-09-28 21:48:28 +02:00
|
|
|
throw ScriptLoadError(STD_STR(err));
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
2008-03-09 22:09:51 +01:00
|
|
|
_stackcheck.check_stack(0);
|
2011-09-28 21:48:37 +02:00
|
|
|
|
2006-12-28 23:55:41 +01:00
|
|
|
lua_getglobal(L, "version");
|
2011-09-28 21:48:37 +02:00
|
|
|
if (lua_isnumber(L, -1) && lua_tointeger(L, -1) == 3) {
|
|
|
|
lua_pop(L, 1); // just to avoid tripping the stackcheck in debug
|
2011-09-28 21:48:28 +02:00
|
|
|
throw ScriptLoadError("Attempted to load an Automation 3 script as an Automation 4 Lua script. Automation 3 is no longer supported.");
|
2006-12-28 23:55:41 +01:00
|
|
|
}
|
2011-09-28 21:48:37 +02:00
|
|
|
|
|
|
|
name = get_global_string(L, "script_name");
|
|
|
|
description = get_global_string(L, "script_description");
|
|
|
|
author = get_global_string(L, "script_author");
|
|
|
|
version = get_global_string(L, "script_version");
|
|
|
|
|
|
|
|
if (name.empty())
|
2007-02-14 01:43:01 +01:00
|
|
|
name = GetPrettyFilename();
|
2011-09-28 21:48:37 +02:00
|
|
|
|
|
|
|
lua_pop(L, 1);
|
2006-12-28 22:18:35 +01:00
|
|
|
// if we got this far, the script should be ready
|
2008-03-09 22:09:51 +01:00
|
|
|
_stackcheck.check_stack(0);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
}
|
2011-09-28 21:48:28 +02:00
|
|
|
catch (agi::Exception const& e) {
|
2007-02-14 01:43:01 +01:00
|
|
|
Destroy();
|
|
|
|
name = GetPrettyFilename();
|
2011-09-28 21:48:28 +02:00
|
|
|
description = e.GetChainedMessage();
|
2007-02-14 01:43:01 +01:00
|
|
|
}
|
2011-09-28 21:48:37 +02:00
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
void LuaScript::Destroy()
|
|
|
|
{
|
|
|
|
// Assume the script object is clean if there's no Lua state
|
|
|
|
if (!L) return;
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
// loops backwards because commands remove themselves from macros when
|
|
|
|
// they're unregistered
|
|
|
|
for (int i = macros.size() - 1; i >= 0; --i)
|
|
|
|
cmd::unreg(macros[i]->name());
|
|
|
|
|
|
|
|
delete_clear(filters);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
lua_close(L);
|
|
|
|
L = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LuaScript::Reload()
|
|
|
|
{
|
|
|
|
Create();
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:52:28 +02:00
|
|
|
void LuaScript::RegisterCommand(LuaCommand *command)
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < macros.size(); ++i) {
|
|
|
|
if (macros[i]->name() == command->name()) {
|
|
|
|
luaL_error(L,
|
|
|
|
"A macro named '%s' is already defined in script '%s'",
|
|
|
|
command->StrDisplay(0).utf8_str().data(), name.utf8_str().data());
|
|
|
|
}
|
|
|
|
}
|
2011-09-28 21:48:47 +02:00
|
|
|
macros.push_back(command);
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:52:28 +02:00
|
|
|
void LuaScript::UnregisterCommand(LuaCommand *command)
|
|
|
|
{
|
2011-09-28 21:48:47 +02:00
|
|
|
macros.erase(remove(macros.begin(), macros.end(), command), macros.end());
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:52:28 +02:00
|
|
|
void LuaScript::RegisterFilter(LuaExportFilter *filter)
|
|
|
|
{
|
2011-09-28 21:48:47 +02:00
|
|
|
filters.push_back(filter);
|
|
|
|
}
|
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
LuaScript* LuaScript::GetScriptObject(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, "aegisub");
|
|
|
|
void *ptr = lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return (LuaScript*)ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
int LuaScript::LuaTextExtents(lua_State *L)
|
|
|
|
{
|
2011-09-28 21:48:47 +02:00
|
|
|
luaL_argcheck(L, lua_istable(L, 1), 1, "");
|
|
|
|
luaL_argcheck(L, lua_isstring(L, 2), 2, "");
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
lua_pushvalue(L, 1);
|
2011-09-28 21:48:37 +02:00
|
|
|
agi::scoped_ptr<AssEntry> et(LuaAssFile::LuaToAssEntry(L));
|
|
|
|
AssStyle *st = dynamic_cast<AssStyle*>(et.get());
|
2006-12-28 22:18:35 +01:00
|
|
|
lua_pop(L, 1);
|
2011-09-28 21:48:37 +02:00
|
|
|
if (!st)
|
|
|
|
return luaL_error(L, "Not a style entry");
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2007-01-15 18:02:39 +01:00
|
|
|
double width, height, descent, extlead;
|
2011-09-28 21:48:47 +02:00
|
|
|
if (!CalculateTextExtents(st, check_wxstring(L, 2), width, height, descent, extlead))
|
2011-09-28 21:48:37 +02:00
|
|
|
return luaL_error(L, "Some internal error occurred calculating text_extents");
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
lua_pushnumber(L, width);
|
|
|
|
lua_pushnumber(L, height);
|
|
|
|
lua_pushnumber(L, descent);
|
|
|
|
lua_pushnumber(L, extlead);
|
|
|
|
return 4;
|
|
|
|
}
|
|
|
|
|
2010-01-28 02:13:13 +01:00
|
|
|
/// @brief Module loader which uses our include rather than Lua's, for unicode file support
|
|
|
|
/// @param L The Lua state
|
|
|
|
/// @return Always 1 per loader_Lua?
|
|
|
|
int LuaScript::LuaModuleLoader(lua_State *L)
|
|
|
|
{
|
|
|
|
int pretop = lua_gettop(L);
|
2011-09-28 21:48:47 +02:00
|
|
|
wxString module(get_wxstring(L, -1));
|
2010-01-28 02:13:13 +01:00
|
|
|
module.Replace(".", LUA_DIRSEP);
|
|
|
|
|
2011-09-28 21:52:02 +02:00
|
|
|
// Get the lua package include path (which the user may have modified)
|
2010-01-28 02:13:13 +01:00
|
|
|
lua_getglobal(L, "package");
|
|
|
|
lua_pushstring(L, "path");
|
|
|
|
lua_gettable(L, -2);
|
2011-09-28 21:48:47 +02:00
|
|
|
wxString package_paths(get_wxstring(L, -1));
|
2010-01-28 02:13:13 +01:00
|
|
|
lua_pop(L, 2);
|
|
|
|
|
2011-09-28 21:43:11 +02:00
|
|
|
wxStringTokenizer toker(package_paths, ";", wxTOKEN_STRTOK);
|
2010-01-28 02:13:13 +01:00
|
|
|
while (toker.HasMoreTokens()) {
|
|
|
|
wxString filename = toker.GetNextToken();
|
2011-09-28 21:43:11 +02:00
|
|
|
filename.Replace("?", module);
|
2011-09-28 21:52:02 +02:00
|
|
|
try {
|
2010-01-28 02:13:13 +01:00
|
|
|
LuaScriptReader script_reader(filename);
|
|
|
|
if (lua_load(L, script_reader.reader_func, &script_reader, filename.utf8_str())) {
|
2011-09-28 21:48:37 +02:00
|
|
|
return luaL_error(L, "Error loading Lua module \"%s\":\n\n%s", filename.utf8_str().data(), lua_tostring(L, -1));
|
2010-01-28 02:13:13 +01:00
|
|
|
}
|
2011-09-28 21:52:02 +02:00
|
|
|
break;
|
|
|
|
}
|
2012-01-12 23:31:54 +01:00
|
|
|
catch (agi::FileNotFoundError const&) {
|
2011-09-28 21:52:02 +02:00
|
|
|
// Not an error so swallow and continue on
|
|
|
|
}
|
2012-01-12 23:31:54 +01:00
|
|
|
catch (agi::acs::NotAFile const&) {
|
2011-09-28 21:52:02 +02:00
|
|
|
// Not an error so swallow and continue on
|
|
|
|
}
|
|
|
|
catch (agi::Exception const& e) {
|
|
|
|
return luaL_error(L, "Error loading Lua module \"%s\":\n\n%s", filename.utf8_str().data(), e.GetChainedMessage().c_str());
|
2010-01-28 02:13:13 +01:00
|
|
|
}
|
|
|
|
}
|
2011-09-28 21:52:02 +02:00
|
|
|
|
2010-01-28 02:13:13 +01:00
|
|
|
return lua_gettop(L) - pretop;
|
|
|
|
}
|
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
int LuaScript::LuaInclude(lua_State *L)
|
|
|
|
{
|
|
|
|
LuaScript *s = GetScriptObject(L);
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
wxString fnames(check_wxstring(L, 1));
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
wxFileName fname(fnames);
|
|
|
|
if (fname.GetDirCount() == 0) {
|
|
|
|
// filename only
|
|
|
|
fname = s->include_path.FindAbsoluteValidPath(fnames);
|
|
|
|
} else if (fname.IsRelative()) {
|
|
|
|
// relative path
|
|
|
|
wxFileName sfname(s->GetFilename());
|
|
|
|
fname.MakeAbsolute(sfname.GetPath(true));
|
|
|
|
} else {
|
|
|
|
// absolute path, do nothing
|
|
|
|
}
|
2011-09-28 21:48:37 +02:00
|
|
|
if (!fname.IsOk() || !fname.FileExists())
|
|
|
|
return luaL_error(L, "Lua include not found: %s", fnames.utf8_str().data());
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2007-01-15 23:19:50 +01:00
|
|
|
LuaScriptReader script_reader(fname.GetFullPath());
|
2011-09-28 21:48:37 +02:00
|
|
|
if (lua_load(L, script_reader.reader_func, &script_reader, fname.GetFullName().utf8_str()))
|
|
|
|
return luaL_error(L, "Error loading Lua include \"%s\":\n\n%s", fname.GetFullPath().utf8_str().data(), lua_tostring(L, -1));
|
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
int pretop = lua_gettop(L) - 1; // don't count the function value itself
|
|
|
|
lua_call(L, 0, LUA_MULTRET);
|
|
|
|
return lua_gettop(L) - pretop;
|
|
|
|
}
|
|
|
|
|
2007-02-15 13:56:36 +01:00
|
|
|
int LuaScript::LuaFrameFromMs(lua_State *L)
|
|
|
|
{
|
2011-09-28 21:49:47 +02:00
|
|
|
const agi::Context *c = get_context(L);
|
2011-09-28 21:48:37 +02:00
|
|
|
int ms = lua_tointeger(L, -1);
|
2007-02-15 13:56:36 +01:00
|
|
|
lua_pop(L, 1);
|
2012-01-09 21:31:19 +01:00
|
|
|
if (c && c->videoController->TimecodesLoaded())
|
2011-09-28 21:49:47 +02:00
|
|
|
lua_pushnumber(L, c->videoController->FrameAtTime(ms, agi::vfr::START));
|
2011-09-28 21:48:37 +02:00
|
|
|
else
|
2007-02-15 13:56:36 +01:00
|
|
|
lua_pushnil(L);
|
|
|
|
|
2011-09-28 21:48:37 +02:00
|
|
|
return 1;
|
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2007-02-15 13:56:36 +01:00
|
|
|
int LuaScript::LuaMsFromFrame(lua_State *L)
|
|
|
|
{
|
2011-09-28 21:49:47 +02:00
|
|
|
const agi::Context *c = get_context(L);
|
2011-09-28 21:48:37 +02:00
|
|
|
int frame = lua_tointeger(L, -1);
|
2007-02-15 13:56:36 +01:00
|
|
|
lua_pop(L, 1);
|
2012-01-09 21:31:19 +01:00
|
|
|
if (c && c->videoController->TimecodesLoaded())
|
2011-09-28 21:49:47 +02:00
|
|
|
lua_pushnumber(L, c->videoController->TimeAtFrame(frame, agi::vfr::START));
|
2011-09-28 21:48:37 +02:00
|
|
|
else
|
2007-02-15 13:56:36 +01:00
|
|
|
lua_pushnil(L);
|
2011-09-28 21:48:37 +02:00
|
|
|
return 1;
|
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2008-09-10 18:53:23 +02:00
|
|
|
int LuaScript::LuaVideoSize(lua_State *L)
|
|
|
|
{
|
2011-09-28 21:49:47 +02:00
|
|
|
const agi::Context *c = get_context(L);
|
2012-01-09 21:31:19 +01:00
|
|
|
if (c && c->videoController->IsLoaded()) {
|
2011-09-28 21:49:47 +02:00
|
|
|
lua_pushnumber(L, c->videoController->GetWidth());
|
|
|
|
lua_pushnumber(L, c->videoController->GetHeight());
|
|
|
|
lua_pushnumber(L, c->videoController->GetAspectRatioValue());
|
|
|
|
lua_pushnumber(L, c->videoController->GetAspectRatioType());
|
2008-09-10 18:53:23 +02:00
|
|
|
return 4;
|
2011-09-28 21:49:47 +02:00
|
|
|
}
|
|
|
|
else {
|
2008-09-10 18:53:23 +02:00
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-22 22:29:56 +01:00
|
|
|
int LuaScript::LuaGetKeyframes(lua_State *L)
|
|
|
|
{
|
|
|
|
const agi::Context *c = get_context(L);
|
2012-01-09 21:31:19 +01:00
|
|
|
if (!c) {
|
|
|
|
lua_pushnil(L);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-12-22 22:29:56 +01:00
|
|
|
std::vector<int> const& kf = c->videoController->GetKeyFrames();
|
|
|
|
|
|
|
|
lua_newtable(L);
|
|
|
|
for (size_t i = 0; i < kf.size(); ++i) {
|
|
|
|
lua_pushinteger(L, kf[i]);
|
|
|
|
lua_rawseti(L, -2, i);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2011-12-22 22:30:05 +01:00
|
|
|
int LuaScript::LuaDecodePath(lua_State *L)
|
|
|
|
{
|
|
|
|
wxString path = check_wxstring(L, 1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
lua_pushstring(L, StandardPaths::DecodePath(path).utf8_str());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-01-20 22:33:20 +01:00
|
|
|
int LuaScript::LuaCancel(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_pushnil(L);
|
|
|
|
return lua_error(L);
|
|
|
|
}
|
|
|
|
|
2011-10-25 03:15:03 +02:00
|
|
|
static void lua_threaded_call(ProgressSink *ps, lua_State *L, int nargs, int nresults, bool can_open_config, bool *failed)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2011-09-28 21:47:40 +02:00
|
|
|
LuaProgressSink lps(L, ps, can_open_config);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:47:40 +02:00
|
|
|
if (lua_pcall(L, nargs, nresults, 0)) {
|
2012-01-20 22:33:20 +01:00
|
|
|
if (!lua_isnil(L, -1)) {
|
|
|
|
// if the call failed, log the error here
|
|
|
|
ps->Log("\n\nLua reported a runtime error:\n");
|
|
|
|
ps->Log(lua_tostring(L, -1));
|
|
|
|
}
|
2011-09-28 21:48:37 +02:00
|
|
|
lua_pop(L, 1);
|
2011-10-25 03:15:03 +02:00
|
|
|
*failed = true;
|
2011-09-28 21:48:37 +02:00
|
|
|
}
|
2007-02-20 03:50:40 +01:00
|
|
|
|
2011-09-28 21:47:40 +02:00
|
|
|
lua_gc(L, LUA_GCCOLLECT, 0);
|
2011-09-28 21:48:37 +02:00
|
|
|
}
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:47:40 +02:00
|
|
|
void LuaThreadedCall(lua_State *L, int nargs, int nresults, wxString const& title, wxWindow *parent, bool can_open_config)
|
|
|
|
{
|
2011-10-25 03:15:03 +02:00
|
|
|
bool failed = false;
|
2011-09-28 21:47:40 +02:00
|
|
|
BackgroundScriptRunner bsr(parent, title);
|
2012-09-25 01:35:27 +02:00
|
|
|
bsr.Run(std::bind(lua_threaded_call, std::placeholders::_1, L, nargs, nresults, can_open_config, &failed));
|
2011-10-25 03:15:03 +02:00
|
|
|
if (failed)
|
|
|
|
throw agi::UserCancelException("Script threw an error");
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// LuaFeature
|
2011-09-28 21:48:47 +02:00
|
|
|
LuaFeature::LuaFeature(lua_State *L)
|
2012-10-26 16:09:14 +02:00
|
|
|
: myid(0)
|
|
|
|
, L(L)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void LuaFeature::RegisterFeature()
|
|
|
|
{
|
2011-09-28 21:48:47 +02:00
|
|
|
myid = luaL_ref(L, LUA_REGISTRYINDEX);
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
void LuaFeature::UnregisterFeature()
|
|
|
|
{
|
|
|
|
luaL_unref(L, LUA_REGISTRYINDEX, myid);
|
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2012-01-20 22:33:39 +01:00
|
|
|
void LuaFeature::GetFeatureFunction(const char *function) const
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
|
|
|
// get this feature's function pointers
|
2011-09-28 21:48:47 +02:00
|
|
|
lua_rawgeti(L, LUA_REGISTRYINDEX, myid);
|
2006-12-28 22:18:35 +01:00
|
|
|
// get pointer for validation function
|
2011-09-28 21:48:47 +02:00
|
|
|
lua_pushstring(L, function);
|
|
|
|
lua_rawget(L, -2);
|
|
|
|
// remove the function table
|
2006-12-28 22:18:35 +01:00
|
|
|
lua_remove(L, -2);
|
2011-09-28 21:48:47 +02:00
|
|
|
assert(lua_isfunction(L, -1));
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
// LuaFeatureMacro
|
|
|
|
int LuaCommand::LuaRegister(lua_State *L)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2011-09-28 21:48:47 +02:00
|
|
|
cmd::reg(new LuaCommand(L));
|
|
|
|
return 0;
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
LuaCommand::LuaCommand(lua_State *L)
|
|
|
|
: LuaFeature(L)
|
|
|
|
, display(check_wxstring(L, 1))
|
2012-01-25 01:21:37 +01:00
|
|
|
, help(get_wxstring(L, 2))
|
2011-09-28 21:48:47 +02:00
|
|
|
, cmd_type(cmd::COMMAND_NORMAL)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2011-09-28 21:52:20 +02:00
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, "filename");
|
|
|
|
cmd_name = STD_STR(wxString::Format("automation/lua/%s/%s", get_wxstring(L, -1), check_wxstring(L, 1)));
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
if (!lua_isfunction(L, 3))
|
|
|
|
luaL_error(L, "The macro processing function must be a function");
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
if (lua_isfunction(L, 4))
|
|
|
|
cmd_type |= cmd::COMMAND_VALIDATE;
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
if (lua_isfunction(L, 5))
|
|
|
|
cmd_type |= cmd::COMMAND_TOGGLE;
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
// new table for containing the functions for this feature
|
|
|
|
lua_newtable(L);
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
// store processing function
|
|
|
|
lua_pushstring(L, "run");
|
|
|
|
lua_pushvalue(L, 3);
|
|
|
|
lua_rawset(L, -3);
|
|
|
|
|
|
|
|
// store validation function
|
|
|
|
lua_pushstring(L, "validate");
|
|
|
|
lua_pushvalue(L, 4);
|
|
|
|
lua_rawset(L, -3);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
// store active function
|
|
|
|
lua_pushstring(L, "isactive");
|
|
|
|
lua_pushvalue(L, 5);
|
|
|
|
lua_rawset(L, -3);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
// store the table in the registry
|
|
|
|
RegisterFeature();
|
|
|
|
|
|
|
|
LuaScript::GetScriptObject(L)->RegisterCommand(this);
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
LuaCommand::~LuaCommand()
|
|
|
|
{
|
|
|
|
UnregisterFeature();
|
|
|
|
LuaScript::GetScriptObject(L)->UnregisterCommand(this);
|
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
static int transform_selection(lua_State *L, const agi::Context *c)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2012-10-05 05:22:54 +02:00
|
|
|
SubtitleSelection const& sel = c->selectionController->GetSelectedSet();
|
2011-09-28 21:48:47 +02:00
|
|
|
AssDialogue *active_line = c->selectionController->GetActiveLine();
|
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
lua_newtable(L);
|
2011-09-28 21:48:47 +02:00
|
|
|
int active_idx = -1;
|
|
|
|
|
|
|
|
int row = 1;
|
|
|
|
int idx = 1;
|
|
|
|
for (entryIter it = c->ass->Line.begin(); it != c->ass->Line.end(); ++it, ++row) {
|
2012-10-12 19:16:39 +02:00
|
|
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
|
2011-09-28 21:48:47 +02:00
|
|
|
if (!diag) continue;
|
|
|
|
|
|
|
|
if (diag == active_line) active_idx = row;
|
|
|
|
if (sel.count(diag)) {
|
|
|
|
lua_pushinteger(L, row);
|
|
|
|
lua_rawseti(L, -2, idx++);
|
|
|
|
}
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
return active_idx;
|
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
bool LuaCommand::Validate(const agi::Context *c)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2011-09-28 21:48:47 +02:00
|
|
|
if (!(cmd_type & cmd::COMMAND_VALIDATE)) return true;
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:49:47 +02:00
|
|
|
set_context(L, c);
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
GetFeatureFunction("validate");
|
|
|
|
LuaAssFile *subsobj = new LuaAssFile(L, c->ass);
|
|
|
|
lua_pushinteger(L, transform_selection(L, c));
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2012-01-25 01:21:37 +01:00
|
|
|
int err = lua_pcall(L, 3, 2, 0);
|
2011-09-28 21:48:47 +02:00
|
|
|
|
|
|
|
subsobj->ProcessingComplete();
|
|
|
|
|
2012-01-25 01:21:37 +01:00
|
|
|
if (err) {
|
2011-09-28 21:48:47 +02:00
|
|
|
wxLogWarning("Runtime error in Lua macro validation function:\n%s", get_wxstring(L, -1));
|
2012-01-25 01:21:37 +01:00
|
|
|
lua_pop(L, 1);
|
|
|
|
return false;
|
|
|
|
}
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2012-01-25 01:21:37 +01:00
|
|
|
bool result = !!lua_toboolean(L, -2);
|
|
|
|
|
|
|
|
wxString new_help_string(get_wxstring(L, -1));
|
|
|
|
if (new_help_string.size()) {
|
|
|
|
help = new_help_string;
|
|
|
|
cmd_type |= cmd::COMMAND_DYNAMIC_HELP;
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_pop(L, 2);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
void LuaCommand::operator()(agi::Context *c)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2012-02-10 02:41:22 +01:00
|
|
|
LuaStackcheck stackcheck(L);
|
2011-09-28 21:49:47 +02:00
|
|
|
set_context(L, c);
|
2012-02-10 02:41:22 +01:00
|
|
|
stackcheck.check_stack(0);
|
2011-09-28 21:49:47 +02:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
GetFeatureFunction("run");
|
|
|
|
LuaAssFile *subsobj = new LuaAssFile(L, c->ass, true, true);
|
|
|
|
lua_pushinteger(L, transform_selection(L, c));
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:50:14 +02:00
|
|
|
try {
|
2012-01-31 01:44:16 +01:00
|
|
|
LuaThreadedCall(L, 3, 2, StrDisplay(c), c->parent, true);
|
2011-09-28 21:50:14 +02:00
|
|
|
|
|
|
|
subsobj->ProcessingComplete(StrDisplay(c));
|
|
|
|
|
2012-01-31 01:44:16 +01:00
|
|
|
AssDialogue *active_line = 0;
|
|
|
|
int active_idx = 0;
|
|
|
|
|
|
|
|
// Check for a new active row
|
|
|
|
if (lua_isnumber(L, -1)) {
|
|
|
|
active_idx = lua_tointeger(L, -1);
|
|
|
|
if (active_idx < 1 || active_idx > (int)c->ass->Line.size()) {
|
|
|
|
wxLogError("Active row %d is out of bounds (must be 1-%u)", active_idx, c->ass->Line.size());
|
|
|
|
active_idx = 0;
|
|
|
|
}
|
|
|
|
}
|
2012-02-10 02:41:22 +01:00
|
|
|
|
|
|
|
stackcheck.check_stack(2);
|
2012-01-31 01:44:16 +01:00
|
|
|
lua_pop(L, 1);
|
|
|
|
|
2011-09-28 21:50:14 +02:00
|
|
|
// top of stack will be selected lines array, if any was returned
|
|
|
|
if (lua_istable(L, -1)) {
|
|
|
|
std::set<AssDialogue*> sel;
|
|
|
|
entryIter it = c->ass->Line.begin();
|
|
|
|
int last_idx = 1;
|
|
|
|
lua_pushnil(L);
|
|
|
|
while (lua_next(L, -2)) {
|
|
|
|
if (lua_isnumber(L, -1)) {
|
|
|
|
int cur = lua_tointeger(L, -1);
|
|
|
|
if (cur < 1 || cur > (int)c->ass->Line.size()) {
|
|
|
|
wxLogError("Selected row %d is out of bounds (must be 1-%u)", cur, c->ass->Line.size());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
advance(it, cur - last_idx);
|
|
|
|
|
2012-10-12 19:16:39 +02:00
|
|
|
AssDialogue *diag = dynamic_cast<AssDialogue*>(&*it);
|
2011-09-28 21:50:14 +02:00
|
|
|
if (!diag) {
|
|
|
|
wxLogError("Selected row %d is not a dialogue line", cur);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
sel.insert(diag);
|
|
|
|
last_idx = cur;
|
2012-01-31 01:44:16 +01:00
|
|
|
if (!active_line || active_idx == cur)
|
|
|
|
active_line = diag;
|
2011-09-28 21:48:47 +02:00
|
|
|
}
|
2011-09-28 21:50:14 +02:00
|
|
|
lua_pop(L, 1);
|
2007-07-06 16:26:04 +02:00
|
|
|
}
|
2011-09-28 21:48:47 +02:00
|
|
|
|
2012-05-05 04:11:09 +02:00
|
|
|
AssDialogue *new_active = c->selectionController->GetActiveLine();
|
|
|
|
if (active_line && (active_idx > 0 || !sel.count(new_active)))
|
|
|
|
new_active = active_line;
|
|
|
|
c->selectionController->SetSelectionAndActive(sel, new_active);
|
2011-09-28 21:50:14 +02:00
|
|
|
}
|
2012-02-10 02:41:22 +01:00
|
|
|
|
|
|
|
stackcheck.check_stack(1);
|
|
|
|
lua_pop(L, 1);
|
2011-09-28 21:50:14 +02:00
|
|
|
}
|
|
|
|
catch (agi::UserCancelException const&) {
|
|
|
|
subsobj->Cancel();
|
2007-07-06 16:26:04 +02:00
|
|
|
}
|
2012-02-10 03:16:49 +01:00
|
|
|
stackcheck.check_stack(0);
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
bool LuaCommand::IsActive(const agi::Context *c)
|
|
|
|
{
|
2011-09-28 21:49:18 +02:00
|
|
|
if (!(cmd_type & cmd::COMMAND_TOGGLE)) return false;
|
|
|
|
|
2012-02-10 03:16:49 +01:00
|
|
|
LuaStackcheck stackcheck(L);
|
|
|
|
|
2011-09-28 21:49:47 +02:00
|
|
|
set_context(L, c);
|
2012-02-10 03:16:49 +01:00
|
|
|
stackcheck.check_stack(0);
|
2011-09-28 21:49:47 +02:00
|
|
|
|
2011-09-28 21:49:18 +02:00
|
|
|
GetFeatureFunction("isactive");
|
|
|
|
LuaAssFile *subsobj = new LuaAssFile(L, c->ass);
|
|
|
|
lua_pushinteger(L, transform_selection(L, c));
|
|
|
|
|
|
|
|
int err = lua_pcall(L, 3, 1, 0);
|
|
|
|
subsobj->ProcessingComplete();
|
|
|
|
|
|
|
|
bool result = false;
|
|
|
|
if (err)
|
|
|
|
wxLogWarning("Runtime error in Lua macro IsActive function:\n%s", get_wxstring(L, -1));
|
|
|
|
else
|
|
|
|
result = !!lua_toboolean(L, -1);
|
|
|
|
|
|
|
|
// clean up stack (result or error message)
|
2012-02-10 03:16:49 +01:00
|
|
|
stackcheck.check_stack(1);
|
2011-09-28 21:49:18 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
|
|
|
|
return result;
|
2011-09-28 21:48:47 +02:00
|
|
|
}
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
// LuaFeatureFilter
|
2011-09-28 21:48:47 +02:00
|
|
|
LuaExportFilter::LuaExportFilter(lua_State *L)
|
|
|
|
: ExportFilter(check_wxstring(L, 1), get_wxstring(L, 2), lua_tointeger(L, 3))
|
|
|
|
, LuaFeature(L)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2011-09-28 21:48:47 +02:00
|
|
|
if (!lua_isfunction(L, 4))
|
|
|
|
luaL_error(L, "The filter processing function must be a function");
|
|
|
|
|
|
|
|
// new table for containing the functions for this feature
|
2006-12-28 22:18:35 +01:00
|
|
|
lua_newtable(L);
|
2011-09-28 21:48:47 +02:00
|
|
|
|
|
|
|
// store processing function
|
|
|
|
lua_pushstring(L, "run");
|
2006-12-28 22:18:35 +01:00
|
|
|
lua_pushvalue(L, 4);
|
2011-09-28 21:48:47 +02:00
|
|
|
lua_rawset(L, -3);
|
|
|
|
|
|
|
|
// store config function
|
|
|
|
lua_pushstring(L, "config");
|
2006-12-28 22:18:35 +01:00
|
|
|
lua_pushvalue(L, 5);
|
|
|
|
has_config = lua_isfunction(L, -1);
|
2011-09-28 21:48:47 +02:00
|
|
|
lua_rawset(L, -3);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
// store the table in the registry
|
|
|
|
RegisterFeature();
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
LuaScript::GetScriptObject(L)->RegisterFilter(this);
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
int LuaExportFilter::LuaRegister(lua_State *L)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2011-09-28 21:48:47 +02:00
|
|
|
(void)new LuaExportFilter(L);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
void LuaExportFilter::ProcessSubs(AssFile *subs, wxWindow *export_dialog)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
2008-01-24 00:02:26 +01:00
|
|
|
LuaStackcheck stackcheck(L);
|
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
GetFeatureFunction("run");
|
2008-03-09 22:09:51 +01:00
|
|
|
stackcheck.check_stack(1);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:48:47 +02:00
|
|
|
// The entire point of an export filter is to modify the file, but
|
|
|
|
// setting undo points makes no sense
|
|
|
|
LuaAssFile *subsobj = new LuaAssFile(L, subs, true);
|
2008-01-24 00:02:26 +01:00
|
|
|
assert(lua_isuserdata(L, -1));
|
2008-03-09 22:09:51 +01:00
|
|
|
stackcheck.check_stack(2);
|
2011-09-28 21:48:47 +02:00
|
|
|
|
2006-12-28 22:18:35 +01:00
|
|
|
// config
|
|
|
|
if (has_config && config_dialog) {
|
2008-01-24 00:02:26 +01:00
|
|
|
int results_produced = config_dialog->LuaReadBack(L);
|
|
|
|
assert(results_produced == 1);
|
2008-03-13 20:12:55 +01:00
|
|
|
(void) results_produced; // avoid warning on release builds
|
2006-12-28 22:18:35 +01:00
|
|
|
// TODO, write back stored options here
|
2007-02-20 03:50:40 +01:00
|
|
|
} else {
|
|
|
|
// no config so put an empty table instead
|
|
|
|
lua_newtable(L);
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
2008-01-24 00:02:26 +01:00
|
|
|
assert(lua_istable(L, -1));
|
2008-03-09 22:09:51 +01:00
|
|
|
stackcheck.check_stack(3);
|
2006-12-28 22:18:35 +01:00
|
|
|
|
2011-09-28 21:50:14 +02:00
|
|
|
try {
|
|
|
|
LuaThreadedCall(L, 2, 0, GetName(), export_dialog, false);
|
|
|
|
stackcheck.check_stack(0);
|
|
|
|
subsobj->ProcessingComplete();
|
|
|
|
}
|
|
|
|
catch (agi::UserCancelException const&) {
|
|
|
|
subsobj->Cancel();
|
|
|
|
throw;
|
|
|
|
}
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:49:27 +02:00
|
|
|
ScriptDialog* LuaExportFilter::GenerateConfigDialog(wxWindow *parent, agi::Context *c)
|
2006-12-28 22:18:35 +01:00
|
|
|
{
|
|
|
|
if (!has_config)
|
|
|
|
return 0;
|
|
|
|
|
2011-09-28 21:49:47 +02:00
|
|
|
set_context(L, c);
|
|
|
|
|
2011-11-30 00:17:20 +01:00
|
|
|
GetFeatureFunction("config");
|
2006-12-28 22:18:35 +01:00
|
|
|
|
|
|
|
// prepare function call
|
2011-09-28 21:48:47 +02:00
|
|
|
LuaAssFile *subsobj = new LuaAssFile(L, c->ass);
|
2006-12-28 22:18:35 +01:00
|
|
|
// stored options
|
|
|
|
lua_newtable(L); // TODO, nothing for now
|
|
|
|
|
|
|
|
// do call
|
2009-07-28 17:39:52 +02:00
|
|
|
int err = lua_pcall(L, 2, 1, 0);
|
2011-09-28 21:48:47 +02:00
|
|
|
subsobj->ProcessingComplete();
|
|
|
|
|
2009-07-28 17:39:52 +02:00
|
|
|
if (err) {
|
2011-09-28 21:48:47 +02:00
|
|
|
wxLogWarning("Runtime error in Lua config dialog function:\n%s", get_wxstring(L, -1));
|
2009-07-28 17:39:52 +02:00
|
|
|
lua_pop(L, 1); // remove error message
|
|
|
|
} else {
|
|
|
|
// Create config dialogue from table on top of stack
|
2011-09-28 21:49:27 +02:00
|
|
|
config_dialog = new LuaDialog(L, false);
|
2007-02-20 03:50:40 +01:00
|
|
|
}
|
2011-09-28 21:48:47 +02:00
|
|
|
|
|
|
|
return config_dialog;
|
2006-12-28 22:18:35 +01:00
|
|
|
}
|
|
|
|
|
2011-09-28 21:46:05 +02:00
|
|
|
LuaScriptFactory::LuaScriptFactory()
|
|
|
|
: ScriptFactory("Lua", "*.lua")
|
2008-03-09 22:49:46 +01:00
|
|
|
{
|
|
|
|
Register(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
Script* LuaScriptFactory::Produce(const wxString &filename) const
|
|
|
|
{
|
|
|
|
// Just check if file extension is .lua
|
|
|
|
// Reject anything else
|
2011-09-28 21:43:11 +02:00
|
|
|
if (filename.Right(4).Lower() == ".lua") {
|
2008-03-09 22:49:46 +01:00
|
|
|
return new LuaScript(filename);
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2011-09-28 21:48:47 +02:00
|
|
|
}
|
2007-12-31 07:46:22 +01:00
|
|
|
|
2008-03-05 00:17:07 +01:00
|
|
|
#endif // WITH_AUTO4_LUA
|