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]);
        }
        /// <summary>
        /// Shows the schema.
        /// </summary>
        private void ShowSchema()
        {
            string fileText = string.Empty;
            string databaseText = string.Empty;

            if (this.fileSide != null)
            {
                fileText = this.GetFile(this.fileSide);
            }

            if (this.databaseSide != null)
            {
                databaseText = this.GetDBSchema(this.databaseSide);
            }

            if (this.checkBoxDiff.Active)
            {
                StyleTextLineMarker addMarker = new StyleTextLineMarker()
                {
                    BackgroundColor = new Cairo.Color(0.8, 0.8, 1)
                };

                StyleTextLineMarker deleteMarker = new StyleTextLineMarker()
                {
                    BackgroundColor = new Cairo.Color(1, 0.8, 0.8)
                };

                StyleTextLineMarker modifyMarker = new StyleTextLineMarker()
                {
                    BackgroundColor = new Cairo.Color(1, 1, 0.6)
                };

                StyleTextLineMarker grayMarker = new StyleTextLineMarker()
                {
                    BackgroundColor = new Cairo.Color(0.6, 0.6, 0.6)
                };

                DiffResult result = new DiffPlex.Differ().CreateLineDiffs(databaseText, fileText, false);

                Dictionary<int, TextLineMarker> databaseMarker = new Dictionary<int, TextLineMarker>();
                Dictionary<int, TextLineMarker> fileMarker = new Dictionary<int, TextLineMarker>();

                string[] fileTextArray = fileText.Split('\n');
                string[] databaseTextArray = databaseText.Split('\n');

                List<string> processedFile = new List<string>();
                List<string> processedDatabase = new List<string>();

                int i1 = 0; // original database line number, start from 0
                int i2 = 0; // original file line number, start from 0
                int d1 = -1;
                int d2 = -1;

                DiffBlock currentBlock = new DiffBlock(-1, 0, -1, 0);
                if (result.DiffBlocks.Count > 0)
                {
                    currentBlock = result.DiffBlocks[0];
                    result.DiffBlocks.RemoveAt(0);
                }

                for (int i = 0; true; i++)
                {
                    bool change = false;

                    if (i1 == currentBlock.DeleteStartA)
                    {
                        d1 = 0;
                    }

                    if (d1 != -1)
                    {
                        change = true;
                        if (d1 < currentBlock.DeleteCountA)
                        {
                            processedDatabase.Add(databaseTextArray[i1]);
                            databaseMarker.Add(i + 1, deleteMarker);

                            processedFile.Add(string.Empty);
                            fileMarker.Add(i + 1, deleteMarker);

                            i1++;
                            d1++;
                        }
                        else
                        {
                            d1 = -1;
                        }
                    }

                    if (i2 == currentBlock.InsertStartB)
                    {
                        d2 = 0;
                    }

                    if (d2 != -1)
                    {
                        change = true;
                        if (d2 < currentBlock.InsertCountB)
                        {
                            processedDatabase.Add(string.Empty);
                            if (databaseMarker.ContainsKey(i + 1))
                            {
                                databaseMarker[i + 1] = modifyMarker;
                            }
                            else
                            {
                                databaseMarker.Add(i + 1, addMarker);
                            }

                            processedFile.Add(fileTextArray[i2]);

                            if (fileMarker.ContainsKey(i + 1))
                            {
                                fileMarker[i + 1] = modifyMarker;
                            }
                            else
                            {
                                fileMarker.Add(i + 1, addMarker);
                            }

                            i2++;
                            d2++;
                        }
                        else
                        {
                            d2 = -1;
                        }
                    }

                    // Stop the iteration if we are on the last line now
                    if (i1 >= databaseTextArray.Length && i2 >= fileTextArray.Length)
                    {
                        break;
                    }

                    if (d1 == -1 && d2 == -1 && change)
                    {
                        if (result.DiffBlocks.Count > 0)
                        {
                            currentBlock = result.DiffBlocks[0];
                            result.DiffBlocks.RemoveAt(0);
                        }
                        else
                        {
                            currentBlock = new DiffBlock(-1, 0, -1, 0);
                        }

                        change = false;
                    }

                    // No changes, insert the original text without marker
                    if (!change)
                    {
                        processedDatabase.Add(databaseTextArray[i1]);
                        processedFile.Add(fileTextArray[i2]);

                        i1++;
                        i2++;
                    }
                }

                this.docDB.Text = string.Join("\n", processedDatabase.ToArray());
                this.docLocal.Text = string.Join("\n", processedFile.ToArray());

                foreach (KeyValuePair<int, TextLineMarker> single in databaseMarker)
                {
                    this.docDB.AddMarker(single.Key, single.Value);
                }

                foreach (KeyValuePair<int, TextLineMarker> single in fileMarker)
                {
                    this.docLocal.AddMarker(single.Key, single.Value);
                }

                this.docDB.CommitUpdateAll();
            }
            else
            {
                this.docDB.Text = databaseText;
                this.docLocal.Text = fileText;
            }
        }