Added shb's incomplete perl support code (doesn't build on VC++ yet)

Originally committed to SVN as r1741.
This commit is contained in:
Rodrigo Braz Monteiro 2008-01-16 18:29:29 +00:00
parent 62bbb59273
commit c2aaa4eb8c
39 changed files with 2035 additions and 68 deletions

View file

@ -5,7 +5,7 @@
*
*/
#include "config.h"
#ifdef WITH_DIRECTSHOW
#include <windows.h>
#ifdef __WXDEBUG__

View file

@ -39,7 +39,6 @@
///////////
// Headers
#include "config.h"
#ifdef WITH_DIRECTSOUND
#include <wx/wxprec.h>

View file

@ -36,7 +36,6 @@
///////////
// Headers
#include "config.h"
#ifdef WITH_FFMPEG
#ifdef WIN32

View file

@ -33,7 +33,7 @@
// Contact: mailto:jiifurusu@gmail.com
//
#include "config.h"
#ifdef WITH_AUTOMATION
#ifdef WITH_AUTO3

View file

@ -33,7 +33,7 @@
// Contact: mailto:jiifurusu@gmail.com
//
#include "config.h"
#ifdef WITH_AUTOMATION
#include "auto4_base.h"

View file

@ -33,7 +33,6 @@
// Contact: mailto:jiifurusu@gmail.com
//
#include "config.h"
#ifdef WITH_AUTOMATION
#include "auto4_lua.h"

View file

@ -33,7 +33,6 @@
// Contact: mailto:jiifurusu@gmail.com
//
#include "config.h"
#ifdef WITH_AUTOMATION
#include "auto4_lua.h"

View file

@ -34,7 +34,6 @@
//
#include "config.h"
#ifdef WITH_AUTOMATION
#include "auto4_lua.h"

View file

@ -33,7 +33,6 @@
// Contact: mailto:jiifurusu@gmail.com
//
#include "config.h"
#ifdef WITH_AUTOMATION
#include "auto4_lua_scriptreader.h"

117
aegisub/auto4_perl.cpp Normal file
View file

@ -0,0 +1,117 @@
// Copyright (c) 2008, Simone Cociancich
// 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
//
#ifdef WITH_PERL
#include "auto4_perl.h"
namespace Automation4 {
///////////////////////////////////
// Perl -> C++ interface (XSUBS)
//
EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);
// Copypasted from somewhere
EXTERN_C void xs_perl_main(pTHX)
{
dXSUB_SYS;
/* DynaLoader is a special case */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__);
// My XSUBS ^^
xs_perl_script(aTHX);
xs_perl_misc(aTHX);
xs_perl_console(aTHX);
}
///////////////////////
// PerlScriptFactory
//
class PerlScriptFactory : public ScriptFactory {
private:
PerlInterpreter *parser;
public:
PerlScriptFactory()
{
// Script engine properties
engine_name = _T("Perl");
filename_pattern = _T("*") _T(PERL_SCRIPT_EXTENSION);
// Perl interpreter initialization (ONE FOR ALL THE SCRIPTS)
parser = perl_alloc();
perl_construct(parser);
char *_embedding[] = { "aegisub", "-e", "0" };
perl_parse(parser, xs_perl_main,
3, _embedding,
NULL);
// (That was pretty magic o_O)
// Let's register the perl script factory \o/
Register(this);
}
~PerlScriptFactory()
{
// Perl interpreter deinitialization
perl_destruct(parser);
perl_free(parser);
}
virtual Script* Produce(const wxString &filename) const
{
if(filename.EndsWith(_T(PERL_SCRIPT_EXTENSION))) {
return new PerlScript(filename);
}
else {
return 0;
}
}
};
// The one and only (thank goodness ¬.¬) perl engine!!!
PerlScriptFactory _perl_script_factory;
};
#endif //WITH_PERL

180
aegisub/auto4_perl.h Normal file
View file

@ -0,0 +1,180 @@
// Copyright (c) 2008, Simone Cociancich
// 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
//
#pragma once
#ifndef _AUTO4_PERL_H
#define _AUTO4_PERL_H
#include "auto4_base.h"
#include <wx/window.h>
#include <wx/string.h>
#include "ass_file.h"
//#include "ass_dialogue.h"
#include <EXTERN.h>
#include <perl.h>
#include <XSUB.h>
#include "auto4_perldata.inc" // Parl variables manipulation macros
// the fucking perl.h redefines _() -.- please disregard warnings during compilation
#define _(s) wxGetTranslation(_T(s))
// String conversions between wxWidgets and Perl
#define wx2pl wxConvUTF8
#define pl2wx wxConvUTF8
#define PERL_SCRIPT_EXTENSION ".pl" /* TODO maybe: make it multi-extension */
namespace Automation4 {
///////////
// XSUBS
//
void xs_perl_script(pTHX);
void xs_perl_misc(pTHX);
void xs_perl_console(pTHX);
///////////////////
// Script object
//
class PerlFeatureMacro;
class PerlScript : public Script {
private:
static PerlScript *active; // The active script (at any given time)
AV *inc_saved;
wxString package; // Every script resides in a package named at random
bool reload; // Automatically reload if source file has changed
time_t mtime; // The mtime of the loaded source file
void load(); // It doas all the script initialization
void unload(); // It does all the script disposing
static void activate(PerlScript *script); // Set the active script /* TODO: add @INC hacking */
static void deactivate(); // Unset the active script
public:
PerlScript(const wxString &filename);
virtual ~PerlScript();
virtual void Reload(); // Reloading of a loaded script
void Activate() { activate(this); } // Set the script as active
void Deactivate() const { deactivate(); } // Unset the active script
const wxString& GetPackage() const { return package; } // The perl package containing script code
static PerlScript *GetScript() { return active; } // Query the value of the active script
/* TODO maybe: change these into tying of scalars */
void ReadVars(); // Sync the script's vars from perl package to script object
void WriteVars() const; // Sync the script's vars from script object to perl package
/* TODO: add c++ equivalents */
static XS(set_info); // Aegisub::Script::set_info()
void AddFeature(Feature *feature);
void DeleteFeature(Feature *feature);
static XS(register_macro); // Aegisub::Script::register_macro()
static XS(register_console); // Aegisub::Script::register_console() /* TODO: move this into PerlConsole class */
};
//////////////////
// Macro object
//
class PerlFeatureMacro : public FeatureMacro {
private:
SV *processing_sub; // May be reference or name of sub
SV *validation_sub; // here too
protected:
PerlScript *script; // The owner script
public:
PerlFeatureMacro(const wxString &name, const wxString &description, PerlScript *perl_script, SV *proc_sub, SV *val_sub);
virtual ~PerlFeatureMacro();
virtual bool Validate(AssFile *subs, const std::vector<int> &selected, int active);
virtual void Process(AssFile *subs, std::vector<int> &selected, int active, wxWindow * const progress_parent);
};
///////////////////////////////////////////////////
// Conversion between aegisub data and perl data
//
class PerlAss {
private:
public:
static wxString GetEntryClass(AssEntry *entry);
static HV *MakeHasshEntry(AssEntry *entry);
static HV *MakeHasshStyle(AssStyle *style);
static HV *MakeHasshDialogue(AssDialogue *diag);
static AV *MakeHasshLines(AV *lines, AssFile *ass);
static AssEntry *MakeAssEntry(HV *entry);
static AssStyle *MakeAssStyle(HV *style);
static AssDialogue *MakeAssDialogue(HV *diag);
static AssFile *MakeAssLines(AssFile *ass, AV *lines);
};
/////////////////////////
// Misc utility functions
//
class PerlLog {
public:
static XS(log_warning); // Aegisub::warn()
};
XS(text_extents); // Aegisub::text_extents()
};
#endif

463
aegisub/auto4_perl_ass.cpp Normal file
View file

@ -0,0 +1,463 @@
// Copyright (c) 2008, Simone Cociancich
// 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
//
#ifdef WITH_PERL
#include "auto4_perl.h"
#include "ass_file.h"
#include "ass_entry.h"
#include "ass_style.h"
#include "ass_dialogue.h"
#include "ass_attachment.h"
// For wxString::Trim
#define right true
#define left false
#define HASSH_BASIC_INIT(ae, he) \
HV_TOUCH(he, "raw", 3)\
HV_STORE(newSVpv(ae->GetEntryData().mb_str(wx2pl), 0));\
HV_TOUCH(he, "section", 7)\
HV_STORE(newSVpv(ae->group.mb_str(wx2pl), 0));\
wxString he ## _class = GetEntryClass(ae);\
HV_TOUCH(he, "class", 5)\
HV_STORE(newSVpv(he ## _class.mb_str(wx2pl), 0))
#define ASS_BASIC_INIT(he, ae) \
HV_FETCH(he, "raw", 3)\
ae->SetEntryData(wxString(SvPV_nolen(HV_VAL), pl2wx));\
HV_FETCH(he, "section", 7)\
ae->group = wxString(SvPV_nolen(HV_VAL), pl2wx)
namespace Automation4 {
wxString PerlAss::GetEntryClass(AssEntry *entry)
{
wxString data = entry->GetEntryData();
if(entry->GetType() == ENTRY_DIALOGUE) return _T("dialogue");
if(entry->GetType() == ENTRY_STYLE) {
return _T("style");
/* TODO: add stylex recognition */
}
if(entry->GetType() == ENTRY_BASE) {
if(entry->group == _T("[Script Info]") && data.Matches(_T("*:*"))) return _T("info");
if(data == entry->group) return _T("head");
if(data.StartsWith(_T("Format:"))) return _T("format");
if(data.IsEmpty()) return _T("clear");
if(data.Trim(left).StartsWith(_T(";"))) return _T("comment");
}
// Fallback
return _T("unknown");
}
HV *PerlAss::MakeHasshEntry(AssEntry *e)
{
switch((int)e->GetType()) {
case ENTRY_DIALOGUE:
return MakeHasshDialogue(AssEntry::GetAsDialogue(e));
case ENTRY_STYLE:
return MakeHasshStyle(AssEntry::GetAsStyle(e));
default:
case ENTRY_BASE:
dHV;
HV *entry = newHV();
HASSH_BASIC_INIT(e, entry);
if(entry_class == _T("info")) {
// Info
HV_TOUCH(entry, "key", 3) {
wxString _text = e->GetEntryData().BeforeFirst(_T(':')).Strip(wxString::both);
HV_STORE(newSVpv(_text.mb_str(wx2pl), 0));
}
HV_TOUCH(entry, "value", 5) {
wxString _text = e->GetEntryData().AfterFirst(_T(':')).Strip(wxString::both);
HV_STORE(newSVpv(_text.mb_str(wx2pl), 0));
}
}
else if(entry_class == _T("format")) {
// Format °_°
HV_TOUCH(entry, "fields", 6) {
AV *fields_av = newAV();
HV_STORE(newRV_noinc((SV*)fields_av));
for(wxString fields_buf = e->GetEntryData().AfterFirst(_T(':')).Trim(left);
!fields_buf.IsEmpty();
fields_buf = fields_buf.AfterFirst(_T(',')).Trim(left)) {
av_push(fields_av, newSVpv(fields_buf.BeforeFirst(_T(',')).Trim(right).mb_str(wx2pl), 0));
}
}
}
else if(entry_class == _T("comment")) {
// Comment
HV_TOUCH(entry, "text", 4) {
wxString _text = e->GetEntryData().AfterFirst(_T(';'));
HV_STORE(newSVpv(_text.mb_str(wx2pl), 0));
}
}
return entry;
}
}
HV *PerlAss::MakeHasshStyle(AssStyle *s)
{
dHV;
// Create new empty hash
HV *style = newHV();
// Add fields
HASSH_BASIC_INIT(s, style);
HV_TOUCH(style, "name", 4)
HV_STORE(newSVpv(s->name.mb_str(wx2pl), 0));
HV_TOUCH(style, "font", 4)
HV_STORE(newSVpv(s->font.mb_str(wx2pl), 0));
HV_FAS(style, "fontsize", 8, nv, s->fontsize);
HV_TOUCH(style, "color1", 6)
HV_STORE(newSVpv(s->primary.GetASSFormatted(true).mb_str(wx2pl), 0));
HV_TOUCH(style, "color2", 6)
HV_STORE(newSVpv(s->secondary.GetASSFormatted(true).mb_str(wx2pl), 0));
HV_TOUCH(style, "color3", 6)
HV_STORE(newSVpv(s->outline.GetASSFormatted(true).mb_str(wx2pl), 0));
HV_TOUCH(style, "color4", 6)
HV_STORE(newSVpv(s->shadow.GetASSFormatted(true).mb_str(wx2pl), 0));
HV_TOUCH(style, "bold", 4) HV_STORE(newSViv(s->bold));
HV_FAS(style, "italic", 6, iv, s->italic);
HV_FAS(style, "underline", 9, iv, s->underline);
HV_FAS(style, "strikeout", 9, iv, s->strikeout);
HV_FAS(style, "scale_x", 7, nv, s->scalex);
HV_FAS(style, "scale_y", 7, nv, s->scaley);
HV_FAS(style, "spacing", 7, nv, s->spacing);
HV_FAS(style, "angle", 5, nv, s->angle);
HV_FAS(style, "borderstyle", 11, iv, s->borderstyle);
HV_FAS(style, "outline", 7, nv, s->outline_w);
HV_FAS(style, "shadow", 6, nv, s->shadow_w);
HV_FAS(style, "align", 5, iv, s->alignment);
HV_FAS(style, "margin_l", 8, iv, s->Margin[0]);
HV_FAS(style, "margin_r", 8, iv, s->Margin[1]);
HV_FAS(style, "margin_t", 8, iv, s->Margin[2]);
HV_FAS(style, "margin_b", 8, iv, s->Margin[3]);
HV_FAS(style, "encoding", 8, iv, s->encoding);
HV_FAS(style, "relative_to", 11, iv, s->relativeTo);
// Return the hassh style
return style;
}
HV *PerlAss::MakeHasshDialogue(AssDialogue *d)
{
dHV;
// Create new hash
HV *diag = newHV();
// Copy the values from the AssDialogue
HASSH_BASIC_INIT(d, diag);
HV_FAS(diag, "comment", 7, iv, d->Comment);
HV_FAS(diag, "layer", 5, iv, d->Layer);
HV_FAS(diag, "start_time", 10, iv, d->Start.GetMS());
HV_FAS(diag, "end_time", 8, iv, d->End.GetMS());
HV_TOUCH(diag, "style", 5)
HV_STORE(newSVpv(d->Style.mb_str(wx2pl), 0));
HV_TOUCH(diag, "actor", 5)
HV_STORE(newSVpv(d->Actor.mb_str(wx2pl), 0));
HV_FAS(diag, "margin_l", 8, iv, d->Margin[0]);
HV_FAS(diag, "margin_r", 8, iv, d->Margin[1]);
HV_FAS(diag, "margin_t", 8, iv, d->Margin[2]);
HV_FAS(diag, "margin_b", 8, iv, d->Margin[3]);
HV_TOUCH(diag, "effect", 6)
HV_STORE(newSVpv(d->Effect.mb_str(wx2pl), 0));
HV_TOUCH(diag, "text", 4)
HV_STORE(newSVpv(d->Text.mb_str(wx2pl), 0));
// Return the dialogue
return diag;
}
AV *PerlAss::MakeHasshLines(AV *lines, AssFile *ass)
{
if(!lines) {
lines = newAV();
}
dAV;
I32 i = 0; I32 lines_len = av_len(lines);
for(std::list<AssEntry*>::iterator it = ass->Line.begin(); it != ass->Line.end(); it++) {
if(i <= lines_len && av_exists(lines, i))
av_delete(lines, i, G_DISCARD);
AV_TOUCH(lines, i++)
AV_STORE(newRV_noinc((SV*)MakeHasshEntry(*it)));
}
for(; i <= lines_len; i++) {
if(av_exists(lines, i))
av_delete(lines, i, G_DISCARD);
}
return lines;
}
AssEntry *PerlAss::MakeAssEntry(HV *entry)
{
dHV;
if(!entry) {
// Create an empty line, if NULL
entry = newHV();
}
// The fallback class
wxString cl(_T("unknown"));
// Let's get the actual class of the hassh
HV_FETCH(entry, "class", 5)
cl = wxString(SvPV_nolen(HV_VAL), pl2wx);
// We trust the value of entry{class}
if(cl == _T("dialogue")) {
// It seems to be a dialogue, let's call the specialized function
return MakeAssDialogue(entry);
}
else if(cl == _T("style")) {
// It seems to be a style, let's call the specialized function
return MakeAssStyle(entry);
}
else {
AssEntry *e = new AssEntry();
ASS_BASIC_INIT(entry, e);
// A base entry
if(cl == _T("info")) {
wxString key, value;
HV_FETCH(entry, "key", 3) {
key = wxString(SvPV_nolen(HV_VAL), pl2wx);
HV_FETCH(entry, "value", 5) {
value = wxString(SvPV_nolen(HV_VAL), pl2wx);
e->SetEntryData(key + _T(": ") + value);
}
}
}
// Not necessary, format customization isn't even supported by aegi (atm? °_°)
/*else if(cl == _T("format")) {
HV_FETCH(entry, "fields", 6) {
AV *fields = (AV*)SvRV(HV_VAL);
for(int i = 0; i < av_len(fields); i++) {
SV ** field = av_fetch(fields, i, 0);
if(field) {
wxString field(SvPV_nolen(*field), pl2wx);
}
}
}
}*/
else if(cl == _T("comment")) {
HV_FETCH(entry, "text", 4) {
e->SetEntryData(_T(";") + wxString(SvPV_nolen(HV_VAL), pl2wx));
}
}
return e;
}
}
AssStyle *PerlAss::MakeAssStyle(HV *style)
{
dHV;
// Create a default style
AssStyle *s = new AssStyle();
// Fill it with the values from the hassh
ASS_BASIC_INIT(style, s);
HV_FETCH(style, "name", 4)
s->name = wxString(SvPV_nolen(HV_VAL), pl2wx);
HV_FETCH(style, "font", 4)
s->font = wxString(SvPV_nolen(HV_VAL), pl2wx);
HV_FAA(style, "fontsize", 8, NV, s->fontsize);
HV_FETCH(style, "color1", 6)
s->primary.Parse(wxString(SvPV_nolen(HV_VAL), pl2wx));
HV_FETCH(style, "color2", 6)
s->secondary.Parse(wxString(SvPV_nolen(HV_VAL), pl2wx));
HV_FETCH(style, "color3", 6)
s->outline.Parse(wxString(SvPV_nolen(HV_VAL), pl2wx));
HV_FETCH(style, "color4", 6)
s->shadow.Parse(wxString(SvPV_nolen(HV_VAL), pl2wx));
HV_FAA(style, "bold", 4, IV, s->bold);
HV_FAA(style, "italic", 6, IV, s->italic);
HV_FAA(style, "underline", 9, IV, s->underline);
HV_FAA(style, "strikeout", 9, IV, s->strikeout);
HV_FAA(style, "scale_x", 7, NV, s->scalex);
HV_FAA(style, "scale_y", 7, NV, s->scaley);
HV_FAA(style, "spacing", 7, NV, s->spacing);
HV_FAA(style, "angle", 5, NV, s->angle);
HV_FAA(style, "borderstyle", 11, IV, s->borderstyle);
HV_FAA(style, "outline", 7, NV, s->outline_w);
HV_FAA(style, "shadow", 6, NV, s->shadow_w);
HV_FAA(style, "align", 5, IV, s->alignment);
HV_FAA(style, "margin_l", 8, IV, s->Margin[0]);
HV_FAA(style, "margin_r", 8, IV, s->Margin[1]);
HV_FAA(style, "margin_t", 8, IV, s->Margin[2]);
HV_FAA(style, "margin_b", 8, IV, s->Margin[3]);
HV_FAA(style, "encoding", 8, IV, s->encoding);
HV_FAA(style, "relative_to", 11, IV, s->relativeTo);
// Return the style
return s;
}
AssDialogue *PerlAss::MakeAssDialogue(HV *diag)
{
dHV;
// Create a default dialogue
AssDialogue *d = new AssDialogue();
ASS_BASIC_INIT(diag, d);
HV_FAA(diag, "comment", 7, IV, d->Comment);
HV_FAA(diag, "layer", 5, IV, d->Layer);
HV_FETCH(diag, "start_time", 10)
d->Start.SetMS(SvIV(HV_VAL));
HV_FETCH(diag, "end_time", 8)
d->End.SetMS(SvIV(HV_VAL));
HV_FETCH(diag, "style", 5)
d->Style = wxString(SvPV_nolen(HV_VAL), pl2wx);
HV_FETCH(diag, "actor", 5)
d->Actor = wxString(SvPV_nolen(HV_VAL), pl2wx);
HV_FAA(diag, "margin_l", 8, IV, d->Margin[0]);
HV_FAA(diag, "margin_r", 8, IV, d->Margin[1]);
HV_FAA(diag, "margin_t", 8, IV, d->Margin[2]);
HV_FAA(diag, "margin_b", 8, IV, d->Margin[3]);
HV_FETCH(diag, "effect", 6)
d->Effect = wxString(SvPV_nolen(HV_VAL), pl2wx);
HV_FETCH(diag, "text", 4)
d->Text = wxString(SvPV_nolen(HV_VAL), pl2wx);
// Return the dialogue
return d;
}
AssFile *PerlAss::MakeAssLines(AssFile *ass, AV *lines)
{
if(!ass) {
/* TODO: create new AssFile if NULL */
return NULL;
}
dAV;
std::list<AssEntry*>::iterator it = ass->Line.begin();
for(I32 i = 0; i <= av_len(lines); i++) {
if(!av_exists(lines, i)) continue;
if(i < ass->Line.size()) {
if(*it) delete *it;
AV_FETCH(lines, i)
*it++ = MakeAssEntry((HV*)SvRV(AV_VAL));
}
else {
AV_FETCH(lines, i)
ass->Line.push_back(MakeAssEntry((HV*)SvRV(AV_VAL)));
}
}
for(; it != ass->Line.end();) {
it = ass->Line.erase(it);
}
return ass;
}
};
#endif //WITH_PERL

View file

@ -0,0 +1,272 @@
// Copyright (c) 2008, Simone Cociancich
// 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
//
#ifdef WITH_PERL
#include "auto4_perl.h"
#include "auto4_perl_console.h"
#include "main.h"
#include "frame_main.h"
#include "subs_grid.h"
namespace Automation4 {
void xs_perl_console(pTHX)
{
newXS("Aegisub::PerlConsole::echo", PerlConsole::echo, __FILE__);
newXS("Aegisub::PerlConsole::register_console", PerlConsole::register_console, __FILE__);
}
////////////////////////////////////
// PerlConsole::Dialog
//
inline PerlConsole::Dialog::Dialog()
{
txt_out = NULL;
}
inline bool PerlConsole::Dialog::Create(wxWindow* parent, wxWindowID id, const wxString& title,
const wxPoint& pos, const wxSize& size,
long style, const wxString& name)
{
wxDialog::Create(parent, id, title, pos, size, style, name);
// The text controls in the console
txt_out = new wxTextCtrl(this, -1, _T(""), wxDefaultPosition, wxSize(300,200),
wxTE_MULTILINE | wxTE_READONLY | wxTE_CHARWRAP | wxTE_RICH);
txt_hist = new wxTextCtrl(this, -1, _T(""), wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxTE_READONLY | wxTE_CHARWRAP | wxTE_RICH);
txt_in = new wxTextCtrl(this, -1, _T(""), wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE | wxTE_CHARWRAP | wxTE_PROCESS_ENTER);
// The right panel
wxBoxSizer *rightpanel = new wxBoxSizer(wxVERTICAL);
rightpanel->Add(txt_hist, 1, wxEXPAND);
rightpanel->Add(txt_in, 0, wxEXPAND);
// And the event handler for the input box
Connect(txt_in->GetId(), wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(PerlConsole::Dialog::InputEnter));
// The whole dialog
wxBoxSizer *mainpanel = new wxBoxSizer(wxHORIZONTAL);
mainpanel->Add(txt_out, 1, wxEXPAND | wxRIGHT, 2);
mainpanel->Add(rightpanel, 1, wxEXPAND | wxLEFT, 2);
// Getting it to work
SetSizer(mainpanel);
mainpanel->SetSizeHints(this);
return true;
}
inline void PerlConsole::Dialog::InputEnter(wxCommandEvent& evt)
{
if(txt_in->GetInsertionPoint() == txt_in->GetLastPosition() &&
txt_in->GetLineLength(txt_in->GetNumberOfLines()-1) == 0) {
// If an empty line have been entered...
/* TODO: implement an actual command history */
*txt_hist << txt_in->GetValue() << PerlConsole::Evaluate(txt_in->GetValue()) << _T("\n");
// Resetting the input box
txt_in->ChangeValue(_T(""));
}
else {
// Just a normal line with text
txt_in->WriteText(_T("\n"));
}
}
inline void PerlConsole::Dialog::Echo(const wxString &str)
{
if(txt_out) *txt_out << str << _T("\n");
else PerlIO_printf(PerlIO_stdout(), "%s\n", str.mb_str(wxConvLocal).data());
}
//////////////////////
// PerlConsole
//
PerlConsole *PerlConsole::registered = NULL;
PerlConsole::PerlConsole(const wxString &name, const wxString &desc, PerlScript *script):
Feature(SCRIPTFEATURE_MACRO, name),
/*FeatureMacro(name, description),*/
PerlFeatureMacro(name, desc, script, NULL, NULL)
{
parent_window = NULL;
dialog = new Dialog();
// Fuck off any previously registered console °_°
if(registered) delete registered;
registered = this;
}
PerlConsole::~PerlConsole()
{
if(dialog) dialog->Destroy();
/* TODO: Free something? */
// Delete the registered console
PerlConsole::registered = NULL;
}
void PerlConsole::Process(AssFile *subs, std::vector<int> &selected, int active, wxWindow * const progress_parent)
{
if(!parent_window) {
// Create the console's dialog if it doesn't already exist
parent_window = progress_parent;
dialog->Create(parent_window, -1, GetName(), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
}
// Show the console
dialog->Show(true);
// and return, the console will stay visible and permit running other macros
// the console will 'just' emulate the execution of a macro whenever some code will be evaluated
}
wxString PerlConsole::evaluate(const wxString &str)
{
/* This mimics FrameMain::OnAutomationMacro */
// Get a hold of the SubsBox
SubtitlesGrid *sb = wxGetApp().frame->SubsBox;
sb->BeginBatch();
// Create the @_ (global <.<)
AV *AT = get_av("_", 1);
av_clear(AT);
// $_[0]
AV *lines = PerlAss::MakeHasshLines(NULL, AssFile::top);
av_push(AT, newRV_noinc((SV*)lines));
// $_[1]
std::vector<int> selected_lines = sb->GetAbsoluteSelection();
AV *selected_av = newAV();
VECTOR_AV(selected_lines, selected_av, int, iv);
av_push(AT, newRV_noinc((SV*)selected_av));
// $_[2]
int first_sel = sb->GetFirstSelRow();
av_push(AT, newSViv(first_sel));
// Clear all maps from the subs grid before running the macro
// The stuff done by the macro might invalidate some of the iterators held by the grid, which will cause great crashing
sb->Clear();
// Here we go
script->WriteVars();
// Box the code into the right package
wxString code = _T("package ") + script->GetPackage() + _T(";\n");
// Add the user's code
code << str;
// Evaluate the code
SV *e = eval_pv(code.mb_str(wx2pl), 0);
/* TODO: check for errors */
script->ReadVars();
// Recreate the top assfile from perl hassh
//AssFile::top->FlagAsModified(GetName());
PerlAss::MakeAssLines(AssFile::top, lines);
av_undef(lines);
// And reset selection vector
selected_lines.clear();
AV_VECTOR(selected_av, selected_lines, IV);
CHOP_SELECTED(AssFile::top, selected_lines);
av_undef(selected_av);
// Have the grid update its maps, this properly refreshes it to reflect the changed subs
sb->UpdateMaps();
sb->SetSelectionFromAbsolute(selected_lines);
sb->CommitChanges(true, false);
sb->EndBatch();
// The eval's return
return wxString(SvPV_nolen(e), pl2wx);
}
XS(PerlConsole::register_console)
{
dXSARGS;
PerlScript *script = PerlScript::GetScript();
if(script) {
wxString name = _T("Perl console");
wxString desc = _T("Show the Perl console");
switch (items) {
case 2:
desc = wxString(SvPV_nolen(ST(1)), pl2wx);
case 1:
name = wxString(SvPV_nolen(ST(0)), pl2wx);
}
if(!registered)
// If there's no registered console
script->AddFeature(new PerlConsole(name, desc, script));
}
}
XS(PerlConsole::echo)
{
dXSARGS;
// We should get some parameters
if(items == 0) XSRETURN_EMPTY;
// Join the params in a unique string :S
wxString buffer = wxString(SvPV_nolen(ST(0)), pl2wx);
for(int i = 1; i < items; i++) {
buffer << _T(" ") << wxString(SvPV_nolen(ST(i)), pl2wx);
}
if(registered) {
// If there's a console echo to it
registered->dialog->Echo(buffer);
}
else {
// Otherwise print on stdout
PerlIO_printf(PerlIO_stdout(), "%s\n", buffer.mb_str(wxConvLocal).data());
// (through perl io system)
}
XSRETURN_EMPTY;
}
};
#endif //WITH_PERL

View file

@ -0,0 +1,91 @@
// Copyright (c) 2008, Simone Cociancich
// 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
//
#pragma once
#ifndef _AUTO4_PERL_CONSOLE_H
#define _AUTO4_PERL_CONSOLE_H
#include "auto4_perl.h"
#include <wx/textctrl.h>
namespace Automation4 {
class PerlConsole : public PerlFeatureMacro {
private:
static PerlConsole *registered;
// Nested classes are messy, therefore we use them :)
class Dialog : public wxDialog {
private:
wxTextCtrl *txt_out, *txt_hist, *txt_in;
public:
Dialog();
bool Create(wxWindow* parent, wxWindowID id, const wxString& title,
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
long style = wxDEFAULT_DIALOG_STYLE, const wxString& name = _T("console_dialog"));
void InputEnter(wxCommandEvent& evt);
void Echo(const wxString &str);
};
Dialog *dialog;
wxWindow *parent_window;
SV *cout;
wxString evaluate(const wxString &str);
public:
PerlConsole(const wxString &name, const wxString &desc, PerlScript *script);
virtual ~PerlConsole();
static PerlConsole *GetConsole() { return registered; }
virtual bool Validate(AssFile *subs, const std::vector<int> &selected, int active) { return true; }
virtual void Process(AssFile *subs, std::vector<int> &selected, int active, wxWindow * const progress_parent);
static wxString Evaluate(const wxString &str) { if(registered) return registered->evaluate(str); }
static XS(register_console);
static XS(echo);
};
};
#endif

View file

@ -0,0 +1,187 @@
// Copyright (c) 2008, Simone Cociancich
// 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
//
#ifdef WITH_PERL
#include "auto4_perl.h"
#include "ass_file.h"
namespace Automation4 {
//////////////////////
// PerlFeatureMacro
//
PerlFeatureMacro::PerlFeatureMacro(const wxString &name, const wxString &description, PerlScript *own_script, SV *proc_sub, SV *val_sub):
Feature(SCRIPTFEATURE_MACRO, name),
FeatureMacro(name, description)
{
// We know what script we belong to ^_^
script = own_script;
// And not surprisingly we have some callbacks too
processing_sub = newSVsv(proc_sub);
validation_sub = newSVsv(val_sub);
}
PerlFeatureMacro::~PerlFeatureMacro() {
// The macro subroutines get undefined
/* This is crappy and creepy at the same time */
/* TODO: thoroughly recheck the code */
CV *cv = Nullcv;
HV *hv = NULL;
GV *gv = NULL;
if(processing_sub) {
cv = sv_2cv(processing_sub, &hv, &gv, 1);
cv_undef(cv);
if(hv) hv_undef(hv);
}
if(validation_sub) {
cv = sv_2cv(validation_sub, &hv, &gv, 1);
cv_undef(cv);
if(hv) hv_undef(hv);
}
};
bool PerlFeatureMacro::Validate(AssFile *subs, const std::vector<int> &selected, int active)
{
// If there's no validation subroutine defined simply return true
if(!validation_sub) return true;
// otherwise...
// Sub lines
AV *lines = PerlAss::MakeHasshLines(NULL, subs);
// Selection array
AV *selected_av = newAV();
VECTOR_AV(selected, selected_av, int, iv);
// Sync script's vars with package's
script->Activate();
bool ret = false;
int c = 0;
// Prepare the stack
dSP;
ENTER;
SAVETMPS;
// Push the parameters on the stack
PUSHMARK(SP);
XPUSHs(sv_2mortal(newRV_noinc((SV*)lines)));
XPUSHs(sv_2mortal(newRV_noinc((SV*)selected_av)));
XPUSHs(sv_2mortal(newSViv(active)));
PUTBACK;
// Call back the callback
c = call_sv(validation_sub, G_EVAL | G_SCALAR);
SPAGAIN;
if(SvTRUE(ERRSV)) {
wxLogVerbose(wxString(SvPV_nolen(ERRSV), pl2wx));
ret = false;
}
else {
SV *wtf = sv_mortalcopy(POPs);
ret = SvTRUE(wtf);
}
// Tidy up everything
PUTBACK;
FREETMPS;
LEAVE;
script->Deactivate();
return ret;
}
void PerlFeatureMacro::Process(AssFile *subs, std::vector<int> &selected, int active, wxWindow * const progress_parent)
{
// Reference to the hassh (lines)
AV *lines = PerlAss::MakeHasshLines(NULL, subs);
// Selection array
AV *selected_av = newAV();
VECTOR_AV(selected, selected_av, int, iv);
script->Activate();
// Prepare the stack
dSP;
ENTER;
SAVETMPS;
// Push the parameters on the stack
PUSHMARK(SP);
XPUSHs(sv_2mortal(newRV_noinc((SV*)lines)));
XPUSHs(sv_2mortal(newRV_noinc((SV*)selected_av)));
XPUSHs(sv_2mortal(newSViv(active)));
PUTBACK;
// Call back the callback :)
call_sv(processing_sub, G_EVAL | G_VOID);
if(SvTRUE(ERRSV)) {
// Error
wxLogError(wxString(SvPV_nolen(ERRSV), pl2wx));
}
else {
// Non-error: recreate the hassh :S
subs->FlagAsModified(GetName());
PerlAss::MakeAssLines(subs, lines);
// And reset selection vector
selected.clear();
AV_VECTOR(selected_av, selected, IV);
CHOP_SELECTED(subs, selected);
}
// Clean everything
FREETMPS;
LEAVE;
script->Deactivate();
}
};
#endif //WITH_PERL

135
aegisub/auto4_perl_misc.cpp Normal file
View file

@ -0,0 +1,135 @@
// Copyright (c) 2008, Simone Cociancich
// 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
//
#ifdef WITH_PERL
#include "auto4_perl.h"
namespace Automation4 {
void xs_perl_misc(pTHX)
{
newXS("Aegisub::warn", PerlLog::log_warning, __FILE__);
newXS("Aegisub::text_extents", text_extents, __FILE__);
}
/////////////
// PerlLog
//
XS(PerlLog::log_warning)
{
dXSARGS;
wxString buffer;
if(items >= 1) {
buffer = wxString(SvPV_nolen(ST(0)), wx2pl);
for(I32 i = 1; i < items; i++) {
buffer << _T(" ") << wxString(SvPV_nolen(ST(i)), wx2pl);
}
}
wxLogWarning(buffer);
}
////////////
// Others
//
XS(text_extents)
{
/* TODO badly: rewrite this shit */
dXSARGS;
// Read the parameters
SV *style; wxString text;
if(items >= 2) {
// Enough of them
style = sv_mortalcopy(ST(0));
text = wxString(SvPV_nolen(ST(1)), pl2wx);
}
else {
// We needed 2 parameters at least!
XSRETURN_UNDEF;
}
// Get the AssStyle
AssStyle *s;
if(SvROK(style)) {
// Create one from the hassh
s = PerlAss::MakeAssStyle((HV*)SvRV(style));
}
else {
// It's the name of the style
wxString sn(SvPV_nolen(style), pl2wx);
// We get it from the AssFile::top
s = AssFile::top->GetStyle(sn);
/* TODO: make it dig from the current hassh's styles */
}
// The return parameters
double width, height, descent, extlead;
// The actual calculation
if(!CalculateTextExtents(s, text, width, height, descent, extlead)) {
/* TODO: diagnose error */
XSRETURN_EMPTY;
}
// Returns
switch(GIMME_V) {
case G_ARRAY:
// List context
EXTEND(SP, 4);
XST_mNV(0, width);
XST_mNV(1, height);
XST_mNV(2, descent);
XST_mNV(3, extlead);
XSRETURN(4);
break;
case G_SCALAR:
// Scalar context
XSRETURN_NV(width);
}
}
};
#endif //WITH_PERL

View file

@ -0,0 +1,353 @@
// Copyright (c) 2008, Simone Cociancich
// 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
//
#ifdef WITH_PERL
#include "auto4_perl.h"
#include "auto4_perl_console.h"
#include "version.h"
#include "standard_paths.h"
namespace Automation4 {
void xs_perl_script(pTHX)
{
newXS("Aegisub::Script::set_info", PerlScript::set_info, __FILE__);
newXS("Aegisub::Script::register_macro", PerlScript::register_macro, __FILE__);
}
//////////////////////
// PerlScript class
//
PerlScript *PerlScript::active = NULL;
PerlScript::PerlScript(const wxString &filename):
Script(filename)
{
// Create a package name for the script
package.Printf(_T("Aegisub::Script::p%lx"), this);
inc_saved = newAV();
reload = false;
mtime = 0;
// Load the code
load();
}
PerlScript::~PerlScript()
{
unload();
}
void PerlScript::Reload()
{
unload();
reload = false;
load();
}
void PerlScript::load()
{
wxLogTrace("Loading %*s inside %s", 0, GetFilename().c_str(), package.c_str());
// Feed some defaults into the script info
name = GetPrettyFilename().BeforeLast(_T('.'));
description = _("Perl script");
author = wxString(getlogin(), wxConvLibc);
version = GetAegisubShortVersionString();
// Get file's mtime
struct stat s;
stat(GetFilename().mb_str(wxConvLibc), &s);
mtime = s.st_mtime;
// Create the script's package
gv_stashpv(package.mb_str(wx2pl), 1);
// Set this script as active
activate(this);
// 'Enclose' the script into its package
wxString _script = _T("package ") + package + _T(";\n")
_T("our ($_script_reload, $_script_path, $_script_package);\n") // Internal vars
_T("our ($script_name, $script_description, $script_author, $script_version);\n") // Package info
_T("open SCRIPT, $_script_path;\n") // Open the script file
_T("local @_source = <SCRIPT>;\n") // read the source
_T("close SCRIPT;\n") // close the file
_T("eval \"@{_source}\n1;\" || die $@;"); // eval the source
// Let's eval the 'boxed' script
eval_pv(_script.mb_str(wx2pl), 0);
if(SvTRUE(ERRSV)) {
wxLogError(wxString(SvPV_nolen(ERRSV), pl2wx));
loaded = false;
}
else {
loaded = true;
}
// The script has done loading (running)
deactivate();
}
void PerlScript::unload() {
wxLogTrace("Unloading %*s(%s)", 0, name, package.c_str());
// Deinstantiate(?) all features and clear the vector
for(; !features.empty(); features.pop_back()) {
delete (Feature*) features.back();
}
features.clear();
// Dismiss the package's stash
hv_undef((HV*)gv_stashpv(package.mb_str(wx2pl), 0));
// Officially finished with unloading
loaded = false;
}
void PerlScript::activate(PerlScript *script)
{
wxLogTrace("Activating %*s(%s)", 0, script->GetName(), script->GetPackage().c_str());
// Check if the source file is newer
if(script->reload) {
struct stat s;
stat(script->GetFilename().mb_str(wxConvLibc), &s);
if(script->mtime != s.st_mtime) {
printf("%d != %d !\n", script->mtime, s.st_mtime);
wxLogVerbose(_("Reloading %s because the file on disk (%s) changed"), script->GetName().c_str(), script->GetFilename().c_str());
script->Reload();
}
}
// Hooking $SIG{__WARN__}
wxLogTrace("Hooking $SIG{__WARN__}", 0);
eval_pv("$SIG{__WARN__} = \\&Aegisub::warn", 1);
// Add the script's includes to @INC
AV *inc_av = get_av("main::INC", 0);
if(inc_av) {
dAV;
// Save the previous includes
AV_COPY(inc_av, script->inc_saved);
// Make room in @INC
I32 inc_count = script->include_path.GetCount();
av_unshift(inc_av, inc_count);
// Add the include paths
for(I32 i = 0; i < inc_count; i++) {
wxLogDebug("Adding %d to @INC", include_path.Item(i).c_str());
AV_TOUCH(inc_av, i)
AV_STORE(newSVpv(script->include_path.Item(i).mb_str(wx2pl), 0));
}
wxLogTrace("@INC = ( %*s )", 0, SvPV_nolen(eval_pv("\"@INC\"", 1)));
}
else {
wxLogWarning(_("Unable to add the automation include path(s) to @INC, you may have problems running the script."));
}
// Set the values of script vars
script->WriteVars();
active = script;
wxLogDebug("%s(%p) activated", active->GetName().c_str(), active);
}
void PerlScript::deactivate()
{
wxLogTrace("Deactivating %*s (%s)", 0, active->GetName().c_str(), active->GetPackage().c_str());
// Revert @INC to its value before the script activation
AV *inc_av = get_av("main::INC", 0);
if(inc_av) {
dAV;
// Reset @INC
if(av_len(active->inc_saved) >= 0) {
// If there's a saved one
AV_COPY(active->inc_saved, inc_av);
wxLogTrace("@INC = ( %*s )", 0, SvPV_nolen(eval_pv("\"@INC\"", 1)));
av_clear(active->inc_saved);
}
}
// Read the values of script vars
active->ReadVars();
// Unooking $SIG{__WARN__}
wxLogTrace("Releasing $SIG{__WARN__} hook", 0);
eval_pv("undef $SIG{__WARN__}", 1);
wxLogDebug("%s(%p) deactivated", active->GetName().c_str(), active);
active = NULL;
}
void PerlScript::AddFeature(Feature *feature)
{
features.push_back(feature);
wxLogDebug("Added %s to %s(%s)'s features", feature->GetName(), name, package);
}
void PerlScript::DeleteFeature(Feature *feature)
{
for(std::vector<Feature*>::iterator it = features.begin(); it != features.end(); it++)
if(*it == feature) {
delete feature;
wxLogDebug("Deleted %s from %s(%s)'s features", feature->GetName(), name, package);
features.erase(it);
}
}
void PerlScript::ReadVars()
{
// This will get anything inside it °_°
SV *whore = NULL;
// All the vars' names will stick to it #_#
wxString bitch;
bitch = package + _T("::script_name");
whore = get_sv(bitch.mb_str(wx2pl), 0);
if(whore) name = wxString(SvPV_nolen(whore), pl2wx);
bitch = package + _T("::script_description");
whore = get_sv(bitch.mb_str(wx2pl), 0);
if(whore) description = wxString(SvPV_nolen(whore), pl2wx);
bitch = package + _T("::script_author");
whore = get_sv(bitch.mb_str(wx2pl), 0);
if(whore) author = wxString(SvPV_nolen(whore), pl2wx);
bitch = package + _T("::script_version");
whore = get_sv(bitch.mb_str(wx2pl), 0);
if(whore) version = wxString(SvPV_nolen(whore), pl2wx);
bitch = package + _T("::_script_reload");
whore = get_sv(bitch.mb_str(wx2pl), 0);
if(whore) reload = SvTRUE(whore);
}
void PerlScript::WriteVars() const
{
// Somewhat as above
SV *whore = NULL;
wxString bitch;
bitch = package + _T("::_script_package");
whore = get_sv(bitch.mb_str(wx2pl), 1);
sv_setpv(whore, package.mb_str(wx2pl));
bitch = package + _T("::_script_path");
whore = get_sv(bitch.mb_str(wx2pl), 1);
sv_setpv(whore, GetFilename().mb_str(wx2pl));
bitch = package + _T("::_script_reload");
whore = get_sv(bitch.mb_str(wx2pl), 1);
sv_setiv(whore, int(reload));
bitch = package + _T("::script_name");
whore = get_sv(bitch.mb_str(wx2pl), 1);
sv_setpv(whore, name.mb_str(wx2pl));
bitch = package + _T("::script_description");
whore = get_sv(bitch.mb_str(wx2pl), 1);
sv_setpv(whore, description.mb_str(wx2pl));
bitch = package + _T("::script_author");
whore = get_sv(bitch.mb_str(wx2pl), 1);
sv_setpv(whore, author.mb_str(wx2pl));
bitch = package + _T("::script_version");
whore = get_sv(bitch.mb_str(wx2pl), 1);
sv_setpv(whore, version.mb_str(wx2pl));
}
XS(PerlScript::set_info)
{
dXSARGS;
if(active) {
// Update the object's vars
active->ReadVars();
// Set script info vars
switch (items) {
case 4:
active->version = wxString(SvPV_nolen(ST(3)), pl2wx);
case 3:
active->author = wxString(SvPV_nolen(ST(2)), pl2wx);
case 2:
active->description = wxString(SvPV_nolen(ST(1)), pl2wx);
case 1:
active->name = wxString(SvPV_nolen(ST(0)), pl2wx);
}
// Update the package's vars
active->WriteVars();
}
}
XS(PerlScript::register_macro)
{
dXSARGS;
if(active && items >= 3) {
wxString name, description;
SV *proc_sub = NULL, *val_sub = NULL;
switch (items) {
case 4:
val_sub = sv_mortalcopy(ST(3));
case 3:
proc_sub = sv_mortalcopy(ST(2));
description = wxString(SvPV_nolen(ST(1)), pl2wx);
name = wxString(SvPV_nolen(ST(0)), pl2wx);
}
if(proc_sub) {
active->AddFeature(new PerlFeatureMacro(name, description, active, proc_sub, val_sub));
XSRETURN_YES;
}
}
XSRETURN_UNDEF;
}
};
#endif //WITH_PERL

122
aegisub/auto4_perldata.inc Normal file
View file

@ -0,0 +1,122 @@
// Copyright (c) 2008, Simone Cociancich
// 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 <assert.h>
// Discards values of selected that are past the end of AssFile::Line
#define CHOP_SELECTED(ass, sel) \
for(; sel.back() >= ass->Line.size(); sel.pop_back())
// Conversions between std::vector<v_t> and AVs
#define VECTOR_AV(v, av, v_t, s_t) \
for(std::vector<v_t>::const_iterator it = v.begin(); it != v.end(); it++) \
av_push(av, newSV ## s_t(*it))
#define AV_VECTOR(av, v, s_t) \
for(int i = 0; i > -1 && i <= av_len(av); i++) { \
SV **_val_ptr = av_fetch(av, i, 0); \
if(_val_ptr) v.push_back(Sv ## s_t(*_val_ptr)); \
}
// Utilities to manipolate hash elements
#define dHV \
SV **HV_r;\
HV *HV_tb; const char *HV_KEY; I32 HV_klen
#define HV_TOUCH(hv, k, kl) \
HV_tb = hv;\
HV_KEY = k;\
HV_klen = kl;\
HV_r = hv_fetch(HV_tb, HV_KEY, HV_klen, 1);\
if(HV_r)
#define HV_FETCH(hv, k, kl) \
HV_tb = hv;\
HV_KEY = k;\
HV_klen = kl;\
HV_r = hv_fetch(HV_tb, HV_KEY, HV_klen, 0);\
if(HV_r)
#define HV_VAL (*HV_r)
#define HV_STORE(si) \
hv_store(HV_tb, HV_KEY, HV_klen, si, 0)
#define HV_FAS(hv, k, kl, vt, v) \
HV_TOUCH(hv, k, kl) HV_STORE(newSV ## vt (v))
#define HV_FAA(hv, k, kl, vt, a) \
HV_FETCH(hv, k, kl) a = Sv ## vt (HV_VAL)
// Utilities to manipulate list elements
#define dAV \
SV **AV_r;\
AV *AV_ar; I32 AV_KEY
#define AV_TOUCH(av, k) \
AV_ar = av;\
AV_KEY = k;\
AV_r = av_fetch(AV_ar, AV_KEY, 1);\
if(AV_r)
#define AV_FETCH(av, k) \
AV_ar = av;\
AV_KEY = k;\
AV_r = av_fetch(AV_ar, AV_KEY, 0);\
if(AV_r)
#define AV_VAL (*AV_r)
#define AV_STORE(si) \
av_store(AV_ar, AV_KEY, si)
#define AV_FAS(av, k, vt, v) \
AV_TOUCH(av, k, kl) AV_STORE(newSV ## vt (v))
#define AV_FAA(av, k, vt, a) \
AV_FETCH(av, k, kl) a = Sv ## vt (AV_VAL)
#define AV_COPY(av_src, av_dst) \
av_clear(av_dst);\
for(I32 i = 0; i <= av_len(av_src); i++) {\
AV_FETCH(av_src, i) {\
SV *src = AV_VAL;\
AV_TOUCH(av_dst, i)\
AV_STORE(newSVsv(src));\
}\
}

View file

@ -33,7 +33,6 @@
// Contact: mailto:pomyk@go2.pl
//
#include "config.h"
#ifdef WITH_RUBY
#include "auto4_ruby.h"
#include "auto4_auto3.h"

View file

@ -33,7 +33,6 @@
// Contact: mailto:pomyk@go2.pl
//
#include "config.h"
#ifdef WITH_RUBY
#include "auto4_ruby.h"
#include "ass_dialogue.h"

View file

@ -33,7 +33,7 @@
// Contact: mailto:pomyk@go2.pl
//
#include "config.h"
#ifdef WITH_RUBY
#include "auto4_ruby.h"
#include <ruby.h>

View file

@ -33,7 +33,7 @@
// Contact: mailto:jiifurusu@gmail.com
//
#include "config.h"
#ifdef WITH_AUTOMATION
#include "main.h"

View file

@ -36,7 +36,7 @@
////////////
// Includes
#include "config.h"
#include <wx/tokenzr.h>
#include "font_file_lister.h"
#include "text_file_writer.h"

View file

@ -36,7 +36,7 @@
////////////
// Includes
#include "config.h"
#ifdef WITH_FREETYPE2
#include "font_file_lister_freetype.h"

View file

@ -43,7 +43,7 @@
#include <wx/tokenzr.h>
#include <wx/image.h>
#include <wx/statline.h>
#include "config.h"
#include "subs_grid.h"
#include "frame_main.h"
#include "avisynth_wrap.h"

View file

@ -49,7 +49,7 @@
#include <wx/sizer.h>
#include <wx/panel.h>
#include <vector>
#include "config.h"
////////////////////

View file

@ -34,7 +34,7 @@
//
#include "config.h"
#ifdef WITH_FFMPEG
#include <wx/wxprec.h>
#include <wx/filename.h>

View file

@ -44,7 +44,7 @@
#include <wx/utils.h>
#include <wx/stdpaths.h>
#include <wx/filefn.h>
#include "config.h"
#include "main.h"
#include "frame_main.h"
#include "options.h"

View file

@ -45,7 +45,7 @@
#include <wx/stackwalk.h>
#include <fstream>
#include "aegisublocale.h"
#include "config.h"
//////////////

View file

@ -37,7 +37,7 @@
///////////
// Headers
#include <wx/wxprec.h>
#include "config.h"
//////////////////////////////////
@ -178,4 +178,11 @@
#endif
////////
// Perl
#ifdef WITH_PERL
#pragma comment(lib,"perl510.lib")
#endif
#endif // VisualC

View file

@ -36,7 +36,7 @@
///////////
// Headers
#include "config.h"
#ifdef WITH_HUNSPELL
#include "spellchecker.h"

View file

@ -36,7 +36,7 @@
///////////
// Headers
#include "config.h"
#ifdef WITH_CSRI
#include <wx/wxprec.h>

View file

@ -35,7 +35,7 @@
///////////
// Headers
#include "config.h"
#ifdef WITH_LIBASS
#include "subtitles_provider.h"

View file

@ -40,7 +40,7 @@
#include <algorithm>
#include <string>
#include "text_file_reader.h"
#include "config.h"
#ifdef __WINDOWS__
#ifdef WITH_UNIVCHARDET

View file

@ -62,7 +62,7 @@
#include "ass_style.h"
#include "subs_grid.h"
#include "vfw_wrap.h"
#include "config.h"
#if !defined(__WINDOWS__) && !defined(__APPLE__)
#ifdef WITH_FFMPEG
#include "lavc_keyframes.h"

View file

@ -36,7 +36,7 @@
///////////
// Headers
#include "config.h"
#ifdef WITH_DIRECTSHOW
#pragma warning(disable: 4995)

View file

@ -36,7 +36,7 @@
///////////
// Headers
#include "config.h"
#ifdef WITH_FFMPEG
#ifdef WIN32

View file

@ -53,7 +53,7 @@
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4267"
ForcedIncludeFiles="stdwx.h"
ForcedIncludeFiles="stdwx.h;config.h"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@ -135,7 +135,7 @@
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4267"
ForcedIncludeFiles="stdwx.h"
ForcedIncludeFiles="stdwx.h;config.h"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@ -402,46 +402,94 @@
RelativePath="..\..\aegisub\auto4_base.h"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua.cpp"
<Filter
Name="Lua"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua.h"
<File
RelativePath="..\..\aegisub\auto4_lua.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua.h"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua_assfile.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua_dialog.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua_scriptreader.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua_scriptreader.h"
>
</File>
</Filter>
<Filter
Name="Ruby"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua_assfile.cpp"
<File
RelativePath="..\..\aegisub\auto4_ruby.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_ruby.h"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_ruby_assfile.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_ruby_dialog.cpp"
>
</File>
</Filter>
<Filter
Name="Perl"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua_dialog.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua_scriptreader.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_lua_scriptreader.h"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_ruby.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_ruby.h"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_ruby_assfile.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_ruby_dialog.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perl.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perl.h"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perl_ass.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perl_console.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perl_console.h"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perl_macro.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perl_misc.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perl_script.cpp"
>
</File>
<File
RelativePath="..\..\aegisub\auto4_perldata.inc"
>
</File>
</Filter>
</Filter>
<Filter
Name="Wrappers"

View file

@ -13,7 +13,7 @@
#include "hunspell.hxx"
#include "hunspell.h"
#include "config.h"
#ifndef MOZILLA_CLIENT
#ifndef W32