using System;
using System.Collections.Generic;
using System.Globalization;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
namespace Nikse.SubtitleEdit.Core.SubtitleFormats
{
public class Sami : SubtitleFormat
{
public override string Extension
{
get { return ".smi"; }
}
public override string Name
{
get { return "SAMI"; }
}
public override bool IsTimeBased
{
get { return true; }
}
public override bool IsMine(List lines, string fileName)
{
var sb = new StringBuilder();
foreach (string l in lines)
sb.AppendLine(l);
if (sb.ToString().Contains(""))
return false;
var subtitle = new Subtitle();
LoadSubtitle(subtitle, lines, fileName);
return subtitle.Paragraphs.Count > _errorCount;
}
public override string ToText(Subtitle subtitle, string title)
{
string language = Utilities.AutoDetectLanguageName("en_US", subtitle);
var ci = CultureInfo.GetCultureInfo(language.Replace("_", "-"));
string languageTag = string.Format("{0}CC", language.Replace("_", string.Empty).ToUpper());
string languageName = ci.Parent.EnglishName;
string languageStyle = string.Format(".{0} [ name: {1}; lang: {2} ; SAMIType: CC ; ]", languageTag, languageName, language.Replace("_", "-"));
languageStyle = languageStyle.Replace("[", "{").Replace("]", "}");
string header =
@"
_TITLE_
Metrics {time:ms;}
Spec {MSFT:1.0;}
<-- Open play menu, choose Captions and Subtiles, On if available -->
<-- Open tools menu, Security, Show local captions when present -->";
bool useExtra = false;
if (!string.IsNullOrEmpty(subtitle.Header) && subtitle.Header.StartsWith("", StringComparison.Ordinal);
if (styleEnd > 0)
{
subtitle.Header = allInput.Substring(styleStart, styleEnd - styleStart + 8);
}
}
const string syncTag = "')
index++;
if (index < allInput.Length && allInput[index] == '>')
index++;
int syncEndPos = allInputLower.IndexOf(syncTag, index, StringComparison.Ordinal);
int syncEndPosEnc = allInputLower.IndexOf(syncTagEnc, index, StringComparison.Ordinal);
if ((syncStartPosEnc >= 0 && syncStartPosEnc < syncStartPos) || syncEndPos == -1)
syncEndPos = syncEndPosEnc;
string text;
if (syncEndPos >= 0)
text = allInput.Substring(index, syncEndPos - index);
else
text = allInput.Substring(index);
string textToLower = text.ToLower();
if (textToLower.Contains(" class="))
{
var className = new StringBuilder();
int startClass = textToLower.IndexOf(" class=", StringComparison.Ordinal);
int indexClass = startClass + 7;
while (indexClass < textToLower.Length && (Utilities.LowercaseLettersWithNumbers + @"'""").Contains(textToLower[indexClass]))
{
className.Append(text[indexClass]);
indexClass++;
}
p.Extra = className.ToString().Trim(' ', '\'', '"');
}
if (text.Contains("ID=\"Source\"") || text.Contains("ID=Source"))
{
int sourceIndex = text.IndexOf("ID=\"Source\"", StringComparison.Ordinal);
if (sourceIndex < 0)
sourceIndex = text.IndexOf("ID=Source", StringComparison.Ordinal);
int st = sourceIndex - 1;
while (st > 0 && text.Substring(st, 2).ToUpper() != " 0)
{
text = text.Substring(0, st) + text.Substring(sourceIndex);
}
int et = st;
while (et < text.Length - 5 && text.Substring(et, 3).ToUpper() != "
" && text.Substring(et, 4).ToUpper() != "
")
{
et++;
}
text = text.Substring(0, st) + text.Substring(et);
}
text = text.Replace(Environment.NewLine, " ");
text = text.Replace(" ", " ");
text = text.TrimEnd();
text = Regex.Replace(text, @"
", Environment.NewLine, RegexOptions.IgnoreCase);
while (text.Contains(" "))
text = text.Replace(" ", " ");
text = text.Replace("", string.Empty).Replace("", string.Empty).TrimEnd();
int endSyncPos = text.ToUpper().IndexOf("", StringComparison.Ordinal);
if (text.IndexOf('>') > 0 && (text.IndexOf('>') < endSyncPos || endSyncPos == -1))
text = text.Remove(0, text.IndexOf('>') + 1);
text = text.TrimEnd();
if (text.EndsWith("", StringComparison.OrdinalIgnoreCase))
text = text.Substring(0, text.Length - 7).TrimEnd();
if (text.EndsWith("
", StringComparison.Ordinal) || text.EndsWith("", StringComparison.Ordinal))
text = text.Substring(0, text.Length - 4).TrimEnd();
text = text.Replace(" ", " ").Replace("&NBSP;", " ");
if (text.Contains(""))
text += "";
if (text.StartsWith("") && !text.Contains(""))
text += "";
if (text.Contains('<') && text.Contains('>'))
{
var total = new StringBuilder();
var partial = new StringBuilder();
bool tagOn = false;
for (int i = 0; i < text.Length && i < 999; i++)
{
string tmp = text.Substring(i);
if (tmp.StartsWith('<') &&
(tmp.StartsWith("') && tagOn)
{
tagOn = false;
total.Append('>');
}
else if (!tagOn)
{
partial.Append(text[i]);
}
else
{
total.Append(text[i]);
}
}
total.Append(WebUtility.HtmlDecode(partial.ToString()));
text = total.ToString();
}
else
{
text = WebUtility.HtmlDecode(text);
}
var cleanText = text.FixExtraSpaces();
cleanText = cleanText.Trim();
if (!string.IsNullOrEmpty(p.Text) && !string.IsNullOrEmpty(millisecAsString))
{
p.EndTime = new TimeCode(long.Parse(millisecAsString));
subtitle.Paragraphs.Add(p);
p = new Paragraph();
}
p.Text = cleanText;
long l;
if (long.TryParse(millisecAsString, out l))
p.StartTime = new TimeCode(l);
if (syncEndPos <= 0)
{
syncStartPos = -1;
}
else
{
syncStartPos = allInputLower.IndexOf(syncTag, syncEndPos, StringComparison.Ordinal);
index = syncStartPos + syncTag.Length;
syncStartPosEnc = allInputLower.IndexOf(syncTagEnc, syncEndPos, StringComparison.Ordinal);
if ((syncStartPosEnc >= 0 && syncStartPosEnc < syncStartPos) || syncStartPos == -1)
{
syncStartPos = syncStartPosEnc;
index = syncStartPosEnc + syncTagEnc.Length;
}
}
}
if (!string.IsNullOrEmpty(p.Text) && !subtitle.Paragraphs.Contains(p))
{
p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + Utilities.GetOptimalDisplayMilliseconds(p.Text);
subtitle.Paragraphs.Add(p);
}
subtitle.Renumber();
if (subtitle.Paragraphs.Count > 0 &&
(subtitle.Paragraphs[subtitle.Paragraphs.Count - 1].Text.ToUpper().Trim() == ""))
subtitle.Paragraphs.RemoveAt(subtitle.Paragraphs.Count - 1);
foreach (Paragraph p2 in subtitle.Paragraphs)
{
p2.Text = p2.Text.Replace('\u00A0', ' '); // non-breaking space to normal space
}
}
public override bool HasStyleSupport
{
get { return true; }
}
}
}