private static bool FindMatchingCloseQuote(SnapshotPoint startPoint, out SnapshotSpan pairSpan)
        {
            pairSpan = new SnapshotSpan(startPoint, startPoint);

            SnapshotSpan enclosingSpan = PkgDefTokenTagger.GetContinuedLines(pairSpan);

            string lineText = enclosingSpan.GetText();

            int posNameStart, posNameEnd, posValueStart, posValueEnd;

            if (FindNameValueQuotes(out posNameStart, out posNameEnd, out posValueStart, out posValueEnd, ref lineText))
            {
                if (startPoint.Position == enclosingSpan.Start + posNameStart)
                {
                    pairSpan = new SnapshotSpan(startPoint.Snapshot, enclosingSpan.Start.Position + posNameEnd, 1);
                    return(true);
                }
                if (startPoint.Position == enclosingSpan.Start + posValueStart)
                {
                    pairSpan = new SnapshotSpan(startPoint.Snapshot, enclosingSpan.Start.Position + posValueEnd, 1);
                    return(true);
                }
            }
            return(false);
        }
        private static bool FindMatchingCloseChar(SnapshotPoint startPoint, char open, char close, out SnapshotSpan pairSpan)
        {
            pairSpan = new SnapshotSpan(startPoint, startPoint);

            SnapshotSpan enclosingSpan = PkgDefTokenTagger.GetContinuedLines(pairSpan);

            string lineText = enclosingSpan.GetText();

            // start after the open char
            int offset = startPoint.Position - enclosingSpan.Start.Position + 1;

            // walk the rest of the 'line'
            while (offset < lineText.Length)
            {
                char currentChar = lineText[offset];
                if (currentChar == close) // found the close character
                {
                    pairSpan = new SnapshotSpan(startPoint.Snapshot, enclosingSpan.Start.Position + offset, 1);
                    return(true);
                }
                offset++;
            }

            return(false);
        }
        private static bool FindMatchingOpenChar(SnapshotPoint startPoint, char open, char close, out SnapshotSpan pairSpan)
        {
            pairSpan = new SnapshotSpan(startPoint, startPoint);

            SnapshotSpan enclosingSpan = PkgDefTokenTagger.GetContinuedLines(pairSpan);

            string lineText = enclosingSpan.GetText();

            // start to the left of the close char
            int offset = startPoint.Position - enclosingSpan.Start.Position - 1;

            // should not happen, but if the offset is negative, we're done
            if (offset < 0)
            {
                return(false);
            }

            // walk to the beginning of the 'line'
            while (offset >= 0)
            {
                char currentChar = lineText[offset];

                if (currentChar == open)
                {
                    pairSpan = new SnapshotSpan(startPoint.Snapshot, enclosingSpan.Start.Position + offset, 1); //we just want the character itself
                    return(true);
                }
                offset--;
            }
            return(false);
        }
        private static bool FindNameValueQuotes(out int posNameStart, out int posNameEnd, out int posValueStart, out int posValueEnd, ref string text)
        {
            posNameStart  = -1;
            posNameEnd    = -1;
            posValueStart = -1;
            posValueEnd   = -1;

            Group textAfterWhiteSpace = PkgDefTokenTagger.SkipWhiteSpace(text);
            int   posEquals           = -1;

            if (textAfterWhiteSpace.Value[0] == '@')
            {
                posEquals = text.IndexOf('=', textAfterWhiteSpace.Index + 1);
            }
            else if (textAfterWhiteSpace.Value[0] == '"')
            {
                posNameStart = textAfterWhiteSpace.Index;
                posNameEnd   = text.IndexOf('"', posNameStart + 1);
                if (posNameEnd > posNameStart)
                {
                    posEquals = text.IndexOf('=', posNameEnd + 1);
                }
            }

            if (posEquals > -1)
            {
                Group textAfterEquals = PkgDefTokenTagger.SkipWhiteSpace(text.Substring(posEquals + 1));
                if (textAfterEquals != null)
                {
                    int posValue = posEquals + textAfterEquals.Index + 1;
                    if (textAfterEquals.Value.StartsWith(PkgDefTokenStrings.StringExpandSzPrefix))
                    {
                        posValue += PkgDefTokenStrings.StringExpandSzPrefix.Length - 1; // remove one char pos for "
                    }
                    if (text[posValue] == '"')
                    {
                        int posLastQuote = text.LastIndexOf('"');
                        if (posLastQuote > posValue)
                        {
                            posValueStart = posValue;
                            posValueEnd   = posLastQuote;
                        }
                    }
                }
            }
            return((posNameStart > -1) || (posValueStart > -1));
        }
        /// <summary>
        /// Find all of the outline sections in the snapshot
        /// </summary>
        private static List <Region> ParseOutlineSections(ITextSnapshot newSnapshot)
        {
            List <Region> newRegions = new List <Region>();

            Region       currentRegion          = null;
            int          currentRegionLineCount = 0;
            string       lineSep         = "";
            SnapshotSpan currentFullSpan = new SnapshotSpan();

            foreach (ITextSnapshotLine line in newSnapshot.Lines)
            {
                if (!currentFullSpan.IsEmpty && currentFullSpan.Contains(line.Start))
                {
                    continue; // already processed, go get next one
                }

                currentFullSpan = PkgDefTokenTagger.GetContinuedLines(new SnapshotSpan(line.Start, line.End));
                int currentFirstLine = currentFullSpan.Start.GetContainingLine().LineNumber;
                int currentEndLine   = currentFullSpan.End.GetContainingLine().LineNumber;

                string text = currentFullSpan.GetText();

                MatchCollection matches = matchKey.Matches(text);
                if ((matches.Count == 1) && (matches[0].Groups.Count == 2))
                {
                    // close out the previous Region
                    if (currentRegion != null)
                    {
                        newRegions.Add(currentRegion);
                    }

                    // and start a new one
                    currentRegionLineCount = 0;
                    lineSep       = "";
                    currentRegion = new Region()
                    {
                        StartLine   = currentEndLine,
                        StartOffset = currentFullSpan.End.GetContainingLine().Length,
                        EndLine     = currentEndLine,
                        Label       = ellipsis,
                        HoverText   = "" // don't include the key in hover text
                    };
                }
                else if ((currentRegion != null) && (text.Trim() != ""))
                {
                    // accumulate non-blank lines for the hover text
                    if (currentRegionLineCount < MaxHiddenLines)
                    {
                        currentRegion.HoverText += lineSep;
                        currentRegion.HoverText += text;
                        currentRegionLineCount  += currentEndLine - currentFirstLine + 1;
                        lineSep = line.GetLineBreakText();
                    }
                    currentRegion.EndLine = currentEndLine;
                }
            }
            // close out the final Region
            if (currentRegion != null)
            {
                newRegions.Add(currentRegion);
                currentRegion = null;
            }

            return(newRegions);
        }