# Copyright (c) 2005 Martin Ankerl
# This application is free software; you can redistribute it and/or
# modify it under the terms of the Ruby license defined in the
# COPYING file.
#
class Search_Engine
def initialize(gui, data)
@gui = gui
@data = data
@search_thread = nil
end
# Executed whenever a search criteria changes to update the packet list.
def on_search
# restart current search
@end_time = Time.now + $cfg.search_delay
@restart_search = true
@gui.search_label.enabled = false
return if @search_thread && @search_thread.status
@search_thread = Thread.new(@search_thread) do
begin
@gui.search_label.enabled = false
# wait untill deadline
while (t = (@end_time - Time.now)) > 0
sleep(t)
end
@data.gui_mutex.synchronize do
# the thread has to use the gui mutex inside
@restart_search = false
match_data = get_match_data
# remove all items
@gui.packet_list.dirty_clear
# add all items that match the search criteria
status_text_deadline = Time.now + $cfg.status_line_update_interval
@data.items.each do |item|
#item.parent = @gui.packet_list if match?(item, match_data)
if match?(item, match_data)
item.show
now = Time.now
if now > status_text_deadline
update_search_status_text
status_text_deadline = now + $cfg.status_line_update_interval
end
end
break if @restart_search
end
update_search_status_text
if (@gui.packet_list.numItems > 0)
@gui.packet_list.setCurrentItem(0)
@gui.packet_list.selectItem(0)
@gui.main.show_info(@gui.packet_list.getItem(0).packet_item.data)
end
@gui.search_label.enabled = true
end # synchronize
end while @restart_search# || match_data != @gui.search_field.text.downcase.split
end #thread.new
end
def get_match_data
str_to_match_data(@gui.search_field.text)
end
# Converts a string into a match_data representation.
def str_to_match_data(str, index=0)
words = [ ]
exclude = [ ]
is_exclude = false
while str[index]
case str[index]
when ?", ?'
word, index = get_word(str, index+1, str[index])
unless word.empty?
if is_exclude
exclude.push word
is_exclude = false
else
words.push word
end
end
when 32 # space
is_exclude = false
=begin
when ?>
min, index = get_word(str, index+1)
min = @gui.logic.size_to_nr(min)
when ?<
max, index = get_word(str, index+1)
max = @gui.logic.size_to_nr(max)
=end
when ?-
is_exclude = true
else
word, index = get_word(str, index)
if is_exclude
exclude.push word
is_exclude = false
else
words.push word
end
end
index += 1
end
# check if word has upcase letters
words.collect! do |w|
[w, /[A-Z]/.match(w)!=nil]
end
exclude.collect! do |w|
[w, /[A-Z]/.match(w)!=nil]
end
[words, exclude]
end
def get_word(str, index, delim=32) # 32==space
word = ""
c = str[index]
while (c && c != delim)
word += c.chr
index += 1
c = str[index]
end
[word, index]
end
# Update the text for the number of displayed packs.
def update_search_status_text
@gui.search_label.text = sprintf($cfg.text.search, @gui.packet_list.numItems, @data.items.size)
end
# Find out if item is matched by current search criteria.
def match?(item, match_data)
words, exclude, min, max = match_data
# check text that has to be there
searchable, sortable_downcase, sortable_normal = item.sortable(0)
words.each do |match_str, is_sensitive|
if is_sensitive
return false unless sortable_normal.include?(match_str)
else
return false unless sortable_downcase.include?(match_str)
end
end
# check text not allowed to be there
exclude.each do |match_str, is_sensitive|
if is_sensitive
return false if sortable_normal.include?(match_str)
else
return false if sortable_downcase.include?(match_str)
end
end
# each check ok
true
end
end
syntax highlighted by Code2HTML, v. 0.9.1