Example #1
0
        public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
        {
            var    language      = Configuration.Settings.Language.FixCommonErrors;
            string fixAction     = language.BreakLongLine;
            int    noOfLongLines = 0;

            for (int i = 0; i < subtitle.Paragraphs.Count; i++)
            {
                Paragraph p       = subtitle.Paragraphs[i];
                var       lines   = p.Text.SplitToLines();
                bool      tooLong = false;
                foreach (string line in lines)
                {
                    if (HtmlUtil.RemoveHtmlTags(line, true).CountCharacters(false, Configuration.Settings.General.IgnoreArabicDiacritics) > Configuration.Settings.General.SubtitleLineMaximumLength)
                    {
                        tooLong = true;
                        break;
                    }
                }
                if (callbacks.AllowFix(p, fixAction) && tooLong)
                {
                    string oldText = p.Text;
                    p.Text = Utilities.AutoBreakLine(p.Text, callbacks.Language);
                    if (oldText != p.Text)
                    {
                        noOfLongLines++;
                        callbacks.AddFixToListView(p, fixAction, oldText, p.Text);
                    }
                    else
                    {
                        callbacks.LogStatus(fixAction, string.Format(language.UnableToFixTextXY, i + 1, p));
                        callbacks.AddToTotalErrors(1);
                    }
                }
            }

            callbacks.UpdateFixStatus(noOfLongLines, language.BreakLongLines, string.Format(language.XLineBreaksAdded, noOfLongLines));
        }
Example #2
0
        public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
        {
            var language = Configuration.Settings.Language.FixCommonErrors;
            string fixAction = language.BreakLongLine;
            int noOfLongLines = 0;
            for (int i = 0; i < subtitle.Paragraphs.Count; i++)
            {
                Paragraph p = subtitle.Paragraphs[i];
                var lines = p.Text.SplitToLines();
                bool tooLong = false;
                foreach (string line in lines)
                {
                    if (HtmlUtil.RemoveHtmlTags(line, true).Length > Configuration.Settings.General.SubtitleLineMaximumLength)
                    {
                        tooLong = true;
                        break;
                    }
                }
                if (callbacks.AllowFix(p, fixAction) && tooLong)
                {
                    string oldText = p.Text;
                    p.Text = Utilities.AutoBreakLine(p.Text, callbacks.Language);
                    if (oldText != p.Text)
                    {
                        noOfLongLines++;
                        callbacks.AddFixToListView(p, fixAction, oldText, p.Text);
                    }
                    else
                    {
                        callbacks.LogStatus(fixAction, string.Format(language.UnableToFixTextXY, i + 1, p));
                        callbacks.AddToTotalErrors(1);
                    }
                }
            }

            callbacks.UpdateFixStatus(noOfLongLines, language.BreakLongLines, string.Format(language.XLineBreaksAdded, noOfLongLines));
        }
Example #3
0
        public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
        {
            var fixAction     = Language.BreakLongLine;
            var noOfLongLines = 0;

            for (var i = 0; i < subtitle.Paragraphs.Count; i++)
            {
                var p       = subtitle.Paragraphs[i];
                var lines   = p.Text.SplitToLines();
                var tooLong = false;
                foreach (var line in lines)
                {
                    if (line.CountCharacters(false) > Configuration.Settings.General.SubtitleLineMaximumLength)
                    {
                        tooLong = true;
                        break;
                    }
                }
                if (callbacks.AllowFix(p, fixAction) && tooLong)
                {
                    string oldText = p.Text;
                    p.Text = Utilities.AutoBreakLine(p.Text, callbacks.Language);
                    if (oldText != p.Text)
                    {
                        noOfLongLines++;
                        callbacks.AddFixToListView(p, fixAction, oldText, p.Text);
                    }
                    else
                    {
                        callbacks.LogStatus(fixAction, string.Format(Language.UnableToFixTextXY, i + 1, p));
                        callbacks.AddToTotalErrors(1);
                    }
                }
            }

            callbacks.UpdateFixStatus(noOfLongLines, Language.BreakLongLines);
        }
        public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
        {
            var language = Configuration.Settings.Language.FixCommonErrors;
            _callbacks = callbacks;

            string fixAction = language.FixShortDisplayTime;
            int noOfShortDisplayTimes = 0;
            for (int i = 0; i < subtitle.Paragraphs.Count; i++)
            {
                Paragraph p = subtitle.Paragraphs[i];
                var skip = p.StartTime.IsMaxTime || p.EndTime.IsMaxTime;
                double displayTime = p.Duration.TotalMilliseconds;
                if (!skip && displayTime < Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
                {
                    Paragraph next = subtitle.GetParagraphOrDefault(i + 1);
                    Paragraph prev = subtitle.GetParagraphOrDefault(i - 1);
                    if (next == null || (p.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines) < next.StartTime.TotalMilliseconds)
                    {
                        var temp = new Paragraph(p) { EndTime = { TotalMilliseconds = p.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds } };
                        if (Utilities.GetCharactersPerSecond(temp) <= Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                        {
                            if (callbacks.AllowFix(p, fixAction))
                            {
                                string oldCurrent = p.ToString();
                                p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds;
                                noOfShortDisplayTimes++;
                                callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                            }
                        }
                    }
                    else if (Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && p.StartTime.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds &&
                             (prev == null || prev.EndTime.TotalMilliseconds < p.EndTime.TotalMilliseconds - Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines))
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            if (next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines > p.EndTime.TotalMilliseconds)
                                p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                            p.StartTime.TotalMilliseconds = p.EndTime.TotalMilliseconds - Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else
                    {
                        callbacks.LogStatus(language.FixShortDisplayTimes, string.Format(language.UnableToFixTextXY, i + 1, p));
                        callbacks.AddToTotalErrors(1);
                        skip = true;
                    }
                }

                double charactersPerSecond = Utilities.GetCharactersPerSecond(p);
                if (!skip && charactersPerSecond > Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                {
                    var temp = new Paragraph(p);
                    while (Utilities.GetCharactersPerSecond(temp) > Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                    {
                        temp.EndTime.TotalMilliseconds++;
                    }
                    Paragraph next = subtitle.GetParagraphOrDefault(i + 1);
                    Paragraph nextNext = subtitle.GetParagraphOrDefault(i + 2);
                    Paragraph prev = subtitle.GetParagraphOrDefault(i - 1);
                    double diffMs = temp.Duration.TotalMilliseconds - p.Duration.TotalMilliseconds;

                    // Normal - just make current subtitle duration longer
                    if (next == null || temp.EndTime.TotalMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines < next.StartTime.TotalMilliseconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            p.EndTime.TotalMilliseconds = temp.EndTime.TotalMilliseconds;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    // Start current subtitle earlier (max 50 ms)
                    else if (Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && p.StartTime.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds &&
                             diffMs < 50 && (prev == null || prev.EndTime.TotalMilliseconds < p.EndTime.TotalMilliseconds - temp.Duration.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines))
                    {
                        noOfShortDisplayTimes = MoveStartTime(fixAction, noOfShortDisplayTimes, p, temp, next);
                    }
                    // Make current subtitle duration longer + move next subtitle
                    else if (diffMs < 1000 &&
                             Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime &&
                             p.StartTime.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds &&
                             (nextNext == null || next.EndTime.TotalMilliseconds + diffMs + Configuration.Settings.General.MinimumMillisecondsBetweenLines * 2 < nextNext.StartTime.TotalMilliseconds))
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + temp.Duration.TotalMilliseconds;
                            var nextDurationMs = next.Duration.TotalMilliseconds;
                            next.StartTime.TotalMilliseconds = p.EndTime.TotalMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                            next.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds + nextDurationMs;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    // Make next subtitle duration shorter + make current subtitle duration longer
                    else if (diffMs < 1000 &&
                             Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && Utilities.GetCharactersPerSecond(new Paragraph(next.Text, p.StartTime.TotalMilliseconds + temp.Duration.TotalMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines, next.EndTime.TotalMilliseconds)) < Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            next.StartTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + temp.Duration.TotalMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                            p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    // Make next-next subtitle duration shorter + move next + make current subtitle duration longer
                    else if (diffMs < 500 &&
                             Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && nextNext != null &&
                             Utilities.GetCharactersPerSecond(new Paragraph(nextNext.Text, nextNext.StartTime.TotalMilliseconds + diffMs + Configuration.Settings.General.MinimumMillisecondsBetweenLines, nextNext.EndTime.TotalMilliseconds - (diffMs))) < Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            p.EndTime.TotalMilliseconds += diffMs;
                            next.StartTime.TotalMilliseconds += diffMs;
                            next.EndTime.TotalMilliseconds += diffMs;
                            nextNext.StartTime.TotalMilliseconds += diffMs;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    // Start current subtitle earlier (max 200 ms)
                    else if (Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && p.StartTime.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds &&
                             diffMs < 200 && (prev == null || prev.EndTime.TotalMilliseconds < p.EndTime.TotalMilliseconds - temp.Duration.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines))
                    {
                        noOfShortDisplayTimes = MoveStartTime(fixAction, noOfShortDisplayTimes, p, temp, next);
                    }
                    else
                    {
                        // move some... though not enough
                        var improvedEndtime = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                        if (improvedEndtime > p.EndTime.TotalMilliseconds)
                        {
                            if (callbacks.AllowFix(p, fixAction))
                            {
                                string oldCurrent = p.ToString();
                                p.EndTime.TotalMilliseconds = improvedEndtime;
                                noOfShortDisplayTimes++;
                                callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                            }
                        }

                        callbacks.LogStatus(language.FixShortDisplayTimes, string.Format(language.UnableToFixTextXY, i + 1, p));
                        callbacks.AddToTotalErrors(1);
                    }
                }
            }
            callbacks.UpdateFixStatus(noOfShortDisplayTimes, fixAction, string.Format(language.XDisplayTimesProlonged, noOfShortDisplayTimes));
        }
        public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
        {
            var language = Configuration.Settings.Language.FixCommonErrors;

            _callbacks = callbacks;

            string fixAction             = language.FixShortDisplayTime;
            int    noOfShortDisplayTimes = 0;

            for (int i = 0; i < subtitle.Paragraphs.Count; i++)
            {
                Paragraph p           = subtitle.Paragraphs[i];
                var       skip        = p.StartTime.IsMaxTime || p.EndTime.IsMaxTime;
                double    displayTime = p.Duration.TotalMilliseconds;
                if (!skip && displayTime < Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
                {
                    Paragraph next = subtitle.GetParagraphOrDefault(i + 1);
                    Paragraph prev = subtitle.GetParagraphOrDefault(i - 1);
                    if (next == null || (p.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines) < next.StartTime.TotalMilliseconds)
                    {
                        var temp = new Paragraph(p)
                        {
                            EndTime = { TotalMilliseconds = p.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds }
                        };
                        if (Utilities.GetCharactersPerSecond(temp) <= Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                        {
                            if (callbacks.AllowFix(p, fixAction))
                            {
                                string oldCurrent = p.ToString();
                                p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds;
                                noOfShortDisplayTimes++;
                                callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                            }
                        }
                    }
                    else if (Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && p.StartTime.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds &&
                             (prev == null || prev.EndTime.TotalMilliseconds < p.EndTime.TotalMilliseconds - Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines))
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            if (next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines > p.EndTime.TotalMilliseconds)
                            {
                                p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                            }

                            p.StartTime.TotalMilliseconds = p.EndTime.TotalMilliseconds - Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else
                    {
                        callbacks.LogStatus(language.FixShortDisplayTimes, string.Format(language.UnableToFixTextXY, i + 1, p));
                        callbacks.AddToTotalErrors(1);
                        skip = true;
                    }
                }

                double charactersPerSecond = Utilities.GetCharactersPerSecond(p);
                if (!skip && charactersPerSecond > Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                {
                    var temp = new Paragraph(p);
                    var numberOfCharacters = temp.Text.CountCharacters(Configuration.Settings.General.CharactersPerSecondsIgnoreWhiteSpace);
                    while (Utilities.GetCharactersPerSecond(temp, numberOfCharacters) > Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                    {
                        temp.EndTime.TotalMilliseconds++;
                    }
                    Paragraph next     = subtitle.GetParagraphOrDefault(i + 1);
                    Paragraph nextNext = subtitle.GetParagraphOrDefault(i + 2);
                    Paragraph prev     = subtitle.GetParagraphOrDefault(i - 1);
                    double    diffMs   = temp.Duration.TotalMilliseconds - p.Duration.TotalMilliseconds;

                    // Normal - just make current subtitle duration longer
                    if (next == null || temp.EndTime.TotalMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines < next.StartTime.TotalMilliseconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            p.EndTime.TotalMilliseconds = temp.EndTime.TotalMilliseconds;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    // Start current subtitle earlier (max 50 ms)
                    else if (Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && p.StartTime.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds &&
                             diffMs < 50 && (prev == null || prev.EndTime.TotalMilliseconds < p.EndTime.TotalMilliseconds - temp.Duration.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines))
                    {
                        noOfShortDisplayTimes = MoveStartTime(fixAction, noOfShortDisplayTimes, p, temp, next);
                    }
                    // Make current subtitle duration longer + move next subtitle
                    else if (diffMs < 1000 &&
                             Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime &&
                             p.StartTime.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds &&
                             (nextNext == null || next.EndTime.TotalMilliseconds + diffMs + Configuration.Settings.General.MinimumMillisecondsBetweenLines * 2 < nextNext.StartTime.TotalMilliseconds))
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + temp.Duration.TotalMilliseconds;
                            var nextDurationMs = next.Duration.TotalMilliseconds;
                            next.StartTime.TotalMilliseconds = p.EndTime.TotalMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                            next.EndTime.TotalMilliseconds   = next.StartTime.TotalMilliseconds + nextDurationMs;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    // Make next subtitle duration shorter + make current subtitle duration longer
                    else if (diffMs < 1000 &&
                             Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && Utilities.GetCharactersPerSecond(new Paragraph(next.Text, p.StartTime.TotalMilliseconds + temp.Duration.TotalMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines, next.EndTime.TotalMilliseconds)) < Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            next.StartTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + temp.Duration.TotalMilliseconds + Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                            p.EndTime.TotalMilliseconds      = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    // Make next-next subtitle duration shorter + move next + make current subtitle duration longer
                    else if (diffMs < 500 &&
                             Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && nextNext != null &&
                             Utilities.GetCharactersPerSecond(new Paragraph(nextNext.Text, nextNext.StartTime.TotalMilliseconds + diffMs + Configuration.Settings.General.MinimumMillisecondsBetweenLines, nextNext.EndTime.TotalMilliseconds - (diffMs))) < Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            string oldCurrent = p.ToString();
                            p.EndTime.TotalMilliseconds          += diffMs;
                            next.StartTime.TotalMilliseconds     += diffMs;
                            next.EndTime.TotalMilliseconds       += diffMs;
                            nextNext.StartTime.TotalMilliseconds += diffMs;
                            noOfShortDisplayTimes++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    // Start current subtitle earlier (max 200 ms)
                    else if (Configuration.Settings.Tools.FixShortDisplayTimesAllowMoveStartTime && p.StartTime.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds &&
                             diffMs < 200 && (prev == null || prev.EndTime.TotalMilliseconds < p.EndTime.TotalMilliseconds - temp.Duration.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines))
                    {
                        noOfShortDisplayTimes = MoveStartTime(fixAction, noOfShortDisplayTimes, p, temp, next);
                    }
                    else
                    {
                        // move some... though not enough
                        var improvedEndtime = next.StartTime.TotalMilliseconds - Configuration.Settings.General.MinimumMillisecondsBetweenLines;
                        if (improvedEndtime > p.EndTime.TotalMilliseconds)
                        {
                            if (callbacks.AllowFix(p, fixAction))
                            {
                                string oldCurrent = p.ToString();
                                p.EndTime.TotalMilliseconds = improvedEndtime;
                                noOfShortDisplayTimes++;
                                callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                            }
                        }

                        callbacks.LogStatus(language.FixShortDisplayTimes, string.Format(language.UnableToFixTextXY, i + 1, p));
                        callbacks.AddToTotalErrors(1);
                    }
                }
            }
            callbacks.UpdateFixStatus(noOfShortDisplayTimes, fixAction, string.Format(language.XDisplayTimesProlonged, noOfShortDisplayTimes));
        }
        public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
        {
            // negative display time
            string fixAction = Language.FixOverlappingDisplayTime;
            int    noOfOverlappingDisplayTimesFixed = 0;

            for (int i = 0; i < subtitle.Paragraphs.Count; i++)
            {
                var p    = subtitle.Paragraphs[i];
                var oldP = new Paragraph(p);
                if (p.Duration.TotalMilliseconds < 0) // negative display time...
                {
                    bool   isFixed = false;
                    string status  = string.Format(Language.StartTimeLaterThanEndTime, i + 1, p.StartTime, p.EndTime, p.Text, Environment.NewLine);

                    var prev = subtitle.GetParagraphOrDefault(i - 1);
                    var next = subtitle.GetParagraphOrDefault(i + 1);

                    double wantedDisplayTime = Utilities.GetOptimalDisplayMilliseconds(p.Text) * 0.9;

                    if (next == null || next.StartTime.TotalMilliseconds > p.StartTime.TotalMilliseconds + wantedDisplayTime)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + wantedDisplayTime;
                            isFixed = true;
                        }
                    }
                    else if (next.StartTime.TotalMilliseconds > p.StartTime.TotalMilliseconds + 500.0)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + 500.0;
                            isFixed = true;
                        }
                    }
                    else if (prev == null || next.StartTime.TotalMilliseconds - wantedDisplayTime > prev.EndTime.TotalMilliseconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.StartTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - wantedDisplayTime;
                            p.EndTime.TotalMilliseconds   = next.StartTime.TotalMilliseconds - 1;
                            isFixed = true;
                        }
                    }
                    else
                    {
                        callbacks.LogStatus(Language.FixOverlappingDisplayTimes, string.Format(Language.UnableToFixStartTimeLaterThanEndTime, i + 1, p), true);
                        callbacks.AddToTotalErrors(1);
                    }

                    if (isFixed)
                    {
                        noOfOverlappingDisplayTimesFixed++;
                        status = string.Format(Language.XFixedToYZ, status, Environment.NewLine, p);
                        callbacks.LogStatus(Language.FixOverlappingDisplayTimes, status);
                        callbacks.AddFixToListView(p, fixAction, oldP.ToString(), p.ToString());
                    }
                }
            }

            // overlapping display time
            for (int i = 1; i < subtitle.Paragraphs.Count; i++)
            {
                Paragraph p                         = subtitle.Paragraphs[i];
                Paragraph prev                      = subtitle.GetParagraphOrDefault(i - 1);
                Paragraph target                    = prev;
                string    oldCurrent                = p.ToString();
                string    oldPrevious               = prev.ToString();
                double    prevWantedDisplayTime     = Utilities.GetOptimalDisplayMilliseconds(prev.Text, Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds);
                double    currentWantedDisplayTime  = Utilities.GetOptimalDisplayMilliseconds(p.Text, Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds);
                double    prevOptimalDisplayTime    = Utilities.GetOptimalDisplayMilliseconds(prev.Text);
                double    currentOptimalDisplayTime = Utilities.GetOptimalDisplayMilliseconds(p.Text);
                bool      canBeEqual                = callbacks.Format != null && (callbacks.Format.GetType() == typeof(AdvancedSubStationAlpha) || callbacks.Format.GetType() == typeof(SubStationAlpha));
                if (!canBeEqual)
                {
                    canBeEqual = Configuration.Settings.Tools.FixCommonErrorsFixOverlapAllowEqualEndStart;
                }

                double diff = prev.EndTime.TotalMilliseconds - p.StartTime.TotalMilliseconds;
                if (!prev.StartTime.IsMaxTime && !p.StartTime.IsMaxTime && diff >= 0 && !(canBeEqual && Math.Abs(diff) < 0.001))
                {
                    int diffHalf = (int)(diff / 2);
                    if (!Configuration.Settings.Tools.FixCommonErrorsFixOverlapAllowEqualEndStart && Math.Abs(p.StartTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds) < 0.001 &&
                        prev.Duration.TotalMilliseconds > 100)
                    {
                        if (callbacks.AllowFix(target, fixAction))
                        {
                            if (!canBeEqual)
                            {
                                bool okEqual = true;
                                if (prev.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
                                {
                                    prev.EndTime.TotalMilliseconds--;
                                }
                                else if (p.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
                                {
                                    p.StartTime.TotalMilliseconds++;
                                }
                                else
                                {
                                    okEqual = false;
                                }

                                if (okEqual)
                                {
                                    noOfOverlappingDisplayTimesFixed++;
                                    callbacks.AddFixToListView(target, fixAction, oldPrevious, prev.ToString());
                                }
                            }
                        }
                    }
                    else if (prevOptimalDisplayTime <= (p.StartTime.TotalMilliseconds - prev.StartTime.TotalMilliseconds))
                    {
                        if (callbacks.AllowFix(target, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds - 1;
                            if (canBeEqual)
                            {
                                prev.EndTime.TotalMilliseconds++;
                            }

                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(target, fixAction, oldPrevious, prev.ToString());
                        }
                    }
                    else if (diff > 0 && currentOptimalDisplayTime <= p.Duration.TotalMilliseconds - diffHalf &&
                             prevOptimalDisplayTime <= prev.Duration.TotalMilliseconds - diffHalf)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds -= diffHalf;
                            p.StartTime.TotalMilliseconds   = prev.EndTime.TotalMilliseconds + 1;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (currentOptimalDisplayTime <= p.EndTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            if (canBeEqual)
                            {
                                p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds;
                            }

                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (diff > 0 && currentWantedDisplayTime <= p.Duration.TotalMilliseconds - diffHalf &&
                             prevWantedDisplayTime <= prev.Duration.TotalMilliseconds - diffHalf)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds -= diffHalf;
                            p.StartTime.TotalMilliseconds   = prev.EndTime.TotalMilliseconds + 1;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (prevWantedDisplayTime <= (p.StartTime.TotalMilliseconds - prev.StartTime.TotalMilliseconds))
                    {
                        if (callbacks.AllowFix(target, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds - 1;
                            if (canBeEqual)
                            {
                                prev.EndTime.TotalMilliseconds++;
                            }

                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(target, fixAction, oldPrevious, prev.ToString());
                        }
                    }
                    else if (currentWantedDisplayTime <= p.EndTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            if (canBeEqual)
                            {
                                p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds;
                            }

                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (Math.Abs(p.StartTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds) < 10 && p.Duration.TotalMilliseconds > 1)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds -= 2;
                            p.StartTime.TotalMilliseconds   = prev.EndTime.TotalMilliseconds + 1;
                            if (canBeEqual)
                            {
                                p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds;
                            }

                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (Math.Abs(p.StartTime.TotalMilliseconds - prev.StartTime.TotalMilliseconds) < 10 && Math.Abs(p.EndTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds) < 10)
                    { // merge lines with same time codes
                        if (callbacks.AllowFix(target, fixAction))
                        {
                            prev.Text = prev.Text.Replace(Environment.NewLine, " ");
                            p.Text    = p.Text.Replace(Environment.NewLine, " ");

                            string stripped = HtmlUtil.RemoveHtmlTags(prev.Text).TrimStart();
                            if (!stripped.StartsWith("- ", StringComparison.Ordinal))
                            {
                                prev.Text = "- " + prev.Text.TrimStart();
                            }

                            stripped = HtmlUtil.RemoveHtmlTags(p.Text).TrimStart();
                            if (!stripped.StartsWith("- ", StringComparison.Ordinal))
                            {
                                p.Text = "- " + p.Text.TrimStart();
                            }

                            prev.Text = prev.Text.Trim() + Environment.NewLine + p.Text;
                            p.Text    = string.Empty;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(target, fixAction, oldCurrent, p.ToString());

                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            p.EndTime.TotalMilliseconds   = p.StartTime.TotalMilliseconds + 1;
                            if (canBeEqual)
                            {
                                p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds;
                                p.EndTime.TotalMilliseconds   = p.StartTime.TotalMilliseconds;
                            }
                        }
                    }
                    else
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            callbacks.LogStatus(Language.FixOverlappingDisplayTimes, string.Format(Language.UnableToFixTextXY, i + 1, Environment.NewLine + prev.Number + "  " + prev + Environment.NewLine + p.Number + "  " + p), true);
                            callbacks.AddToTotalErrors(1);
                        }
                    }
                }
            }

            callbacks.UpdateFixStatus(noOfOverlappingDisplayTimesFixed, fixAction);
        }
        public void Fix(Subtitle subtitle, IFixCallbacks callbacks)
        {
            var language = Configuration.Settings.Language.FixCommonErrors;

            // negative display time
            string fixAction = language.FixOverlappingDisplayTime;
            int noOfOverlappingDisplayTimesFixed = 0;
            for (int i = 0; i < subtitle.Paragraphs.Count; i++)
            {
                var p = subtitle.Paragraphs[i];
                var oldP = new Paragraph(p);
                if (p.Duration.TotalMilliseconds < 0) // negative display time...
                {
                    bool isFixed = false;
                    string status = string.Format(language.StartTimeLaterThanEndTime,
                                                    i + 1, p.StartTime, p.EndTime, p.Text, Environment.NewLine);

                    var prev = subtitle.GetParagraphOrDefault(i - 1);
                    var next = subtitle.GetParagraphOrDefault(i + 1);

                    double wantedDisplayTime = Utilities.GetOptimalDisplayMilliseconds(p.Text) * 0.9;

                    if (next == null || next.StartTime.TotalMilliseconds > p.StartTime.TotalMilliseconds + wantedDisplayTime)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + wantedDisplayTime;
                            isFixed = true;
                        }
                    }
                    else if (next.StartTime.TotalMilliseconds > p.StartTime.TotalMilliseconds + 500.0)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + 500.0;
                            isFixed = true;
                        }
                    }
                    else if (prev == null || next.StartTime.TotalMilliseconds - wantedDisplayTime > prev.EndTime.TotalMilliseconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.StartTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - wantedDisplayTime;
                            p.EndTime.TotalMilliseconds = next.StartTime.TotalMilliseconds - 1;
                            isFixed = true;
                        }
                    }
                    else
                    {
                        callbacks.LogStatus(language.FixOverlappingDisplayTimes, string.Format(language.UnableToFixStartTimeLaterThanEndTime, i + 1, p), true);
                        callbacks.AddToTotalErrors(1);
                    }

                    if (isFixed)
                    {
                        noOfOverlappingDisplayTimesFixed++;
                        status = string.Format(language.XFixedToYZ, status, Environment.NewLine, p);
                        callbacks.LogStatus(language.FixOverlappingDisplayTimes, status);
                        callbacks.AddFixToListView(p, fixAction, oldP.ToString(), p.ToString());
                    }
                }
            }

            // overlapping display time
            for (int i = 1; i < subtitle.Paragraphs.Count; i++)
            {
                Paragraph p = subtitle.Paragraphs[i];
                Paragraph prev = subtitle.GetParagraphOrDefault(i - 1);
                Paragraph target = prev;
                string oldCurrent = p.ToString();
                string oldPrevious = prev.ToString();
                double prevWantedDisplayTime = Utilities.GetOptimalDisplayMilliseconds(prev.Text, Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds);
                double currentWantedDisplayTime = Utilities.GetOptimalDisplayMilliseconds(p.Text, Configuration.Settings.General.SubtitleMaximumCharactersPerSeconds);
                double prevOptimalDisplayTime = Utilities.GetOptimalDisplayMilliseconds(prev.Text);
                double currentOptimalDisplayTime = Utilities.GetOptimalDisplayMilliseconds(p.Text);
                bool canBeEqual = callbacks.Format != null && callbacks.Format.GetType() == typeof(AdvancedSubStationAlpha) || callbacks.Format.GetType() == typeof(SubStationAlpha);
                if (!canBeEqual)
                    canBeEqual = Configuration.Settings.Tools.FixCommonErrorsFixOverlapAllowEqualEndStart;

                double diff = prev.EndTime.TotalMilliseconds - p.StartTime.TotalMilliseconds;
                if (!prev.StartTime.IsMaxTime && !p.StartTime.IsMaxTime && diff >= 0 && !(canBeEqual && Math.Abs(diff) < 0.001))
                {
                    int diffHalf = (int)(diff / 2);
                    if (!Configuration.Settings.Tools.FixCommonErrorsFixOverlapAllowEqualEndStart && Math.Abs(p.StartTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds) < 0.001 &&
                        prev.Duration.TotalMilliseconds > 100)
                    {
                        if (callbacks.AllowFix(target, fixAction))
                        {
                            if (!canBeEqual)
                            {
                                bool okEqual = true;
                                if (prev.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
                                    prev.EndTime.TotalMilliseconds--;
                                else if (p.Duration.TotalMilliseconds > Configuration.Settings.General.SubtitleMinimumDisplayMilliseconds)
                                    p.StartTime.TotalMilliseconds++;
                                else
                                    okEqual = false;
                                if (okEqual)
                                {
                                    noOfOverlappingDisplayTimesFixed++;
                                    callbacks.AddFixToListView(target, fixAction, oldPrevious, prev.ToString());
                                }
                            }
                        }
                        //prev.EndTime.TotalMilliseconds--;
                    }
                    else if (prevOptimalDisplayTime <= (p.StartTime.TotalMilliseconds - prev.StartTime.TotalMilliseconds))
                    {
                        if (callbacks.AllowFix(target, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds - 1;
                            if (canBeEqual)
                                prev.EndTime.TotalMilliseconds++;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(target, fixAction, oldPrevious, prev.ToString());
                        }
                    }
                    else if (diff > 0 && currentOptimalDisplayTime <= p.Duration.TotalMilliseconds - diffHalf &&
                             prevOptimalDisplayTime <= prev.Duration.TotalMilliseconds - diffHalf)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds -= diffHalf;
                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (currentOptimalDisplayTime <= p.EndTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            if (canBeEqual)
                                p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (diff > 0 && currentWantedDisplayTime <= p.Duration.TotalMilliseconds - diffHalf &&
                             prevWantedDisplayTime <= prev.Duration.TotalMilliseconds - diffHalf)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds -= diffHalf;
                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (prevWantedDisplayTime <= (p.StartTime.TotalMilliseconds - prev.StartTime.TotalMilliseconds))
                    {
                        if (callbacks.AllowFix(target, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds - 1;
                            if (canBeEqual)
                                prev.EndTime.TotalMilliseconds++;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(target, fixAction, oldPrevious, prev.ToString());
                        }
                    }
                    else if (currentWantedDisplayTime <= p.EndTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            if (canBeEqual)
                                p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (Math.Abs(p.StartTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds) < 10 && p.Duration.TotalMilliseconds > 1)
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            prev.EndTime.TotalMilliseconds -= 2;
                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            if (canBeEqual)
                                p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(p, fixAction, oldCurrent, p.ToString());
                        }
                    }
                    else if (Math.Abs(p.StartTime.TotalMilliseconds - prev.StartTime.TotalMilliseconds) < 10 && Math.Abs(p.EndTime.TotalMilliseconds - prev.EndTime.TotalMilliseconds) < 10)
                    { // merge lines with same time codes
                        if (callbacks.AllowFix(target, fixAction))
                        {
                            prev.Text = prev.Text.Replace(Environment.NewLine, " ");
                            p.Text = p.Text.Replace(Environment.NewLine, " ");

                            string stripped = HtmlUtil.RemoveHtmlTags(prev.Text).TrimStart();
                            if (!stripped.StartsWith("- ", StringComparison.Ordinal))
                                prev.Text = "- " + prev.Text.TrimStart();

                            stripped = HtmlUtil.RemoveHtmlTags(p.Text).TrimStart();
                            if (!stripped.StartsWith("- ", StringComparison.Ordinal))
                                p.Text = "- " + p.Text.TrimStart();

                            prev.Text = prev.Text.Trim() + Environment.NewLine + p.Text;
                            p.Text = string.Empty;
                            noOfOverlappingDisplayTimesFixed++;
                            callbacks.AddFixToListView(target, fixAction, oldCurrent, p.ToString());

                            p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds + 1;
                            p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds + 1;
                            if (canBeEqual)
                            {
                                p.StartTime.TotalMilliseconds = prev.EndTime.TotalMilliseconds;
                                p.EndTime.TotalMilliseconds = p.StartTime.TotalMilliseconds;
                            }
                        }
                    }
                    else
                    {
                        if (callbacks.AllowFix(p, fixAction))
                        {
                            callbacks.LogStatus(language.FixOverlappingDisplayTimes, string.Format(language.UnableToFixTextXY, i + 1, Environment.NewLine + prev.Number + "  " + prev + Environment.NewLine + p.Number + "  " + p), true);
                            callbacks.AddToTotalErrors(1);
                        }
                    }
                }
            }

            callbacks.UpdateFixStatus(noOfOverlappingDisplayTimesFixed, fixAction, string.Format(language.XOverlappingTimestampsFixed, noOfOverlappingDisplayTimesFixed));
        }