#include "global.h" #include "TitleSubstitution.h" #include "RageUtil.h" #include "RageLog.h" #include "FontCharAliases.h" #include "RageFile.h" #define TRANSLATION_PATH "Data/Translation.dat" struct TitleTrans { Regex TitleFrom, SubFrom, ArtistFrom; TitleFields Dest; /* If this is true, no translit fields will be generated automatically. */ bool translit; TitleTrans() { translit = true; } TitleTrans( const TitleFields &tf, bool translit_): Dest(tf), translit(translit_) { } bool Matches( const TitleFields &tf ); }; vector ttab; bool TitleTrans::Matches( const TitleFields &tf ) { if( !TitleFrom.Compare(tf.Title) ) return false; /* no match */ if( !SubFrom.Compare(tf.Subtitle) ) return false; /* no match */ if( !ArtistFrom.Compare(tf.Artist) ) return false; /* no match */ return true; } void TitleSubst::AddTrans(const TitleTrans &tr) { ttab.push_back(new TitleTrans(tr)); } void TitleSubst::Subst( TitleFields &tf ) { for(unsigned i = 0; i < ttab.size(); ++i) { if(!ttab[i]->Matches(tf)) continue; /* The song matches. Replace whichever strings aren't empty. */ if( !ttab[i]->Dest.Title.empty() && tf.Title != ttab[i]->Dest.Title ) { if( ttab[i]->translit ) tf.TitleTranslit = tf.Title; tf.Title = (ttab[i]->Dest.Title != "-erase-")? ttab[i]->Dest.Title: CString(""); FontCharAliases::ReplaceMarkers( tf.Title ); } if( !ttab[i]->Dest.Subtitle.empty() && tf.Subtitle != ttab[i]->Dest.Subtitle ) { if( ttab[i]->translit ) tf.SubtitleTranslit = tf.Subtitle; tf.Subtitle = (ttab[i]->Dest.Subtitle != "-erase-")? ttab[i]->Dest.Subtitle: CString(""); FontCharAliases::ReplaceMarkers( tf.Subtitle ); } if( !ttab[i]->Dest.Artist.empty() && tf.Artist != ttab[i]->Dest.Artist ) { if( ttab[i]->translit ) tf.ArtistTranslit = tf.Artist; tf.Artist = (ttab[i]->Dest.Artist != "-erase-")? ttab[i]->Dest.Artist: CString(""); FontCharAliases::ReplaceMarkers( tf.Artist ); } /* These are used when applying kanji to a field that doesn't have the * correct data. Should be used sparingly. */ if( !ttab[i]->Dest.TitleTranslit.empty() ) { tf.TitleTranslit = (ttab[i]->Dest.TitleTranslit != "-erase-")? ttab[i]->Dest.TitleTranslit: CString(""); FontCharAliases::ReplaceMarkers( tf.TitleTranslit ); } if( !ttab[i]->Dest.SubtitleTranslit.empty() ) { tf.SubtitleTranslit = (ttab[i]->Dest.SubtitleTranslit != "-erase-")? ttab[i]->Dest.SubtitleTranslit: CString(""); FontCharAliases::ReplaceMarkers( tf.SubtitleTranslit ); } if( !ttab[i]->Dest.ArtistTranslit.empty() ) { tf.ArtistTranslit = (ttab[i]->Dest.ArtistTranslit != "-erase-")? ttab[i]->Dest.ArtistTranslit: CString(""); FontCharAliases::ReplaceMarkers( tf.ArtistTranslit ); } } } TitleSubst::TitleSubst(const CString §ion) { Load( TRANSLATION_PATH, section); } void TitleSubst::Load(const CString &filename, const CString §ion) { RageFile f; if( !f.Open(filename) ) { LOG->Trace("Error opening %s: %s", filename.c_str(), f.GetError().c_str() ); return; } CString CurrentSection; TitleTrans tr; while (!f.AtEOF()) { CString line; int ret = f.GetLine( line ); if( ret == 0 ) break; if( ret == -1 ) { LOG->Trace("Error reading %s: %s", filename.c_str(), f.GetError().c_str() ); break; } if(line.size() > 0 && utf8_get_char(line.c_str()) == 0xFEFF) { /* Annoying header that Windows puts on UTF-8 plaintext * files; remove it. */ line.erase(0, utf8_get_char_len(line[0])); } TrimLeft(line); TrimRight(line); if(line.size() == 0) continue; /* blank */ if(line[0] == '#') continue; /* comment */ if(!line.CompareNoCase("DontTransliterate")) { tr.translit = false; continue; } size_t pos = line.find_first_of(':'); if(pos != string::npos) { /* x: y */ CString id = line.substr(0, pos); CString txt = line.substr(pos+1); TrimLeft(txt); /* Surround each regex with ^(...)$, to force all comparisons to default * to being a full-line match. (Add ".*" manually if this isn't wanted.) */ if(!id.CompareNoCase("TitleFrom")) tr.TitleFrom = "^(" + txt + ")$"; else if(!id.CompareNoCase("ArtistFrom")) tr.ArtistFrom = "^(" + txt + ")$"; else if(!id.CompareNoCase("SubtitleFrom")) tr.SubFrom = "^(" + txt + ")$"; else if(!id.CompareNoCase("TitleTo")) tr.Dest.Title = txt; else if(!id.CompareNoCase("ArtistTo")) tr.Dest.Artist = txt; else if(!id.CompareNoCase("SubtitleTo")) tr.Dest.Subtitle = txt; else if(!id.CompareNoCase("TitleTransTo")) tr.Dest.TitleTranslit = txt; else if(!id.CompareNoCase("ArtistTransTo")) tr.Dest.ArtistTranslit = txt; else if(!id.CompareNoCase("SubtitleTransTo")) tr.Dest.SubtitleTranslit = txt; else LOG->Warn( "Unknown TitleSubst tag: \"%s\"", id.c_str() ); } /* Add the translation if this is a terminator (*) or section * marker ([foo]). */ if(line[0] == '*' || line[0] == '[') { if(!CurrentSection.CompareNoCase(section)) AddTrans(tr); /* Reset. */ tr = TitleTrans(); } if(line[0] == '[' && line[line.size()-1] == ']') { CurrentSection = line.substr(1, line.size()-2); } } } TitleSubst::~TitleSubst() { for(unsigned i = 0; i < ttab.size(); ++i) delete ttab[i]; } /* * (c) 2003-2004 Glenn Maynard * All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, and/or sell copies of the Software, and to permit persons to * whom the Software is furnished to do so, provided that the above * copyright notice(s) and this permission notice appear in all copies of * the Software and that both the above copyright notice(s) and this * permission notice appear in supporting documentation. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF * THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS * INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */