Index: /ipk/source.sh4/epg_epgsearch/CONTROL/control
===================================================================
--- /ipk/source.sh4/epg_epgsearch/CONTROL/control	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/CONTROL/control	(revision 7489)
@@ -0,0 +1,10 @@
+Package: enigma2-plugin-epg-epgsearch
+Version: 1.0
+Architecture: sh4
+OE: EPGSearch
+Section: epg
+Priority: optional
+Maintainer: moritz.venn@freaque.net
+Homepage: http://www.aaf-digital.info
+Source: Moritz Venn
+Description: Plugin EPGSearch
Index: /ipk/source.sh4/epg_epgsearch/CONTROL/postinst
===================================================================
--- /ipk/source.sh4/epg_epgsearch/CONTROL/postinst	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/CONTROL/postinst	(revision 7489)
@@ -0,0 +1,12 @@
+#!/bin/sh
+TMP=/tmp/.epg
+
+echo "successfully installed"
+echo "syncing disk"
+sync
+if [ `df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1 | wc -l` -eq 1 ]; then
+	SPACE=`df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1`
+	FREE=`expr $SPACE - 100`
+	echo new freespace size $FREE kb
+fi
+exit 0
Index: /ipk/source.sh4/epg_epgsearch/CONTROL/postrm
===================================================================
--- /ipk/source.sh4/epg_epgsearch/CONTROL/postrm	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/CONTROL/postrm	(revision 7489)
@@ -0,0 +1,14 @@
+#!/bin/sh
+TMP=/tmp/.epg
+PLUGINDIR=/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch
+rm -r $PLUGINDIR > /dev/null 2>&1
+
+echo "successfully removed"
+echo "syncing disk"
+sync
+if [ `df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1 | wc -l` -eq 1 ]; then
+	SPACE=`df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1`
+	FREE=`expr $SPACE - 100`
+	echo new freespace size $FREE kb
+fi
+exit 0
Index: /ipk/source.sh4/epg_epgsearch/CONTROL/preinst
===================================================================
--- /ipk/source.sh4/epg_epgsearch/CONTROL/preinst	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/CONTROL/preinst	(revision 7489)
@@ -0,0 +1,44 @@
+#!/bin/sh
+#
+TMP=/tmp/.epg
+echo "syncing disk"
+sync
+
+model=`cat /etc/model`
+echo""
+echo "Checking your Boxtype...."
+echo "Some Plugins will not work correctly on your $model!"
+echo ""
+if [ "$model" = "" ]; then
+	echo "Sorry! This Plugin is not available for your $model because it will not work correctly!!!"
+	echo "Aborting installation..."
+	exit 1
+else
+	echo "Boxtype: $model OK"
+fi
+
+if [ `df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1 | wc -l` -eq 1 ]; then
+	SPACE=`df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1`
+	FREE=`expr $SPACE - 100`
+	SIZE=880
+	echo "checking freespace"
+	echo packege size $SIZE kb
+	echo freespace size $FREE kb
+	if  [ "$FREE" -lt "$SIZE" ]; then
+		echo "sorry no freespace left on device"
+		exit 1
+	else
+		echo ok
+	fi
+fi   
+echo "installing EPGSearch ..."
+echo "checking OS"
+if  [ `cat /etc/motd | grep AAF | grep M | grep rev | wc -l` -eq 0 ]; then                      
+	echo ---------------------------
+	echo DONT USE this IPK Package!!
+	echo ---
+	echo Only for AAF Image!!
+	echo ---------------------------
+	exit 1
+fi
+exit 0
Index: /ipk/source.sh4/epg_epgsearch/CONTROL/prerm
===================================================================
--- /ipk/source.sh4/epg_epgsearch/CONTROL/prerm	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/CONTROL/prerm	(revision 7489)
@@ -0,0 +1,11 @@
+#!/bin/sh
+TMP=/tmp/.epg
+echo "syncing disk"
+sync
+if [ `df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1 | wc -l` -eq 1 ]; then
+	SPACE=`df | grep /dev/mtdblock | grep var | sed 's/ \+/ /g' | cut -d ' ' -f4 | tail -n1`
+	FREE=`expr $SPACE - 100`
+	echo freespace size $FREE kb
+fi
+echo "removing EPGSearch"
+exit 0
Index: /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/EPGSearch.py
===================================================================
--- /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/EPGSearch.py	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/EPGSearch.py	(revision 7489)
@@ -0,0 +1,435 @@
+# for localized messages  	 
+from . import _
+
+from enigma import eEPGCache, eServiceReference, RT_HALIGN_LEFT, \
+		RT_HALIGN_RIGHT, eListboxPythonMultiContent
+
+from Tools.LoadPixmap import LoadPixmap
+from ServiceReference import ServiceReference
+
+from Screens.ChannelSelection import SimpleChannelSelection
+from Screens.ChoiceBox import ChoiceBox
+from Screens.EpgSelection import EPGSelection
+from Screens.MessageBox import MessageBox
+from Screens.Screen import Screen
+from NTIVirtualKeyBoard import NTIVirtualKeyBoard
+
+from Components.ActionMap import ActionMap
+from Components.Button import Button
+from Components.config import config
+from Components.EpgList import EPGList, EPG_TYPE_SINGLE, EPG_TYPE_MULTI
+from Components.TimerList import TimerList
+from Components.Sources.ServiceEvent import ServiceEvent
+from Components.Sources.Event import Event
+
+from time import localtime
+
+# Partnerbox installed and icons in epglist enabled?
+try:
+	from Plugins.Extensions.Partnerbox.PartnerboxEPGList import \
+			isInRemoteTimer, getRemoteClockPixmap
+	from Plugins.Extensions.Partnerbox.PartnerboxSetup import \
+			showPartnerboxIconsinEPGList
+	PartnerBoxIconsEnabled = showPartnerboxIconsinEPGList()
+except ImportError:
+	PartnerBoxIconsEnabled = False
+
+# AutoTimer installed?
+try:
+	from Plugins.Extensions.AutoTimer.AutoTimerEditor import \
+			addAutotimerFromEvent, addAutotimerFromSearchString
+	autoTimerAvailable = True
+except ImportError:
+	autoTimerAvailable = False
+
+# Overwrite EPGSelection.__init__ with our modified one
+baseEPGSelection__init__ = None
+def EPGSelectionInit():
+	global baseEPGSelection__init__
+	if baseEPGSelection__init__ is None:
+		baseEPGSelection__init__ = EPGSelection.__init__
+	EPGSelection.__init__ = EPGSelection__init__
+
+# Modified EPGSelection __init__
+def EPGSelection__init__(self, session, service, zapFunc=None, eventid=None, bouquetChangeCB=None, serviceChangeCB=None):
+	baseEPGSelection__init__(self, session, service, zapFunc, eventid, bouquetChangeCB, serviceChangeCB)
+	if self.type != EPG_TYPE_MULTI:
+		def bluePressed():
+			cur = self["list"].getCurrent()
+			if cur[0] is not None:
+				name = cur[0].getEventName()
+			else:
+				name = ''
+			self.session.open(EPGSearch, name, False)
+
+		self["epgsearch_actions"] = ActionMap(["EPGSelectActions"],
+				{
+					"blue": bluePressed,
+				})
+		self["key_blue"].text = _("EPG Search")
+
+# Modified EPGSearchList with support for PartnerBox
+class EPGSearchList(EPGList):
+	def __init__(self, type=EPG_TYPE_SINGLE, selChangedCB=None, timer=None):
+		EPGList.__init__(self, type, selChangedCB, timer)
+		self.l.setBuildFunc(self.buildEPGSearchEntry)
+
+		if PartnerBoxIconsEnabled:
+			# Partnerbox Clock Icons
+			self.remote_clock_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock.png')
+			self.remote_clock_add_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_add.png')
+			self.remote_clock_pre_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_pre.png')
+			self.remote_clock_post_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_post.png')
+			self.remote_clock_prepost_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_prepost.png')
+
+	def buildEPGSearchEntry(self, service, eventId, beginTime, duration, EventName):
+		rec1 = beginTime and self.timer.isInTimer(eventId, beginTime, duration, service)
+		# Partnerbox 
+		if PartnerBoxIconsEnabled:
+			rec2 = beginTime and isInRemoteTimer(self,beginTime, duration, service)
+		else:
+			rec2 = False
+		r1 = self.weekday_rect
+		r2 = self.datetime_rect
+		r3 = self.descr_rect
+		t = localtime(beginTime)
+		serviceref = ServiceReference(service) # for Servicename
+		res = [
+			None, # no private data needed
+			(eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_RIGHT, self.days[t[6]]),
+			(eListboxPythonMultiContent.TYPE_TEXT, r2.left(), r2.top(), r2.width(), r1.height(), 0, RT_HALIGN_RIGHT, "%02d.%02d, %02d:%02d"%(t[2],t[1],t[3],t[4]))
+		]
+		if rec1 or rec2:
+			if rec1:			
+				clock_pic = self.getClockPixmap(service, beginTime, duration, eventId)
+				# maybe Partnerbox too
+				if rec2:
+					clock_pic_partnerbox = getRemoteClockPixmap(self,service, beginTime, duration, eventId)
+			else:
+				clock_pic = getRemoteClockPixmap(self,service, beginTime, duration, eventId)
+			if rec1 and rec2:
+				# Partnerbox and local
+				res.extend((
+					(eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, clock_pic),
+					(eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left() + 25, r3.top(), 21, 21, clock_pic_partnerbox),
+					(eListboxPythonMultiContent.TYPE_TEXT, r3.left() + 50, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, serviceref.getServiceName() + ": " + EventName)))
+			else:
+				res.extend((
+					(eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, clock_pic),
+					(eListboxPythonMultiContent.TYPE_TEXT, r3.left() + 25, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, serviceref.getServiceName() + ": " + EventName)))
+		else:
+			res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left(), r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, serviceref.getServiceName() + ": " + EventName))
+		return res
+
+# main class of plugin
+class EPGSearch(EPGSelection):
+	def __init__(self, session, *args):
+		Screen.__init__(self, session)
+		self.skinName = ["EPGSearch", "EPGSelection"]
+
+		self.searchargs = args
+		self.currSearch = ""
+
+		# XXX: we lose sort begin/end here
+		self["key_yellow"] = Button(_("New Search"))
+		self["key_blue"] = Button(_("History"))
+
+# begin stripped copy of EPGSelection.__init__
+		self.bouquetChangeCB = None
+		self.serviceChangeCB = None
+		self.ask_time = -1 #now
+		self["key_red"] = Button("")
+		self.closeRecursive = False
+		self.saved_title = None
+		self["Service"] = ServiceEvent()
+		self["Event"] = Event()
+		self.type = EPG_TYPE_SINGLE
+		self.currentService=None
+		self.zapFunc = None
+		self.sort_type = 0
+		self["key_green"] = Button(_("Add timer"))
+		self.key_green_choice = self.ADD_TIMER
+		self.key_red_choice = self.EMPTY
+		self["list"] = EPGSearchList(type = self.type, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
+		self["actions"] = ActionMap(["EPGSelectActions", "OkCancelActions", "MenuActions"],
+			{
+				"menu": self.menu,
+				"cancel": self.closeScreen,
+				"ok": self.eventSelected,
+				"timerAdd": self.timerAdd,
+				"yellow": self.yellowButtonPressed,
+				"blue": self.blueButtonPressed,
+				"info": self.infoKeyPressed,
+				"red": self.zapTo, # needed --> Partnerbox
+				"nextBouquet": self.nextBouquet, # just used in multi epg yet
+				"prevBouquet": self.prevBouquet, # just used in multi epg yet
+				"nextService": self.nextService, # just used in single epg yet
+				"prevService": self.prevService, # just used in single epg yet
+			})
+
+		self["actions"].csel = self
+		self.onLayoutFinish.append(self.onCreate)
+# end stripped copy of EPGSelection.__init__
+
+		# Partnerbox
+		if PartnerBoxIconsEnabled:
+			EPGSelection.PartnerboxInit(self, False)
+
+	def onCreate(self):
+		self.setTitle(_("EPG Search"))
+
+		if self.searchargs:
+			self.searchEPG(*self.searchargs)
+		else:
+			l = self["list"]
+			l.recalcEntrySize()
+			l.list = []
+			l.l.setList(l.list)
+		del self.searchargs
+
+		# Partnerbox
+		if PartnerBoxIconsEnabled:
+			EPGSelection.GetPartnerboxTimerlist(self)
+
+	def closeScreen(self):
+		# Save our history
+		config.plugins.epgsearch.save()
+		EPGSelection.closeScreen(self)
+
+	def yellowButtonPressed(self):
+		self.session.openWithCallback(
+			self.searchEPG,
+			NTIVirtualKeyBoard,
+			title = _("Enter text to search for")
+		)
+
+	def menu(self):
+		options = [
+			(_("Import from Timer"), self.importFromTimer),
+			(_("Import from EPG"), self.importFromEPG),
+		]
+
+		if autoTimerAvailable:
+			options.extend((
+				(_("Import from AutoTimer"), self.importFromAutoTimer),
+				(_("Save search as AutoTimer"), self.addAutoTimer),
+				(_("Export selected as AutoTimer"), self.exportAutoTimer),
+			))
+
+		self.session.openWithCallback(
+			self.menuCallback,
+			ChoiceBox,
+			list = options
+		)
+
+	def menuCallback(self, ret):
+		ret and ret[1]()
+
+	def importFromTimer(self):
+		self.session.openWithCallback(
+			self.searchEPG,
+			EPGSearchTimerImport
+		)
+
+	def importFromEPG(self):
+		self.session.openWithCallback(
+			self.searchEPG,
+			EPGSearchChannelSelection
+		)
+
+	def importFromAutoTimer(self):
+		removeInstance = False
+		try:
+			# Import Instance
+			from Plugins.Extensions.AutoTimer.plugin import autotimer
+
+			if autotimer is None:
+				removeInstance = True
+				# Create an instance
+				from Plugins.Extensions.AutoTimer.AutoTimer import AutoTimer
+				autotimer = AutoTimer()
+
+			# Read in configuration
+			autotimer.readXml()
+		except Exception, e:
+			self.session.open(
+				MessageBox,
+				_("Could not read AutoTimer timer list: %s") % e,
+				type = MessageBox.TYPE_ERROR
+			)
+		else:
+			# Fetch match strings
+			# XXX: we could use the timer title as description
+			options = [(x.match, x.match) for x in autotimer.getTimerList()]
+
+			self.session.openWithCallback(
+				self.searchEPGWrapper,
+				ChoiceBox,
+				title = _("Select text to search for"),
+				list = options
+			)
+		finally:
+			# Remove instance if there wasn't one before
+			if removeInstance:
+				autotimer = None
+
+	def addAutoTimer(self):
+		addAutotimerFromSearchString(self.session, self.currSearch)
+
+	def exportAutoTimer(self):
+		cur = self['list'].getCurrent()
+		if cur is None:
+			return
+		addAutotimerFromEvent(self.session, cur[0], cur[1])
+
+	def blueButtonPressed(self):
+		options = [(x, x) for x in config.plugins.epgsearch.history.value]
+
+		if options:
+			self.session.openWithCallback(
+				self.searchEPGWrapper,
+				ChoiceBox,
+				title = _("Select text to search for"),
+				list = options
+			)
+		else:
+			self.session.open(
+				MessageBox,
+				_("No history"),
+				type = MessageBox.TYPE_INFO
+			)
+
+	def searchEPGWrapper(self, ret):
+		if ret:
+			self.searchEPG(ret[1])
+
+	def searchEPG(self, searchString = None, searchSave = True):
+		if searchString:
+			self.currSearch = searchString
+			if searchSave:
+				# Maintain history
+				history = config.plugins.epgsearch.history.value
+				if searchString not in history:
+					history.insert(0, searchString)
+					if len(history) > 10:
+						history.pop(10)
+				else:
+					history.remove(searchString)
+					history.insert(0, searchString)
+
+			# Workaround to allow search for umlauts if we know the encoding (pretty bad, I know...)
+			encoding = config.plugins.epgsearch.encoding.value
+			if encoding != 'UTF-8':
+				try:
+					searchString = searchString.decode('UTF-8', 'replace').encode(encoding, 'replace')
+				except (UnicodeDecodeError, UnicodeEncodeError):
+					pass
+
+			# Search EPG, default to empty list
+			epgcache = eEPGCache.getInstance() # XXX: the EPGList also keeps an instance of the cache but we better make sure that we get what we want :-)
+			ret = epgcache.search(('RIBDT', 200, eEPGCache.PARTIAL_TITLE_SEARCH, searchString, eEPGCache.NO_CASE_CHECK)) or []
+			ret.sort(key = lambda x: x[2]) # sort by time
+
+			# Update List
+			l = self["list"]
+			l.recalcEntrySize()
+			l.list = ret
+			l.l.setList(ret)
+
+class EPGSearchTimerImport(Screen):
+	def __init__(self, session):
+		Screen.__init__(self, session)
+		self.skinName = ["EPGSearchTimerImport", "TimerEditList"]
+
+		self.list = []
+		self.fillTimerList()
+
+		self["timerlist"] = TimerList(self.list)
+
+		self["key_red"] = Button(_("Cancel"))
+		self["key_green"] = Button(_("OK"))
+		self["key_yellow"] = Button("")
+		self["key_blue"] = Button("")
+
+		self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
+		{
+			"ok": self.search,
+			"cancel": self.cancel,
+			"green": self.search,
+			"red": self.cancel
+		}, -1)
+		self.onLayoutFinish.append(self.setCustomTitle)
+
+	def setCustomTitle(self):
+		self.setTitle(_("Select a timer to search"))
+
+	def fillTimerList(self):
+		l = self.list
+		del l[:]
+
+		for timer in self.session.nav.RecordTimer.timer_list:
+			l.append((timer, False))
+
+		for timer in self.session.nav.RecordTimer.processed_timers:
+			l.append((timer, True))
+		l.sort(key = lambda x: x[0].begin)
+
+	def search(self):
+		cur = self["timerlist"].getCurrent()
+		if cur:
+			self.close(cur.name)
+
+	def cancel(self):
+		self.close(None)
+
+class EPGSearchChannelSelection(SimpleChannelSelection):
+	def __init__(self, session):
+		SimpleChannelSelection.__init__(self, session, _("Channel Selection"))
+		self.skinName = ["EPGSearchChannelSelection", "SimpleChannelSelection"]
+
+		self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
+		{
+				"showEPGList": self.channelSelected
+		})
+
+	def channelSelected(self):
+		ref = self.getCurrentSelection()
+		if (ref.flags & 7) == 7:
+			self.enterPath(ref)
+		elif not (ref.flags & eServiceReference.isMarker):
+			self.session.openWithCallback(
+				self.epgClosed,
+				EPGSearchEPGSelection,
+				ref,
+				False
+			)
+
+	def epgClosed(self, ret = None):
+		if ret:
+			self.close(ret)
+
+class EPGSearchEPGSelection(EPGSelection):
+	def __init__(self, session, ref, openPlugin):
+		EPGSelection.__init__(self, session, ref)
+		self.skinName = ["EPGSearchEPGSelection", "EPGSelection"]
+		self["key_green"].text = _("Search")
+		self.openPlugin = openPlugin
+
+	def infoKeyPressed(self):
+		self.timerAdd()
+
+	def timerAdd(self):
+		cur = self["list"].getCurrent()
+		evt = cur[0]
+		sref = cur[1]
+		if not evt:
+			return
+
+		if self.openPlugin:
+			self.session.open(
+				EPGSearch,
+				evt.getEventName()
+			)
+		else:
+			self.close(evt.getEventName())
+
Index: /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/LICENSE
===================================================================
--- /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/LICENSE	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/LICENSE	(revision 7489)
@@ -0,0 +1,12 @@
+All Files of this Software are licensed under the Creative Commons 
+Attribution-NonCommercial-ShareAlike 3.0 Unported 
+License if not stated otherwise in a Files Head. To view a copy of this license, visit
+http://creativecommons.org/licenses/by-nc-sa/3.0/ or send a letter to Creative
+Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
+
+Alternatively, this plugin may be distributed and executed on hardware which
+is licensed by Dream Multimedia GmbH.
+
+This plugin is NOT free software. It is open source, you are allowed to
+modify it (if you keep the license), but it may not be commercially 
+distributed other than under the conditions noted above.
Index: /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/NTIVirtualKeyBoard.py
===================================================================
--- /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/NTIVirtualKeyBoard.py	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/NTIVirtualKeyBoard.py	(revision 7489)
@@ -0,0 +1,52 @@
+from Tools.NumericalTextInput import NumericalTextInput
+from Screens.VirtualKeyBoard import VirtualKeyBoard
+from Components.ActionMap import NumberActionMap
+
+class NTIVirtualKeyBoard(VirtualKeyBoard, NumericalTextInput):
+	def __init__(self, session, **kwargs):
+		VirtualKeyBoard.__init__(self, session, **kwargs)
+		NumericalTextInput.__init__(self, nextFunc = self.nextFunc)
+
+		self.skinName = "VirtualKeyBoard"
+
+		self["NumberActions"] = NumberActionMap(["NumberActions"],
+		{
+			"1": self.keyNumberGlobal,
+			"2": self.keyNumberGlobal,
+			"3": self.keyNumberGlobal,
+			"4": self.keyNumberGlobal,
+			"5": self.keyNumberGlobal,
+			"6": self.keyNumberGlobal,
+			"7": self.keyNumberGlobal,
+			"8": self.keyNumberGlobal,
+			"9": self.keyNumberGlobal,
+			"0": self.keyNumberGlobal
+		})
+
+		self.editing = False
+
+	def backClicked(self):
+		self.nextKey()
+		self.editing = False
+		self["text"].setMarkedPos(-1)
+		VirtualKeyBoard.backClicked(self)
+
+	def okClicked(self):
+		self.nextKey()
+		self.editing = False
+		self["text"].setMarkedPos(-1)
+		VirtualKeyBoard.okClicked(self)
+
+	def keyNumberGlobal(self, number):
+		unichar = self.getKey(number)
+		if not self.editing:
+			self.text = self["text"].getText()
+			self.editing = True
+			self["text"].setMarkedPos(len(self.text))
+		self["text"].setText(self.text + unichar.encode('utf-8', 'ignore'))
+
+	def nextFunc(self):
+		self.text = self["text"].getText()
+		self.editing = False
+		self["text"].setMarkedPos(-1)
+
Index: /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/__init__.py
===================================================================
--- /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/__init__.py	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/__init__.py	(revision 7489)
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+from Components.Language import language
+from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_LANGUAGE
+from os import environ as os_environ
+import gettext
+
+def localeInit():
+	lang = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
+	os_environ["LANGUAGE"] = lang # Enigma doesn't set this (or LC_ALL, LC_MESSAGES, LANG). gettext needs it!
+	gettext.bindtextdomain("EPGSearch", resolveFilename(SCOPE_PLUGINS, "Extensions/EPGSearch/locale"))
+
+def _(txt):
+	t = gettext.dgettext("EPGSearch", txt)
+	if t == txt:
+		t = gettext.gettext(txt)
+	return t
+
+localeInit()
+language.addCallback(localeInit)
+
Index: /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/maintainer.info
===================================================================
--- /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/maintainer.info	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/maintainer.info	(revision 7489)
@@ -0,0 +1,2 @@
+moritz.venn@freaque.net
+EPGSearch
Index: /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/plugin.py
===================================================================
--- /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/plugin.py	(revision 7489)
+++ /ipk/source.sh4/epg_epgsearch/usr/lib/enigma2/python/Plugins/Extensions/EPGSearch/plugin.py	(revision 7489)
@@ -0,0 +1,75 @@
+# for localized messages  	 
+from . import _
+
+from enigma import eServiceCenter
+
+# Config
+from Components.config import config, ConfigSet, ConfigSubsection, ConfigText
+
+config.plugins.epgsearch = ConfigSubsection()
+config.plugins.epgsearch.history = ConfigSet(choices = [])
+# XXX: configtext is more flexible but we cannot use this for a (not yet created) gui config
+config.plugins.epgsearch.encoding = ConfigText(default = 'ISO8859-15', fixed_size = False)
+
+# Plugin
+from EPGSearch import EPGSearch, EPGSearchEPGSelection, EPGSelectionInit
+
+# Plugin definition
+from Plugins.Plugin import PluginDescriptor
+
+# Autostart
+def autostart(reason, **kwargs):
+	try:
+		# for blue key activating in EPGSelection
+		EPGSelectionInit()
+	except Exception:
+		pass
+
+# Mainfunction
+def main(session, *args, **kwargs):
+	s = session.nav.getCurrentService()
+	if s:
+		info = s.info()
+		event = info.getEvent(0) # 0 = now, 1 = next
+		name = event and event.getEventName() or ''
+		session.open(EPGSearch, name, False)
+	else:
+		session.open(EPGSearch)
+
+# Event Info
+def eventinfo(session, *args, **kwargs):
+	ref = session.nav.getCurrentlyPlayingServiceReference()
+	session.open(EPGSearchEPGSelection, ref, True)
+
+# Movielist
+def movielist(session, service, **kwargs):
+	serviceHandler = eServiceCenter.getInstance()
+	info = serviceHandler.info(service)
+	name = info and info.getName(service) or ''
+
+	session.open(EPGSearch, name)
+
+def Plugins(**kwargs):
+	return [
+		PluginDescriptor(
+			where = PluginDescriptor.WHERE_SESSIONSTART,
+			fnc = autostart,
+		),
+		PluginDescriptor(
+			name = "EPGSearch",
+			description = _("Search EPG"),
+			where = PluginDescriptor.WHERE_PLUGINMENU,
+			fnc = main,
+		),
+		PluginDescriptor(
+			name = _("search EPG..."),
+			where = PluginDescriptor.WHERE_EVENTINFO,
+			fnc = eventinfo,
+		),
+		PluginDescriptor(
+			name = "EPGSearch",
+			description = _("search EPG..."),
+			where = PluginDescriptor.WHERE_MOVIELIST,
+			fnc = movielist,
+		),
+	]
