2 // A provider to display man pages
5 // Johannes Roith <johannes@roith.de>
6 // Jonathan Pryor <jpryor@novell.com>
8 // (C) 2008 Novell, Inc.
12 using System.Collections;
18 // The simple provider generates the information source
20 public class ManProvider : Provider {
23 public ManProvider (string[] handbookTocFiles)
25 tocFiles = handbookTocFiles;
28 if (!File.Exists (tocFiles[0]))
29 throw new FileNotFoundException (String.Format ("The table of contents, `{0}' does not exist", tocFiles[0]));
32 public override void PopulateTree (Tree tree)
34 foreach(string TocFile in tocFiles) {
36 XmlDocument doc = new XmlDocument();
39 XmlNodeList nodeList = doc.GetElementsByTagName("manpage");
40 Node nodeToAddChildrenTo = tree;
42 foreach(XmlNode node in nodeList) {
44 XmlAttribute name = node.Attributes["name"];
45 XmlAttribute page = node.Attributes["page"];
47 if (name == null || page == null) continue;
49 if (!File.Exists (page.Value))
52 string target = "man:" + name.Value;
53 nodeToAddChildrenTo.CreateNode (name.Value, target);
55 if (File.Exists(page.Value))
56 nodeToAddChildrenTo.tree.HelpSource.PackFile (page.Value, name.Value);
62 public override void CloseTree (HelpSource hs, Tree tree)
68 // The HelpSource is used during the rendering phase.
71 public class ManHelpSource : HelpSource {
73 public ManHelpSource (string base_file, bool create) : base (base_file, create) {}
74 protected const string MAN_PREFIX = "man:";
76 public override string GetText (string url, out Node match_node)
79 if (url.IndexOf (MAN_PREFIX) > -1)
80 return GetTextFromUrl (url);
82 // display an index of sub-nodes.
83 StringBuilder buf = new StringBuilder ();
84 buf.Append ("<table bgcolor=\"#b0c4de\" width=\"100%\" cellpadding=\"5\"><tr><td><h3>Mono Documentation Library</h3></td></tr></table>");
85 buf.Append ("<p>Available man pages:</p>").Append ("<blockquote>");
86 foreach (Node n in Tree.Nodes) {
87 buf.Append ("<a href=\"").Append (n.Element).Append ("\">")
88 .Append (n.Caption).Append ("</a><br/>");
90 buf.Append ("</blockquote>");
91 return buf.ToString ();
97 protected string GetTextFromUrl (string url)
99 // Remove "man:" prefix including any help-source id on the front.
100 int prefixStart = url.IndexOf(MAN_PREFIX);
101 if (prefixStart > -1)
102 url = url.Substring (prefixStart + 4);
104 if (url == null || url.Length == 0)
106 Console.WriteLine("Warning, NULL url!");
107 return "<html>url was null</html>";
110 Stream stream = GetHelpStream (url);
111 return GetTextFromStream (stream);
114 public static string GetTextFromStream (Stream stream)
117 return "<html>url was null</html>";
118 StreamReader file = new StreamReader(stream);
121 StateInfo s = new StateInfo ();
123 while ((line = file.ReadLine ()) != null) {
124 ProcessLine (line, s);
126 return s.output.ToString ();
137 public Stack tags = new Stack ();
138 public StringBuilder output = new StringBuilder ();
141 private static void ProcessLine (string line, StateInfo s)
143 string[] parts = SplitLine (line);
145 case ".\\\"": // comments
146 case ".de": // define macro
149 case "..": // end macro
153 s.output.Append ("<i>");
154 Translate (parts, 1, s.output);
155 s.output.Append ("</i>");
158 s.output.Append ("<b>");
159 Translate (parts, 1, s.output);
160 s.output.Append ("</b>");
163 Translate (parts, 1, s.output);
164 s.output.Append ("<br />");
168 s.output.Append ("<pre>\n");
169 s.tags.Push ("</pre>");
172 Expect (s, "</pre>");
175 Expect (s, "</p>", "</dd>", "</dl>");
179 s.output.Append ("<p>");
180 Translate (parts, 1, s.output);
181 s.tags.Push ("</p>");
185 s.output.Append ("<blockquote>");
186 s.tags.Push ("</blockquote>");
189 ClearUntil (s, "</blockquote>");
193 s.output.Append ("<h2>");
194 Translate (parts, 1, s.output);
195 s.output.Append ("</h2>")
196 .Append ("<blockquote>");
197 s.tags.Push ("</blockquote>");
200 s.output.Append ("<h3>");
201 Translate (parts, 1, s.output);
202 s.output.Append ("</h3>");
206 string name = "", extra = "";
207 if (parts.Length >= 4 && parts [2].Trim ().Length == 0) {
208 name = parts [1] + "(" + parts [3] + ")";
209 if (parts.Length > 4) {
211 if (parts [start].Trim ().Length == 0)
213 extra = string.Join ("", parts, start, parts.Length-start);
217 name = string.Join ("", parts, 1, parts.Length-1);
218 s.output.Append ("<table width=\"100%\" bgcolor=\"#b0c4da\">" +
219 "<tr colspan=\"2\"><td>Manual Pages</td></tr>\n" +
221 Translate (name, s.output);
222 s.output.Append ("</h3></td><td align=\"right\">");
223 Translate (extra, s.output);
224 s.output.Append ("</td></tr></table>");
229 if (s.tags.Count > 0 && s.tags.Peek ().ToString () != "</dd>") {
230 s.output.Append ("<dl>");
231 s.tags.Push ("</dl>");
235 s.output.Append ("<dt>");
236 s.tags.Push ("</dt>");
237 s.ls = ListState.Start;
240 Translate (line, s.output);
243 if (s.ls == ListState.Start)
244 s.ls = ListState.Title;
245 else if (s.ls == ListState.Title) {
247 s.output.Append ("<dd>");
248 s.tags.Push ("</dd>");
249 s.ls = ListState.None;
251 s.output.Append ("\n");
254 private static string[] SplitLine (string line)
256 if (line.Length > 1 && line [0] != '.')
257 return new string[]{null, line};
260 for (i = 0; i < line.Length; ++i) {
261 if (char.IsWhiteSpace (line, i))
265 if (i == line.Length)
266 return new string[]{line};
268 ArrayList pieces = new ArrayList ();
269 pieces.Add (line.Substring (0, i));
270 bool inQuotes = false;
274 for ( ; i < line.Length; ++i) {
278 Add (pieces, line, start, i);
284 if (prevWs && c == '"') {
285 Add (pieces, line, start, i);
289 else if (char.IsWhiteSpace (c)) {
291 Add (pieces, line, start, i);
298 Add (pieces, line, start, i);
305 if (start > 0 && start != line.Length)
306 pieces.Add (line.Substring (start, line.Length-start));
307 return (string[]) pieces.ToArray (typeof(string));
310 private static void Add (ArrayList pieces, string line, int start, int end)
314 pieces.Add (line.Substring (start, end-start));
317 private static void Expect (StateInfo s, params string[] expected)
320 while (s.tags.Count > 0 &&
321 Array.IndexOf (expected, (e = s.tags.Peek ().ToString ())) >= 0) {
322 s.output.Append (s.tags.Pop ().ToString ());
326 private static void ClearUntil (StateInfo s, string required)
329 while (s.tags.Count > 0 &&
330 (e = s.tags.Peek ().ToString ()) != required) {
331 s.output.Append (s.tags.Pop ().ToString ());
334 s.output.Append (s.tags.Pop ().ToString ());
337 private static void ClearAll (StateInfo s)
339 while (s.tags.Count > 0)
340 s.output.Append (s.tags.Pop ().ToString ());
343 private static void Translate (string[] lines, int startIndex, StringBuilder output)
345 if (lines.Length <= startIndex)
348 Translate (lines [startIndex++], output);
349 if (startIndex == lines.Length)
351 } while (startIndex < lines.Length);
354 private static void Translate (string line, StringBuilder output)
357 int start = output.Length;
358 for (int i = 0; i < line.Length; ++i) {
361 if ((i+2) < line.Length && line [i+1] == 'f') {
362 if (line [i+2] == 'I') {
363 output.Append ("<i>");
366 else if (line [i+2] == 'B') {
367 output.Append ("<b>");
370 else if (line [i+2] == 'R' || line [i+2] == 'P') {
371 output.Append (span);
377 else if ((i+1) < line.Length) {
378 output.Append (line [i+1]);
386 output.Append ("<");
389 output.Append (">");
392 output.Append ("&");
395 output.Append (line [i]);