syntaxdocument.cs

来自「Fireball.CodeEditor is an source code ed」· CS 代码 · 共 1,880 行 · 第 1/3 页

CS
1,880
字号
		}

		/// <summary>
		/// Gets a Range from a given text
		/// </summary>
		/// <param name="text"></param>
		/// <param name="xPos"></param>
		/// <param name="yPos"></param>
		/// <returns></returns>
		public TextRange GetRangeFromText(string text, int xPos, int yPos)
		{
			string t = text.Replace(Environment.NewLine, "\n");
			string[] lines = t.Split("\n".ToCharArray());
			TextRange r = new TextRange();
			r.FirstColumn = xPos;
			r.FirstRow = yPos;
			r.LastRow = lines.Length - 1 + yPos;
			r.LastColumn = lines[lines.Length - 1].Length;
			if (r.FirstRow == r.LastRow)
				r.LastColumn += r.FirstColumn;

			return r;
		}

		public void AddToUndoList(UndoBlock undo)
		{
			//store the undo action in a actiongroup
			UndoBlockCollection ActionGroup = new UndoBlockCollection();
			ActionGroup.Add(undo);

			AddToUndoList(ActionGroup);
		}

		/// <summary>
		/// Add an action to the undo stack
		/// </summary>
		/// <param name="ActionGroup">action to add</param>
		public void AddToUndoList(UndoBlockCollection ActionGroup)
		{
			//int count=UndoBuffer.Count-UndoStep;
//			if (count>0)
//			{
//				System.Windows.Forms.MessageBox.Show (UndoStep.ToString ());
//				System.Windows.Forms.MessageBox.Show (count.ToString ());
//			}

			UndoBuffer.ClearFrom(UndoStep);

			//	System.Windows.Forms.MessageBox.Show (UndoBuffer.Count.ToString());		
			UndoBuffer.Add(ActionGroup);
			UndoStep++;
			this.OnUndoBufferChanged();
		}

		/// <summary>
		/// Perform an undo action
		/// </summary>
		/// <returns>The position where the caret should be placed</returns>
		public TextPoint Undo()
		{
			if (UndoStep == 0)
				return new TextPoint(-1, -1);


			UndoBlockCollection ActionGroup = (UndoBlockCollection) this.UndoBuffer[UndoStep - 1];
			UndoBlock undo = (UndoBlock) ActionGroup[0];

			for (int i = ActionGroup.Count - 1; i >= 0; i--)
			{
				undo = (UndoBlock) ActionGroup[i];
				//TextPoint tp=new TextPoint (undo.Position.X,undo.Position.Y);
				switch (undo.Action)
				{
					case UndoAction.DeleteRange:
						InsertText(undo.Text, undo.Position.X, undo.Position.Y, false);
						break;
					case UndoAction.InsertRange:
						{
							TextRange r = GetRangeFromText(undo.Text, undo.Position.X, undo.Position.Y);
							DeleteRange(r, false);
						}
						break;
					default:
						break;
				}
			}

			UndoStep--;
			this.ResetVisibleRows();

			//no undo steps left , the document is not dirty
			if (UndoStep == 0)
				Modified = false;

			TextPoint tp = new TextPoint(undo.Position.X, undo.Position.Y);
			OnUndoBufferChanged();
			return tp;

		}

		public void AutoIndentSegment(Segment Segment)
		{
			if (Segment == null)
				Segment = this[0].StartSegment;

			Row start = Segment.StartRow;
			Row end = Segment.EndRow;
			if (start == null)
				start = this[0];

			if (end == null)
				end = this[this.Count - 1];


			for (int i = start.Index; i <= end.Index; i++)
			{
				Row r = this[i];
				int depth = r.Indent;
				string text = r.Text.Substring(r.GetLeadingWhitespace().Length);
				string indent = new string('\t', depth);
				r.Text = indent + text;
			}
			this.ResetVisibleRows();

		}

		//Returns the segment object at the given position
		/// <summary>
		/// Gets a Segment object form a given column , Row index
		/// (This only applies if the row is fully parsed)
		/// </summary>
		/// <param name="p">Column and Rowindex</param>
		/// <returns>Segment object at the given position</returns>
		public Segment GetSegmentFromPos(TextPoint p)
		{
			Row xtr = this[p.Y];
			int CharNo = 0;

			if (xtr.Count == 0)
				return xtr.StartSegment;

			Segment prev = xtr.StartSegment;
            Word w;
            //foreach (Word w in xtr)
            for (int i = 0; i < xtr.Count; i++)
            {
                w = xtr[i];

				if (w.Text.Length + CharNo > p.X)
				{
					if (CharNo == p.X)
						return prev;
					else
						return w.Segment;
				}
				else
				{
					CharNo += w.Text.Length;
					prev = w.Segment;
				}
			}

			return xtr.EndSegment;
		}

		//the specific word that contains the char in point p
		/// <summary>
		/// Gets a Word object form a given column , Row index
		/// (this only applies if the row is fully parsed)
		/// </summary>
		/// <param name="p">Column and Rowindex</param>
		/// <returns>Word object at the given position</returns>
		public Word GetWordFromPos(TextPoint p)
		{
			Row xtr = this[p.Y];
			int CharNo = 0;
			Word CorrectWord = null;

            Word w;
			//foreach (Word w in xtr)
            for(int i = 0; i< xtr.Count;i++)
			{
                w = xtr[i];

				if (CorrectWord != null)
				{
					if (w.Text == "")
						return w;
					else
						return CorrectWord;
				}

				if (w.Text.Length + CharNo > p.X || w == xtr[xtr.Count - 1])
				{
					//return w;
					CorrectWord = w;
				}
				else
				{
					CharNo += w.Text.Length;
				}
			}
			return CorrectWord;
		}

		//the specific word that contains the char in point p
		/// <summary>
		/// Gets a Word object form a given column , Row index
		/// (this only applies if the row is fully parsed)
		/// </summary>
		/// <param name="p">Column and Rowindex</param>
		/// <returns>Word object at the given position</returns>
		public Word GetFormatWordFromPos(TextPoint p)
		{
			Row xtr = this[p.Y];
			int CharNo = 0;
			Word CorrectWord = null;
			//foreach (Word w in xtr.FormattedWords)
            for(int i = 0; i< xtr.FormattedWords.Count;i++)
			{
                Word w = xtr.FormattedWords[i];

				if (CorrectWord != null)
				{
					if (w.Text == "")
						return w;
					else
						return CorrectWord;
				}

				if (w.Text.Length + CharNo > p.X || w == xtr[xtr.Count - 1])
				{
					//return w;
					CorrectWord = w;
				}
				else
				{
					CharNo += w.Text.Length;
				}
			}
			return CorrectWord;
		}

		/// <summary>
		/// Call this method to make the document raise the RowParsed event
		/// </summary>
		/// <param name="row"></param>
		public void InvokeRowParsed(Row row)
		{
			this.OnRowParsed(row);
		}


		/// <summary>
		/// Call this method to recalculate the visible rows
		/// </summary>
		public void ResetVisibleRows()
		{
			InternalResetVisibleRows();
		}

		private void InternalResetVisibleRows()
		{
//			if (System.DateTime.Now > new DateTime (2002,12,31))
//			{
//				
//				this.mDocument = new RowCollection ();
//				this.Add ("BETA VERSION EXPIRED");
//				VisibleRows = this.mDocument;
//				return;
//			}

			if (!this.mFolding)
			{
				VisibleRows = mDocument;
				this.NeedResetRows = false;
			}
			else
			{
				this.NeedResetRows = false;
				VisibleRows = new RowCollection(); //.Clear ();			
				int RealRow = 0;
				Row r = null;
				for (int i = 0; i < this.Count; i++)
				{
					r = this[RealRow];
					VisibleRows.Add(r);
					bool collapsed = false;
					if (r.CanFold)
						if (r.Expansion_StartSegment.Expanded == false)
						{
							if (r.Expansion_StartSegment.EndWord == null)
							{
							}
							else
							{
								r = r.Expansion_EndRow; // .Expansion_StartSegment.EndRow;
								collapsed = true;
							}
						}

					if (!collapsed)
						RealRow++;
					else
						RealRow = this.IndexOf(r) + 1;

					if (RealRow >= this.Count)
						break;
				}
			}
		}

		/// <summary>
		/// Converts a Column/Row index position into a char index
		/// </summary>
		/// <param name="pos">TextPoint where x is column and y is row index</param>
		/// <returns>Char index in the document text</returns>
		public int PointToIntPos(TextPoint pos)
		{
			int y = 0;
			int p = 0;
			foreach (Row r in this)
			{
				if (y == pos.Y)
					break;
				p += r.Text.Length + Environment.NewLine.Length;
				y++;
			}

			return p + Math.Min(pos.X, this[pos.Y].Text.Length);
		}

		/// <summary>
		/// Converts a char index into a Column/Row index
		/// </summary>
		/// <param name="pos">Char index to convert</param>
		/// <returns>Point where x is column and y is row index</returns>
		public TextPoint IntPosToPoint(int pos)
		{
			int p = 0;
			int y = 0;
			int x = 0;
			foreach (Row r in this)
			{
				p += r.Text.Length + Environment.NewLine.Length;
				if (p > pos)
				{
					p -= r.Text.Length + Environment.NewLine.Length;
					x = pos - p;
					return new TextPoint(x, y);
				}
				y++;
			}
			return new TextPoint(-1, -1);
		}

		/// <summary>
		/// Toggle expansion of a given row
		/// </summary>
		/// <param name="r"></param>
		public void ToggleRow(Row r)
		{
			if (!mFolding)
				return;

			if (r.Expansion_EndRow == null || r.Expansion_StartRow == null)
				return;


//			if (r.IsCollapsed)
//			{
//				r.Expansion_StartSegment.Expanded =	true;
//				ExpandRow(r);
//			}
//			else
//			{
//				r.Expansion_StartSegment.Expanded =	false;
//				CollapseRow(r);
//			}

			if (r.CanFold)
				r.Expanded = !r.Expanded;
			ResetVisibleRows();

			OnChange();
		}

		/// <summary>
		/// Collapse a given row
		/// </summary>
		/// <param name="r">Row to collapse</param>
		private void CollapseRow(Row r)
		{
			//remove rows from visible list
			Row start = r.Expansion_StartRow;
			Row end = r.Expansion_EndRow;
			int count = end.VisibleIndex - start.VisibleIndex - 1;
			int startIndex = start.VisibleIndex + 1;
			for (int i = 0; i <= count; i++)
			{
				this.VisibleRows.RemoveAt(startIndex);
			}
		}

		/// <summary>
		/// Expand a given row
		/// </summary>
		/// <param name="r">Row to expand</param>
		private void ExpandRow(Row r)
		{
			//add rows to visible list...
			Row start = r.Expansion_StartRow;
			Row end = r.Expansion_EndRow;
			int count = end.Index - start.Index - 1;
			int startIndex = start.Index + 1;

			int visIndex = start.VisibleIndex + 1;
			int i = 0;
			while (i <= count)
			{
				Row tmpRow = this[startIndex + i];
				this.VisibleRows.Insert(visIndex, tmpRow);
				if (tmpRow.Expansion_StartSegment != null)
					if (tmpRow.Expansion_StartSegment.Expanded == false)
					{
						tmpRow = tmpRow.Expansion_StartSegment.EndRow;
						i = tmpRow.Index - startIndex;
					}
				visIndex++;
				i++;
			}

			//ResetVisibleRows ();
		}

		/// <summary>
		/// Perform an redo action
		/// </summary>
		/// <returns>The position where the caret should be placed</returns>
		public TextPoint Redo()
		{
			if (UndoStep >= UndoBuffer.Count)
				return new TextPoint(-1, -1);

			UndoBlockCollection ActionGroup = (UndoBlockCollection) this.UndoBuffer[UndoStep];
			UndoBlock undo = (UndoBlock) ActionGroup[0];
			for (int i = 0; i < ActionGroup.Count; i++)
			{
				undo = (UndoBlock) ActionGroup[i];

				switch (undo.Action)
				{
					case UndoAction.InsertRange:
						{
							InsertText(undo.Text, undo.Position.X, undo.Position.Y, false);
						}
						break;
					case UndoAction.DeleteRange:
						{
							TextRange r = GetRangeFromText(undo.Text, undo.Position.X, undo.Position.Y);
							DeleteRange(r, false);
						}
						break;
					default:
						break;
				}
			}

			TextRange ran = GetRangeFromText(undo.Text, undo.Position.X, undo.Position.Y);
			UndoStep++;
			this.ResetVisibleRows();
			OnUndoBufferChanged();
			return new TextPoint(ran.LastColumn, ran.LastRow);

		}

		public Word GetStartBracketWord(Word Start, Pattern End, Segment FindIn)
		{
			if (Start == null || Start.Pattern == null || Start.Segment == null)
				return null;

			int CurrentRow = Start.Row.Index;
			int FirstRow = FindIn.StartRow.Index;
			int x = Start.Index;
			int count = 0;
			while (CurrentRow >= FirstRow)
			{
				for (int i = x; i >= 0; i--)
				{
					Word w = this[CurrentRow][i];
					if (w.Segment == FindIn && w.Type == WordType.xtWord)
					{
						if (w.Pattern == Start.Pattern)
							count++;
						if (w.Pattern == End)
							count--;

						if (count == 0)
							return w;
					}
				}

				if (!Start.Pattern.IsMultiLineBracket)
					break;

				CurrentRow--;
				if (CurrentRow >= 0)
					x = this[CurrentRow].Count - 1;
			}
			return null;
		}


		public Word GetEndBracketWord(Word Start, Pattern End, Segment FindIn)
		{
			if (Start == null || Start.Pattern == null || Start.Segment == null)
				return null;

			int CurrentRow = Start.Row.Index;

			int LastRow = this.Count - 1;
			if (FindIn.EndRow != null)
				LastRow = FindIn.EndRow.Index;


			int x = Start.Index;
			int count = 0;
			while (CurrentRow <= LastRow)
			{
				for (int i = x; i < this[CurrentRow].Count; i++)
				{
					Word w = this[CurrentRow][i];
					if (w.Segment == FindIn && w.Type == WordType.xtWord)
					{
						if (w.Pattern == Start.Pattern)
							count++;
						if (w.Pattern == End)
							count--;

						if (count == 0)
							return w;
					}
				}

				if (!Start.Pattern.IsMultiLineBracket)
					break;

				CurrentRow++;
				x = 0;
			}
			return null;
		}


		/// <summary>
		/// 
		/// </summary>
		~SyntaxDocument()
		{
		}

		protected internal void OnApplyFormatRanges(Row row)
		{
			if (this.FormatRanges == null)
				return;


			if (!this.FormatRanges.RowContainsFormats(row) || row.RowState != RowState.AllParsed)
			{
				row.FormattedWords = row.mWords;
			}
			else
			{
				row.FormattedWords = new WordCollection();
				int i = 0;
				int l = 0;
				int x = 0;
				int ri = row.Index;
				foreach (char c in row.Text)
				{
					Word w = row[i];
					FormatRange fr = FormatRanges.MergeFormats(x, ri);
					Word wn = new Word();
					wn.Text = c.ToString();


					if (fr == null)
					{
						wn.Style = w.Style;
					}
					else
					{
						wn.Style = new TextStyle();
						if (w.Style == null)
							w.Style = new TextStyle();

						wn.Style.BackColor = (fr.BackColor == Color.Empty) ? w.Style.BackColor : fr.BackColor;
						wn.Style.ForeColor = (fr.ForeColor == Color.Empty) ? w.Style.ForeColor : fr.ForeColor;
						wn.InfoTip = fr.InfoTip;
						/*wn.Style.Bold = false;
						wn.Style.Italic = true;
						wn.Style.Underline = false;*/
						if (fr.WaveColor != Color.Empty)
						{
							wn.HasError = true;
							wn.ErrorColor = fr.WaveColor;
						}
					}
					wn.Type = w.Type;
					wn.Segment = w.Segment;
					row.FormattedWords.Add(wn);


					l++;
					if (l == row[i].Text.Length)
					{
						i++;
						l = 0;
					}
					x++;
				}

			}
		}
	}
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?