diff --git a/src/Forms/Main.cs b/src/Forms/Main.cs index 313e049e3..0b605915b 100644 --- a/src/Forms/Main.cs +++ b/src/Forms/Main.cs @@ -4811,19 +4811,19 @@ namespace Nikse.SubtitleEdit.Forms string s = Utilities.RemoveHtmlTags(text).Replace(Environment.NewLine, string.Empty); // we don't count new line in total length... correct? if (s.Length < Configuration.Settings.General.SubtitleLineMaximumLength * 1.9) { - lineTotal.ForeColor = System.Drawing.Color.Black; + lineTotal.ForeColor = Color.Black; if (!textBoxHasFocus) lineTotal.Text = string.Format(_languageGeneral.TotalLengthX, s.Length); } else if (s.Length < Configuration.Settings.General.SubtitleLineMaximumLength * 2.1) { - lineTotal.ForeColor = System.Drawing.Color.Orange; + lineTotal.ForeColor = Color.Orange; if (!textBoxHasFocus) lineTotal.Text = string.Format(_languageGeneral.TotalLengthX, s.Length); } else { - lineTotal.ForeColor = System.Drawing.Color.Red; + lineTotal.ForeColor = Color.Red; if (!textBoxHasFocus) lineTotal.Text = string.Format(_languageGeneral.TotalLengthXSplitLine, s.Length); if (buttonUnBreak.Visible) @@ -4834,7 +4834,7 @@ namespace Nikse.SubtitleEdit.Forms } } UpdateListViewTextCharactersPerSeconds(charactersPerSecond, paragraph); - labelCharactersPerSecond.Left = textBox.Left + (textBox.Width - labelCharactersPerSecond.Width); + charactersPerSecond.Left = textBox.Left + (textBox.Width - labelCharactersPerSecond.Width); lineTotal.Left = textBox.Left + (textBox.Width - lineTotal.Width); FixVerticalScrollBars(textBox); } @@ -9141,23 +9141,7 @@ namespace Nikse.SubtitleEdit.Forms panelVideoPlayer.Invalidate(); - if (Configuration.Settings.General.AllowEditOfOriginalSubtitle && _subtitleAlternate != null && _subtitleAlternate.Paragraphs.Count > 0) - { - textBoxListViewText.Width = (groupBoxEdit.Width - (textBoxListViewText.Left + 10)) / 2; - textBoxListViewTextAlternate.Left = textBoxListViewText.Left + textBoxListViewText.Width + 3; - labelAlternateText.Left = textBoxListViewTextAlternate.Left; - - textBoxListViewTextAlternate.Width = textBoxListViewText.Width; - - labelAlternateCharactersPerSecond.Left = textBoxListViewTextAlternate.Left + (textBoxListViewTextAlternate.Width - labelAlternateCharactersPerSecond.Width); - labelTextAlternateLineLengths.Left = textBoxListViewTextAlternate.Left; - labelAlternateSingleLine.Left = labelTextAlternateLineLengths.Left + labelTextAlternateLineLengths.Width; - labelTextAlternateLineTotal.Left = textBoxListViewTextAlternate.Left + (textBoxListViewTextAlternate.Width - labelTextAlternateLineTotal.Width); - } - - labelCharactersPerSecond.Left = textBoxListViewText.Left + (textBoxListViewText.Width - labelCharactersPerSecond.Width); - labelTextLineTotal.Left = textBoxListViewText.Left + (textBoxListViewText.Width - labelTextLineTotal.Width); - SubtitleListview1.AutoSizeAllColumns(this); + MainResize(); // Due to strange bug in listview when maximizing SaveSubtitleListviewIndexes(); @@ -9167,6 +9151,32 @@ namespace Nikse.SubtitleEdit.Forms panelVideoPlayer.Refresh(); } + private void MainResize() + { + if (Configuration.Settings.General.AllowEditOfOriginalSubtitle && _subtitleAlternate != null && + _subtitleAlternate.Paragraphs.Count > 0) + { + textBoxListViewText.Width = (groupBoxEdit.Width - (textBoxListViewText.Left + 10))/2; + textBoxListViewTextAlternate.Left = textBoxListViewText.Left + textBoxListViewText.Width + 3; + labelAlternateText.Left = textBoxListViewTextAlternate.Left; + + textBoxListViewTextAlternate.Width = textBoxListViewText.Width; + + labelAlternateCharactersPerSecond.Left = textBoxListViewTextAlternate.Left + + (textBoxListViewTextAlternate.Width - + labelAlternateCharactersPerSecond.Width); + labelTextAlternateLineLengths.Left = textBoxListViewTextAlternate.Left; + labelAlternateSingleLine.Left = labelTextAlternateLineLengths.Left + labelTextAlternateLineLengths.Width; + labelTextAlternateLineTotal.Left = textBoxListViewTextAlternate.Left + + (textBoxListViewTextAlternate.Width - labelTextAlternateLineTotal.Width); + } + + labelCharactersPerSecond.Left = textBoxListViewText.Left + + (textBoxListViewText.Width - labelCharactersPerSecond.Width); + labelTextLineTotal.Left = textBoxListViewText.Left + (textBoxListViewText.Width - labelTextLineTotal.Width); + SubtitleListview1.AutoSizeAllColumns(this); + } + private void PlayCurrent() { if (_subtitleListViewIndex >= 0) @@ -10027,6 +10037,7 @@ namespace Nikse.SubtitleEdit.Forms SubtitleListview1.Items[index].Focused = true; } } + MainResize(); _loading = false; OpenVideo(_videoFileName); timerTextUndo.Start(); diff --git a/src/Forms/Main.resx b/src/Forms/Main.resx index 972138fc5..070534608 100644 --- a/src/Forms/Main.resx +++ b/src/Forms/Main.resx @@ -681,7 +681,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAD0 - CAAAAk1TRnQBSQFMAgEBAgEAAUgBEAFIAhABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA + CAAAAk1TRnQBSQFMAgEBAgEAAVABEAFQAhABAAEQAQAE/wEJAQAI/wFCAU0BNgEEBgABNgEEAgABKAMA AUADAAEQAwABAQEAAQgGAAEEGAABgAIAAYADAAKAAQABgAMAAYABAAGAAQACgAIAA8ABAAHAAdwBwAEA AfABygGmAQABMwUAATMBAAEzAQABMwEAAjMCAAMWAQADHAEAAyIBAAMpAQADVQEAA00BAANCAQADOQEA AYABfAH/AQACUAH/AQABkwEAAdYBAAH/AewBzAEAAcYB1gHvAQAB1gLnAQABkAGpAa0CAAH/ATMDAAFm diff --git a/src/Forms/MultipleReplace.cs b/src/Forms/MultipleReplace.cs index 774a8b3bf..90d579105 100644 --- a/src/Forms/MultipleReplace.cs +++ b/src/Forms/MultipleReplace.cs @@ -147,7 +147,7 @@ namespace Nikse.SubtitleEdit.Forms } else if (searchType == Configuration.Settings.Language.MultipleReplace.RegularExpression) { - Regex regex = new Regex(findWhat); + var regex = new Regex(findWhat, RegexOptions.Multiline); var match = regex.Match(newText); if (match.Success) { @@ -264,7 +264,8 @@ namespace Nikse.SubtitleEdit.Forms SearchType = LocalSearchTypeToEnglish(item.SubItems[3].Text) }); } - Configuration.Settings.Save(); + if (saveToDisk) + Configuration.Settings.Save(); } private void ResetUncheckLines() @@ -336,7 +337,7 @@ namespace Nikse.SubtitleEdit.Forms var item = listViewReplaceList.SelectedItems[0]; item.SubItems[1].Text = textBoxFind.Text; item.SubItems[2].Text = textBoxReplace.Text; - item.SubItems[3].Text = searchType; + item.SubItems[3].Text = EnglishSearchTypeToLocal(searchType); GeneratePreview(); textBoxFind.Select(); diff --git a/src/Logic/SubtitleFormats/BelleNuitSubtitler.cs b/src/Logic/SubtitleFormats/BelleNuitSubtitler.cs new file mode 100644 index 000000000..c08d89cbd --- /dev/null +++ b/src/Logic/SubtitleFormats/BelleNuitSubtitler.cs @@ -0,0 +1,290 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; + +namespace Nikse.SubtitleEdit.Logic.SubtitleFormats +{ + class BelleNuitSubtitler : SubtitleFormat + { + ///tc 00:00:35:09 00:00:38:05 + static readonly Regex RegexTimeCode = new Regex(@"^\/tc \d\d:\d\d:\d\d:\d\d \d\d:\d\d:\d\d:\d\d", RegexOptions.Compiled); + + public override string Extension + { + get { return ".stp"; } + } + + public override string Name + { + get { return "Belle Nuit Subtitler"; } + } + + public override bool HasLineNumber + { + get { return false; } + } + + public override bool IsTimeBased + { + get { return true; } + } + + public override bool IsMine(List lines, string fileName) + { + var subtitle = new Subtitle(); + LoadSubtitle(subtitle, lines, fileName); + return subtitle.Paragraphs.Count > _errorCount; + } + + public override string ToText(Subtitle subtitle, string title) + { + const string paragraphWriteFormat = "/tc {0} {1}{2}{3}{2}"; + + var sb = new StringBuilder(); + foreach (Paragraph p in subtitle.Paragraphs) + { + sb.AppendLine(string.Format(paragraphWriteFormat, EncodeTimeCode(p.StartTime), EncodeTimeCode(p.EndTime), Environment.NewLine, p.Text)); + } + + var doc = new XmlDocument(); + doc.LoadXml("" + Environment.NewLine + @" + document + + creator + SICT + type + STLI + version + 1.4 + applicationversion + Belle Nuit Subtitler 1.7.8 + creationdate + 2012-03-13 16:30:32 + modificationdate + 2012-03-13 16:30:32 + + mainleft + 40 + maintop + 48 + mainwidth + 825 + mainheight + 886 + styledt + + exportdt + + previewdt + + moviedt + + exportformat + TIFF + style + + font + Geneva + size + 26 + spacing + 1 + leading + 7 + bold + + italic + + underline + + vertical + 486 + halin + 1 + valign + 2 + standard + PAL + height + 576 + width + 720 + widthreal + 768 + antialiasing + 4 + left + 40 + right + 680 + wrapmethod + 2 + interlaced + + textcolor + #FBFFF2 + textalpha + 1 + textsoft + 0 + bordercolor + #F0F10 + borderalpha + 1 + bordersoft + 0 + borderwidth + 6 + rectcolor + #0 + rectalpha + 0 + rectsoft + 0 + rectform + 1 + shadowcolor + #7F7F7F + shadowalpha + 0 + shadowsoft + 0 + shadowx + 2 + shadowy + 2 + framerate + 25 + + folderpath + + prefix + + moviepath + + movieoffset + 00:00:00:00 + moviesyncoption + + pagesetup + + titlelist +"); + XmlNode node = doc.CreateElement("string"); + node.InnerText = sb.ToString().Trim() + Environment.NewLine + Environment.NewLine; + doc.DocumentElement.AppendChild(node); + + var ms = new MemoryStream(); + var writer = new XmlTextWriter(ms, Encoding.UTF8) {Formatting = Formatting.Indented}; + doc.Save(writer); + return Encoding.UTF8.GetString(ms.ToArray()).Trim(); + } + + public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName) + { + _errorCount = 0; + var sb = new StringBuilder(); + foreach (var line in lines) + { + sb.AppendLine(line); + } + var doc = new XmlDocument(); + try + { + doc.LoadXml(sb.ToString()); + if (doc.DocumentElement == null || doc.DocumentElement.Name != "xmldict" || doc.DocumentElement.SelectSingleNode("string") == null) + return; + } + catch (Exception) + { + _errorCount = 1; + return; + } + + string text = null; + string keyName = string.Empty; + foreach (XmlNode node in doc.DocumentElement.ChildNodes) + { + if (node.Name == "key") + { + keyName = node.InnerText; + } + else if (node.Name == "string" && keyName == "titlelist") + { + text = node.InnerText; + break; + } + } + if (text == null) + return; + + subtitle.Paragraphs.Clear(); + Paragraph paragraph = null; + sb = new StringBuilder(); + foreach (string line in text.Split(Environment.NewLine.ToCharArray())) + { + if (RegexTimeCode.IsMatch(line)) + { + string[] parts = line.Substring(4, 11).Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + if (parts.Length == 4) + { + try + { + if (paragraph != null && sb.ToString().Trim().Length > 0) + { + paragraph.Text = sb.ToString().Trim().Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine).Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine); + } + + var start = DecodeTimeCode(parts); + parts = line.Substring(16, 11).Split(":".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + var end = DecodeTimeCode(parts); + paragraph = new Paragraph { StartTime = start, EndTime = end }; + subtitle.Paragraphs.Add(paragraph); + sb = new StringBuilder(); + } + catch + { + _errorCount++; + } + } + } + else if (paragraph != null) + { + sb.AppendLine(line); + } + else + { + _errorCount++; + } + } + if (paragraph != null && sb.ToString().Trim().Length > 0) + { + paragraph.Text = sb.ToString().Trim().Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine).Replace(Environment.NewLine + Environment.NewLine, Environment.NewLine); + } + subtitle.Renumber(1); + } + + private string EncodeTimeCode(TimeCode time) + { + return string.Format("{0:00}:{1:00}:{2:00}:{3:00}", time.Hours, time.Minutes, time.Seconds, MillisecondsToFrames(time.Milliseconds)); + } + + private TimeCode DecodeTimeCode(string[] parts) + { + string hour = parts[0]; + string minutes = parts[1]; + string seconds = parts[2]; + string frames = parts[3]; + + int milliseconds = (int)((1000.0 / Configuration.Settings.General.CurrentFrameRate) * int.Parse(frames)); + if (milliseconds > 999) + milliseconds = 999; + + return new TimeCode(int.Parse(hour), int.Parse(minutes), int.Parse(seconds), milliseconds); + } + + } +} \ No newline at end of file diff --git a/src/Logic/SubtitleFormats/SubtitleFormat.cs b/src/Logic/SubtitleFormats/SubtitleFormat.cs index 7a1e514c6..24d397992 100644 --- a/src/Logic/SubtitleFormats/SubtitleFormat.cs +++ b/src/Logic/SubtitleFormats/SubtitleFormat.cs @@ -24,6 +24,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats new AdvancedSubStationAlpha(), new AQTitle(), new AvidCaption(), + new BelleNuitSubtitler(), new Captionate(), new CaptionateMs(), new CaraokeXml(), @@ -93,6 +94,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats new UnknownSubtitle13(), new UnknownSubtitle14(), new UnknownSubtitle15(), + new UnknownSubtitle16(), new UTSubtitleXml(), new Utx(), new UtxFrames(), diff --git a/src/Logic/SubtitleFormats/TimedText.cs b/src/Logic/SubtitleFormats/TimedText.cs index a3531dfc6..791879b9c 100644 --- a/src/Logic/SubtitleFormats/TimedText.cs +++ b/src/Logic/SubtitleFormats/TimedText.cs @@ -30,20 +30,19 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats public override bool IsMine(List lines, string fileName) { - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); lines.ForEach(line => sb.AppendLine(line)); string xmlAsString = sb.ToString().Trim(); if (xmlAsString.Contains("http://www.w3.org/") && xmlAsString.Contains("/ttaf1")) { - XmlDocument xml = new XmlDocument(); + var xml = new XmlDocument(); try { xml.LoadXml(xmlAsString); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable); + var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttaf1", xml.DocumentElement.NamespaceURI); - XmlNode div = xml.DocumentElement.SelectSingleNode("//ttaf1:body", nsmgr).FirstChild; int numberOfParagraphs = div.ChildNodes.Count; return numberOfParagraphs > 0; @@ -54,10 +53,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats return false; } } - else - { - return false; - } + return false; } private static string ConvertToTimeString(TimeCode time) @@ -83,9 +79,9 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats " " + Environment.NewLine + ""; - XmlDocument xml = new XmlDocument(); + var xml = new XmlDocument(); xml.LoadXml(xmlStructure); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable); + var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttaf1", "http://www.w3.org/2006/10/ttaf1"); nsmgr.AddNamespace("ttp", "http://www.w3.org/2006/10/ttaf1#parameter"); nsmgr.AddNamespace("tts", "http://www.w3.org/2006/10/ttaf1#style"); @@ -130,9 +126,8 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats no++; } - MemoryStream ms = new MemoryStream(); - XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8); - writer.Formatting = Formatting.Indented; + var ms = new MemoryStream(); + var writer = new XmlTextWriter(ms, Encoding.UTF8) {Formatting = Formatting.Indented}; xml.Save(writer); return Encoding.UTF8.GetString(ms.ToArray()).Trim(); } @@ -141,48 +136,79 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats { _errorCount = 0; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); lines.ForEach(line => sb.AppendLine(line)); - XmlDocument xml = new XmlDocument(); + var xml = new XmlDocument(); xml.LoadXml(sb.ToString()); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable); + var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttaf1", xml.DocumentElement.NamespaceURI); XmlNode div = xml.DocumentElement.SelectSingleNode("//ttaf1:body", nsmgr).FirstChild; foreach (XmlNode node in div.ChildNodes) { try { - StringBuilder pText = new StringBuilder(); + var pText = new StringBuilder(); foreach (XmlNode innerNode in node.ChildNodes) { - switch (innerNode.Name.ToString()) + switch (innerNode.Name) { case "br": pText.AppendLine(); break; + case "span": + bool italic = false; + if (innerNode.Attributes != null) + { + var fs = innerNode.Attributes.GetNamedItem("tts:fontStyle"); + if (fs != null && fs.Value == "italic") + { + italic = true; + pText.Append(""); + } + } + if (innerNode.HasChildNodes) + { + foreach (XmlNode innerInnerNode in innerNode.ChildNodes) + { + if (innerInnerNode.Name == "br") + { + pText.AppendLine(); + } + else + { + pText.Append(innerInnerNode.InnerText); + } + } + } + else + { + pText.Append(innerNode.InnerText); + } + if (italic) + pText.Append(""); + break; default: pText.Append(innerNode.InnerText); break; } } string start = node.Attributes["begin"].InnerText; - string end; + string text = pText.ToString(); + text = text.Replace(Environment.NewLine + "", "" + Environment.NewLine); + text = text.Replace("", string.Empty); if (node.Attributes["end"] != null) { - end = node.Attributes["end"].InnerText; - subtitle.Paragraphs.Add(new Paragraph(GetTimeCode(start), GetTimeCode(end), pText.ToString())); + string end = node.Attributes["end"].InnerText; + subtitle.Paragraphs.Add(new Paragraph(GetTimeCode(start), GetTimeCode(end), text)); } else if (node.Attributes["dur"] != null) { TimeCode duration = GetTimeCode(node.Attributes["dur"].InnerText); TimeCode startTime = GetTimeCode(start); TimeCode endTime = new TimeCode(TimeSpan.FromMilliseconds(startTime.TotalMilliseconds + duration.TotalMilliseconds)); - subtitle.Paragraphs.Add(new Paragraph(startTime, endTime, pText.ToString())); + subtitle.Paragraphs.Add(new Paragraph(startTime, endTime, text)); } - - - } catch (Exception ex) { @@ -204,7 +230,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats } else { - string[] parts = s.Split(new char[] { ':', '.', ',' }); + string[] parts = s.Split(new[] { ':', '.', ',' }); ts = new TimeSpan(0, int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3])); } return new TimeCode(ts); diff --git a/src/Logic/SubtitleFormats/TimedText10.cs b/src/Logic/SubtitleFormats/TimedText10.cs index 9351dfd35..79a2452a5 100644 --- a/src/Logic/SubtitleFormats/TimedText10.cs +++ b/src/Logic/SubtitleFormats/TimedText10.cs @@ -34,16 +34,16 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats public override bool IsMine(List lines, string fileName) { - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); lines.ForEach(line => sb.AppendLine(line)); string xmlAsString = sb.ToString().Trim(); if (xmlAsString.Contains("http://www.w3.org/ns/ttml")) { - XmlDocument xml = new XmlDocument(); + var xml = new XmlDocument(); try { xml.LoadXml(xmlAsString); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable); + var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); var nds = xml.DocumentElement.SelectSingleNode("ttml:body", nsmgr); var paragraphs = nds.SelectNodes("//ttml:p", nsmgr); @@ -80,9 +80,9 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats " " + Environment.NewLine + ""; - XmlDocument xml = new XmlDocument(); + var xml = new XmlDocument(); xml.LoadXml(xmlStructure); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable); + var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); nsmgr.AddNamespace("ttp", "http://www.w3.org/ns/10/ttml#parameter"); nsmgr.AddNamespace("tts", "http://www.w3.org/ns/10/ttml#style"); @@ -127,9 +127,8 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats no++; } - MemoryStream ms = new MemoryStream(); - XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8); - writer.Formatting = Formatting.Indented; + var ms = new MemoryStream(); + var writer = new XmlTextWriter(ms, Encoding.UTF8) {Formatting = Formatting.Indented}; xml.Save(writer); return Encoding.UTF8.GetString(ms.ToArray()).Trim(); } @@ -139,28 +138,61 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats _errorCount = 0; double startSeconds = 0; - StringBuilder sb = new StringBuilder(); + var sb = new StringBuilder(); lines.ForEach(line => sb.AppendLine(line)); - XmlDocument xml = new XmlDocument(); + var xml = new XmlDocument(); xml.LoadXml(sb.ToString()); - XmlNamespaceManager nsmgr = new XmlNamespaceManager(xml.NameTable); + var nsmgr = new XmlNamespaceManager(xml.NameTable); nsmgr.AddNamespace("ttml", "http://www.w3.org/ns/ttml"); XmlNode body = xml.DocumentElement.SelectSingleNode("ttml:body", nsmgr); foreach (XmlNode node in body.SelectNodes("//ttml:p", nsmgr)) { try { - StringBuilder pText = new StringBuilder(); + var pText = new StringBuilder(); foreach (XmlNode innerNode in node.ChildNodes) { - switch (innerNode.Name.ToString()) + switch (innerNode.Name) { case "br": pText.AppendLine(); break; + case "span": + bool italic = false; + if (innerNode.Attributes != null) + { + var fs = innerNode.Attributes.GetNamedItem("tts:fontStyle"); + if (fs != null && fs.Value == "italic") + { + italic = true; + pText.Append(""); + } + } + if (innerNode.HasChildNodes) + { + foreach (XmlNode innerInnerNode in innerNode.ChildNodes) + { + if (innerInnerNode.Name == "br") + { + pText.AppendLine(); + } + else + { + pText.Append(innerInnerNode.InnerText); + } + } + } + else + { + pText.Append(innerNode.InnerText); + } + if (italic) + pText.Append(""); + break; + default: - pText.Append(innerNode.InnerText.Trim()); + pText.Append(innerNode.InnerText); break; } } @@ -183,7 +215,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats dur = node.Attributes["dur"].InnerText; } - TimeCode startCode = new TimeCode(TimeSpan.FromSeconds(startSeconds)); + var startCode = new TimeCode(TimeSpan.FromSeconds(startSeconds)); if (start != string.Empty) { startCode = GetTimeCode(start); @@ -204,7 +236,7 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats } startSeconds = endCode.TotalSeconds; - subtitle.Paragraphs.Add(new Paragraph(startCode, endCode, pText.ToString())); + subtitle.Paragraphs.Add(new Paragraph(startCode, endCode, pText.ToString().Replace(" ", " ").Replace(" ", " "))); } catch (Exception ex) { @@ -223,12 +255,8 @@ namespace Nikse.SubtitleEdit.Logic.SubtitleFormats TimeSpan ts = TimeSpan.FromSeconds(double.Parse(s)); return new TimeCode(ts); } - else - { - string[] parts = s.Split(new char[] { ':', '.', ',' }); - TimeSpan ts = new TimeSpan(0, int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3])); - return new TimeCode(ts); - } + string[] parts = s.Split(new[] { ':', '.', ',' }); + return new TimeCode(new TimeSpan(0, int.Parse(parts[0]), int.Parse(parts[1]), int.Parse(parts[2]), int.Parse(parts[3]))); } } } diff --git a/src/Logic/SubtitleFormats/UnknownSubtitle16.cs b/src/Logic/SubtitleFormats/UnknownSubtitle16.cs new file mode 100644 index 000000000..6828c3954 --- /dev/null +++ b/src/Logic/SubtitleFormats/UnknownSubtitle16.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Text.RegularExpressions; + +namespace Nikse.SubtitleEdit.Logic.SubtitleFormats +{ + public class UnknownSubtitle16 : SubtitleFormat + { + static readonly Regex RegexTimeCode = new Regex(@" \d\d:\d\d:\d\d.\d\d\\tab \d\d:\d\d:\d\d.\d\d", RegexOptions.Compiled); + + public override string Extension + { + get { return ".cip"; } + } + + public override string Name + { + get { return "Unknown 16"; } + } + + public override bool HasLineNumber + { + get { return false; } + } + + public override bool IsTimeBased + { + get { return true; } + } + + public override bool IsMine(List lines, string fileName) + { + var subtitle = new Subtitle(); + LoadSubtitle(subtitle, lines, fileName); + return subtitle.Paragraphs.Count > _errorCount; + } + + private string MakeTimeCode(TimeCode tc) + { + //10:01:37.23 + return string.Format("{0:00}:{1:00}:{2:00}.{3:00}", tc.Hours, tc.Minutes, tc.Seconds, MillisecondsToFrames(tc.Milliseconds)); + } + + public override string ToText(Subtitle subtitle, string title) + { + var sb = new StringBuilder(); + sb.AppendLine(@"{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Tahoma;}{\f1\fnil\fcharset0 Courier New;}{\f2\fmodern\fprq6\fcharset0 SimSun;}{\f3\fmodern\fprq1\fcharset0 Gulim;}}"); + sb.AppendLine(@"{\colortbl ;\red0\green0\blue0;\red230\green230\blue230;\red0\green0\blue220;\red255\green255\blue255;}"); + foreach (Paragraph p in subtitle.Paragraphs) + { + sb.Append(@"\protect0\pard\protect\tx1320\tx2933\tx4546\tx6160\tx8066\cf2\highlight2\fs22 #0\cf3 1026\tab "); + sb.Append(MakeTimeCode(p.StartTime)); + sb.Append(@"\tab "); + sb.Append(MakeTimeCode(p.EndTime)); + sb.AppendLine(@"\tab\cf2 00:00:0\cf3 2.10\tab #F CC\cf2 00000D0\cf3\tab\cf2 #C\cf3 \highlight0\fs15\par"); + sb.AppendLine(p.Text.Trim().Replace(Environment.NewLine, @"\par" + Environment.NewLine)+ @"\par"); + } + sb.AppendLine("}"); + return sb.ToString().Trim(); + } + + private TimeCode DecodeTimeCode(string timeCode) + { + string[] arr = timeCode.Split(".,:".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + int hour = int.Parse(arr[0]); + int minutes = int.Parse(arr[1]); + int seconds = int.Parse(arr[2]); + int frames = int.Parse(arr[3]); + + int milliseconds = (int) Math.Round(((1000.0 / Configuration.Settings.General.CurrentFrameRate) * frames)); + if (milliseconds > 999) + milliseconds = 999; + + return new TimeCode(hour, minutes, seconds, milliseconds); + } + + public override void LoadSubtitle(Subtitle subtitle, List lines, string fileName) + { + _errorCount = 0; + Paragraph p = null; + var text = new StringBuilder(); + + if (lines.Count == 0 || !lines[0].Trim().StartsWith("{\\rtf1")) + return; + + foreach (string line in lines) + { + string s = line.Trim(); + Match match = RegexTimeCode.Match(s); + if (match.Success) + { + try + { + if (p != null) + { + p.Text = text.ToString().Trim(); + subtitle.Paragraphs.Add(p); + } + string[] arr = s.Substring(match.Index, match.Length).Split("\\".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + text = new StringBuilder(); + p = new Paragraph(DecodeTimeCode(arr[0]), DecodeTimeCode(arr[1].Replace("tab ", string.Empty)), ""); + } + catch + { + _errorCount++; + p = null; + } + } + else if (p != null) + { + if (s.StartsWith("\\")) + { + int index = s.IndexOf(" "); + if (index > 0 && index < s.Length - 1) + { + s = s.Substring(index); + index = s.IndexOf("\\"); + if (index > 0) + s = s.Substring(0, index); + text.AppendLine(s.Trim()); + } + } + else + { + int index = s.IndexOf("\\"); + if (index > 0) + s = s.Substring(0, index); + text.AppendLine(s.Trim()); + } + } + else + { + _errorCount++; + } + } + + if (p != null && p.Text.Length > 0) + { + p.Text = text.ToString().Trim(); + subtitle.Paragraphs.Add(p); + } + subtitle.Renumber(1); + } + + } +} diff --git a/src/SubtitleEdit.csproj b/src/SubtitleEdit.csproj index 0fc94c6e1..3f3bbaeda 100644 --- a/src/SubtitleEdit.csproj +++ b/src/SubtitleEdit.csproj @@ -584,6 +584,7 @@ + @@ -634,6 +635,7 @@ +