var win_height = 0;
function OnDocResize()
{
	// 14.03.06 amoro:
	// Проверка, существует ли объект body - пока страница не загрузилась
	// его нет
	var body = document.body;
	if (typeof(body) == "undefined")
		return;
		
	// 16.05.06 amoro:
	// похоже, что дважды обработчик вызывается только в IE
	var ie = false;
	var nav = window.navigator;
	if (nav == null)
		nav = window.clientInformation;
	if (nav != null && nav.userAgent.indexOf('MSIE') > 0)
		ie = true;
	
	// обработчик вызывается дважды, логично восстанавливать состояние
	// во второй раз
	if (win_height == body.offsetHeight || !ie)
	{	
		// 25.04.06 amoro:
		// сделал автоподбор кол-ва отображаемых ярлычков
		// в панели инструментов
		autoSelectTabCnt();
		
		if (typeof frameStates == 'undefined')
			return;
		
		var i;
		for (i in frameStates.frames)
		{
			var frm = window.frames[i];
			try{
				if (frm != null && frm.restorePagePosition != null)
					frm.restorePagePosition();
			}catch (err){
			}
		}
	}
	else
		win_height = body.offsetHeight;
		
	var tree_header = document.getElementById('tree_header');
	if (tree_header != null){
		if (tree_header.clientWidth > document.body.clientWidth - 50)
			tree_header.style.width = (document.body.clientWidth - 50) + 'px';
	}
}
	
// 08.02.06 amoro:
// Хранитель номера открытой вкладки
function ActivePartState(num)
{
	if (num == null)
		num = 0;
	this.partNum = num;
	
	this.load = APS_load;
	this.save = APS_save;
}

function APS_load(state)
{
	this.partNum = parseInt(state);
}

function APS_save()
{
	return this.partNum+"";
}

function focusOnTabContent(tnum)
{
	var frm_wnd = window.frames['f' + tnum];
	if (frm_wnd == null)
		return;
	var frm_body = frm_wnd.document.body;
	if (frm_body != null && frm_body.focus)
		setFocusTo(frm_body);
}

// 08.02.06 amoro:
// Сокрытие вкладки
function hideTab(num)
{
	setTabState(num, false);
	var frm = document.getElementById('f' + num);
	if (frm != null)
		frm.style.display = 'none';
}

function testFrameLoading()
{
	if (window.wait_timer != null){
		window.clearTimeout(window.wait_timer);
		window.wait_timer = null;
	}
	if ((window.load_frame == null) || 
		(window.load_frame.document == null) || 
		((window.load_frame.document.readyState == "complete") ||
		 (window.load_frame.document.readyState == "interactive"))){
		window.load_frame = null;
		hideProgressMsg(window.document.body);
		return;
	}
	window.wait_timer = window.setTimeout("testFrameLoading()", 400);
}

function showFrameLoading()
{
	if (window.wait_timer != null){
		window.clearTimeout(window.wait_timer);
		window.wait_timer = null;
	}
	if (window.load_frame == null)
		return;
	if (window.load_frame.document == null)
		return;
	if ((window.load_frame.document.readyState == "complete") ||
		(window.load_frame.document.readyState == "interactive"))
		return;
	showProgressMsg(window.document.body);
	window.wait_timer = window.setTimeout("testFrameLoading()", 400);
}

// 08.02.06 amoro:
// Переключение на вкладку
function showTab(el, mark, itp)
{
	if (el == null)
		return false;
	var n_part = el.id.substring(1);
	setTabState(n_part, true);
	window.activePart.partNum = n_part;
	var res = false;
	var frm = document.getElementById('f' + n_part);
	if (frm != null){
		frm.style.display = '';
		
		// 06.04.06 amoro:
		// теперь во всех случаях URL-и задаются
		// напрямую и не модифицируются здесь
		// 26.04.06 amoro:
		// опциональные параметры (в частности, 
		// используются на странице поиска)
		var frm_src = el.href;
		if (mark != null)
		{
			var ind = frm_src.indexOf('#');
			if (ind != -1)
			{
				frm_src = frm_src.substring(0, ind) + '&mark=' + mark + '#I0';
			}
			else
			{
				frm_src += '&mark=' + mark + '#I0';
			}
		}
		// 19.09.06 amoro:
		// при возврате по истории на страницу поиска надо восстанавливать
		// параметры поиска:
		var itp = document.getElementById('additional_tab_params');
		if (itp != null)
		{
			frm_src += itp.value;
		}
		var frm_wnd = window.frames['f' + n_part];
		try{
			if ((frm_wnd.location + '').substring(0, frm_src.length) != frm_src){
				frm_wnd.location.replace(frm_src);
				if (window.wait_timer != null){
					window.clearTimeout(window.wait_timer);
					hideProgressMsg(window.document.body);
				}
				window.wait_timer = window.setTimeout("showFrameLoading()", 3000);
				window.load_frame = frm_wnd;
			}
			else
			{
				// если содержимое вкладки уже загружено, надо обновить ее состояние
				// (чтобы восстановить позицию, например)
				var frmState = frameStates.get(frm.name);
				if (frmState != null)
					frmState.reload();
				res = true;
			}
		}catch (err){
			frm.src = frm_src;
		}
	}	
	setTitle();
	return res;
}

function setTitle()
{
	var tab = document.getElementById('t' + window.activePart.partNum);
	var title = window.original_title;
	// менять заголовок окна, только если
	// страница это поддерживает (установлен original_title)
	if (title == null)
		return;
	var part  = ' [' + html_unescape(tab.innerHTML) + ']';
	var len = 250 - part.length;
	if (len < 15)
		len = 15;
	if (title.length > len)
	{
		var title = title.substring(0, len);
		var index = title.lastIndexOf(' ' );
		if (index > 0)
			title = title.substring(0, index);
		title += '...';
	}
	document.title = title + part;
}
window.setTitle = setTitle;

// 08.02.06 amoro:
// Обработчик события нажатия на ярлычок вкладки
// Вынес большую часть кода в hideTab и showTab,
// чтобы применять их отдельно для установки открытой
// вкладки при загрузке страницы
function tabClick(el)
{
	if (el == null)
		return false;
	
	var apart = window.activePart.partNum;
	if (parseInt(el.id.substring(1)) == apart)
		return false;
	var frmState = frameStates.get('f' + apart);
	if (frmState != null)
		frmState.save();
	
	hideTab(apart);
	var alreadyLoaded = showTab(el);
	
	hidePopup();
	
	// 19.04.06 amoro:
	// сброс галочки в меню "непоместившихся" вкладок
	if (window.activePart.partNum < getTabCount())
		selectPopupMenuItem("tabMenu");
		
	focusOnTabContent(window.activePart.partNum);
	
	// 24.08.06 amoro:
	// не придумал ничего лучше, как проверять возможность поиска по тексту здесь
	var frm = window.frames['f' + window.activePart.partNum];
	if (typeof(frm.canSearch) != 'undefined')
		setSearchState(frm.canSearch());
	else
		setSearchState(true);
	var word = document.getElementById('word');
	if (word != null)
		setButtonState(word, !(frm.isDjVuDoc && frm.isDjVuDoc()));
		
	// 05.07.07 amoro:
	// проверим, в актуальном ли состоянии настройки поиска
	// на вкладке с DjVu-документом
	var djvuMode = false;
	if (frm.isDjVuDoc && frm.isDjVuDoc())
	{
		frm.djvuCheckSearch();
		djvuMode = true;
	}
		
	// 05.07.07 amoro:
	// на разных вкладках - разные варианты поиска,
	// переключаем тут это дело
	if (!djvuMode || alreadyLoaded)
		setSearchModes(djvuMode);

	// 07.04.06 amoro:
	// в некоторых случаях надо выполнять доп. действия
	// (напр., на странице поиска)	
	if (typeof(tabAfterClick) != "undefined")
		tabAfterClick(window.activePart.partNum, apart);
	
	return false;
}

window.tabClick = tabClick;

function goChap(nh, chap)
{
	var el = document.getElementById('t' + nh);
	if (el == null)
		el = document.getElementById('m' + nh);
	if (el == null)
		return false;
	var frm = window.frames['f' + nh];
	if (frm == null)
		return false;
	if (frm.document.location == 'about:blank'){
		var href = el.href;
		var i = href.indexOf('d&');
		var frm_src = href.substring(0, i) + 'text&chap=' + chap + href.substring(i + 1);
		frm.document.location = frm_src + '#c' + chap;
		tabClick(el);
		return true;
	}
	tabClick(el);
	if (frm.isDjVuDoc && frm.isDjVuDoc())
	{
		frm.djvuGoChap(chap);
	}
	else
	{
		frmDoc	= frm.document;
		if (frmDoc == null)
			return false;
		var anchor = frmDoc.getElementById('c' + chap);
		if (anchor == null)
			return true;
		var next = anchor.nextSibling;
		if ((next != null) && (next.className.substring(0, 8) == 'punload_'))
			frmDoc.anchor = 'c' + chap;
		anchor.scrollIntoView(true);
	}
	return true;
}

window.goChap = goChap;
function html_unescape(s)
{
	return s.replace('&nbsp;', ' ').replace('&nbsp;', ' ').replace('&amp;', '&').replace('<u>', '').replace('</u>', '').replace('<U>', '').replace('</U>', '');
}

function html_escape(s)
{
	return (s + '').replace('&', '&amp;').replace('<', '&lt;').replace('>', '&gt;');
}

function menuTabClick(el)
{
	// 18.04.06 amoro:
	// в связи с вводом универсального механизма
	// формирования всплывающего меню, элемент ANCHOR
	// теперь лежит глубже в подчиненных элементах
	var elms = el.getElementsByTagName("A");
	if (elms == null || elms.length == 0)
		return false;
	window.parent.tabClick(elms[0]);
	return true;
}

// 17.03.06 amoro:
// Восстановление состояния страницы из информации о состоянии,
// упакованной в строку
function restoreStateFromString(str)
{
	if (window.activePart == null)
	{
		stateCtrl.load(str);
		return;
	}
	
	var oldNum = window.activePart.partNum;
	stateCtrl.load(str);
	if (window.activePart.partNum == oldNum)
		return;

	hideTab(oldNum);
	var n_part = window.activePart.partNum;
	var tab = document.getElementById('t' + n_part);
	if (tab == null)
		tab = document.getElementById('m' + n_part);
	showTab(tab);
	
	// 22.05.06 amoro:
	// вынес из showTab, т.к. иногда надо позиционироваться не во вкладку
	focusOnTabContent(n_part);
	
	// 07.04.06 amoro:
	// в некоторых случаях надо выполнять доп. действия
	// (напр., на странице поиска)	
	if (typeof(tabAfterClick) != "undefined")
		tabAfterClick(n_part, oldNum);
}

// 09.02.06 amoro:
// Восстановление состояния страницы
function restoreState(el)
{
	restoreStateFromString(el.getAttribute('pageState')+'');
}

// 09.02.06 amoro:
// Сохранение состояния страницы
function saveState(el)
{
	var ss = stateCtrl.save();
	el.setAttribute('pageState', ss);
}


function setPopupTab(el)
{
	var n_part = el.id.substring(1);
 	setTabState(window.activePart.partNum, false);
	setTabState('', true);
}

function showTabPopup(el)
{
	setPopupTab(el);
	return showCustomPopup(el, 'tabMenu', 10, 0, hideTabPopup);
}

function hideTabPopup()
{
	// 19.04.06 amoro:
	// если уже была выделена вкладка из числа тех,
	// которые скрываются в меню вкладок, то после
	// закрытия меню не нужно "гасить" ярлычок '...'
 	if (window.activePart.partNum < getTabCount())
 	{
 		setTabState(window.activePart.partNum, true);
		setTabState('', false);
	}
}

function showFindPopup(el)
{
	return showCustomPopup(el, 'findMenu', -1, -5);
}

function tabFocus(el)
{
	if ((window.event != null) && window.event.altKey)
		el.click();
}

function getCursorPos(textElement) 
{
	//save off the current value to restore it later,
	var sOldText = textElement.value;

	//create a range object and save off it's text
	var objRange = document.selection.createRange();
	var sOldRange = objRange.text;

	//set this string to a small string that will not normally be encountered
	var sWeirdString = '#%~';

	//insert the weirdstring where the cursor is at
	objRange.text = sOldRange + sWeirdString; objRange.moveStart('character', (0 - sOldRange.length - sWeirdString.length));

	//save off the new string with the weirdstring in it
	var sNewText = textElement.value;

	//set the actual text value back to how it was
	objRange.text = sOldRange;

	//look through the new string we saved off and find the location of
	//the weirdstring that was inserted and return that value
	for (i=0; i <= sNewText.length; i++) {
		var sTemp = sNewText.substring(i, i + sWeirdString.length);
		if (sTemp == sWeirdString) {
			var cursorPos = (i - sOldRange.length);
			return cursorPos;
		}
	}
}

function checkInput()
{
	var objRange = document.selection.createRange();
	if (objRange.text == ''){
		var input = document.getElementById('barsearch');
		if (input.value != ''){
			var pos = getCursorPos(input);
			if ((input.value != window.query_text) ||
				(pos != window.query_pos)){
			}
		}
	}
	window.setTimeout("checkInput()", 100);
}

function inputFocus(el)
{
	var def_el = document.getElementById(el.id + '_def');
	var class_name = el.className;
	if (class_name.substring(class_name.length - 4) == '_def')
		el.className = class_name.substring(0, class_name.length - 4);
	if (el.value != def_el.value)
		return;
	el.value = '';
}

function inputBlur(el)
{
	if (el.value != '')
		return;
	var def_el = document.getElementById(el.id + '_def');
	el.value = def_el.value;
	var class_name = el.className;
	if (class_name.substring(class_name.length - 4) != '_def')
		el.className = class_name + '_def';
}

function barsearchKeypress(el, e)
{
	if (e == null)
		e = window.event;
	if (e.keyCode == 13)
	{
		// 26.03.07 amoro:
		// обработчик события "запуск интеллектуального поиска" задается в одном
		// месте - в описании кнопки
		if (this.value != '')
		{
			var sbtn = document.getElementById('barsearch_isearch_btn');
			sbtn.click();
		}
		else
			return false;
	}
	return true;
}

function checkBarsearchTitle(el)
{
	if (el.value != '')
	{
		if (el.title != "")
		{
			window.barsearch_title = el.title;
			el.title = "";
		}
	}
	else if (typeof(window.barsearch_title) != "undefined" && (window.barsearch_title+"" != ""))
	{
		el.title = window.barsearch_title;
	}
}

function helpKeydown(e)
{
	if (e == null)
		e = window.event;
	var code = e.keyCode;
	if (code == 112){ // F1
		var help = document.getElementById('help');
		if (help != null){
			help.click();
			return false;
		}
	}
	return true;
}

function mainKeydown(e)
{
	if (e == null)
		e = window.event;
	var code = e.keyCode;
	if (code == 112){
		var help = document.getElementById('help');
		if (help != null){
			help.click();
			return;
		}
	}
	if ((code == 65) && e.ctrlKey){
		if (e.srcElement.tagName == 'INPUT')
			return true;
		if (window.active_frame != null){
			var frm = window.active_frame;
		}else{
			var frm = GetWorkFrame();
		}
		if (frm != null){
			if (frm.SelectAll != null){
				frm.SelectAll();
			}else{
				var doc = frm.document;
				doc.execCommand("SelectAll");
			}
		}
		return false;
	}
	return true;
}

function loadDoc(notree)
{
	document.onkeydown = mainKeydown;
    if (window.activePart != null){
		// 27.04.06 amoro:
		// для исключения перерисовки ярлычков после возврата
		// из элемента списка на страницу расширенного поиска,
		// вызовем здесь процедуру маскирования незадействованных ярлычков
		var etabs = document.getElementById('initially_enabled_tabs');
		if (etabs != null)
			setEnabledTabsList(etabs.value);
		// 25.04.06 amoro:
		// сделал автоподбор кол-ва отображаемых
		// ярлычков в панели инструментов
		autoSelectTabCnt();
		var n_part = activePart.partNum;
		var tab = document.getElementById('t' + n_part);
		if (tab == null)
			tab = document.getElementById('m' + n_part);
		var mark = document.getElementById('mark');
		if (mark != null)
			mark = mark.value;
		showTab(tab, mark);
		// 14.07.06 amoro:
		// надо ставить фокус на страницу, но это можно
		// переопределять в tabAfterClick
		focusOnTabContent(n_part);
		if (typeof(tabAfterClick) != "undefined")
			tabAfterClick(n_part, null);
	}

	var els = document.getElementsByTagName('INPUT');
	for (i = 0; i < els.length; i++){
		var el = els[i];
		// 26.03.07 amoro:
		// Если поле ввода уже заполнено, не надо его перезаписывать
		// значением по-умолчанию
		if (el.value != '')
			continue;
		var def_el = document.getElementById(el.id + '_def');
		if (def_el != null){
			el.value = def_el.value;
			var class_name = el.className;
			if (class_name.substring(class_name.length - 4) != 'def')
				el.className = class_name + '_def';
		}
	}
	if (typeof OnSettingChange != 'undefined'){
		OnSettingChange();
		OnCopyChange();
	}
	if ((notree == null) && (window.tree != null))
		tree_init();
}

function setButtonState(button, state)
{
	if (button == null)
		return;
	var src = button.src;
//26 ноября 2006, Макс. Я убрал (закоментарил) изменение disabled по той причине,
//что в safework это приводит к перезагрузке в iframe, дерганью и перерисовке. Похоже, что это 
//происходит при любом изменении стилей в элементах. ПО крайней мере, я наблюдал что-то
//подобное по крайней мере один раз и не в safework
	if (state){
		//button.parentNode.disabled = false;
		if (src.substring(src.length - 6) == '_d.gif')
			button.src = src.substring(0, src.length - 6) + '.gif';
	}else{
		//button.parentNode.disabled = true;
		if (src.substring(src.length - 6) != '_d.gif'){
			if (src.substring(src.length - 6) == '_a.gif'){
				button.src = src.substring(0, src.length - 6) + '_d.gif';
			}else{
				button.src = src.substring(0, src.length - 4) + '_d.gif';
			}
		}
	}
}

window.setButtonState = setButtonState;

function getURL(frm)
{
	var frm_url = frm.document.URL;
	var url     = document.URL;
	var p1		= frm_url.indexOf('://');
	var p2		= url.indexOf('://');
	if ((p1 != p2) || (frm_url.substring(0, p1) != url.substring(0, p2)))
		return frm_url;
	for (;;){
		p1 = frm_url.indexOf('/');
		p2 = url.indexOf('/');
		if ((p1 < 0) || (p1 != p2) || (frm_url.substring(0, p1) != url.substring(0, p2)))
			break;
		frm_url	= frm_url.substring(p1 + 1);
		url		= url.substring(p2 + 1);
	}
	return '/' + frm_url;
}

function getTabUrl(ntab)
{
	var e = document.getElementById('t' + ntab);
	if (e == null)
		e = document.getElementById('m' + ntab);
	if (e == null)
		return '';
	return e.href+'';
}

function replaceScriptInUrl(url, newScript)
{
	var i1 = url.indexOf('?');
	if (i1 < 0)
		return url;
	var res = url.substring(0, i1) + '?' + newScript;
	var url2 = url.substring(i1);
	var i2 = url2.indexOf('&');
	if (i2 > 0)
		res += url2.substring(i2);
	return res;
}

function copyToWord(el)
{
//debugger;
	var word = document.getElementById('word');
	if (word != null){
		var src  = word.src;
		if (src.substring(src.length - 6) == '_d.gif')
			return false;
	}

	var listSel = false;
	var frmWnd	= null;
	var copy_text = null;
	var copy_url  = null;
	if (window.active_frame != null){
		var frm = window.active_frame;
	}else{
		var frm = GetWorkFrame();
	}
	if (frm != null){
		var top = null;
		var doc = frm.document;
		if (doc != null){
			sel = doc.selection;
			if ((sel != null) && (sel.type != 'Text'))
				sel = null;
		}
		frmWnd = frm.window;
		if (typeof(frmWnd.isActiveSelected) == "undefined")
		{
			var list_frm = frmWnd.frames['list_frm'];
			if (list_frm != null)
			{
				frmWnd = list_frm;
			}
		}
		if (typeof(frmWnd.isActiveSelected) != "undefined")
		{
			listSel = frmWnd.isActiveSelected();
		}
	}
	
	if (sel != null){
		copy_text = getSelectionHTML(sel, doc);
	}

	var what = '';

	if ((copy_text == null) && listSel && (frmWnd != null))
	{
		var listPrintParams = frmWnd.getPrintParams();
		if (listPrintParams != null)
		{
			var res = showModalDialog(window.pPath + 'wordpart');
			if (res == null)
				return false;
			copy_url  = listPrintParams.Url + '&' + listPrintParams.Selection;
			what = '&what=' + res;
		}
	}

	if ((window.active_frame != null) || (window.activePart == null)){
		var url = el.href;
		var pos = url.indexOf('word&');
		if (pos >= 0)
			url = url.substring(0, pos + 5);
		if (window.active_frame != null){
			url += 'url=' + escape(getURL(window.active_frame));
		}else{
			url += 'url=' + escape(getURL(frm));
		}
		el.href = url + what;
		return true;
	}
	var n_part = window.activePart.partNum;
	var url = getTabUrl(n_part);
	if (url == '')
		return true;
	url = replaceScriptInUrl(url, 'word');
	if ((copy_url != null) || (copy_text != null))
	{
		var frm    = document.getElementById('post_form');
		var action = frm.action;
		action     = url + what;
		frm.action = action;
		frm.target = '';
		var p_text  = document.getElementById('post_form_text');
		var p_url   = document.getElementById('post_form_url');
		p_text.value = '';
		p_url.value  = '';
		if (copy_text != null)
			p_text.value = copy_text;
		if (copy_url != null)
			p_url.value  = copy_url;
		frm.submit();
		return false;
	}
	el.href = url + what;
	return true;
}

function saveToFile(el)
{
	if ((window.active_frame != null) || (window.activePart == null)){
		var url = el.href;
		var pos = url.indexOf('/url');
		if (pos >= 0)
			url = url.substring(0, pos);
		if (window.active_frame != null){
			url += '/url=' + escape(getURL(window.active_frame)).replace(/\//g, '%2F');
		}else{
			var frm = GetWorkFrame();
			if (frm == null)
				return false;
			url += '/url=' + escape(getURL(frm)).replace(/\//g, '%2F');
		}
		el.href = url;
		return true;
	}
	var n_part = window.activePart.partNum;
	var url = getTabUrl(n_part);
	if (url == '')
		return true;
	url = replaceScriptInUrl(url, 'save').replace('?', '/').replace(/\&/g, '/');
	var el_url = (el.href + '');
	var i = el_url.lastIndexOf('/');
	if (i >= 0)
		el_url = el_url.substring(i);
	el.href = url + el_url;
	return true;
}

function checkQuery()
{
	var el = document.getElementById('barsearch');
	var def_el = document.getElementById('barsearch_def');
	if ((el.value == def_el.value) || (el.value == '')){
		alert(window.str_input_query_string, window.str_search);
		return false;
	}
	return true;
}


// поддержка материалов пользователя

function is_space(s)
{
	return (s == ' ') || (s == '\r') || (s == '\n') || (s == '\t');
}

function html_scape(s)
{
	return s.replace(/\&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

function GetWorkFrame()
{
	var workFrameNumber = null;
	if (window.activePart != null)
		workFrameNumber = window.activePart.partNum;

	// теперь пытаемся получить iframe
	// 17.05.06 amoro:
	// для поддержки разных браузеров надо использовать коллекцию window.frames
	var workFrame = null;
	if (workFrameNumber != null)
		workFrame = window.frames["f" + workFrameNumber];
	if (workFrame == null)
		workFrame = window.frames["url_frm"];
	return workFrame;
}

function GetWorkFrameNumber()
{
	if (window.activePart != null)
		return window.activePart.partNum;
	return null;
}

function AddFavorite(numdoc, basepath)
{
	var workFrame = GetWorkFrame();
	if (workFrame == null)
		return;
			
	// 02.05.06 amoro:
	// если есть выделение в списке, обрабатываем выделенные элементы
	var listSel = false;
	var frmWnd = workFrame;
	if (typeof(frmWnd.isActiveSelected) == "undefined")
	{
		var frm = frmWnd.document.getElementById('list_frm');
		if (frm != null)
		{
			frmWnd = frmWnd.frames['list_frm'];
		}
	}
	if (typeof(frmWnd.isActiveSelected) != "undefined")
	{
		listSel = frmWnd.isActiveSelected();
	}
	
	// 19.10.06 amoro:
	// поддержка DjVu-документов
	var djvu = false;
	if (typeof(frmWnd.isDjVuDoc) != "undefined")
	{
		djvu = frmWnd.isDjVuDoc();
	}
	
	var words = 0;
	var sel   = null;
	var textrange = null;
	var name  = '';
	if (workFrame.document.selection != null && workFrame.document.selection.type == 'Text')
	{
		var textrange = workFrame.document.selection.createRange();
		if (is_space(textrange.text.substring(0, 1))){
			for (;;){
				if (textrange.moveStart('character', 1) == 0)
					break;
				if (!is_space(textrange.text.substring(0, 1)))
					break;
			}
		}else{
			for (;;){
				var tr = textrange.duplicate();
				if (tr.moveStart('character', -1) == 0)
					break;
				if (is_space(tr.text.substring(0, 1)))
					break;
				var htmlText = textrange.htmlText;
				htmlText = htmlText.replace(/[\r\n]/g, '');
				var trText = tr.htmlText.replace(/[\r\r]/g, '');
				if (trText.indexOf(htmlText.substring(0, 3)) > 1)
					break;
				textrange = tr;
			}
		}
		if (is_space(textrange.text.substring(textrange.text.length - 1))){
			for (;;){
				if (textrange.moveEnd('character', -1) == 0)
					break;
				if (!is_space(textrange.text.substring(textrange.text.length - 1)))
					break;
			}
		}else{
			for (;;){
				var tr = textrange.duplicate();
				if (tr.moveEnd('character', 1) == 0)
					break;
				if (is_space(tr.text.substring(tr.text.length - 1)))
					break;
				var htmlText = textrange.htmlText;
				htmlText = htmlText.replace(/[\r\n]/g, '').substring(htmlText.length - 3);
				var trText = tr.htmlText.replace(/[\r\r]/g, '');
				if (trText.lastIndexOf(htmlText) < tr.htmlText.length - htmlText.length - 1)
					break;
				textrange = tr;
			}
		}
		var name = textrange.text;
		var arr  = name.split(/[ \t\n\r\.\,:;\'\"\[\]\(\)]+(-+[ \t\n\r\.\,:;\'\"\[\]\(\)]+)?/);
		words = arr.length;
		sel   = textrange.duplicate();
		textrange.collapse();
	}
	else
	{
		// спозиционируемся на первый объект
		if (workFrame.document.URL != 'about:blank'){
			var textrange = workFrame.document.body.createTextRange();
			textrange.moveToPoint(1, 1);
		}
	}
	var wc = 0;
	if (textrange != null)
		textrange.moveEnd("word", 32);

	var fav_param = new FavoriteParams(numdoc);
	fav_param.frame  = GetWorkFrameNumber();
	if (textrange != null)
		fav_param.marker = textrange.text;
	if (words > 0){
		name = name.replace(/\r?\n/g, ' ').replace(/ +/g, ' ');
		if (name.length > 256){
			name = name.substring(0, 253);
			var pos = name.lastIndexOf(' ');
			if (pos > 50)
				name = name.substring(0, pos);
			name += '...';
		}
		fav_param.name = name;
	}
	fav_param.words  = words;
	
	// 19.10.06 amoro:
	// поддержка DjVu-документов
	if (djvu)
	{
		fav_param.marker = frmWnd.djvuGetCurrentPage();
		fav_param.special_marker = 1;
	}

	var annot = document.getElementById('annot');
	if (annot != null)
		fav_param.comment = annot.innerText;

	// запросим пользователя диалогом о наименовании линка, папке для
	// хранения, комментарии
	var res = showModalDialog(basepath + "dialog_addfavorite", fav_param, 'dialogWidth: 400px');
	if( res == 1 )
	{
		// 02.05.06 amoro:
		// если есть выделение в списке - специальная обработка
		if (listSel && frmWnd != null && typeof(frmWnd.AddSelectionToFavorite) != "undefined")
		{
			frmWnd.AddSelectionToFavorite(fav_param);
			return;
		}
		
		// найдем теперь документ в кодексе, сгенерируем маркер, полную URL
		// и положим в папку пользователя
		var xmlHttp = CreateXmlHttp();
		xmlHttp.open('POST', window.pPath + 'userm_ajax&func=CreateFavorite', false, document.location.href);
		var longArg = "";
		for(var vn in fav_param) longArg += (longArg==''?'':'&') + 'fp_' + vn + '=' + escape(fav_param[vn]);
		xmlHttp.send(longArg);
		if( xmlHttp.status < 200 || xmlHttp.status > 299 )
		{
			alert(xmlHttp.responseText);
			return;
		}
		setFocusTo(workFrame);
		if (sel != null){
			// если не удалось поставить выделение, то перезагрузим документ
			try
			{
				SetRangeClass(sel, 'bookmark', ' title="' + html_scape(fav_param.comment) + '"');
				sel.select();
			}
			catch(err)
			{
				var url = document.location + window.pPath;
				var pos = url.lastIndexOf('/');
				if (pos > 0)
					url = url.substring(0, pos + 1);
				url += xmlHttp.responseText;
				document.location.replace(url);
			}
		}
	}
}

function SetRangeClass(sel, classname, title, id)
{
	var start_tag = '<span class="' + classname + '"';
	if (title != null)
		start_tag += title;
	var end_tag   = '</span>';
	var src  = sel.htmlText.replace(/[\r\n]/g, '');
	var html = '';
	var id_src = id;
	var n_id   = 0;
	
	while (src.length > 0){
		var n = src.indexOf('<');
		if (n != 0){
			var start = start_tag;
			if (id != null){
				start += ' id="' + id + '"';
				n_id++;
				id = id_src + '_' + n_id;
			}
			start += '>';
		}
		if (n < 0){
			html += start;
			html += src;
			html += end_tag;
			break;
		}
		if (n > 0){
			html += start;
			html += src.substring(0, n);
			html += end_tag;
			src = src.substring(n);
		}
		var n = src.indexOf('>');
		if (n < 0)
			break;
		html += src.substring(0, n + 1);
		src = src.substring(n + 1);
	}
	if (html.substring(0, 2) == '<P'){
		var n = html.indexOf('>');
		html = html.substring(n + 1);
	}
	if (html.substring(html.length - 4) == '</P>')
		html = html.substring(0, html.length - 4);

	var range = sel.duplicate();
	range.collapse();
	
	sel.pasteHTML(html);
}

function PutSearchToFavorite(basepath)
{
	var workFrame = window.frames["f" + window.activePart.partNum];
	if (workFrame == null)
	{
		// не удалось найти рабочий iframe
		// пока не обрабатываем
		return;
	}
	
	var sp_inp = workFrame.document.getElementById('search_params');
	if (sp_inp != null)
	{
		var sp = sp_inp.value;
		var fav_param = new FavoriteParams(0);
		fav_param.params = sp;
		
		var res = showModalDialog(basepath + "dialog_addfavorite", fav_param, 'dialogWidth: 400px');
		if( res == 1 )
		{
			var xmlHttp = CreateXmlHttp();
			xmlHttp.open('POST', window.pPath + 'userm_ajax&func=PutSearchToFavorite', false, document.location.href);
			var longArg = "";
			for(var vn in fav_param) longArg += (longArg==''?'':'&') + 'sfp_' + vn + '=' + escape(fav_param[vn]);
			xmlHttp.send(longArg);
			if( xmlHttp.status < 200 || xmlHttp.status > 299 )
			{
			alert(window.msg_error + ". " + xmlHttp.responseText);
				return;
			}
		}
	}
}

function FavoriteParams(numdoc)
{
	this.nd			= numdoc;	// номер документа
	
	this.name		= document.title;	// имя закладки
	this.comment	= "";	// примечание (комментарий)
	this.folder		= "";	// GUID папки, куда надо положить
	
	this.frame		= -1;	// номер текущего видимого фрейма
	this.objid		= "";	// id объекта
	this.wc			= -1;	// счетчик первого видимого слова в объекте
	this.wclength	= -1;	// длина этих слов в символах
	this.marker		= '';
}

function IsKodeksId(id)
{
	return (id.match(/^P[0-9A-Fa-f]+$/) != null) && ((id.length-1) % 4 == 0);
}

function FindVisibleChild(doc, startObj)
{
	if( startObj == null ) return null;
	var obj;
	var foundobj = null;
	for(obj = startObj.firstChild; obj != null; obj = obj.nextSibling)
	{
		if( obj.id != "" && obj.tagName == "P" && IsVisible(doc, obj) )
		{
			return obj;
		}
		if( null != obj.hasChildNodes )
		{
			foundobj = FindVisibleChild(doc, obj);
			if( foundobj != null ) return foundobj;
		}
	}
	return null;
}

function IsVisible(doc, obj)
{
	var tr = doc.body.createTextRange();
	tr.moveToElementText(obj);
	var trc = tr.getBoundingClientRect();
	return trc.bottom >= 0;
}


// функция для создания новой папки для материалов пользователя
function FavoriteAddFolder()
{
	// 17.05.06 amoro:
	// для поддержки разных браузеров надо использовать коллекцию window.frames
	var url = window.parent.pPath + "dialog_addfolder";
	// 26.06.06 amoro:
	// пусть в диалоге изначально будет выделена текущая папка
	// 05.07.06 amoro:
	// после создания новой папки надо ее выделить
	var folderWnd = window.frames['f0'].frames['folders'];
	if (folderWnd == null || folderWnd.getSelectedFolder == null)
		return;
	var guid = folderWnd.getSelectedFolder();
	if (guid != null && guid != 'GUID-ROOT')
		url += '&parent=' + guid;
	var res = showModalDialog(url, null, "dialogWidth: 400px");
	if (res == null)
		return;
	folderWnd.setSelectedFolder(res);
	if (typeof(stateCtrl) != "undefined")
		stateCtrl.save();
	folderWnd.location.reload(true);
}

// функция для удаления папки с материалами пользователя
function FavoriteDelFolder()
{
	// проверим на запрещенность кнопки
	if( document.getElementById('favdelfolder') == null ) return;
	var aobj = document.getElementById('favdelfolder').parentNode;
	if( aobj == null ) return;
	if( aobj.disabled == true ) return;

	// получим документ с папками
	// 17.05.06 amoro:
	// для поддержки разных браузеров надо использовать коллекцию window.frames
	// 05.07.06 amoro:
	// небольшая переделка кода, без изменения функциональности
	var folderWnd = window.frames['f0'].frames['folders'];
	if (folderWnd && folderWnd.getSelectedFolder)
	{
		var guid = folderWnd.getSelectedFolder();
		if (guid == null)
			return;
		var xmlHttp = CreateXmlHttp();
		var ask = '';
		if( guid == 'GUID-ROOT' )
		{
			ask = window.msg_delete_all;
		}
		else
		{
			// получим имя папки
			xmlHttp.open('GET', window.pPath + 'userm_ajax&func=GetFolderName&guid=' + guid, false, document.location.href);
			xmlHttp.send();
			if( xmlHttp.status != 200 )
			{
				alert(window.msg_error_folder);
				return;
			}
			var name = xmlHttp.responseText;
			ask = window.msg_delete_folder + " '" + name + "'?";
		}
		var name = xmlHttp.responseText;
		var ans = confirm(ask);
		if( ans == true )
		{
			xmlHttp.open('GET', window.pPath + 'userm_ajax&func=DeleteFolder&guid=' + guid, false, document.location.href);
			xmlHttp.send();
			if( xmlHttp.status == 200 && xmlHttp.responseText == 'true' )
			{
				folderWnd.location.reload(true);
				window.frames['f0'].frames['links'].location.reload(true);
			}
		}
	}
}

function FavoriteDelFavorite()
{
	// проверим на запрещенность кнопки
	if( document.getElementById('favdelfavorite') == null ) return;
	var aobj = document.getElementById('favdelfavorite').parentNode;
	if( aobj == null ) return;
	if( aobj.disabled == true ) return;
	
	// получим номер документа закладки для удаления
	// 17.05.06 amoro:
	// для поддержки разных браузеров надо использовать коллекцию window.frames
	var linksWnd = window.frames['f0'].frames['links'].frames['list_frm'];
	if( linksWnd && linksWnd.GetSelectedUsermID )
	{
		// 03.07.06 amoro:
		// удаление списка закладок
		var usermID = linksWnd.GetSelectedUsermID();
		if( usermID != null && usermID.length > 0 )
		{
			var xmlHttp = CreateXmlHttp();
			xmlHttp.open('GET', window.pPath + 'userm_ajax&func=DeleteFavoriteMsg&n=' + usermID.length, false, document.location.href);
			xmlHttp.send();
			if (xmlHttp.status == 200){
				if (!confirm(xmlHttp.responseText))
					return;
			}
			// надо удалить документ
			var xmlHttp = CreateXmlHttp();
			xmlHttp.open('GET', window.pPath + 'userm_ajax&func=DeleteFavorite&guid=' + usermID.join(';'), false, document.location.href);
			xmlHttp.send();
			if( xmlHttp.status == 200 && xmlHttp.responseText == 'true' )
			{
				if (linksWnd.ClearFavSelection)
					linksWnd.ClearFavSelection();
				stateCtrl.save();
				linksWnd.parent.location.reload(true);
			}
		}
	}
}

/* Конфигурирование материалов пользователя */
function FavoriteConfig()
{
	var url = window.parent.pPath + "dialog_umsetup";
	var res = showModalDialog(url);
}

function HistoryConfig()
{
	var url = window.parent.pPath + "dialog_history";
	var res = showModalDialog(url);
}

function setImageState(img, state)
{
	if (img == null)
		return;
	var src = img.src + '';
	var ext = '';
	var index = src.lastIndexOf('.');
	if (index >= 0){
		ext = src.substring(index);
		src = src.substring(0, index);
	}
	var img_state = src.substring(src.length - 2);
	if (img_state == '_d')
		return;
	if (state){
		if (img_state != '_a')
			img.src = src + '_a' + ext;
	}else{
		if (img_state == '_a')
			img.src = src.substring(0, src.length - 2) + ext;
	}
}

function getBackground(td)
{
	if (td.background != null)
		return td.background + '';
	for (var i in td.attributes){
		if (td.attributes[i].name.toLowerCase() == 'background')
			return td.attributes[i].nodeValue;
	}
}

function setBackground(td, bg)
{
	if (td.background != null){
		td.background = bg;
		return;
	}
	for (var i in td.attributes){
		if (td.attributes[i].name.toLowerCase() == 'background'){
			td.attributes[i].nodeValue = bg;
			return;
		}
	}
}

function setTabState(tab, state)
{
	if (parseInt(tab) >= getTabCount())
		tab = '';
	setImageState(document.getElementById('il' + tab), state);
	setImageState(document.getElementById('ir' + tab), state);
	var a = document.getElementById('t' + tab);
	if (a != null)
		a.className = state ? 'tabOn' : 'tabOff';
	var td = document.getElementById('tab' + tab);
	if (td != null){
		var src = getBackground(td);
		var ext = '';
		var index = src.lastIndexOf('.');
		if (index >= 0){
			ext = src.substring(index);
			src = src.substring(0, index);
		}
		var bg;
		if (state){
			if (src.substring(src.length - 2) != '_a')
				setBackground(td, src + '_a' + ext);
		}else{
			if (src.substring(src.length - 2) == '_a')
				setBackground(td, src.substring(0, src.length - 2) + ext);
		}
	}	
}

function doCopy()
{
	if (document.selection.type != 'Text'){
		if (window.DoCopy != null){
			if (window.DoCopy())
				return;
		}
	}
	external.Application.Browser.Copy();
}

function PrintPart(name, url, is_djvu, id)
{
	if (is_djvu == null)
		is_djvu = false;
	this.Name		= name;
	this.URL		= url;
	this.isPrint	= false;
	this.isTab		= false;
	this.arguments	= null;
	this.is_djvu	= is_djvu;
	this.id			= id;
}

function showPartsDialog(parts)
{
	var url = window.print_parts.URL;
	var add = '';
	for (var i = 0; i < window.print_parts.length; i++){
		var part = window.print_parts[i];
		if (part.id == '')
			continue;
		add += ':' + i + ',' + part.id + ',' + escape(part.Name) + ',' + escape(part.URL);
	}
	if (add.length > 1)
		url += '&add=' + add.substring(1);
	if (parts.save != null)
		url += '&save=1';
	return showModalDialog(url, parts, null, window);
}

function selectAllParts(parts)
{
	var changed = false;
	for (var i = 0; i < parts.length; i++){
		var p = parts[i];
		var isPrint = ((p.HTML == null) && (p.URL != null) && (p.onActivate == null));
		if (p.isPrint == isPrint)
			continue;
		changed = true;
		p.isPrint = isPrint;
	}
	return changed;
}

function Subst()
{
}

function getSelectionHTML(sel, doc)
{
	var res  = '';
	var range = sel.createRange();
	var html = range.htmlText;
	while (html.length > 0){
		var pos = html.indexOf('<A ');
		if (pos < 0){
			res += html;
			html = '';
			break;
		}
		res += html.substring(0, pos);
		html = html.substring(pos);
		pos  = html.indexOf('>');
		var tag = html.substring(0, pos + 1);
		html = html.substring(pos + 1);
		pos  = tag.indexOf('target=_blank');
		if (pos < 0){
			res += tag;
			continue;
		}
		pos  = html.indexOf('</A>');
		html = html.substring(pos + 4);
	}
	var el = range.parentElement();
	while (el != null){
		if ((el.tagName == 'BODY') || (el.tagName == 'TD'))
			break;
		var tag = el.outerHTML;
		var pos = tag.indexOf('>');
		if (pos >= 0)
			tag = tag.substring(0, pos + 1);
		res = tag + res + '</' + el.tagName + '>';
		el = el.parentNode;
	}
	var styles = doc.styleSheets;
	var s = ''
	for (var i = 0; i < styles.length; i++){
		var style = styles[i];
		s += '<STYLE>' + style.cssText + '</STYLE>';
	}
	return '<HTML><HEAD>' + s + '</HEAD><BODY CLASS="' + doc.body.className + '">' + res + '</BODY></HTML>';
}

function isDjVu()
{
	if (window.active_frame != null){
		var frm = window.active_frame;
	}else{
		var frm = GetWorkFrame();
	}
	if (frm == null)
		return false;
	if (frm.isDjVuDoc && frm.isDjVuDoc())
		return true;
	return false;
}

function getPrintParts(no_djvu)
{
	if (no_djvu == null)
		no_djvu = false;

	var parts = new Array();
	parts.save = null;
	
	var sel = null;
	var doc = document;
	var listSel = false;
	var frmWnd = null;
	if (window.active_frame != null){
		var frm = window.active_frame;
	}else{
		var frm = GetWorkFrame();
	}
	if (frm != null){
		var top = null;
		var doc = frm.document;
		if (doc != null){
			sel = doc.selection;
			if ((sel != null) && (sel.type != 'Text'))
				sel = null;
		}
		frmWnd = frm.window;
		if (typeof(frmWnd.isActiveSelected) == "undefined")
		{
			var frm = frmWnd.document.getElementById('list_frm');
			if (frm != null)
			{
				frmWnd = frmWnd.frames['list_frm'];
			}
		}
		if (typeof(frmWnd.isActiveSelected) != "undefined")
		{
			listSel = frmWnd.isActiveSelected();
		}
	}
	var is_selection = false;
	if (sel != null){
		var n = parts.length;
		parts[n] = new PrintPart(window.str_selection);
		parts[n].isPrint = false;
		parts[n].HTML = getSelectionHTML(sel, doc);
		parts[n].BaseURL = document.URL;
		is_selection = true;
		parts[n].isPrint = true;
	}
	if (listSel && frmWnd != null)
	{
		var listPrintParams = frmWnd.getPrintParams();
		if (listPrintParams != null)
		{
			var n = parts.length;
			parts[n] = new PrintPart(window.str_selection);
			parts[n].isPrint = true;
			parts[n].URL = listPrintParams.Url;
			parts[n].arguments = listPrintParams.Selection;
			if (window.list_data != null)
				parts[n].arguments += '&l=' + window.list_data;
			is_selection = true;
		}
	}
	if (doc != null){
		var first_anchor   = null;
		var first_anchor_y = 0xFFFFFFF;
		var pos_anchor	   = null;
		var pos_anchor_y   = -1;
		var pos_y = doc.body.scrollTop + 10;
		var anchors = doc.getElementsByTagName('A');
		for (var i = 0; i < anchors.length; i++){
			var anchor = anchors[i];
			if ((anchor.id + '').substring(0, 2) != 'cP')
				continue;
			var y = 0;
			var el = anchor;
			while (el != null){
				y += el.offsetTop;
				el = el.offsetParent;
			}
			if (y < first_anchor_y){
				first_anchor_y = y;
				first_anchor   = anchor;
			}
			if ((y <= pos_y) && (y > pos_anchor_y)){
				pos_anchor_y = y;
				pos_anchor   = anchor;
			}
		}
		if (pos_anchor == null)
			pos_anchor = first_anchor;
		if (pos_anchor != null){
			var name_el = doc.getElementById('n' + pos_anchor.id);
			if (name_el != null){
				var n = parts.length;
				var value = name_el.value + '';
				if (value.length > 60){
					value = value.substring(0, 60);
					var index = value.lastIndexOf(' ');
					if (index > 0)
						value = value.substring(0, index);
					value += '...';
				}
				parts[n] = new PrintPart(value, window.print_parts[window.activePart.partNum].URL);
				parts[n].isPrint   = !is_selection;
				parts[n].arguments = 'p=' + pos_anchor.id.substring(2);
				is_selection = true;
			}
		}
	}
	
	if (window.print_parts != null){
		var is_set = false;
		var n_parts = 0;
		for (var i = 0; i < window.print_parts.length; i++){
			if (no_djvu){
				if ((window.print_parts[i].is_djvu != null) && window.print_parts[i].is_djvu)
					continue;
			}
			n_parts++;
			// 07.09.06 amoro:
			// стоит показывать в списке печати только те вкладки,
			// в которых есть содержимое; если речь идет о рез-ах
			// поиска, то это такие вкладки, у которых виден либо
			// ярлычок, либо пункт в меню выбора непоместившихся
			var tab = document.getElementById('tabBlock' + i);
			var menuDoc = getMenuDoc('tabMenu');
			var menu;
			if (menuDoc != null)
				menu = menuDoc.getElementById('tabMenu_bar_m' + i);
			if (tab != null && tab.style.display == 'none' && menu != null && menu.style.display == 'none')
				continue;
			var n = parts.length;
			parts[n] = window.print_parts[i];
			parts[n].isTab = true;
			parts[n].isPrint = false;
			if (!is_selection && ((window.activePart == null) || (i == window.activePart.partNum))){
				parts[n].isPrint = true;
				is_set = true;
			}
		}
		if (!is_set && (parts.length > 0))
			parts[0].isPrint = true;
		if (n_parts > 1){
			var n = parts.length;
			parts[n] = new PrintPart(window.str_all_parts);
			parts[n].onActivate = selectAllParts;
			var n = parts.length;
			parts[n] = new PrintPart(window.str_custom);
			parts[n].onActivate = showPartsDialog;
		}
	}
	return parts;
}

window.getPrintParts	= getPrintParts;

function doPrint(el)
{
	// определим дополнительные параметры
	// 18.04.06 amoro:
	// т.к. на странице могут быть и другие фреймы (например, на странице
	// расширенного поиска форма ввода атрибутов хранится во фрейме),
	// то лучше передавать имя, а не номер фрейма вкладки
//	var av = 'frame=f' + activePart.partNum;
//	external.Application.Browser.PrintTemplate('kwtp://cd/ptempl/' + av);
//	return;
	
	if ((navigator.appName.indexOf('Explorer') == -1)||(typeof(external) == 'undefined')||(external.Application == null) || (external.Application.Printer == null))
	{
		if (window.active_frame != null){
			var url = el.href;
			var pos = url.indexOf('&url');
			if (pos >= 0)
				url = url.substring(0, pos);
			url += '&url=' + escape(getURL(window.active_frame)).replace(/\//g, '%2F');
			el.href = url;
			return true;
		}
		var n_part = window.activePart.partNum;
		var e = document.getElementById('t' + n_part);
		if (e == null)
			e = document.getElementById('m' + n_part);
		if (e == null)
			return true;
		var url = (e.href + '').replace('?text', '?print');
		var el_url = (el.href + '');
		el.href = url + el_url;
		return true;
	}
	
	var printer = external.Application.Printer;
	
	printer.Subst	 = new Subst();
	printer.DefSubst = new Subst();
	printer.Subst.n = html_escape(document.title);
	printer.DefSubst.n = window.str_short_title;
	if (window.original_title != null)
		printer.Subst.n = window.original_title;
	printer.JobName = printer.Subst.n;
	printer.Subst.m = printer.Subst.n;
	printer.DefSubst.m = window.str_full_title;
	printer.Orientation = 2;
	
	var annot = document.getElementById('annot');
	if (annot != null)
		printer.Subst.m = annot.innerHTML;
	printer.Subst.a = '';
	var ainfo = document.getElementById('ainfo');
	if (ainfo != null)
		printer.Subst.a = ainfo.innerHTML;
	printer.DefSubst.a = window.str_information_string;
	printer.Subst.d    = window.current_date;
	printer.DefSubst.d = window.str_current_date;

	var parts	= getPrintParts();
	external.Application.Browser.Print(parts, printer);
	if (external.Application.UserConfig != null)
		external.Application.UserConfig.Printer = printer;
	return false;
}

function submitSearchForm(advanced, topBarPanelId)
{
	// 04.07.06 amoro:
	// показ сообщения об идущем процессе поиска
	disableDataPanelForSearch(window.parent, topBarPanelId);
	
	//найдем форму для поиска
	var doc = window.parent.document;
	var searchForm = doc.forms["find"];
	var input = doc.getElementById('barsearch');
	var input_def = doc.getElementById('barsearch_def');
	if (input.value == input_def.value)
		input.value = '';
	searchForm.advanced.value = advanced.toString();
	searchForm.submit();
}


// определение числа отображаемых ярлычков (в т.ч. незадействованных, хотя они не видны)
function getTabCount()
{
	if (window.displayedTabsManager != null)
		return window.displayedTabsManager.getDisplayedTabsCount();
	var tc = document.getElementById('displayed_tabs_cnt');
	if (tc != null)
		return parseInt(tc.value);
	return 0;
}

// проверка, а не вылезают ли ярлычки за допустимые границы
function isTabOver()
{
	var tab = document.getElementById('toolBarEnd');
	if (tab == null)
		return false;
		
	var coords = getTotalOffset(tab);
	var right = coords.x + tab.offsetWidth;
	var body = document.body;
	var bo = body.offsetWidth;
	if (coords.x >= bo || right > bo)
		return true;
	return false;
}

// автоподбор максимально влезающего числа ярлычков
function autoSelectTabCnt()
{
	if (window.displayedTabsManager != null)
		window.displayedTabsManager.balance();
}


// amoro: скопировал из text.js, надо делать общий модуль!
function getTotalOffset(eel)
{
	var el = eel;
	var ox = 0;
	var oy = 0;
	while (el != null)
	{
		ox += el.offsetLeft;
		oy += el.offsetTop;
		el = el.offsetParent;
	}
	return new Coords(ox, oy);
}

function Coords(x, y)
{
	this.x = x;
	this.y = y;
}

// _____________________________________________________________________________
// Поиск в тексте

window.searchEnabled = true;

function setSearchState(enabled)
{
	window.searchEnabled = enabled;
	var btn = document.getElementById('search');
	if (btn == null || typeof(btn) == 'undefined')
		return;
	setButtonState(btn, enabled);
}

window.setSearchState = setSearchState;

function doSearch()
{
	if (window.searchEnabled != null && !window.searchEnabled)
		return;
	var sdiv = document.getElementById('search_div');
	if (sdiv == null || typeof(sdiv) == 'undefined')
		return;
	sdiv.style.display = '';
	var frm = frames['search_frm'];
	if (frm == null)
		return;
	var h = frm.document.body.scrollHeight;
	document.getElementById('search_frm').style.height = h + 'px';
	var str = frm.document.getElementById('search_str');
	str.select();
	setFocusTo(str);	
	var frm = GetWorkFrame();
	checkSearch();
}

function search_forward()
{
	next_search(false);
}

function search_backward()
{
	next_search(true);
}

function next_search(shift, noselect)
{
	// найти следующее вхождение контекста
	if (window.active_frame == null){
		var frm = GetWorkFrame();
	}else{
		var frm = window.active_frame;
	}
	if (frm == null)
		return false;
	// 06.10.06 amoro:
	// поиск в DjVu-документе
	if (frm.isDjVuDoc && frm.isDjVuDoc())
	{
		// 12.02.07 amoro:
		// при переходе по вхождениям контекста, надо включать/выключать
		// соотв. кнопки дальнейшего перехода; для нормальных документов
		// это делается в другом месте
		var res = frm.djvuNextSearch(shift, noselect);
		if (noselect)
			return res;
		setDisabled(search_frm.document.getElementById('search_prev'), !next_search(true, true));
		setDisabled(search_frm.document.getElementById('search_next'), !next_search(false, true));
		return res;
	}
	if (frm.selected_ts != null){
		var ts = frm.selected_ts;
		var n_parts = frm.document.getElementById('n_parts');
		if (n_parts == null){
			if (shift){
				if (findTsBackwardFrom(ts, frm.document.body, frm, noselect))
					return true;
			}else{
				if (findTsForwardFrom(ts, frm.document.body, frm, noselect))
					return true;
			}
			if (noselect == null)
				selectTs(ts, frm);
			return false;
		}
		n_parts = parseInt(n_parts.value);
		var n_part = 0;
		var el = ts;
		while (el != null){
			if ((el.tagName == 'DIV') && (el.id.match(/P[0-9]+/) != null)){
				n_part = parseInt(el.id.substring(1));
				break;
			}
			el = el.parentNode;
		}
		if (shift){
			if (findTsBackwardFrom(ts, el, frm, noselect))
				return true;
		}else{
			if (findTsForwardFrom(ts, el, frm, noselect))
				return true;
		}
		if (shift){
			for (n_part--; n_part >= 0; n_part--){
				if (frm.search_res[n_part] != null){
					if (noselect == null){
						window.goUp = true;
						tsDiv(frm.document.getElementById('P' + n_part), frm);
					}
					return true;
				}
			}						
		}else{
			for (n_part++; n_part <= n_parts; n_part++){
				if (frm.search_res[n_part] != null){
					if (noselect == null){
						window.goUp = false;
						tsDiv(frm.document.getElementById('P' + n_part), frm);
					}
					return true;
				}
			}						
		}
		if (noselect == null)
			selectTs(ts, frm);
		return false;
	}
	if (frm.document.elementFromPoint == null)
		return false;
	var el = frm.document.elementFromPoint(50, 0);
	if (el == null)
		return false;
	if (shift){
		if (findTsBackward(el, true, frm))
			return true;
		if (findTsBackwardFrom(el, frm.document.body, frm, noselect))
			return true;
	}else{
		if (findTsForward(el, true, frm))
			return true;
		if (findTsForwardFrom(el, frm.document.body, frm, noselect))
			return true;
	}
	return false;
}

function startSearch(no_clear_frames, is_explorer)
{
	var number;
	var html = '';
	if (window.active_frame == null){
		number = GetWorkFrameNumber();
		var frm = GetWorkFrame();
		if ((frm != null) && (number == null))
			html = '&html=' + escape(frm.document.body.innerHTML);
	}else{
		var frm = window.active_frame;
	}
	if (frm == null)
		return;
	var djvuMode = (frm.isDjVuDoc && frm.isDjVuDoc());
	var search_frm = frames['search_frm'];
	var searchType = search_frm.document.getElementById('search_type').value;
	// 25.04.07 amoro:
	// если пользователь сменил тип поиска, то нужно искать по новой,
	// а не пытаться продолжать поиск
	if (frm.search_res != null&&
		window.find_str == search_frm.document.getElementById('search_str').value &&
		searchType != 2 &&
		searchType == window.find_type){
		var shift = false;
		var e = window.event;
		if (e == null){
			if (frm != null)
				e = frm.event;
			if (e == null && frm.isDjVuDoc && frm.isDjVuDoc())
				e = frm.frames['djvu_doc'].event;
		}
		if (e != null)
			shift = e.shiftKey;			
		next_search(shift);
		return false;
	}
	
	if(is_explorer && searchType == 1)
		window.searchXmlHttp = null;
	if (window.searchXmlHttp == null){
		window.searchXmlHttp = CreateXmlHttp();
		window.searchXmlHttp.onreadystatechange = function()
		{
			if (window.searchXmlHttp.readyState != 4)
				return;
			if (window.search_done != null)
				window.search_done(window.searchXmlHttp.responseText);
		};
	}
	if (searchType != 2)
	{
		setDisabled(search_frm.document.getElementById('search_next'), true);
		setDisabled(search_frm.document.getElementById('search_prev'), true);
	}
	setButtonText(search_frm.document.getElementById('ok'), window.str_find);
	if (no_clear_frames == null && searchType != 2)
		clearSearchFrames();
	window.search_done  = searchDone;
	window.search_frame = frm;
	frm.search_res  = new Array();
	window.find_str   = search_frm.document.getElementById('search_str').value;
	window.find_type  = searchType;
	var n_parts = frm.document.getElementById('n_parts');
	var nh;
	var nh_el = document.getElementById(frm.name + "_nh");
	if (nh_el != null)
	{
		nh = parseInt(nh_el.value, 10);
	}
	else
	{
		var url = frm.location.href;
		var ind = url.indexOf("&nh=");
		if (ind > 0)
		{
			url = url.substring(ind+4);
			nh = parseInt(url, 10);
		}
	}
	if (searchType == 2)
	{
		if (djvuMode)
		{
			if (window.searchXmlHttp2 == null){
				window.searchXmlHttp2 = CreateXmlHttp();
				window.searchXmlHttp2.onreadystatechange = function()
				{
					if (window.searchXmlHttp2.readyState != 4)
						return;
					if (window.search_done != null)
						window.search_done(window.searchXmlHttp2.responseText);
					loadISearchAnnotation(window.searchXmlHttp2.find_str, window.searchXmlHttp2.nh);
				};
			}
			if (checkISearchAnnotation(window.find_str, nh))
			{
				loadISearchAnnotation(window.find_str, nh);
			}
			else
			{
				clearSearchFrames();
				window.search_done  = searchDone;
				window.search_frame = frm;
				frm.search_res  = new Array();
				window.find_str   = search_frm.document.getElementById('search_str').value;
				window.find_type  = searchType;
				var url = window.pPath + 'search&nd=' + window.nd + '&nh=' + nh;
				window.searchXmlHttp2.find_str = window.find_str;
				window.searchXmlHttp2.nh = nh;
				window.searchXmlHttp2.open("POST", url, true);
				window.searchXmlHttp2.send("_c=" + escape(window.find_str));
			}
		}
		else
		{
			var sstr = window.find_str;
			if (!checkISearchAnnotation(sstr, nh))
				clearSearchFrames();
			loadISearchAnnotation(sstr, nh);
		}
		return false;
	}
	if (!djvuMode && ((window.find_type == 3) || (window.find_type == 4)) && (n_parts == null)){
		var search_res = new Array();
		search_res[0] = new Array();
		search_res[0][0] = window.find_str;
		searchResult(search_res, true, searchType);
		return false;
	}
	var data = '_c=' + escape(search_frm.document.getElementById('search_str').value) + html;
	var url = window.pPath + 'search';
	if (window.active_frame == null){
		url += '&nd=' + window.nd + '&nh=' + nh;
	}else{
		url += '&url=' + escape(getURL(window.active_frame));
	}
	url += '&type=' + window.find_type;
	window.searchXmlHttp.open("POST", url, true);
	window.searchXmlHttp.send(data);
	return false;
}

window.startSearch = startSearch;

function clearSearchResult()
{
	window.searchResultCleared = true;
	document.onkeydown = null;
	if (window.isDjVuDoc && window.isDjVuDoc())
		window.frames['djvu_doc'].document.onkeydown = null;
	if (this.document.body.createTextRange != null){
		this.selected_ts = null;
		var range = this.document.body.createTextRange();
		for (var n = 0; ; n++){
			var el = this.document.getElementById('ts' + n);
			if (el == null)
				break;
			var p = el.parentNode;
			el.outerHTML = el.innerHTML;
			for (var nn = 1; ;nn++){
				var el = this.document.getElementById('ts' + n + '_' + nn);
				if (el == null)
					break;
				el.outerHTML = el.innerHTML;
			}
		}
		return;
	}
	for (var n = 0; ; n++){
		var el = this.document.getElementById('ts' + n);
		if (el == null)
			break;
		var r = el.ownerDocument.createRange();
		r.setStartBefore(el);
		var df = r.createContextualFragment(el.innerHTML);
		el.parentNode.replaceChild(df, el);
	}
}

function nextSearch()
{
	var e = window.event;
	if (e == null){
		if (window.active_frame != null){
			frm = window.active_frame;
		}else{
			var frm = window.frames['f' + window.activePart.partNum];
		}
		e = frm.event;
		if (e == null && frm.isDjVuDoc && frm.isDjVuDoc())
		{
			e = frm.frames['djvu_doc'].event;
		}
	}
	if (e == null)
		return;
	if (e.keyCode != 114) // F3
		return;
	startSearch();
}

window.nextSearch = nextSearch;

function highlightWord(node, word)
{
    for (var child = node.firstChild; child != null; child = child.nextSibling){
		highlightWord(child, word);
    }
	if (node.nodeType != 3)
		return;
	var tempNodeVal = node.nodeValue.toLowerCase();
    var tempWordVal = word.toLowerCase();
	var pos = tempNodeVal.indexOf(tempWordVal);
	if (pos == -1)
		return;
	var doc = node.ownerDocument;
	var nv  = node.nodeValue;
	var pn  = node.parentNode;
    for (;;){
		var pos = tempNodeVal.indexOf(tempWordVal);
		if (pos == -1)
			break;
		var before = doc.createTextNode(nv.substr(0, pos));
		var hiwordtext = doc.createTextNode(nv.substr(pos, word.length));
		nv = nv.substr(pos + word.length);
		tempNodeVal = tempNodeVal.substr(pos + word.length);
		var hiword = doc.createElement('span');
		hiword.className = 'context';
		hiword.id = 'ts' + window.search_spans;
		window.search_spans++;
		hiword.appendChild(hiwordtext);
		pn.insertBefore(before,node);
		pn.insertBefore(hiword,node);
    }
	var after  = doc.createTextNode(nv);
 	pn.insertBefore(after,node);
    pn.removeChild(node);
}

function searchDone(res)
{
	var set_ts = true;
	var search_res = new Array();
	try{
		eval(res);
	}catch (err){
	}
	searchResult(search_res, set_ts);
}	

function searchResult(search_res, set_ts, searchType)
{
	if (window.active_frame == null){
		var frm = window.frames['f' + window.activePart.partNum];
	}else{
		var frm = window.active_frame;
	}
	if (window.search_frame != null)
		frm = window.search_frame;
		
	frm.search_res = search_res;
	stopSearch();
	var search_frm = frames['search_frm'];
	if (searchType == null)
	{
		searchType = search_frm.document.getElementById('search_type').value;
	}
	
	if (window.search_frames == null)
		window.search_frames = new Array();
	window.search_frames[window.search_frames.length] = frm;
	
	if (search_res.length == 0)
		return;
		
	var djvuMode = (frm.isDjVuDoc && frm.isDjVuDoc());

	// 25.04.07 amoro:
	// в случае поиска иного типа, нежели контекстный, в этом месте
	// еще не известно, нашли чего или нет;
	// поэтому не надо "включать" кнопки
	// 11.05.07 amoro:
	// однако, в случае точного поиска и разбивки документа по частям, мы тоже
	// уже точно знаем, что результаты есть
	// 14.05.07 amoro:
	// в DjVu-документах тоже по-своему кнопки включаются/выключаются (см. ниже)
	var n_parts = frm.document.getElementById('n_parts');
	if ((searchType == 1 || ((searchType == 3 || searchType == 4) && n_parts != null)) && !djvuMode)
	{
		setDisabled(search_frm.document.getElementById('search_next'), false);
		setDisabled(search_frm.document.getElementById('search_prev'), false);
	}
	var n = 0;
	frm.clearSearchResult = clearSearchResult;
	frm.document.onkeydown = nextSearch;
	document.onkeydown = nextSearch;
	// 06.10.06 amoro:
	// поиск в DjVu-документах
	if (djvuMode)
	{
		frm.clearSearchResult = frm.djvuClearSearchRes;
		frm.frames['djvu_doc'].document.onkeydown = nextSearch;
		frm.djvuApplySearch(search_res[0], searchType);
		setDisabled(search_frm.document.getElementById('search_prev'), !next_search(true, true));
		setDisabled(search_frm.document.getElementById('search_next'), !next_search(false, true));
		return;
	}
	
	var body = frm.document.body;
	if (n_parts == null){
		// Текст одним куском - просто его разметим
		if (set_ts){
			var arr = search_res[0];
			if (body.createTextRange == null){
				window.search_spans = 0;
				for (var nword in arr){
					var word = arr[nword];
					highlightWord(body, word);
				}
				// 25.04.07 amoro:
				// если ничего не нашли, то отражаем этот факт в панели поиска и выходим
				if (window.search_spans == 0)
				{
					searchFailed(frm, search_frm);
					return;
				}
				// 25.04.07 amoro:
				// теперь, когда что-то нашли, можно "включать" кнопки вперед-назад для
				// иных, кроме контекстного видов поиска
				if (searchType != 1)
				{
					setDisabled(search_frm.document.getElementById('search_next'), false);
					setDisabled(search_frm.document.getElementById('search_prev'), false);
				}
				var sel = null;
				for (var n = 0; ; n++){
					var span = frm.document.getElementById('ts' + n);
					if (span == null)
						break;
					sel = span;
					var y = 0;
					while (span != null){
						y += span.offsetTop;
						span = span.parentOffset;
					}
					if (y > frm.document.body.scrollTop)
						break;
				}
				if (sel != null)
					selectTs(sel, frm);
			}else{
				var range = body.createTextRange();
				var flag = 2;
				if (window.find_type == 3)
					flag = 0;
				if (window.find_type == 4)
					flag = 4;
				for (var nword in arr){
					var word = arr[nword];
					range.moveToElementText(frm.document.body);
					while (range.findText(word, 10000000, flag)){
						var el = range.parentElement();
						while (el != null){
							if (el.tagName == 'BODY'){
								el = null;
								break;
							}
							if ((el.tagName == 'SPAN') && (el.className == 'context'))
								break;
							el = el.parentNode;
						}
						if (el != null){
							range.collapse(false);
						}
						var err = null;
						try{
							SetRangeClass(range, 'context', null, "ts" + n);
							n++;									
						}catch (err){
							alert(err.message);
						}
						range.collapse(false);	
					}
				}
				// 25.04.07 amoro:
				// если ничего не нашли, то отражаем этот факт в панели поиска и выходим
				if (n == 0){	
					searchFailed(frm, search_frm);
					return;
				}
				// 25.04.07 amoro:
				// теперь, когда что-то нашли, можно "включать" кнопки вперед-назад для
				// иных, кроме контекстного видов поиска
				if (searchType != 1)
				{
					setDisabled(search_frm.document.getElementById('search_next'), false);
					setDisabled(search_frm.document.getElementById('search_prev'), false);
				}
				window.search_spans = n;
				var el = frm.document.elementFromPoint(50, 0);
				if (el != null){
					if (findTsForward(el, null, frm))
						return;
					if (findTsForwardFrom(el, frm.document.body, frm))
						return;
				}
				findTsForward(frm.document.body, null, frm);
			}
		}else{
			var mark = frm.document.getElementById('CM');
			if (mark != null)
				findTsForwardFrom(mark, frm.document.body, frm);
		}
		return;
	}
	// здесь ищем результат в документе загруженном по частям
	// находим текущую часть
	window.search_spans = 0;
	n_parts = parseInt(n_parts.value);
	if (!set_ts){
		var n_part = 0;
		var mark = frm.document.getElementById('mark');
		var marker = null;
		if (mark != null){
			for (var div = mark.nextSibling; div != null; div = div.nextSibling){
				if (div.tagName != 'DIV')
					continue;
				if (div.id.substring(0, 1) != 'P')
					continue;
				n_part = parseInt(div.id.substring(1));
				mark = document.getElementById('mark');
				if (mark != null)
					marker = mark.value;
				break;
			}
		}
		// 11.05.07 amoro:
		// n_parts так формируется, что это не число частей, а номер последней части
		for (; n_part <= n_parts; n_part++){
			if (search_res[n_part] == null)
				continue;
			var part = frm.document.getElementById('P' + n_part);
			if (part == null)
				return;
			tsDiv(part, frm, marker);
			return;
		}
		return;
	}
	// 11.05.07 amoro:
	// n_parts так формируется, что это не число частей, а номер последней части
	for (var n_part = 0; n_part <= n_parts; n_part++){
		var el = frm.document.getElementById('P' + n_part);
		if (el == null)
			continue;
		if (el.className != 'load')
			continue;
		selectContextInPart(el, frm);
	}
	var n_part = 0;
	var el = frm.document.elementFromPoint(50, 0);
	while (el != null){
		if ((el.tagName == 'DIV') && (el.id.match(/P[0-9]+/) != null)){
			n_part = parseInt(el.id.substring(1));
			break;
		}
		el = el.parentNode;
	}
	var go_part = null;
	frm.goUp = false;
	// 11.05.07 amoro:
	// n_parts так формируется, что это не число частей, а номер последней части
	for (var n = n_part; n <= n_parts; n++){
		if (search_res[n] != null){
			go_part = n;
			break;
		}
	}
	if (go_part == null){
		frm.goUp = true;
		for (n = 0; n < n_part; n++){
			if (search_res[n] != null){
				go_part = n;
				break;
			}
		}
	}
	if (go_part == null)
		return;
	var load_div = frm.document.getElementById('P' + go_part);
	tsDiv(load_div, frm);
}

window.searchDone = searchDone;

function searchFailed(frm, search_frm)
{
	frm.search_res = new Array();
	var ed = search_frm.document.getElementById('search_str');
	ed.className = 'notfound';
	setFocusTo(ed);
}

function tsDiv(load_div, frm, marker)
{
	if (load_div == null)
		return;
	if (load_div.className == 'load'){
		// Часть уже загружена - выделяем в ней
		if (window.goUp){
			findTsBackward(load_div, null, frm);
		}else{
			findTsForward(load_div, null, frm);
		}
		return;
	}
	// надо загрузить вот эту часть - найти в ней и выделить
	var frm = load_div.document.parentWindow;
	if (frm.document.getElementById('part_url') == null)
		return;
	var xmlHttp = frm.getXmlHttp();
	if (xmlHttp == null)
		return;
	// 16.06.06 amoro:
	// надо позиционироваться на выделенный элемент в результатах
	// контекстного поиска
	if (marker != null){
		xmlHttp.loadPart(load_div, frm.document, frm, "I0", null, marker);
		return;
	}
	xmlHttp.loadPart(load_div, frm.document, frm, "CM", divLoaded);
}

function selectContextInPart(el, frm)
{
	if (frm.search_res == null)
		return;
	var n_part = parseInt(el.id.substring(1));
	var res = frm.search_res[n_part];
	if (res == null)
		return;
	var nn = window.search_spans;
	var range = el.document.body.createTextRange();
		var flag = 2;
	if (window.find_type == 3)
		flag = 0;
	if (window.find_type == 4)
		flag = 4;
	for (var n in res){
		var word = res[n];
		range.moveToElementText(el);
		while (range.findText(word, 10000000, flag)){
			var p = range.parentElement();
			while (p != null){
				if ((p.tagName == 'DIV') && (p.id == el.id))
					break;
				p = p.parentNode;
			}
			if (p == null)
				break;
			try{
				range.pasteHTML('<span id="ts' + nn + '" class="context">' + range.htmlText + '</span>');
				nn++;
			}catch (err){
			}
			range.collapse(false);
		}		
	}
	window.search_spans = nn;
}

window.selectContextInPart = selectContextInPart;

function divLoaded(el, doc, wnd)
{
	if (window.goUp){
		findTsBackward(el, null, wnd);
	}else{
		findTsForward(el, null, wnd);
	}
}

function selectTs(el, wnd)
{
	var doc;
	if (wnd.selected_ts != null){
		wnd.selected_ts.style.backgroundColor = '';
		wnd.selected_ts = null;
	}
	if (el.document != null){
		doc = el.document;
		setFocusTo(wnd);
		var range = doc.body.createTextRange();
		range.moveToElementText(el);
		range.scrollIntoView();
	}else{
		doc = el.ownerDocument;
		var sel = wnd.getSelection();

		var range = doc.createRange();
		range.selectNode(el);
		sel.removeAllRanges();
		sel.addRange(range);
		
		var y = 0;
		var e = el;
		while (e != null){
			y += e.offsetTop;
			e = e.offsetParent;
		}
		var screen_y = doc.body.scrollTop;
		if (y < screen_y){
			doc.body.scrollTop = screen_y;
		}else{
			screen_y += doc.body.clientHeight;
			y += el.offsetHeight;
			if (y > screen_y)
				doc.body.scrollTop = y - doc.body.clientHeight;
		}
	}
	el.style.backgroundColor = 'chartreuse';
	wnd.selected_ts = el;
	var search_frm = frames['search_frm'];
	setDisabled(search_frm.document.getElementById('search_next'), !next_search(false, true));
	setDisabled(search_frm.document.getElementById('search_prev'), !next_search(true, true));
}

function findTsBackwardFrom(from, root, wnd, noselect, my_id)
{
	if (my_id == null)
		my_id = from.id;
	for (var child = from.previousSibling; child != null; child = child.previousSibling){
		if (findTsBackward(child, noselect, wnd, my_id))
			return true;
	}
	if (from == root)
		return false;
	var p = from.parentNode;
	if (p == null)
		return false;
	return findTsBackwardFrom(p, root, wnd, noselect, from, my_id);
}

function findTsForwardFrom(from, root, wnd, noselect, my_id)
{
	if (my_id == null)
		my_id = from.id;
	for (var child = from.nextSibling; child != null; child = child.nextSibling){
		if (findTsForward(child, noselect, wnd, my_id))
			return true;
	}
	if (from == root)
		return false;
	var p = from.parentNode;
	if (p == null)
		return false;
	return findTsForwardFrom(p, root, wnd, noselect, my_id);
}

function tsY(el, delta)
{
	var doc = el.document;
	if (doc == null)
		doc = el.ownerDocument;
	var y = delta - doc.body.scrollTop;
	while (el != null){
		y += el.offsetTop;
		el = el.offsetParent;
	}
	return y;
}

function expandParent(el)
{
	while (el != null){
		if (!el.style)
			break;
		if (el.style.display == 'none'){
			var btn = el.document.getElementById(el.id + '_btn');
			if (btn != null)
				btn.click();
		}
		el = el.parentNode;
	}
}

function findTsBackward(el, check, wnd, my_id)
{
	if ((el.style != null) && (el.style.display == 'none'))
		return false;
	if ((el.tagName == 'SPAN') && (el.id.substring(0, 2) == 'ts') && (el.id != my_id)){
		expandParent(el);
		if (check == null)
			selectTs(el, wnd);
		return true;
	}
	for (var child = el.lastChild; child != null; child = child.previousSibling){
		if (findTsBackward(child, check, wnd))
			return true;
	}
	return false;
}

function findTsForward(el, check, wnd, my_id)
{
	if ((el.style != null) && (el.style.display == 'none'))
		return false;
	if ((el.tagName == 'SPAN') && (el.id.substring(0, 2) == 'ts') && (el.id != my_id)){
		expandParent(el);
		if (tsY(el, el.offsetHeight) >= 0){
			if (check == null)
				selectTs(el, wnd);
			return true;
		}
	}
	for (var child = el.firstChild; child != null; child = child.nextSibling){
		if (findTsForward(child, check, wnd))
			return true;
	}
	return false;
}

function setButtonText(el, text)
{
	var n = text.indexOf('&');
	if (n < 0){
		el.innerHTML = text;
		el.accessKey = null;
		return;
	}
	el.accessKey = text.substring(n, 1);
	text = text.substring(0, n) + text.substring(n + 1);
	el.innerHTML = text;
}

function stopSearch()
{
	window.search_frame = null;
	window.search_done  = null;
	var search_frm = frames['search_frm'];
	var ed = search_frm.document.getElementById('search_str');
	ed.className = '';
	setButtonText(search_frm.document.getElementById('ok'), window.str_find);
}

function clearSearchFrames()
{
	if (window.search_frames == null)
		return;
	for (var i = 0; i < window.search_frames.length; i++){
		var frm = window.search_frames[i];
		if (frm.clearSearchResult != null)
			frm.clearSearchResult();
		frm.search_res = null;
	}
	window.search_frames = null;
	document.onkeydown = null;
	window.find_str = null;
}

function closeSearch()
{
	var frm = GetWorkFrame();
	if (frm != null)
		frm.focus();
	setDisabled(document.getElementById('search_next'), true);
	setDisabled(document.getElementById('search_prev'), true);
	clearSearchFrames();
	document.getElementById('search_div').style.display = 'none';
	stopSearch();
	var search_frm = frames['search_frm'];
	var ed = search_frm.document.getElementById('search_str');
	ed.value = '';
	return false;
}

window.closeSearch = closeSearch;

function checkSearch()
{
	if (document.getElementById('search_div').style.display == 'none')
		return;		
	var search_frm = frames['search_frm'];
	var ed = search_frm.document.getElementById('search_str');
	var st = search_frm.document.getElementById('search_type');
	if ((ed != null) && (st != null) && (window.find_str != null) && ((window.find_str != ed.value) || (window.find_type != st.value))){
		ed.className = '';
		setDisabled(search_frm.document.getElementById('search_next'), true);
		setDisabled(search_frm.document.getElementById('search_prev'), true);
		clearSearchFrames();
	}
	if (window.find_str != null){
		if (window.active_frame == null){
			var frm = window.frames['f' + window.activePart.partNum];
		}else{
			var frm = window.active_frame;
		}
		if (window.search_current != frm){
			if ((frm != null) && 
				(frm.document != null) && 
				(frm.document.body != null)){
				var ed = search_frm.document.getElementById('search_str');
				if (frm.search_res == null){
					if (window.search_frame == null)
						startSearch(true);
				}else{
					window.search_current = frm;
					if (frm.window.search_res.length == 0){
						if (window.search_frame == null){
							if (ed.className != 'notfound')
							{
								ed.className = 'notfound';
								setFocusTo(ed);
							}
						}else{
							window.search_current = null;
						}
					}else{
						if (ed.className == 'notfound')
							ed.className = '';
					}
					setDisabled(search_frm.document.getElementById('search_next'), !next_search(false, true));
					setDisabled(search_frm.document.getElementById('search_prev'), !next_search(true, true));
				}
			}else{
				setDisabled(search_frm.document.getElementById('search_next'), true);
				setDisabled(search_frm.document.getElementById('search_prev'), true);
			}
		}
	}else{
		window.search_current = null;
	}
	var ok = search_frm.document.getElementById('ok');
	if (ok != null)
		ok.disabled = (ed.value == '');
	window.setTimeout('checkSearch()', 500);
}

window.checkSearch = checkSearch;

// _______________________________________________________________________________

// перегрузить активную вкладку
function reloadActiveTab(attrs)
{
	var apart = window.activePart.partNum;
	var frm = window.frames['f' + apart];
	if (frm == null)
		return;
	if (typeof(frameStates) != "undefined")
	{
		var state = frameStates.get('f' + apart);
		if (state != null)
			state.clear();
	}
	var anchor = document.getElementById('t' + apart);
	var frm_src = anchor.href + attrs;
	if (frm.location != frm_src)
		frm.location.replace(frm_src);
}

// сбросить содержимое неактивных вкладок
function clearInactiveTabs()
{
	if (window.displayedTabsManager == null)
		return;
	var apart = window.activePart.partNum;
	var i, count = window.displayedTabsManager.enabledTabsCollection.count;
	for (i = 0; i < count; i++)
	{
		if (i == apart)
			continue;
		var frm = document.getElementById('f' + i);
		if (frm != null)
			frm.src = 'about:blank';
		if (typeof(frameStates) != "undefined")
		{
			var state = frameStates.get('f' + i);
			if (state != null)
				state.clear();
		}
	}
}


// Коллекция задействованных вкладок.
// Позволяет найти очередную задействованную вкладку
function EnabledTabsCollection()
{
	this.enabledTabs = new Array();
	var i;
	var tc = document.getElementById("tabs_cnt");
	var count = parseInt(tc.value);
	for (i = 0; i < count; i++)
		this.enabledTabs[this.enabledTabs.length] = i;
	this.enabledList = this.enabledTabs.join(';');
	this.count = count;
	
	this.setEnabledList = TC_setEnabledList;
	this.find = TC_find;
	this.next = TC_next;
	this.prev = TC_prev;
	this.isEnabled = TC_isEnabled;
}

function TC_setEnabledList(list)
{
	if (list == this.enabledList)
		return false;
	
	var arr = list.split(';');
	var narr = new Array();
	var i, len = arr.length;
	for (i = 0; i < len; i++)
		narr[i] = parseInt(arr[i]);
	this.enabledTabs = narr;
	this.enabledList = narr.join(';');
	return true;
}

function TC_find(num, strict)
{
	// ищет элемент в массиве включенных вкладок
	// и возвращает либо его индекс, либо индекс
	// ближайшего меньшего, либо null;
	// если выставлен флаг strict, то ищет 
	// строгое соответствие
	if (strict == null)
		strict = false;
	var l = 0, r = this.enabledTabs.length-1;
	var p;
	while (l != r)
	{
		var c = parseInt((l+r)/2);
		p = this.enabledTabs[c];
		if (p == num)
			return c;
			
		if (p < num)
		{
			if (l < c)
				l = c;
			else
				l++;
		}
		else
			r = c;
	}
	p = this.enabledTabs[r];
	if (p == num)
		return r;
	if (strict)
		return null;
	if (p < num)
		return r;
	if (p > num)
	{
		if (r == 0)
			return null;
		return r-1;
	}
}

function TC_next(num)
{
	var j;
	var i = this.find(num);
	if (i == null)
		j = 0;
	j = i+1;
	return this.enabledTabs[j];
}

function TC_prev(num)
{
	var i = this.find(num);
	if (i == null)
		return null;
	var j = i;
	if (this.enabledTabs[i] == num)
	{
		if (i == 0)
			return null;
		j = i-1;
	}
	return this.enabledTabs[j];
}

function TC_isEnabled(num)
{
	if (this.find(num, true) == null)
		return false;
	return true;
}


// Распределитель вкладок между отображаемыми и доступными через меню
function DisplayedTabsManager()
{
	var dtc = document.getElementById("displayed_tabs_cnt");
	this.firstHidedTab = parseInt(dtc.value);

	this.getDisplayedTabsCount = DTM_getDisplayedTabsCount;	
	this.getLastDisplayedTab = DTM_getLastDisplayedTab;
	this.pushTabToMenu = DTM_pushTabToMenu;
	this.popTabFromMenu = DTM_popTabFromMenu;
	this.reinit = DTM_reinit;
	this.balance = DTM_balance;
	
	this.enabledTabsCollection = new EnabledTabsCollection();
}

function DTM_getDisplayedTabsCount()
{
	return this.firstHidedTab;
}

function DTM_getLastDisplayedTab()
{
	return this.enabledTabsCollection.prev(this.firstHidedTab);
}

function DTM_pushTabToMenu()
{
	if (this.firstHidedTab == 0)
		return false;
	var num = this.enabledTabsCollection.prev(this.firstHidedTab);
	if (num == null)
		return false;
	
	var tab = document.getElementById('tabBlock' + num);
	if (tab != null)
	{
		this.firstHidedTab = num;
		var id = 'm' + num;
		var apart = window.activePart.partNum;
		showMenuItem('tabMenu', id, (apart == num));
		var mtab = document.getElementById('menuTab');
		mtab.style.display = '';
		tab.style.display = 'none';
		setTabState(num, false);
		if (apart >= num)
			setTabState('', true);
		return true;
	}
	
	return false;
}

function DTM_popTabFromMenu()
{
	var num = this.firstHidedTab;
	var count = this.enabledTabsCollection.count;
	if (num == count)
		return false;

	var tab = document.getElementById('tabBlock' + num);
	if (tab != null)
	{
		var next = this.enabledTabsCollection.next(this.firstHidedTab);
		if (next == null)
		{
			this.firstHidedTab = count;
			var mtab = document.getElementById('menuTab');
			mtab.style.display = 'none';
		}
		else
			this.firstHidedTab = next;
		
		var id = 'm' + num;
		hideMenuItem('tabMenu', id);
		tab.style.display = '';
		var selId = getCheckedMenuItemId('tabMenu');
		if (id == selId)
		{
			setTabState(num, true);
			setTabState('', false);
			selectPopupMenuItem("tabMenu");
		}
		else
			setTabState(num, false);
		return true;
	}
	return false;
}

function DTM_reinit()
{
	var i, count = this.enabledTabsCollection.count;
	
	// 26.06.06 amoro:
	// теперь 0-ю тоже можно скрывать
	// скрыть все
	for (i = 0; i < count; i++)
	{
		var tab = document.getElementById('tabBlock' + i);
		if (tab != null)
		{
			tab.style.display = 'none';
			setTabState(i, false);
		}
		var id = 'm' + i;
		hideMenuItem('tabMenu', id);
	}
	setTabState('', false);
	selectPopupMenuItem("tabMenu");
	var mtab = document.getElementById('menuTab');
	mtab.style.display = 'none';
	
	// показать задействованные
	this.firstHidedTab = count;
	var apart = window.activePart.partNum;
	for (i = this.enabledTabsCollection.enabledTabs[0]; i != null; i = this.enabledTabsCollection.next(i))
	{
		var tab = document.getElementById('tabBlock' + i);
		if (tab != null)
		{
			tab.style.display = '';
			if (apart == i)
				setTabState(i, true);
		}
	}
	
	// переместить лишние в меню
	while(isTabOver())
		if (!this.pushTabToMenu())
			break;
}

function DTM_balance()
{
	while (!isTabOver())
		if (!this.popTabFromMenu())
			break;
	while(isTabOver())
		if (!this.pushTabToMenu())
			break;
}


// установка списка задействованных вкладок
//
// внимание: чтобы смена списка задействованных вкладок работала
// правильно, надо, чтобы список на входе (передаваемый в
// виде строки) был отсортирован в числовом порядке
function setEnabledTabsList(list)
{
	if (window.displayedTabsManager == null)
		return;
	if (displayedTabsManager.enabledTabsCollection.setEnabledList(list))
	{
		window.displayedTabsManager.reinit();
		
		// проверка, а вдруг активная вкладка оказалась не у дел
		var apart = window.activePart.partNum;
		if (!window.displayedTabsManager.enabledTabsCollection.isEnabled(apart))
		{
			// 26.06.06 amoro:
			// 0-я может быть скрыта, поэтому надо щелкать по первой включенной
			var num = window.displayedTabsManager.enabledTabsCollection.enabledTabs[0];
			var el = document.getElementById('t' + num);
			if (el != null)
				tabClick(el);
		}
	}
}
window.setEnabledTabsList = setEnabledTabsList;


function replaceSpackInUrl(old_url, new_spack)
{
	var url = old_url;
	var ind = url.indexOf('&spack');
	if (ind != -1)
	{
		ind += 7;
		var eu = url.substring(ind);
		url = url.substring(0, ind) + new_spack;
		ind = eu.indexOf('&');
		if (ind != -1)
		{
			url += eu.substring(ind);
		}
		else
		{
			ind = eu.indexOf('#');
			if (ind != -1)
				url += eu.substring(ind);
		}
	}
	else
	{
		ind = url.indexOf('#');
		if (ind != -1)
		{
			url = url.substring(0, ind) + '&spack=' + new_spack + url.substring(ind);
		}
		else
		{
			url += '&spack=' + new_spack;
		}
	}
	return url;
}


// установить новые упакованные параметры для вкладки
function setNewSpackForTab(ntab, new_spack)
{
	var tab = document.getElementById('t' + ntab);
	if (tab != null)
	{
		tab.href = replaceSpackInUrl(tab.href, new_spack);
	}
	tab = document.getElementById('m' + ntab);
	if (tab != null)
	{
		tab.href = replaceSpackInUrl(tab.href, new_spack);
	}
	if (window.print_parts != null && window.print_parts[ntab] != null && window.print_parts[ntab].URL != null)
		window.print_parts[ntab].URL = replaceSpackInUrl(window.print_parts[ntab].URL, new_spack);
}
window.setNewSpackForTab = setNewSpackForTab;

// установить новые упакованные параметры для вкладок
function setNewSpack(new_spack)
{
	var tcnt = parseInt(document.getElementById('tabs_cnt').value);
	var i;
	for (i = 0; i < tcnt; i++)
	{
		setNewSpackForTab(i, new_spack);
	}
}
window.setNewSpack = setNewSpack;


// вывод справки

function showHelp(topic)
{
	var tid = '';
	if (typeof(topic) != 'undefined' && topic != null){
		tid = topic;
	}else{
		if (window.active_frame != null){
			var frm = window.active_frame;
		}else{
			var frm = GetWorkFrame();
		}
		if ((frm != null) && (frm.help_topic != null))
			tid = frm.help_topic;
	}
	window.open(window.pPath + 'help' + (tid != '' ? '&topic=' + tid : ''), '_blank');
}


function showProgressMsg(parent)
{
	var wnd = window.parent;
	while (wnd != wnd.parent)
		wnd = wnd.parent;
	var doc = wnd.parent.document;
	if (parent == null)
		parent = doc.body;
	var pwMsg = doc.getElementById('progressMsgWnd');
	if (pwMsg != null)
	{
		//parent.disabled = true;
		pwMsg.style.display = '';
		var pwBody = frames['progressMsgWnd'].document.body;
		pwMsg.style.width  = pwBody.scrollWidth + 'px';
		pwMsg.style.height = pwBody.scrollHeight + 'px';
		var x = parseInt((parent.offsetWidth  - pwBody.scrollWidth) / 2);
		var y = parseInt((parent.offsetHeight - pwBody.scrollHeight) / 2);
		if (x < 0)
			x = 0;
		if (y < 0)
			y = 0;
		do
		{
			x += parent.offsetLeft;
			y += parent.offsetTop;
			parent = parent.offsetParent;
		} while (parent != null);
		pwMsg.style.left = x + 'px';
		pwMsg.style.top = y + 'px';
	}
}

function hideProgressMsg(parent)
{
	var wnd = window.parent;
	while (wnd != wnd.parent)
		wnd = wnd.parent;
	var doc = wnd.parent.document;
	if (parent == null)
		parent = doc.body;
	var pwMsg = doc.getElementById('progressMsgWnd');
	if (pwMsg != null)
		pwMsg.style.display = 'none';
	//parent.disabled = false;
}

// отключение части окна, показывающей содержимое документа и панель инструментов
// для проведения длительного процесса (поиска)
function disableDataPanelForSearch(wnd, topBarPanelId)
{
	//получение панели снизу от панели навигации
	var doc = wnd.document;
	var panel = doc.getElementById(topBarPanelId);
	if (panel != null)
	{
		var table = panel.parentNode;
		panel = table.rows[panel.rowIndex+1];
		if (panel != null)
		{
			// после панели навигации следует панель инструментов,
			// ее надо просто отключить и получить следующую -
			// панель собственно содержимого
			//panel.disabled = true;
			panel = table.rows[panel.rowIndex+1];
		}
	}
	//показ сообщения о процессе поиска
	showProgressMsg(panel);
}

function disableSelect() 
{ 
	var e = window.event.srcElement;
	while (e != null){
		if ((e.tagName == "INPUT") || (e.tagName == "IFRAME"))
			return true;
		e = e.parentNode;
	}
	return false;
}

function setFlat(el, state)
{
	if (state){
		el.className = 'flat';
		el.hideFocus = true;
	}else{
		el.className = '';
	}
}

function setDisabled(el, state)
{
	if (el == null)
		return;
	if (el.disabled == state)
		return;
	if (state)
		setFlat(el, true);
	el.disabled = state;
	setImageDisabled(el, state);
}

function setImageDisabled(el, state)
{
	if (el.tagName == 'IMG'){
		if (state){
			el.src = el.src.substring(0, el.src.length - 4) + '_d.gif';
		}else{
			el.src = el.src.substring(0, el.src.length - 6) + '.gif';
		}
		return;
	}
	for (var child = el.firstChild; child != null; child = child.nextSibling)
		setImageDisabled(child, state);
}


// 22.02.06 amoro:
// Блокирование/разблокирование пользовательского интерфейса для длительных операций
function lockUI()
{
	// 14.03.06 amoro:
	// Проверка, существует ли объект body - пока страница не загрузилась
	// его нет
	var body = document.body;
	if (typeof(body) == "undefined")
		return;
		
	// пока просто меняется вид курсора
	body.style.cursor = "wait";
}

function unlockUI()
{
	// 14.03.06 amoro:
	// Проверка, существует ли объект body - пока страница не загрузилась
	// его нет
	var body = document.body;
	if (typeof(body) == "undefined")
		return;
		
	// пока просто меняется вид курсора
	body.style.cursor = "auto";
}

function setLongProcess(parent)
{
	lockUI();
	showProgressMsg(parent);
}

function endLongProcess(parent)
{
	unlockUI();
	hideProgressMsg(parent);
}

function checkISearchAnnotation(search_str, nh)
{
	if (document.getElementById("ca_search_popup") == null)
		return false;
	var words = search_str.split(new RegExp("[,.' \t\"]+", "g"));
	var context = words.join(';');
	var url = window.pPath + "context_annot&id=ca_search_popup&doc_search=1&nd=" + window.nd +
		"&stats=" + escape(context);
	if (nh != null)
		url += "&nh=" + nh;
	var ca_wnd = frames['ca_search_popup'];
	var oldUrl = ca_wnd.location.href;
	var i = oldUrl.indexOf(window.pPath);
	var len = window.pPath.length;
	var len2 = url.length;
	var u2 = oldUrl.substring(i+len, i+len2);
	return !(i < 0 || oldUrl.substring(i+len, i+len2) != url.substring(len));
}

function loadISearchAnnotation(search_str, nh)
{
	window.isearchAnnotationShowed = null;
	var words = search_str.split(new RegExp("[,.' \t\"]+", "g"));
	var context = words.join(';');
	var ca_frm = document.getElementById("ca_search_popup");
	if (ca_frm == null)
		return;
	var loadUrl = window.pPath + "d&nd=" + window.nd;
	var url = window.pPath + "context_annot&id=ca_search_popup&doc_search=1&nd=" + window.nd + 
		"&stats=" + escape(context);
	if (nh != null)
		url += "&nh=" + nh;
	url += "&lurl=" + escape(loadUrl);
	var pop = window.top.popup;
	var ca_wnd = frames['ca_search_popup'];
	// просто сравнить URL-и не получится, т.к. window.pPath
	// не обязательно включает в себя префикс протокола;
	// возьмем те части, что являются индивидуальными для данной задачи
	var oldUrl = ca_wnd.location.href;
	var i = oldUrl.indexOf(window.pPath);
	var len = window.pPath.length;
	if (i < 0 || oldUrl.substring(i+len) != url.substring(len))
	{
		if (pop != null)
			hidePopup();
		var sfrm = document.getElementById("search_frm");
		var x = 0;
		var y = 0;
		var el = sfrm;
		do
		{
			x += el.offsetLeft;
			y += el.offsetTop;
			el = el.offsetParent;
		} while (el != null);
		var ok_btn = frames['search_frm'].document.getElementById("ok");
		el = ok_btn;
		do
		{
			x += el.offsetLeft;
			el = el.offsetParent;
		} while (el != null);
		if (x > 30)
			x -= 30;
		ca_frm.x = x;
		ca_frm.y = y-1;
		setLongProcess(document.body);
		ca_wnd.location.replace(url);
	}
	else
	{
		showISearchAnnotation(true);
	}
}

function isearchNotFound()
{
	hidePopup();
	var search_frm = window.frames['search_frm'];
	var ed = search_frm.document.getElementById('search_str');
	ed.className = 'notfound';
	setFocusTo(ed);
}

function showISearchAnnotation(secondTime)
{
	if (secondTime == null)
		secondTime = false;
	var ca_frm = document.getElementById("ca_search_popup");
	if (ca_frm == null)
		return;
	var ca_wnd = frames['ca_search_popup'];
	if (!secondTime)
	{
		window.isearchAnnotationShowed = true;
		hilightWordsInParagraphs(ca_wnd.document);
		endLongProcess(document.body);
	} else if (window.searchResultCleared)
		hilightWordsInParagraphs(ca_wnd.document);
	var mainElm = ca_wnd.document.body.firstChild;
	while (mainElm != null && mainElm.tagName != "DIV")
	{
		mainElm = mainElm.nextSibling;
	}
	if (mainElm == null || mainElm.innerHTML == "")
	{
		isearchNotFound();
		return;
	}
	var anno_cnt_el = ca_wnd.document.getElementById("annoCnt");
	if (anno_cnt_el != null)
	{
		var anno_cnt = parseInt(anno_cnt_el.value);
		if (anno_cnt == 0)
		{
			isearchNotFound();
			return;
		}
		if (anno_cnt == 1)
		{
			var p_id;
			var pars = ca_wnd.document.getElementsByTagName('P');
			for (i = 0; i < pars.length; i++)
			{
				var p = pars[i];
				if (p.id.substring(0, 1) != 'P')
					continue;
				p_id = p.id;
				break;
			}
			scrollToParagraph(p_id);
			hidePopup();
			return;
		}
	}
	ca_frm.style.display = '';
	var w = mainElm.offsetWidth+20;
	var h = mainElm.offsetHeight+20;
	var elm = mainElm;
	do
	{
		w += elm.offsetLeft;
		h += elm.offsetTop;
		elm = elm.offsetParent;
	} while (elm != null);
	var x = ca_frm.x;
	var y = ca_frm.y;
	var body = document.body;
	if ((x+w) > (body.clientWidth-20))
	{
		if (w > body.clientWidth-60)
			w = body.clientWidth-60;
		x = body.clientWidth-20-w;
	}
	var frm = document.getElementById('f' + window.activePart.partNum);
	var min_y = 0;
	elm = frm;
	do
	{
		min_y += elm.offsetTop;
		elm = elm.offsetParent;
	} while (elm != null);
	if (y < h)
	{
		h = y-20;
	}
	if ((y-h) < min_y)
	{
		h = y - min_y - 1;
	}
	ca_frm.style.left = x;
	ca_frm.style.top = y-h;
	ca_frm.style.width = w;
	ca_frm.style.height = h;
	setHandleOnFrames(window.top, ca_frm);
}

window.showISearchAnnotation = showISearchAnnotation;

function findPartByParagraphId(id, doc, n_parts)
{
	for (var n_part = 0; n_part <= n_parts; n_part++)
	{
		var el = doc.getElementById('P' + n_part);
		if (el == null)
			continue;
		var style = el.className;
		if (style.substring(0, 7) != "punload")
			continue;
		var idRng = style.substring(8);
		var i = idRng.indexOf('_');
		if (i < 0)
		{
			alert('Index of _ in id range is invalid');
			continue;
		}
		var begin = parseInt(idRng.substring(1, i), 16);
		var end = (idRng.length > i+1 ? parseInt(idRng.substring(i+2), 16) : -1);
		if (begin <= id && (id < end || end == -1))
		{
			return el;
		}
	}
	return null;
}

function selectSearchResInParagraph(p, wnd)
{
	var el;
	for (el = p.firstChild; el != null; el = el.nextSibling)
	{
		if ((el.style != null) && (el.style.display == 'none'))
			return false;
		if ((el.tagName == 'SPAN') && (el.id.substring(0, 2) == 'ts'))
		{
			selectTs(el, wnd);
			return;
		}
	}
}

function scrollToParagraph(id)
{
	if (window.active_frame == null){
		var frm = window.frames['f' + window.activePart.partNum];
	}else{
		var frm = window.active_frame;
	}
	if (frm.isDjVuDoc && frm.isDjVuDoc())
	{
		frm.djvuGoChap(id, true);
		return;
	}
	if (id == "P")
	{
		var pars = frm.document.getElementsByTagName("P");
		var i, len = pars.length;
		for (i = 0; i < len; i++)
		{
			selectSearchResInParagraph(pars[i], frm);
		}
		return;
	}
	var n_parts_elm = frm.document.getElementById('n_parts');
	var p = frm.document.getElementById(id);
	if (p != null)
	{
		p.scrollIntoView();
		selectSearchResInParagraph(p, frm);
		return;
	}
	if (n_parts_elm == null)
	{
		alert('No such object');
		return;
	}
	if (id.length < 2)
	{
		alert('Invalid id');
		return;
	}
	var n_parts = parseInt(n_parts_elm.value);
	var cur = parseInt(id.substring(1), 16);
	var el = findPartByParagraphId(cur, frm.document, n_parts);
	if (el == null)
	{
		alert('DEBUG ERROR: подгружаемая секция, содержащая параграф ' + id + ' не существует');
		return;
	}
	el.scrollIntoView();
	//tsDiv(el, frm);
}

window.scrollToParagraph = scrollToParagraph;

function hilightWordsInParagraphs(doc)
{
	if (window.active_frame == null){
		var frm = window.frames['f' + window.activePart.partNum];
	}else{
		var frm = window.active_frame;
	}
	if (frm.isDjVuDoc && frm.isDjVuDoc())
	{
		window.searchResultCleared = false;
		return;
	}
	var tdoc = frm.document;
	var n_parts = tdoc.getElementById('n_parts');
	if (n_parts != null)
		n_parts = parseInt(n_parts.value);
	var pars = doc.getElementsByTagName('P');
	if (pars == null)
		return;
	var i;
	var re = /<SPAN[^>]+>([^ ]+)<\/SPAN>/g;
	var search_res = new Array();
	for (i = 0; i < pars.length; i++)
	{
		var p = pars[i];
		if (p.id.substring(0, 1) != 'P')
			continue;
		var resInd;
		if (n_parts == null)
		{
			resInd = 0;
		}
		else
		{
			var partEl;
			var pEl = tdoc.getElementById(p.id);
			if (pEl != null)
			{
				for(partEl = pEl.parentNode;
					partEl != null && partEl.tagName != "DIV" && partEl.className != "load";
					partEl = partEl.parentNode);
			}
			else
			{
				partEl = findPartByParagraphId(parseInt(p.id.substring(1), 16), tdoc, n_parts);
			}
			if (partEl == null)
			{
				continue;
			}
			resInd = parseInt(partEl.id.substring(1));
		}
		var res;
		if (search_res[resInd] == null)
		{
			res = new Array();
			search_res[resInd] = res;
		}
		else
			res = search_res[resInd];
		var m = p.innerHTML.match(re);
		if (m != null)
		{
			var j, i1, i2, s;
			for (j = 0; m[j] != null; j++)
			{
				s = m[j];
				i1 = s.indexOf('>')+1;
				i2 = s.indexOf('<', i1);
				var w = s.substring(i1, i2).toLowerCase();
				for (var k = 0; k < res.length; k++)
					if (res[k] == w)
						break;
				if (k == res.length)
					res[res.length] = w;
			}
		}
	}
	window.searchResultCleared = false;
	if (search_res.length == 0)
		return;
	searchResult(search_res, true);
}

function setSearchModes(contextOnly)
{
	var sfrm = window.parent.parent.frames['search_frm'];
	if (sfrm != null)
	{
		var sdoc = sfrm.document;
		var selElm = sdoc.getElementById('search_type');
		if (contextOnly)
		{
			selElm.value = "1";
			selElm.style.display = "none";
		}
		else
		{
			selElm.style.display = "";
		}
	}
}

function start_resize(el)
{
	el.onmousemove = function()
	{
		el.td.parentNode.style.width = '';
		var w = el.w + window.event.screenX - this.x;
		if (w < 50)
			w = 50;
		var body_width = document.body.clientWidth;
		if (w > body_width - 50)
			w = body_width - 50;
		el.td.style.width = w + 'px';
		var tth = document.getElementById('tree_tbl_header');
		if (tth == null)
			return;
		el.td.style.width = tth.clientWidth + 'px';
	}
	
	el.onmouseup = function()
	{
		this.releaseCapture();
		this.onmousemove = null;
		if (typeof(SaveTreeState) != 'undefined')
			SaveTreeState(window.tree);
	}

	var tr = el.parentNode;
	if (tr.previousSibling != null)
		tr	= tr.previousSibling;
	el.td = tr.firstChild;
	el.w  = el.td.clientWidth;
	el.td = el.td.firstChild;
	el.x  = window.event.screenX;
	el.setCapture();
}

function toggle_tree()
{
	var tth = document.getElementById('tree_tbl_header');
	var tdh = document.getElementById('tree_div_header');
	var td  = document.getElementById('tree_div');
	var t   = document.getElementById('tree');
	var tba = document.getElementById('tree_btn_alt');
	var ti  = document.getElementById('tree_img');
	var src = ti.src;
	if (tth.style.display == 'none'){
		tth.style.display = '';
		tdh.style.display = '';
		td.style.display  = '';
		t.style.display   = '';
		ti.src = src.substring(0, src.left - 9) + 'left.gif';
	}else{
		tth.style.display = 'none';
		tdh.style.display = 'none';
		td.style.display  = 'none';
		t.style.display   = 'none';
		ti.src = src.substring(0, src.left - 8) + 'right.gif';
	}
	var alt_text = tba.value;
	tba.value    = ti.alt;
	ti.alt       = alt_text;
	if (typeof(SaveTreeState) != 'undefined')
		SaveTreeState(window.tree);
	return false;
}

function tree_init()
{
	var content = document.getElementById('tree_content');
	if (content == null)
		return;
	content.url = document.URL;
	content.url = content.url.replace('?d&', '?tree&tree=' + window.tree + '&');
	content.innerHTML = tree_level_html('', 0);
	if (content.saved_state != null){	
		var arr = content.saved_state.split(':');
		for (var i = 1; i < arr.length; i++){
			tree_expand(arr[i]);
		}
		tree_select(arr[0]);
		restoreStateFromString(content.full_state);
		content.saved_state = null;
		return;
	}
	try{
		var xmlHttp = CreateXmlHttp();
		xmlHttp.open('GET', content.url + '&parents', false, document.location.href);
		xmlHttp.send();
		var res = eval(xmlHttp.responseText);
		for (var i = 0; i < res.length - 1; i++)
			tree_expand(res[i]);
		tree_select(res[res.length - 1], true);
	}catch (err){
	}
}

function tree_level_html(id, level)
{
	var content = document.getElementById('tree_content');
	if (content == null)
		return;
	id += '';
	var pos = id.indexOf('_');
	if (pos > 0)
		id = id.substring(0, pos);
	var html = '';
	var xmlHttp = CreateXmlHttp();
	xmlHttp.open('GET', content.url + '&level=' + id, false, document.location.href);
	xmlHttp.send();
	try{
		var res = eval(xmlHttp.responseText);
		for (var i = 0; i < res.length; i++){
			var item = res[i];
			var el = document.getElementById(item.id);
			if (el != null){
				for (var n = 0;; n++){
					el = document.getElementById(item.id + '_' + n);
					if (el == null){
						item.id += '_' + n;
						break;
					}
				}
			}
			html += '<div id="' + item.id + '" onClick="return item_click(this)" onDblClick="return item_dbl_click(this)"><input type="hidden" id="' + item.id + '-level" value="' + level + '"><table width=100% cellpadding=0 cellspacing=0><tr><td valign="top">';
			var lev = level;
			if (item.hasChilds == null)
				lev++;
			if (lev > 0)
				html += '<img src="' + window.pPath + 'space.gif" width=' + (19 * lev) + ' height=16></td><td valign="top">';			
			if (item.hasChilds != null)
				html += '<img id="' + item.id + '-open" src="' + window.pPath + 'tree_plus.gif" onClick="return plus_click(this)">';
			html += '</td><td valign="top"><img id="' + item.id + '-image" src="' + window.pPath;
			if (item.picture == null){
				html += 'folder.gif';
			}else{
				html += item.picture;
			}
			html += '"></td><td width=100%><span id="' + item.id + '-name" class="tree-item">'
			html += html_escape(item.name) + '</span></td></tr></table></div>';
			if (item.hasChilds != null)
				html += '<div id="' + item.id + '-childs" style="display: none" class="tree-container"></div>';
		}		
	}catch (err){
	}
	return html;
}

function tree_expand(id)
{
	var childs = document.getElementById(id + '-childs');
	if ((childs == null) || (childs.style.display != 'none'))
		return;
	if (childs.innerHTML == '')
		childs.innerHTML = tree_level_html(id, parseInt(document.getElementById(id + '-level').value) + 1);
	childs.style.display = '';
	var el = document.getElementById(id + '-open');
	if (el != null){
		var src = el.src;
		el.src = src.substring(0, src.length - 8) + 'minus.gif';
	}
	var img = document.getElementById(id + '-image');
	if (img != null){
		var src = img.src;
		if (src.substring(src.length - 10) == 'folder.gif')
			img.src = src.substring(0, src.length - 10) + 'folderopen.gif';
	}
}

function tree_collapse(id)
{
	var childs = document.getElementById(id + '-childs');
	if ((childs == null) || (childs.style.display != ''))
		return;
	childs.style.display = 'none';
	var el = document.getElementById(id + '-open');
	if (el != null){
		var src = el.src;
		el.src = src.substring(0, src.length - 9) + 'plus.gif';
	}
	if (window.selected != id){
		var img = document.getElementById(id + '-image');
		if (img != null){
			var src = img.src;
			if (src.substring(src.length - 14) == 'folderopen.gif')
				img.src = src.substring(0, src.length - 14) + 'folder.gif';
		}
	}
	
	
	if (window.selected != null){
		var el = document.getElementById(window.selected);
		while (el != null){
			el = el.parentElement;
			if (el == null)
				break;
			if (el.style.display != 'none')
				break;
			var el_id = el.id;
			el = document.getElementById(el_id.substring(0, el_id.length - 6));
		}
		if (el == null)
			select(id);
	}
}

function plus_click(item)
{
	var id = item.id;
	id = id.substring(0, id.length - 5);
	var el = document.getElementById(id + '-childs');
	if (el == null)
		return false;
	if (el.style.display == 'none'){
		tree_expand(id);
	}else{
		tree_collapse(id);
	}
	window.event.cancelBubble = true;
	return false;
}

function item_click(item)
{
    tree_select(item.id);
    return true;
}

function item_dbl_click(item)
{
	tree_expand(item.id);
	return false;
}

function tree_current_item()
{
	if (window.selected == null)
		return null;
	if (document.getElementById(window.selected))
		return window.selected;
	return null;
}

function tree_first_item()
{
	var el = document.getElementById('tree_content');
	for (var child = el.firstChild; child != null; child = child.nextSibling){
		if (child.id != null)
			return child.id;
	}
	return null;
}

function tree_last_item()
{
	var el = document.getElementById('tree_content');
	var child = el.lastChild;
	for (;;){
		for (; child != null; child = child.previousSibling){
			if ((child.id == null) || (child.id == ''))
				continue;
			if (child.id.substring(child.id.length - 7) == '-childs'){
				if (child.style.display == 'none')
					continue;
				break;	
			}
			return child.id;
		}
		if (child == null){
			if (el.id == '')
				return null;
			child = el.previosSibling;
			continue;
		}
		el = child;
		child = el.lastChild;
	}
}

function tree_prev_item(id)
{
	var el = document.getElementById(id);
	if (el == null)
		return null;
	var child = el.previousSibling;
	for (;;){
		for (; child != null; child = child.previousSibling){
			if ((child.id == null) || (child.id == ''))
				continue;
			if (child.id.substring(child.id.length - 7) == '-childs'){
				if (child.style.display == 'none')
					continue;
				break;	
			}
			return child.id;
		}
		if (child != null){
			child = child.lastChild;
			continue;
		}
		el = el.parentNode;
		if ((el == null) || (el.id == 'tree_content'))
			return null;
		child = el.previousSibling;
	}
}

function tree_next_item(id)
{
	var el = document.getElementById(id);
	if (el == null)
		return null;
	var childs = document.getElementById(id + '-childs');
	if (childs != null){
		el = childs;
		if (childs.style.display != 'none'){
			for (var child = childs.firstChild; child != null; child = child.nextSibling){
				if ((child.id != null) && (child.id != ''))
					return child.id;
			}
		}
	}
	for (;;){
		for (var child = el.nextSibling; child != null; child = child.nextSibling){
			if ((child.id == null) || (child.id == '') || (child.id.substring(child.id.length - 7) == '-childs'))
				continue;
			return child.id;
		}
		el = el.parentNode;
		if ((el == null) || (el.id == 'tree_content'))
			return null;
	}
}

function item_top(item)
{
	var el = document.getElementById(item);
	if (el == null)
		return 0;
	var y = 0;
	for (; el != null; el = el.offsetParent){
		y += el.offsetTop;
	}
	return y;
}

function tree_select(id, noredraw)
{
	if (window.selected == id)
		return;
	if (window.selected != null){
	    var el = document.getElementById(window.selected + '-name');
		if (el != null)
			el.className = 'tree-item';
		var childs = document.getElementById(window.selected + '-childs');
		if ((childs == null) || (childs.style.display == 'none')){
			var img = document.getElementById(window.selected + '-image');
			if (img != null){
				var src = img.src;
				if (src.substring(src.length - 14) == 'folderopen.gif')
					img.src = src.substring(0, src.length - 14) + 'folder.gif';
			}
		}
	}
    var el = document.getElementById(id + '-name');
    if (el != null)
		el.className = 'tree-item-selected';
	var childs = document.getElementById(id + '-childs');
	if ((childs == null) || (childs.style.display == 'none')){
		var img = document.getElementById(id + '-image');
		if (img != null){
			var src = img.src;
			if (src.substring(src.length - 10) == 'folder.gif')
				img.src = src.substring(0, src.length - 10) + 'folderopen.gif';
		}
	}
	window.selected = id;
	var el = document.getElementById(id);
	if (el == null)
		return;
	var top = 0;
	var content = document.getElementById('tree_content');
	for (p = el; p != null; p = p.offsetParent){
		if (p === content)
			break;
		top += p.offsetTop;
	}
	var h = el.offsetHeight;
	var y = content.scrollTop;
	if (y + content.clientHeight < top + h)
		y = top + h - content.clientHeight;
	if (y > top)
		y = top;
	content.scrollTop = y;
	if (noredraw != null)
		return;
	var content = document.getElementById('tree_content');
	content.xmlHttp = CreateXmlHttp();
	content.xmlHttp.open('GET', content.url + '&navigate=' + id, false, document.location.href);
	content.xmlHttp.onreadystatechange = function()
	{
		var content = document.getElementById('tree_content');
		if (content == null)
			return;
		if (content.xmlHttp.readyState != 4)
			return;
		try{
			var res = eval(content.xmlHttp.responseText);
			document.getElementById('_tabBox').innerHTML = res.tab_html;
			document.getElementById('doc_frames').innerHTML = res.frames_html;
			window.original_title = res.title;
			eval(res.tab_script);
			window.loadDoc(true);			
		}catch (err){
		}
	}
	content.xmlHttp.send();
}

function tree_key_down(e)
{
	if (e == null)
		e = window.event;
	var key = e.keyCode;
	switch (key)
	{
	case 36:	// Home
		var	item = tree_first_item();
		if (item != null){
			tree_select(item);
			e.cancelBubble = true;
			return false;
		}
		break;
	case 35:	// End
		var	item = tree_last_item();
		if (item != null){
			tree_select(item);
			e.cancelBubble = true;
			return false;
		}
		break;
	case 40: // Down
		var item = tree_current_item();
		if (item == null)
			item = tree_first_item();
		if (item != null){
			item = tree_next_item(item);
			if (item != null){
				tree_select(item);
				e.cancelBubble = true;
				return false;
			}
		}
		break;
	case 38: // Up
		var item = tree_current_item();
		if (item == null)
			item = tree_last_item();
		if (item != null){
			item = tree_prev_item(item);
			if (item != null){
				tree_select(item);
				e.cancelBubble = true;
				return false;
			}
		}
		break;
	case 34:	// PgDown
		var item = tree_current_item();
		if (item == null)
			item = tree_first_item();
		if (item != null){
			var content = document.getElementById('tree_content');
			var y = item_top(item) + content.clientHeight;
			var prev_item = null;
			for (;;){
				prev_item = item;
				item = tree_next_item(item);
				if (item == null)
					break;
				if (item_top(item) + document.getElementById(item).offsetHeight > y)
					break;
			}
			if (prev_item != null){
				tree_select(prev_item);
				e.cancelBubble = true;
				return false;
			}
		}	
		break;
	case 33:	// PgUp
		var item = tree_current_item();
		if (item == null)
			item = tree_last_item();
		if (item != null){
			var content = document.getElementById('tree_content');
			var y = item_top(item) + document.getElementById(item).offsetHeight - content.clientHeight;
			var prev_item = null;
			for (;;){
				prev_item = item;
				item = tree_prev_item(item);
				if (item == null)
					break;
				if (item_top(item) < y)
					break;
			}
			if (prev_item != null){
				tree_select(prev_item);
				e.cancelBubble = true;
				return false;
			}
		}	
		break;
	case 107:	// +
		var item = tree_current_item();
		if (item != null)
			tree_expand(item);
		break;
	case 109:	// -
		var item = tree_current_item();
		if (item != null)
			tree_collapse(item);
		break;
	}
	return true;
}

function tree_state()
{
	this.load	= function(str, state)
	{
		var content = document.getElementById('tree_content');
		if (content == null)
			return;
		content.saved_state = str;
		content.full_state  = state;
	}
	
	this.save	= function()
	{
		var content = document.getElementById('tree_content');
		if (content == null)
			return;
		var res = window.selected;
		var arr = content.getElementsByTagName('DIV');
		for (var i = 0; i < arr.length; i++){
			var id = arr[i].id;
			if (id.substring(id.length - 7) != '-childs')
				continue;
			if (arr[i].style.display == 'none')
				continue;
			res += ':' + id.substring(0, id.length - 7);
		}
		return res;
	}

}
