Почти доделал. Только callback не работает. А как сделаю, так опубликую, может кому пригодится

Сам долго искал в нете, нашел и то пришлось дорабатывать.
Ну вот, вроде и все. Вот окончательный код:
Код
<?php
setlocale(LC_ALL, array ('ru_RU.CP1251', 'rus_RUS.1251'));
/*
Ограничения поиска:
Работает только с учетом регистра.
Для работы с тегами <title>, <style>, <script> и т. п. где между ними размещен "особый" код, надо создавать
свой список таких тегов.
Callback не будет работать правильно, если одинаковые специальные теги будут вложены. То есть для следующей
строки подсветка сработает неправильно: "<script><script></script></script>".
Алгоритм никогда не сможет найти слово Вадим в строке "<font size='7'>В</font>адим".
Такой поиск сделать можно, но его надо очччень хорошо продумать и алгоритм там будет другой. Придется писать
свою функцию replace_str, так, что бы она при проходе от первого сивола к последнему считала строки
"<$i>" как за пустые ("").
*/
function myfunc($x) {
$firststr='<span style="color:#ff0000;">';
$secondstr='</span>';
return str_replace($firststr, "", str_replace($secondstr, "", $x));
}
function highlighter ($data, $mystr) {
// Массив тегов (определены, как регулярные выражения)
$specialTags=array("<title>", "<\/title>", "<style>", "<\/style>", "<script[^>]*?>", "<\/script>");
// Открывающая строка для подсветки
$firststr='<span style="color:#ff0000;">';
// Закрывающая строка для подсветки
$secondstr='</span>';
// Получаем массив слов которые надо подсвечивать и заодно заменяем спец. символы html-сущностями.
$t=explode(' ', htmlspecialchars($mystr, ENT_QUOTES, "Windows-1251"));
// Удаляем повторяющиеся слова. Ведь бывают же извращенцы;)
$t=array_unique($t);
// Выполняем процедуру подсветки для каждого слова
foreach($t as $hren) {
// Получаем список тегов
preg_match_all('#<[^>]*?>#', $data, $tags);
// Без комментариев;)
$tagList=array(); $k=0;
// В $tags[0] полное совпадение по шаблону, там находятся все теги
foreach($tags[0] as $i) {
// Увеличиваем размер массив
$k++;
// Заносим в массив новый уникальный тег
$tagList[$k]=$i;
// А в строке заменяем этот тег на "<номер элемента массива, в котором мы сохранили тег>"
$data=substr_replace($data, '<<'.$k.'>>', strpos($data, $i), strlen($i));
}
// Производим обрамление текста <span>-ами
$data=str_replace($hren, $firststr.$hren.$secondstr, $data);
// Если пользователь ищет цифры, то они могут встретится в тегах. Поэтому возвращаем замененные теги назад
$data=preg_replace_callback( '#<(([0-9])*?(<[^>]*?>)*?)*?>#',
create_function(
'$m',
'return myfunc($m[0]);'
),
$data );
// Убираем все подсветки внутри "особых" тегов
$ffirst=0;
$ssecond=0;
for($i=0; $i<=(count($specialTags)-1)/2; $i++) {
for ($j=1; $j<=$k; $j++) {
if (preg_match ("/".$specialTags[$i*2]."/i", $tagList[$j])) $ffirst="<<".$j.">>";
if (preg_match ("/".$specialTags[$i*2+1]."/i", $tagList[$j])) $ssecond="<<".$j.">>";
if ($ffirst && $ssecond) {
$data=preg_replace_callback( '#'.$ffirst.'(.*?)'.$ssecond.'#',
create_function(
'$m',
'return myfunc($m[0]);'
),
$data );
$ffirst=0;
$ssecond=0;
}
}
}
// Возвращаем все теги на место
foreach($tagList as $k=>$i) $data=str_replace('<<'.$k.'>>', $i, $data);
}
// Возвращаем подсвеченный текст
return $data;
}
?>
Хотелось бы, что бы вы его потестили, а то может чего я из виду и упустил. Но проверял несколько раз. Все равно не верится, что у меня получилось. Думал лет в 20 такое напишу, когда будет работа и т. д. и т. п.
А так всем спасибо за участие и поддержку. Сейчас все будут награждены плюсиками