/// <summary> /// Selects a node identified by its chm file and local /// </summary> /// <param name="col">treenode collection to search</param> /// <param name="chmFile">chm filename</param> /// <param name="local">local of the toc item</param> private void SelectTOCItem(TreeNodeCollection col, string chmFile, string local) { foreach (TreeNode curNode in col) { TOCItem curItem = curNode.Tag as TOCItem; if (curItem != null) { if ((curItem.Local == local) || (("/" + curItem.Local) == local)) { if (chmFile.Length > 0) { if (curItem.AssociatedFile.ChmFilePath == chmFile) { tocTreeView.SelectedNode = curNode; return; } } else { tocTreeView.SelectedNode = curNode; return; } } } SelectTOCItem(curNode.Nodes, chmFile, local); } }
private async void PreviewContent(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count == 0 || TestRunning.IsActive) { return; } TestRunning.IsActive = true; TOCItem Item = ( TOCItem )e.AddedItems[0]; Chapter Ch = Item.Ch; if (Ch == null) { ProcManager.PanelMessage(ID, "Chapter is not available", LogType.INFO); return; } string VId = Ch.Volume.Meta[AppKeys.GLOBAL_VID]; string CId = Ch.Meta[AppKeys.GLOBAL_CID]; EpInstruction EpInst = TempInst.GetVolInsts().First(x => x.VId == VId).EpInsts.Cast <EpInstruction>().First(x => x.CId == CId); IEnumerable <ProcConvoy> Convoys = await EpInst.Process(); StorageFile TempFile = await AppStorage.MkTemp(); StringResources stx = StringResources.Load("LoadingMessage"); foreach (ProcConvoy Konvoi in Convoys) { ProcConvoy Convoy = ProcManager.TracePackage( Konvoi , (d, c) => c.Payload is IEnumerable <IStorageFile> || c.Payload is IStorageFile ); if (Convoy == null) { continue; } if (Convoy.Payload is IStorageFile) { await TempFile.WriteFile(( IStorageFile )Convoy.Payload, true, new byte[] { ( byte )'\n' }); } else if (Convoy.Payload is IEnumerable <IStorageFile> ) { foreach (IStorageFile ISF in ((IEnumerable <IStorageFile>)Convoy.Payload)) { ProcManager.PanelMessage(ID, string.Format(stx.Str("MergingContents"), ISF.Name), LogType.INFO); await TempFile.WriteFile(ISF, true, new byte[] { ( byte )'\n' }); } } } ShowSource(TempFile); TestRunning.IsActive = false; }
/// <summary> /// Parses a HHC file and returns an ArrayList with the table of contents (TOC) tree /// </summary> /// <param name="hhcFile">string content of the hhc file</param> /// <param name="chmFile">CHMFile instance</param> /// <returns>Returns an ArrayList with the table of contents (TOC) tree</returns> public static ArrayList ParseHHC(string hhcFile, CHMFile chmFile) { _lastTopicItem = null; _mergeItems = null; // clear merged item list ArrayList tocList = new ArrayList(); ulRE = new Regex(RE_ULBoundaries, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); NestedRE = new Regex(RE_NestedBoundaries, RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); ObjectRE = new Regex(RE_ObjectBoundaries, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); ParamRE = new Regex(RE_ParamBoundaries, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); AttributesRE = new Regex(RE_QuoteAttributes, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); int innerTextIdx = ulRE.GroupNumberFromName("innerText"); if (ulRE.IsMatch(hhcFile, 0)) { Match m = ulRE.Match(hhcFile, 0); int nFirstUL = 0; nFirstUL = hhcFile.ToLower().IndexOf("<ul>"); if (nFirstUL == -1) { nFirstUL = hhcFile.ToLower().IndexOf("<il>"); } if (ObjectRE.IsMatch(hhcFile, 0)) // first object block contains information types and categories { Match mO = ObjectRE.Match(hhcFile, 0); int iOTxt = ObjectRE.GroupNumberFromName("innerText"); string globalText = mO.Groups[iOTxt].Value; if (mO.Groups[iOTxt].Index <= nFirstUL) { ParseGlobalSettings(globalText, chmFile); } } // parse toc tree string innerText = m.Groups["innerText"].Value; innerText = innerText.Replace("(", "("); innerText = innerText.Replace(")", ")"); innerText = Regex.Replace(innerText, RE_ULOpening, "(", RegexOptions.IgnoreCase); innerText = Regex.Replace(innerText, RE_ULClosing, ")", RegexOptions.IgnoreCase); ParseTree(innerText, null, tocList, chmFile); } return(tocList); }
public TOCPane(Volume[] Vols) { Volumes = new List <TOCItem>(); Chapters = new List <TOCItem>(); foreach (Volume V in Vols) { IEnumerable <TOCItem> Chs = V.Chapters.Select(C => new TOCItem(C)).ToArray(); Chapters.AddRange(Chs); TOCItem VItem = new TOCItem(V) { Children = Chs.ToList() }; Volumes.Add(VItem); } SearchSet = new TreeList(Volumes.ToArray()); }
/// <summary> /// Recursively builds the toc tree and fills the treeview /// </summary> /// <param name="tocItems">list of toc-items</param> /// <param name="col">treenode collection of the current level</param> /// <param name="filter">information type/category filter</param> private void BuildTOC(ArrayList tocItems, Collection <Node> nodes) { for (int i = 0; i < tocItems.Count; i++) { TOCItem curItem = (TOCItem)tocItems[i]; Node newNode = new Node(curItem.Name); newNode.Object = curItem; if (curItem.Children.Count > 0) { newNode.Image = hhImages.Images[0]; } else { newNode.Image = hhImages.Images[2]; } //newNode.Image = hhImages.Images[curItem.ImageIndex]; nodes.Add(newNode); if (curItem.Children.Count > 0) { BuildTOC(curItem.Children, newNode.Nodes); } // check if we have a book/folder which doesn't have any children // after applied filter. if ((curItem.Children.Count > 0) && (newNode.Nodes.Count <= 0)) { // check if the item has a local value // if not, this don't display this item in the tree if (curItem.Local.Length > 0) { nodes.Add(newNode); } } else { nodes.Add(newNode); } } }
/// <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, TOCItem parent, ArrayList 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)) { TOCItem p = ((TOCItem)(arrNodes[arrNodes.Count - 1])); ParseTree(innerText, p, p.Children, 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> /// Called if the user has collapsed a tree item /// </summary> /// <param name="sender">event sender</param> /// <param name="e">event parameter</param> private void tocTreeView_AfterCollapse(object sender, System.Windows.Forms.TreeViewEventArgs e) { TOCItem curItem = (TOCItem)(e.Node.Tag); if (curItem != null) { if (HtmlHelpSystem.UseHH2TreePics) { if (curItem.ImageIndex <= 15) { e.Node.ImageIndex = curItem.ImageIndex; e.Node.SelectedImageIndex = curItem.ImageIndex; } } else { if (curItem.ImageIndex < 8) { e.Node.ImageIndex = curItem.ImageIndex; e.Node.SelectedImageIndex = curItem.ImageIndex; } } } }
/// <summary> /// Recursively parses a sitemap tree /// </summary> /// <param name="text">content text</param> /// <param name="arrNodes">arraylist which receives the extracted nodes</param> /// <param name="chmFile">CHMFile instance</param> static private void ParseTree(ArrayList arrNodes, CHMFile chmFile) { bool bProcessing = true; do { bProcessing = false; // Indent int idxa = m_text1.IndexOf("<ul>", m_CurrentPos); int idxb = m_text1.IndexOf("<li>", m_CurrentPos); int idxc = m_text1.IndexOf("</ul>", m_CurrentPos); if ((idxa < idxb) && (idxa < idxc) && (idxa > -1)) { bProcessing = true; m_CurrentPos = idxa + 4; if (arrNodes.Count < 1) { ParseTree(arrNodes, chmFile); } else { ParseTree(((TOCItem)(arrNodes[arrNodes.Count - 1])).Children, chmFile); } continue; } // new item if ((idxb < idxa) && (idxb < idxc) && (idxb > -1)) { bProcessing = true; m_CurrentPos = idxb + 4; int idx2 = m_text1.IndexOf("<object", m_CurrentPos); if (idx2 != -1) { int idx3 = m_text1.IndexOf("</object>", idx2 + 7); if (idx3 != -1) { string text = m_text2.Substring(idx2, idx3 - idx2); m_CurrentPos = idx3 + 9; // Parse items in text. TOCItem tocItem = ParseItems(text, chmFile); if (tocItem != null) { arrNodes.Add(tocItem); } } } } // Undent if ((idxc < idxa) && (idxc < idxb) && (idxc > -1)) { m_CurrentPos = idxc + 5; bProcessing = true; return; } }while (bProcessing); }
/// <summary> /// Parses tree nodes from the text /// </summary> /// <param name="itemstext">text containing the items</param> /// <param name="arrNodes">arraylist where the nodes should be added</param> /// <param name="chmFile">CHMFile instance</param> private static TOCItem ParseItems(string itemstext, CHMFile chmFile) { int innerPTextIdx = ParamRE.GroupNumberFromName("innerText"); // get group-name indexes int nameIndex = AttributesRE.GroupNumberFromName("attributeName"); int valueIndex = AttributesRE.GroupNumberFromName("attributeValue"); int tdIndex = AttributesRE.GroupNumberFromName("attributeTD"); TOCItem tocItem = new TOCItem(); // read parameters int nParamIndex = 0; while (ParamRE.IsMatch(itemstext, nParamIndex)) { Match mP = ParamRE.Match(itemstext, nParamIndex); string innerP = mP.Groups[innerPTextIdx].Value; string paramName = ""; string paramValue = ""; int nAttrIdx = 0; 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 = attributeValue; } if (attributeName.ToLower() == "value") { paramValue = attributeValue; } nAttrIdx = mA.Index + mA.Length; } tocItem.Params[paramName] = paramValue; switch (paramName.ToLower()) { case "name": { tocItem.Name = paramValue; }; break; case "local": { tocItem.Local = paramValue; }; break; case "imagenumber": { tocItem.ImageIndex = Int32.Parse(paramValue); if (tocItem.ImageIndex == 2) { tocItem.ImageIndex = TOCItem.STD_FOLDER_HH1; } }; break; } nParamIndex = mP.Index + mP.Length; } tocItem.ChmFile = chmFile.ChmFilePath; return(tocItem); }
/// <summary> /// Standard constructor /// </summary> /// <param name="item">toc item associated with the event</param> public TocEventArgs(TOCItem item) { _tocItem = item; }
/// <summary> /// Parses tree nodes from the text /// </summary> /// <param name="itemstext">text containing the items</param> /// <param name="parent">Parent for all read items</param> /// <param name="arrNodes">arraylist where the nodes should be added</param> /// <param name="chmFile">CHMFile instance</param> private static void ParseItems(string itemstext, TOCItem parent, ArrayList 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; while (ObjectRE.IsMatch(itemstext, nObjStartIndex)) { Match m = ObjectRE.Match(itemstext, nObjStartIndex); string innerText = m.Groups[innerTextIdx].Value; TOCItem tocItem = new TOCItem(); tocItem.TocMode = DataMode.TextBased; tocItem.AssociatedFile = chmFile; tocItem.Parent = parent; // read parameters int nParamIndex = 0; while (ParamRE.IsMatch(innerText, nParamIndex)) { Match mP = ParamRE.Match(innerText, nParamIndex); string innerP = mP.Groups[innerPTextIdx].Value; string paramName = ""; string paramValue = ""; int nAttrIdx = 0; 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 } 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; } tocItem.Params[paramName] = paramValue; switch (paramName.ToLower()) { case "name": { tocItem.Name = paramValue; }; break; case "local": { tocItem.Local = paramValue.Replace("../", "").Replace("./", ""); }; break; case "imagenumber": { tocItem.ImageIndex = Int32.Parse(paramValue); tocItem.ImageIndex -= 1; int nFolderAdd = 0; if ((chmFile != null) && (chmFile.ImageTypeFolder)) { // get the value which should be added, to display folders instead of books if (HtmlHelpSystem.UseHH2TreePics) { nFolderAdd = 8; } else { nFolderAdd = 4; } } if (tocItem.ImageIndex % 2 != 0) { if (tocItem.ImageIndex == 1) { tocItem.ImageIndex = 0; } } if (HtmlHelpSystem.UseHH2TreePics) { if (tocItem.ImageIndex == 0) { tocItem.ImageIndex = TOCItem.STD_FOLDER_HH2 + nFolderAdd; } } }; break; case "merge": // this item contains topics or a full TOC from a merged CHM { tocItem.MergeLink = paramValue; // "register" this item as merge-link if (_mergeItems == null) { _mergeItems = new ArrayList(); } _mergeItems.Add(tocItem); }; break; case "type": // information type assignment for item { tocItem.InfoTypeStrings.Add(paramValue); }; break; } nParamIndex = mP.Index + mP.Length; } tocItem.ChmFile = chmFile.ChmFilePath; if (tocItem.MergeLink.Length > 0) { if (_lastTopicItem != null) { tocItem.Parent = _lastTopicItem; _lastTopicItem.Children.Add(tocItem); } else { arrNodes.Add(tocItem); } } else { _lastTopicItem = tocItem; arrNodes.Add(tocItem); } nObjStartIndex = m.Index + m.Length; } }
/// <summary> /// Decodes the binary file data and fills the internal properties /// </summary> /// <returns>true if succeeded</returns> private bool DecodeData() { _toc = new ArrayList(); _offsetTable = new Hashtable(); bool bRet = true; MemoryStream memStream = new MemoryStream(_binaryFileData); BinaryReader binReader = new BinaryReader(memStream); int nCurOffset = 0; _offset2028 = binReader.ReadInt32(); _offset16structs = binReader.ReadInt32(); _numberOf16structs = binReader.ReadInt32(); _offsetOftopics = binReader.ReadInt32(); binReader.BaseStream.Seek(_offset2028, SeekOrigin.Begin); if (RecursivelyBuildTree(ref binReader, _offset2028, _toc, null)) { binReader.BaseStream.Seek(_offset16structs, SeekOrigin.Begin); nCurOffset = (int)binReader.BaseStream.Position; for (int i = 0; i < _numberOf16structs; i++) { int tocOffset = binReader.ReadInt32(); int sqNr = binReader.ReadInt32(); int topOffset = binReader.ReadInt32(); int hhctopicIdx = binReader.ReadInt32(); nCurOffset = (int)binReader.BaseStream.Position; int topicIdx = -1; // if the topic offset is within the range of the stream // and is >= the offset of the first topic dword if ((topOffset < (binReader.BaseStream.Length - 4)) && (topOffset >= _offsetOftopics)) { // read the index of the topic for this item binReader.BaseStream.Seek(topOffset, SeekOrigin.Begin); topicIdx = binReader.ReadInt32(); binReader.BaseStream.Seek(nCurOffset, SeekOrigin.Begin); TOCItem item = (TOCItem)_offsetTable[tocOffset.ToString()]; if (item != null) { if ((topicIdx < _associatedFile.TopicsFile.TopicTable.Count) && (topicIdx >= 0)) { TopicEntry te = (TopicEntry)(_associatedFile.TopicsFile.TopicTable[topicIdx]); if ((te != null) && (item.TopicOffset < 0)) { item.TopicOffset = te.EntryOffset; } } } } } } return(bRet); }
/// <summary> /// Recursively reads the binary toc tree from the file /// </summary> /// <param name="binReader">reference to binary reader</param> /// <param name="NodeOffset">offset of the first node in the current level</param> /// <param name="level">arraylist of TOCItems for the current level</param> /// <param name="parentItem">parent item for the item</param> /// <returns>Returns true if succeeded</returns> private bool RecursivelyBuildTree(ref BinaryReader binReader, int NodeOffset, ArrayList level, TOCItem parentItem) { bool bRet = true; int nextOffset = 0; int nReadOffset = (int)binReader.BaseStream.Position; binReader.BaseStream.Seek(NodeOffset, SeekOrigin.Begin); do { int nCurOffset = (int)binReader.BaseStream.Position; int unkn1 = binReader.ReadInt16(); // unknown int unkn2 = binReader.ReadInt16(); // unknown int flag = binReader.ReadInt32(); int nFolderAdd = 0; if ((_associatedFile != null) && (_associatedFile.ImageTypeFolder)) { // get the value which should be added, to display folders instead of books if (HtmlHelpSystem.UseHH2TreePics) { nFolderAdd = 8; } else { nFolderAdd = 4; } } int nFolderImgIdx = (HtmlHelpSystem.UseHH2TreePics ? (TOCItem.STD_FOLDER_HH2 + nFolderAdd) : (TOCItem.STD_FOLDER_HH1 + nFolderAdd)); int nFileImgIdx = (HtmlHelpSystem.UseHH2TreePics ? TOCItem.STD_FILE_HH2 : TOCItem.STD_FILE_HH1); int stdImage = ((flag & 0x4) != 0) ? nFolderImgIdx : nFileImgIdx; int stringOffset = binReader.ReadInt32(); int ParentOffset = binReader.ReadInt32(); nextOffset = binReader.ReadInt32(); int firstChildOffset = 0; int unkn3 = 0; if ((flag & 0x4) != 0) { firstChildOffset = binReader.ReadInt32(); unkn3 = binReader.ReadInt32(); // unknown } TOCItem newItem = new TOCItem(); newItem.ImageIndex = stdImage; newItem.Offset = nCurOffset; newItem.OffsetNext = nextOffset; newItem.AssociatedFile = _associatedFile; newItem.TocMode = DataMode.Binary; newItem.Parent = parentItem; if ((flag & 0x08) == 0) { // toc item doesn't have a local value (=> stringOffset = offset of strings file) newItem.Name = _associatedFile.StringsFile[stringOffset]; } else { // this item has a topic entry (=> stringOffset = index of topic entry) if ((stringOffset < _associatedFile.TopicsFile.TopicTable.Count) && (stringOffset >= 0)) { TopicEntry te = (TopicEntry)(_associatedFile.TopicsFile.TopicTable[stringOffset]); if (te != null) { newItem.TopicOffset = te.EntryOffset; } } } _offsetTable[nCurOffset.ToString()] = newItem; // if this item has children (firstChildOffset > 0) if (firstChildOffset > 0) { bRet &= RecursivelyBuildTree(ref binReader, firstChildOffset, newItem.Children, newItem); } level.Add(newItem); if (nCurOffset != nextOffset) { binReader.BaseStream.Seek(nextOffset, SeekOrigin.Begin); } }while(nextOffset != 0); binReader.BaseStream.Seek(nReadOffset, SeekOrigin.Begin); 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: { IndexItem foundIdx = _reader.Index.SearchIndex(keyword, IndexType.AssiciativeLinks); if (foundIdx != null) { if (foundIdx.Topics.Count > 0) { IndexTopic topic = foundIdx.Topics[0] as IndexTopic; if (topic.Local.Length > 0) { NavigateBrowser(topic.URL); } } } }; break; case HelpNavigator.Find: { this.Cursor = Cursors.WaitCursor; this.helpSearch2.SetSearchText(keyword); DataTable dtResults = _reader.PerformSearch(keyword, 500, true, false); this.helpSearch2.SetResults(dtResults); this.Cursor = Cursors.Arrow; this.helpSearch2.Focus(); }; break; case HelpNavigator.Index: { ((IHelpViewer)this).ShowHelpIndex(url); }; break; case HelpNavigator.KeywordIndex: { IndexItem foundIdx = _reader.Index.SearchIndex(keyword, IndexType.KeywordLinks); if (foundIdx != null) { if (foundIdx.Topics.Count == 1) { IndexTopic topic = foundIdx.Topics[0] as IndexTopic; if (topic.Local.Length > 0) { NavigateBrowser(topic.URL); } } else if (foundIdx.Topics.Count > 1) { this.helpIndex1.SelectText(foundIdx.IndentKeyWord); } } this.helpIndex1.Focus(); }; break; case HelpNavigator.TableOfContents: { TOCItem foundTOC = _reader.TableOfContents.SearchTopic(keyword); if (foundTOC != null) { if (foundTOC.Local.Length > 0) { NavigateBrowser(foundTOC.Url); } } this.tocTree1.Focus(); }; break; case HelpNavigator.Topic: { TOCItem foundTOC = _reader.TableOfContents.SearchTopic(keyword); if (foundTOC != null) { if (foundTOC.Local.Length > 0) { NavigateBrowser(foundTOC.Url); } } }; break; } }