private void UnPackDiffedLine(HtmlTableRowGroup rowGroup, List<string> leftLines, List<string> rightLines)
        {
            if (leftLines.Count < rowGroup.Lines.Count || rightLines.Count < rowGroup.Lines.Count)
            {
                Log.Error("Interline Diff error: line count mismatch: {0} != {1}", leftLines.Count, rightLines.Count);
                return;
            }

            for (var idx = 0; idx < rowGroup.Lines.Count; idx++)
            {
                var line = rowGroup.Lines[idx];

                var value = leftLines[idx];
                if (value != line.Left.LineText && line.Left.LineText != null)
                {
                    var newLine = new Line { Id = line.Left.Id, LineNum = line.Left.LineNum, LineText = value };
                    line.Left = newLine;
                }

                value = rightLines[idx];
                if (value != line.Right.LineText && line.Right.LineText != null)
                {
                    var newLine = new Line { Id = line.Right.Id, LineNum = line.Right.LineNum, LineText = value };
                    line.Right = newLine;
                }
            }
        }
        private void InterlineDiff(HtmlTableRowGroup rowGroup, bool ignoreWhiteSpaces)
        {
            var baseLineInfo = new LineDiffInfo(rowGroup);
            var diffLineInfo = new LineDiffInfo(rowGroup, baseLineInfo);
            InterlineDiff(baseLineInfo, diffLineInfo, ignoreWhiteSpaces);

            UnPackDiffedLine(rowGroup, baseLineInfo.Lines, diffLineInfo.Lines);

            baseLineInfo.Dispose();
            diffLineInfo.Dispose();
        }
        private void AddSeperators(HtmlTableRowGroup rowGroup,
            HtmlTable left,
            HtmlTable right,
            HtmlTable edge)
        {
            // Unchanged seperator
            left.AddBody("Seperator Base");
            right.AddBody("Seperator Diff");
            edge.AddBody("Seperator Diff");

            var startLine = rowGroup.Lines.Count > 0 ? rowGroup.Lines.First() : GetEmptyLine();
            var endLine = rowGroup.Lines.Count > 0 ? rowGroup.Lines.Last() : GetEmptyLine();

            left.AddBodySeperator(startLine.Left.LineNum, startLine.Left.Id, string.Format("Lines {0} to {1}", startLine.Left.LineNumber, endLine.Left.LineNumber));
            right.AddBodySeperator(startLine.Right.LineNum, startLine.Right.Id, string.Format("Lines {0} to {1}", startLine.Right.LineNumber, endLine.Right.LineNumber));
            edge.AddEdgeSeperator(startLine.Right.LineNum, startLine.Right.Id);

            left.EndBody();
            right.EndBody();
            edge.EndBody();
        }
        /// <summary>
        ///     Generates the diff view for two file revisions.
        /// </summary>
        private string GenerateFileDiffView(
            int baseRevision, int diffRevision, UserSettingsDto settings,
            StreamCombiner baseFile, int baseId, string baseHeader,
            StreamCombiner diffFile, int diffId, string diffHeader,
            StreamCombiner rawDiff, string fileName, string outputFile)
        {
            var baseEncoder = GetEncoderForFile(fileName);
            var diffEncoder = GetEncoderForFile(fileName);

            var baseFileInfo = new DiffFileInfo(baseFile, baseEncoder, baseId, BaseOrDiff.Base);
            var diffFileInfo = new DiffFileInfo(diffFile, diffEncoder, diffId, BaseOrDiff.Diff);

            // Line Stamp format
            var baseScriptIdPrefix = "Base-" + EncodeLinePrefix(baseRevision, diffRevision, baseId, diffId, baseId);
            var diffScriptIdPrefix = "Diff-" + EncodeLinePrefix(baseRevision, diffRevision, baseId, diffId, diffId);
            var edgePrefix = "Edge-" + EncodeLinePrefix(baseRevision, diffRevision, baseId, diffId, diffId);
            var rowGroups = new List<HtmlTableRowGroup>();
            var lastBaseLine = "1";
            var lastDiffLine = "1";

            foreach (var diffItem in DiffItem.EnumerateDifferences(rawDiff))
            {
                var atEnd = diffItem.BaseLineCount == int.MaxValue;

                var baseLines = new List<Line>();
                for (var i = 0; i < diffItem.BaseLineCount && baseFileInfo.MoveNextLine(); ++i)
                    baseLines.Add(new Line
                        {
                            LineNum = baseFileInfo.CurLineNum.ToString(CultureInfo.InvariantCulture),
                            LineText = baseFileInfo.CurLine
                        });

                var diffLines = new List<Line>();
                for (var i = 0; i < diffItem.DiffLineCount && diffFileInfo.MoveNextLine(); ++i)
                    diffLines.Add(new Line
                        {
                            LineNum = diffFileInfo.CurLineNum.ToString(CultureInfo.InvariantCulture),
                            LineText = diffFileInfo.CurLine
                        });

                var baseLinesLength = baseLines.Count();
                var diffLinesLength = diffLines.Count();

                // The end is the only case where the DiffInfo line counts may be incorrect. If there are in fact
                // zero lines then just continue, which should cause the foreach block to end and we'll continue
                // like the DiffItem never existed.
                if (atEnd && diffItem.DiffType == DiffType.Unchanged && baseLinesLength == 0 && diffLinesLength == 0)
                    continue;

                var rowGroup = new HtmlTableRowGroup(diffItem.DiffType);

                for (var i = 0; i < Math.Max(baseLinesLength, diffLinesLength); ++i)
                {
                    var line = new HtmlTableLine();
                    if (i < baseLinesLength)
                    {
                        line.Left = baseLines[i];
                        line.Left.LineText = baseFileInfo.Encoder.EncodeLine(baseLines[i].LineText, int.MaxValue,
                                                                             TabValue);
                        lastBaseLine = line.Left.LineNum;
                    }
                    else
                    {
                        // new diff code - add entry for empty line with old line #
                        var idx = i - baseLinesLength;
                        line.Left = new Line { Id = lastBaseLine + '_' + idx };
                    }

                    if (i < diffLinesLength)
                    {
                        line.Right = diffLines[i];
                        line.Right.LineText = diffFileInfo.Encoder.EncodeLine(diffLines[i].LineText, int.MaxValue,
                                                                             TabValue);
                        lastDiffLine = line.Right.LineNum;
                    }
                    else
                    {
                        // new diff code - add entry for empty line with old line #
                        var idx = i - diffLinesLength;
                        line.Right = new Line { Id = lastDiffLine + '_' + idx };
                    }

                    rowGroup.Lines.Add(line);
                }

                if (diffItem.DiffType == DiffType.Changed)
                {
                    if (settings.diff.intraLineDiff)
                        InterlineDiff(rowGroup, settings.diff.ignoreWhiteSpace);
                }

                rowGroups.Add(rowGroup);
            }

            baseEncoder.Dispose();
            diffEncoder.Dispose();

            var htmlLines = EncodeRowGroups(rowGroups, baseHeader, diffHeader, baseScriptIdPrefix, diffScriptIdPrefix,
                                       edgePrefix);
            if (!string.IsNullOrWhiteSpace(outputFile))
            {
                var folder = Path.GetDirectoryName(outputFile);
                Directory.CreateDirectory(folder);
                File.WriteAllLines(outputFile, htmlLines);
                Log.Info("Generated {0}", outputFile);
                return outputFile;
            }
            else
            {
                return string.Join(Environment.NewLine, htmlLines);
            }
        }
            public LineDiffInfo(HtmlTableRowGroup rowGroup, LineDiffInfo baseInfo = null)
            {
                BaseInfo = baseInfo ?? this;
                BaseMode = baseInfo == null;

                var charsList = new List<string>();
                foreach (var item in rowGroup.Lines)
                {
                    var line = BaseMode ? item.Left.Code : item.Right.Code;
                    line = line ?? "";
                    var lineEscapes = UnEncodeLine(ref line);
                    Escapes.Add(lineEscapes);
                    Chars += line;

                    var chars = line.ToCharArray();
                    charsList.AddRange(chars.Select(ch => ch.ToString(CultureInfo.InvariantCulture)));

                    LinePositions.Add(line.Length);
                }
                Length = Chars.Length;

                File.WriteAllLines(TempFileName, charsList);
            }