<? 
 /* 	
	Поиск по словарю Мюллера
	Скрипт на PHP4 для http://sk1.sourceforge.net/testing/
	Автор: Андрей Черепанов <sibskull@mail.ru>
	Версия: 1.01 от 02.07.2005г.

	License: GPL v.2
*/

	$dictionary = "Mueller7GPL.koi"; 
	$hash_file  = "Mueller7GPL.hash"; 

	header("Content-type: text/html; charset=koi8-r");
	
?>
<!--!doctype html public "-//IETF//DTD HTML//EN"-->
<html>
<head>
   <meta http-equiv="content-type" content="text/html; charset=koi8-r">
   <meta name="author" content="Андрей Черепанов">
   <title>Поиск по словарю Мюллера</title>
</head>

<body>
<h2 style="color: darkred">Поиск по словарю Мюллера</h2>
<form action="index.php" method="get">
<input type="text" name="word" size="40" value="<? if(isset($_GET['word']) ) { echo $_GET['word']; } ?>">
<input type="submit" value="Поиск"></form>
<hr noshadow size="1" color="black">
<? 	

// For count work time in microseconds
function getmicrotime() {  list($usec, $sec) = explode(" ", microtime()); return ((float)$usec + (float)$sec); } 

// Lookout in hash file
function lookup_hash( $handle, $range, $w_key ) {
	// range: { f_pos, f_value, l_pos, l_value }
	if( $range[1] == $w_key ) { // Key found!
		fseek($handle, ($range[0]+1)*12, SEEK_SET);
		$ret = unpack('L*', fread($handle, 8));
		return $ret;
	} else {
		// Check range...
		if( $range[0] == $range[2]-1 ) { // One element and it is not w_key: not found
			return array();
		}
		// Seek deeper
		$len = $range[2] - $range[0]; // Count of items
		$v_range = $range[3] - $range[1]; // Values range
		$pos = $range[0] + floor( ($w_key - $range[1])/$v_range * $len );
		// Too small offset
		if($pos == $range[0]) {
			$pos++;
		} elseif ($pos == $range[2]) {
			$pos--;
		}

		// Read from <pos>
		fseek($handle, $pos*12, SEEK_SET);
		$v_key = unpack('l', fread($handle, 4));
		$new_key = $v_key[1];

		if( $new_key == $w_key ) { // Key found!
			$ret = unpack('L*', fread($handle, 8));
			return $ret;
		}

		// Select range based on new key
		if( $new_key > $w_key ) {
			// Lower bound
			$range[2] = $pos;
			$range[3] = $new_key;
		} else {
			// Upper bound
			$range[0] = $pos;
			$range[1] = $new_key;
		}
		// Lookup deeper
		return lookup_hash( $handle, $range, $w_key );
	}
}

// Get text from file
function get_text( $pos ) {
	global $dictionary;
	$dic = fopen($dictionary, "r");
	fseek($dic, $pos[1]);
	$text = fread($dic, $pos[2]-$pos[1]);
	fclose($dic);
	return $text;
}

// Get text from file
function article( $text ) {
	$search = array ( '/\n/',
			  '/ ([0-9]{1,2})> /',	// Sections
			  '/ ([абвгдеёжзийклмнопрстуфхцчшщъыьэюя])> /', // Literal sections
			  '/^(.+)  /m',		// Word(s)
			  '/\n\n/',		// Separate multiply lines
			  '/\b_([^.]+)\./',	// Abbreviatures
			  '/ \b([0-9]{1,2})\. /', // Form
			  '/[;:] ([a-zA-Z .?\!]+) /' // Separate phrases
			);
	$replacement = array( chr(10).chr(10),
			  ' <br><b>$1)</b> ',		// Sections
			  ' <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$1) ', 	// Literal sections
			  '<h2>$1</h2><blockquote> ', 		// Word(s)
			  '</blockquote>'.chr(10),		// Separate multiply lines
			  '<i style="color: gray">$1.</i> ', 	// Abbreviatures
			  '<br>&nbsp;<br><b style="font-size: larger">$1.</b> ', // Form
			  '<br><b style="color: green">$1</b> ' // Separate phrases
			);
	// Format text
	$text = preg_replace($search, $replacement, $text);

	// Transcription
	preg_match_all('/\[([^]]+)\]/', $text, $matches);
	while (list($key, $val) = each($matches[1])) {
		// TODO: $trans = "[<img align=\"bottom\" src=\"transcription.php3?$val\">]";
		$trans = "";
		$text  = str_replace('['.$val.']', $trans, $text);
	}

	echo $text;
}

$a = array();
if ( isset($_GET['word']) || isset($_SERVER['argv'][1]) ) {
	// Fix time
	$time_start = getmicrotime();
	
	if( isset($_SERVER['argv'][1]) ) {
		$word = strtolower($_SERVER['argv'][1]); // Command line call
	} else { 
		$word = strtolower($_GET['word']);	// HTTP request
	}

	// Open dictionary hash
	$hash = fopen($hash_file, "r");
	
	// Lookup in dictionary
	$crc = crc32(trim($word));
	
	$total = fstat($hash);
	fseek($hash, 0, SEEK_SET);
	$first = unpack('l', fread($hash, 4));
	fseek($hash, -12, SEEK_END);
	$last = unpack('l', fread($hash, 4));
	$found = lookup_hash($hash, array( 0, $first[1], $total['size']/12-1, $last[1] ), $crc);

	// Close file
	fclose($hash);

	// If found - show result
	if( isset($found[1]) ) {
		article(get_text($found));
	} else {
		echo "Слово '<b>".trim($word)."</b>' не найдено.<br>";
	}


	// Show elapsed time
	$time = round( getmicrotime() - $time_start, 4 );
	echo '<hr noshadow size="1" color="black">';
	echo "Затраченное время: $time сек.";
}
?>
<hr noshadow size="1" color="black">
<div style="border: goldenrod solid 0.75pt; background: #FFEDD3; padding: 3mm">
<small>Механизм поиска: &copy; <a href="mailto:sibskull@mail.ru?subject=mueller">Андрей Черепанов</a>, 2005. Версия 1.01. Лицензия: GPL v.2.<br>
Страница сделана для проекта <a href="http://sk1.sourceforge.net/testing/">http://sk1.sourceforge.net/testing/</a>.<br>
Файлы:<ul>
<li><a href="Mueller7GPL.koi">Mueller7GPL.koi</a> (словарь, 5,7 МБ)</li>
<li><a href="Mueller7GPL.hash">Mueller7GPL.hash</a> (индексный файл, сформированный программой <i>makehash.php</i>, 0,5 МБ)</li>
<li><a href="mueller_index.html">index.php</a> (скрипт поиска по словарю, скачать с подсветкой - 31,9 КБ, 181 строкa)</li>
<li><a href="makehash.html">makehash.php</a> (скрипт формирования индексного файла, скачать с подсветкой - 8,1 КБ, 51 строка)</li>
</ul></small></div>

</body></html>