Aegisub/core/ass_override.cpp
2006-01-16 21:02:54 +00:00

691 lines
22 KiB
C++

// Copyright (c) 2005, Rodrigo Braz Monteiro
// 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:zeratul@cellosoft.com
//
////////////
// Includes
#include "ass_dialogue.h"
#include "ass_override.h"
#include <wx/tokenzr.h>
////////////////////// AssOverrideParameter //////////////////////
///////////////
// Constructor
AssOverrideParameter::AssOverrideParameter () {
classification = PARCLASS_NORMAL;
ommited = false;
}
//////////////
// Destructor
AssOverrideParameter::~AssOverrideParameter () {
}
////////
// Copy
void AssOverrideParameter::CopyFrom (const AssOverrideParameter &param) {
switch(param.GetType()) {
case VARDATA_INT: SetInt(param.AsInt()); break;
case VARDATA_FLOAT: SetFloat(param.AsFloat()); break;
case VARDATA_TEXT: SetText(param.AsText()); break;
case VARDATA_BOOL: SetBool(param.AsBool()); break;
case VARDATA_COLOUR: SetColour(param.AsColour()); break;
case VARDATA_BLOCK: SetBlock(param.AsBlock()); break;
default: DeleteValue();
}
classification = param.classification;
ommited = param.ommited;
}
void AssOverrideParameter::operator= (const AssOverrideParameter &param) {
CopyFrom(param);
}
////////////////////// AssDialogueBlockOverride //////////////////////
///////////////
// Constructor
AssDialogueBlockOverride::AssDialogueBlockOverride () {
type = BLOCK_OVERRIDE;
}
//////////////
// Destructor
AssDialogueBlockOverride::~AssDialogueBlockOverride () {
for (std::vector<AssOverrideTag*>::iterator cur=Tags.begin();cur!=Tags.end();cur++) {
delete *cur;
}
Tags.clear();
}
/////////////
// Read tags
void AssDialogueBlockOverride::ParseTags () {
// Clear current vector
Tags.clear();
// Fix parenthesis matching
while (text.Freq(_T('(')) > text.Freq(_T(')'))) {
text += _T(")");
}
// Initialize tokenizer
wxStringTokenizer tkn(text,_T("\\"),wxTOKEN_RET_EMPTY_ALL);
while (tkn.HasMoreTokens()) {
wxString curTag = _T("\\");
curTag += tkn.GetNextToken();
if (curTag == _T("\\")) continue;
// Check for parenthesis matching
while (curTag.Freq(_T('(')) > curTag.Freq(_T(')'))) {
if (!tkn.HasMoreTokens()) {
wxLogWarning(_T("Unmatched parenthesis! Line contents: ") + parent->Text);
break;
}
curTag << _T("\\") << tkn.GetNextToken();
}
AssOverrideTag *newTag = new AssOverrideTag;
newTag->SetText(curTag);
Tags.push_back(newTag);
}
}
///////////////////////////
// Get Text representation
wxString AssDialogueBlockOverride::GetText () {
text = _T("");
for (std::vector<AssOverrideTag*>::iterator cur=Tags.begin();cur!=Tags.end();cur++) {
text += (*cur)->ToString();
}
return text;
}
///////////////////////////////////
// Process parameters via callback
void AssDialogueBlockOverride::ProcessParameters(void (*callback)(wxString,int,AssOverrideParameter *,void *),void *userData) {
AssOverrideTag *curTag;
AssOverrideParameter *curPar;
// Find tags
for (std::vector<AssOverrideTag*>::iterator cur=Tags.begin();cur!=Tags.end();cur++) {
int n = 0;
curTag = *cur;
// Find parameters
for (std::vector<AssOverrideParameter*>::iterator curParam=curTag->Params.begin();curParam!=curTag->Params.end();curParam++) {
curPar = *curParam;
if (curPar->GetType() != VARDATA_NONE && curPar->ommited == false) {
// Do callback
(*callback)(curTag->Name,n,curPar,userData);
// Go recursive if it's a block parameter
//if (curPar->classification == VARDATA_BLOCK) {
if (curPar->GetType() == VARDATA_BLOCK) {
curPar->AsBlock()->ProcessParameters(callback,userData);
}
}
n++;
}
}
}
///////////////////////// AssOverrideParamProto //////////////////////////
///////////////
// Constructor
AssOverrideParamProto::AssOverrideParamProto (VariableDataType _type,int opt,ASS_ParameterClass classi) {
type = _type;
optional = opt;
classification = classi;
}
//////////////
// Destructor
AssOverrideParamProto::~AssOverrideParamProto() {
}
///////////////////////// AssOverrideTagProto //////////////////////////
///////////////
// Static vars
std::list<AssOverrideTagProto> AssOverrideTagProto::proto;
bool AssOverrideTagProto::loaded = false;
///////////////
// Constructor
AssOverrideTagProto::AssOverrideTagProto() {
}
//////////////
// Destructor
AssOverrideTagProto::~AssOverrideTagProto() {
}
///////////////////
// Load prototypes
void AssOverrideTagProto::LoadProtos () {
if (loaded) return;
loaded = true;
// \alpha
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\alpha");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT));
// \bord<depth>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\bord");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_SIZE));
// \shad<depth>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\shad");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_SIZE));
// \fade(<a1>,<a2>,<a3>,<t1>,<t2>,<t3>,<t4>)
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fade");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_RELATIVE_TIME_START));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_RELATIVE_TIME_START));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_RELATIVE_TIME_START));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_RELATIVE_TIME_START));
// \move(<x1>,<y1>,<x2>,<y2>[,<t1>,<t2>])
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\move");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_X));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_Y));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_X));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_Y));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,OPTIONAL_6,PARCLASS_RELATIVE_TIME_START));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,OPTIONAL_6,PARCLASS_RELATIVE_TIME_START));
// \clip(<x1>,<y1>,<x2>,<y2>)
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\clip");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_X));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_Y));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_X));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_Y));
// \clip([<scale>,]<some drawings>)
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\clip");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,OPTIONAL_2,PARCLASS_NORMAL));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_DRAWING));
// \fscx<percent>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fscx");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_RELATIVE_SIZE_X));
// \fscy<percent>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fscy");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_RELATIVE_SIZE_Y));
// \pos(<x>,<y>)
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\pos");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_X));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_Y));
// \org(<x>,<y>)
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\org");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_X));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_Y));
// \pbo<y>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\pbo");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_POS_Y));
// \fad(<t1>,<t2>)
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fad");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_RELATIVE_TIME_START));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_RELATIVE_TIME_END));
// \fsp<pixels>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fsp");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_SIZE));
// \frx<degrees>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\frx");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \fry<degrees>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fry");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \frz<degrees>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\frz");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \fr<degrees>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fr");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \1c&H<bbggrr>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\1c");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \2c&H<bbggrr>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\2c");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \3c&H<bbggrr>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\3c");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \4c&H<bbggrr>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\4c");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \1a&H<aa>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\1a");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \2a&H<aa>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\2a");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \3a&H<aa>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\3a");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \4a&H<aa>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\4a");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \fe<charset>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fe");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \ko<duration>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\ko");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_KARAOKE));
// \kf<duration>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\kf");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_KARAOKE));
// \be<0/1>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\be");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_BOOL,NOT_OPTIONAL,PARCLASS_NORMAL));
// \fn<name>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fn");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \fs<size>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\fs");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_ABSOLUTE_SIZE));
// \an<alignment>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\an");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \c&H<bbggrr>&
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\c");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \b<0/1/weight>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\b");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,OPTIONAL_1,PARCLASS_NORMAL));
proto.back().params.back().defaultValue.SetBool(false);
// \i<0/1>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\i");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_BOOL,OPTIONAL_1,PARCLASS_NORMAL));
proto.back().params.back().defaultValue.SetBool(false);
// \u<0/1>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\u");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_BOOL,OPTIONAL_1,PARCLASS_NORMAL));
proto.back().params.back().defaultValue.SetBool(false);
// \s<0/1>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\s");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_BOOL,OPTIONAL_1,PARCLASS_NORMAL));
proto.back().params.back().defaultValue.SetBool(false);
// \a<alignment>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\a");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \k<duration>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\k");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_KARAOKE));
// \K<duration>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\K");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_KARAOKE));
// \q<0-3>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\q");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \p<n>
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\p");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,NOT_OPTIONAL,PARCLASS_NORMAL));
// \r[<name>]
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\r");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_TEXT,OPTIONAL_1,PARCLASS_NORMAL));
// \t([<t1>,<t2>,][<accel>,]<style modifiers>)
proto.push_back(AssOverrideTagProto());
proto.back().name = _T("\\t");
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,OPTIONAL_3 | OPTIONAL_4,PARCLASS_RELATIVE_TIME_START));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_INT,OPTIONAL_3 | OPTIONAL_4,PARCLASS_RELATIVE_TIME_START));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_FLOAT,OPTIONAL_2 | OPTIONAL_4,PARCLASS_NORMAL));
proto.back().params.push_back(AssOverrideParamProto(VARDATA_BLOCK,NOT_OPTIONAL,PARCLASS_NORMAL));
}
//////////////////////// AssOverrideTag //////////////////////////
///////////////
// Constructor
AssOverrideTag::AssOverrideTag () {
valid = false;
}
//////////////
// Destructor
AssOverrideTag::~AssOverrideTag () {
for (std::vector<AssOverrideParameter*>::iterator cur=Params.begin();cur!=Params.end();cur++) {
delete *cur;
}
Params.clear();
valid = false;
}
////////////////////////////
// Parses text and sets tag
void AssOverrideTag::SetText (wxString text) {
// Determine name
Name = _T("");
AssOverrideTagProto *proto;
for (std::list<AssOverrideTagProto>::iterator cur=AssOverrideTagProto::proto.begin();cur!=AssOverrideTagProto::proto.end();cur++) {
proto = &(*cur);
if (text.Left(proto->name.length()) == proto->name) {
Name = proto->name;
break;
}
}
// Set tag name
if (!Name.empty()) {
ParseParameters(text.Mid(Name.length()));
valid = true;
}
// Junk tag
else {
Name = text;
valid = false;
}
}
/////////////////////////
// Checks if it is valid
bool AssOverrideTag::IsValid() {
return valid;
}
/////////////////////
// Parses parameters
void AssOverrideTag::ParseParameters(wxString text) {
// Split parameters
wxArrayString paramList;
size_t start = 0;
wxString work;
int parDepth = 0;
for (size_t i=0;i<text.Length();i++) {
// Started an overrides block
if (text[i] == _T('\\')) {
work = text.Mid(start);
while (parDepth > 0 && work.Right(1) == _T(")")) {
work = work.Left(work.Length()-1);
work.Trim(true);
work.Trim(false);
parDepth--;
}
paramList.Add(work);
start = text.Length();
break;
}
else if (text[i] == _T(',') || text[i] == _T('(') || text[i] == _T(')')) {
if (text[i] == _T('(')) parDepth++;
work = text.SubString(start,i-1);
work.Trim(true);
work.Trim(false);
if (work != _T("")) paramList.Add(work);
start = i+1;
}
else if (text[i] == _T(')')) parDepth--;
}
work = text.Mid(start);
work.Trim(true);
work.Trim(false);
if (work != _T(""))
paramList.Add(work);
int curPar = 0;
int totalPars = paramList.GetCount();
// Get optional parameters flag
//wxStringTokenizer tkn(text,_T(",()"),wxTOKEN_STRTOK);
//int totalPars = tkn.CountTokens();
ASS_ParameterOptional parsFlag = OPTIONAL_0;
switch (totalPars) {
case 1: parsFlag = OPTIONAL_1; break;
case 2: parsFlag = OPTIONAL_2; break;
case 3: parsFlag = OPTIONAL_3; break;
case 4: parsFlag = OPTIONAL_4; break;
case 5: parsFlag = OPTIONAL_5; break;
case 6: parsFlag = OPTIONAL_6; break;
case 7: parsFlag = OPTIONAL_7; break;
}
// Find prototype
bool clipOnce = true;
AssOverrideTagProto *proto = NULL;
for (std::list<AssOverrideTagProto>::iterator cur=AssOverrideTagProto::proto.begin();cur!=AssOverrideTagProto::proto.end();cur++) {
if (Name == (*cur).name) {
if (Name == _T("\\clip") && totalPars != 4 && clipOnce) {
clipOnce = false;
continue;
}
proto = &(*cur);
break;
}
}
if (proto == NULL) {
throw _T("Couldn't find tag prototype while parsing.");
}
// Get parameters
size_t n=0;
wxString curtok = _T("");
if (curPar < totalPars) {
curtok = paramList[curPar];
curPar++;
}
//while (curtok != _T("")) {
while (n < proto->params.size()) {
AssOverrideParamProto *curproto = &proto->params[n];
bool isDefault = false;
n++;
// Create parameter
AssOverrideParameter *newparam = new AssOverrideParameter;
// Check if it's optional and not set (set to default)
if (!(curproto->optional & parsFlag)) {
isDefault = true;
newparam->CopyFrom(curproto->defaultValue);
newparam->ommited = true;
}
else {
// Determine parameter type and set value
switch (curproto->type) {
case VARDATA_INT: {
long temp;
curtok.ToLong(&temp);
newparam->SetInt(temp);
break;
}
case VARDATA_FLOAT: {
double temp;
curtok.ToDouble(&temp);
newparam->SetFloat(temp);
break;
}
case VARDATA_TEXT: {
newparam->SetText(curtok);
break;
}
case VARDATA_BOOL: {
long temp;
curtok.ToLong(&temp);
newparam->SetBool(temp != 0);
break;
}
case VARDATA_BLOCK: {
AssDialogueBlockOverride *temp = new AssDialogueBlockOverride;
temp->text = curtok;
temp->ParseTags();
newparam->SetBlock(temp);
break;
}
}
// Get next actual parameter
if (curPar < totalPars) {
curtok = paramList[curPar];
curPar++;
}
else curtok = _T("");
}
// Add to list
newparam->classification = curproto->classification;
Params.push_back(newparam);
}
}
//////////////
// Get string
wxString AssOverrideTag::ToString() {
// Start with name
wxString result = Name;
// Determine if it needs parenthesis
bool parenthesis = false;
if (Name == _T("\\t") || Name == _T("\\pos") || Name == _T("\\fad") || Name == _T("\\org") || Name == _T("\\clip") || Name == _T("\\move") || Name == _T("\\fade")) parenthesis = true;
if (parenthesis) result += _T("(");
// Add parameters
int n = 0;
for (std::vector<AssOverrideParameter*>::iterator cur=Params.begin();cur!=Params.end();cur++) {
if ((*cur)->GetType() != VARDATA_NONE && (*cur)->ommited == false) {
result += (*cur)->AsText();
result += _T(",");
n++;
}
}
if (n > 0) result = result.Left(result.Length()-1);
// Finish
if (parenthesis) result += _T(")");
return result;
}