// Shows the difference between ao and bo in the text box.
 private void DisplayArrayDiff(RichTextBox rtb, IFormatter f, object ao, object bo, DiffOperation dop,
                               int indent, string path)
 {
     CheckLineNumber(rtb, path);
     if (dop is RemoveOperation)
     {
         RemovedText(rtb, f.ArrayItem(ao, indent));
     }
     else if (dop is ChangeOperation)
     {
         ChangedText(rtb, f.ArrayItem(ao, indent), f.ArrayItem(bo, indent));
     }
     else if (dop is ChangeObjectOperation)
     {
         SameText(rtb, f.ObjectStart(indent));
         DisplayDiff(rtb, f, ao as Hashtable, bo as Hashtable, (dop as ChangeObjectOperation).Diff, indent + 1, path);
         SameText(rtb, f.ObjectEnd(indent));
     }
     else if (dop is ChangePositionArrayOperation)
     {
         SameText(rtb, f.ArrayStart(indent));
         DisplayDiff(rtb, f, ao as ArrayList, bo as ArrayList, (dop as ChangePositionArrayOperation).Diff, indent + 1, path);
         SameText(rtb, f.ArrayEnd(indent));
     }
     else if (dop is ChangeIdArrayOperation)
     {
         SameText(rtb, f.ArrayStart(indent));
         DisplayDiff(rtb, f, ao as ArrayList, bo as ArrayList, (dop as ChangeIdArrayOperation).Diff, indent + 1, path);
         SameText(rtb, f.ArrayEnd(indent));
     }
     else
     {
         SameText(rtb, f.ArrayItem(ao, indent));
     }
 }
        // Shows the difference between a and b in the text box.
        private void DisplayDiff(RichTextBox rtb, IFormatter f, Hashtable a, Hashtable b, HashDiff diff,
                                 int indent, string path)
        {
            HashSet <string> keys = new HashSet <string>();

            foreach (string key in a.Keys)
            {
                keys.Add(key);
            }
            foreach (string key in b.Keys)
            {
                keys.Add(key);
            }

            foreach (string key in keys.OrderBy(i => i))
            {
                string subpath = path + "." + key;
                CheckLineNumber(rtb, subpath);

                if (diff.Operations.ContainsKey(key))
                {
                    DiffOperation dop = diff.Operations[key];
                    if (dop is RemoveOperation)
                    {
                        RemovedText(rtb, f.ObjectField(a, key, indent));
                    }
                    else if (dop is ChangeOperation)
                    {
                        ChangedText(rtb, f.ObjectField(a, key, indent), f.ObjectField(b, key, indent));
                    }
                    else if (dop is ChangeObjectOperation)
                    {
                        SameText(rtb, f.ObjectStart(key, indent));
                        DisplayDiff(rtb, f, a[key] as Hashtable, b[key] as Hashtable, (dop as ChangeObjectOperation).Diff, indent + 1, subpath);
                        SameText(rtb, f.ObjectEnd(indent));
                    }
                    else if (dop is ChangePositionArrayOperation)
                    {
                        SameText(rtb, f.ArrayStart(key, indent));
                        DisplayDiff(rtb, f, a[key] as ArrayList, b[key] as ArrayList, (dop as ChangePositionArrayOperation).Diff, indent + 1, subpath);
                        SameText(rtb, f.ArrayEnd(indent));
                    }
                    else if (dop is ChangeIdArrayOperation)
                    {
                        SameText(rtb, f.ArrayStart(key, indent));
                        DisplayDiff(rtb, f, a[key] as ArrayList, b[key] as ArrayList, (dop as ChangeIdArrayOperation).Diff, indent + 1, subpath);
                        SameText(rtb, f.ArrayEnd(indent));
                    }
                }
                else
                {
                    SameText(rtb, f.ObjectField(b, key, indent));
                }
            }
        }
        // Shows the difference between two hash tables.
        private void DisplayDiff(Hashtable a, Hashtable b, HashDiff diff, int indent)
        {
            HashSet <string> keys = new HashSet <string>();

            foreach (string key in a.Keys)
            {
                keys.Add(key);
            }
            foreach (string key in b.Keys)
            {
                keys.Add(key);
            }

            foreach (string key in keys.OrderBy(i => i))
            {
                if (diff.Operations.ContainsKey(key))
                {
                    DiffOperation dop = diff.Operations[key];
                    if (dop is RemoveOperation)
                    {
                        RemovedText(_af.ObjectField(a, key, indent), "");
                    }
                    else if (dop is ChangeOperation)
                    {
                        ChangedText(_af.ObjectField(a, key, indent), _bf.ObjectField(b, key, indent));
                    }
                    else if (dop is ChangeObjectOperation)
                    {
                        SameText(_af.ObjectStart(key, indent), _bf.ObjectStart(key, indent));
                        DisplayDiff(a[key] as Hashtable, b[key] as Hashtable, (dop as ChangeObjectOperation).Diff, indent + 1);
                        SameText(_af.ObjectEnd(indent), _bf.ObjectEnd(indent));
                    }
                    else if (dop is ChangePositionArrayOperation)
                    {
                        SameText(_af.ArrayStart(key, indent), _bf.ArrayStart(key, indent));
                        DisplayDiff(a[key] as ArrayList, b[key] as ArrayList, (dop as ChangePositionArrayOperation).Diff, indent + 1);
                        SameText(_af.ArrayEnd(indent), _bf.ArrayEnd(indent));
                    }
                    else if (dop is ChangeIdArrayOperation)
                    {
                        SameText(_af.ArrayStart(key, indent), _bf.ArrayStart(key, indent));
                        DisplayDiff(a[key] as ArrayList, b[key] as ArrayList, (dop as ChangeIdArrayOperation).Diff, indent + 1);
                        SameText(_af.ArrayEnd(indent), _bf.ArrayEnd(indent));
                    }
                }
                else
                {
                    SameText(_af.ObjectField(a, key, indent), _bf.ObjectField(a, key, indent));
                }
            }
        }