/// <summary> /// Creates a patch from the PatchMessage sent by the client. /// Then applies the patch to the ShadowCopy followed by applying the patch to the live server copy. /// Then creates new diffs from the live server text and the shadow (which contains the exact copy of latest client message). /// These diffs will then be send to the client so that the client now has the latest updates. /// </summary> /// <param name="message"></param> private void HandlePatchMessage(PatchMessage message) { _edits.Clear(); Edit edit = message.Edits.Pop(); Task.Factory.StartNew(() => { if (edit.ClientVersion > User.Document.ShadowCopy.ClientVersion || edit.ClientVersion == 0) { // Update Server Shadow bool success; List <Patch> patches; try { patches = _dmp.patch_make(User.Document.ShadowCopy.ShadowText, edit.Diffs); User.Document.ShadowCopy.ShadowText = _dmp.patch_apply(patches, User.Document.ShadowCopy.ShadowText)[0].ToString(); //User.Document.ShadowCopy.ClientVersion++; User.Document.BackupShadowCopy.BackupText = User.Document.ShadowCopy.ShadowText; success = true; } catch (ArgumentOutOfRangeException e) { Console.WriteLine(e); success = false; Session.BroadCastOutOfSyncResponse(Session.Document.CurrentText); } if (success) { // Update Server Current patches = _dmp.patch_make(Session.Document.CurrentText, edit.Diffs); Session.Document.CurrentText = _dmp.patch_apply(patches, Session.Document.CurrentText)[0].ToString(); Console.WriteLine( $"Updated client: {User.Username}, With test: {Session.Document.CurrentText}"); } } }).ContinueWith((result) => { List <Diff> diffs = _dmp.diff_main(User.Document.ShadowCopy.ShadowText, Session.Document.CurrentText, false); _dmp.diff_cleanupEfficiency(diffs); _edits.Push(new Edit(diffs, User.Document.ShadowCopy.ClientVersion, User.Document.ShadowCopy.ServerVersion)); SendMessage(new PatchMessage("Server", _edits)); User.Document.ShadowCopy.ShadowText = Session.Document.CurrentText; _edits.Clear(); }); }
private static string GetPrettyHtmlDiff(string text1, string text2) { if (text1 == null) { text1 = ""; } if (text2 == null) { text2 = ""; } var diffs = Dmp.diff_main(text1, text2); Dmp.diff_cleanupSemantic(diffs); return(Dmp.diff_prettyHtml(diffs)); }
private void PopulateObjectDefinitions(string objDefSource, string objDefTarget, ComparisonObjectType objType, ComparisonObjectStatus objStatus) { try { IterateJson(txtSourceObjectDefinition, objDefSource); IterateJson(txtTargetObjectDefinition, objDefTarget); } catch (Exception) { txtSourceObjectDefinition.Text = ""; txtSourceObjectDefinition.Text = objDefSource; txtTargetObjectDefinition.Text = ""; txtTargetObjectDefinition.Text = objDefTarget; } #region Difference Highlighting if (objStatus == ComparisonObjectStatus.DifferentDefinitions || (objStatus == ComparisonObjectStatus.SameDefinition && objType == ComparisonObjectType.Perspective && _comparisonInfo.OptionsInfo.OptionMergePerspectives) || (objStatus == ComparisonObjectStatus.SameDefinition && objType == ComparisonObjectType.Culture && _comparisonInfo.OptionsInfo.OptionMergeCultures) ) { _diffs = _diff.diff_main(objDefSource, objDefTarget); _diff.diff_cleanupSemantic(_diffs); //_diff.diff_cleanupSemanticLossless(_diffs); //_diff.diff_cleanupEfficiency(_diffs); // NG: Evaluate if this needs to be added //Are we merging perspectives/cultures? if ((objType == ComparisonObjectType.Perspective && _comparisonInfo.OptionsInfo.OptionMergePerspectives) || (objType == ComparisonObjectType.Culture && _comparisonInfo.OptionsInfo.OptionMergeCultures) ) { _chunklistSource = CollectChunks(source: true, backColors: _backColorsMerge); _chunklistTarget = CollectChunks(source: false, backColors: _backColorsMerge); //If same definition with merge perspectives/cultures option, just want to highlight differences in target that will not be applied, so do not paint chunks for source if (objStatus == ComparisonObjectStatus.DifferentDefinitions) { PaintChunks(txtSourceObjectDefinition, _chunklistSource); } PaintChunks(txtTargetObjectDefinition, _chunklistTarget); } else { _chunklistSource = CollectChunks(source: true, backColors: _backColors); _chunklistTarget = CollectChunks(source: false, backColors: _backColors); PaintChunks(txtSourceObjectDefinition, _chunklistSource); PaintChunks(txtTargetObjectDefinition, _chunklistTarget); } } #endregion //select 1st characters so not scrolled at bottom if (txtSourceObjectDefinition.Text != "") { txtSourceObjectDefinition.SelectionStart = 0; txtSourceObjectDefinition.SelectionLength = 0; txtSourceObjectDefinition.ScrollToCaret(); } if (txtTargetObjectDefinition.Text != "") { txtTargetObjectDefinition.SelectionStart = 0; txtTargetObjectDefinition.SelectionLength = 0; txtTargetObjectDefinition.ScrollToCaret(); } }
/// <summary> /// An array of differences is computed which describe the transformation of text1 into text2. /// Each difference is an array of Diff objects. The first element specifies if it is an insertion (1), /// a deletion (-1) or an equality (0). The second element specifies the affected text. /// </summary> public void Diff(string text1, string text2) { DiffMatchPatch diffMatchPatch = CreateDiffMatchPatch(); diffs = diffMatchPatch.diff_main(text1, text2); }