sub SearchTitleAndBody { my $string = shift; my $and = T('and'); my $or = T('or'); my @strings = split(/ +$and +/, $string); my @found; foreach my $name (AllPagesList()) { OpenPage($name); OpenDefaultText(); next if ($Text{'text'} =~ /^#FILE / and $string !~ /^\^#FILE/); # skip files unless requested my $found = 1; # assume found foreach my $str (@strings) { my @temp = split(/ +$or +/, $str); $str = join('|', @temp); if (not ($Text{'text'} =~ /$str/i)) { $found = 0; last; } } if ($found or $name =~ /$string/i) { push(@found, $name); } elsif ($FreeLinks && ($name =~ m/_/)) { my $freeName = $name; $freeName =~ s/_/ /g; if ($freeName =~ /$string/i) { push(@found, $name); } } } return @found; } sub PrintSearchResults { my ($searchstring, @results) = @_ ; my $and = T('and'); my $or = T('or'); my $searchstring = join('|', split(/ +(?:$and|$or) +/, $searchstring)); my ($snippetlen, $maxsnippets) = (100, 4) ; # these seem nice. print $q->h2(Ts('%s pages found:', ($#results + 1))); my $files = ($searchstring =~ /^\^#FILE/); # usually skip files foreach my $name (@results) { OpenPage($name); OpenDefaultText(); my $pageText = QuoteHtml($Text{'text'}); # get the page, filter it, remove all tags $pageText =~ s/$FS//g; # Remove separators (paranoia) $pageText =~ s/[\s]+/ /g; # Shrink whitespace $pageText =~ s/([-_=\\*\\.]){10,}/$1$1$1$1$1/g ; # e.g. shrink "----------" my $htmlre = join('|',(@HtmlTags, 'pre', 'nowiki', 'code')); $pageText =~ s/\<\/?($htmlre)(\s[^<>]+?)?\>//gi; # entry header print '<p>' . $q->span({-class=>'result'}, GetPageLink($name)), $q->br(); if ($files) { $pageText =~ /^#FILE ([^ ]+)/; print $1; } else { # show a snippet from the top of the document my $j = index($pageText, ' ', $snippetlen); # end on word boundary my $t = substr($pageText, 0, $j); $t =~ s/($searchstring)/<strong>\1<\/strong>/gi; print $t, ' ', $q->b('...'); $pageText = substr($pageText, $j); # to avoid rematching # search for occurrences of searchstring my $jsnippet = 0 ; while ($jsnippet < $maxsnippets && $pageText =~ m/($searchstring)/i) { $jsnippet++; if (($j = index($pageText, $1)) > -1 ) { # get substr containing (start of) match, ending on word boundaries my $start = index($pageText, ' ', $j-($snippetlen/2)); $start = 0 if ($start == -1); my $end = index($pageText, ' ', $j+($snippetlen/2)); $end = length($pageText ) if ($end == -1); $t = substr($pageText, $start, $end-$start); # highlight occurrences and tack on to output stream. $t =~ s/($searchstring)/<strong>\1<\/strong>/gi; print $t, ' ', $q->b('...'); # truncate text to avoid rematching the same string. $pageText = substr($pageText, $end); } } } # entry trailer print $q->br(), $q->span({-class=>'info'}, int((length($pageText)/1024)+1) . 'K - ' . T('last updated') . ' ' . TimeToText($Section{ts}) . ' ' . T('by') . ' ' . GetAuthorLink($Section{'host'}, $Section{'username'})), '</p>'; } }