public void FixCasing(List <string> nameList, bool changeNameCases, bool makeUppercaseAfterBreak, bool checkLastLine, string lastLine, double millisecondsFromLast = 0) { var replaceIds = new List <string>(); var replaceNames = new List <string>(); var originalNames = new List <string>(); ReplaceNames1Remove(nameList, replaceIds, replaceNames, originalNames); if (checkLastLine && ShouldStartWithUpperCase(lastLine, millisecondsFromLast)) { if (StrippedText.StartsWith("_@", StringComparison.Ordinal)) { for (int i = 0; i < replaceIds.Count; i++) { string id = $"_@{i}_"; if (StrippedText.StartsWith(id, StringComparison.Ordinal)) { if (!string.IsNullOrEmpty(originalNames[i])) { originalNames[i] = originalNames[i].CapitalizeFirstLetter(); } break; } } } else { StrippedText = StrippedText.CapitalizeFirstLetter(); } } if (makeUppercaseAfterBreak && StrippedText.Contains(ExpectedCharsArray)) { const string breakAfterChars = @".!?:;)]}([{"; const string expectedChars = "\"“`´'()<>!?.- \r\n"; var sb = new StringBuilder(StrippedText.Length); 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)); 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])) { originalNames[k] = char.ToUpper(originalNames[k][0]) + originalNames[k].Remove(0, 1); } break; } } } } } } 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(); if (temp.Length > 0 && !char.IsLetterOrDigit(temp[temp.Length - 1])) { lastWasBreak = true; } } else if (s == ']' && idx == -1 && Pre.IndexOf('[') >= 0) { // [ 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; } else { idx = sb.ToString().LastIndexOf(' '); if (idx >= 0 && idx < sb.Length - 2 && !IsInMiddleOfUrl(i - idx, StrippedText.Substring(idx + 1))) { lastWasBreak = true; } else if (StrippedText.Length > i + 1 && " \r\n".Contains(StrippedText[i + 1])) { lastWasBreak = true; } } } else if (s == '-' && Pre.IndexOf('-') >= 0) { 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; } } } } } StrippedText = sb.ToString(); } ReplaceNames2Fix(replaceIds, changeNameCases ? replaceNames : originalNames); }