Exemplo n.º 1
0
        /// <summary>
        /// Gets a list of all marked ranges in the specified range. The current selection is updated to the end of the range to scan.
        /// </summary>
        /// <param name="rangeToScan">The Range to scan.</param>
        /// <param name="ShadingColor">The color for redaction marks in the document.</param>
        /// <param name="mergeAdjacent">True to merge adjacent ranges with identical formatting, False otherwise.</param>
        /// <returns>A List of RangeDataEx objects containing each marked subrange.</returns>
        internal static List <RangeDataEx> GetAllMarkedRanges(Word.Range rangeToScan, Word.WdColor ShadingColor, bool mergeAdjacent)
        {
            object Missing             = Type.Missing;
            object CollapseStart       = Word.WdCollapseDirection.wdCollapseStart;
            object CharacterFormatting = Word.WdUnits.wdCharacterFormatting;

            int LastPosition;
            int OriginalPosition;
            List <RangeDataEx> Ranges             = new List <RangeDataEx>();
            List <RangeDataEx> RangesToDelete     = new List <RangeDataEx>();
            List <RangeDataEx> ConcatenatedRanges = new List <RangeDataEx>();

            //we don't redact comments - if that's where we are, return
            if (rangeToScan.StoryType == Word.WdStoryType.wdCommentsStory)
            {
                return(ConcatenatedRanges);
            }

            //move the selection to the beginning of the requested range
            rangeToScan.Select();

            Word.Selection CurrentSelection = rangeToScan.Application.Selection;
            CurrentSelection.Collapse(ref CollapseStart);
            OriginalPosition = CurrentSelection.Start;

            //scan for distinct ranges of formatting
            do
            {
                //update LastPosition
                LastPosition = CurrentSelection.Start;

                //move to the next position
                CurrentSelection.Move(ref CharacterFormatting, ref Missing);

                //BUG 3913: if we detect that .Move has moved us out of the scan range (which appears to happen because of a Word bug)
                // break out and don't save the current range
                if (CurrentSelection.Start < OriginalPosition)
                {
                    CurrentSelection.End = rangeToScan.End;
                    break;
                }

                //store that range
                if (CurrentSelection.Start != LastPosition && rangeToScan.End != LastPosition)
                {
                    if (mergeAdjacent)
                    {
                        Ranges.Add(new RangeDataEx(LastPosition, CurrentSelection.Start < rangeToScan.End ? CurrentSelection.Start : rangeToScan.End, new RangeDataEx())); //since we're going to merge, don't fetch the extra properties
                    }
                    else
                    {
                        Word.Font CurrentFont = CurrentSelection.Font;
                        Ranges.Add(new RangeDataEx(LastPosition, CurrentSelection.Start < rangeToScan.End ? CurrentSelection.Start : rangeToScan.End, CurrentFont.Name, CurrentFont.Size, CurrentFont.Bold, CurrentFont.Italic, CurrentSelection.OMaths.Count > 0));
                    }
                }
            }while (CurrentSelection.End <= rangeToScan.End && CurrentSelection.End > LastPosition);

            if (CurrentSelection.End != rangeToScan.End)
            {
                if (mergeAdjacent)
                {
                    Ranges.Add(new RangeDataEx(CurrentSelection.End, rangeToScan.End, new RangeDataEx())); //since we're going to merge, don't fetch the extra properties
                }
                else
                {
                    Word.Font CurrentFont = CurrentSelection.Font;
                    Ranges.Add(new RangeDataEx(CurrentSelection.End, rangeToScan.End, CurrentFont.Name, CurrentFont.Size, CurrentFont.Bold, CurrentFont.Italic, CurrentSelection.OMaths.Count > 0));
                }
            }

            //go through those ranges and check if they are marked
            foreach (RangeDataEx UniqueRange in Ranges)
            {
                rangeToScan.Start = UniqueRange.Start;
                rangeToScan.End   = UniqueRange.End;

                //remove the range from the list
                if (!IsMarkedRange(rangeToScan, ShadingColor))
                {
                    RangesToDelete.Add(UniqueRange);
                }
            }

            //clean out the list
            foreach (RangeDataEx RangeToDelete in RangesToDelete)
            {
                Ranges.Remove(RangeToDelete);
            }
            RangesToDelete.Clear();

            //concatenate ranges that are next to each other
            int?Start = null;
            int?End   = null;

            for (int i = 0; i < Ranges.Count; i++)
            {
                //set start and end points
                if (Start == null)
                {
                    Start = Ranges[i].Start;
                }
                if (End == null)
                {
                    End = Ranges[i].End;
                }

                if ((i + 1) < Ranges.Count && (mergeAdjacent || (Ranges[i].InMath && Ranges[i + 1].InMath) || Ranges[i].IdenticalTo(Ranges[i + 1])) && End == Ranges[i + 1].Start)
                {
                    End = null;
                }
                else
                {
                    ConcatenatedRanges.Add(new RangeDataEx((int)Start, (int)End, Ranges[i]));
                    Start = End = null;
                }
            }

            //return the marked ranges
            return(ConcatenatedRanges);
        }