Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Documents / FixedFindEngine.cs / 1305600 / FixedFindEngine.cs
//---------------------------------------------------------------------------- //// Copyright (C) 2004 by Microsoft Corporation. All rights reserved. // // // Description: // Implements fast, paginated search functionality for Fixed documents // // // History: // 03/13/2006 AGurcan - Created // //--------------------------------------------------------------------------- namespace System.Windows.Documents { using System; using System.IO; using System.Xml; using System.Text; using System.Globalization; using System.Diagnostics; using System.Windows.Markup; internal sealed class FixedFindEngine { //Searches for the specified pattern and updates start *or* end pointers depending on search direction //At the end of the operation, start or end should be pointing to the beginning/end of the page //of occurance of pattern respectively internal static TextRange Find ( ITextPointer start, ITextPointer end, string findPattern, CultureInfo cultureInfo, bool matchCase, bool matchWholeWord, bool matchLast, bool matchDiacritics, bool matchKashida, bool matchAlefHamza) { Debug.Assert(start != null); Debug.Assert(end != null); Debug.Assert( ((start is DocumentSequenceTextPointer) && (end is DocumentSequenceTextPointer)) || ((start is FixedTextPointer) && (end is FixedTextPointer)) ); Debug.Assert(findPattern != null); if (findPattern.Length == 0) { return null; } IDocumentPaginatorSource paginatorSource = start.TextContainer.Parent as IDocumentPaginatorSource; DynamicDocumentPaginator paginator = paginatorSource.DocumentPaginator as DynamicDocumentPaginator; Debug.Assert(paginator != null); int pageNumber = -1; int endPageNumber = -1; if (matchLast) { endPageNumber = paginator.GetPageNumber( (ContentPosition) start); pageNumber = paginator.GetPageNumber( (ContentPosition) end); } else { endPageNumber = paginator.GetPageNumber( (ContentPosition) end); pageNumber = paginator.GetPageNumber( (ContentPosition) start); } TextRange result = null; CompareInfo compareInfo = cultureInfo.CompareInfo; bool replaceAlefWithAlefHamza = false; CompareOptions compareOptions = _InitializeSearch(cultureInfo, matchCase, matchAlefHamza, matchDiacritics, ref findPattern, out replaceAlefWithAlefHamza); //Translate the page number int translatedPageNumber = pageNumber; //If this is a DocumentSequence, we need to pass translated page number to the below call FixedDocumentSequence documentSequence = paginatorSource as FixedDocumentSequence; DynamicDocumentPaginator childPaginator = null; if (documentSequence != null) { documentSequence.TranslatePageNumber(pageNumber, out childPaginator, out translatedPageNumber); } if (pageNumber - endPageNumber != 0) { ITextPointer firstSearchPageStart = null; ITextPointer firstSearchPageEnd = null; _GetFirstPageSearchPointers(start, end, translatedPageNumber, matchLast, out firstSearchPageStart, out firstSearchPageEnd); Debug.Assert(firstSearchPageStart != null); Debug.Assert(firstSearchPageEnd != null); //Need to search the first page using TextFindEngine to start exactly from the requested search location to avoid false positives result = TextFindEngine.InternalFind( firstSearchPageStart, firstSearchPageEnd, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza); if (result == null) { //Start from the next page and check all pages until the end pageNumber = matchLast ? pageNumber-1 : pageNumber+1; int increment = matchLast ? -1 : 1; for (; matchLast ? pageNumber >= endPageNumber : pageNumber <= endPageNumber; pageNumber+=increment) { FixedDocument fixedDoc = null; translatedPageNumber = pageNumber; childPaginator = null; if (documentSequence != null) { documentSequence.TranslatePageNumber(pageNumber, out childPaginator, out translatedPageNumber); fixedDoc = (FixedDocument) childPaginator.Source; } else { fixedDoc = paginatorSource as FixedDocument; } Debug.Assert(fixedDoc != null); String pageString = _GetPageString(fixedDoc, translatedPageNumber, replaceAlefWithAlefHamza); if (pageString == null) { //This is not a page-per-stream //Default back to slow search return TextFindEngine.InternalFind( start, end, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza); } if ( _FoundOnPage(pageString, findPattern, cultureInfo, compareOptions) ) { //Update end or start pointer depending on search direction if (documentSequence != null) { ChildDocumentBlock childBlock = documentSequence.TextContainer.FindChildBlock(fixedDoc.DocumentReference); if (matchLast) { end = new DocumentSequenceTextPointer(childBlock, new FixedTextPointer(false, LogicalDirection.Backward, fixedDoc.FixedContainer.FixedTextBuilder.GetPageEndFlowPosition(translatedPageNumber))); start = new DocumentSequenceTextPointer(childBlock, new FixedTextPointer(false, LogicalDirection.Forward, fixedDoc.FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(translatedPageNumber))); } else { start = new DocumentSequenceTextPointer(childBlock, new FixedTextPointer(false, LogicalDirection.Forward, fixedDoc.FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(translatedPageNumber))); end = new DocumentSequenceTextPointer(childBlock, new FixedTextPointer(false, LogicalDirection.Backward, fixedDoc.FixedContainer.FixedTextBuilder.GetPageEndFlowPosition(translatedPageNumber))); } } else { //We are working on a FixedDocument FixedTextBuilder textBuilder = ((FixedDocument)(paginatorSource)).FixedContainer.FixedTextBuilder; if (matchLast) { end = new FixedTextPointer(false, LogicalDirection.Backward, textBuilder.GetPageEndFlowPosition(pageNumber)); start = new FixedTextPointer(false, LogicalDirection.Forward, textBuilder.GetPageStartFlowPosition(pageNumber)); } else { start = new FixedTextPointer(false, LogicalDirection.Forward, textBuilder.GetPageStartFlowPosition(pageNumber)); end = new FixedTextPointer(false, LogicalDirection.Backward, textBuilder.GetPageEndFlowPosition(pageNumber)); } } result = TextFindEngine.InternalFind( start, end, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza); //If the result is null, this means we had a false positive if (result != null) { return result; } } } } } else { //Make sure fast search result and slow search result are consistent FixedDocument fixedDoc = childPaginator != null ? childPaginator.Source as FixedDocument : paginatorSource as FixedDocument; String pageString = _GetPageString(fixedDoc, translatedPageNumber, replaceAlefWithAlefHamza); if (pageString == null || _FoundOnPage(pageString, findPattern, cultureInfo, compareOptions)) { //The search is only limited to the current page result = TextFindEngine.InternalFind( start, end, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza); } } return result; } private static bool _FoundOnPage(string pageString, string findPattern, CultureInfo cultureInfo, CompareOptions compareOptions) { CompareInfo compareInfo = cultureInfo.CompareInfo; //We don't need to use LastIndexOf in this function even if mathcLast is true because //we are only trying to determine whether the pattern exists on a specific page or not. //Exact location will be determined in TextFindEngine.InternalFind string[] tokens = findPattern.Split(null); if (tokens != null) { foreach (string token in tokens) { if (!String.IsNullOrEmpty(token) && compareInfo.IndexOf(pageString, token, compareOptions) == -1) { return false; } } } return true; } private static CompareOptions _InitializeSearch (CultureInfo cultureInfo, bool matchCase, bool matchAlefHamza, bool matchDiacritics, ref string findPattern, out bool replaceAlefWithAlefHamza) { CompareOptions compareOptions = CompareOptions.None; replaceAlefWithAlefHamza = false; if (!matchCase) { compareOptions |= CompareOptions.IgnoreCase; } bool stringContainedBidiCharacter; bool stringContainedAlefCharacter; // Initialize Bidi flags whether the string contains the bidi characters // or alef character. TextFindEngine.InitializeBidiFlags( findPattern, out stringContainedBidiCharacter, out stringContainedAlefCharacter); if (stringContainedAlefCharacter && !matchAlefHamza) { // Replace the alef-hamza with the alef. findPattern = TextFindEngine.ReplaceAlefHamzaWithAlef(findPattern); replaceAlefWithAlefHamza = true; } // Ignore Bidi diacritics that use for only Bidi language. if (!matchDiacritics && stringContainedBidiCharacter) { // Ignore Bidi diacritics with checking non-space character. compareOptions |= CompareOptions.IgnoreNonSpace; } return compareOptions; } private static void _GetFirstPageSearchPointers ( ITextPointer start, ITextPointer end, int pageNumber, bool matchLast, out ITextPointer firstSearchPageStart, out ITextPointer firstSearchPageEnd) { if (matchLast) { //The page in question is the last page //Need to search between the start of the last page and the end pointer DocumentSequenceTextPointer endAsDSTP = end as DocumentSequenceTextPointer; if (endAsDSTP != null) { FlowPosition pageStartFlowPosition = ((FixedTextContainer)(endAsDSTP.ChildBlock.ChildContainer)).FixedTextBuilder.GetPageStartFlowPosition(pageNumber); firstSearchPageStart = new DocumentSequenceTextPointer(endAsDSTP.ChildBlock, new FixedTextPointer(false, LogicalDirection.Forward,pageStartFlowPosition)); } else { FixedTextPointer endAsFTP = end as FixedTextPointer; Debug.Assert(endAsFTP != null); firstSearchPageStart = new FixedTextPointer(false, LogicalDirection.Forward, endAsFTP.FixedTextContainer.FixedTextBuilder.GetPageStartFlowPosition(pageNumber)); } firstSearchPageEnd = end; } else { //The page in question is the first page //Need to search between the start pointer and the end of the first page DocumentSequenceTextPointer startAsDSTP = start as DocumentSequenceTextPointer; if (startAsDSTP != null) { FlowPosition pageEndFlowPosition = ((FixedTextContainer)startAsDSTP.ChildBlock.ChildContainer).FixedTextBuilder.GetPageEndFlowPosition(pageNumber); firstSearchPageEnd = new DocumentSequenceTextPointer( startAsDSTP.ChildBlock, new FixedTextPointer(false, LogicalDirection.Backward, pageEndFlowPosition)); } else { FixedTextPointer startAsFTP = start as FixedTextPointer; Debug.Assert(startAsFTP != null); firstSearchPageEnd = new FixedTextPointer(false, LogicalDirection.Backward, startAsFTP.FixedTextContainer.FixedTextBuilder.GetPageEndFlowPosition(pageNumber)); } firstSearchPageStart = start; } } private static String _GetPageString(FixedDocument doc, int translatedPageNo, bool replaceAlefWithAlefHamza) { String pageString = null; Debug.Assert(doc != null); Debug.Assert(translatedPageNo >= 0 && translatedPageNo < doc.PageCount); PageContent pageContent = doc.Pages[translatedPageNo]; Stream pageStream = pageContent.GetPageStream(); bool reverseRTL = true; if (doc.HasExplicitStructure) { reverseRTL = false; } if (pageStream != null) { pageString = _ConstructPageString(pageStream, reverseRTL); if (replaceAlefWithAlefHamza) { // Replace the alef-hamza with the alef. pageString = TextFindEngine.ReplaceAlefHamzaWithAlef(pageString); } } return pageString; } private static String _ConstructPageString(Stream pageStream, bool reverseRTL) { Debug.Assert(pageStream != null); XmlTextReader xmlTextReader = new XmlTextReader(pageStream); //Wrap around a compatibility reader XmlReader xmlReader = new XmlCompatibilityReader(xmlTextReader, _predefinedNamespaces); XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreWhitespace = true; settings.IgnoreComments = true; settings.ProhibitDtd = true; xmlReader = XmlReader.Create(xmlReader, settings); xmlReader.MoveToContent(); StringBuilder pageString = new StringBuilder(); bool isSideways = false; string unicodeStr = null; while (xmlReader.Read()) { switch (xmlReader.NodeType) { case XmlNodeType.Element: { if (xmlReader.Name == "Glyphs") { unicodeStr = xmlReader.GetAttribute("UnicodeString"); if (!String.IsNullOrEmpty(unicodeStr)) { string sidewaysString = xmlReader.GetAttribute("IsSideways"); isSideways = false; if (sidewaysString != null && String.Compare(sidewaysString, Boolean.TrueString, StringComparison.OrdinalIgnoreCase) == 0) { isSideways = true; } if (reverseRTL) { //This is to cover for MXDW generation //RTL Glyphs are saved LTR and bidi level is not set //In this case we need to reverse the UnicodeString string bidiLevelAsString = xmlReader.GetAttribute("BidiLevel"); int bidiLevel = 0; if (!String.IsNullOrEmpty(bidiLevelAsString)) { try { bidiLevel = Convert.ToInt32(bidiLevelAsString, CultureInfo.InvariantCulture); } catch (Exception) { } } string caretStops = xmlReader.GetAttribute("CaretStops"); if (bidiLevel == 0 && !isSideways && String.IsNullOrEmpty(caretStops) && FixedTextBuilder.MostlyRTL(unicodeStr)) { char[] chars = unicodeStr.ToCharArray(); Array.Reverse(chars); unicodeStr = new String(chars); } } pageString.Append(unicodeStr); } } } break; } } return pageString.ToString(); } //Private constructor to prevent the compiler from generating a default constructor (fxcop) private FixedFindEngine() { } static private string [] _predefinedNamespaces = new string [2] { "http://schemas.microsoft.com/xps/2005/06", XamlReaderHelper.DefinitionMetroNamespaceURI }; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- //// Copyright (C) 2004 by Microsoft Corporation. All rights reserved. // // // Description: // Implements fast, paginated search functionality for Fixed documents // // // History: // 03/13/2006 AGurcan - Created // //--------------------------------------------------------------------------- namespace System.Windows.Documents { using System; using System.IO; using System.Xml; using System.Text; using System.Globalization; using System.Diagnostics; using System.Windows.Markup; internal sealed class FixedFindEngine { //Searches for the specified pattern and updates start *or* end pointers depending on search direction //At the end of the operation, start or end should be pointing to the beginning/end of the page //of occurance of pattern respectively internal static TextRange Find ( ITextPointer start, ITextPointer end, string findPattern, CultureInfo cultureInfo, bool matchCase, bool matchWholeWord, bool matchLast, bool matchDiacritics, bool matchKashida, bool matchAlefHamza) { Debug.Assert(start != null); Debug.Assert(end != null); Debug.Assert( ((start is DocumentSequenceTextPointer) && (end is DocumentSequenceTextPointer)) || ((start is FixedTextPointer) && (end is FixedTextPointer)) ); Debug.Assert(findPattern != null); if (findPattern.Length == 0) { return null; } IDocumentPaginatorSource paginatorSource = start.TextContainer.Parent as IDocumentPaginatorSource; DynamicDocumentPaginator paginator = paginatorSource.DocumentPaginator as DynamicDocumentPaginator; Debug.Assert(paginator != null); int pageNumber = -1; int endPageNumber = -1; if (matchLast) { endPageNumber = paginator.GetPageNumber( (ContentPosition) start); pageNumber = paginator.GetPageNumber( (ContentPosition) end); } else { endPageNumber = paginator.GetPageNumber( (ContentPosition) end); pageNumber = paginator.GetPageNumber( (ContentPosition) start); } TextRange result = null; CompareInfo compareInfo = cultureInfo.CompareInfo; bool replaceAlefWithAlefHamza = false; CompareOptions compareOptions = _InitializeSearch(cultureInfo, matchCase, matchAlefHamza, matchDiacritics, ref findPattern, out replaceAlefWithAlefHamza); //Translate the page number int translatedPageNumber = pageNumber; //If this is a DocumentSequence, we need to pass translated page number to the below call FixedDocumentSequence documentSequence = paginatorSource as FixedDocumentSequence; DynamicDocumentPaginator childPaginator = null; if (documentSequence != null) { documentSequence.TranslatePageNumber(pageNumber, out childPaginator, out translatedPageNumber); } if (pageNumber - endPageNumber != 0) { ITextPointer firstSearchPageStart = null; ITextPointer firstSearchPageEnd = null; _GetFirstPageSearchPointers(start, end, translatedPageNumber, matchLast, out firstSearchPageStart, out firstSearchPageEnd); Debug.Assert(firstSearchPageStart != null); Debug.Assert(firstSearchPageEnd != null); //Need to search the first page using TextFindEngine to start exactly from the requested search location to avoid false positives result = TextFindEngine.InternalFind( firstSearchPageStart, firstSearchPageEnd, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza); if (result == null) { //Start from the next page and check all pages until the end pageNumber = matchLast ? pageNumber-1 : pageNumber+1; int increment = matchLast ? -1 : 1; for (; matchLast ? pageNumber >= endPageNumber : pageNumber <= endPageNumber; pageNumber+=increment) { FixedDocument fixedDoc = null; translatedPageNumber = pageNumber; childPaginator = null; if (documentSequence != null) { documentSequence.TranslatePageNumber(pageNumber, out childPaginator, out translatedPageNumber); fixedDoc = (FixedDocument) childPaginator.Source; } else { fixedDoc = paginatorSource as FixedDocument; } Debug.Assert(fixedDoc != null); String pageString = _GetPageString(fixedDoc, translatedPageNumber, replaceAlefWithAlefHamza); if (pageString == null) { //This is not a page-per-stream //Default back to slow search return TextFindEngine.InternalFind( start, end, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza); } if ( _FoundOnPage(pageString, findPattern, cultureInfo, compareOptions) ) { //Update end or start pointer depending on search direction if (documentSequence != null) { ChildDocumentBlock childBlock = documentSequence.TextContainer.FindChildBlock(fixedDoc.DocumentReference); if (matchLast) { end = new DocumentSequenceTextPointer(childBlock, new FixedTextPointer(false, LogicalDirection.Backward, fixedDoc.FixedContainer.FixedTextBuilder.GetPageEndFlowPosition(translatedPageNumber))); start = new DocumentSequenceTextPointer(childBlock, new FixedTextPointer(false, LogicalDirection.Forward, fixedDoc.FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(translatedPageNumber))); } else { start = new DocumentSequenceTextPointer(childBlock, new FixedTextPointer(false, LogicalDirection.Forward, fixedDoc.FixedContainer.FixedTextBuilder.GetPageStartFlowPosition(translatedPageNumber))); end = new DocumentSequenceTextPointer(childBlock, new FixedTextPointer(false, LogicalDirection.Backward, fixedDoc.FixedContainer.FixedTextBuilder.GetPageEndFlowPosition(translatedPageNumber))); } } else { //We are working on a FixedDocument FixedTextBuilder textBuilder = ((FixedDocument)(paginatorSource)).FixedContainer.FixedTextBuilder; if (matchLast) { end = new FixedTextPointer(false, LogicalDirection.Backward, textBuilder.GetPageEndFlowPosition(pageNumber)); start = new FixedTextPointer(false, LogicalDirection.Forward, textBuilder.GetPageStartFlowPosition(pageNumber)); } else { start = new FixedTextPointer(false, LogicalDirection.Forward, textBuilder.GetPageStartFlowPosition(pageNumber)); end = new FixedTextPointer(false, LogicalDirection.Backward, textBuilder.GetPageEndFlowPosition(pageNumber)); } } result = TextFindEngine.InternalFind( start, end, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza); //If the result is null, this means we had a false positive if (result != null) { return result; } } } } } else { //Make sure fast search result and slow search result are consistent FixedDocument fixedDoc = childPaginator != null ? childPaginator.Source as FixedDocument : paginatorSource as FixedDocument; String pageString = _GetPageString(fixedDoc, translatedPageNumber, replaceAlefWithAlefHamza); if (pageString == null || _FoundOnPage(pageString, findPattern, cultureInfo, compareOptions)) { //The search is only limited to the current page result = TextFindEngine.InternalFind( start, end, findPattern, cultureInfo, matchCase, matchWholeWord, matchLast, matchDiacritics, matchKashida, matchAlefHamza); } } return result; } private static bool _FoundOnPage(string pageString, string findPattern, CultureInfo cultureInfo, CompareOptions compareOptions) { CompareInfo compareInfo = cultureInfo.CompareInfo; //We don't need to use LastIndexOf in this function even if mathcLast is true because //we are only trying to determine whether the pattern exists on a specific page or not. //Exact location will be determined in TextFindEngine.InternalFind string[] tokens = findPattern.Split(null); if (tokens != null) { foreach (string token in tokens) { if (!String.IsNullOrEmpty(token) && compareInfo.IndexOf(pageString, token, compareOptions) == -1) { return false; } } } return true; } private static CompareOptions _InitializeSearch (CultureInfo cultureInfo, bool matchCase, bool matchAlefHamza, bool matchDiacritics, ref string findPattern, out bool replaceAlefWithAlefHamza) { CompareOptions compareOptions = CompareOptions.None; replaceAlefWithAlefHamza = false; if (!matchCase) { compareOptions |= CompareOptions.IgnoreCase; } bool stringContainedBidiCharacter; bool stringContainedAlefCharacter; // Initialize Bidi flags whether the string contains the bidi characters // or alef character. TextFindEngine.InitializeBidiFlags( findPattern, out stringContainedBidiCharacter, out stringContainedAlefCharacter); if (stringContainedAlefCharacter && !matchAlefHamza) { // Replace the alef-hamza with the alef. findPattern = TextFindEngine.ReplaceAlefHamzaWithAlef(findPattern); replaceAlefWithAlefHamza = true; } // Ignore Bidi diacritics that use for only Bidi language. if (!matchDiacritics && stringContainedBidiCharacter) { // Ignore Bidi diacritics with checking non-space character. compareOptions |= CompareOptions.IgnoreNonSpace; } return compareOptions; } private static void _GetFirstPageSearchPointers ( ITextPointer start, ITextPointer end, int pageNumber, bool matchLast, out ITextPointer firstSearchPageStart, out ITextPointer firstSearchPageEnd) { if (matchLast) { //The page in question is the last page //Need to search between the start of the last page and the end pointer DocumentSequenceTextPointer endAsDSTP = end as DocumentSequenceTextPointer; if (endAsDSTP != null) { FlowPosition pageStartFlowPosition = ((FixedTextContainer)(endAsDSTP.ChildBlock.ChildContainer)).FixedTextBuilder.GetPageStartFlowPosition(pageNumber); firstSearchPageStart = new DocumentSequenceTextPointer(endAsDSTP.ChildBlock, new FixedTextPointer(false, LogicalDirection.Forward,pageStartFlowPosition)); } else { FixedTextPointer endAsFTP = end as FixedTextPointer; Debug.Assert(endAsFTP != null); firstSearchPageStart = new FixedTextPointer(false, LogicalDirection.Forward, endAsFTP.FixedTextContainer.FixedTextBuilder.GetPageStartFlowPosition(pageNumber)); } firstSearchPageEnd = end; } else { //The page in question is the first page //Need to search between the start pointer and the end of the first page DocumentSequenceTextPointer startAsDSTP = start as DocumentSequenceTextPointer; if (startAsDSTP != null) { FlowPosition pageEndFlowPosition = ((FixedTextContainer)startAsDSTP.ChildBlock.ChildContainer).FixedTextBuilder.GetPageEndFlowPosition(pageNumber); firstSearchPageEnd = new DocumentSequenceTextPointer( startAsDSTP.ChildBlock, new FixedTextPointer(false, LogicalDirection.Backward, pageEndFlowPosition)); } else { FixedTextPointer startAsFTP = start as FixedTextPointer; Debug.Assert(startAsFTP != null); firstSearchPageEnd = new FixedTextPointer(false, LogicalDirection.Backward, startAsFTP.FixedTextContainer.FixedTextBuilder.GetPageEndFlowPosition(pageNumber)); } firstSearchPageStart = start; } } private static String _GetPageString(FixedDocument doc, int translatedPageNo, bool replaceAlefWithAlefHamza) { String pageString = null; Debug.Assert(doc != null); Debug.Assert(translatedPageNo >= 0 && translatedPageNo < doc.PageCount); PageContent pageContent = doc.Pages[translatedPageNo]; Stream pageStream = pageContent.GetPageStream(); bool reverseRTL = true; if (doc.HasExplicitStructure) { reverseRTL = false; } if (pageStream != null) { pageString = _ConstructPageString(pageStream, reverseRTL); if (replaceAlefWithAlefHamza) { // Replace the alef-hamza with the alef. pageString = TextFindEngine.ReplaceAlefHamzaWithAlef(pageString); } } return pageString; } private static String _ConstructPageString(Stream pageStream, bool reverseRTL) { Debug.Assert(pageStream != null); XmlTextReader xmlTextReader = new XmlTextReader(pageStream); //Wrap around a compatibility reader XmlReader xmlReader = new XmlCompatibilityReader(xmlTextReader, _predefinedNamespaces); XmlReaderSettings settings = new XmlReaderSettings(); settings.IgnoreWhitespace = true; settings.IgnoreComments = true; settings.ProhibitDtd = true; xmlReader = XmlReader.Create(xmlReader, settings); xmlReader.MoveToContent(); StringBuilder pageString = new StringBuilder(); bool isSideways = false; string unicodeStr = null; while (xmlReader.Read()) { switch (xmlReader.NodeType) { case XmlNodeType.Element: { if (xmlReader.Name == "Glyphs") { unicodeStr = xmlReader.GetAttribute("UnicodeString"); if (!String.IsNullOrEmpty(unicodeStr)) { string sidewaysString = xmlReader.GetAttribute("IsSideways"); isSideways = false; if (sidewaysString != null && String.Compare(sidewaysString, Boolean.TrueString, StringComparison.OrdinalIgnoreCase) == 0) { isSideways = true; } if (reverseRTL) { //This is to cover for MXDW generation //RTL Glyphs are saved LTR and bidi level is not set //In this case we need to reverse the UnicodeString string bidiLevelAsString = xmlReader.GetAttribute("BidiLevel"); int bidiLevel = 0; if (!String.IsNullOrEmpty(bidiLevelAsString)) { try { bidiLevel = Convert.ToInt32(bidiLevelAsString, CultureInfo.InvariantCulture); } catch (Exception) { } } string caretStops = xmlReader.GetAttribute("CaretStops"); if (bidiLevel == 0 && !isSideways && String.IsNullOrEmpty(caretStops) && FixedTextBuilder.MostlyRTL(unicodeStr)) { char[] chars = unicodeStr.ToCharArray(); Array.Reverse(chars); unicodeStr = new String(chars); } } pageString.Append(unicodeStr); } } } break; } } return pageString.ToString(); } //Private constructor to prevent the compiler from generating a default constructor (fxcop) private FixedFindEngine() { } static private string [] _predefinedNamespaces = new string [2] { "http://schemas.microsoft.com/xps/2005/06", XamlReaderHelper.DefinitionMetroNamespaceURI }; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ThaiBuddhistCalendar.cs
- Baml2006KeyRecord.cs
- XmlEnumAttribute.cs
- SqlCacheDependencySection.cs
- Int32RectConverter.cs
- BitmapImage.cs
- SortableBindingList.cs
- ScrollItemPattern.cs
- ServiceRoute.cs
- OutputCache.cs
- NamespaceEmitter.cs
- ProjectedWrapper.cs
- LinearQuaternionKeyFrame.cs
- AsymmetricSignatureFormatter.cs
- CoTaskMemHandle.cs
- DeadCharTextComposition.cs
- DataKeyArray.cs
- UnionCodeGroup.cs
- XmlEncodedRawTextWriter.cs
- HealthMonitoringSectionHelper.cs
- StringSorter.cs
- PublishLicense.cs
- WizardPanel.cs
- GlyphCollection.cs
- SchemaSetCompiler.cs
- MatcherBuilder.cs
- JsonWriterDelegator.cs
- ImageMapEventArgs.cs
- TransformerConfigurationWizardBase.cs
- CellRelation.cs
- ScrollViewerAutomationPeer.cs
- TableRowCollection.cs
- ModelItemDictionaryImpl.cs
- COM2PropertyBuilderUITypeEditor.cs
- TreeIterator.cs
- CodeMethodInvokeExpression.cs
- SecurityChannel.cs
- SimpleType.cs
- InplaceBitmapMetadataWriter.cs
- UshortList2.cs
- DBParameter.cs
- ForEachAction.cs
- MonitorWrapper.cs
- MethodRental.cs
- ScriptRegistrationManager.cs
- ContentType.cs
- ToolStripItemCollection.cs
- LocatorBase.cs
- WebPartZoneCollection.cs
- PngBitmapDecoder.cs
- StructuralComparisons.cs
- VectorCollectionConverter.cs
- RepeaterItem.cs
- ToolTipService.cs
- SafePointer.cs
- EditorAttribute.cs
- FacetEnabledSchemaElement.cs
- AddressingProperty.cs
- SoapHeader.cs
- SqlLiftIndependentRowExpressions.cs
- BitmapFrame.cs
- DataServiceConfiguration.cs
- xdrvalidator.cs
- ConnectionString.cs
- InputScope.cs
- NullableLongSumAggregationOperator.cs
- PortCache.cs
- ConversionContext.cs
- ConditionalBranch.cs
- ResourceManager.cs
- ApplicationServiceManager.cs
- Help.cs
- ParserContext.cs
- ExpressionDumper.cs
- WrappedIUnknown.cs
- RightsManagementPermission.cs
- autovalidator.cs
- DelegateTypeInfo.cs
- SafeNativeMethods.cs
- ThrowHelper.cs
- Transform3DGroup.cs
- PropertyGridEditorPart.cs
- XmlAttributeProperties.cs
- updatecommandorderer.cs
- SBCSCodePageEncoding.cs
- WebBaseEventKeyComparer.cs
- EntityDataSourceEntityTypeFilterConverter.cs
- SpecularMaterial.cs
- WSHttpBindingBase.cs
- RC2.cs
- XmlCodeExporter.cs
- FreeIndexList.cs
- DesignerDataStoredProcedure.cs
- ToolTipService.cs
- log.cs
- SerializerDescriptor.cs
- UrlAuthFailureHandler.cs
- TreePrinter.cs
- ItemsPanelTemplate.cs
- DataGridTablesFactory.cs