📄 textline.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 + -