import rox
from rox import g
from EditWindow import Minibuffer

class Search(Minibuffer):
	"A minibuffer used to search for text."

	def setup(self, window):
		self.window = window
		buffer = window.buffer
		cursor = buffer.get_iter_at_mark(window.insert_mark)
		buffer.move_mark_by_name('search_base', cursor)
		self.dir = 1
		self.set_label()
	
	info = 'Type a string to search for. The display will scroll to show the ' \
		'next match as you type. Use the Up and Down cursor keys to move ' \
		'to the next or previous match. Press Escape or Return to finish.'
	
	def set_label(self):
		if self.dir == 1:
			self.window.set_mini_label('Forward search:')
		else:
			self.window.set_mini_label('Backward search:')
	
	def set_dir(self, dir):
		assert dir == 1 or dir == -1

		buffer = self.window.buffer
		cursor = buffer.get_iter_at_mark(self.window.insert_mark)
		buffer.move_mark_by_name('search_base', cursor)

		if dir == self.dir:
			if dir == 1:
				cursor.forward_char()
			else:
				cursor.backward_char()
			if self.search(cursor):
				buffer.move_mark_by_name('search_base', cursor)
			else:
				g.gdk.beep()
		else:
			self.dir = dir
			self.set_label()
		self.changed()
	
	def activate(self):
		self.window.set_minibuffer(None)

	def key_press(self, kev):
		k = kev.keyval
		if k == g.keysyms.Up:
			self.set_dir(-1)
		elif k == g.keysyms.Down:
			self.set_dir(1)
		else:
			return 0
		return 1
	
	def search(self, start):
		"Search forwards or backwards for the pattern. Matches at 'start'"
		"are allowed in both directions. Returns (match_start, match_end) if"
		"found."
		iter = start.copy()
		pattern = self.window.mini_entry.get_text()
		if not pattern:
			return (iter, iter)
		if self.dir == 1:
			found = iter.forward_search(pattern, 0, None)
		else:
			iter.forward_chars(len(pattern))
			found = iter.backward_search(pattern, 0, None)
		return found
	
	def changed(self):
		buffer = self.window.buffer
		pos = buffer.get_iter_at_mark(self.window.search_base)

		found = self.search(pos)
		if found:
			buffer.move_mark_by_name('insert', found[0])
			buffer.move_mark_by_name('selection_bound', found[1])
			self.window.text.scroll_to_iter(found[0], 0.05, g.FALSE)
		else:
			g.gdk.beep()
