SourceToHTML にGUIを

「SourceToHTML」と「SourceToRTF」をマージし、
また、"HTA"によるユーザーインターフェースを持たせました。

以下は、「SourceToHtml」の本体です。

.\library\SourceToHtml.js (3/3)


//=============================================================================
// 予約語一覧を取得する
//=============================================================================
function getKeywordList()
{
_convert.keyword = new Array();

// 予約語一覧
_convert.keyword[0] = new Object();

// 強調表示 一覧
_convert.keyword[1] = new Object();
_convert.keyword[2] = new Object();
_convert.keyword[3] = new Object();

var keyFileName = "";
for (var i=0;i<4;i++)
{
// 予約語・強調表示 一覧ファイル名
if (i == 0)
keyFileName = ".\\application\\" + _arg.langType + ".key";
else
keyFileName = ".\\application\\" + _arg.langType + ".sp" + i;

// ファイルがなければ、何もしない
if (!_fs.FileExists(keyFileName)) continue;

// 予約語一覧ファイルを 読み込み専用モードで 開く
var tsKeyword = _fs.OpenTextFile(keyFileName, 1);
while (!tsKeyword.AtEndOfStream)
{
var s = tsKeyword.ReadLine();

// 大文字・小文字を区別しない → 予約語を小文字に変換して登録する
if (_convert.ignoreCase) _convert.keyword[i]['"' + s.toLowerCase() + '"'] = s;
// 大文字・小文字を区別する → 予約語をそのまま登録する
else _convert.keyword[i]['"' + s + '"'] = s;

// ↑ 何故か toString が登録されるので、" で囲む
}
tsKeyword.Close();
}
}
//-----------------------------------------------------------------------------
// 予約語か? (大文字・小文字を区別する)
//-----------------------------------------------------------------------------
function getKeywordCase(idx, value)
{
// 予約語一覧に登録されていれば、予約語を返す
return (_convert.keyword[idx][value]);
}
//-----------------------------------------------------------------------------
// 予約語か? (大文字・小文字を区別しない)
//-----------------------------------------------------------------------------
function getKeywordIgnoreCase(idx, value)
{
// 予約語一覧に登録されていれば、予約語を返す
return (_convert.keyword[idx][value.toLowerCase()]);
}
//-----------------------------------------------------------------------------
// その「識別子」は、「予約語」か? または「強調表示」対象か?
//-----------------------------------------------------------------------------
function toEmphasis(context)
{
// その「識別子」は、「予約語」か?
for (var i=0;i<4;i++)
{
// 例えば、VB の 「MyBase.New()」 という文の
// 「New」 は、予約語として表示したくないので。。。
if ((i == 0) && (context.prevToken.charAt(context.prevToken.length - 1) == ".")) continue;

var s = _convert.getKeyword(i, '"' + context.token + '"');
// ↑ 何故か toString が登録されるので、" で囲んである
if (s)
{
context.token = s;

if (i == 0)
context.type = "予約語";
else
context.type = "強調表示" + i;

break;
}
}
}
//*****************************************************************************
// プログラムソース を 出力
//*****************************************************************************
function putSource(tsOut)
{
// 入力ファイルを 読み込み専用モードで 開く
var tsIn = _fs.OpenTextFile(_arg.inFileName, 1);

// 文脈オブジェクト
var context = new Object();

//現在の状態
context.state = "開始待ち";

// 入力ファイルの終わりまで繰り返す
while (!tsIn.AtEndOfStream)
{
// 入力ファイルを 1行ずつ読む
context.value = tsIn.ReadLine();

// TAB を 空白に 変換
context.value = TabToSpace(context.value);

// プログラムソース を 変換して 出力
tsOut.WriteLine(_convert.ConvToHtml(context) + _convert.NewLine);
}
// 入力ファイルを 閉じる
tsIn.Close();
}
//=============================================================================
// テキスト を 変換して返す (文字のエスケ−プだけ)
//=============================================================================
function ConvToHtmlText(context)
{
// 行番号を 出力
var ret = tokenToHtml(FormatNum(++_lineNo) + _arg.lineNoDlm, "行番号");

// 変換対象の文字を 変換
ret += tokenToHtml(context.value, "");

return ret;
}
//=============================================================================
// プログラムソース を 変換して返す
//=============================================================================
function ConvToHtmlOther(context)
{
// 変換出力用文字列
var ret = "";

// 行番号を 出力
ret = tokenToHtml(FormatNum(++_lineNo) + _arg.lineNoDlm, "行番号");

// トークンを退避
context.prevToken = "";
context.prevType = "空白";

// トークンの種類を クリア
if (context.state == "開始待ち")
context.type = "空白";
// トークンを クリア
context.token = "";

while (context.value.length > 0)
{
if (context.state == "開始待ち")
{
var isMatch = false;

for (var i=0;i<_convert.state.waitStart.length;i++)
{
// トークンの種類を判定
if (_convert.state.waitStart[i].getToken(context.value))
{
context.token = RegExp.lastMatch;
context.type = _convert.state.waitStart[i].currType;
context.state = _convert.state.waitStart[i].nextState;
context.value = RegExp.rightContext;
isMatch = true;

// その「識別子」は、「予約語」か? または「強調表示」対象か?
if (context.type == "識別子") toEmphasis(context);

// 終了判定用関数を 割り当て
if (context.state == "終了待ち")
context.getTerm = _convert.state.waitStart[i].getTerm;

break;
}
}
// 2 Byte文字 なら
if (!isMatch)
{
context.token = context.value.charAt(0);
context.type = (_convert.useMultiByte ? "識別子" : "不正な文字");
context.state = "開始待ち";
context.value = context.value.substring(1);
}
}
else // 終了待ち
{
// 終了?
if (context.getTerm(context.value))
{
context.token = RegExp.lastMatch;
context.state = "開始待ち";
context.value = RegExp.rightContext;
}
else // まだ、次の行に続く...
{
context.token = context.value;
context.state = "終了待ち";
context.value = "";
}
}
// トークンの種類が変わったら
if (context.prevType != context.type)
{
// トークンを出力
ret += tokenToHtml(context.prevToken, context.prevType);
context.prevToken = context.token;
}
else
{
context.prevToken += context.token;
}
context.prevType = context.type;
}
// トークンを出力
ret += tokenToHtml(context.prevToken, context.prevType);

return ret;
}
//-----------------------------------------------------------------------------
// 数値の書式化 (例: 123 → "00123")
//-----------------------------------------------------------------------------
function FormatNum(num)
{
var s = "0000000000" + num;
return (s.substring(s.length - _arg.lineNoLen));
}
//=============================================================================
// トークンに TAG を付けて 返す
//=============================================================================
function tokenToHtml(token, type)
{
if (token.length < 1) return "";

// 変換出力用文字列
var ret = "";

// 1文字ずつ処理する
for (var i=0;i<token.length;i++)
{
// 1文字取り出す
var c = token.charAt(i);

// 変換対象の文字なら、変換して出力 ( "0" → "&#x30;" )
if (_arg.escapeChar.indexOf(c) >= 0)
ret += _convert.getEscapeChar(c);

// それ以外なら、そのまま出力
else
ret += c;
}

// タグで囲む
for (var i=1;i<13;i++)
{
if ((type == _arg.Emphasis[i].Name)
&& (_arg.Emphasis[i].FontEnabled || _arg.Emphasis[i].BackEnabled))
return _arg.Emphasis[i].Begin + ret + _arg.Emphasis[i].End;
}
// 変換しなかった場合
return ret;
}
//-----------------------------------------------------------------------------
// 変換対象の文字を、変換して返す
//-----------------------------------------------------------------------------
function getEscapeCharHtml(arg)
{
return "&#x" + arg.charCodeAt(0).toString(16) + ";";
}
function getEscapeCharRtf(arg)
{
return "\\" + arg;
}
//*****************************************************************************
// 色の指定 (HTML 専用)
//*****************************************************************************
function putColorCss(tsOut)
{
// 出力文字列
var ret = "";

// 基本色の指定
ret = "PRE {";
ret += "color:#" + _arg.Emphasis[0].FontColor + ";";
ret += "background-color:#" + _arg.Emphasis[0].BackColor + ";";
ret += "}";
tsOut.WriteLine(ret);

// 各表示項目の指定
for (var i=1;i<13;i++)
{
// 無効
if (!_arg.Emphasis[i].FontEnabled && !_arg.Emphasis[i].BackEnabled) continue;

ret = "PRE SPAN." + _arg.Emphasis[i].Class + "{";

// 文字
if (_arg.Emphasis[i].FontEnabled)
{
// 文字色
if (_arg.Emphasis[i].FontColor != _arg.Emphasis[0].FontColor)
ret += "color:#" + _arg.Emphasis[i].FontColor + ";";

// 太字
if (_arg.Emphasis[i].Bold)
ret += "font-weight:bold;";

// 斜体
if (_arg.Emphasis[i].Italic)
ret += "font-style:italic;";

// 下線
if (_arg.Emphasis[i].UnderLine)
ret += "text-decoration:underline;";
}

// 背景
if (_arg.Emphasis[i].BackEnabled)
{
// 背景色
if (_arg.Emphasis[i].BackColor != _arg.Emphasis[0].BackColor)
ret += "background-color:#" + _arg.Emphasis[i].BackColor + ";";
}

ret += "}";
tsOut.WriteLine(ret);

// HTML の 指定
_arg.Emphasis[i].Begin = '<SPAN CLASS="' + _arg.Emphasis[i].Class + '">';
_arg.Emphasis[i].End = '</SPAN>';
}
}
//*****************************************************************************
// 色の指定 (RTF 専用)
//*****************************************************************************
function putColorRtf(tsOut)
{
// 出力文字列
var ret = "";

// 各表示項目の指定
for (var i=1;i<13;i++)
{
// 無効
if (!_arg.Emphasis[i].FontEnabled && !_arg.Emphasis[i].BackEnabled) continue;

// COLOR TABLE の 指定 (文字色)
var r = _arg.Emphasis[i].FontColor.substr(0, 2)
var g = _arg.Emphasis[i].FontColor.substr(2, 2);
var b = _arg.Emphasis[i].FontColor.substr(4, 2);
tsOut.WriteLine("\\red" + parseInt(r, 16) + "\\green" + parseInt(g, 16) + "\\blue" + parseInt(b, 16) + ";");

// COLOR TABLE の 指定 (背景色)
r = _arg.Emphasis[i].BackColor.substr(0, 2)
g = _arg.Emphasis[i].BackColor.substr(2, 2);
b = _arg.Emphasis[i].BackColor.substr(4, 2);
tsOut.WriteLine("\\red" + parseInt(r, 16) + "\\green" + parseInt(g, 16) + "\\blue" + parseInt(b, 16) + ";");

// 各要素ごとの 指定 (開始タグ)
ret = "";

// 文字
if (_arg.Emphasis[i].FontEnabled)
{
// 文字色
if (_arg.Emphasis[i].FontColor != _arg.Emphasis[0].FontColor)
ret += "\\cf" + ((i - 1) * 2 + 1).toString() + " ";

// 太字
if (_arg.Emphasis[i].Bold)
ret += "\\b ";

// 斜体
if (_arg.Emphasis[i].Italic)
ret += "\\i ";

// 下線
if (_arg.Emphasis[i].UnderLine)
ret += "\\ul ";
}

// 背景
if (_arg.Emphasis[i].BackEnabled)
{
// 背景色
if (_arg.Emphasis[i].BackColor != _arg.Emphasis[0].BackColor)
ret += "\\highlight" + ((i - 1) * 2 + 2).toString() + " ";
}

_arg.Emphasis[i].Begin = ret;

// 各要素ごとの 指定 (終了タグ)
ret = "";

// 背景
if (_arg.Emphasis[i].BackEnabled)
{
// 背景色
if (_arg.Emphasis[i].BackColor != _arg.Emphasis[0].BackColor)
ret += "\\highlight0 ";
}

// 文字
if (_arg.Emphasis[i].FontEnabled)
{
// 下線
if (_arg.Emphasis[i].UnderLine)
ret += "\\ulnone ";

// 斜体
if (_arg.Emphasis[i].Italic)
ret += "\\i0 ";

// 太字
if (_arg.Emphasis[i].Bold)
ret += "\\b0 ";


// 文字色
if (_arg.Emphasis[i].FontColor != _arg.Emphasis[0].FontColor)
ret += "\\cf0 ";
}

_arg.Emphasis[i].End = ret;
}
}
//*****************************************************************************
// TAB を 空白に 変換
//*****************************************************************************
function TabToSpace(arg)
{
// 変換出力用文字列
var ret = "";

// 現在位置
var pos = 0;

// 1文字ずつ処理する
for (var i=0;i<arg.length;i++)
{
// 1文字取り出す
var c = arg.charAt(i);

// TAB か?
if (c == "\t")
{
// 空白何文字分に置き換えればよいか
var num = 4 - (pos % 4);
// 現在位置を加算
pos += num;
// 変換して出力
ret += " ".substr(0, num);
}
else
{
// 現在位置を加算
if (escape(c).length < 4)
pos++;
else
pos += 2;
// そのまま出力
ret += c;
}
}

//行末の空白を削除
return ret.replace(/ +$/,"");
}