Beispiel #1
0
        static bool NextChunk(string oldText, ref int oldIndex, string newText, ref int newIndex, List<TextChange> changes) {
            int oldLength = oldText.Length;
            int newLength = newText.Length;

            if (oldIndex >= oldLength && newIndex >= newLength)
                return false;

            if (oldIndex >= oldLength && newIndex < newLength) {
                // new text is longer, this is the last chunk
                var tc = new TextChange(oldLength, 0, newText.Substring(newIndex));
                AddChange(tc, changes);
                return false;
            }

            if (newIndex >= newLength && oldIndex < oldLength) {
                // old text is longer, this is the last chunk
                var tc = new TextChange(oldIndex, oldLength - oldIndex, string.Empty);
                AddChange(tc, changes);
                return false;
            }

            int oldChunkStart = oldIndex;
            int newChunkStart = newIndex;

            // collect whitespace in the old text - next time both indices will be at non-ws
            while (oldIndex < oldLength && char.IsWhiteSpace(oldText[oldIndex]))
                oldIndex++;

            // collect whitespace in the new text - next time both indices will be at non-ws
            while (newIndex < newLength && char.IsWhiteSpace(newText[newIndex]))
                newIndex++;

            if (oldIndex > oldChunkStart || newIndex > newChunkStart) {
                // some ws collected
                AddChange(oldText, oldChunkStart, oldIndex - oldChunkStart, newText, newChunkStart, newIndex - newChunkStart, changes);
                return true;
            }

            bool oldStartsWithDelimiter = false;
            bool newStartsWithDelimiter = false;

            // collect non-whitespace in the old text - next time both indices will be at whitespace or a delimiter
            while (oldIndex < oldLength) {
                char oldChar = oldText[oldIndex];
                if (char.IsWhiteSpace(oldChar))
                    break;

                oldIndex++;
            }

            while (newIndex < newLength) {
                char newChar = newText[newIndex];
                if (char.IsWhiteSpace(newChar))
                    break;

                newIndex++;
            }

            // If both start with a delimiter, then move them past it
            if (oldStartsWithDelimiter && newStartsWithDelimiter) {
                oldIndex += 1;
                newIndex += 1;
            }

            AddChange(oldText, oldChunkStart, oldIndex - oldChunkStart, newText, newChunkStart, newIndex - newChunkStart, changes);
            return true;
        }
Beispiel #2
0
        static void AddChange(TextChange tc, List<TextChange> changes) {
            if (changes.Count > 0) {
                TextChange lastChange = changes[changes.Count - 1];

                // Check if new change can be merged with the last one
                if (tc.Position == lastChange.Position + lastChange.Length) {
                    if (lastChange.NewText.Length == 0 && tc.NewText.Length == 0) // both delete
                    {
                        lastChange.Length += tc.Length;
                        return;
                    } else if (lastChange.NewText.Length > 0 && tc.NewText.Length > 0) // both insert or replace
                      {
                        lastChange.Length += tc.Length;
                        lastChange.NewText += tc.NewText;
                        return;
                    }
                }
            }

            changes.Add(tc);
        }
Beispiel #3
0
        static bool NextChunk(string oldText, ref int oldIndex, string newText, ref int newIndex, List <TextChange> changes)
        {
            int oldLength = oldText.Length;
            int newLength = newText.Length;

            if (oldIndex >= oldLength && newIndex >= newLength)
            {
                return(false);
            }

            if (oldIndex >= oldLength && newIndex < newLength)
            {
                // new text is longer, this is the last chunk
                var tc = new TextChange(oldLength, 0, newText.Substring(newIndex));
                AddChange(tc, changes);
                return(false);
            }

            if (newIndex >= newLength && oldIndex < oldLength)
            {
                // old text is longer, this is the last chunk
                var tc = new TextChange(oldIndex, oldLength - oldIndex, string.Empty);
                AddChange(tc, changes);
                return(false);
            }

            int oldChunkStart = oldIndex;
            int newChunkStart = newIndex;

            // collect whitespace in the old text - next time both indices will be at non-ws
            while (oldIndex < oldLength && char.IsWhiteSpace(oldText[oldIndex]))
            {
                oldIndex++;
            }

            // collect whitespace in the new text - next time both indices will be at non-ws
            while (newIndex < newLength && char.IsWhiteSpace(newText[newIndex]))
            {
                newIndex++;
            }

            if (oldIndex > oldChunkStart || newIndex > newChunkStart)
            {
                // some ws collected
                AddChange(oldText, oldChunkStart, oldIndex - oldChunkStart, newText, newChunkStart, newIndex - newChunkStart, changes);
                return(true);
            }

            bool oldStartsWithDelimiter = false;
            bool newStartsWithDelimiter = false;

            // collect non-whitespace in the old text - next time both indices will be at whitespace or a delimiter
            while (oldIndex < oldLength)
            {
                char oldChar = oldText[oldIndex];
                if (char.IsWhiteSpace(oldChar))
                {
                    break;
                }

                oldIndex++;
            }

            while (newIndex < newLength)
            {
                char newChar = newText[newIndex];
                if (char.IsWhiteSpace(newChar))
                {
                    break;
                }

                newIndex++;
            }

            // If both start with a delimiter, then move them past it
            if (oldStartsWithDelimiter && newStartsWithDelimiter)
            {
                oldIndex += 1;
                newIndex += 1;
            }

            AddChange(oldText, oldChunkStart, oldIndex - oldChunkStart, newText, newChunkStart, newIndex - newChunkStart, changes);
            return(true);
        }
Beispiel #4
0
        static void AddChange(
            string oldText,
            int oldChunkStart,
            int oldChunkLength,
            string newText,
            int newChunkStart,
            int newChunkLength,
            List<TextChange> changes) {
            int maxCharsToTrim = Math.Min(oldChunkLength, newChunkLength);
            int i;

            // trim off matching characters from the start
            for (i = 0; i < maxCharsToTrim; i++) {
                if (oldText[oldChunkStart + i] != newText[newChunkStart + i])
                    break;
            }

            if (i > 0) {
                oldChunkStart += i;
                newChunkStart += i;
                oldChunkLength -= i;
                newChunkLength -= i;
                maxCharsToTrim -= i;
            }

            // trim off matching characters from the end
            int oldChunkLastIndex = oldChunkStart + oldChunkLength - 1;
            int newChunkLastIndex = newChunkStart + newChunkLength - 1;
            for (i = 0; i < maxCharsToTrim; i++) {
                if (oldText[oldChunkLastIndex - i] != newText[newChunkLastIndex - i])
                    break;
            }

            if (i > 0) {
                oldChunkLength -= i;
                newChunkLength -= i;
            }

            if (oldChunkLength != 0 || newChunkLength != 0) {
                if (newChunkLength > 0) {
                    // Dev12 933254: Don't allow a \r\n at the end to get broken apart
                    //  At some point we may want to handle more of the \r\n splitting cases,
                    //  but this is the only one that we know comes up (due to us converting
                    //  a \n to a \r\n
                    newChunkLastIndex = newChunkStart + newChunkLength - 1;
                    if ((newText[newChunkLastIndex] == '\r') && (newChunkLastIndex + 1 < newText.Length) && (newText[newChunkLastIndex + 1] == '\n')) {
                        newChunkLength += 1;
                        oldChunkLength += 1;
                    }
                }

                string newChunkText = newText.Substring(newChunkStart, newChunkLength);

                var tc = new TextChange(oldChunkStart, oldChunkLength, newChunkText);
                AddChange(tc, changes);
            }
        }
Beispiel #5
0
        static void AddChange(
            string oldText,
            int oldChunkStart,
            int oldChunkLength,
            string newText,
            int newChunkStart,
            int newChunkLength,
            List <TextChange> changes)
        {
            int maxCharsToTrim = Math.Min(oldChunkLength, newChunkLength);
            int i;

            // trim off matching characters from the start
            for (i = 0; i < maxCharsToTrim; i++)
            {
                if (oldText[oldChunkStart + i] != newText[newChunkStart + i])
                {
                    break;
                }
            }

            if (i > 0)
            {
                oldChunkStart  += i;
                newChunkStart  += i;
                oldChunkLength -= i;
                newChunkLength -= i;
                maxCharsToTrim -= i;
            }

            // trim off matching characters from the end
            int oldChunkLastIndex = oldChunkStart + oldChunkLength - 1;
            int newChunkLastIndex = newChunkStart + newChunkLength - 1;

            for (i = 0; i < maxCharsToTrim; i++)
            {
                if (oldText[oldChunkLastIndex - i] != newText[newChunkLastIndex - i])
                {
                    break;
                }
            }

            if (i > 0)
            {
                oldChunkLength -= i;
                newChunkLength -= i;
            }

            if (oldChunkLength != 0 || newChunkLength != 0)
            {
                if (newChunkLength > 0)
                {
                    // Dev12 933254: Don't allow a \r\n at the end to get broken apart
                    //  At some point we may want to handle more of the \r\n splitting cases,
                    //  but this is the only one that we know comes up (due to us converting
                    //  a \n to a \r\n
                    newChunkLastIndex = newChunkStart + newChunkLength - 1;
                    if ((newText[newChunkLastIndex] == '\r') && (newChunkLastIndex + 1 < newText.Length) && (newText[newChunkLastIndex + 1] == '\n'))
                    {
                        newChunkLength += 1;
                        oldChunkLength += 1;
                    }
                }

                string newChunkText = newText.Substring(newChunkStart, newChunkLength);

                var tc = new TextChange(oldChunkStart, oldChunkLength, newChunkText);
                AddChange(tc, changes);
            }
        }