/// <summary>
        ///     Destructively Copies the whole MarkupString Structure into the given MarkupString Object.
        /// </summary>
        /// <param name="newMarkupString">The MarkupString object to copy into.</param>
        /// <returns>The newMarkupString, now filled with this MarkupString's information.</returns>
        public MarkupString CopyInto(MarkupString newMarkupString)
        {
            if (this.IsString())
            {
                newMarkupString.beneathList  = null;
                newMarkupString.stringWeight = null;
                newMarkupString.MyMarkup     = null;
                newMarkupString.bareString   = new StringBuilder();
                newMarkupString.bareString.Append(this.bareString);
                return(newMarkupString);
            }

            // Implied else.
            newMarkupString.beneathList  = new List <MarkupString>();
            newMarkupString.stringWeight = new List <int>();
            newMarkupString.MyMarkup     = new Markup(this.MyMarkup);
            foreach (MarkupString mySubMarkupString in this.beneathList)
            {
                newMarkupString.bareString = null;
                var thisOne = new MarkupString();
                newMarkupString.beneathList.Add(mySubMarkupString.CopyInto(thisOne));
                newMarkupString.stringWeight.Add(thisOne.Weight());
            }

            return(newMarkupString);
        }
Beispiel #2
0
        /// <summary>
        ///     An edit function that replaces the position->range with a copy of the new MarkupString.
        /// </summary>
        /// <param name="newMarkupString">The new MarkupString to copy and insert into this structure.</param>
        /// <param name="position">The position where the edit begins, based on an insert position.</param>
        /// <param name="length">The length of string to 'replace' with this edit.</param>
        /// <returns>The MarkupString itself.</returns>
        public MarkupString Replace(MarkupString newMarkupString, int position, int length)
        {
            var replacement = new MarkupString(newMarkupString);

            Insert(replacement, position);
            Remove(position + replacement.Weight(), length);
            return(this);
        }
Beispiel #3
0
        /// <summary>
        ///     This function returns the position of the MarkupString after concatenating two existing ones.
        ///     <remarks>It is up to another function to link this result in properly.</remarks>
        /// </summary>
        /// <param name="left">MarkupString on the left.</param>
        /// <param name="right">MarkupString on the right.</param>
        /// <returns>A MarkupString that simply has concatenated the two MarkupStrings.</returns>
        public MarkupString Concat(MarkupString left, MarkupString right)
        {
            var newMarkupString = new MarkupString();

            newMarkupString.beneathList.Add(left);
            newMarkupString.stringWeight.Add(left.Weight());

            newMarkupString.beneathList.Add(right);
            newMarkupString.stringWeight.Add(right.Weight());

            return(newMarkupString);
        }
        /// <summary>
        ///     The work-horse for destructively copying a substring set of a MarkupString into the given MarkupString object.
        /// </summary>
        /// <param name="newMarkupString">The MarkupString object to copy into.</param>
        /// <param name="position">The zero-based starting character position in this instance.</param>
        /// <param name="length">The number of characters in the substring.</param>
        private void CopySubstringInto(MarkupString newMarkupString, int position, int length)
        {
            if (this.IsString())
            {
                newMarkupString.MyMarkup     = null;
                newMarkupString.beneathList  = null;
                newMarkupString.stringWeight = null;
                newMarkupString.bareString   = new StringBuilder(this.bareString.ToString().Substring(position, length));
            }
            else
            {
                newMarkupString.MyMarkup     = new Markup(this.MyMarkup);
                newMarkupString.beneathList  = new List <MarkupString>();
                newMarkupString.stringWeight = new List <int>();
                newMarkupString.bareString   = null;

                // We can't do this in parallel. Must be done in-order.
                foreach (MarkupString markupStringItem in this.beneathList)
                {
                    // We're done if we have nothing else to add to the substring node.
                    if (length <= 0)
                    {
                        break;
                    }

                    // If the weight is less than the position, or equal to, this is not where we want to copy from.
                    // So reduce the relative-position and try again.
                    if (markupStringItem.Weight() <= position)
                    {
                        position -= markupStringItem.Weight();
                        continue;
                    }

                    int maxCut = markupStringItem.Weight() - position;
                    int curCut = maxCut < length ? maxCut : length;

                    var thisOne = new MarkupString();
                    markupStringItem.CopySubstringInto(thisOne, position, curCut);

                    newMarkupString.beneathList.Add(thisOne);
                    newMarkupString.stringWeight.Add(thisOne.Weight());

                    length  -= curCut;
                    position = 0;
                }
            }
        }
Beispiel #5
0
 /// <summary>
 ///     Appends a MarkupString to the end of this instance of MarkupString.
 /// </summary>
 /// <param name="markupStringArg">The MarkupString being added to this instance.</param>
 /// <returns>The MarkupString itself.</returns>
 public MarkupString Append(MarkupString markupStringArg)
 {
     beneathList.Add(markupStringArg);
     stringWeight.Add(markupStringArg.Weight());
     return(this);
 }
Beispiel #6
0
        /// <summary>
        ///     The InsertString will put markupStringArg into the position in the MarkupString structure.
        ///     To do this, it may split up a string beneath it. After all, the node is expected to be Marked Up.
        /// </summary>
        /// <param name="markupStringArg">The MarkupString to insert. Please make sure to give it a Copy!</param>
        /// <param name="position">The position into which to insert. See remarks for insertion logic.</param>
        /// <returns>The MarkupString itself.</returns>
        public MarkupString Insert(MarkupString markupStringArg, int position)
        {
            if (IsString())
            {
                beneathList  = new List <MarkupString>();
                stringWeight = new List <int>();
                MyMarkup     = new Markup(); // Blank Markup Transition

                var rightside = bareString.ToString().Substring(position);
                var leftside  = bareString.ToString().Substring(0, bareString.Length - rightside.Length);

                beneathList.Add(new MarkupString(leftside));
                beneathList.Add(new MarkupString(markupStringArg));
                beneathList.Add(new MarkupString(rightside));

                bareString = null;

                stringWeight.Add(beneathList[0].Weight());
                stringWeight.Add(beneathList[1].Weight());
                stringWeight.Add(beneathList[2].Weight());
            }
            else
            {
                var targetPosition = position;

                // We need to find the way this string is now 'split', and leave the 'remainder' up to another call of InsertString.
                var passedWeights = stringWeight.TakeWhile(val => (targetPosition -= val) >= 0).Count();

                /* Warning: here, a position of 3 generates a targetPosition of -5 after noticing a weight 8. The position it needs to
                 *  go into is 3. But had it passed over a weight of 2, the targetposition would be '1' for the /next/ unit. Which is correct.
                 *
                 * But if that had a weight of 4, it'd end up being 1-4 = -3. We need to re-add the last step, on which the evaluation failed.
                 */
                if (targetPosition == 0)
                {
                    // We must place it 'between', at the beginning, or at the 'end' of a beneathList.
                    // We know how many elements in we should be... so:
                    // If count is at 0, it's an insert.
                    // If count is equal to stringWeight.Count, append at end.
                    // Otherwise, pass the new targetPosition to insert into the String.
                    beneathList.Insert(passedWeights, markupStringArg);
                    stringWeight.Insert(passedWeights, markupStringArg.Weight());
                }
                else
                {
                    // This is the adjustment for the 'last step reduction' error.
                    targetPosition += stringWeight[passedWeights];

                    beneathList[passedWeights].Insert(markupStringArg, targetPosition);
                    stringWeight[passedWeights] += markupStringArg.Weight();

                    if (!beneathList[passedWeights].MyMarkup.IsOnlyInherit())
                    {
                        return(this);
                    }

                    // If the below is now an empty (OnlyInherit) Markup, we can 'pull it up'.
                    // That is to say, we can put its individual beneathLists in the position where we had our old one.
                    // If the item below is not an empty (OnlyInherit) Markup, then it wasn't the item below that we did
                    // the final insert into.
                    var reference = beneathList[passedWeights];
                    beneathList.RemoveAt(passedWeights);
                    stringWeight.RemoveAt(passedWeights);
                    beneathList.InsertRange(passedWeights, reference.beneathList);
                    stringWeight.InsertRange(passedWeights, reference.stringWeight);
                }
            }

            return(this);
        }