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); } } }
/// <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); }
/// <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; }
public IDeleteTextCommand <OperationContext> CreateDeleteTextCommand( SingleLineTextRange range) { var operation = new DeleteTextOperation(range); return(operation); }
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); } }
/// <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); }
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); }
/// <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))); }
/// <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; }
/// <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 & 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); }