/// <summary> /// Checks the selection of the listbox. If the keyword contains more than one topic, /// a "Topics found" dialog will be displayed to the user and let him select de desired topic. /// Fires the <c>IndexSelected</c> event let the parent window know, that the user wants to view /// a new help topic. /// </summary> /// <param name="errorOnNothingSelected">set this true, if you want to display an error message if no item is selected</param> private void DisplayTopic(bool errorOnNothingSelected) { if (lbIndex.SelectedIndex >= 0) { HtmlHelpIndexItem item = _arrIndex[lbIndex.SelectedIndex]; if (item.Topics.Count > 1) { OnTopicsFound(new TopicsFoundEventArgs(item.Topics)); } else { if (item.IsSeeAlso) { if (item.SeeAlso.Length > 0) { SelectText(item.SeeAlso[0]); string url = ""; string title = item.KeyWord; if (item.Topics.Count == 1) { url = item.Topics[0].URL; title = item.Topics[0].Title; } OnIndexSelected(new IndexEventArgs(title, url, item.IsSeeAlso, item.SeeAlso)); return; } } if (item.Topics.Count == 1) { OnIndexSelected(new IndexEventArgs(item.Topics[0].Title, item.Topics[0].URL, item.IsSeeAlso, item.SeeAlso)); } } } else { if (errorOnNothingSelected) { MessageBox.Show("Select a keyword first !", "Index", MessageBoxButtons.OK, MessageBoxIcon.Error); } } }
/// <summary> /// Recursively parses a sitemap tree /// </summary> /// <param name="text">content text</param> /// <param name="parent">Parent for all read items</param> /// <param name="arrNodes">arraylist which receives the extracted nodes</param> /// <param name="chmFile">CHMFile instance</param> private static void ParseTree(string text, HtmlHelpIndexItem parent, List <HtmlHelpIndexItem> arrNodes, CHMFile chmFile) { string strPreItems = "", strPostItems = ""; string innerText = ""; int nIndex = 0; while (NestedRE.IsMatch(text, nIndex)) { Match m = NestedRE.Match(text, nIndex); innerText = m.Value.Substring(1, m.Length - 2); strPreItems = text.Substring(nIndex, m.Index - nIndex); ParseItems(strPreItems, parent, arrNodes, chmFile); if ((arrNodes.Count > 0) && (innerText.Length > 0)) { HtmlHelpIndexItem p = ((HtmlHelpIndexItem)(arrNodes[arrNodes.Count - 1])); ParseTree(innerText, p, arrNodes, chmFile); } nIndex = m.Index + m.Length; } if (nIndex == 0) { strPostItems = text.Substring(nIndex, text.Length - nIndex); ParseItems(strPostItems, parent, arrNodes, chmFile); } else if (nIndex < text.Length - 1) { strPostItems = text.Substring(nIndex, text.Length - nIndex); ParseTree(strPostItems, parent, arrNodes, chmFile); } }
/// <summary> /// Parses nodes from the text /// </summary> /// <param name="itemstext">text containing the items</param> /// <param name="parentItem">parent index item</param> /// <param name="arrNodes">arraylist where the nodes should be added</param> /// <param name="chmFile">CHMFile instance</param> private static void ParseItems(string itemstext, HtmlHelpIndexItem parentItem, List <HtmlHelpIndexItem> arrNodes, CHMFile chmFile) { int innerTextIdx = ObjectRE.GroupNumberFromName("innerText"); int innerPTextIdx = ParamRE.GroupNumberFromName("innerText"); // get group-name indexes int nameIndex = AttributesRE.GroupNumberFromName("attributeName"); int valueIndex = AttributesRE.GroupNumberFromName("attributeValue"); int tdIndex = AttributesRE.GroupNumberFromName("attributeTD"); int nObjStartIndex = 0; int nLastObjStartIndex = 0; string sKeyword = ""; while (ObjectRE.IsMatch(itemstext, nObjStartIndex)) { Match m = ObjectRE.Match(itemstext, nObjStartIndex); string innerText = m.Groups[innerTextIdx].Value; HtmlHelpIndexItem idxItem = new HtmlHelpIndexItem(); // read parameters int nParamIndex = 0; int nNameCnt = 0; string paramTitle = ""; string paramLocal = ""; bool bAdded = false; while (ParamRE.IsMatch(innerText, nParamIndex)) { Match mP = ParamRE.Match(innerText, nParamIndex); string innerP = mP.Groups[innerPTextIdx].Value; string paramName = ""; string paramValue = ""; int nAttrIdx = 0; //sKeyword = ""; while (AttributesRE.IsMatch(innerP, nAttrIdx)) { Match mA = AttributesRE.Match(innerP, nAttrIdx); string attributeName = mA.Groups[nameIndex].Value; string attributeValue = mA.Groups[valueIndex].Value; string attributeTD = mA.Groups[tdIndex].Value; if (attributeTD.Length > 0) { // delete the trailing textqualifier if (attributeValue.Length > 0) { int ltqi = attributeValue.LastIndexOf(attributeTD); if (ltqi >= 0) { attributeValue = attributeValue.Substring(0, ltqi); } } } if (attributeName.ToLower() == "name") { paramName = HttpUtility.HtmlDecode(attributeValue); // for unicode encoded values nNameCnt++; } if (attributeName.ToLower() == "value") { paramValue = HttpUtility.HtmlDecode(attributeValue); // for unicode encoded values // delete trailing / while ((paramValue.Length > 0) && (paramValue[paramValue.Length - 1] == '/')) { paramValue = paramValue.Substring(0, paramValue.Length - 1); } } nAttrIdx = mA.Index + mA.Length; } if (nNameCnt == 1) // first "Name" param = keyword { sKeyword = ""; if (parentItem != null) { sKeyword = parentItem.KeyWordPath + ","; } string sOldKW = sKeyword; sKeyword += paramValue; HtmlHelpIndexItem idxFind = FindByKeyword(arrNodes, sKeyword); if (idxFind != null) { idxItem = idxFind; } else { if (sKeyword.Split(new char[] { ',' }).Length > 1) { idxItem.CharIndex = sKeyword.Length - paramValue.Length; } else { sKeyword = paramValue; sOldKW = sKeyword; idxItem.CharIndex = 0; } idxItem.KeyWordPath = sKeyword; idxItem.Indent = sKeyword.Split(new char[] { ',' }).Length - 1; idxItem.IsSeeAlso = false; sKeyword = sOldKW; } } else { if ((nNameCnt > 2) && (paramName.ToLower() == "name")) { bAdded = true; HtmlHelpIndexTopic idxTopic = new HtmlHelpIndexTopic(paramTitle, paramLocal, chmFile.CompileFile, chmFile.ChmFilePath); idxItem.Topics.Add(idxTopic); paramTitle = ""; paramLocal = ""; } switch (paramName.ToLower()) { case "name": //case "keyword": { paramTitle = paramValue; }; break; case "local": { paramLocal = paramValue.Replace("../", "").Replace("./", ""); }; break; case "type": // information type assignment for item { idxItem.InfoTypeStrings.Add(paramValue); }; break; case "see also": { idxItem.AddSeeAlso(paramValue); idxItem.IsSeeAlso = true; bAdded = true; }; break; } } nParamIndex = mP.Index + mP.Length; } if (!bAdded) { bAdded = false; HtmlHelpIndexTopic idxTopic = new HtmlHelpIndexTopic(paramTitle, paramLocal, chmFile.CompileFile, chmFile.ChmFilePath); idxItem.Topics.Add(idxTopic); paramTitle = ""; paramLocal = ""; } idxItem.ChmFile = chmFile; arrNodes.Add(idxItem); nLastObjStartIndex = nObjStartIndex; nObjStartIndex = m.Index + m.Length; } }
/// <summary> /// Decodes a block of url-string data /// </summary> /// <param name="dataBlock">block of data</param> /// <param name="nOffset">current file offset</param> /// <param name="indexBlocks">number of index blocks</param> /// <returns>true if succeeded</returns> private bool DecodeBlock(byte[] dataBlock, ref int nOffset, int indexBlocks) { bool bRet = true; int nblockOffset = nOffset; MemoryStream memStream = new MemoryStream(dataBlock); BinaryReader binReader = new BinaryReader(memStream); int freeSpace = binReader.ReadInt16(); // length of freespace int nrOfEntries = binReader.ReadInt16(); // number of entries bool bListingEndReached = false; //while( (memStream.Position < (memStream.Length-freeSpace)) && (bRet) ) //{ int nIndexOfPrevBlock = -1; int nIndexOfNextBlock = -1; int nIndexOfChildBlock = 0; if (_readListingBlocks) { nIndexOfPrevBlock = binReader.ReadInt32(); // -1 if this is the header nIndexOfNextBlock = binReader.ReadInt32(); // -1 if this is the last block } else { nIndexOfChildBlock = binReader.ReadInt32(); } for (int nE = 0; nE < nrOfEntries; nE++) { if (_readListingBlocks) { bListingEndReached = (nIndexOfNextBlock == -1); string keyWord = BinaryReaderHelp.ExtractUTF16String(ref binReader, 0, true, _associatedFile.TextEncoding); bool isSeeAlsoKeyword = (binReader.ReadInt16() != 0); int indent = binReader.ReadInt16(); // indent of entry int nCharIndex = binReader.ReadInt32(); binReader.ReadInt32(); int numberOfPairs = binReader.ReadInt32(); int[] nTopics = new int[numberOfPairs]; string[] seeAlso = new string[numberOfPairs]; for (int i = 0; i < numberOfPairs; i++) { if (isSeeAlsoKeyword) { seeAlso[i] = HttpUtility.HtmlDecode(BinaryReaderHelp.ExtractUTF16String(ref binReader, 0, true, _associatedFile.TextEncoding)); } else { nTopics[i] = binReader.ReadInt32(); } } binReader.ReadInt32(); // unknown int nIndexOfThisEntry = binReader.ReadInt32(); HtmlHelpIndexItem newItem = new HtmlHelpIndexItem(_associatedFile, keyWord, isSeeAlsoKeyword, indent, nCharIndex, nIndexOfThisEntry, seeAlso, nTopics); _indexList.Add(newItem); } else { string keyWord = BinaryReaderHelp.ExtractUTF16String(ref binReader, 0, true, _associatedFile.TextEncoding); bool isSeeAlsoKeyword = (binReader.ReadInt16() != 0); int indent = binReader.ReadInt16(); // indent of entry int nCharIndex = binReader.ReadInt32(); binReader.ReadInt32(); int numberOfPairs = binReader.ReadInt32(); int[] nTopics = new int[numberOfPairs]; string[] seeAlso = new string[numberOfPairs]; for (int i = 0; i < numberOfPairs; i++) { if (isSeeAlsoKeyword) { seeAlso[i] = BinaryReaderHelp.ExtractUTF16String(ref binReader, 0, true, _associatedFile.TextEncoding); } else { nTopics[i] = binReader.ReadInt32(); } } int nIndexChild = binReader.ReadInt32(); int nIndexOfThisEntry = -1; HtmlHelpIndexItem newItem = new HtmlHelpIndexItem(_associatedFile, keyWord, isSeeAlsoKeyword, indent, nCharIndex, nIndexOfThisEntry, seeAlso, nTopics); _indexList.Add(newItem); } } //} binReader.ReadBytes(freeSpace); if (bListingEndReached) { _readListingBlocks = false; } return(bRet); }
/// <summary> /// Shows help for a specific keyword /// </summary> /// <param name="namespaceFilter">namespace filter (used for merged files)</param> /// <param name="hlpNavigator">navigator value</param> /// <param name="keyword">keyword</param> /// <param name="url">url</param> void IHelpViewer.ShowHelp(string namespaceFilter, HelpNavigator hlpNavigator, string keyword, string url) { switch (hlpNavigator) { case HelpNavigator.AssociateIndex: { HtmlHelpIndexItem foundIdx = _reader.Index.SearchIndex(keyword, IndexType.AssiciativeLinks); if (foundIdx != null) { if (foundIdx.Topics.Count > 0) { HtmlHelpIndexTopic topic = foundIdx.Topics[0]; if (topic.Local.Length > 0) { NavigateBrowser(topic.URL); } } } } break; case HelpNavigator.Find: { this.Cursor = Cursors.WaitCursor; this.helpSearch.SetSearchText(keyword); DataTable dtResults = _reader.PerformSearch(keyword, 500, true, false); this.helpSearch.SetResults(dtResults); this.Cursor = Cursors.Arrow; this.helpSearch.Focus(); } break; case HelpNavigator.Index: { ((IHelpViewer)this).ShowHelpIndex(url); } break; case HelpNavigator.KeywordIndex: { HtmlHelpIndexItem foundIdx = _reader.Index.SearchIndex(keyword, IndexType.KeywordLinks); if (foundIdx != null) { if (foundIdx.Topics.Count == 1) { HtmlHelpIndexTopic topic = foundIdx.Topics[0]; if (topic.Local.Length > 0) { NavigateBrowser(topic.URL); } } else if (foundIdx.Topics.Count > 1) { this.helpIndex.SelectText(foundIdx.IndentKeyWord); } } this.helpIndex.Focus(); } break; case HelpNavigator.TableOfContents: { HtmlHelpTocItem foundTOC = _reader.HtmlHelpToc.SearchTopic(keyword); if (foundTOC != null) { if (foundTOC.Local.Length > 0) { NavigateBrowser(foundTOC.Url); } } this.helpTocTree.Focus(); } break; case HelpNavigator.Topic: { HtmlHelpTocItem foundTOC = _reader.HtmlHelpToc.SearchTopic(keyword); if (foundTOC != null) { if (foundTOC.Local.Length > 0) { NavigateBrowser(foundTOC.Url); } } } break; } }