[This documentation is for preview only, is not supported, and is subject to change in later releases.]

using System;

using System.Collections.Generic;

using System.Collections.ObjectModel;

using System.Linq;

using System.Text;

using System.Xml;

using System.Windows.Data;

using System.IO;

using System.Globalization;

using System.Web;

using Microsoft.VisualStudio.Shell.Interop;

using System.Windows.Controls.Primitives;

using System.Windows.Controls;

using Microsoft.Win32;

 

 

namespace MS.SDKMSDNKeywordIndex

{

    public class HelpApiShim

    {

        private static string _baseOfflineUrlSession;

        private const string baseOfflineUrl = "http://127.0.0.1:47873/help/";

        private static string _locale;

 

        public HelpApiShim()

        {

            _baseOfflineUrlSession = GetBaseHelpUrl(); // baseOfflineUrl + NativeMethods.GetSessionNumber().ToString() + "/ms.help?";

            _locale = CultureInfo.CurrentUICulture.ToString();

        }

 

 

        private static string GetBaseHelpUrl()

        {

            string pid;

            HelpUtility.StartHelpAgent();

 

            System.Diagnostics.Process[] helpProcesses = System.Diagnostics.Process.GetProcessesByName("helplibagent");

            pid = helpProcesses[0].Id.ToString();

 

            _baseOfflineUrlSession = baseOfflineUrl + NativeMethods.GetSessionNumber().ToString() + "-" + pid + "/ms.help?";

 

            return _baseOfflineUrlSession;

        }

 

        public List<TocNode> GetRootTocNodes()

        {

            TocNode rootNode = new TocNode("", "", "-1");

            return GetTocNodes(rootNode);

        }

 

        public List<TocNode> GetTocNodes(TocNode tocNode)

        {

            List<TocNode> childNodes = new List<TocNode>();

            if (tocNode == null)

                return childNodes;

 

            string tocURL = buildHelpUrl("children", tocNode.Id, "VS", "100", "xml");

            Stream tocXmlStream = HelpUtility.GetHelpXmlAsStream(tocURL);

            XmlTextReader tocReader = new XmlTextReader(tocXmlStream);

 

            while (tocReader.Read())

            {

                switch (tocReader.NodeType)

                {

                    case XmlNodeType.Element:

                        if (tocReader.Name.Equals("topic"))

                        {

                            TocNode node = new TocNode();

                            node.Id = tocReader.GetAttribute("id");

                            tocReader.ReadToDescendant("title");

                            node.Title = tocReader.ReadString();

                            tocReader.ReadToNextSibling("url");

                            node.Url = tocReader.ReadString();

                            node.hasChildren = nodeHasChildren(node);

                            childNodes.Add(node);

                        }

                   break;

                }

            }

 

            return childNodes;

        }

 

        private static bool nodeHasChildren(TocNode node)

        {

            string tocURL = buildHelpUrl("children", node.Id, "VS", "100", "xml");

            XmlDocument document = HelpUtility.GetHelpXmlAsXmlDocument(tocURL);

            XmlNodeList topicNodes = document.SelectNodes("/children/topic");

            if (topicNodes.Count > 0)

            { return true; }

            else

            { return false; }

        }

 

        public List<kwdItem> GetKeywordItems(string keyword)

        {

            List<kwdItem> kwdList = new List<kwdItem>();

            string helpUrl = buildHelpUrl("keywords", keyword, "VS", "100", "xml", "&pageSize=100000&pagenumber=1");

            Stream keywordXmlStream = HelpUtility.GetHelpXmlAsStream(helpUrl);

           

            if (keywordXmlStream == null)

                return kwdList;

           

            XmlTextReader keywordReader = new XmlTextReader(keywordXmlStream);

            string currentKwd = "";

 

            while (keywordReader.Read())

            {

                switch (keywordReader.NodeType)

                {

                    case XmlNodeType.Element:

                        if (keywordReader.Name.Equals("keywords"))

                        {

                            //keywordCount = int.Parse(keywordReader.GetAttribute("totalKeywords"));

                            //currentKeywordCount += int.Parse(keywordReader.GetAttribute("returnedkeywords"));

                        }

                        else if (keywordReader.Name.Equals("keyword"))

                        {

                            currentKwd = keywordReader.GetAttribute("value");

                            kwdList.Add(new kwdItem(currentKwd, currentKwd));

 

                        }

                        else if (keywordReader.Name.Equals("subkey"))

                        {

                            string subKey = keywordReader.GetAttribute("display");

                            kwdList.Add(new kwdItem("  " + subKey, currentKwd + "," + subKey));

                        }

                        break;

                }

            }

            return kwdList;

        }

 

 

        public void NavigateKeywordTopic(kwdItem kwd, string browser, bool embedTOC)

        {

            string helpUrl = createKwdItemUrl(kwd, embedTOC);

            if (helpUrl != null)

            {

                launchHelp(helpUrl, browser);

            }

        }

 

        public void NavigateKeywordTopic(XmlDocument keywordTopicXML, string browser, bool embedTOCparam)

        {

            string helpUrl = createKwdItemUrl(keywordTopicXML, embedTOCparam);

            if (helpUrl != null)

            {

                launchHelp(helpUrl, browser);

            }

        }

 

        public void NavigateTopicItem(TopicItem topic, string browser, bool embedTOCParam)

        {

            string helpUrl = createTopicItemUrl(topic, embedTOCParam);

            if (helpUrl != null)

            {

                launchHelp(helpUrl, browser);

            }

        }

 

        public void NavigateSearchTerm(string searchTerm, string browser, bool embedTOCParam)

        {

            string helpUrl = createSearchItemUrl(searchTerm, embedTOCParam);

            if (helpUrl != null)

            {

                launchHelp(helpUrl, browser);

            }

        }

 

        public XmlDocument GetTopicXMLForKeyword (kwdItem kwd)

        {

            string encodedKwdValue = HttpUtility.UrlEncode(kwd.Value.TrimStart());

            string helpUrl = buildHelpUrl("keywords", encodedKwdValue, "VS", "100", "xml", "&category=topic");

            XmlDocument topics = HelpUtility.GetHelpXmlAsXmlDocument(helpUrl);

            return topics;

        }

 

        public void NavigateTocNode(TocNodeViewModel toc, string browser, bool embedTOCParam)

        {

            string helpUrl = buildHelpUrl("page", Uri.EscapeUriString(toc.Id.Replace("#", "%23")), "VS", "100", "xhtml", "&category=topic&embedded=" + embedTOCParam);

            launchHelp(helpUrl, browser);

        }

 

        private static string buildHelpUrl(string method, string query, string product, string version, string returnFormat, string otherParams = "")

        {

 

            return _baseOfflineUrlSession + "method=" + method + getQueryName(method) + query + "&product=" + product + "&productversion=" + version + "&locale=" + _locale + "&format=" + returnFormat + otherParams;

        }

 

        private void launchHelp(string url ,string browser)

        {

            switch (browser)

            {

                case "IDE":

                    HelpUtility.LaunchIDEBrowserHelp(url);

                    break;

                case "default":

                    HelpUtility.LaunchBrowserHelp(url);

                    break;

            }

        }

 

        private string createKwdItemUrl(kwdItem kwd, bool embedTOCParam)

        {

            string encodedKwdValue = HttpUtility.UrlEncode(kwd.Value.TrimStart());

            string helpUrl = buildHelpUrl("keywords", encodedKwdValue, "VS", "100", "xml", "&category=topic");

 

            XmlDocument topics = HelpUtility.GetHelpXmlAsXmlDocument(helpUrl);

            XmlNodeList topicNodes = topics.SelectNodes("/keywords/topic");

            if (topicNodes.Count > 0)

            {

                helpUrl = buildHelpUrl("page", Uri.EscapeUriString(topicNodes[0].Attributes["id"].Value.Replace("#", "%23")), "VS", "100", "xhtml", "&embedded=" + embedTOCParam);

                return helpUrl;

            }

 

            return null;

        }

 

 

 

        private string createKwdItemUrl(XmlDocument keywordTopicXML, bool embedTOCParam)

        {

            XmlNodeList topicNodes = keywordTopicXML.SelectNodes("/keywords/topic");

            if (topicNodes.Count > 0)

            {

                return buildHelpUrl("page", Uri.EscapeUriString(topicNodes[0].Attributes["id"].Value.Replace("#", "%23")), "VS", "100", "xhtml", "&embedded=" + embedTOCParam);

            }

            return null;

        }

 

        private string createTopicItemUrl(TopicItem topic, bool embedTOCparam)

        {

            return buildHelpUrl("page", Uri.EscapeUriString(topic.Id.Replace("#", "%23")), "VS", "100", "xhtml","&topicversion=" + topic.Version + "embedded=" + embedTOCparam);      

        }

 

       

        private string createSearchItemUrl(string searchTerm, bool embedTOCParam)

        {

            return buildHelpUrl("search", HttpUtility.UrlEncode(searchTerm.TrimStart()), "VS", "100", "xhtml");

        }

 

        public XmlDocument getTopicsForKeyword(kwdItem kwd)

        {

            string encodedKwdValue = HttpUtility.UrlEncode(kwd.Value.TrimStart());

            string helpUrl = buildHelpUrl("keywords", encodedKwdValue, "VS", "100", "xml", "&category=topic");

 

            XmlDocument topics = HelpUtility.GetHelpXmlAsXmlDocument(helpUrl);

 

            return topics;

        }

 

 

 

        private static string getQueryName(string method)

        {

            string queryName = "";

            switch (method)

            {

                case "page":

                    queryName = "&id=";

                    break;

                case "children":

                    queryName = "&id=";

                    break;

                default:

                    queryName = "&query=";

                    break;

            }

            return queryName;

        }

    }

}