public static void GetBeginAndEndCharacterIndices(
            this SingleLineTextRange range,
            ProjectBlockCollection blocks,
            out int blockIndex,
            out int sourceBegin,
            out int sourceEnd,
            out string text)
        {
            using (blocks.AcquireLock(RequestLock.Read))
            {
                // Start by getting the block based on the index.
                Block block;

                blockIndex = range.LinePosition.GetLineIndex(blocks.Count);

                using (
                    blocks.AcquireBlockLock(
                        RequestLock.Read, RequestLock.Read, blockIndex, out block))
                {
                    // Get the text and calculate the character indicies.
                    text = block.Text;

                    range.GetBeginAndEndCharacterIndices(text, out sourceBegin, out sourceEnd);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Gets the Pango markup for a given line.
        /// </summary>
        /// <param name="lineIndex">The line.</param>
        /// <param name="lineContexts">The line contexts.</param>
        /// <returns></returns>
        public string GetSelectionMarkup(
            int lineIndex,
            LineContexts lineContexts)
        {
            // Get the line markup from the underlying buffer.
            string markup = LineBuffer.GetLineMarkup(lineIndex, lineContexts);

            // Check to see if we are in the selection.
            CharacterPosition beginCharacterPosition;
            CharacterPosition endCharacterPosition;
            bool containsLine = DisplayContext.Caret.Selection.ContainsLine(
                LineBuffer, lineIndex, out beginCharacterPosition, out endCharacterPosition);

            if (containsLine)
            {
                // Apply the markup to the line.
                var linePosition        = new LinePosition(lineIndex);
                var singleLineTextRange = new SingleLineTextRange(
                    linePosition, beginCharacterPosition, endCharacterPosition);
                return(SelectionRenderer.GetSelectionMarkup(markup, singleLineTextRange));
            }

            // Return the resulting markup.
            return(markup);
        }
Пример #3
0
 /// <summary>
 /// Takes the given string (which assumes a valid Pango markup) and
 /// adds the markup to apply a selection to the string.
 /// </summary>
 /// <param name="pangoMarkup">The Pango markup to apply the selection.</param>
 /// <param name="characters">The range of character to select.</param>
 /// <returns>A Pango markup string with the selection applied.</returns>
 public string GetSelectionMarkup(
     string pangoMarkup,
     SingleLineTextRange characters)
 {
     return(GetSelectionMarkup(
                pangoMarkup, characters, "span", " background='#CCCCFF'"));
 }
 public InsertTextFromTextRangeOperation(
     TextPosition destinationPosition,
     SingleLineTextRange sourceRange)
 {
     DestinationPosition = destinationPosition;
     SourceRange         = sourceRange;
 }
Пример #5
0
        public IDeleteTextCommand <OperationContext> CreateDeleteTextCommand(
            SingleLineTextRange range)
        {
            var operation = new DeleteTextOperation(range);

            return(operation);
        }
Пример #6
0
        protected override void Do(
            object context,
            CommandFactoryManager <OperationContext> commandFactory,
            object commandData,
            OperationContext operationContext,
            EditorViewController controller,
            IDisplayContext displayContext,
            TextPosition position)
        {
            var range =
                new SingleLineTextRange(
                    displayContext.Caret.Position.LinePosition,
                    CharacterPosition.Word,
                    displayContext.Caret.Position.CharacterPosition);
            IDeleteTextCommand <OperationContext> deleteCommand =
                controller.CommandController.CreateDeleteTextCommand(range);

            deleteCommand.UpdateTextPosition = DoTypes.All;

            // Execute the command.
            controller.CommandController.Do(deleteCommand, operationContext);

            // If we have a text position, we need to set it.
            if (operationContext.Results.HasValue)
            {
                displayContext.Caret.SetAndScrollToPosition(
                    operationContext.Results.Value.TextPosition);
            }
        }
Пример #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="InsertTextFromBlock" /> class.
 /// </summary>
 /// <param name="destinationPosition">The position to insert the text into.</param>
 /// <param name="range">The range.</param>
 public InsertTextFromIndexedBlock(
     TextPosition destinationPosition,
     SingleLineTextRange range)
 {
     DestinationPosition = destinationPosition;
     Range = range;
 }
        public IDeleteTextCommand <OperationContext> CreateDeleteTextCommand(
            SingleLineTextRange range)
        {
            // Create the command adapter and return it.
            var command = new ProjectDeleteTextCommand(Project, range);

            //Debug.WriteLine("CreateDeleteTextCommand: " + range);
            return(command);
        }
Пример #9
0
        CreateInsertTextFromTextRangeCommand(
            TextPosition destinationPosition,
            SingleLineTextRange sourceRange)
        {
            var operation = new InsertTextFromTextRangeOperation(
                destinationPosition, sourceRange);

            return(operation);
        }
        public ProjectDeleteTextCommand(
            Project project,
            SingleLineTextRange range)
            : base(project)
        {
            // Create the project command wrapper.
            var command = new DeleteTextCommand(range);

            // Set the command into the adapter.
            Command = command;
        }
        public LineBufferOperationResults DeleteText(
            int lineIndex,
            int beginCharacterIndex,
            int endCharacterIndex)
        {
            var range = new SingleLineTextRange(
                new LinePosition(lineIndex),
                new CharacterPosition(beginCharacterIndex),
                new CharacterPosition(endCharacterIndex));

            return(DeleteText(range));
        }
        public static void GetBeginAndEndCharacterIndices(
            this SingleLineTextRange range,
            ProjectBlockCollection blocks,
            out int blockIndex,
            out int sourceBegin,
            out int sourceEnd)
        {
            string text;

            GetBeginAndEndCharacterIndices(
                range, blocks, out blockIndex, out sourceBegin, out sourceEnd, out text);
        }
        public void HandleBlank()
        {
            // Setup
            string markup            = string.Empty;
            var    selectionRenderer = new SelectionRenderer();
            var    characters        = new SingleLineTextRange(0, 1, 2);

            // Operation
            string output = selectionRenderer.GetSelectionMarkup(markup, characters);

            // Verification
            Assert.AreEqual(string.Empty, output);
        }
        CreateInsertTextFromTextRangeCommand(
            TextPosition destinationPosition,
            SingleLineTextRange sourceRange)
        {
            // Create the command adapter and return it.
            var command = new ProjectInsertTextFromTextRangeCommand(
                Project, destinationPosition, sourceRange);

            //Debug.WriteLine(
            //	"CreateInsertTextFromTextRangeCommand: " + destinationPosition + ", "
            //		+ sourceRange);
            return(command);
        }
        public void PlainEmptySelectionAtEndOfLine()
        {
            // Setup
            const string markup            = "this";
            var          selectionRenderer = new SelectionRenderer();
            var          characters        = new SingleLineTextRange(0, 5, CharacterPosition.End);

            // Operation
            string output = selectionRenderer.GetSelectionMarkup(markup, characters);

            // Verification
            Assert.AreEqual("this", output);
        }
        public void PlainMiddleOfString()
        {
            // Setup
            const string markup            = "this is a string";
            var          selectionRenderer = new SelectionRenderer();
            var          characters        = new SingleLineTextRange(0, 5, 9);

            // Operation
            string output = selectionRenderer.GetSelectionMarkup(markup, characters);

            // Verification
            Assert.AreEqual("this <span background='#CCCCFF'>is a</span> string", output);
        }
        public void HandleNull()
        {
            // Setup
            const string markup            = null;
            var          selectionRenderer = new SelectionRenderer();
            var          characters        = new SingleLineTextRange(0, 1, 2);

            // Operation
            string output = selectionRenderer.GetSelectionMarkup(markup, characters);

            // Verification
            Assert.IsNull(output);
        }
        public ProjectInsertTextFromTextRangeCommand(
            Project project,
            TextPosition destinationPosition,
            SingleLineTextRange sourceRange)
            : base(project)
        {
            // Save the position for later.
            this.destinationPosition = destinationPosition;

            // Create the project command wrapper.
            var command = new InsertTextFromIndexedBlock(
                destinationPosition, sourceRange);

            // Set the command into the adapter.
            Command = command;
        }
        /// <summary>
        /// Performs one of the exhaustive tests by taking the input and applying
        /// the selection to characters 3-4.
        /// </summary>
        /// <param name="startIndex">The start index.</param>
        /// <param name="endIndex">The end index.</param>
        /// <param name="input">The input.</param>
        /// <param name="desiredOutput">The output.</param>
        protected void TestExhaustive(
            int startIndex,
            int endIndex,
            string input,
            string desiredOutput)
        {
            // Setup
            var selectionRenderer = new SelectionRenderer();
            var characters        = new SingleLineTextRange(0, startIndex, endIndex);

            // Operation
            string output = selectionRenderer.GetSelectionMarkup(
                input, characters, "s", String.Empty);

            // Verification
            Assert.AreEqual(desiredOutput, output);
        }
Пример #20
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DeleteTextOperation" /> class.
 /// </summary>
 /// <param name="characterRange">The character range.</param>
 public DeleteTextOperation(SingleLineTextRange characterRange)
 {
     TextRange = characterRange;
 }
 public DeleteTextCommand(SingleLineTextRange range)
     : base(new TextPosition(range.LinePosition, range.BeginCharacterPosition))
 {
     // DREM ToTextPosition
     End = range.EndCharacterPosition;
 }
 /// <summary>
 /// Deletes the text from the buffer using a <see cref="DeleteTextOperation" />.
 /// </summary>
 /// <param name="characterRange">The character range.</param>
 /// <returns></returns>
 public LineBufferOperationResults DeleteText(
     SingleLineTextRange characterRange)
 {
     return(Do(new DeleteTextOperation(characterRange)));
 }
Пример #23
0
 public DeleteTextCommand(SingleLineTextRange range)
     : base(new TextPosition(range.LinePosition, range.BeginCharacterPosition))
 {
     // DREM ToTextPosition
     End = range.EndCharacterPosition;
 }
Пример #24
0
        /// <summary>
        /// Gets the indexes in the markup string for the given character range. This
        /// handles mapping attributes and entities as zero and one-length characters
        /// respectively. It also returns information to optimize the search for XML
        /// tags inside the Pango string.
        /// </summary>
        /// <param name="pangoMarkup">The pango markup.</param>
        /// <param name="characters">The characters.</param>
        /// <param name="startIndex">The start index.</param>
        /// <param name="endIndex">The end index.</param>
        /// <param name="leadingXmlDepth">The number of nested XML elements at the
        /// point of the
        /// <paramref name="startIndex"/>.
        /// <param name="leadingXmlIndex">
        /// The character index of the opening XML tag before the selection. If this
        /// -1 one, then there is no opening tag and
        /// <paramref name="leadingXmlDepth"/> will be zero.
        /// </param></param>
        /// <param name="leadingXmlIndex">Index of the leading XML.</param>
        /// <param name="trailingXmlDepth">The number of nested XML elements at the
        /// point the selection ends.</param>
        private static void GetMarkupIndexes(
            string pangoMarkup,
            SingleLineTextRange characters,
            out int startIndex,
            out int endIndex,
            out int leadingXmlDepth,
            out int leadingXmlIndex,
            out int trailingXmlDepth)
        {
            // Strip off the Pango formatting so we can calculate lengths. We
            // add in an extra " " so GetCharacterIndex can handle end of file
            // lengths.
            string plainText = GetText(pangoMarkup) + " ";
            int    firstCharacterIndex;
            int    lastCharacterIndex;

            characters.GetFirstAndLastCharacterIndices(
                plainText, out firstCharacterIndex, out lastCharacterIndex);

            // Because of how the loop works, we have to set the startIndex to
            // a sane default and only check to see if we found the endIndex.
            startIndex       = -1;
            leadingXmlDepth  = 0;
            trailingXmlDepth = 0;
            leadingXmlIndex  = -1;

            // Check for the selection starting at the beginning.
            if (characters.FirstCharacterPosition == CharacterPosition.Begin)
            {
                startIndex = 0;
            }

            // Loop through the entire markup string. We keep track of two
            // indexes. The markupIndex is the index inside the markup string.
            // The character index is the logical characters, treating XML tags
            // as zero-width characters, and is used to match against characters.
            for (int markupIndex = 0,
                 characterIndex = 0;
                 markupIndex < pangoMarkup.Length;
                 markupIndex++)
            {
                // Keep track of the starting markup index since we'll use that
                // to find the beginning of an XML tag or entity.
                int markupIndexAnchor = markupIndex;

                // Grab the character at this position.
                char c = pangoMarkup[markupIndex];

                // Use the character to determine if we have an entity or tag.
                switch (c)
                {
                case '&':
                    // Treat the entire entity as a single character.
                    while (c != ';')
                    {
                        markupIndex++;
                        c = pangoMarkup[markupIndex];
                    }

                    // We don't include the final markupIndex because of
                    // the for loop increment.

                    break;

                case '<':
                    // Grab the next character to see if we have an opening
                    // or closing tag.
                    markupIndex++;
                    c = pangoMarkup[markupIndex];

                    if (c == '/')
                    {
                        // If we are still looking for the start index,
                        // process the leading elements.
                        if (startIndex == -1)
                        {
                            // If we are closing the outer-most tag, then clear
                            // the index since we don't need to process it.
                            if (leadingXmlDepth == 1)
                            {
                                leadingXmlIndex = -1;
                            }

                            // Decrement the depth.
                            leadingXmlDepth--;
                        }

                        // Decrement the depth of trailing.
                        trailingXmlDepth--;
                    }
                    else
                    {
                        // If we are still looking for the start index,
                        // process the leading elements.
                        if (startIndex == -1)
                        {
                            // We need to first check to see if we are at
                            // the selection point. If we are, then we want
                            // to start before we open a new tag.
                            if (characterIndex == firstCharacterIndex)
                            {
                                // Save the start index for the selection.
                                startIndex = markupIndexAnchor;
                            }
                            else
                            {
                                // Increment the depth of the tag.
                                leadingXmlDepth++;

                                // If we are the outer-most tag, then keep track
                                // of the start index.
                                if (leadingXmlDepth == 1)
                                {
                                    leadingXmlIndex = markupIndexAnchor;
                                }
                            }
                        }
                        else if (characterIndex == lastCharacterIndex)
                        {
                            // This is right before the selection ends.
                            // Since this is an opening tag, we want to
                            // stop here.
                            endIndex = markupIndexAnchor;
                            return;
                        }

                        // Increment the trailing XML depth.
                        trailingXmlDepth++;
                    }

                    // Skip over the entire XML tag.
                    while (c != '>')
                    {
                        markupIndex++;
                        c = pangoMarkup[markupIndex];
                    }

                    // We continue since we want to treat XML tags as
                    // zero-width characters.
                    continue;
                }

                // Check to see if we have the start index.
                if (startIndex == -1 &&
                    characterIndex == firstCharacterIndex)
                {
                    startIndex = markupIndexAnchor;
                }

                // Check to see if we are done processing.
                if (characterIndex == lastCharacterIndex)
                {
                    endIndex = markupIndexAnchor;
                    return;
                }

                // Increment the character index.
                characterIndex++;
            }

            // If we got this far, we hit the end of the line, so just mark the
            // end as the last character in the string.
            endIndex = pangoMarkup.Length;
        }
Пример #25
0
        /// <summary>
        /// Takes the given string (which assumes a valid Pango markup) and
        /// adds the markup to apply a selection to the string.
        /// </summary>
        /// <param name="markup">The markup.</param>
        /// <param name="characters">The range of character to select.</param>
        /// <param name="selectionTag">The selection tag to use.</param>
        /// <param name="selectionAttributes">The selection attributes to use.</param>
        /// <returns>
        /// A Pango markup string with the selection applied.
        /// </returns>
        public string GetSelectionMarkup(
            string markup,
            SingleLineTextRange characters,
            string selectionTag,
            string selectionAttributes)
        {
            // Check for nulls and invalid strings.
            if (String.IsNullOrEmpty(markup))
            {
                // We can't really do anything with this.
                return(markup);
            }

            // The primary concern for applying the selection is that we already
            // have Pango markup in the string and we have to maintain that
            // markup while adjusting it. Pango doesn't allow for non-XML rules
            // such as nested spans, so we go through the string and keep track
            // of the spans as they apply. When we get to the selection, we
            // disable those spans and replace them with ones of our own.
            //
            // In addition, the character range does not apply to entities such
            // as &amp; so the entity is treated as a single string.

            // To start with, we need to get the index in the string for the
            // selection.
            int startIndex,
                endIndex,
                leadingXmlDepth,
                leadingXmlIndex,
                trailingXmlDepth;

            GetMarkupIndexes(
                markup,
                characters,
                out startIndex,
                out endIndex,
                out leadingXmlDepth,
                out leadingXmlIndex,
                out trailingXmlDepth);

            // If we have a startIndex of -1, that means that the selection is
            // the end of the line and we have nothing.
            if (startIndex < 0)
            {
                return(markup);
            }

            // Use a string builder and build up the selection markup, this way
            // we avoid as much object creation as possible.
            var buffer = new StringBuilder();

            // Add in all the text before the selection.
            string leadingMarkup = markup.Substring(0, startIndex);

            buffer.Append(leadingMarkup);

            // Get all the tags that were opened at the point the selection
            // starts and close them.
            TagInfo[] leadingTags = null;

            if (leadingXmlDepth > 0)
            {
                // Allocate space equal to the depth since we won't get any
                // larger than that.
                leadingTags = new TagInfo[leadingXmlDepth];

                // Get all the tags in the leading markup.
                GetOpenTags(leadingMarkup, leadingXmlIndex, startIndex, 0, ref leadingTags);

                // Close all the leading tags in reverse order.
                for (int index = leadingXmlDepth - 1;
                     index >= 0;
                     index--)
                {
                    buffer.AppendFormat("</{0}>", leadingTags[index].Name);
                }
            }

            // Add the selection tag itself.
            buffer.AppendFormat("<{0}{1}>", selectionTag, selectionAttributes);

            // Open up the tags that were open before the selection.
            if (leadingTags != null)
            {
                // Close all the leading tags in reverse order.
                for (int index = 0;
                     index < leadingXmlDepth;
                     index++)
                {
                    buffer.Append(leadingTags[index].ToString());
                }
            }

            // Add in the text inside the selection.
            string innerSelectionMarkup = markup.Substring(
                startIndex, endIndex - startIndex);

            buffer.Append(innerSelectionMarkup);

            // Get the tags that were inside the selection so we can close them.
            TagInfo[] trailingTags = null;

            if (trailingXmlDepth > 0)
            {
                // Allocate space equal to the depth since we won't get any
                // larger than that.
                trailingTags = new TagInfo[trailingXmlDepth];

                // Copy in any of the tags from the leading to fill the space.
                if (leadingTags != null)
                {
                    int total = Math.Min(trailingXmlDepth, leadingXmlDepth);

                    for (int index = 0;
                         index < total;
                         index++)
                    {
                        trailingTags[index] = leadingTags[index];
                    }
                }

                // Get all the tags in the leading markup.
                GetOpenTags(
                    innerSelectionMarkup,
                    0,
                    endIndex - startIndex,
                    leadingXmlDepth,
                    ref trailingTags);

                // Close all the leading tags in reverse order.
                for (int index = trailingXmlDepth - 1;
                     index >= 0;
                     index--)
                {
                    buffer.AppendFormat("</{0}>", trailingTags[index].Name);
                }
            }

            // Close the selection tag.
            buffer.AppendFormat("</{0}>", selectionTag);

            // Open up the tags that were open before the selection ended.
            if (trailingTags != null)
            {
                // Close all the leading tags in reverse order.
                for (int index = 0;
                     index < trailingXmlDepth;
                     index++)
                {
                    buffer.Append(trailingTags[index].ToString());
                }
            }

            // Add everything after the markup.
            buffer.Append(markup.Substring(endIndex));

            // Combine the list together and return it.
            string selectionMarkup = buffer.ToString();

            return(selectionMarkup);
        }