namespace CtoHTML
{
/// <summary>CtoHTML</summary>
class CtoHTML
{
#region Inner Class
/// <summary>ToHTML</summary>
class ToHTML
{
#region Implementers
public static string filter(string text, bool preMode)
{
text = TABtoSpace(text);
text = TrimEnd(text);
System.Collections.ArrayList tokens = TokenBuilder.toTokens(text);
string newText = string.Empty;
foreach (TokenBuilder.Token token in tokens)
{
for (int index = 0; index <= token.text.Length; index++)
{
State oldState = state;
state = state.getState(token, index);
if (state.isChange && !oldState.GetType().Equals(state.GetType()))
{
newText += oldState.closeText();
newText += state .openText ();
}
newText += toHTML(token.text, index, preMode);
}
}
if (state.lineEnd())
{
State oldState = state;
state = state.getState();
if (state.isChange && !oldState.GetType().Equals(state.GetType()))
{
newText += oldState.closeText();
newText += state .openText ();
}
}
newText += "<br>";
return newText;
}
public static string end()
{
string text = state.closeText();
state = new NormalState();
return text;
}
#endregion // Implementers
#region Private
private static string TABtoSpace(string text)
{
string newText = string.Empty;
int column = 0;
for (int index = 0; index < text.Length; index++)
{
if (text[index] == '\t')
{
do
{
newText += ' ';
column++;
}
while ((column % (int)tab) != 0);
}
else
{
newText += text[index];
column++;
}
}
return newText;
}
private static string TrimEnd(string text)
{
char[] trimChars = new char[] {' '};
return text.TrimEnd(trimChars);
}
private static string toHTML(string text, int index, bool preMode)
{
string newText = string.Empty;
if (index < text.Length)
{
switch (text[index])
{
case ' ' :
if (!preMode && index > 0 && text[index - 1] == ' ')
newText = " ";
else
newText = " ";
break;
case '&' : newText = "&" ; break;
case '<' : newText = "<" ; break;
case '>' : newText = ">" ; break;
case '\"': newText = """ ; break;
default : newText += text[index]; break;
}
}
return newText;
}
private static State state = new NormalState();
#endregion // Private
}
/// <summary>TokenBuilder</summary>
class TokenBuilder
{
#region Inner Class
/// <summary>Token</summary>
public class Token
{
#region Enum
public enum Kind
{
WHITESPACE,
MARK ,
SPECIAL ,
OTHER
}
#endregion // Enum
#region Constructors
public Token()
{}
public Token(string text, Kind kind)
{
text_ = text;
kind_ = kind;
}
#endregion // Constructors
#region Implementers
public virtual Token clone()
{
return new Token(text, kind);
}
#endregion // Implementers
#region Properties
public string text
{
get { return text_; }
set { text_ = value; }
}
public Kind kind
{
get { return kind_; }
set { kind_ = value; }
}
#endregion // Properties
#region Private
private string text_ = string.Empty;
private Kind kind_ = Kind.WHITESPACE;
#endregion // Private
}
#endregion // Inner Class
#region Constructors
static TokenBuilder()
{
initializeHashTables();
}
#endregion // Constructors
#region Implementers
public static System.Collections.ArrayList toTokens(string text)
{
System.Collections.ArrayList tokens = new System.Collections.ArrayList();
Token current = new Token();
for (int index = 0; index < text.Length; index++)
{
object o = characterTable_[text[index]];
Token.Kind kind = (o == null) ? Token.Kind.OTHER : (Token.Kind)o;
if (kind == current.kind)
{
current.text += text[index];
}
else
{
if (current.text.Length > 0)
{
tokens.Add(current.clone());
current.text = string.Empty;
}
current.kind = kind;
current.text += text[index];
}
}
if (current.text.Length > 0)
tokens.Add(current.clone());
return tokens;
}
#endregion // Implementers
#region Private
private static char[] whiteSpaceCharacters_ = new char[] {' ', '\t', '\v', '\f', '\r', '\n'};
private static char[] markCharacters_ = new char[] {'<', '>', '=', '+', '-', '*', '/', '%', '&', '|', '^', '!', '~', '.', '[', ']', '(', ')', '?', ':', '{', '}', ';'};
private static char[] specialCharacters_ = new char[] {'\\', '\"', '\'', '\0', '\a', '\b'};
private static System.Collections.Hashtable characterTable_ = new System.Collections.Hashtable();
private static void initializeHashTables()
{
foreach (char c in whiteSpaceCharacters_)
characterTable_.Add(c, Token.Kind.WHITESPACE);
foreach (char c in markCharacters_ )
characterTable_.Add(c, Token.Kind.MARK );
foreach (char c in specialCharacters_ )
characterTable_.Add(c, Token.Kind.SPECIAL );
}
#endregion // Private
}
/// <summary>Keyword</summary>
public class Keyword
{
#region Constants
public const string comment1Start_ = "/*";
public const string comment1End_ = "*/";
public const string comment2Start_ = "//";
#endregion // Constants
#region Implementers
public static void initialize()
{
initializeKeywordText();
foreach (string s in csharpKeywordText_ )
csharpKeywordTextTable_ .Add(s, 0);
foreach (string s in cplusplusKeywordText_)
cplusplusKeywordTextTable_.Add(s, 1);
}
public static bool isKeyword(string text)
{
return (keywordTextTable_[text] != null);
}
public static void initializeKeywordText()
{
System.Collections.ArrayList textList = new System.Collections.ArrayList();
System.IO.TextReader reader = textReaderFromFile(csharpKeywordFileName);
while (reader.Peek() > -1)
{
string keyword = reader.ReadLine();
if (keyword.Length > 0)
textList.Add(keyword);
}
reader.Close();
csharpKeywordText_ = new string[textList.Count];
for (int i = 0; i < textList.Count; i++)
csharpKeywordText_[i] = (string)textList[i];
textList.Clear();
reader = textReaderFromFile(cplusplusKeywordFileName);
while (reader.Peek() > -1)
{
string keyword = reader.ReadLine();
if (keyword.Length > 0)
textList.Add(keyword);
}
reader.Close();
cplusplusKeywordText_ = new string[textList.Count];
for (int i = 0; i < textList.Count; i++)
cplusplusKeywordText_[i] = (string)textList[i];
textList.Clear();
}
#endregion // Implementers
#region Properties
public static ModeKind Mode
{
get
{
return mode_;
}
set
{
if (value != mode_)
{
mode_ = value;
switch (mode_)
{
case ModeKind.CSharp : keywordTextTable_ = csharpKeywordTextTable_ ; break;
case ModeKind.CPlusPlus: keywordTextTable_ = cplusplusKeywordTextTable_; break;
}
}
}
}
public static string keywordFileName
{
get
{
switch (Mode)
{
case ModeKind.CSharp : return csharpKeywordFileName ;
case ModeKind.CPlusPlus: return cplusplusKeywordFileName;
}
return csharpKeywordFileName;
}
}
#endregion // Properties
#region Private
private static ModeKind mode_ = ModeKind.CSharp;
private const string csharpKeywordFileName = @".\csharpkeyword.txt" ;
private const string cplusplusKeywordFileName = @".\cpluspluskeyword.txt";
private static string[] csharpKeywordText_ ;
private static string[] cplusplusKeywordText_;
private static System.Collections.Hashtable csharpKeywordTextTable_ = new System.Collections.Hashtable();
private static System.Collections.Hashtable cplusplusKeywordTextTable_ = new System.Collections.Hashtable();
private static System.Collections.Hashtable keywordTextTable_ = csharpKeywordTextTable_;
#endregion // Private
}
/// <summary>State</summary>
abstract class State
{
#region Virtual
public virtual string openText()
{
return string.Empty;
}
public virtual string closeText()
{
return string.Empty;
}
public virtual bool lineEnd()
{
return false;
}
public virtual State getState(TokenBuilder.Token token, int index)
{
if (isSingleQuotation(token, index)) return new SingleQuotationState(token, index);
if (isDoubleQuotation(token, index)) return new DoubleQuotationState(token, index);
else if (isComment1 (token, index)) return new Comment1State ();
else if (isComment2 (token, index)) return new Comment2State ();
else if (isKeyword (token, index)) return new KeywordState (token);
else if (isMark (token, index)) return new MarkState ();
return new NormalState ();
}
public virtual State getState()
{
return this;
}
#endregion // Virtual
#region Properties
public bool isChange
{
get
{
bool isChangeFlag = isChange_;
isChange_ = false;
return isChangeFlag;
}
}
#endregion // Properties
#region Protected
private static bool isEscapeCharacter(TokenBuilder.Token token, int index)
{
return ((index > 0 && token.text[index - 1] == '\\') && // 一つ前が \ で且つ
(index < 2 || token.text[index - 2] != '\\')); // 二つ前が \ でない
}
protected static bool isSingleQuotation(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.SPECIAL &&
(index < token.text.Length && token.text[index] == '\'') &&
!isEscapeCharacter(token, index));
}
protected static bool isSingleQuotationEnd(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.SPECIAL &&
(index > 0 && token.text[index - 1] == '\'') &&
!isEscapeCharacter(token, index - 1));
}
protected static bool isDoubleQuotation(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.SPECIAL &&
(index < token.text.Length && token.text[index] == '\"') &&
!isEscapeCharacter(token, index));
}
protected static bool isDoubleQuotationEnd(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.SPECIAL &&
(index > 0 && token.text[index - 1] == '\"') &&
!isEscapeCharacter(token, index - 1));
}
protected static bool isComment1(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.MARK &&
index < token.text.Length &&
string.Compare(token.text, index, Keyword.comment1Start_, 0, Keyword.comment1Start_.Length) == 0);
}
protected static bool isComment1End(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.MARK &&
index > 1 &&
string.Compare(token.text, index - Keyword.comment1End_.Length, Keyword.comment1End_, 0, Keyword.comment1End_.Length) == 0);
}
protected static bool isComment2(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.MARK &&
index < token.text.Length &&
string.Compare(token.text, index, Keyword.comment2Start_, 0, Keyword.comment2Start_.Length) == 0);
}
protected static bool isKeyword(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.OTHER &&
Keyword.isKeyword(token.text));
}
protected static bool isMark(TokenBuilder.Token token, int index)
{
return (token.kind == TokenBuilder.Token.Kind.MARK);
}
#endregion // Protected
#region Private
private bool isChange_ = true;
#endregion // Private
}
/// <summary>NormalState</summary>
class NormalState : State
{}
/// <summary>QuotationState</summary>
abstract class QuotationState : State
{
#region Constructors
protected QuotationState(TokenBuilder.Token token, int index)
{
token_ = token;
index_ = index;
}
#endregion // Constructors
#region Protected
protected bool isSame(TokenBuilder.Token token, int index)
{
return (token == token_ && (index - 1) == index_);
}
#endregion // Protected
#region Private
private readonly TokenBuilder.Token token_;
private readonly int index_;
#endregion // Private
}
/// <summary>SingleQuotationState</summary>
class SingleQuotationState : QuotationState
{
#region Constructors
public SingleQuotationState(TokenBuilder.Token token, int index) : base(token, index)
{}
#endregion // Constructors
#region Override
public override State getState(TokenBuilder.Token token, int index)
{
if (!isSame(token, index) && isSingleQuotationEnd(token, index))
return base.getState(token, index);
return this;
}
public override string openText()
{
return singleQuotationTagOpen;
}
public override string closeText()
{
return singleQuotationTagClose;
}
#endregion // Override
}
/// <summary>DoubleQuotationState</summary>
class DoubleQuotationState : QuotationState
{
#region Constructors
public DoubleQuotationState(TokenBuilder.Token token, int index) : base(token, index)
{}
#endregion // Constructors
#region Override
public override State getState(TokenBuilder.Token token, int index)
{
if (!isSame(token, index) && isDoubleQuotationEnd(token, index))
return base.getState(token, index);
return this;
}
public override string openText()
{
return doubleQuotationTagOpen;
}
public override string closeText()
{
return doubleQuotationTagClose;
}
#endregion // Override
}
/// <summary>CommentState</summary>
abstract class CommentState : State
{
#region Override
public override string openText()
{
return commentTagOpen;
}
public override string closeText()
{
return commentTagClose;
}
#endregion // Override
}
/// <summary>Comment1State</summary>
class Comment1State : CommentState
{
#region Override
public override State getState(TokenBuilder.Token token, int index)
{
if (isComment1End(token, index))
return base.getState(token, index);
return this;
}
#endregion // Override
}
/// <summary>Comment2State</summary>
class Comment2State : CommentState
{
#region Override
public override bool lineEnd()
{
isEnd_ = true;
return true;
}
public override State getState(TokenBuilder.Token token, int index)
{
return this;
}
public override State getState()
{
if (isEnd_)
{
return new NormalState();
}
return this;
}
#endregion // Override
#region Private
private bool isEnd_ = false;
#endregion // Private
}
/// <summary>KeywordState</summary>
class KeywordState : State
{
#region Constructors
public KeywordState(TokenBuilder.Token token)
{
token_ = token;
}
#endregion // Constructors
#region Override
public override State getState(TokenBuilder.Token token, int index)
{
if (token != token_ || index >= token.text.Length)
return base.getState(token, index);
return this;
}
public override string openText()
{
return keywordTagOpen;
}
public override string closeText()
{
return keywordTagClose;
}
#endregion // Override
#region Private
private readonly TokenBuilder.Token token_;
#endregion // Private
}
/// <summary>MarkState</summary>
class MarkState : State
{
#region Override
public override State getState(TokenBuilder.Token token, int index)
{
return base.getState(token, index);
}
public override string openText()
{
return markTagOpen;
}
public override string closeText()
{
return markTagClose;
}
#endregion // Override
}
/// <summary>Registry</summary>
class Registry
{
#region Private
private const string headerTextKeyName = "Header Text";
private const string footerTextKeyName = "Footer Text";
private const string singleQuotationTagOpenKeyName = "Single Quotation Tag Open";
private const string singleQuotationTagCloseKeyName = "Single Quotation Tag Close";
private const string doubleQuotationTagOpenKeyName = "Double Quotation Tag Open";
private const string doubleQuotationTagCloseKeyName = "Double Quotation Tag Close";
private const string commentTagOpenKeyName = "Comment Tag Open";
private const string commentTagCloseKeyName = "Comment Tag Close";
private const string keywordTagOpenKeyName = "Keyword Tag Open";
private const string keywordTagCloseKeyName = "Keyword Tag Close";
private const string markTagOpenKeyName = "Mark Tag Open";
private const string markTagCloseKeyName = "Mark Tag Close";
private const string encodingKeyName = "Encoding";
private const string tabKeyName = "TAB";
private const string preModeKeyName = "Pre Mode";
private const string modeKeyName = "Mode";
private const string browserModeKeyName = "Browser Mode";
private const string browserKeyName = "Browser";
#endregion // Private
#region Implementers
public static void read(Microsoft.Win32.RegistryKey key)
{
string[] texts = (string[])key.GetValue(headerTextKeyName);
if (texts != null)
headerText_ = texts;
texts = (string[])key.GetValue(footerTextKeyName);
if (texts != null)
footerText_ = texts;
string text = (string)key.GetValue(singleQuotationTagOpenKeyName);
if (text != null)
singleQuotationTagOpen_ = text;
text = (string)key.GetValue(singleQuotationTagCloseKeyName);
if (text != null)
singleQuotationTagClose = text;
text = (string