示例#1
0
文件: TextStore.cs 项目: mind0n/hive
        // GetText handler for text runs.
        private static bool WalkTextRun(ITextPointer navigator, ITextPointer limit, char[] text, int cchReq, ref int charsCopied, UnsafeNativeMethods.TS_RUNINFO[] runInfo, int cRunInfoReq, ref int cRunInfoRcv)
        {
            int runCount;
            int offset;
            bool hitLimit;

            Invariant.Assert(navigator.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text);
            Invariant.Assert(limit == null || navigator.CompareTo(limit) <= 0);

            hitLimit = false;

            if (cchReq > 0)
            {
                runCount = TextPointerBase.GetTextWithLimit(navigator, LogicalDirection.Forward, text, charsCopied, Math.Min(cchReq, text.Length - charsCopied), limit);
                navigator.MoveByOffset(runCount);
                charsCopied += runCount;
                hitLimit = (text.Length == charsCopied) || (limit != null && navigator.CompareTo(limit) == 0);
            }
            else
            {
                // Caller doesn't want text, just run info.
                // Advance the navigator.
                runCount = navigator.GetTextRunLength(LogicalDirection.Forward);
                navigator.MoveToNextContextPosition(LogicalDirection.Forward);

                // If the caller passed in a non-null limit, backup to the limit if
                // we've passed it.
                if (limit != null)
                {
                    if (navigator.CompareTo(limit) >= 0)
                    {
                        offset = limit.GetOffsetToPosition(navigator);
                        Invariant.Assert(offset >= 0 && offset <= runCount, "Bogus offset -- extends past run!");
                        runCount -= offset;
                        navigator.MoveToPosition(limit);
                        hitLimit = true;
                    }
                }
            }

            if (cRunInfoReq > 0 && runCount > 0)
            {
                // Be sure to merge this text run with the previous run, if they are both text runs.
                // (A good robustness fix would be to make cicero handle this, if we ever get the chance.)
                if (cRunInfoRcv > 0 && runInfo[cRunInfoRcv - 1].type == UnsafeNativeMethods.TsRunType.TS_RT_PLAIN)
                {
                    runInfo[cRunInfoRcv - 1].count += runCount;
                }
                else
                {
                    runInfo[cRunInfoRcv].count = runCount;
                    runInfo[cRunInfoRcv].type = UnsafeNativeMethods.TsRunType.TS_RT_PLAIN;
                    cRunInfoRcv++;
                }
            }

            return hitLimit;
        }
        /// <summary>
        /// Gets start and end offset for a text segment but clamps those values to the start and end 
        /// of a given element.  This way if a large text range is being resolved on a node that only contains
        /// a portion of the text range (such as a paragraph) the result only includes the content in that node.
        /// </summary>
        private void GetTextSegmentValues(TextSegment segment, ITextPointer elementStart, ITextPointer elementEnd, out int startOffset, out int endOffset)
        {
            startOffset = 0;
            endOffset = 0;

            if (elementStart.CompareTo(segment.Start) >= 0)
            {
                // segment starts before the start of the element
                startOffset = 0;
            }
            else
            {
                startOffset = elementStart.GetOffsetToPosition(segment.Start);
            }

            if (elementEnd.CompareTo(segment.End) >= 0)
            {
                endOffset = elementStart.GetOffsetToPosition(segment.End);
            }
            else
            {
                // segment ends after the end of the element
                endOffset = elementStart.GetOffsetToPosition(elementEnd);
            }
        }
        // Like GetText, excepts also accepts a limit parameter -- no text is returned past
        // this second position.
        // limit may be null, in which case it is ignored.
        internal static int GetTextWithLimit(ITextPointer thisPointer, LogicalDirection direction, char[] textBuffer, int startIndex, int count, ITextPointer limit)
        {
            int charsCopied;

            if (limit == null)
            {
                // No limit, just call GetText.
                charsCopied = thisPointer.GetTextInRun(direction, textBuffer, startIndex, count);
            }
            else if (direction == LogicalDirection.Forward && limit.CompareTo(thisPointer) <= 0)
            {
                // Limit completely blocks the read.
                charsCopied = 0;
            }
            else if (direction == LogicalDirection.Backward && limit.CompareTo(thisPointer) >= 0)
            {
                // Limit completely blocks the read.
                charsCopied = 0;
            }
            else
            {
                int maxCount;

                // Get an upper bound on the amount of text to copy.
                // Since GetText always stops on non-text boundaries, it's
                // ok if the count too high, it will get truncated anyways.
                if (direction == LogicalDirection.Forward)
                {
                    maxCount = Math.Min(count, thisPointer.GetOffsetToPosition(limit));
                }
                else
                {
                    maxCount = Math.Min(count, limit.GetOffsetToPosition(thisPointer));
                }
                maxCount = Math.Min(count, maxCount);

                charsCopied = thisPointer.GetTextInRun(direction, textBuffer, startIndex, maxCount);
            }

            return charsCopied;
        }
示例#4
0
        // Finds the next dirty range following searchStart, without considering
        // the current caret or IME composition. 
        private void GetNextScanRangeRaw(ITextPointer searchStart, out ITextPointer start, out ITextPointer end)
        {
            Invariant.Assert(searchStart != null);
 
            start = null;
            end = null; 
 
            // Grab the first dirty range.
            _statusTable.GetFirstDirtyRange(searchStart, out start, out end); 

            if (start != null)
            {
                Invariant.Assert(start.CompareTo(end) < 0); 

                // Cap the block size by a constant. 
                if (start.GetOffsetToPosition(end) > MaxScanBlockSize) 
                {
                    end = start.CreatePointer(MaxScanBlockSize); 
                }

                // Ensure the block has constant language.
                XmlLanguage language = GetCurrentLanguage(start); 
                end = GetNextLanguageTransition(start, LogicalDirection.Forward, language, end);
                Invariant.Assert(start.CompareTo(end) < 0); 
            } 
        }
示例#5
0
            // Creates a new instance. 
            // contextStart/End refer to the whole run of text.
            // contentStart/End are a subset of the text, which is what
            // the engine will actually tag with errors.
            // The space between context and content is used by the engine 
            // to correctly analyze multiple word phrase like "Los Angeles"
            // that could otherwise be truncated and incorrectly tagged. 
            internal TextMap(ITextPointer contextStart, ITextPointer contextEnd, 
                ITextPointer contentStart, ITextPointer contentEnd)
            { 
                ITextPointer position;
                int maxChars;
                int inlineCount;
                int runCount; 
                int i;
                int distance; 
 
                Invariant.Assert(contextStart.CompareTo(contentStart) <= 0);
                Invariant.Assert(contextEnd.CompareTo(contentEnd) >= 0); 

                _basePosition = contextStart.GetFrozenPointer(LogicalDirection.Backward);

                position = contextStart.CreatePointer(); 
                maxChars = contextStart.GetOffsetToPosition(contextEnd);
 
                _text = new char[maxChars]; 
                _positionMap = new int[maxChars+1];
 
                _textLength = 0;
                inlineCount = 0;

                _contentStartOffset = 0; 
                _contentEndOffset = 0;
 
                // Iterate over the run, building up a matching plain text buffer 
                // and a table that tells us how to map back to the original text.
                while (position.CompareTo(contextEnd) < 0) 
                {
                    if (position.CompareTo(contentStart) == 0)
                    {
                        _contentStartOffset = _textLength; 
                    }
                    if (position.CompareTo(contentEnd) == 0) 
                    { 
                        _contentEndOffset = _textLength;
                    } 

                    switch (position.GetPointerContext(LogicalDirection.Forward))
                    {
                        case TextPointerContext.Text: 
                            runCount = position.GetTextRunLength(LogicalDirection.Forward);
                            runCount = Math.Min(runCount, _text.Length - _textLength); 
                            runCount = Math.Min(runCount, position.GetOffsetToPosition(contextEnd)); 

                            position.GetTextInRun(LogicalDirection.Forward, _text, _textLength, runCount); 

                            for (i = _textLength; i < _textLength + runCount; i++)
                            {
                                _positionMap[i] = i + inlineCount; 
                            }
 
                            distance = position.GetOffsetToPosition(contentStart); 
                            if (distance >= 0 && distance <= runCount)
                            { 
                                _contentStartOffset = _textLength + position.GetOffsetToPosition(contentStart);
                            }
                            distance = position.GetOffsetToPosition(contentEnd);
                            if (distance >= 0 && distance <= runCount) 
                            {
                                _contentEndOffset = _textLength + position.GetOffsetToPosition(contentEnd); 
                            } 

                            position.MoveByOffset(runCount); 
                            _textLength += runCount;
                            break;

                        case TextPointerContext.ElementStart: 
                        case TextPointerContext.ElementEnd:
                            if (IsAdjacentToFormatElement(position)) 
                            { 
                                // Filter out formatting tags from the plain text.
                                inlineCount++; 
                            }
                            else
                            {
                                // Stick in a word break to account for the block element. 
                                _text[_textLength] = ' ';
                                _positionMap[_textLength] = _textLength + inlineCount; 
                                _textLength++; 
                            }
                            position.MoveToNextContextPosition(LogicalDirection.Forward); 
                            break;

                        case TextPointerContext.EmbeddedElement:
                            _text[_textLength] = '\xf8ff'; // Unicode private use. 
                            _positionMap[_textLength] = _textLength + inlineCount;
                            _textLength++; 
 
                            position.MoveToNextContextPosition(LogicalDirection.Forward);
                            break; 
                    }
                }

                if (position.CompareTo(contentEnd) == 0) 
                {
                    _contentEndOffset = _textLength; 
                } 

                if (_textLength > 0) 
                {
                    _positionMap[_textLength] = _positionMap[_textLength - 1] + 1;
                }
                else 
                {
                    _positionMap[0] = 0; 
                } 

                Invariant.Assert(_contentStartOffset <= _contentEndOffset); 
            }
示例#6
0
        /// <summary> 
        /// Set the find text content from reading the text on the current text position. 
        /// </summary>
        /// <returns> 
        /// Returns the number of characters actually loaded into the findText array.
        /// </returns>
        private static int SetFindTextAndFindTextPositionMap(
            ITextPointer startPosition, 
            ITextPointer endPosition,
            ITextPointer navigator, 
            LogicalDirection direction, 
            bool matchLast,
            char[] findText, 
            int[] findTextPositionMap)
        {
            Invariant.Assert(startPosition.CompareTo(navigator) <= 0);
            Invariant.Assert(endPosition.CompareTo(navigator) >= 0); 

            int runCount; 
            int inlineCount = 0; 
            int findTextLength = 0;
 
            // Set the first offset which is zero on TextBufferSize + 1 location of
            // the text position map in case of the backward searching
            if (matchLast && findTextLength == 0)
            { 
                findTextPositionMap[findTextPositionMap.Length - 1] = 0;
            } 
 
            while ((matchLast ? startPosition.CompareTo(navigator) : navigator.CompareTo(endPosition)) < 0)
            { 

                switch (navigator.GetPointerContext(direction))
                {
                    case TextPointerContext.Text: 
                        runCount = navigator.GetTextRunLength(direction);
                        runCount = Math.Min(runCount, findText.Length - findTextLength); 
 
                        if (!matchLast)
                        { 
                            runCount = Math.Min(runCount, navigator.GetOffsetToPosition(endPosition));
                            navigator.GetTextInRun(direction, findText, findTextLength, runCount);

                            for (int i = findTextLength; i < findTextLength + runCount; i++) 
                            {
                                findTextPositionMap[i] = i + inlineCount; 
                            } 
                        }
                        else 
                        {
                            runCount = Math.Min(runCount, startPosition.GetOffsetToPosition(navigator));
                            navigator.GetTextInRun(
                                direction, 
                                findText,
                                findText.Length - findTextLength - runCount, 
                                runCount); 

                            // Set the text offest for the amount of runCount from the last index 
                            // of text position map
                            int mapIndex = findText.Length - findTextLength - 1;
                            for (int i = findTextLength; i < findTextLength + runCount; i++)
                            { 
                                findTextPositionMap[mapIndex--] = i + inlineCount + 1;
                            } 
                        } 

                        // Move the navigator position for the amount of runCount 
                        navigator.MoveByOffset(matchLast ? - runCount : runCount);
                        findTextLength += runCount;
                        break;
 
                    case TextPointerContext.None:
                    case TextPointerContext.ElementStart: 
                    case TextPointerContext.ElementEnd: 
                        if (IsAdjacentToFormatElement(navigator, direction))
                        { 
                            // Filter out formatting tags since find text content is plain.
                            inlineCount++;
                        }
                        else 
                        {
                            if (!matchLast) 
                            { 
                                // Stick in a line break to account for the block element.
                                findText[findTextLength] = '\n'; 
                                findTextPositionMap[findTextLength] = findTextLength + inlineCount;
                                findTextLength++;
                            }
                            else 
                            {
                                // Increse the find text length first since adding text and map reversely 
                                findTextLength++; 

                                // Stick in a line break to account for the block element and 
                                // add text offset on the last index of text position map
                                findText[findText.Length - findTextLength] = '\n';
                                findTextPositionMap[findText.Length - findTextLength] = findTextLength + inlineCount;
                            } 
                        }
 
                        navigator.MoveToNextContextPosition(direction); 
                        break;
 
                    case TextPointerContext.EmbeddedElement:
                        if (!matchLast)
                        {
                            findText[findTextLength] = '\xf8ff'; // Unicode private use. 
                            findTextPositionMap[findTextLength] = findTextLength + inlineCount;
                            findTextLength++; 
                        } 
                        else
                        { 
                            // Increse the find text length first since adding text and map reversely
                            findTextLength++;

                            // Set the private unicode value and text offset 
                            findText[findText.Length - findTextLength] = '\xf8ff';
                            findTextPositionMap[findText.Length - findTextLength] = findTextLength + inlineCount; 
                        } 

                        navigator.MoveToNextContextPosition(direction); 
                        break;
                }

                if (findTextLength >= findText.Length) 
                {
                    break; 
                } 
            }
 
            // Complete the adding the find text position to the position map for only the forward finding.
            // The backward finding(matchLast) is already added initially as the zero offset at the end of
            // text position map.
            if (!matchLast) 
            {
                if (findTextLength > 0) 
                { 
                    findTextPositionMap[findTextLength] = findTextPositionMap[findTextLength - 1] + 1;
                } 
                else
                {
                    findTextPositionMap[0] = 0;
                } 
            }
 
            return findTextLength; 
        }
示例#7
0
        // Returns true iff there is a character in the specificed direction adjacent to a
        // position which is classified as a separator.  This is useful in detecting word breaks.
        private static bool HasNeighboringSeparatorChar(ITextPointer position, LogicalDirection direction) 
        {
            ITextPointer nextPosition = position.GetNextInsertionPosition(direction); 
 
            if (nextPosition == null)
            { 
                return true;
            }

            if (position.CompareTo(nextPosition) > 0) 
            {
                ITextPointer temp = position; 
                position = nextPosition; 
                nextPosition = temp;
            } 

            int maxCharCount = position.GetOffsetToPosition(nextPosition);
            char[] findText = new char[maxCharCount];
            int []findTextPositionMap = new int[maxCharCount + 1]; 
            int findTextLength;
 
            findTextLength = SetFindTextAndFindTextPositionMap( 
                                position,
                                nextPosition, 
                                position.CreatePointer() /* need unfrozen pointer */,
                                LogicalDirection.Forward,
                                false /* matchLast */,
                                findText, 
                                findTextPositionMap);
 
            if (findTextLength == 0) 
            {
                return true; 
            }

            bool hasNeighboringSeparatorChar;
 
            if (direction == LogicalDirection.Forward)
            { 
                hasNeighboringSeparatorChar = IsSeparatorChar(findText[0]); 
            }
            else 
            {
                hasNeighboringSeparatorChar = IsSeparatorChar(findText[findTextLength-1]);
            }
 
            return hasNeighboringSeparatorChar;
        }