public MergeEditor(LineBlock yourBlock, LineBlock updatedBlock, LineBlock originalBlock, LineBlock editBlock = null) { InitializeComponent(); Style = (Style)FindResource(typeof(Window)); RenderLineBlock(yourBlock, yourText); myStr = yourBlock.ToString(); RenderLineBlock(updatedBlock, updatedText); updatedStr = updatedBlock.ToString(); originalStr = originalBlock.ToString(); if (editBlock != null) { mergedText.Text = editBlock.ToString(); } }
private void RenderLineBlock(LineBlock lineBlock, RichTextBox r) { r.Document.Blocks.Clear(); foreach (Line line in lineBlock.lines) { var p = new Paragraph(); foreach (Block block in line.blocks) { string text = block.text; if (text.EndsWith(SentenceFilter.SentenceDelim)) { text = text.Substring(0, text.Length - SentenceFilter.SentenceDelim.Length); } p.Inlines.Add(new Run(text) { Style = GetStyle("text" + block.type) }); } r.Document.Blocks.Add(p); } }
public void Append(LineBlock lb) { foreach (Line line in lb.lines) { lines.Add(line); } }
private void ProcessDiff(string original, string myVersion, string newVersion) { // Do a line-by-line diff, marking changed line groups. // Also, find intersecting diffs and mark them as conflicted changes for resolution. var d = new Differ(); var diffs = new DiffResult[2] { d.CreateLineDiffs(original, myVersion ?? "", false), d.CreateLineDiffs(original, newVersion ?? "", false) }; string[][] newPieces = new string[2][]; newPieces[0] = diffs[0].PiecesNew; newPieces[1] = diffs[1].PiecesNew; if (myVersion == "") newPieces[0] = new string[] { "" }; if (newVersion == "") newPieces[1] = new string[] { "" }; var dblocks = new List<Tuple<DiffBlock, int>>(); for (int side = 0; side < 2; side++) { foreach (var block in diffs[side].DiffBlocks) { DiffBlock actualBlock = block; if (diffs[side].PiecesNew.Length == 0 && block.InsertCountB == 0 && block.InsertStartB == 0) { actualBlock = new DiffBlock(block.DeleteStartA, block.DeleteCountA, 0, 1); } dblocks.Add(new Tuple<DiffBlock, int>(actualBlock, side)); } } dblocks.Sort((a, b) => a.Item1.DeleteStartA.CompareTo(b.Item1.DeleteStartA)); content = new List<LineBlock>[2]; for (int i = 0; i < 2; i++) { content[i] = new List<LineBlock>(); } conflictOrigBlocks = new List<LineBlock>(); string[] origLines = diffs[0].PiecesOld; int nextOriginalLine = 0; for (int i = 0; i < dblocks.Count; ) { DiffBlock block = dblocks[i].Item1; int owner = dblocks[i].Item2; // Add unchanged (original) lines. if (block.DeleteStartA > nextOriginalLine) { foreach (var lineBlocks in content) { lineBlocks.Add(new LineBlock(Util.ArraySlice(origLines, nextOriginalLine, block.DeleteStartA - nextOriginalLine))); } nextOriginalLine = block.DeleteStartA; } int rangeStart = block.DeleteStartA; int rangeEnd = rangeStart + block.DeleteCountA; int j = i; // If this change intersects any other changes, then merge them together to form a block. while (j < dblocks.Count && dblocks[j].Item1.DeleteStartA <= rangeEnd) { rangeEnd = Math.Max(rangeEnd, dblocks[j].Item1.DeleteStartA + dblocks[j].Item1.DeleteCountA); j++; } if (j == i + 1) { // A regular change. var oldBlock = new LineBlock(Util.ArraySlice(diffs[owner].PiecesOld, block.DeleteStartA, block.DeleteCountA), BlockType.ChangeDelete); var newBlock = new LineBlock(Util.ArraySlice(newPieces[owner], block.InsertStartB, block.InsertCountB), BlockType.ChangeAdd); if (block.DeleteCountA != 0 && block.InsertCountB != 0) { oldBlock.type = BlockType.Conflict; newBlock.type = BlockType.Conflict; } else if (block.DeleteCountA == 0) { oldBlock.type = BlockType.Blank; } else if (block.InsertCountB == 0) { newBlock.type = BlockType.Blank; } // can't both be empty! ProcessBlockDiff(oldBlock, newBlock); content[owner].Add(newBlock); content[1 - owner].Add(oldBlock); conflictOrigBlocks.Add(owner == 0 ? newBlock : oldBlock); } else { // Create a change block. for (int side = 0; side < 2; side++) { int curOriginalLine = rangeStart; var conflictBlock = new LineBlock(); var origBlock = new LineBlock(); conflictBlock.type = BlockType.Conflict; for (int k = i; k < j; k++) { DiffBlock subBlock = dblocks[k].Item1; if (dblocks[k].Item2 != side) continue; if (subBlock.DeleteStartA > curOriginalLine) { conflictBlock.AddLines(Util.ArraySlice(origLines, curOriginalLine, subBlock.DeleteStartA - curOriginalLine)); } curOriginalLine = subBlock.DeleteStartA + subBlock.DeleteCountA; var oldBlock = new LineBlock(Util.ArraySlice(diffs[side].PiecesOld, subBlock.DeleteStartA, subBlock.DeleteCountA), BlockType.ChangeDelete); var newBlock = new LineBlock(Util.ArraySlice(newPieces[side], subBlock.InsertStartB, subBlock.InsertCountB), BlockType.ChangeAdd); ProcessBlockDiff(oldBlock, newBlock, false); origBlock.Append(oldBlock); conflictBlock.Append(newBlock); } if (rangeEnd > curOriginalLine) { conflictBlock.AddLines(Util.ArraySlice(origLines, curOriginalLine, rangeEnd - curOriginalLine)); } if (conflictBlock.lines.Count == 0) { conflictBlock.type = BlockType.ChangeDelete; } content[side].Add(conflictBlock); if (side == 0) { conflictOrigBlocks.Add(origBlock); } } int last = content[0].Count - 1; if (content[0][last].ToString() == content[1][last].ToString()) { // Not actually a conflict if they're both the same change. if (content[0][last].lines.Count == 0) { // If both are deleted, just show nothing. content[0].RemoveAt(last); content[1].RemoveAt(last); } else { // Make them normal blocks. content[0][last] = new LineBlock(content[0][last].lines.Select(x => x.ToString()).ToArray()); content[1][last] = new LineBlock(content[1][last].lines.Select(x => x.ToString()).ToArray()); } conflictOrigBlocks.RemoveAt(conflictOrigBlocks.Count - 1); } } nextOriginalLine = rangeEnd; i = j; } // Add any remaining unchanged lines. if (origLines.Length > nextOriginalLine) { foreach (var lineBlocks in content) { lineBlocks.Add(new LineBlock(Util.ArraySlice(origLines, nextOriginalLine, origLines.Length - nextOriginalLine))); } } origBlocks = new LineBlock[2][]; origBlocks[0] = new LineBlock[content[0].Count]; origBlocks[1] = new LineBlock[content[1].Count]; content[0].CopyTo(origBlocks[0]); content[1].CopyTo(origBlocks[1]); }
private void ProcessBlockDiff(LineBlock oldLineBlock, LineBlock newLineBlock, bool modifyOld = true) { // Do block-by-block diffs inside LineBlocks. var oldBlocks = new List<Block>(); var newBlocks = new List<Block>(); foreach (var line in oldLineBlock.lines) { oldBlocks.AddRange(line.blocks); } foreach (var line in newLineBlock.lines) { newBlocks.AddRange(line.blocks); } var d = new Differ(); DiffResult diff = d.CreateLineDiffs(String.Join("\n", oldBlocks.Select(x => x.ToString()).ToArray()), String.Join("\n", newBlocks.Select(x => x.ToString()).ToArray()), false); foreach (DiffBlock dblock in diff.DiffBlocks) { if (modifyOld) { for (int i = 0; i < dblock.DeleteCountA && dblock.DeleteStartA + i < oldBlocks.Count; i++) { oldBlocks[i + dblock.DeleteStartA].type = BlockType.ChangeDelete; } } for (int i = 0; i < dblock.InsertCountB && dblock.InsertStartB + i < newBlocks.Count; i++) { newBlocks[i + dblock.InsertStartB].type = BlockType.ChangeAdd; } } }
private void ClickSave(object sender, RoutedEventArgs e) { string text = mergedText.Text; newBlock = new LineBlock(SentenceFilter.SplitLines(text), BlockType.Edited); Close(); }