/// <remarks>
        /// Calculates the fold level of a specific line.
        /// </remarks>
        public List<FoldMarker> GenerateFoldMarkers(IDocument document, string fileName, object parseInfo)
        {
            var parseInformation = parseInfo as DmModelDB;
            if (parseInformation == null || parseInformation.Models == null || parseInformation.Models.Count == 0)
            {
                return null;
            }

            List<FoldMarker> foldMarkers = new List<FoldMarker>();

            foreach (var model in parseInformation.Models.Values)
            {

                var startLine = model.TokenPair.BeginToken.Line -1;
                var startColumn = model.TokenPair.BeginToken.CharPositionInLine;
                var endLine = model.TokenPair.EndToken.Line -1;
                var endColumn = model.TokenPair.EndToken.CharPositionInLine + 1;

                var fold = new FoldMarker(document, startLine, startColumn, endLine, endColumn, FoldType.Unspecified, "class " + model.Name);
                foldMarkers.Add(fold);
            }

            //if (parseInformation.BestCompilationUnit != parseInformation.MostRecentCompilationUnit)
            //{
            //    List<FoldMarker> oldFoldMarkers = GetFoldMarkers(document, parseInformation.BestCompilationUnit);
            //    int lastLine = (foldMarkers.Count == 0) ? 0 : foldMarkers[foldMarkers.Count - 1].EndLine;
            //    int totalNumberOfLines = document.TotalNumberOfLines;
            //    foreach (FoldMarker marker in oldFoldMarkers)
            //    {
            //        if (marker.StartLine > lastLine && marker.EndLine < totalNumberOfLines)
            //            foldMarkers.Add(marker);
            //    }
            //}
            return foldMarkers;
        }
        public ArrayList GenerateFoldMarkers(IDocument document, string fileName, object parseInformation)
        {
            ArrayList foldMarkers = new ArrayList();

            int startLine = Int32.MinValue;
            string foldWord = "";

            for (int x = 0; x < document.LineSegmentCollection.Count; x++)
            {
                LineSegment segment = (LineSegment)document.LineSegmentCollection[x];

                if (segment.Words.Count > 0)
                {
                    TextWord word = (TextWord)segment.Words[0];

                    if (startLine == Int32.MinValue)
                    {
                        if (word.Word.ToLower() == "action" && segment.Words.Count > 2)
                        {
                            startLine = x;

                            for (int y = 2; y < segment.Words.Count; y++)
                            {
                                TextWord comments = (TextWord)segment.Words[y];

                                if (comments.Word != "//")
                                {
                                    foldWord += " " + comments.Word;
                                }
                            }
                        }
                    }
                    else
                    {
                        if (word.Word == "}")
                        {
                            FoldMarker actionMarker = new FoldMarker(document, startLine, 1, x, 1, FoldType.Region, foldWord, false);
                            foldMarkers.Add(actionMarker);
                            startLine = Int32.MinValue;
                            foldWord = "";
                        }
                    }
                }
            }
            return foldMarkers;
        }
		void AddClassMembers(IClass c, List<FoldMarker> foldMarkers, IDocument document)
		{
			if (c.ClassType == ClassType.Delegate) {
				return;
			}
			DomRegion cRegion = c.BodyRegion;
			if (cRegion.IsEmpty) cRegion = c.Region;
			if (cRegion.BeginLine < cRegion.EndLine) {
				FoldMarker newFoldMarker = new FoldMarker(document, cRegion.BeginLine - 1, cRegion.BeginColumn - 1,
				                                          cRegion.EndLine - 1, cRegion.EndColumn, c.ClassType == ClassType.Enum ? FoldType.MemberBody : FoldType.TypeBody);
				if (newFoldMarker.Length > 0) {
					foldMarkers.Add(newFoldMarker);
				}
			}
			foreach (IClass innerClass in c.InnerClasses) {
				AddClassMembers(innerClass, foldMarkers, document);
			}
			
			foreach (IMethod m in c.Methods) {
				if (m.Region.EndLine < m.BodyRegion.EndLine) {
					foldMarkers.Add(new FoldMarker(document, m.Region.EndLine - 1, m.Region.EndColumn - 1,
					                               m.BodyRegion.EndLine - 1, m.BodyRegion.EndColumn - 1, FoldType.MemberBody));
				}
			}
			
			foreach (IProperty p in c.Properties) {
				if (p.Region.EndLine < p.BodyRegion.EndLine) {
					foldMarkers.Add(new FoldMarker(document, p.Region.EndLine - 1, p.Region.EndColumn - 1,
					                               p.BodyRegion.EndLine- 1, p.BodyRegion.EndColumn - 1, FoldType.MemberBody));
				}
			}
			
			foreach (IEvent evt in c.Events) {
				if (evt.Region.EndLine < evt.BodyRegion.EndLine) {
					if (!evt.BodyRegion.IsEmpty) {
						foldMarkers.Add(new FoldMarker(document, evt.Region.EndLine - 1, evt.Region.EndColumn - 1,
						                               evt.BodyRegion.EndLine- 1, evt.BodyRegion.EndColumn - 1, FoldType.MemberBody));
					}
				}
			}
		}
		internal TextLocation GetLogicalColumn(int lineNumber, int visualPosX, out FoldMarker inFoldMarker)
		{
			visualPosX += textArea.VirtualTop.X;
			
			inFoldMarker = null;
			if (lineNumber >= Document.TotalNumberOfLines) {
				return new TextLocation((int)(visualPosX / WideSpaceWidth), lineNumber);
			}
			if (visualPosX <= 0) {
				return new TextLocation(0, lineNumber);
			}
			
			int start = 0; // column
			int posX = 0; // visual position
			
			int result;
			using (Graphics g = textArea.CreateGraphics()) {
				// call GetLogicalColumnInternal to skip over text,
				// then skip over fold markers
				// and repeat as necessary.
				// The loop terminates once the correct logical column is reached in
				// GetLogicalColumnInternal or inside a fold marker.
				while (true) {
					
					LineSegment line = Document.GetLineSegment(lineNumber);
					FoldMarker nextFolding = FindNextFoldedFoldingOnLineAfterColumn(lineNumber, start-1);
					int end = nextFolding != null ? nextFolding.StartColumn : int.MaxValue;
					result = GetLogicalColumnInternal(g, line, start, end, ref posX, visualPosX);
					
					// break when GetLogicalColumnInternal found the result column
					if (result < end)
						break;
					
					// reached fold marker
					lineNumber = nextFolding.EndLine;
					start = nextFolding.EndColumn;
					int newPosX = posX + 1 + MeasureStringWidth(g, nextFolding.FoldText, TextEditorProperties.FontContainer.RegularFont);
					if (newPosX >= visualPosX) {
						inFoldMarker = nextFolding;
						if (IsNearerToAThanB(visualPosX, posX, newPosX))
							return new TextLocation(nextFolding.StartColumn, nextFolding.StartLine);
						else
							return new TextLocation(nextFolding.EndColumn, nextFolding.EndLine);
					}
					posX = newPosX;
				}
			}
			return new TextLocation(result, lineNumber);
		}
 /// <summary>
 /// Create an element fold if the start and end tag are on different lines.
 /// </summary>
 void CreateElementFold(IDocument document, List<FoldMarker> foldMarkers, XmlTextReader reader, XmlFoldStart foldStart)
 {
     int endLine = reader.LineNumber - 1;
     if (endLine > foldStart.Line)
     {
         int endCol = reader.LinePosition + foldStart.Name.Length;
         FoldMarker foldMarker = new FoldMarker(document, foldStart.Line, foldStart.Column, endLine, endCol, FoldType.TypeBody, foldStart.FoldText);
         foldMarkers.Add(foldMarker);
     }
 }
        /// <summary>
        /// Creates a comment fold if the comment spans more than one line.
        /// </summary>
        /// <remarks>The text displayed when the comment is folded is the first line of the comment.</remarks>
        void CreateCommentFold(IDocument document, List<FoldMarker> foldMarkers, XmlTextReader reader)
        {
            if (reader.Value != null)
            {
                string comment = reader.Value.Replace("\r\n", "\n");
                string[] lines = comment.Split('\n');
                if (lines.Length > 1)
                {

                    // Take off 5 chars to get the actual comment start (takes
                    // into account the <!-- chars.

                    int startCol = reader.LinePosition - 5;
                    int startLine = reader.LineNumber - 1;

                    // Add 3 to the end col value to take into account the '-->'
                    int endCol = lines[lines.Length - 1].Length + startCol + 3;
                    int endLine = startLine + lines.Length - 1;
                    string foldText = String.Concat("<!--", lines[0], "-->");
                    FoldMarker foldMarker = new FoldMarker(document, startLine, startCol, endLine, endCol, FoldType.TypeBody, foldText);
                    foldMarkers.Add(foldMarker);
                }
            }
        }
        private List<FoldMarker> GetFoldMarkers(IDocument doc, IBaseScope root)
        {
            List<FoldMarker> foldMarkers = new List<FoldMarker>();
            if (!(root is TypeScope))
            {
                Position pos = root.GetPosition();
                if (pos.file_name != null)
                {
                    Position head_pos = root.GetHeaderPosition();
                    FoldMarker newFoldMarker = null;
                    if (head_pos.file_name == null)
                        newFoldMarker = new FoldMarker(doc, pos.line - 1, pos.column - 1, pos.end_line - 1, pos.end_column, FoldType.MemberBody);
                    else
                        newFoldMarker = new FoldMarker(doc, head_pos.end_line - 1, head_pos.end_column - 1, pos.end_line - 1, pos.end_column, FoldType.MemberBody);
                    if (newFoldMarker.Length > 0)
                    {
                        foldMarkers.Add(newFoldMarker);
                    }
                }
                if (root.Regions != null)
                {
                    foreach (Position p in root.Regions)
                    {
                        foldMarkers.Add(new FoldMarker(doc, p.line - 1, p.column, p.end_line - 1, p.end_column, FoldType.MemberBody, p.fold_text));
                    }
                }
                Position body_pos = root.GetBodyPosition();
                if (body_pos.file_name != null)
                {
                    FoldMarker newFoldMarker = null;
                    newFoldMarker = new FoldMarker(doc, body_pos.line - 1, body_pos.column - 1, body_pos.end_line - 1, body_pos.end_column, FoldType.MemberBody);
                    if (newFoldMarker.Length > 0)
                    {
                        foldMarkers.Add(newFoldMarker);
                    }
                }

            }
            foreach (IBaseScope ss in root.Members)
            {
                if (ss is ITypeScope)
                {
                    Position body_pos = ss.GetBodyPosition();
                    Position head_pos = ss.GetHeaderPosition();
                    if (head_pos.file_name == null || body_pos.file_name == null) continue;
                    FoldMarker newFoldMarker = new FoldMarker(doc, head_pos.end_line - 1, head_pos.end_column - 1, body_pos.end_line - 1, body_pos.end_column, FoldType.TypeBody);
                    if (newFoldMarker.Length > 0)
                    {
                        foldMarkers.Add(newFoldMarker);
                    }
                    foldMarkers.AddRange(GetFoldMarkers(doc, ss));
                }
                else if (ss is IProcScope)
                {
                    FoldType ft = FoldType.MemberBody;
                    Position head_pos = ss.GetHeaderPosition();
                    Position body_pos = ss.GetBodyPosition();
                    if (head_pos.file_name == null || body_pos.file_name == null) continue;
                    FoldMarker newFoldMarker = new FoldMarker(doc, head_pos.end_line - 1, head_pos.end_column, body_pos.end_line - 1, body_pos.end_column, ft);
                    if (newFoldMarker.Length > 0)
                    {
                        foldMarkers.Add(newFoldMarker);
                    }
                }
                else if (ss is IImplementationUnitScope)
                    foldMarkers.AddRange(GetFoldMarkers(doc, ss));
            }

            return foldMarkers;
        }
        internal TextLocation GetLogicalColumn(int lineNumber, int visualPosX, out FoldMarker inFoldMarker)
        {
            visualPosX += textArea.VirtualTop.X;

            inFoldMarker = null;
            if (lineNumber >= Document.TotalNumberOfLines) {
                return new TextLocation((int)(visualPosX / WideSpaceWidth), lineNumber);
            }
            if (visualPosX <= 0) {
                return new TextLocation(0, lineNumber);
            }

            int start = 0; // column
            int posX = 0; // visual position

            int result;
            using (Graphics g = textArea.CreateGraphics()) {
                do {
                    LineSegment line = Document.GetLineSegment(lineNumber);
                    FoldMarker nextFolding = FindNextFoldedFoldingOnLineAfterColumn(lineNumber, start-1);
                    int end = nextFolding != null ? nextFolding.StartColumn : int.MaxValue;
                    result = GetLogicalColumnInternal(g, line, start, end, ref posX, visualPosX);
                    if (result < 0) {
                        // reached fold marker
                        lineNumber = nextFolding.EndLine;
                        start = nextFolding.EndColumn;
                        int newPosX = posX + 1 + MeasureStringWidth(g, nextFolding.FoldText, TextEditorProperties.FontContainer.RegularFont);
                        if (newPosX >= visualPosX) {
                            inFoldMarker = nextFolding;
                            if (IsNearerToAThanB(visualPosX, posX, newPosX))
                                return new TextLocation(nextFolding.StartColumn, nextFolding.StartLine);
                            else
                                return new TextLocation(nextFolding.EndColumn, nextFolding.EndLine);
                        }
                        posX = newPosX;
                    }
                } while (result < 0);
            }
            return new TextLocation(result, lineNumber);
        }