2016-11-19 22:40:34 +01:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace Nikse.SubtitleEdit.Core
|
|
|
|
|
{
|
|
|
|
|
public class StrippableText
|
|
|
|
|
{
|
|
|
|
|
public string Pre { get; set; }
|
|
|
|
|
public string Post { get; set; }
|
|
|
|
|
public string StrippedText { get; set; }
|
2017-08-03 18:31:21 +02:00
|
|
|
|
public string OriginalText { get; }
|
2016-11-19 22:40:34 +01:00
|
|
|
|
|
2017-08-03 18:31:21 +02:00
|
|
|
|
public string MergedString => Pre + StrippedText + Post;
|
2016-11-19 22:40:34 +01:00
|
|
|
|
|
|
|
|
|
public StrippableText(string text)
|
2017-08-03 18:31:21 +02:00
|
|
|
|
: this(text, " >-\"„”“['‘`´¶(♪¿¡.…—", " -\"”“]'`´¶)♪.!?:…—؛،؟")
|
2016-11-19 22:40:34 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-29 21:33:20 +01:00
|
|
|
|
public StrippableText(string input, string stripStartCharacters, string stripEndCharacters)
|
2016-11-19 22:40:34 +01:00
|
|
|
|
{
|
2019-01-29 21:33:20 +01:00
|
|
|
|
OriginalText = input;
|
|
|
|
|
var text = input;
|
2016-11-19 22:40:34 +01:00
|
|
|
|
|
|
|
|
|
Pre = string.Empty;
|
|
|
|
|
if (text.Length > 0 && ("<{" + stripStartCharacters).Contains(text[0]))
|
|
|
|
|
{
|
|
|
|
|
int beginLength;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
beginLength = text.Length;
|
|
|
|
|
|
|
|
|
|
while (text.Length > 0 && stripStartCharacters.Contains(text[0]))
|
|
|
|
|
{
|
|
|
|
|
Pre += text[0];
|
|
|
|
|
text = text.Remove(0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ASS/SSA codes like {\an9}
|
|
|
|
|
int endIndex = text.IndexOf('}');
|
|
|
|
|
if (endIndex > 0 && text.StartsWith("{\\", StringComparison.Ordinal))
|
|
|
|
|
{
|
|
|
|
|
int nextStartIndex = text.IndexOf('{', 2);
|
|
|
|
|
if (nextStartIndex == -1 || nextStartIndex > endIndex)
|
|
|
|
|
{
|
|
|
|
|
endIndex++;
|
|
|
|
|
Pre += text.Substring(0, endIndex);
|
|
|
|
|
text = text.Remove(0, endIndex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tags like <i> or <font face="Segoe Print" color="#ff0000">
|
|
|
|
|
endIndex = text.IndexOf('>');
|
|
|
|
|
if (text.StartsWith('<') && endIndex >= 2)
|
|
|
|
|
{
|
|
|
|
|
endIndex++;
|
|
|
|
|
Pre += text.Substring(0, endIndex);
|
|
|
|
|
text = text.Remove(0, endIndex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (text.Length < beginLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Post = string.Empty;
|
|
|
|
|
if (text.Length > 0 && (">" + stripEndCharacters).Contains(text[text.Length - 1]))
|
|
|
|
|
{
|
|
|
|
|
int beginLength;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
beginLength = text.Length;
|
|
|
|
|
|
|
|
|
|
while (text.Length > 0 && stripEndCharacters.Contains(text[text.Length - 1]))
|
|
|
|
|
{
|
|
|
|
|
Post = text[text.Length - 1] + Post;
|
|
|
|
|
text = text.Substring(0, text.Length - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (text.EndsWith('>'))
|
|
|
|
|
{
|
|
|
|
|
// tags </i> </b> </u>
|
|
|
|
|
if (text.EndsWith("</i>", StringComparison.OrdinalIgnoreCase) ||
|
|
|
|
|
text.EndsWith("</b>", StringComparison.OrdinalIgnoreCase) ||
|
|
|
|
|
text.EndsWith("</u>", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Post = text.Substring(text.Length - 4) + Post;
|
|
|
|
|
text = text.Substring(0, text.Length - 4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// tag </font>
|
|
|
|
|
if (text.EndsWith("</font>", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
Post = text.Substring(text.Length - 7) + Post;
|
|
|
|
|
text = text.Substring(0, text.Length - 7);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
while (text.Length < beginLength);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
StrippedText = text;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static string GetAndInsertNextId(List<string> replaceIds, List<string> replaceNames, string name, int idName)
|
|
|
|
|
{
|
|
|
|
|
string id = $"_@{idName}_";
|
|
|
|
|
replaceIds.Add(id);
|
|
|
|
|
replaceNames.Add(name);
|
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-10 19:23:24 +02:00
|
|
|
|
private void ReplaceNames1Remove(List<string> nameList, List<string> replaceIds, List<string> replaceNames, List<string> originalNames)
|
2016-11-19 22:40:34 +01:00
|
|
|
|
{
|
|
|
|
|
if (Post.StartsWith('.'))
|
|
|
|
|
{
|
|
|
|
|
StrippedText += ".";
|
|
|
|
|
Post = Post.Remove(0, 1);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-21 09:53:15 +01:00
|
|
|
|
string lower = StrippedText.ToLowerInvariant();
|
2016-11-19 22:40:34 +01:00
|
|
|
|
int idName = 0;
|
2017-04-10 19:23:24 +02:00
|
|
|
|
foreach (string name in nameList)
|
2016-11-19 22:40:34 +01:00
|
|
|
|
{
|
2018-01-02 21:38:03 +01:00
|
|
|
|
int start = lower.IndexOf(name.ToLowerInvariant(), StringComparison.Ordinal);
|
2016-11-19 22:40:34 +01:00
|
|
|
|
while (start >= 0 && start < lower.Length)
|
|
|
|
|
{
|
|
|
|
|
bool startOk = (start == 0) || (lower[start - 1] == ' ') || (lower[start - 1] == '-') ||
|
2018-01-27 13:50:44 +01:00
|
|
|
|
(lower[start - 1] == '"') || (lower[start - 1] == '\'') || (lower[start - 1] == '>') || (lower[start - 1] == '[') || (lower[start - 1] == '“') ||
|
2016-11-19 22:40:34 +01:00
|
|
|
|
Environment.NewLine.EndsWith(lower[start - 1]);
|
|
|
|
|
|
2017-03-28 18:52:18 +02:00
|
|
|
|
if (startOk && string.CompareOrdinal(name, "Don") == 0 && lower.Substring(start).StartsWith("don't", StringComparison.Ordinal))
|
2019-01-19 14:40:37 +01:00
|
|
|
|
{
|
2016-11-19 22:40:34 +01:00
|
|
|
|
startOk = false;
|
2019-01-19 14:40:37 +01:00
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
|
|
|
|
|
if (startOk)
|
|
|
|
|
{
|
|
|
|
|
int end = start + name.Length;
|
|
|
|
|
bool endOk = end <= lower.Length;
|
|
|
|
|
if (endOk)
|
2019-01-19 14:40:37 +01:00
|
|
|
|
{
|
2018-01-23 15:42:42 +01:00
|
|
|
|
endOk = end == lower.Length || (@" ,.!?:;')]- <”""" + Environment.NewLine).Contains(lower[end]);
|
2019-01-19 14:40:37 +01:00
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
|
|
|
|
|
if (endOk && StrippedText.Length >= start + name.Length)
|
|
|
|
|
{
|
|
|
|
|
string originalName = StrippedText.Substring(start, name.Length);
|
|
|
|
|
originalNames.Add(originalName);
|
|
|
|
|
StrippedText = StrippedText.Remove(start, name.Length);
|
|
|
|
|
StrippedText = StrippedText.Insert(start, GetAndInsertNextId(replaceIds, replaceNames, name, idName++));
|
2019-01-21 09:53:15 +01:00
|
|
|
|
lower = StrippedText.ToLowerInvariant();
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (start + 3 > lower.Length)
|
2019-01-19 14:40:37 +01:00
|
|
|
|
{
|
2016-11-19 22:40:34 +01:00
|
|
|
|
start = lower.Length + 1;
|
2019-01-19 14:40:37 +01:00
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
else
|
2019-01-19 14:40:37 +01:00
|
|
|
|
{
|
2016-11-19 22:40:34 +01:00
|
|
|
|
start = lower.IndexOf(name, start + 3, StringComparison.OrdinalIgnoreCase);
|
2019-01-19 14:40:37 +01:00
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (StrippedText.EndsWith('.'))
|
|
|
|
|
{
|
|
|
|
|
Post = "." + Post;
|
|
|
|
|
StrippedText = StrippedText.TrimEnd('.');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ReplaceNames2Fix(List<string> replaceIds, List<string> replaceNames)
|
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < replaceIds.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
StrippedText = StrippedText.Replace(replaceIds[i], replaceNames[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static readonly char[] ExpectedCharsArray = { '.', '!', '?', ':', ';', ')', ']', '}', '(', '[', '{' };
|
2018-01-24 16:11:48 +01:00
|
|
|
|
public void FixCasing(List<string> nameList, bool changeNameCases, bool makeUppercaseAfterBreak, bool checkLastLine, string lastLine, double millisecondsFromLast = 0)
|
2016-11-19 22:40:34 +01:00
|
|
|
|
{
|
|
|
|
|
var replaceIds = new List<string>();
|
|
|
|
|
var replaceNames = new List<string>();
|
|
|
|
|
var originalNames = new List<string>();
|
2017-04-10 19:23:24 +02:00
|
|
|
|
ReplaceNames1Remove(nameList, replaceIds, replaceNames, originalNames);
|
2016-11-19 22:40:34 +01:00
|
|
|
|
|
2018-03-06 02:10:42 +01:00
|
|
|
|
if (checkLastLine && ShouldStartWithUpperCase(lastLine, millisecondsFromLast))
|
2016-11-19 22:40:34 +01:00
|
|
|
|
{
|
2018-03-06 02:10:42 +01:00
|
|
|
|
if (StrippedText.StartsWith("_@", StringComparison.Ordinal))
|
2016-11-19 22:40:34 +01:00
|
|
|
|
{
|
2018-03-06 02:10:42 +01:00
|
|
|
|
for (int i = 0; i < replaceIds.Count; i++)
|
2017-04-14 15:48:43 +02:00
|
|
|
|
{
|
2018-03-06 02:10:42 +01:00
|
|
|
|
string id = $"_@{i}_";
|
|
|
|
|
if (StrippedText.StartsWith(id, StringComparison.Ordinal))
|
2018-01-02 21:38:03 +01:00
|
|
|
|
{
|
2018-03-06 02:10:42 +01:00
|
|
|
|
if (!string.IsNullOrEmpty(originalNames[i]))
|
2018-01-02 21:38:03 +01:00
|
|
|
|
{
|
2018-03-06 02:10:42 +01:00
|
|
|
|
originalNames[i] = originalNames[i].CapitalizeFirstLetter();
|
2018-01-02 21:38:03 +01:00
|
|
|
|
}
|
2018-03-06 02:10:42 +01:00
|
|
|
|
|
|
|
|
|
break;
|
2018-01-02 21:38:03 +01:00
|
|
|
|
}
|
2017-04-14 15:48:43 +02:00
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
2018-03-06 02:10:42 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
StrippedText = StrippedText.CapitalizeFirstLetter();
|
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (makeUppercaseAfterBreak && StrippedText.Contains(ExpectedCharsArray))
|
|
|
|
|
{
|
|
|
|
|
const string breakAfterChars = @".!?:;)]}([{";
|
2018-01-20 00:04:54 +01:00
|
|
|
|
const string expectedChars = "\"“`´'()<>!?.- \r\n";
|
2018-01-02 21:38:03 +01:00
|
|
|
|
var sb = new StringBuilder(StrippedText.Length);
|
2016-11-19 22:40:34 +01:00
|
|
|
|
bool lastWasBreak = false;
|
|
|
|
|
for (int i = 0; i < StrippedText.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
var s = StrippedText[i];
|
|
|
|
|
if (lastWasBreak)
|
|
|
|
|
{
|
|
|
|
|
if (expectedChars.Contains(s))
|
|
|
|
|
{
|
|
|
|
|
sb.Append(s);
|
|
|
|
|
}
|
|
|
|
|
else if ((sb.EndsWith('<') || sb.ToString().EndsWith("</", StringComparison.Ordinal)) && i + 1 < StrippedText.Length && StrippedText[i + 1] == '>')
|
|
|
|
|
{ // tags
|
|
|
|
|
sb.Append(s);
|
|
|
|
|
}
|
|
|
|
|
else if (sb.EndsWith('<') && s == '/' && i + 2 < StrippedText.Length && StrippedText[i + 2] == '>')
|
|
|
|
|
{ // tags
|
|
|
|
|
sb.Append(s);
|
|
|
|
|
}
|
|
|
|
|
else if (sb.ToString().EndsWith("... ", StringComparison.Ordinal))
|
|
|
|
|
{
|
|
|
|
|
sb.Append(s);
|
|
|
|
|
lastWasBreak = false;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (breakAfterChars.Contains(s))
|
|
|
|
|
{
|
|
|
|
|
sb.Append(s);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
lastWasBreak = false;
|
|
|
|
|
sb.Append(char.ToUpper(s));
|
2018-01-02 21:38:03 +01:00
|
|
|
|
|
|
|
|
|
if (StrippedText.Substring(i).StartsWith("_@", StringComparison.Ordinal))
|
|
|
|
|
{
|
|
|
|
|
var ks = StrippedText.Substring(i);
|
|
|
|
|
for (int k = 0; k < replaceIds.Count; k++)
|
|
|
|
|
{
|
|
|
|
|
string id = $"_@{k}_";
|
|
|
|
|
if (ks.StartsWith(id, StringComparison.Ordinal))
|
|
|
|
|
{
|
|
|
|
|
if (!string.IsNullOrEmpty(originalNames[k]))
|
2019-01-19 14:40:37 +01:00
|
|
|
|
{
|
2018-01-02 21:38:03 +01:00
|
|
|
|
originalNames[k] = char.ToUpper(originalNames[k][0]) + originalNames[k].Remove(0, 1);
|
2019-01-19 14:40:37 +01:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-02 21:38:03 +01:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
sb.Append(s);
|
|
|
|
|
if (breakAfterChars.Contains(s))
|
|
|
|
|
{
|
|
|
|
|
var idx = sb.ToString().IndexOf('[');
|
|
|
|
|
if (s == ']' && idx > 1)
|
|
|
|
|
{ // I [Motor roaring] love you!
|
|
|
|
|
string temp = sb.ToString(0, idx - 1).Trim();
|
2018-01-02 21:38:03 +01:00
|
|
|
|
if (temp.Length > 0 && !char.IsLetterOrDigit(temp[temp.Length - 1]))
|
2019-01-19 14:40:37 +01:00
|
|
|
|
{
|
2016-11-19 22:40:34 +01:00
|
|
|
|
lastWasBreak = true;
|
2019-01-19 14:40:37 +01:00
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
2018-01-02 21:38:03 +01:00
|
|
|
|
else if (s == ']' && idx == -1 && Pre.Contains('['))
|
|
|
|
|
{ // [ Motor roaring ] Hallo!
|
|
|
|
|
lastWasBreak = true;
|
|
|
|
|
}
|
|
|
|
|
else if (s == ':') // seems to be the rule (in subtitles) to nearly always capitalize first letter efter semicolon
|
|
|
|
|
{
|
|
|
|
|
lastWasBreak = true;
|
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
else
|
|
|
|
|
{
|
2017-04-14 15:48:43 +02:00
|
|
|
|
idx = sb.ToString().LastIndexOf(' ');
|
|
|
|
|
if (idx >= 0 && idx < sb.Length - 2 && !IsInMiddleOfUrl(i - idx, StrippedText.Substring(idx + 1)))
|
|
|
|
|
{
|
|
|
|
|
lastWasBreak = true;
|
|
|
|
|
}
|
2018-01-27 13:50:44 +01:00
|
|
|
|
else if (StrippedText.Length > i + 1 && " \r\n".Contains(StrippedText[i + 1]))
|
2018-01-20 00:04:54 +01:00
|
|
|
|
{
|
|
|
|
|
lastWasBreak = true;
|
|
|
|
|
}
|
2018-01-27 13:50:44 +01:00
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
2018-01-02 21:38:03 +01:00
|
|
|
|
else if (s == '-' && Pre.Contains("-"))
|
|
|
|
|
{
|
|
|
|
|
if (sb.ToString().EndsWith(Environment.NewLine + "-"))
|
|
|
|
|
{
|
|
|
|
|
var prevLine = HtmlUtil.RemoveHtmlTags(sb.ToString().Substring(0, sb.Length - 2).TrimEnd());
|
|
|
|
|
if (prevLine.EndsWith('.') ||
|
|
|
|
|
prevLine.EndsWith('!') ||
|
|
|
|
|
prevLine.EndsWith('?') ||
|
|
|
|
|
prevLine.EndsWith(". ♪", StringComparison.Ordinal) ||
|
|
|
|
|
prevLine.EndsWith("! ♪", StringComparison.Ordinal) ||
|
|
|
|
|
prevLine.EndsWith("? ♪", StringComparison.Ordinal) ||
|
|
|
|
|
prevLine.EndsWith(']') ||
|
|
|
|
|
prevLine.EndsWith(')') ||
|
|
|
|
|
prevLine.EndsWith(':'))
|
|
|
|
|
{
|
|
|
|
|
lastWasBreak = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
StrippedText = sb.ToString();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ReplaceNames2Fix(replaceIds, changeNameCases ? replaceNames : originalNames);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-25 21:04:18 +01:00
|
|
|
|
private static bool IsInMiddleOfUrl(int idx, string s)
|
2017-04-14 15:48:43 +02:00
|
|
|
|
{
|
|
|
|
|
if (idx < s.Length - 1 && (char.IsWhiteSpace(s[idx]) || char.IsPunctuation(s[idx])))
|
2019-01-19 14:40:37 +01:00
|
|
|
|
{
|
2017-04-14 15:48:43 +02:00
|
|
|
|
return false;
|
2019-01-19 14:40:37 +01:00
|
|
|
|
}
|
|
|
|
|
|
2017-04-14 15:48:43 +02:00
|
|
|
|
return s.StartsWith("www.", StringComparison.OrdinalIgnoreCase) || s.StartsWith("http", StringComparison.OrdinalIgnoreCase);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-19 22:40:34 +01:00
|
|
|
|
public string CombineWithPrePost(string text)
|
|
|
|
|
{
|
|
|
|
|
return Pre + text + Post;
|
|
|
|
|
}
|
2018-03-06 02:10:42 +01:00
|
|
|
|
|
|
|
|
|
private bool ShouldStartWithUpperCase(string lastLine, double millisecondsgaps)
|
|
|
|
|
{
|
|
|
|
|
// do not capitalize url
|
|
|
|
|
if (StrippedText.StartsWith("www.", StringComparison.OrdinalIgnoreCase) || StrippedText.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// do not capitalize word like iPhone
|
|
|
|
|
if (StrippedText.Length > 1 && StrippedText[0] == 'i' && char.IsUpper(StrippedText[1]))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// shouldn't capitalize current line not closed
|
|
|
|
|
if (Pre.Contains("...") || Pre.Contains("…"))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// too much gaps between lines, so should be considered as closed
|
|
|
|
|
if (millisecondsgaps > 5000)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var preLine = HtmlUtil.RemoveHtmlTags(lastLine).TrimEnd().TrimEnd('\"', '”').TrimEnd();
|
|
|
|
|
|
|
|
|
|
// check if previous line was fully closed
|
2018-03-14 01:45:05 +01:00
|
|
|
|
if (string.IsNullOrEmpty(preLine))
|
2018-03-06 02:10:42 +01:00
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-03-14 01:45:05 +01:00
|
|
|
|
|
2018-03-14 22:02:40 +01:00
|
|
|
|
char lastChar = preLine[preLine.Length - 1];
|
|
|
|
|
if (lastChar == '♪')
|
|
|
|
|
{
|
|
|
|
|
string tempPreLine = preLine.Substring(0, preLine.Length - 1).TrimEnd();
|
|
|
|
|
// update last char
|
|
|
|
|
if (tempPreLine.Length > 0)
|
2018-03-14 01:45:05 +01:00
|
|
|
|
{
|
2018-03-14 22:02:40 +01:00
|
|
|
|
lastChar = tempPreLine[tempPreLine.Length - 1];
|
2018-03-14 01:45:05 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-03-14 22:02:40 +01:00
|
|
|
|
if (lastChar == '.' || lastChar == '!' || lastChar == '?' || lastChar == ']' || lastChar == ')' || lastChar == ':' || lastChar == '_')
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2018-03-06 02:10:42 +01:00
|
|
|
|
|
|
|
|
|
// previous line ends with music symbol but current line doesn't contains any music symbol
|
|
|
|
|
if ((preLine.EndsWith('♪') || preLine.EndsWith('♫')) && !Pre.Contains(new[] { '♪', '♫' }))
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// do not capitalize
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2016-11-19 22:40:34 +01:00
|
|
|
|
}
|
|
|
|
|
}
|