var obj, document, id, window;
obj      = new ActiveXObject("Sleipnir.API");
id       = obj.GetDocumentID(obj.ActiveIndex);
document = obj.GetDocumentObject(id);

var CurSel;

if (document == null) {
	obj.MessageBox('Document が開かれていません');
}else{	
	var query = '('+obj.SearchBarString.replace(/( |　)/g,'|')+')';
	var GD = new TGrepData(obj);
	obj.OutputVisible = true;
	obj.OutputClear();
	obj.OutputAddString('処理中です...');
	obj.OutputAddString('');
	var progress;
	for (var i= 0; i < obj.GetCount; i++){
		id = obj.GetDocumentID(i);
		GD.AddBookmark(id, query);
		progress = '0% □□□□□□□□□□ 100%';
			for (var j = 0; j < (i + 1) / obj.GetCount * 10; j++){
				progress = progress.replace('□', '■');
			}
		obj.OutputDeleteString(1);
		obj.OutputAddString(progress);
	}
	GD.OPText.push('スクリプトの終了');
	GD.Output();
	while (true){
		WScript.Sleep(100);
		CurSel = obj.OutputCurSel;
		//スクリプトの終了を選択していたらループから抜ける
		if (CurSel == obj.OutputGetCount() -1){
			obj.OutputClear();
			obj.OutputVisible = false;
			break;
		}
		//直前に選択していた行と現在選択している行が異なっていたらジャンプ
		if (GD.CurSelected != CurSel){
			GD.CurSelected = CurSel;
			//IDの検索
			while (true){
				if (obj.OutputGetString(CurSel).match(/^\d+/) > 0){
					id = obj.OutputGetString(CurSel).match(/^\d+/);
					break;
				}
				CurSel--;
			}
			FindTab(id);
			if (GD.Bookmark[GD.CurSelected] != ''){
				var text = GD.DocumentObject[CurSel].body.createTextRange();
				text.moveToBookmark(GD.Bookmark[GD.CurSelected]);
				text.select();
				text = null;
			}
		}
			
	}
	GD = null;
	document = null;
}
obj = null;
//[MAINEND]

/*
TGrepData
Bookmarkの取得等はすべてこのオブジェクトを通して行う
*/
function TGrepData(obj){
	this.obj = obj;
	
	//public method
	this.AddBookmark = AddBookmark;
	this.Output = Output;
	//private method
	this.SetMatchText = SetMatchText;
	this.SetBookmark = SetBookmark;
	this.s = s;	

	this.Bookmark = new Array();
	this.DocumentObject = new Array();
	this.OPText = new Array();
	this.CurSelected = 0;
	this.MatchText;
}
/*
AddBookmark(id, query)
id : documentID
query : 正規表現
IDからDocumentオブジェクトを取得、子メソッドを用いてTGrepDataのMatchText、Bookmark、OPTextを設定。
*/
function AddBookmark(id, query){
	document = this.obj.GetDocumentObject(id);
	if (document == null){
		return(false);
	}else{
		var aod = new ArrayOfDocument();
		aod.GetDocument(id, null);
	}
	for (var i = 0; i < aod.list.length; i++){
		this.SetMatchText(aod.list[i], query);
		this.SetBookmark(id, aod.list[i], this.MatchText);
	}
	aod = null;
	return(true);
}
/*
Output()
OutputにOPTextを出力
*/
function Output(){
	this.obj.OutputClear();
	for (var i = 0; i < GD.OPText.length; i++){
		this.obj.OutputAddString(this.OPText[i]);
	}
	this.obj.OutputVisible = true;
	this.obj.OutputCurSel = 0;
}

/**
 * SetMatchText(document, query)
 * 正規表現queryでdocumentを検索しマッチする文字列を返す
 * 引数 : document documentオブジェクト
 *        query 検索する文字列。正規表現
 * 戻り値 : マッチする文字列を格納する配列。ただし0番目の配列は空文字列
 *
**/
function SetMatchText(document, query){
	var text = document.body.innerText;
	var re = new RegExp(query, 'ig');
	var matchtext = text.match(re);
	var result = new Array();
	var original;
	if (matchtext != null){
		result.push('');
		for (var i = 0; i < matchtext.length; i++){
			original = true;
			//すでに同じキーワードが登録されていたら多重登録しない
			for (var j = 0; j < result.length; j++){
				if (matchtext[i].toLowerCase() == result[j].toLowerCase()){
					original = false;
					break;
				}
			}
			if (original){
				result.push(matchtext[i]);
			}
		}
	}
	
	re = null;
	this.MatchText = result;
	result = null;
}

/**
 * SetBookmark(document, query)
 * MatchTextから位置を元にソートしたTextRangeオブジェクトのBookmark,及びOPTextを設定。
 * 引数 : document documentオブジェクト
          query TGrepData.MatchText
 *
**/

function SetBookmark(id, document, query){
	var TempBookmark = new Array();
	var SortData = new Array();
	var TempOPText = new Array();
	var text = document.body.createTextRange();
	var temp = 0;
	for (var i = 1; i < query.length ; i++){
		while (text.findText(query[i])){
			TempBookmark.push(text.getBookmark());

			var dup = text.duplicate();
			dup.moveStart('character', -20);
			dup.moveEnd('character', 20);
			TempOPText.push('                 '+dup.text);
			dup = null;

			SortData.push(text.offsetTop+':'+temp+':'+text.offsetLeft);
			text.move('character', 1);
			temp++;
		}
		text.move('textedit', -1);
	}
	if (TempBookmark.length != 0){
		this.Bookmark.push('')
		this.OPText.push(id+': ['+document.title+']');
	}
	SortData.sort(this.s);
	//ソート結果に従いBookmark等を格納していく
	for (var j = 0; j < SortData.length ; j++){
			SortData[j].match(/^-?\d+:(.*):-?\d+$/);
			this.Bookmark.push(TempBookmark[RegExp.$1]);
			this.OPText.push(TempOPText[RegExp.$1]);
			if (j == 0){
				this.DocumentObject[this.OPText.length -2] = document;
			}
	}
	if (TempBookmark.length > 0){
		this.Bookmark.push('')
		this.OPText.push('');
	}
	text = null;
	TempBookmark = null;
	SortData = null;
	TempOPText = null;
}

/**
 * s(a, b)
 * SortDataをソートする
 *
**/
function s(a, b){
	if ((a.match(/^-?\d+/) - b.match(/^-?\d+/)) == 0){
		//上からの位置が一致したら、左からの位置でソート
		return(a.match(/-?\d+$/) - b.match(/-?\d+$/));
	}
	return(a.match(/^-?\d+/) - b.match(/^-?\d+/));
}
/*
 * FindTab(id)
 * idから目的のタブを見つけ出しアクティブにする
 * 引数 : id DocumentID
 *
**/
function FindTab(id){
	var obj;
	obj = new ActiveXObject("Sleipnir.API");
	for (i = 0; i < obj.GetCount; i++){
		if (obj.GetDocumentID(i) == id){
			obj.ActiveIndex = i;
		}
	}
	obj = null;
}
/**
 *ArrayOfDocument
 *フレームページのすべてのドキュメントを保持するクラス
 *メソッド : GetDocument documentオブジェクトを取得する
 *プロパティ : list documentオブジェクトの配列
 *
**/
function ArrayOfDocument(){
	var obj = new ActiveXObject("Sleipnir.API");
	this.obj = obj;
	this.GetDocument = GetDocument;
	this.list = new Array();

}
/**
 *[ArrayOfDocument]
 *GetDocument(id, document)
 *documentオブジェクトを取得し、listにセット
 *引数 : id DocumentID
         document documentオブジェクト
 *
**/
function GetDocument(id, document){
	if (document == null){
		document = this.obj.GetDocumentObject(id);
		this.GetDocument(id, document);
	}else if (document.frames.length > 0){
		for (var k = 0; k < document.frames.length; k++) {
			try{
				var window = document.frames.item(k);
				this.GetDocument(id, window.document);
			}
			catch(e){
				break;
			}
		}
	}else{
		this.list.push(document);
	}
}

//[END]	
