# 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