diff options
author | Jérémie Laval <jeremie.laval@gmail.com> | 2013-06-26 00:09:19 +0400 |
---|---|---|
committer | Jérémie Laval <jeremie.laval@gmail.com> | 2013-06-26 00:09:32 +0400 |
commit | 812b381989f90b7c15754628b113fe4e4d20bd06 (patch) | |
tree | 835176cdd5a04ffc6739a6429acad109425eee80 | |
parent | 19e095b1103891462343565aff9b187f88bf3947 (diff) |
[docbrowser] Make it compile again with Mono 3.0
-rw-r--r-- | docbrowser/Makefile.am | 3 | ||||
-rw-r--r-- | docbrowser/browser.cs | 74 | ||||
-rw-r--r-- | docbrowser/editing.cs | 519 |
3 files changed, 581 insertions, 15 deletions
diff --git a/docbrowser/Makefile.am b/docbrowser/Makefile.am index a1a26265..065c430f 100644 --- a/docbrowser/Makefile.am +++ b/docbrowser/Makefile.am @@ -40,6 +40,7 @@ browser_sources = \ $(srcdir)/list.cs \ $(srcdir)/elabel.cs \ $(srcdir)/history.cs \ + $(srcdir)/editing.cs \ $(srcdir)/Contributions.cs \ $(srcdir)/XmlNodeWriter.cs \ $(srcdir)/IHtmlRender.cs \ @@ -67,7 +68,7 @@ admin_sources = \ $(srcdir)/admin.cs \ $(srcdir)/Contributions.cs -browser_assemblies = $(GTK_SHARP_LIBS) $(MONODOC_LIBS) $(GNOME_SHARP_LIBS) -r:System.Web.Services +browser_assemblies = $(GTK_SHARP_LIBS) $(MONODOC_LIBS) $(GNOME_SHARP_LIBS) -r:System.Web.Services -r:System.Web # we insert gtkhtml libs if we have them for printing geckorender_assemblies = $(GTK_SHARP_LIBS) $(GTKHTML_SHARP_LIBS) $(GECKO_SHARP_LIBS) $(GNOME_SHARP_LIBS) $(MONODOC_LIBS) -r:browser.exe gtkhtmlrender_assemblies = $(GTK_SHARP_LIBS) $(GTKHTML_SHARP_LIBS) $(GNOME_SHARP_LIBS) $(MONODOC_LIBS) -r:browser.exe diff --git a/docbrowser/browser.cs b/docbrowser/browser.cs index 2984bc78..6f706207 100644 --- a/docbrowser/browser.cs +++ b/docbrowser/browser.cs @@ -60,7 +60,7 @@ class Driver { v => sources.Add (v) }, { "edit=", "Edit mdoc(5) XML documentation found within {PATH}.", - v => RootTree.UncompiledHelpSources.Add (v) }, + v => RootTree.AddUncompiledSource (v) }, { "engine=", "Specify which HTML rendering {ENGINE} to use:\n" + " " + string.Join ("\n ", engines) + "\n" + @@ -132,7 +132,7 @@ class Driver { return r; } - if (mergeConfigFile != null) { + /*if (mergeConfigFile != null) { ArrayList targetDirs = new ArrayList (); for (int i = 0; i < topics.Count; i++) @@ -145,7 +145,7 @@ class Driver { e.Merge (); return 0; - } + }*/ if (r != 0 || !show_gui) return r; @@ -257,6 +257,7 @@ public class Browser { TreeView search_tree; TreeStore search_store; SearchableIndex search_index; + ArrayList searchResults = new ArrayList (20); string highlight_text; [Glade.Widget] VBox search_vbox; ProgressPanel ppanel; @@ -578,6 +579,7 @@ public class Browser { Result r = search_index.Search (term); if (r == null) return; //There was a problem with the index + searchResults.Add (r); //insert the results in the tree TreeIter iter; @@ -622,7 +624,7 @@ public class Browser { return; int i_0 = p.Indices [0]; int i_1 = p.Indices [1]; - Result res = (Result) search_index.Results [i_0]; + Result res = (Result) searchResults [i_0]; TreeIter parent; model.IterParent (out parent, iter); string term = (string) search_store.GetValue (parent, 0); @@ -648,21 +650,21 @@ public class Browser { void TextLarger (object obj, EventArgs args) { SettingsHandler.Settings.preferred_font_size += 10; - HelpSource.CssCode = null; + //HelpSource.CssCode = null; Reload (); SettingsHandler.Save (); } void TextSmaller (object obj, EventArgs args) { SettingsHandler.Settings.preferred_font_size -= 10; - HelpSource.CssCode = null; + //HelpSource.CssCode = null; Reload (); SettingsHandler.Save (); } void TextNormal (object obj, EventArgs args) { SettingsHandler.Settings.preferred_font_size = 100; - HelpSource.CssCode = null; + //HelpSource.CssCode = null; Reload (); SettingsHandler.Save (); } @@ -794,8 +796,8 @@ public class Browser { // string tabTitle; tabTitle = matched_node.Caption; //Normal title - string[] parts = matched_node.URL.Split('/', '#'); - if(matched_node.URL != null && matched_node.URL.StartsWith("ecma:")) { + string[] parts = matched_node.PublicUrl.Split('/', '#'); + if(matched_node.PublicUrl != null && matched_node.PublicUrl.StartsWith("ecma:")) { if(parts.Length == 3 && parts[2] != String.Empty) { //List of Members, properties, events, ... tabTitle = parts[1] + ": " + matched_node.Caption; } else if(parts.Length >= 4) { //Showing a concrete Member, property, ... @@ -1701,7 +1703,7 @@ ExtLoop: void OnOkClicked (object sender, EventArgs a) { - CommentService service = new CommentService(); + //CommentService service = new CommentService(); // todo newcomment.Hide (); } @@ -2020,7 +2022,7 @@ public class TreeBrowser { if (tree_view.Selection.GetSelected (out model, out iter)){ Node n = (Node) iter_to_node [iter]; - string url = n.URL; + string url = n.PublicUrl; Node match; string s; @@ -2048,7 +2050,7 @@ public class TreeBrowser { return; } - ((Browser)browser).Render ("<h1>Unhandled URL</h1>" + "<p>Functionality to view the resource <i>" + n.URL + "</i> is not available on your system or has not yet been implemented.</p>", null, url); + ((Browser)browser).Render ("<h1>Unhandled URL</h1>" + "<p>Functionality to view the resource <i>" + n.PublicUrl + "</i> is not available on your system or has not yet been implemented.</p>", null, url); } } } @@ -2712,7 +2714,7 @@ public class Tab : Notebook { string [] uSplit = EditingUtils.ParseEditUrl (edit_url); if (uSplit[0].StartsWith ("monodoc:")) - EditingUtils.SaveChange (edit_url, browser.help_tree, edit_node, EcmaHelpSource.GetNiceUrl (browser.CurrentTab.CurrentNode)); + EditingUtils.SaveChange (edit_url, browser.help_tree, edit_node, GetNiceUrl (browser.CurrentTab.CurrentNode)); else if (uSplit[0].StartsWith ("file:")) EditingUtils.SaveChange (edit_url, browser.help_tree, edit_node, String.Empty); else @@ -2721,6 +2723,49 @@ public class Tab : Notebook { history.ActivateCurrent (); } + public static string GetNiceUrl (Node node) { + if (node.Element.StartsWith("N:")) + return node.Element; + string name, full; + int bk_pos = node.Caption.IndexOf (' '); + // node from an overview + if (bk_pos != -1) { + name = node.Caption.Substring (0, bk_pos); + full = node.Parent.Caption + "." + name.Replace ('.', '+'); + return "T:" + full; + } + // node that lists constructors, methods, fields, ... + if ((node.Caption == "Constructors") || (node.Caption == "Fields") || (node.Caption == "Events") + || (node.Caption == "Members") || (node.Caption == "Properties") || (node.Caption == "Methods") + || (node.Caption == "Operators")) { + bk_pos = node.Parent.Caption.IndexOf (' '); + name = node.Parent.Caption.Substring (0, bk_pos); + full = node.Parent.Parent.Caption + "." + name.Replace ('.', '+'); + return "T:" + full + "/" + node.Element; + } + int pr_pos = node.Caption.IndexOf ('('); + // node from a constructor + if (node.Parent.Element == "C") { + name = node.Parent.Parent.Parent.Caption; + int idx = node.PublicUrl.IndexOf ('/'); + return node.PublicUrl[idx+1] + ":" + name + "." + node.Caption.Replace ('.', '+'); + // node from a method with one signature, field, property, operator + } else if (pr_pos == -1) { + bk_pos = node.Parent.Parent.Caption.IndexOf (' '); + name = node.Parent.Parent.Caption.Substring (0, bk_pos); + full = node.Parent.Parent.Parent.Caption + "." + name.Replace ('.', '+'); + int idx = node.PublicUrl.IndexOf ('/'); + return node.PublicUrl[idx+1] + ":" + full + "." + node.Caption; + // node from a method with several signatures + } else { + bk_pos = node.Parent.Parent.Parent.Caption.IndexOf (' '); + name = node.Parent.Parent.Parent.Caption.Substring (0, bk_pos); + full = node.Parent.Parent.Parent.Parent.Caption + "." + name.Replace ('.', '+'); + int idx = node.PublicUrl.IndexOf ('/'); + return node.PublicUrl[idx+1] + ":" + full + "." + node.Caption; + } + } + void OnCancelEdits (object sender, EventArgs a) { SetMode (Mode.Viewer); @@ -2747,6 +2792,7 @@ public class Tab : Notebook { StringWriter sw = new StringWriter (); XmlWriter w = new XmlTextWriter (sw); + var converter = new Monodoc.Generators.Html.Ecma2Html (); try { edit_node.InnerXml = text_editor.Buffer.Text; @@ -2760,7 +2806,7 @@ public class Tab : Notebook { } browser.statusbar.Pop (browser.context_id); browser.statusbar.Push (browser.context_id, "XML OK"); - string s = HelpSource.BuildHtml (EcmaHelpSource.css_ecma_code, sw.ToString ()); + string s = converter.Export (sw.ToString (), new Dictionary<string, string> ()); html_preview.Render(s); return false; diff --git a/docbrowser/editing.cs b/docbrowser/editing.cs new file mode 100644 index 00000000..d7c1e327 --- /dev/null +++ b/docbrowser/editing.cs @@ -0,0 +1,519 @@ +// +// editing.cs +// +// Author: +// Ben Maurer (bmaurer@users.sourceforge.net) +// +// (C) 2003 Ben Maurer +// + +using System; +using System.Collections; +using System.Collections.Specialized; +using System.IO; +using System.Text; +using System.Xml; +using System.Xml.Serialization; +using System.Xml.XPath; +using System.Web; + +namespace Monodoc { + public class EditingUtils { + + public static string FormatEditUri (string document_identifier, string xpath) + { + return String.Format ("edit:{0}@{1}", HttpUtility.UrlEncode (document_identifier), + HttpUtility.UrlEncode (xpath)); + } + + public static string GetXPath (XPathNavigator n) + { + switch (n.NodeType) { + case XPathNodeType.Root: return "/"; + case XPathNodeType.Attribute: { + string ret = "@" + n.Name; + n.MoveToParent (); + string s = GetXPath (n); + return s + (s == "/" ? "" : "/") + ret; + } + + case XPathNodeType.Element: { + string ret = n.Name; + int i = 1; + while (n.MoveToPrevious ()) { + if (n.NodeType == XPathNodeType.Element && n.Name == ret) + i++; + } + ret += "[" + i + "]"; + if (n.MoveToParent ()) { + string s = GetXPath (n); + return s + (s == "/" ? "" : "/") + ret; + } + } + break; + } + throw new Exception ("node type not supported for editing"); + + } + + public static XmlNode GetNodeFromUrl (string url, RootTree tree) + { + Console.WriteLine ("Url is: {0}", url); + string [] uSplit = ParseEditUrl (url); + Console.WriteLine ("Results are: {0}\n{1}\n{2}", uSplit [0], uSplit [1], uSplit [2]); + + string xp = uSplit [2]; + string id = uSplit [1]; + + XmlDocument d; + + if (uSplit[0].StartsWith("monodoc:///")) { + int prov = int.Parse (uSplit [0].Substring("monodoc:///".Length)); + d = tree.GetHelpSourceFromId (prov).GetHelpXmlWithChanges (id); + } else if (uSplit[0].StartsWith("file:")) { + d = new XmlDocument(); + d.PreserveWhitespace = true; + d.Load(uSplit[0].Substring(5)); + } else { + throw new NotImplementedException("Don't know how to load " + url); + } + + return d.SelectSingleNode (xp); + + } + + public static void SaveChange (string url, RootTree tree, XmlNode node, string node_url) + { + /*string [] uSplit = ParseEditUrl (url); + + string xp = uSplit [2]; + string id = uSplit [1]; + + if (uSplit[0].StartsWith("monodoc:///")) { + int prov = int.Parse (uSplit [0].Substring("monodoc:///".Length)); + HelpSource hs = tree.GetHelpSourceFromId (prov); + + changes.AddChange (hs.Name, hs.GetRealPath (id), xp, node, node_url); + changes.Save (); + } else if (uSplit[0].StartsWith("file:")) { + uSplit[0] = uSplit[0].Substring(5); + + XmlDocument d = new XmlDocument(); + d.PreserveWhitespace = true; + d.Load(uSplit[0]); + + XmlNode original = d.SelectSingleNode(xp); + original.ParentNode.ReplaceChild(d.ImportNode(node, true), original); + + d.Save(uSplit[0]); + } else { + throw new NotImplementedException("Don't know how to save to " + url); + }*/ + } + + public static void RemoveChange (string url, RootTree tree) + { + /*string [] uSplit = ParseEditUrl (url); + + string xp = uSplit [2]; + string id = uSplit [1]; + + if (uSplit[0].StartsWith("monodoc:///")) { + int prov = int.Parse (uSplit [0].Substring("monodoc:///".Length)); + HelpSource hs = tree.GetHelpSourceFromId (prov); + + changes.RemoveChange (hs.Name, hs.GetRealPath (id), xp); + changes.Save (); + } else if (uSplit[0].StartsWith("file:")) { + //TODO: Not implemented + }*/ + } + + public static void RenderEditPreview (string url, RootTree tree, XmlNode new_node, XmlWriter w) + { + string [] uSplit = ParseEditUrl (url); + + if (uSplit[0].StartsWith("monodoc:///")) { + int prov = int.Parse (uSplit [0].Substring("monodoc:///".Length)); + HelpSource hs = tree.GetHelpSourceFromId (prov); + hs.RenderPreviewDocs (new_node, w); + } else { + foreach (HelpSource hs in tree.HelpSources) { + if (hs is Monodoc.Providers.EcmaUncompiledHelpSource) { + // It doesn't matter which EcmaHelpSource is chosen. + hs.RenderPreviewDocs (new_node, w); + break; + } + } + } + } + + public static string [] ParseEditUrl (string url) + { + if (!url.StartsWith ("edit:")) + throw new Exception ("wtf"); + + string [] parts = url.Split ('@'); + if (parts.Length != 2) + throw new Exception (String.Format ("invalid editing url {0}", parts.Length)); + + string xp = HttpUtility.UrlDecode (parts [1]); + parts = HttpUtility.UrlDecode (parts [0]).Substring ("edit:".Length).Split ('@'); + if (parts.Length == 1) { + string p = parts[0]; + parts = new string[2]; + parts[0] = p; + parts[1] = ""; + } + + return new string [] {parts [0], parts [1], xp}; + } + + public static void AccountForChanges (XmlDocument d, string doc_set, string real_file) + { + try { + FileChangeset fcs = changes.GetChangeset (doc_set, real_file); + if (fcs == null) + return; + + foreach (Change c in fcs.Changes) { + // Filter out old changes + if (c.FromVersion != RootTree.MonodocVersion) + continue; + + XmlNode old = d.SelectSingleNode (c.XPath); + if (old != null) + old.ParentNode.ReplaceChild (d.ImportNode (c.NewNode, true), old); + } + } catch { + return; + } + } + + public static GlobalChangeset changes = GlobalChangeset.Load (); + + static public GlobalChangeset GetChangesFrom (int starting_serial_id) + { + return changes.GetFrom (starting_serial_id); + } + } + +#region Data Model + public class GlobalChangeset { + + public static XmlSerializer serializer = new XmlSerializer (typeof (GlobalChangeset)); + static string changeset_file = Path.Combine (SettingsHandler.Path, "changeset.xml"); + static string changeset_backup_file = Path.Combine (SettingsHandler.Path, "changeset.xml~"); + + public static GlobalChangeset Load () + { + try { + if (File.Exists (changeset_file)) + return LoadFromFile (changeset_file); + } catch {} + + return new GlobalChangeset (); + } + + public static GlobalChangeset LoadFromFile (string fileName) + { + using (Stream s = File.OpenRead (fileName)) { + return (GlobalChangeset) serializer.Deserialize (s); + } + } + + public void Save () + { + SettingsHandler.EnsureSettingsDirectory (); + + try { + if (File.Exists(changeset_file)) // create backup copy + File.Copy (changeset_file, changeset_backup_file, true); + + using (FileStream fs = File.Create (changeset_file)){ + serializer.Serialize (fs, this); + } + } catch (Exception e) { + Console.WriteLine ("Error while saving changes. " + e); + if (File.Exists(changeset_backup_file)) // if saving fails then use backup if we have one + File.Copy (changeset_backup_file, changeset_file, true); + else + File.Delete (changeset_file); // if no backup, delete invalid changeset + } + } + + static void VerifyDirectoryExists (DirectoryInfo d) { + if (d.Exists) + return; + + VerifyDirectoryExists (d.Parent); + d.Create (); + } + + [XmlElement ("DocSetChangeset", typeof (DocSetChangeset))] + public ArrayList DocSetChangesets = new ArrayList (); + + public FileChangeset GetChangeset (string doc_set, string real_file) + { + foreach (DocSetChangeset dscs in DocSetChangesets) { + if (dscs.DocSet != doc_set) + continue; + + foreach (FileChangeset fcs in dscs.FileChangesets) { + if (fcs.RealFile == real_file) + return fcs; + } + } + + return null; + } + + public int Count { + get { + int count = 0; + + foreach (DocSetChangeset dscs in DocSetChangesets){ + foreach (FileChangeset fcs in dscs.FileChangesets){ + count += fcs.Changes.Count; + } + } + + return count; + } + } + + Change NewChange (string xpath, XmlNode new_node, string node_url) + { + Change new_change = new Change (); + new_change.XPath = xpath; + new_change.NewNode = new_node; + new_change.NodeUrl = node_url; + + Console.WriteLine ("New serial:" + SettingsHandler.Settings.SerialNumber); + new_change.Serial = SettingsHandler.Settings.SerialNumber; + + return new_change; + } + + public void AddChange (string doc_set, string real_file, string xpath, XmlNode new_node, string node_url) + { + FileChangeset new_file_change_set; + Change new_change = NewChange (xpath, new_node, node_url); + + if (real_file == null) + throw new Exception ("Could not find real_file. Please talk to Miguel or Ben about this"); + + foreach (DocSetChangeset dscs in DocSetChangesets) { + if (dscs.DocSet != doc_set) + continue; + + foreach (FileChangeset fcs in dscs.FileChangesets) { + if (fcs.RealFile != real_file) + continue; + + foreach (Change c in fcs.Changes) { + if (c.XPath == xpath) { + c.NewNode = new_node; + c.Serial = SettingsHandler.Settings.SerialNumber; + return; + } + } + + fcs.Changes.Add (new_change); + return; + + } + + new_file_change_set = new FileChangeset (); + new_file_change_set.RealFile = real_file; + new_file_change_set.Changes.Add (new_change); + dscs.FileChangesets.Add (new_file_change_set); + return; + + } + + DocSetChangeset new_dcs = new DocSetChangeset (); + new_dcs.DocSet = doc_set; + + new_file_change_set = new FileChangeset (); + new_file_change_set.RealFile = real_file; + + new_file_change_set.Changes.Add (new_change); + new_dcs.FileChangesets.Add (new_file_change_set); + DocSetChangesets.Add (new_dcs); + } + + public void RemoveChange (string doc_set, string real_file, string xpath) + { + if (real_file == null) + throw new Exception ("Could not find real_file. Please talk to Miguel or Ben about this"); + + for (int i = 0; i < DocSetChangesets.Count; i++) { + DocSetChangeset dscs = DocSetChangesets [i] as DocSetChangeset; + if (dscs.DocSet != doc_set) + continue; + + for (int j = 0; j < dscs.FileChangesets.Count; j++) { + FileChangeset fcs = dscs.FileChangesets [j] as FileChangeset; + if (fcs.RealFile != real_file) + continue; + + for (int k = 0; k < fcs.Changes.Count; k++) { + Change c = fcs.Changes [k] as Change; + if (c.XPath == xpath) { + fcs.Changes.Remove (c); + break; + } + } + if (fcs.Changes.Count == 0) + dscs.FileChangesets.Remove (fcs); + } + + if (dscs.FileChangesets.Count == 0) + DocSetChangesets.Remove (dscs); + } + } + + public GlobalChangeset GetFrom (int starting_serial_id) + { + GlobalChangeset s = null; + + foreach (DocSetChangeset dscs in DocSetChangesets){ + object o = dscs.GetFrom (starting_serial_id); + if (o == null) + continue; + if (s == null) + s = new GlobalChangeset (); + s.DocSetChangesets.Add (o); + } + return s; + } + } + + public class DocSetChangeset { + [XmlAttribute] public string DocSet; + + [XmlElement ("FileChangeset", typeof (FileChangeset))] + public ArrayList FileChangesets = new ArrayList (); + + public DocSetChangeset GetFrom (int starting_serial_id) + { + DocSetChangeset dsc = null; + + foreach (FileChangeset fcs in FileChangesets){ + object o = fcs.GetFrom (starting_serial_id); + if (o == null) + continue; + if (dsc == null){ + dsc = new DocSetChangeset (); + dsc.DocSet = DocSet; + } + dsc.FileChangesets.Add (o); + } + return dsc; + } + } + + public class FileChangeset { + [XmlAttribute] public string RealFile; + + [XmlElement ("Change", typeof (Change))] + public ArrayList Changes = new ArrayList (); + + public FileChangeset GetFrom (int starting_serial_id) + { + FileChangeset fcs = null; + + foreach (Change c in Changes){ + if (c.Serial < starting_serial_id) + continue; + if (fcs == null){ + fcs = new FileChangeset (); + fcs.RealFile = RealFile; + } + fcs.Changes.Add (c); + } + return fcs; + } + } + + public class Change { + [XmlAttribute] public string XPath; + [XmlAttribute] public int FromVersion = RootTree.MonodocVersion; + [XmlAttribute] public string NodeUrl; + + public XmlNode NewNode; + + public int Serial; + + bool applied = false; + + // + // These are not a property, because we dont want them serialized; + // Only used by the Admin Client. + // + public bool Applied () + { + return applied; + } + + public void SetApplied (bool value) + { + applied = value; + } + } +#endregion + + public class EditMerger { + GlobalChangeset changeset; + ArrayList targetDirs; + + public EditMerger (GlobalChangeset changeset, ArrayList targetDirs) + { + this.changeset = changeset; + this.targetDirs = targetDirs; + } + + public void Merge () + { + foreach (DocSetChangeset dsc in changeset.DocSetChangesets) { + bool merged = false; + foreach (string path in targetDirs) { + if (File.Exists (Path.Combine (path, dsc.DocSet + ".source"))) { + Merge (dsc, path); + merged = true; + break; + } + } + if (!merged) Console.WriteLine ("Could not merge docset {0}", dsc.DocSet); + } + } + + void Merge (DocSetChangeset dsc, string path) + { + Console.WriteLine ("Merging changes in {0} ({1})", dsc.DocSet, path); + + foreach (FileChangeset fcs in dsc.FileChangesets) { + if (File.Exists (Path.Combine (path, fcs.RealFile))) + Merge (fcs, path); + else + Console.WriteLine ("\tCould not find file {0}", Path.Combine (path, fcs.RealFile)); + } + } + + void Merge (FileChangeset fcs, string path) + { + XmlDocument d = new XmlDocument (); + d.Load (Path.Combine (path, fcs.RealFile)); + + foreach (Change c in fcs.Changes) { + XmlNode old = d.SelectSingleNode (c.XPath); + if (old != null) + old.ParentNode.ReplaceChild (d.ImportNode (c.NewNode, true), old); + } + + d.Save (Path.Combine (path, fcs.RealFile)); + } + } +} + |