⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 textline.cs

📁 c#精彩编程百例(源代码)
💻 CS
字号:
//  TextLine.cs
//  Copyright (c) 2000 Mike Krueger
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

using System;
using System.Drawing;
using System.Collections;

namespace SharpDevelop.Internal.Text {
	
	/// <summary>
	/// In this class are single lines saved, it colorizes the line.
	/// (It devides it up into single words, when you set the Text property)
	/// </summary>
	public class TextLine
	{
		string      line;
		TextWord[]  word;
		TextBuffer  buffer;
		public bool Selected  = false;
		public bool foldon    = false;
		public bool foldoff   = false;
		public bool Visible   = true;
		int  linenumber;
		
		public int LineNumber {
			get {
				return linenumber;
			}
			set {
				linenumber = value;
			}
		}
		
		public TextLine(TextBuffer buffer, int linenumber, string line)
		{
			TextBuffer = buffer;
			Text = line;
		}
		
		public TextWord this[int i] {
			get {
				return word[i];	
			}
			set {
				word[i] = value;
			}
		}
		public TextBuffer TextBuffer {
			get {
				return buffer;
			}
			set {
				buffer = value;
			}
		}
		
		public int Length {
			get {
				return word.Length;
			}
		}
		
		public bool BlockSpanOn = false;
		public bool Span        = false;
		public Span CurSpan     = null;
		
		
		ArrayList words = new ArrayList();
		int       curoffset;
		int       curlength;
		
		/// <summary>
		/// pushes the curWord string on the word list, with the
		/// correct color.
		/// </summary>
		void PushCurWord()
		{
			if (curlength > 0) {
				RuleSet ruleset = TextBuffer.Syntax.GetRuleSet(Span ? CurSpan.Rule : null);
				
				if (true)
					
					if (words.Count > 0) {
						TextWord prevword = ((TextWord)words[words.Count - 1]);
						if (prevword.NotMarked) {
							PrevMarker marker = (PrevMarker)ruleset.PrevMarkers[line, curoffset, curlength];
							if (marker != null)
								prevword.SyntaxColor = marker.Color;
						}
					}
					
					if (Span) {
						SyntaxColor c = null;
						if (CurSpan.Rule == null) 
							c = CurSpan.Color;
						else
							c = TextBuffer.Syntax.GetColor(CurSpan.Rule, line, curoffset, curlength);
						
						if (c == null) {
							c = CurSpan.Color;
							if (c.Color == Color.Transparent)
								c = TextBuffer.Syntax.defaultColor;
						}
						words.Add(new TextWord(line, curoffset, curlength, TextBuffer.Syntax, c));
					} else {
						words.Add(new TextWord(line, curoffset, curlength, TextBuffer.Syntax, TextBuffer.Syntax.GetColor(line, curoffset, curlength)));
					}
					curoffset += curlength;
					curlength = 0;
			}
		}
		
		/// <summary>
		/// get the string, which matches the regular expression expr,
		/// in string s2 at index
		/// </summary>
		string GetRegString(string expr, string s2, int index)
		{
			int j = 0;
			string regexpr = "";
			
			for (int i = 0; i < expr.Length; ++i, ++j) {
				if (index + j >= s2.Length) 
					break;
				
				switch (expr[i]) {
					case '@': // "special" meaning
					++i;
					switch (expr[i]) {
						case '!': // don't match the following expression
						string whatmatch = "";
						++i;
						while (i < expr.Length && expr[i] != '@')
							whatmatch += expr[i++];
						break;
						case '@': // matches @
						regexpr += s2[index + j];
						break;
					}
					
					break;
					default:
						if (expr[i] != s2[index + j])
							return regexpr;
					regexpr += s2[index + j];
					break;
				}
			}
			return regexpr;
		}
		
		/// <summary>
		/// returns true, if the get the string s2 at index matches the expression expr
		/// </summary>
		bool MatchExpr(string expr, string s2, int index)
		{
			for (int i = 0, j = 0; i < expr.Length; ++i, ++j) {
				switch (expr[i]) {
					case '@': // "special" meaning
					++i;
					switch (expr[i]) {
						case '!': // don't match the following expression
						string whatmatch = "";
						++i;
						while (i < expr.Length && expr[i] != '@')
							whatmatch += expr[i++];
						++i;
						
						if (i + whatmatch.Length < expr.Length) {
							int k = 0;
							for (; k < whatmatch.Length; ++k)
								if (s2[index + j + k] != whatmatch[k])
									break;
							if (k >= whatmatch.Length) {
								return false;
							}
						}
						break;
						case '@': // matches @
						if (index + j >= s2.Length || '@' != s2[index + j]) {
							return false;
						}
						break;
					}
					
					break;
					default:
						if (index + j >= s2.Length || expr[i] != s2[index + j]) 
							return false;
					break;
				}
			}
			return true;
		}
		
		Stack  spanstack = new Stack();
		
		public string Text {
			get {
				return line;
			} set {
				words = new ArrayList();
				line = value;
				foldoff = foldon = false;
				bool obo        = BlockSpanOn;
				Span OldSpan    = CurSpan;
				
				curoffset = 0;
				curlength = 0;
				
				int myNumber = 0;
				for (myNumber = 0; myNumber < TextBuffer.Length; ++myNumber)
					if (TextBuffer[myNumber] == this)
						break;
				
				if (myNumber > 0 && TextBuffer[myNumber - 1 ].BlockSpanOn) {
					CurSpan     = TextBuffer[myNumber - 1].CurSpan;
					BlockSpanOn = Span = true;
				} else {
					CurSpan     = null;
					BlockSpanOn = Span = false;
				}
				
				bool delimeter = false;
				
				for (int i = 0; i < line.Length; ++i) {
					char ch = line[i];
				    
					switch (ch) {
						case '{':
							foldon = true;
							goto default;
						case '}':
							if (foldon) {
								foldon = false;
							}
							foldoff = true;
							goto default;
						case ' ':
							PushCurWord();
							words.Add(new TextWord(TextWordType.Space));
							++curoffset;
							break;
						case '\t':
							PushCurWord();
							words.Add(new TextWord(TextWordType.Tab));
							++curoffset;
							break;
						default: {							
							// handle escape chars
							if (ch == '\\') {
								++curlength;
								if (i + 1 < line.Length)
									++curlength;
								PushCurWord();
								++i;
								continue;
							}
							
							// highlight digits
							if (!Span && (Char.IsDigit(ch) || (ch == '.' && i + 1 < line.Length && Char.IsDigit(line[i + 1]))) && curlength == 0) {
								bool ishex = false;
								bool isfloatingpoint = false;
								
								if (ch == '0' && i + 1 < line.Length && Char.ToUpper(line[i + 1]) == 'X') { // hex digits
									string hex = "0123456789ABCDEF";
									++curlength;
									++i; // skip 'x'
									++curlength; 
									ishex = true;
									while (i + 1 < line.Length && hex.IndexOf(Char.ToUpper(line[i + 1])) != -1) {
										++i;
										++curlength;
									}
								} else {
									++curlength; 
									while (i + 1 < line.Length && Char.IsDigit(line[i + 1])) {
										++i;
										++curlength;
									}
								}
								if (!ishex && i + 1 < line.Length && line[i + 1] == '.') {
									isfloatingpoint = true;
									++i;
									++curlength;
									while (i + 1 < line.Length && Char.IsDigit(line[i + 1])) {
										++i;
										++curlength;
									}
								} 
									
								if (i + 1 < line.Length && Char.ToUpper(line[i + 1]) == 'E') {
									isfloatingpoint = true;
									++i;
									++curlength;
									if (i + 1 < line.Length && (line[i + 1] == '+' || line[i + 1] == '-')) {
										++i;
										++curlength;
									}
									while (i + 1 < line.Length && Char.IsDigit(line[i + 1])) {
										++i;
										++curlength;
									}
								}
								
								if (i + 1 < line.Length) {
									char nextch = Char.ToUpper(line[i + 1]);
									if (nextch == 'F' || nextch == 'M' || nextch == 'D') {
										isfloatingpoint = true;
										++i;
										++curlength;
									}
								}
							
								if (!isfloatingpoint) {
									bool isunsigned = false;
									if (i + 1 < line.Length && Char.ToUpper(line[i + 1]) == 'U') {
										++i;
										++curlength;
										isunsigned = true;
									}
									if (i + 1 < line.Length && Char.ToUpper(line[i + 1]) == 'L') {
										++i;
										++curlength;
										if (!isunsigned && i + 1 < line.Length && Char.ToUpper(line[i + 1]) == 'U') {
											++i;
											++curlength;
										}
									}
								}
								
								
								words.Add(new TextWord(line, curoffset, curlength, TextBuffer.Syntax, TextBuffer.Syntax.DigitColor));
								curoffset += curlength;
								curlength = 0;
								continue;
							}
							
							// was delimeter ?
							if (delimeter) {
								PushCurWord();
								delimeter = false;
							}
							
							// check if the char is a delimeter
							RuleSet ruleset = TextBuffer.Syntax.GetRuleSet(Span ? CurSpan.Rule : null);

							if (ruleset != null)
								for (int j = 0; j < ruleset.Delimeters.Length; ++j)
									if (ch == ruleset.Delimeters[j]) {
										PushCurWord();
										delimeter = true;
										break;
									}
									
									Span oldSpan = spanstack.Count == 0 ? null : (Span)spanstack.Peek();
							
							// SPAN Check
							if (Span) {
								// check for SPAN END
								if (CurSpan.End != null && !CurSpan.End.Equals("")) {
									//								string tmp2 = line.Substring(i, line.Length - i);
									if (MatchExpr(CurSpan.End, line, i)) {
										string regex = GetRegString(CurSpan.End, line, i);
										curlength += regex.Length;
										words.Add(new TextWord(line, curoffset, curlength, TextBuffer.Syntax, CurSpan.Color));
										curoffset += curlength;
										curlength = 0;
										i += regex.Length - 1;
										
										BlockSpanOn = false;
										Span        = false;
										
										CurSpan     = oldSpan;
										if (spanstack.Count > 0) {
											BlockSpanOn = !CurSpan.StopEOL;
											Span = true;
											spanstack.Pop();
										}
										continue;
									}
								}
							}
							
							// check for SPAN BEGIN
							foreach (RuleSet rule in TextBuffer.Syntax.Rules) {
								if (!Span && rule.Name == null || (Span && rule.Name == CurSpan.Rule && CurSpan.Rule != null)) {
									foreach (Span span in rule.Spans) {
										if (MatchExpr(span.Begin, line, i)) {
											string regex = GetRegString(span.Begin, line, i);
											curlength += regex.Length;
											words.Add(new TextWord(line, curoffset, curlength, TextBuffer.Syntax, span.Color));
											curoffset += curlength;
											curlength = 0;
											
											i += regex.Length - 1;
											
											BlockSpanOn = !span.StopEOL;
											Span        = true;
											if (CurSpan != null)
												spanstack.Push(CurSpan);
											CurSpan     = span;
											goto skip;
										}
									}
								}
							}
								
							++curlength;
							skip: continue;
						}
					}
				}
				
				PushCurWord();
				
				word = new TextWord[words.Count];
				for (int i = 0; i < word.Length; ++i) {
					word[i] = (TextWord)words[i];
				}
				
				// Redraw Span Change
				if (((obo ^ BlockSpanOn) ||             // SPAN On/Off
				(BlockSpanOn && OldSpan != CurSpan))    // SPAN type changed
				&& myNumber + 1 < TextBuffer.Length) {      // length check
					TextBuffer[myNumber + 1].Text = TextBuffer[myNumber + 1].Text;
					TextBuffer.UpdateRequested = true;
				}
			}
		}
	}
}

⌨️ 快捷键说明

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