using System;
using System.Drawing;
using System.Text.RegularExpressions;
using System.Windows.Forms;
namespace Sand.Services.CodeXchange.Client.Controls
{
public class SourceCodeTextBox : TextBox
{
public SourceCodeTextBox()
{
Multiline = true;
ScrollBars = ScrollBars.Vertical;
}
}
#if Code
public class SourceCodeTextBox : RichTextBox
{
#region Constants
#endregion
#region Private fields
// All c# keywords in alphabetic order :
string[] keywords =
{ "abstract"
, "as"
, "base"
, "bool"
, "break"
, "byte"
, "case"
, "catch"
, "char"
, "checked"
, "class"
, "const"
, "continue"
, "decimal"
, "default"
, "delegate"
, "do"
, "double"
, "else"
, "enum"
, "event"
, "explicit"
, "extern"
, "false"
, "finally"
, "fixed"
, "float"
, "for"
, "foreach"
, "get"
, "goto"
, "if"
, "implicit"
, "in"
, "int"
, "interface"
, "internal"
, "is"
, "lock"
, "long"
, "namespace"
, "new"
, "null"
, "object"
, "operator"
, "out"
, "override"
, "params"
, "private"
, "protected"
, "public"
, "readonly"
, "ref"
, "return"
, "sbyte"
, "sealed"
, "set"
, "short"
, "sizeof"
, "stackalloc"
, "static"
, "string"
, "struct"
, "switch"
, "this"
, "throw"
, "true"
, "try"
, "typeof"
, "uint"
, "ulong"
, "unchecked"
, "unsafe"
, "ushort"
, "using"
, "virtual"
, "void"
, "volatile"
, "while"
};
private bool parseInProgress = false;
#endregion
#region Constructors
public SourceCodeTextBox() : base()
{
this.Multiline = true;
this.WordWrap = false;
this.AcceptsTab = true;
this.ScrollBars = RichTextBoxScrollBars.ForcedBoth;
this.ForeColor = SystemColors.WindowText;
this.Font = new Font("Courier New", 8, FontStyle.Regular );
}
#endregion
#region Overriden methods
protected override void OnTextChanged ( System.EventArgs e )
{
if( !parseInProgress )
{
base.OnTextChanged(e);
ParseLines();
}
}
protected override void OnVisibleChanged(EventArgs e)
{
if( !parseInProgress )
{
base.OnVisibleChanged (e);
ParseLines();
}
}
#endregion
#region Public Methods
public void RefreshText()
{
ParseLines();
}
#endregion
#region Public Properties
#endregion
#region Private-Protected Methods
private void ParseLines()
{
parseInProgress = true;
int startPos = this.SelectionStart;
string currentText = this.Text;
this.Text = "";
bool inMultiLineComment = false;
bool inComment = false;
bool inString = false;
bool inChar = false;
bool isKeyWord = false;
bool stringBeganWithAtSign = false;
Regex regExSplitTokens = new Regex("([ \\\\\t\\n{}().:;\"'])");
string [] tokens = regExSplitTokens.Split(currentText);
string prevToken = "";
for( int iToken = 0 ; iToken < tokens.Length ; iToken++ )
{
string token = tokens[ iToken ];
if( token.Length > 0 ) // Strangely enought there are empty strings in there.
{
isKeyWord = false;
if( inMultiLineComment )
{
inMultiLineComment = ( token != @"*/" && !token.StartsWith( @"*/") && !token.EndsWith( @"*/") );
}
else if ( inComment )
{
// At end of line comment ends
inComment = ( token != "\n" );
}
else if ( inString )
{
// String ends with another " char
if( stringBeganWithAtSign || prevToken != @"\" ) inString = ( token != '"'.ToString() );
}
else if ( inChar )
{
// Char ends with another ' char
inChar = ( token != "'" );
}
else
{
inMultiLineComment = ( token == @"/*" || token.StartsWith( @"/*") );
if( !inMultiLineComment ) inComment = ( token == @"//" || token.StartsWith( @"//") );
if( !inMultiLineComment && !inComment )
{
inString = ( token == '"'.ToString());
if( inString )
{
stringBeganWithAtSign = ( prevToken == "@" );
}
}
if( !inMultiLineComment && !inComment && !inString ) inChar = ( token == "'" );
if ( ( !inMultiLineComment )
&& ( !inComment )
&& ( !inString )
&& ( !inChar )
)
{
// Check keywords
for (int iKeyword = 0; iKeyword < keywords.Length; iKeyword++)
{
if ( token == keywords[iKeyword] )
{
isKeyWord = true;
break;
}
}
}
}
if( inMultiLineComment || inComment )
{
this.SelectionColor = Color.Green;
}
else if ( inString || inChar )
{
this.SelectionColor = Color.Purple;
}
else if( isKeyWord )
{
this.SelectionColor = Color.Blue;
}
else
{
this.SelectionColor = this.ForeColor;
}
// We need the previous token just for strings with \" in them,
// which indicates that the " is part of the string.
prevToken = token;
this.SelectedText = token;
}
}
if( startPos != -1 ) this.SelectionStart = startPos;
parseInProgress = false;
}
#endregion
}
#endif
}