/// <summary>
        /// Gets the location from an offset.
        /// </summary>
        /// <seealso cref="GetOffset(TextLocation)"/>
        public TextLocation GetLocation(int offset)
        {
            DocumentLine line = GetLineByOffset(offset);

            return(new TextLocation(line.LineNumber, offset - line.Offset + 1));
        }
Exemple #2
0
        public void Remove(int offset, int length)
        {
            Debug.Assert(length >= 0);
            if (length == 0)
            {
                return;
            }
            DocumentLine startLine       = documentLineTree.GetByOffset(offset);
            int          startLineOffset = startLine.Offset;

            Debug.Assert(offset < startLineOffset + startLine.TotalLength);
            if (offset > startLineOffset + startLine.Length)
            {
                Debug.Assert(startLine.DelimiterLength == 2);
                // we are deleting starting in the middle of a delimiter

                // remove last delimiter part
                SetLineLength(startLine, startLine.TotalLength - 1);
                // remove remaining text
                Remove(offset, length - 1);
                return;
            }

            if (offset + length < startLineOffset + startLine.TotalLength)
            {
                // just removing a part of this line
                //startLine.RemovedLinePart(ref deferredEventList, offset - startLineOffset, length);
                SetLineLength(startLine, startLine.TotalLength - length);
                return;
            }
            // merge startLine with another line because startLine's delimiter was deleted
            // possibly remove lines in between if multiple delimiters were deleted
            int charactersRemovedInStartLine = startLineOffset + startLine.TotalLength - offset;

            Debug.Assert(charactersRemovedInStartLine > 0);
            //startLine.RemovedLinePart(ref deferredEventList, offset - startLineOffset, charactersRemovedInStartLine);


            DocumentLine endLine = documentLineTree.GetByOffset(offset + length);

            if (endLine == startLine)
            {
                // special case: we are removing a part of the last line up to the
                // end of the document
                SetLineLength(startLine, startLine.TotalLength - length);
                return;
            }
            int endLineOffset           = endLine.Offset;
            int charactersLeftInEndLine = endLineOffset + endLine.TotalLength - (offset + length);
            //endLine.RemovedLinePart(ref deferredEventList, 0, endLine.TotalLength - charactersLeftInEndLine);
            //startLine.MergedWith(endLine, offset - startLineOffset);

            // remove all lines between startLine (excl.) and endLine (incl.)
            DocumentLine tmp = startLine.NextLine;
            DocumentLine lineToRemove;

            do
            {
                lineToRemove = tmp;
                tmp          = tmp.NextLine;
                RemoveLine(lineToRemove);
            } while (lineToRemove != endLine);

            SetLineLength(startLine, startLine.TotalLength - charactersRemovedInStartLine + charactersLeftInEndLine);
        }
Exemple #3
0
        // optimization note: I tried packing color and isDeleted into a single byte field, but that
        // actually increased the memory requirements. The JIT packs two bools and a byte (delimiterSize)
        // into a single DWORD, but two bytes get each their own DWORD. Three bytes end up in the same DWORD, so
        // apparently the JIT only optimizes for memory when there are at least three small fields.
        // Currently, DocumentLine takes 36 bytes on x86 (8 byte object overhead, 3 pointers, 3 ints, and another DWORD
        // for the small fields).
        // TODO: a possible optimization would be to combine 'totalLength' and the small fields into a single uint.
        // delimiterSize takes only two bits, the two bools take another two bits; so there's still
        // 28 bits left for totalLength. 268435455 characters per line should be enough for everyone :)

        /// <summary>
        /// Resets the line to enable its reuse after a document rebuild.
        /// </summary>
        internal void ResetLine()
        {
            totalLength = delimiterLength = 0;
            isDeleted   = color = false;
            left        = right = parent = null;
        }