/// <summary> /// Removes a chm file from the internal file collection /// </summary> /// <param name="chmFile">full file path of the chm file to remove</param> public void RemoveFile(string chmFile) { int nIdx = -1; CHMFile removeInstance = null; foreach (CHMFile curFile in _chmFiles) { nIdx++; if (curFile.ChmFilePath.ToLower() == chmFile.ToLower()) { removeInstance = curFile; break; } } if (nIdx >= 0) { _toc.Clear(); // forces a rebuild of the merged toc _index.Clear(); // force a rebuild of the merged index RemoveFileInfoTypesCategories(removeInstance); _chmFiles.RemoveAt(nIdx); } }
/// <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) { DateTime StartTime = DateTime.Now; ArrayList tocList = new ArrayList(); m_text2 = hhcFile; m_text1 = hhcFile.ToLower(); int idx = m_text1.IndexOf("<ul>"); if (idx == -1) { return(null); } m_CurrentPos = idx + 4; ParamRE = new Regex(RE_ParamBoundaries, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); AttributesRE = new Regex(RE_QuoteAttributes, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); ParseTree(tocList, chmFile); DateTime EndTime = DateTime.Now; TimeSpan Diff = EndTime - StartTime; string x = Diff.ToString(); return(tocList); }
/// <summary> /// Constructor of the class used during binary data extraction /// </summary> /// <param name="topicOffset">offset of the associated topic entry</param> /// <param name="ImageIndex">image index to use</param> /// <param name="associatedFile">associated chm file</param> public TOCItem(int topicOffset, int ImageIndex, CHMFile associatedFile) { _tocMode = DataMode.Binary; _associatedFile = associatedFile; _chmFile = associatedFile.ChmFilePath; _topicOffset = topicOffset; _imageIndex = ImageIndex; }
/// <summary> /// Constructor of the class /// </summary> /// <param name="uniqueID">unique id</param> /// <param name="entryOffset">offset of the entry</param> /// <param name="topicIndex">topic index</param> /// <param name="urlstrOffset">urlstr offset for filename</param> /// <param name="associatedFile">associated chm file</param> internal UrlTableEntry(uint uniqueID, int entryOffset, int topicIndex, int urlstrOffset, CHMFile associatedFile) { _uniqueID = uniqueID; _entryOffset = entryOffset; _topicsIndex = topicIndex; _urlStrOffset = urlstrOffset; _associatedFile = associatedFile; }
/// <summary> /// Sets the associated CHMFile instance /// </summary> /// <param name="associatedFile">instance to set</param> internal void SetCHMFile(CHMFile associatedFile) { _associatedFile = associatedFile; foreach (TopicEntry curEntry in _topicTable) { curEntry.SetCHMFile(associatedFile); } }
/// <summary> /// Constructor of the class /// </summary> /// <param name="binaryFileData">binary file data of the #URLTBL file</param> /// <param name="associatedFile">associated chm file</param> public CHMUrltable(byte[] binaryFileData, CHMFile associatedFile) { _binaryFileData = binaryFileData; _associatedFile = associatedFile; DecodeData(); // clear internal binary data after extraction _binaryFileData = null; }
/// <summary> /// Sets the associated CHMFile instance /// </summary> /// <param name="associatedFile">instance to set</param> internal void SetCHMFile(CHMFile associatedFile) { _associatedFile = associatedFile; foreach (UrlTableEntry curEntry in _urlTable) { curEntry.SetCHMFile(associatedFile); } }
/// <summary> /// Internal constructor used in the class <see cref="HtmlHelp.ChmDecoding.CHMFile">CHMFile</see>. /// </summary> /// <param name="associatedFile">associated chm file</param> internal ChmFileInfo(CHMFile associatedFile) { _associatedFile = associatedFile; if (_associatedFile == null) { throw new ArgumentException("Associated CHMFile instance must not be null !", "associatedFile"); } }
/// <summary> /// Constructor of the class /// </summary> /// <param name="entryOffset">offset of this entry</param> /// <param name="tocidxOffset">offset in the binary toc index</param> /// <param name="titleOffset">offset of the title (in the #STRINGS file)</param> /// <param name="urltableOffset">offset in the urltable containing the urlstr offset for the url</param> /// <param name="visibilityMode">visibility mode 2 indicates not in contents, 6 indicates that it is in the contents, 0/4 something else (unknown)</param> /// <param name="unknownMode">0, 2, 4, 8, 10, 12, 16, 32 (unknown)</param> /// <param name="associatedFile">associated chmfile object</param> internal TopicEntry(int entryOffset, int tocidxOffset, int titleOffset, int urltableOffset, int visibilityMode, int unknownMode, CHMFile associatedFile) { _entryOffset = entryOffset; _tocidxOffset = tocidxOffset; _titleOffset = titleOffset; _urltableOffset = urltableOffset; _visibilityMode = visibilityMode; _unknownMode = unknownMode; _associatedFile = associatedFile; }
/// <summary> /// Constructor of the class /// </summary> /// <param name="binaryFileData">binary file data of the $FIftiMain file</param> /// <param name="associatedFile">associated chm file</param> public FullTextEngine(byte[] binaryFileData, CHMFile associatedFile) { _binaryFileData = binaryFileData; _associatedFile = associatedFile; if (_associatedFile.SystemFile.FullTextSearch) { _header = new FTHeader(_binaryFileData); // reading header } }
/// <summary> /// Reads the object data from a dump store /// </summary> /// <param name="reader">reader to read the data</param> /// <param name="filesList">filelist from helpsystem</param> internal bool ReadDump(ref BinaryReader reader, ArrayList filesList) { int i = 0; _keyWord = reader.ReadString(); _isSeeAlso = reader.ReadBoolean(); _indent = reader.ReadInt32(); _chmFileName = reader.ReadString(); foreach (CHMFile curFile in filesList) { if (curFile.ChmFilePath == _chmFileName) { _chmFile = curFile; break; } } if (_chmFile == null) { return(false); } int nCnt = reader.ReadInt32(); for (i = 0; i < nCnt; i++) { string sIT = reader.ReadString(); _infoTypeStrings.Add(sIT); } nCnt = reader.ReadInt32(); _seeAlso = new string[nCnt]; for (i = 0; i < nCnt; i++) { _seeAlso[i] = reader.ReadString(); } nCnt = reader.ReadInt32(); for (i = 0; i < nCnt; i++) { IndexTopic topic = new IndexTopic("", "", "", ""); topic.SetChmInfo(_chmFile.CompileFile, _chmFile.ChmFilePath); topic.AssociatedFile = _chmFile; topic.ReadDump(ref reader); Topics.Add(topic); } return(true); }
/// <summary> /// Constructor of the class /// </summary> /// <param name="chmFile">associated CHMFile instance</param> /// <param name="keyWord">keyword</param> /// <param name="isSeeAlso">true if it is a see-also keyword</param> /// <param name="indent">indent of the entry</param> /// <param name="charIndex">char index of the last keyword in the separated list</param> /// <param name="entryIndex">index of the entry</param> /// <param name="seeAlsoValues">string array with see-also values</param> /// <param name="topicOffsets">integer array with topic offsets</param> internal IndexItem(CHMFile chmFile, string keyWord, bool isSeeAlso, int indent, int charIndex, int entryIndex, string[] seeAlsoValues, int[] topicOffsets) { _chmFile = chmFile; _chmFileName = _chmFile.ChmFilePath; _keyWord = keyWord; _isSeeAlso = isSeeAlso; _indent = indent; _charIndex = charIndex; _entryIndex = entryIndex; _seeAlso = seeAlsoValues; _nTopics = topicOffsets; }
/// <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); }
/// <summary> /// Constructor of the class /// </summary> /// <param name="binaryFileData">binary file data of the #SYSTEM file</param> /// <param name="associatedFile">associated chm file</param> public CHMSystem(byte[] binaryFileData, CHMFile associatedFile) { _binaryFileData = binaryFileData; _associatedFile = associatedFile; DecodeData(); if (_culture == null) { // Set the text encoder of the chm file to the read charset/codepage _associatedFile.TextEncoding = Encoding.GetEncoding(this.CodePage); } }
/// <summary> /// Opens a chm file and creates /// </summary> /// <param name="chmFile">full file path of the chm file to open</param> /// <param name="dmpInfo">dumping info</param> /// <remarks>If you call this method, all existing merged files will be cleared.</remarks> public void OpenFile(string chmFile, DumpingInfo dmpInfo) { if (File.Exists(chmFile)) { _chmFiles.Clear(); _toc.Clear(); _index.Clear(); _informationTypes.Clear(); _categories.Clear(); CHMFile newFile = new CHMFile(this, chmFile, dmpInfo); _toc = new HtmlHelpToc(newFile.TOC); _index = new HtmlHelpIndex(newFile.IndexKLinks, newFile.IndexALinks); _chmFiles.Add(newFile); // add all infotypes and categories of the read file to this system instance MergeFileInfoTypesCategories(newFile); // check if the file has a merged files list if (newFile.MergedFiles.Length > 0) { // extract the path of the chm file (usually merged files are in the same path) FileInfo fi = new FileInfo(chmFile); string sPath = fi.DirectoryName; for (int i = 0; i < newFile.MergedFiles.Length; i++) { string sFile = newFile.MergedFiles[i]; if (sFile.Length > 0) { if (sFile[1] != ':') // no full path setting { sFile = Path.Combine(sPath, sFile); } MergeFile(sFile, dmpInfo, true); } } if (newFile.MergLinks.Count > 0) { RecalculateMergeLinks(newFile); } RemoveMergeLinks(); // clear all merge-links which have no target ! } } }
/// <summary> /// Constructor of the class /// </summary> /// <param name="binaryFileData">binary file data of the $WWKeywordLinks/BTree file</param> /// <param name="associatedFile">associated chm file</param> public CHMBtree(byte[] binaryFileData, CHMFile associatedFile) { if (associatedFile == null) { throw new ArgumentException("CHMBtree.ctor() - Associated CHMFile must not be null !", "associatedFile"); } _binaryFileData = binaryFileData; _associatedFile = associatedFile; DecodeData(); // clear internal binary data after extraction _binaryFileData = null; }
/// <summary> /// Constructor for extrating the file information of the provided file. /// The constructor opens the chm-file and reads its system data. /// </summary> /// <param name="chmFile">full file name which information should be extracted</param> public ChmFileInfo(string chmFile) { if (!File.Exists(chmFile)) { throw new ArgumentException("Chm file must exist on disk !", "chmFileName"); } if (!chmFile.ToLower().EndsWith(".chm")) { throw new ArgumentException("HtmlHelp file must have the extension .chm !", "chmFile"); } _chmFileName = chmFile; _associatedFile = new CHMFile(null, chmFile, true); // only load system data of chm }
/// <summary> /// Closes all files and destroys TOC/index /// </summary> public void CloseAllFiles() { for (int i = 0; i < _chmFiles.Count; i++) { CHMFile curFile = _chmFiles[i]; _chmFiles.RemoveAt(i); curFile.Dispose(); i--; } _chmFiles.Clear(); _toc.Clear(); _index.Clear(); _informationTypes.Clear(); _categories.Clear(); }
/// <summary> /// Reads the object data from a dump store /// </summary> /// <param name="reader">reader to read the data</param> /// <param name="chmFile">current CHMFile instance which reads from dump</param> internal void ReadDump(ref BinaryReader reader, CHMFile chmFile) { _name = reader.ReadString(); _description = reader.ReadString(); int nCnt = reader.ReadInt32(); for (int i = 0; i < nCnt; i++) { string sITName = reader.ReadString(); InformationType linkedType = chmFile.GetInformationType(sITName); if (linkedType != null) { linkedType.SetCategoryFlag(true); _infoTypes.Add(linkedType); } } }
/// <summary> /// Removes the information types and categories read by the CHMFile instance /// </summary> /// <param name="chmFile">file instance</param> private void RemoveFileInfoTypesCategories(CHMFile chmFile) { if (chmFile.HasInformationTypes) { for (int i = 0; i < chmFile.InformationTypes.Count; i++) { InformationType curType = chmFile.InformationTypes[i]; InformationType sysType = GetInformationType(curType.Name); if (sysType != null) { sysType.ReferenceCount--; if (sysType.ReferenceCount <= 0) { _informationTypes.Remove(sysType); } } } } if (chmFile.HasCategories) { for (int i = 0; i < chmFile.Categories.Count; i++) { Category curCat = chmFile.Categories[i]; Category sysCat = GetCategory(curCat.Name); if (sysCat != null) { sysCat.ReferenceCount--; if (sysCat.ReferenceCount <= 0) { _categories.Remove(sysCat); } } } } }
/// <summary> /// Parses a HHK file and returns an list with the index tree /// </summary> /// <param name="hhkFile">string content of the hhk file</param> /// <param name="chmFile">CHMFile instance</param> /// <returns>Returns an list with the index tree</returns> public static List <HtmlHelpIndexItem> ParseHHK(string hhkFile, CHMFile chmFile) { List <HtmlHelpIndexItem> indexList = new List <HtmlHelpIndexItem>(); 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(hhkFile, 0)) { Match m = ulRE.Match(hhkFile, 0); if (ObjectRE.IsMatch(hhkFile, 0)) // first object block contains information types and categories { Match mO = ObjectRE.Match(hhkFile, 0); int iOTxt = ObjectRE.GroupNumberFromName("innerText"); string globalText = mO.Groups[iOTxt].Value; ParseGlobalSettings(globalText, chmFile); } 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, indexList, chmFile); } return(indexList); }
/// <summary> /// Checks if the hhc file contains a global object tag. /// </summary> /// <param name="hhcFile">string content of the hhc file</param> /// <param name="chmFile">chm file</param> /// <returns>true if the hhc content contains a global object tag</returns> public static bool HasGlobalObjectTag(string hhcFile, CHMFile chmFile) { bool bRet = false; ulRE = new Regex(RE_ULBoundaries, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); ObjectRE = new Regex(RE_ObjectBoundaries, 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) { bRet = true; } } } return(bRet); }
/// <summary> /// Merges the information types and categories read by the CHMFile instance /// into the system instance /// </summary> /// <param name="chmFile">file instance</param> private void MergeFileInfoTypesCategories(CHMFile chmFile) { if (chmFile.HasInformationTypes) { for (int i = 0; i < chmFile.InformationTypes.Count; i++) { InformationType curType = chmFile.InformationTypes[i]; InformationType sysType = GetInformationType(curType.Name); if (sysType == null) { _informationTypes.Add(curType); } else { curType.ReferenceCount++; } } } if (chmFile.HasCategories) { for (int i = 0; i < chmFile.Categories.Count; i++) { Category curCat = chmFile.Categories[i]; Category sysCat = GetCategory(curCat.Name); if (sysCat == null) { _categories.Add(curCat); } else { curCat.ReferenceCount++; } } } }
/// <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> /// Merges a chm file to the current help contents /// </summary> /// <param name="chmFile">full file path of the chm file to merge</param> /// <param name="dmpInfo">dumping info</param> /// <param name="mergedFileList">true if the merge is done because a merged file list /// was found in the previously loaded CHM.</param> internal void MergeFile(string chmFile, DumpingInfo dmpInfo, bool mergedFileList) { if (File.Exists(chmFile)) { if (_chmFiles.Count == 1) { // if we open the first file, we directly point into the toc and index of this file. // So that we don't merge the new toc's indexe's into the first file, we have to // clone the internal arraylists first to a new instance of the toc/index holder classes. IList <HtmlHelpTocItem> atoc = _toc.TOC; IList <HtmlHelpIndexItem> alinks = _index.ALinks; IList <HtmlHelpIndexItem> klinks = _index.KLinks; _toc = new HtmlHelpToc(); _index = new HtmlHelpIndex(); _toc.MergeToC(atoc); _index.MergeIndex(alinks, IndexType.AssiciativeLinks); _index.MergeIndex(klinks, IndexType.KeywordLinks); } CHMFile newFile = new CHMFile(this, chmFile, dmpInfo); if (mergedFileList) // if we've called this method due to a merged file list merge { RecalculateMergeLinks(newFile); _toc.MergeToC(newFile.TOC, _chmFiles); _index.MergeIndex(newFile.IndexALinks, IndexType.AssiciativeLinks); _index.MergeIndex(newFile.IndexKLinks, IndexType.KeywordLinks); _chmFiles.Add(newFile); // add all infotypes and categories of the read file to this system instance MergeFileInfoTypesCategories(newFile); } else { _toc.MergeToC(newFile.TOC, _chmFiles); _index.MergeIndex(newFile.IndexALinks, IndexType.AssiciativeLinks); _index.MergeIndex(newFile.IndexKLinks, IndexType.KeywordLinks); _chmFiles.Add(newFile); // add all infotypes and categories of the read file to this system instance MergeFileInfoTypesCategories(newFile); // check if the file has a merged files list if (newFile.MergedFiles.Length > 0) { // extract the path of the chm file (usually merged files are in the same path) FileInfo fi = new FileInfo(chmFile); string sPath = fi.DirectoryName; for (int i = 0; i < newFile.MergedFiles.Length; i++) { string sFile = newFile.MergedFiles[i]; if (sFile.Length > 0) { if (sFile[1] != ':') // no full path setting { sFile = Path.Combine(sPath, sFile); } MergeFile(sFile, dmpInfo, true); } } //if(newFile.MergLinks.Count > 0) // RecalculateMergeLinks(newFile); RemoveMergeLinks(); // clear all merge-links which have no target ! } } } }
/// <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> /// Checks all Merg-links read till now. Checks if the merg-link points to the /// file <c>currentFile</c>. If yes the link will be replaced by the contents of the /// merged file. /// </summary> /// <param name="currentFile">Current CHMFile instance</param> internal void RecalculateMergeLinks(CHMFile currentFile) { foreach (CHMFile curFile in _chmFiles) { if (curFile.MergLinks.Count > 0) { for (int i = 0; i < curFile.MergLinks.Count; i++) { HtmlHelpTocItem curItem = curFile.MergLinks[i] as HtmlHelpTocItem; string sMerge = curItem.MergeLink; string [] sSplit = sMerge.Split(new char[] { ':' }); string sFName = ""; string sTarget = ""; if (sSplit.Length > 3) // merge info contains path name { sFName = sSplit[0] + ":" + sSplit[1]; sTarget = sSplit[3]; } else if (sSplit.Length == 3) // merge info contains only file name { FileInfo fi = new FileInfo(currentFile.ChmFilePath); string sPath = fi.DirectoryName; string sFile = sSplit[0]; if (sFile.Length > 0) { if (sFile[1] != ':') // no full path setting { sFile = Path.Combine(sPath, sFile); } } sFName = sFile; sTarget = sSplit[2]; } List <HtmlHelpTocItem> arrToc = null; if ((sFName.Length > 0) && (sTarget.Length > 0)) { // if this link points into the current file if (sFName.ToLower() == currentFile.ChmFilePath.ToLower()) { if (sTarget.ToLower().IndexOf(".hhc") >= 0) { string sfCheck = sTarget; // remove prefixing ./ while ((sfCheck[0] == '.') || (sfCheck[0] == '/')) { sfCheck = sfCheck.Substring(1); } if (currentFile.ContentsFile.ToLower() != sfCheck) { arrToc = currentFile.ParseHHC(sTarget); if (arrToc.Count > 0) { } } else { arrToc = currentFile.TOC; } // target points to a complete TOC int nCnt = 0; foreach (HtmlHelpTocItem chkItem in arrToc) { if (nCnt == 0) { curItem.AssociatedFile = currentFile; curItem.Children = chkItem.Children; curItem.ChmFile = currentFile.ChmFilePath; curItem.ImageIndex = chkItem.ImageIndex; curItem.Local = chkItem.Local; curItem.MergeLink = chkItem.MergeLink; curItem.Name = chkItem.Name; curItem.TocMode = chkItem.TocMode; curItem.TopicOffset = chkItem.TopicOffset; MarkChildrenAdded(chkItem.Children, curFile.MergLinks); } else { IList <HtmlHelpTocItem> checkList = null; if (curItem.Parent != null) { checkList = curItem.Parent.Children; } else { checkList = curFile.TOC; } int nIdx = checkList.IndexOf(curItem); if ((nIdx + nCnt) > checkList.Count) { checkList.Add(chkItem); } else { checkList.Insert(nIdx + nCnt, chkItem); } curFile.MergLinks.Add(chkItem); MarkChildrenAdded(chkItem.Children, curFile.MergLinks); } nCnt++; } } else { // target points to a single topic HtmlHelpTocItem chkItem = currentFile.GetTOCItemByLocal(sTarget); if (chkItem != null) { curItem.AssociatedFile = currentFile; curItem.Children = chkItem.Children; curItem.ChmFile = currentFile.ChmFilePath; curItem.ImageIndex = chkItem.ImageIndex; curItem.Local = chkItem.Local; curItem.MergeLink = chkItem.MergeLink; curItem.Name = chkItem.Name; curItem.TocMode = chkItem.TocMode; curItem.TopicOffset = chkItem.TopicOffset; curFile.MergLinks.Add(chkItem); MarkChildrenAdded(chkItem.Children, curFile.MergLinks); } } } } } } } }
/// <summary> /// Creates a new instance of the class (binary extraction mode) /// </summary> /// <param name="topicOffset">offset of the topic entry</param> /// <param name="associatedFile">associated CHMFile instance</param> internal IndexTopic(int topicOffset, CHMFile associatedFile) { _topicMode = DataMode.Binary; _topicOffset = topicOffset; _associatedFile = associatedFile; }
/// <summary> /// Sets the associated CHMFile instance /// </summary> /// <param name="associatedFile">instance to set</param> internal void SetCHMFile(CHMFile associatedFile) { _associatedFile = associatedFile; }
/// <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); }