[vdr-plugin-tvguide] 01/03: Imported Upstream version 1.2.2

Tobias Grimm tiber-guest at moszumanska.debian.org
Tue Feb 10 18:11:47 UTC 2015


This is an automated email from the git hooks/post-receive script.

tiber-guest pushed a commit to branch master
in repository vdr-plugin-tvguide.

commit ca346bbbd3ef7d7cf25dc59fc707df5af273a8d5
Author: etobi <git at e-tobi.net>
Date:   Tue Feb 10 19:08:40 2015 +0100

    Imported Upstream version 1.2.2
---
 HISTORY                                            |  128 +
 Makefile                                           |   25 +-
 Makefile-smaller-VDR1.7.34                         |  115 -
 README                                             |  281 +-
 channelcolumn.c                                    |  558 ++--
 channelcolumn.h                                    |   82 +-
 channelgroup.c                                     |   98 +
 channelgroup.h                                     |   44 +
 channelgroups.c                                    |  143 +
 channelgroups.h                                    |   30 +
 channeljump.c                                      |   90 +
 channeljump.h                                      |   29 +
 config.c                                           |  472 ++--
 config.h                                           |  308 ++-
 detailview.c                                       |  315 +--
 detailview.h                                       |   49 +-
 dummygrid.c                                        |  111 +
 dummygrid.h                                        |   34 +
 epggrid.c                                          |  255 +-
 epggrid.h                                          |   56 +-
 fontmanager.c                                      |   96 +
 fontmanager.h                                      |   41 +
 footer.c                                           |  174 +-
 footer.h                                           |   32 +-
 geometrymanager.c                                  |   74 +
 geometrymanager.h                                  |   54 +
 grid.c                                             |   82 +
 grid.h                                             |   58 +
 headergrid.c                                       |  128 +
 headergrid.h                                       |   21 +
 icons/darkredNG/osdElements/button_30percent.png   |  Bin 0 -> 39062 bytes
 icons/darkredNG/osdElements/button_70percent.png   |  Bin 0 -> 103047 bytes
 .../osdElements/button_active_30percent.png        |  Bin 0 -> 38329 bytes
 .../osdElements/button_active_70percent.png        |  Bin 0 -> 99939 bytes
 icons/darkredNG/osdElements/buttonblue.png         |  Bin 0 -> 12519 bytes
 icons/darkredNG/osdElements/buttongreen.png        |  Bin 0 -> 12737 bytes
 icons/darkredNG/osdElements/buttonred.png          |  Bin 0 -> 12362 bytes
 icons/darkredNG/osdElements/buttonyellow.png       |  Bin 0 -> 13023 bytes
 icons/darkredNG/osdElements/channel_jump.png       |  Bin 0 -> 76404 bytes
 .../darkredNG/osdElements/channelgroup_bottom.png  |  Bin 0 -> 2292 bytes
 icons/darkredNG/osdElements/channelgroup_head.png  |  Bin 0 -> 2288 bytes
 .../osdElements/channelgroup_horizontal.png        |  Bin 0 -> 31050 bytes
 icons/darkredNG/osdElements/channelgroup_left.png  |  Bin 0 -> 1998 bytes
 icons/darkredNG/osdElements/channelgroup_right.png |  Bin 0 -> 1861 bytes
 .../osdElements/channelgroup_vertical.png          |  Bin 0 -> 14472 bytes
 .../osdElements/channellogoback_horizontal.png     |  Bin 0 -> 16307 bytes
 .../osdElements/channellogoback_vertical.png       |  Bin 0 -> 26057 bytes
 icons/darkredNG/osdElements/clock.png              |  Bin 0 -> 5976 bytes
 icons/darkredNG/osdElements/date_vertical.png      |  Bin 0 -> 19803 bytes
 icons/darkredNG/osdElements/grid_active_bottom.png |  Bin 0 -> 2642 bytes
 icons/darkredNG/osdElements/grid_active_head.png   |  Bin 0 -> 2684 bytes
 .../osdElements/grid_active_horizontal.png         |  Bin 0 -> 30601 bytes
 icons/darkredNG/osdElements/grid_active_left.png   |  Bin 0 -> 2328 bytes
 icons/darkredNG/osdElements/grid_active_right.png  |  Bin 0 -> 2208 bytes
 .../darkredNG/osdElements/grid_active_vertical.png |  Bin 0 -> 97490 bytes
 icons/darkredNG/osdElements/grid_bottom.png        |  Bin 0 -> 4170 bytes
 icons/darkredNG/osdElements/grid_head.png          |  Bin 0 -> 3852 bytes
 icons/darkredNG/osdElements/grid_horizontal.png    |  Bin 0 -> 32326 bytes
 icons/darkredNG/osdElements/grid_left.png          |  Bin 0 -> 2301 bytes
 icons/darkredNG/osdElements/grid_right.png         |  Bin 0 -> 2182 bytes
 icons/darkredNG/osdElements/grid_vertical.png      |  Bin 0 -> 98957 bytes
 icons/darkredNG/osdElements/recmenu_background.png |  Bin 0 -> 309224 bytes
 .../osdElements/statusheader_content_full.png      |  Bin 0 -> 259761 bytes
 .../osdElements/statusheader_content_windowed.png  |  Bin 0 -> 195867 bytes
 .../darkredNG/osdElements/statusheader_tvframe.png |  Bin 0 -> 57079 bytes
 .../darkredNG/osdElements/timeline1_horizontal.png |  Bin 0 -> 21401 bytes
 icons/darkredNG/osdElements/timeline1_vertical.png |  Bin 0 -> 17751 bytes
 .../darkredNG/osdElements/timeline2_horizontal.png |  Bin 0 -> 20310 bytes
 icons/darkredNG/osdElements/timeline2_vertical.png |  Bin 0 -> 17650 bytes
 icons/darkredNG/recmenuicons/activetimer.png       |  Bin 0 -> 1731 bytes
 icons/darkredNG/recmenuicons/arrow_left.png        |  Bin 0 -> 1136 bytes
 icons/darkredNG/recmenuicons/arrow_right.png       |  Bin 0 -> 936 bytes
 icons/darkredNG/recmenuicons/delete_active.png     |  Bin 0 -> 768 bytes
 icons/darkredNG/recmenuicons/delete_inactive.png   |  Bin 0 -> 886 bytes
 icons/darkredNG/recmenuicons/edit_active.png       |  Bin 0 -> 2599 bytes
 icons/darkredNG/recmenuicons/edit_inactive.png     |  Bin 0 -> 2009 bytes
 icons/darkredNG/recmenuicons/icon_backspace.png    |  Bin 0 -> 1873 bytes
 icons/darkredNG/recmenuicons/icon_del_ins.png      |  Bin 0 -> 1532 bytes
 icons/darkredNG/recmenuicons/icon_shift.png        |  Bin 0 -> 1274 bytes
 icons/darkredNG/recmenuicons/info_active.png       |  Bin 0 -> 2421 bytes
 icons/darkredNG/recmenuicons/info_inactive.png     |  Bin 0 -> 1859 bytes
 icons/darkredNG/recmenuicons/no.png                |  Bin 0 -> 1627 bytes
 icons/darkredNG/recmenuicons/record_active.png     |  Bin 0 -> 6736 bytes
 icons/darkredNG/recmenuicons/record_inactive.png   |  Bin 0 -> 3859 bytes
 icons/darkredNG/recmenuicons/search_active.png     |  Bin 0 -> 3426 bytes
 icons/darkredNG/recmenuicons/search_inactive.png   |  Bin 0 -> 2977 bytes
 icons/darkredNG/recmenuicons/yes.png               |  Bin 0 -> 2655 bytes
 icons/default/osdElements/button_30percent.png     |  Bin 0 -> 38442 bytes
 icons/default/osdElements/button_70percent.png     |  Bin 0 -> 105355 bytes
 .../osdElements/button_active_30percent.png        |  Bin 0 -> 39767 bytes
 .../osdElements/button_active_70percent.png        |  Bin 0 -> 105357 bytes
 icons/default/osdElements/buttonblue.png           |  Bin 0 -> 12519 bytes
 icons/default/osdElements/buttongreen.png          |  Bin 0 -> 12737 bytes
 icons/default/osdElements/buttonred.png            |  Bin 0 -> 12362 bytes
 icons/default/osdElements/buttonyellow.png         |  Bin 0 -> 13023 bytes
 icons/default/osdElements/channel_jump.png         |  Bin 0 -> 87769 bytes
 icons/default/osdElements/channelgroup_bottom.png  |  Bin 0 -> 1877 bytes
 icons/default/osdElements/channelgroup_head.png    |  Bin 0 -> 1836 bytes
 .../osdElements/channelgroup_horiziontal.png       |  Bin 0 -> 31893 bytes
 .../osdElements/channelgroup_horizontal.png        |  Bin 0 -> 31893 bytes
 icons/default/osdElements/channelgroup_left.png    |  Bin 0 -> 1942 bytes
 icons/default/osdElements/channelgroup_right.png   |  Bin 0 -> 1789 bytes
 .../default/osdElements/channelgroup_vertical.png  |  Bin 0 -> 16921 bytes
 .../default/osdElements/channelgroups_vertical.png |  Bin 0 -> 19041 bytes
 .../osdElements/channellogoback_horizontal.png     |  Bin 0 -> 17836 bytes
 .../osdElements/channellogoback_vertical.png       |  Bin 0 -> 28204 bytes
 icons/default/osdElements/clock.png                |  Bin 0 -> 6001 bytes
 icons/default/osdElements/date_vertical.png        |  Bin 0 -> 19803 bytes
 icons/default/osdElements/grid_active_bottom.png   |  Bin 0 -> 3289 bytes
 icons/default/osdElements/grid_active_head.png     |  Bin 0 -> 3424 bytes
 .../default/osdElements/grid_active_horizontal.png |  Bin 0 -> 33656 bytes
 icons/default/osdElements/grid_active_left.png     |  Bin 0 -> 2524 bytes
 icons/default/osdElements/grid_active_right.png    |  Bin 0 -> 2527 bytes
 icons/default/osdElements/grid_active_vertical.png |  Bin 0 -> 100607 bytes
 icons/default/osdElements/grid_bottom.png          |  Bin 0 -> 2863 bytes
 icons/default/osdElements/grid_head.png            |  Bin 0 -> 2800 bytes
 icons/default/osdElements/grid_horizontal.png      |  Bin 0 -> 33304 bytes
 icons/default/osdElements/grid_left.png            |  Bin 0 -> 2462 bytes
 icons/default/osdElements/grid_right.png           |  Bin 0 -> 2389 bytes
 icons/default/osdElements/grid_vertical.png        |  Bin 0 -> 100766 bytes
 icons/default/osdElements/grids_vertical.png       |  Bin 0 -> 116790 bytes
 icons/default/osdElements/recmenu_background.png   |  Bin 0 -> 305292 bytes
 .../osdElements/statusheader_content_full.png      |  Bin 0 -> 262937 bytes
 .../osdElements/statusheader_content_windowed.png  |  Bin 0 -> 212247 bytes
 icons/default/osdElements/statusheader_tvframe.png |  Bin 0 -> 57459 bytes
 icons/default/osdElements/timeline1_horizontal.png |  Bin 0 -> 21401 bytes
 icons/default/osdElements/timeline1_vertical.png   |  Bin 0 -> 17751 bytes
 icons/default/osdElements/timeline2_horizontal.png |  Bin 0 -> 20310 bytes
 icons/default/osdElements/timeline2_vertical.png   |  Bin 0 -> 17650 bytes
 icons/default/recmenuicons/activetimer.png         |  Bin 0 -> 1731 bytes
 icons/default/recmenuicons/arrow_left.png          |  Bin 0 -> 1136 bytes
 icons/default/recmenuicons/arrow_right.png         |  Bin 0 -> 936 bytes
 icons/default/recmenuicons/delete_active.png       |  Bin 0 -> 768 bytes
 icons/default/recmenuicons/delete_inactive.png     |  Bin 0 -> 886 bytes
 icons/default/recmenuicons/edit_active.png         |  Bin 0 -> 2599 bytes
 icons/default/recmenuicons/edit_inactive.png       |  Bin 0 -> 2009 bytes
 icons/default/recmenuicons/icon_backspace.png      |  Bin 0 -> 1873 bytes
 icons/default/recmenuicons/icon_del_ins.png        |  Bin 0 -> 1532 bytes
 icons/default/recmenuicons/icon_shift.png          |  Bin 0 -> 1274 bytes
 icons/default/recmenuicons/info_active.png         |  Bin 0 -> 2421 bytes
 icons/default/recmenuicons/info_inactive.png       |  Bin 0 -> 1859 bytes
 icons/default/recmenuicons/no.png                  |  Bin 0 -> 1627 bytes
 icons/default/recmenuicons/record_active.png       |  Bin 0 -> 6736 bytes
 icons/default/recmenuicons/record_inactive.png     |  Bin 0 -> 3859 bytes
 icons/default/recmenuicons/search_active.png       |  Bin 0 -> 3426 bytes
 icons/default/recmenuicons/search_inactive.png     |  Bin 0 -> 2977 bytes
 icons/default/recmenuicons/yes.png                 |  Bin 0 -> 2655 bytes
 icons/recmenuicons/activetimer.png                 |  Bin 0 -> 1731 bytes
 icons/recmenuicons/arrow_left.png                  |  Bin 0 -> 1136 bytes
 icons/recmenuicons/arrow_right.png                 |  Bin 0 -> 936 bytes
 icons/recmenuicons/delete_active.png               |  Bin 0 -> 768 bytes
 icons/recmenuicons/delete_inactive.png             |  Bin 0 -> 886 bytes
 icons/recmenuicons/edit_active.png                 |  Bin 0 -> 2599 bytes
 icons/recmenuicons/edit_inactive.png               |  Bin 0 -> 2009 bytes
 icons/recmenuicons/icon_backspace.png              |  Bin 0 -> 1873 bytes
 icons/recmenuicons/icon_del_ins.png                |  Bin 0 -> 1532 bytes
 icons/recmenuicons/icon_shift.png                  |  Bin 0 -> 1274 bytes
 icons/recmenuicons/info_active.png                 |  Bin 0 -> 2421 bytes
 icons/recmenuicons/info_inactive.png               |  Bin 0 -> 1859 bytes
 icons/recmenuicons/no.png                          |  Bin 0 -> 1627 bytes
 icons/recmenuicons/record_active.png               |  Bin 0 -> 6736 bytes
 icons/recmenuicons/record_inactive.png             |  Bin 0 -> 3859 bytes
 icons/recmenuicons/search_active.png               |  Bin 0 -> 3426 bytes
 icons/recmenuicons/search_inactive.png             |  Bin 0 -> 2977 bytes
 icons/recmenuicons/yes.png                         |  Bin 0 -> 2655 bytes
 imagecache.c                                       |  715 +++++
 imagecache.h                                       |   92 +
 imageloader.c                                      |  179 +-
 imageloader.h                                      |   16 +-
 imagemagickwrapper.c                               |  162 ++
 imagemagickwrapper.h                               |   27 +
 imagescaler.c                                      |  149 +
 imagescaler.h                                      |   97 +
 messagebox.c                                       |  114 -
 messagebox.h                                       |   31 -
 osdmanager.c                                       |   68 +-
 osdmanager.h                                       |   23 +
 po/ca_ES.po                                        |  958 +++++++
 po/de_DE.po                                        |  882 +++++-
 po/ru_RU.po                                        |  955 +++++++
 po/sk_SK.po                                        |  955 +++++++
 recmanager.c                                       |  714 +++++
 recmanager.h                                       |   63 +
 recmenu.c                                          |  695 +++++
 recmenu.h                                          |   66 +
 recmenuitem.c                                      | 2902 ++++++++++++++++++++
 recmenuitem.h                                      |  684 +++++
 recmenumanager.c                                   |  893 ++++++
 recmenumanager.h                                   |   42 +
 recmenus.c                                         | 1561 +++++++++++
 recmenus.h                                         |  485 ++++
 searchtimer.c                                      |  570 ++++
 searchtimer.h                                      |  136 +
 services/epgsearch.h                               |  202 ++
 services/remotetimers.h                            |   33 +
 services/scraper2vdr.h                             |  194 ++
 setup.c                                            |  561 +++-
 setup.h                                            |  100 +-
 statusheader.c                                     |  142 +
 statusheader.h                                     |   25 +
 styledpixmap.c                                     |  233 +-
 styledpixmap.h                                     |   70 +-
 switchtimer.c                                      |  113 +
 switchtimer.h                                      |   31 +
 themes/tvguide-blue.theme                          |   53 +
 themes/tvguide-darkblue.theme                      |   28 +-
 themes/tvguide-darkred.theme                       |   53 +
 themes/tvguide-darkredNG.theme                     |   53 +
 themes/tvguide-default.theme                       |   65 +-
 themes/tvguide-green.theme                         |   53 +
 themes/tvguide-iceblue.theme                       |   51 +
 themes/tvguide-keepitsimple.theme                  |   49 +
 themes/tvguide-nOpacity.theme                      |   28 -
 themes/tvguide-nOpacitygreen.theme                 |   28 -
 timeline.c                                         |  334 ++-
 timeline.h                                         |   29 +-
 timer.c                                            |  200 +-
 timer.h                                            |   66 +-
 timerconflict.c                                    |  177 ++
 timerconflict.h                                    |   38 +
 tools.c                                            |  474 ++++
 tools.h                                            |   68 +
 tvguide.c                                          |  156 +-
 tvguideosd.c                                       | 1171 ++++----
 tvguideosd.h                                       |   48 +-
 view.c                                             | 1046 +++++++
 view.h                                             |  149 +
 227 files changed, 21820 insertions(+), 2518 deletions(-)

diff --git a/HISTORY b/HISTORY
index 3e346c4..6611bea 100644
--- a/HISTORY
+++ b/HISTORY
@@ -10,3 +10,131 @@ VDR Plugin 'tvguide' Revision History
 - Changed color buttons to nOpacity style
 - Changed channelheader to display transparent logos properly
 - Added "style nOpacity" for backgrounds and theme nOpacity
+
+2013-05-13: Version 0.0.3
+
+- Added dummy grids if no EPG information is available for a certain
+  time
+- Completely rewrote code for creation of epg grids for a channel column
+- Completely rewrote code for scrolling forward and backward in time
+- Added status header with epg information of currently selected 
+  schedule and scaled video picture
+
+2013-05-24: Version 0.0.4
+
+- Introduced horizontal display
+
+2013-06-01: Version 0.0.5
+
+- Added Theme DarkRed
+- Fixed some Bugs (position of video, deadlock)
+- Added Theme IceBlue
+- setup of usage of blending now done with clrDoBlending theme color
+  variable and not by setup
+- font color of active grid themable
+- avoided nasty font pixelation effects with theme iceblue
+- Display of channel groups
+- Buttons green / yellow can be configured to jump to prev / next channel
+  group
+- Added setup option to hide last channel group
+- Display of Main Menu Entry configurable
+- Eliminated setup option "Number of channels to jump", directly jump 
+  number of channel columns / rows with green / yellow
+- Added setup option to switch functionality of keys "Blue" and "OK"
+- Setup option to hide schedules time display in horizontal EPG grids
+
+2013-07-08: Version 0.0.6
+
+- added frame around scaled video picture
+- added theme "keep it simple" (thanks @saman)
+- display of additional EPG pictures in detailed epg view
+- Introduction of "Search & Recording" Menu
+- added possibility to replace original VDR schedules menu
+- changed channel jump logic
+- red button also available in detail view
+- page scrolling with keys left and right in detail view
+- added possibility to choose folder for instant recording, possible
+  folders are read from VDRs folders list
+- recording folder also choosable for series timers
+- blue button also available in detail view
+- color buttons displayed as configured in VDR
+- Added Setup Option to define if tvguide closes after channel switching
+- Added remotetimers support (thanks @Saman for providing a patch)
+- Pimped timeline
+
+2013-07-23: Version 1.0.0
+
+- added tvscraper support
+
+Version 1.1.0
+
+- changed build system
+- introduced image caching
+- introduced new "graphical" style
+- added new graphical default theme and theme darkred NG corresponding 
+  to nOpacity themes
+- using automatically configured nOpacity theme if available
+- adapted startup options to nOpacity startup options:
+  -e epgimages directory
+  -i icons directory
+  -l logo directory
+- changed detailed epg view using full screen, some further optimisations
+- search for <event_id>_0.jpg beside <event_id>.jpg as epg image
+- implemented GraphicsMagick compatibility (thanks @Manuel Reimer
+  for providing the patch)
+- changed Makefile to support both ImageMagick and GraphicsMagick
+  (configurable in Makefile)
+- Added russian and catalan translation
+- Added slovakian translation
+- fixed channel switching with blue key if detailed epg view is opened and
+  if "close tvguide on channel switch" is configured
+- fixed wrong font for clock in horizontal view
+- Added feature to jump to a specific channel with number keys
+- Fixed Bug 1484
+- Added Event Short Text (if available) to RecName (Closes Ticket 1490)
+- Fixed OSD Background Color (Closes Ticket 1474)
+- Rounded Corners for color buttons (Closes Ticket 1475)
+- Fixed some issues with text backgrounds in flat themes (closes 
+  Tickets 1480 and 1486)
+- Added possibility to search for reruns in case of a timer conflict
+- Added timer Timeline view in red button recording menu
+- Current channel positioned in middle of channellist when tvguide is 
+  opened
+- Added possibility to manage EPG Search Timers in red button recording 
+  menu
+- completely refactored recording menu
+- restructured detailöed EPG View that tv frame and status buttons 
+  are displayed
+- Favorites menu with EPG Search favorite timers with blue key
+- Display baseline for current time
+- Added possibility to create timer from favorites results
+- left / right scroll page up / down in recmenu result lists
+- Improved favorites menu with whats on now / next and up to four user
+  defined times
+- also check default paths when images and icons are loaded
+- directory for timers can be edited in timer edit menu
+- series recording can be configured in searchtimer menus
+- directory for searchtimers can be set and edited in searchtimer menus
+- set blue key favorite mode as new default
+
+Version 1.2.0
+
+- changed video directory choosage behaviour: added possibility to use 
+  a fixed recording dir which also supports epgsearch variables
+- fixed a bug when scrolling page up and the menu footer is active
+- order of search timers in search timer list in alphabetical order
+- changed order of actions on search timer menu items
+
+Version 1.2.1
+
+- changed event result lists that it is possible to scroll page up and
+  down directly with left / right. A recording is triggered now with the
+  red key.
+- Added possibility to create a recording from search timer result list
+- Set minimum time to display in Plugin Setup from 120 to 60 minutes
+- made order of search timer list case insensitive
+
+Version 1.2.2
+
+- added scraper2vdr support
+- introduced tabbed EPG detail view
diff --git a/Makefile b/Makefile
index df0ba33..27f6838 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,9 @@
 #
 # $Id$
 
+# External image lib to use: imagemagick, graphicsmagick	
+IMAGELIB = imagemagick
+
 # The official name of this plugin.
 # This name will be used in the '-P...' option of VDR to load the plugin.
 # By default the main source file also carries this name.
@@ -21,6 +24,7 @@ LIBDIR = $(call PKGCFG,libdir)
 LOCDIR = $(call PKGCFG,locdir)
 PLGCFG = $(call PKGCFG,plgcfg)
 VDRCONFDIR= $(call PKGCFG,configdir)
+PLGRESDIR = $(call PKGCFG,resdir)/plugins/$(PLUGIN)
 TMPDIR ?= /tmp
 
 ### The compiler options:
@@ -43,17 +47,19 @@ SOFILE = libvdr-$(PLUGIN).so
 
 ### Includes and Defines (add further entries here):
 
-INCLUDES += $(shell pkg-config --cflags-only-I Magick++)
-
 DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
-DEFINES += -DMAGICKCORE_HDRI_ENABLE=0
-DEFINES += -DMAGICKCORE_QUANTUM_DEPTH=16
 
-LIBS += $(shell pkg-config --libs Magick++)
+ifeq ($(IMAGELIB), imagemagick)
+	INCLUDES += $(shell pkg-config --cflags Magick++)
+	LIBS += $(shell pkg-config --libs Magick++)
+else ifeq ($(IMAGELIB), graphicsmagick)
+	INCLUDES += $(shell pkg-config --cflags GraphicsMagick++)
+	LIBS += $(shell pkg-config --libs GraphicsMagick++)
+endif
 
 ### The object files (add further files here):
 
-OBJS = $(PLUGIN).o
+OBJS = $(PLUGIN).o channelcolumn.o channelgroup.o channelgroups.o channeljump.o config.o detailview.o dummygrid.o epggrid.o fontmanager.o footer.o geometrymanager.o grid.o headergrid.o imagecache.o imageloader.o imagemagickwrapper.o imagescaler.o osdmanager.o recmanager.o recmenu.o recmenuitem.o recmenumanager.o recmenus.o searchtimer.o setup.o statusheader.o styledpixmap.o switchtimer.o timeline.o timer.o timerconflict.o tools.o tvguideosd.o view.o
 
 ### The main target:
 
@@ -100,6 +106,7 @@ i18n: $(I18Nmo) $(I18Npot)
 install-i18n: $(I18Nmsgs)
 
 ### Targets:
+
 $(SOFILE): $(OBJS)
 	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
 
@@ -110,7 +117,11 @@ install-themes:
 	@mkdir -p $(DESTDIR)$(VDRCONFDIR)/themes
 	cp themes/* $(DESTDIR)$(VDRCONFDIR)/themes
 
-install: install-lib install-i18n install-themes
+install-icons:
+	mkdir -p $(DESTDIR)$(PLGRESDIR)/icons
+	cp -r icons/* $(DESTDIR)$(PLGRESDIR)/icons
+		
+install: install-lib install-i18n install-themes install-icons
 
 dist: $(I18Npo) clean
 	@-rm -rf $(TMPDIR)/$(ARCHIVE)
diff --git a/Makefile-smaller-VDR1.7.34 b/Makefile-smaller-VDR1.7.34
deleted file mode 100644
index 49b84cc..0000000
--- a/Makefile-smaller-VDR1.7.34
+++ /dev/null
@@ -1,115 +0,0 @@
-#
-# Makefile for a Video Disk Recorder plugin
-#
-# $Id$
-
-# The official name of this plugin.
-# This name will be used in the '-P...' option of VDR to load the plugin.
-# By default the main source file also carries this name.
-# IMPORTANT: the presence of this macro is important for the Make.config
-# file. So it must be defined, even if it is not used here!
-#
-PLUGIN = tvguide
-
-### The version number of this plugin (taken from the main source file):
-
-VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ print $$6 }' | sed -e 's/[";]//g')
-
-### The C++ compiler and options:
-
-CXX      ?= g++
-CXXFLAGS ?= -g -O3 -Wall -Woverloaded-virtual -Wno-parentheses
-
-### The directory environment:
-
-VDRDIR ?= ../../..
-LIBDIR ?= ../../lib
-TMPDIR ?= /tmp
-
-### Make sure that necessary options are included:
-
-include $(VDRDIR)/Make.global
-
-### Allow user defined options to overwrite defaults:
-
--include $(VDRDIR)/Make.config
-
-### The version number of VDR's plugin API (taken from VDR's "config.h"):
-
-APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
-
-### The name of the distribution archive:
-
-ARCHIVE = $(PLUGIN)-$(VERSION)
-PACKAGE = vdr-$(ARCHIVE)
-
-### Includes and Defines (add further entries here):
-
-INCLUDES += -I$(VDRDIR)/include
-INCLUDES += -I/usr/include/ImageMagick
-
-DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
-
-### The object files (add further files here):
-
-OBJS = $(PLUGIN).o
-
-### The main target:
-
-all: libvdr-$(PLUGIN).so i18n
-
-### Implicit rules:
-
-%.o: %.c
-	$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
-
-### Dependencies:
-
-MAKEDEP = $(CXX) -MM -MG
-DEPFILE = .dependencies
-$(DEPFILE): Makefile
-	@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
-
--include $(DEPFILE)
-
-### Internationalization (I18N):
-
-PODIR     = po
-LOCALEDIR = $(VDRDIR)/locale
-I18Npo    = $(wildcard $(PODIR)/*.po)
-I18Nmsgs  = $(addprefix $(LOCALEDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file))))))
-I18Npot   = $(PODIR)/$(PLUGIN).pot
-
-%.mo: %.po
-	msgfmt -c -o $@ $<
-
-$(I18Npot): $(wildcard *.c)
-	xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --package-name=vdr-$(PLUGIN) --package-version=$(VERSION) --msgid-bugs-address='<see README>' -o $@ $^
-
-%.po: $(I18Npot)
-	msgmerge -U --no-wrap --no-location --backup=none -q $@ $<
-	@touch $@
-
-$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
-	@mkdir -p $(dir $@)
-	cp $< $@
-
-.PHONY: i18n
-i18n: $(I18Nmsgs) $(I18Npot)
-
-### Targets:
-
-libvdr-$(PLUGIN).so: $(OBJS)
-	$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) -lMagick++ -o $@
-	@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
-
-dist: $(I18Npo) clean
-	@-rm -rf $(TMPDIR)/$(ARCHIVE)
-	@mkdir $(TMPDIR)/$(ARCHIVE)
-	@cp -a * $(TMPDIR)/$(ARCHIVE)
-	@tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE)
-	@-rm -rf $(TMPDIR)/$(ARCHIVE)
-	@echo Distribution package created as $(PACKAGE).tgz
-
-clean:
-	@-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot
diff --git a/README b/README
index 1003a21..3047018 100644
--- a/README
+++ b/README
@@ -2,9 +2,9 @@ This is a "plugin" for the Video Disk Recorder (VDR).
 
 Written by:                  Louis Braun <louis DOT braun AT gmx DOT de>
 
-Project's homepage:          URL
+Project's homepage:          http://projects.vdr-developer.org/projects/plg-tvguide 
 
-Latest version available at: URL
+Latest version available at: http://projects.vdr-developer.org/projects/plg-tvguide/files
 
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
@@ -15,36 +15,68 @@ See the file COPYING for more information.
 Requirements
 ------------
 
-- VDR version >= 1.7.17 (TrueColor OSD is mandatorily needed)
-
-- Installed ImageMagick for showing png/jpg Channel Logos and EPG Images
+- Clone Git Repository: git clone git://projects.vdr-developer.org/vdr-plugin-tvguide.git
+- VDR version >= 2.0.0
+- Installed ImageMagick or GraphiksMagick for showing png/jpg Channel Logos, EPG Images 
+  and menu icons
+- for scaling the video picture to fit into the VDR menu window please use
+  softhddevice plugin revision 87c1c7be (2013-01-01) or newer.
+- Installed epgsearch Plugin for extended search & recording features.
+- Installed remotetimers Plugin for creating timers on a vdr server remotely from a 
+  vdr client.
 
 
 Description
 -----------
 
-"TvGuide" is a highly customizable 2D EPG viewer plugin.
+"TvGuide" is a highly customizable 2D EPG viewer plugin. The "Search & Recordings"
+Menü provided by the red button allows to search in the EPG and manage timers,
+search timers, series timers and switch timers in an convenient way.  
 
 Installation
 ------------
 
-After "normal" Plugin installation copy the themes from 
+After "normal" Plugin installation you have to care about the paths for the
+used Icons, the channel logos and epg images. The following paths can be set
+at startup:
 
-/put/your/path/here/VDR/PLUGINS/src/tvguide/themes/
+-l path, --logodir=path
+    Path to the logos (Default: <ResourceDirectory>/plugins/tvguide/channellogos/).
 
-to
+-e path, --epgimages=path
+    Path to the epgimages (Default: <CacheDirectory>/plugins/tvguide/epgimages/).
 
-VDRCONF/themes/
+-i path, --icons=path
+    Path to the icons directory (Default: <ResourceDirectory>/plugins/tvguide/epgimages/).
 
-Options
--------
+<ResourceDirectory> and <CacheDirectory> is taken from your VDR configuration 
+(make.config or vdr.pc).
 
--l path, --logodir=path
-    Path to the logos (Default: <vdrconfdir>/plugins/tvguide/channellogos/).
+During a "make install" the Icons are automatically copied from <PlgSourceDirectory>/icons/
+to the default path. Included Theme files are also copied from <PlgSourceDirectory>/themes/
+to <ConfigDirectory>/themes/
+
+If directories for channel logos or icons are set via startup 
+parameters, images are searched first in these directories. If the image
+is not available, an additional search in the according default directory
+will be performed.
+
+I recommend to use channel logos from https://github.com/3PO/Senderlogos
+To download them just change in the directory you want to place the logos
+and do a:
 
--i path, --epgimages=path
-    Path to the epgimages (Default: <vdrconfdir>/plugins/tvguide/epgimages/).
+git clone https://github.com/3PO/Senderlogos.git logos
 
+An update of the logos can then be done with a "git pull" just inside this
+directory.
+
+For S2-6400 Users: Disable High Level OSD, otherwise the plugin will not be
+loaded because lack of true color support
+
+For Xine-Plugin Users: Set "Blend scaled Auto" as OSD display mode to achieve
+an suitable true color OSD.
+
+For Xineliboutput Users: Start vdr-sxfe with the --hud option enabled
 
 Usage
 -----
@@ -54,79 +86,192 @@ Remote Control Keys:
 Up/Down/Left/Right:    Navigation in the EPG grid
 Ok:                    Detailed EPG View of the selected grid
                        2nd Ok closes the detailed view
-Red:                   Set recording timer for the currently selected grid
+Red:                   Search & Recording Menu
 Green / Yellow:	       Jump (default) five channels back / forward
-Blue:                  Switch to currently selected channel
+Blue:                  Depends on configured Mode:
+                       Default: Favorites Menu, Switch to channel in 
+                       detailed EPG View
+                       Optional: Switch to currently selected channel
+                       Optional: Open detailed EPG view (OK switches
+                       then to channel)
+
+Numeric Keys: If Setup Option "Functionality of numeric Keys" is configured
+to "Jump to specific channel", the numeric keys are used for channel number
+input. If "Timely Jump" is configured, the keys are used as follows:
+
 1 / 3:                 Big jump (default 3h) back / forward in time
 4 / 6:                 huge jump (default 24h) back / forward in time
 7 / 9:                 jump to previous / next prime time (8pm)
+
 Exit:                  closes plugin
 
+In Search & Recording menu the following options are available:
+
+- Instant Record: create a timer for the currently selected program. An
+  check for timer conflicts will be performed, if a timer conflict occurs,
+  the involved timers can be adapted to solve the conflict. Alternatively
+  reruns can be searched and used to solve timer conflicts. 
+- Delete / Edit Timer: if a timer already exists for the currently selected
+  broadcast, this timer can be deleted or edited.
+- Timer Timeline: displays active timers per day
+- Create Search Timer: create an search timer with epgsearch. The most
+  important options can be defined directly in the menu, expert options
+  are available via the "advanced options" button.
+- Manage Search Timers: edit, delete and check results of search timers  
+- Create Series Timer: create a periodical timer for a dedicated time on
+  dedicated days.
+- Create Switch Timer: create a switch timer for the currently selected
+  program.
+- Search: search with epgsearch
+- Check for Timer Conflicts: check for timer conflicts with epgsearch.
+- Search in Recordings: check if a recording already exists for the currently
+  selected program.
+
+The search & recordings menu is intended to present a convenient interface
+to different VDR core recording features and additional epgsearch features.
+The main goal is to reach better usability for "non expert users".
+
+The navigation through the search & recording menu can be done easily with
+up/down, left/right and the ok key. In scrolling lists, with left/right
+(after the first/last option of the displayed list element is selected) you
+jump to the next page of the list. Pressing up on the first / down on the 
+last list item jumpps to the end / start of the list.
+
+In the Plugin Setup Menu in Section "Recording Menus and Favorites" you can
+choose three alternatives for the option "Folder for instant Recordings":
+- "Always use root video folder": the recording will always be placed in the
+  video root folder
+- "Select from folder list": before creating a timer, you'll get asked in which
+  directory the recording should be placed. If the epgsearch plugin is not 
+  available, the entries from VDRs <VDRCONFIG>/folders.conf will be used. If
+  the epgsearch plugin is available, the more sophisticated epgsearch mechanism
+  will be used to identify the possible folders (folders from 
+  <VDRCONFIG>/folders.conf and epgsearchfolders.conf and all already existing 
+  folders in the video directory).
+- "Use fixed folder": the configured folder will always be used. If this string
+  is a epgsearch variable ("%variable%"), epgsearch will be used to replace 
+  the variable with a concrete folder. All values defined in the epgsearch config
+  file "epgsearchuservars.conf" can be used. These variables use the definitions
+  from "epgsearchcats.conf". For a detailed description see the epgsearch Manual.
+  With that and a with an EPG with detailed information about movies and series 
+  it is possible to create sophisticated paths for timers automatically (for 
+  instance with series season and episode in the filename).   
+
+For a search timer also all folders and the defined dedicated folder can be used.
+
+Favorites Menu: if configured, the blue key provides a favorite menu. In this
+menu the current scheduling ("What's on now") and the next upcomming Shows 
+("What's on next") can be listed. Via the Plugin Setup Menu up to four user 
+defined times can be configured with a dedicated description (for instance 
+"Primetime" for 8:15 pm). These user defined times are also shown as options in 
+the favorites menu. Finally all search timers with the option "use as favorite" 
+enabled are displayed in the favorites menu. By selecting this entry, all hits
+for this search timer are shown.
 
 Setup Options
 -------------
 
-* General:
-
-- Number of Channels / Columns:				
-  Number of columns per screen (max. 8)
-  Keep in mind that the True Color OSD displays 64 Pixmaps in maximum, and each EPG
-  entry is a dedicated Pixmap. So if this value is too large, maybe not all EPG
-  information is shown on the screen.
-
-- Channel Jump (Keys Green / Yellow):
-  Number of channels to jump back / forward, counted from the currently selected
-  channel (channel to which the selected EPG entry belongs)
-
-- Time to display vertically in minutes
-  With this value the number of minutes per screen is determinated. The value is
-  an approximately value, because rounded values are used during calculation.
-  int((OSD Height - Header Height - Footer Height) / value) 
-  --> Number of Pixel for one minute
-
+* General Settings:
+
+- Show Main Menu Entry
+  Display "tvguide" in main menu
+- Replace VDR Schedules Menu
+  If set to "yes", the original VDR schedules menu will be replaced by tvguide
+- Use appropriate nOpacity Theme: if nOpacity is configured as VDR skin, you can 
+  configure TVGuide to select the choosen nOpacity theme automatically also as 
+  TVGuide theme. If the appropriate theme is not avaiable, the default theme
+  will be used. If set to "no", you can configure the theme independend of
+  nOpacity
+  - Theme: nOpacity independent theme to use
+- Time to display in minutes: period of time to display in main EPG view
+- Rounded Corners
+  Use rounded corners for displayed boxes
+- Channel Jump Mode (Keys Green / Yellow)
+  select between jumping x channels back/forward or to the previous / next 
+  channel group
+- Keys Blue and OK
+  Blue: Favorites in normal view, channel switch in det. EPG View, Ok: det. EPG View
+  or 
+  Blue: Channel Switch, Ok: Detailed EPG 
+  or
+  Blue: Detailed EPG, Ok: Channel Switch
+- Close TVGuide after channel switch: If set to "no", tvguide will not be closed
+  after a channel switch.
+- Functionality of numeric Keys: see chapter Usage / Remote Control Keys
+- Hide last Channel Group
+  If set to yes, the channels of the last channel group will not be displayed
 - Big Step (Keys 1 / 3) in hours
-  Hours to jump vertically with keys 1 / 3    
-
+  Hours to jump vertically with keys 1 / 3
 - Huge Step (Keys 4 / 6) in hours
   Hours to jump vertically with keys 4 / 6
-
 - Time Format (12h/24h)
-  Switching between 12h and 24h time format
-  
-* Screen Layout:
-
-- Theme
-  Used Theme, theme files have to be placed accordingly
-  
-- Width of left Time Column
-  Width of almost left column in Pixel
-  
-- Height of Header (Channel Logos)
-  Height of header row in Pixel
-  
-- Height of Footer (Buttons)
-  Height of footer with color buttons in Pixel
-  
-- Show Channel Logos	
+- Display Reruns in detailed EPG View
+
+* Screen Presentation:
+
+- Display Mode
+  Choose between horizontal or vertical display of the channels. All further
+  width / height settings are dependend of this setting
+- Width/Height of Channel Header (% of osd width/height)
+- Width/Height of Timeline (% of osd width/height)
+- Number of Channels to display
+- Height of Headers (Status Header and EPG View Header, % of osd height)
+- Height of Footer
+- Display status header
+  - Scale video to upper right corner
+  - Rounded corners around video frame
+- Display channel names in Header
+- Display channel groups
+  - Width/Height of channel groups (% of osd width/height)
+- Display current time baseline
+- Show Channel Logos
   show / hide channel logos, if logos are shown:
   - Logo Extension
     jpg / png
-  - Logo width
-    in Pixel
-  - Logo height
-    in Pixel
-	
+  - Logo width ratio
+  - Logo height ratio
+- Text Border in Detailed EPG View (in pixel)
 - Show EPG Images
   show / hide EPG images, if images are shown:
-  - EPG Image width
-    in Pixel
-  - EPG Image height
-    in Pixel
+  - EPG Image width ratio
+  - EPG Image height ratio
+  - Number of additional EPG Images: number of additional EPG
+    images displayed at the bottom of the detailed EPG view.
+  - Additional EPG Image width (in Pixel)
+  - Additional EPG Image height (in Pixel)
 	
 * Fonts and Fontsizes:
 
 - Font:
   Used Font, all Fonts installed on your system are shown
-- various font sizes:
-  Size in Pixel used for described purpose
-
+- adjust various font sizes:
+  the defined value is added to / subtracted from the default font size
+
+* Recording Menus and Favorites
+
+- Folder for instant Recordings: (see chapter "Usage" for detailed description)
+  - Always use root video folder
+  - Select from folder list
+  - Use fixed folder
+- Use Remotetimers: Timers are handled not locally but on a VDR Server defined
+  with the remotetimers plugin.
+- Use "What's on now" in favorites
+- Use "What's on next" in favorites
+- Use user defined time 1 (to 4) in favorites
+  - Description (1 - 4)
+  - Time (1 - 4)
+- Limit channels in favorites: if set to yes, only the configured channel range
+  is used to display favorite results (except for search timer favorites)
+  - start channel
+  - stop channel
+
+* Image Caching
+
+- Create Log Messages for image loading: enable debug messages for image loading
+- Limit Logo Cache: if set to "no", every channel logo is cached. if set to "yes",
+  only the amount configured for "Maximal number of logos to cache" is cached, all
+  other logos are always loaded "on the fly"
+  - Maximal number of logos to cache
+- Number of  logos to cache at start: number of logos to pre cache at plugin startup
+  (a too large number causes a slower VDR start)
+- Information about image cache sizes
\ No newline at end of file
diff --git a/channelcolumn.c b/channelcolumn.c
index 5590ce3..c23fbe6 100644
--- a/channelcolumn.c
+++ b/channelcolumn.c
@@ -1,283 +1,367 @@
 #include "channelcolumn.h"
+#include "dummygrid.h"
 
-cChannelColumn::cChannelColumn(int num, cChannel *channel, cMyTime *myTime) {
-	this->channel = channel;
-	this->num = num;
-	this->myTime = myTime;
-	hasTimer = channel->HasTimer();
+cChannelColumn::cChannelColumn(int num, const cChannel *channel, cMyTime *myTime) {
+    this->channel = channel;
+    this->num = num;
+    this->myTime = myTime;
+    hasTimer = channel->HasTimer();
+    hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);
+    schedulesLock = new cSchedulesLock(false, 100);
+    header = NULL;
 }
 
 cChannelColumn::~cChannelColumn(void) {
-    osdManager.releasePixmap(pixmapLogo, cString::sprintf("channelcolumn logo %s", channel->Name()));
-	grids.Clear();
+    if (header)
+        delete header;
+    grids.Clear();
+    delete schedulesLock;
 }
 
 void cChannelColumn::clearGrids() {
-	grids.Clear();
+    grids.Clear();
 }
 
 void cChannelColumn::createHeader() {
-    color = theme.Color(clrHeader);
-    colorBlending = theme.Color(clrHeaderBlending);
-    caller = cString::sprintf("channelcolumn %s", channel->Name());
-    pixmap = osdManager.requestPixmap(2, cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight),
-                                         cRect::Null, *caller);
-	if (!pixmap) {
-		return;
-	}
-    pixmapLogo = osdManager.requestPixmap(3, cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight),
-                                             cRect::Null, *caller);
-    if (!pixmapLogo) {
-		return;
-	}
-    pixmapLogo->Fill(clrTransparent);
-
-	drawBackground();
-	cTextWrapper tw;
-	cString headerText = cString::sprintf("%d - %s", channel->Number(), channel->Name());
-	tw.Set(*headerText, tvguideConfig.FontHeader, tvguideConfig.colWidth - 8);
-	int lines = tw.Lines();
-	int lineHeight = tvguideConfig.FontHeader->Height();
-	int yStart = (tvguideConfig.headerHeight - lines*lineHeight)/2 + 8;
-
-	if (!tvguideConfig.hideChannelLogos) {
-		cImageLoader imgLoader;
-		if (imgLoader.LoadLogo(channel->Name())) {
-				cImage logo = imgLoader.GetImage();
-				int logoX = (tvguideConfig.colWidth - tvguideConfig.logoWidth)/2;
-				pixmapLogo->DrawImage(cPoint(logoX, 5), logo);
-		}
-		yStart = tvguideConfig.logoHeight + 8;
-	}
-	for (int i=0; i<lines; i++) {
-		int textWidth = tvguideConfig.FontHeader->Width(tw.GetLine(i));
-		int xText = (tvguideConfig.colWidth - textWidth) / 2;
-		if (xText < 0) 
-			xText = 0;
-		pixmap->DrawText(cPoint(xText, yStart + i*lineHeight), tw.GetLine(i), theme.Color(clrFontHeader), clrTransparent, tvguideConfig.FontHeader);
-	}
-	drawBorder();
+    header = new cHeaderGrid();
+    header->createBackground(num);
+    header->drawChannel(channel);
 }
 
 void cChannelColumn::drawHeader() {
-	pixmap->SetViewPort(cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight));
-	pixmapLogo->SetViewPort(cRect(tvguideConfig.timeColWidth + num*tvguideConfig.colWidth, 0, tvguideConfig.colWidth, tvguideConfig.headerHeight));
+    header->setPosition(num);
 }
 
 bool cChannelColumn::readGrids() {
-	schedules = cSchedules::Schedules(schedulesLock);
-	const cSchedule *Schedule = NULL;
-	Schedule = schedules->GetSchedule(channel);
-	if (!Schedule) {
-		return false;
-	}
-	bool eventFound = false;
-	const cEvent *event = Schedule->GetEventAround(myTime->GetStart());
-	if (event != NULL) {
-		eventFound = true;
-	} else {
-		for (int i=1; i<6; i++) {
-			event = Schedule->GetEventAround(myTime->GetStart()+i*5*60);
-			if (event) {
-				eventFound = true;
-				break;
-			}
-		}
-	} 
-	if (eventFound) {
-		bool col = true;
-		for (; event; event = Schedule->Events()->Next(event)) {
-			cEpgGrid *grid = new cEpgGrid(this, event);
-			grid->setText();
-			grid->SetColor(col);
-			col = !col;
-			grids.Add(grid);
-			if (event->EndTime() > myTime->GetStop()) {
-				break;
-			}
-		}
-		return true;
-	} else {
-		return false;
-	}
-	
+    schedules = cSchedules::Schedules(*schedulesLock);
+    const cSchedule *Schedule = NULL;
+    Schedule = schedules->GetSchedule(channel);
+    if (!Schedule) {
+        addDummyGrid(myTime->GetStart(), myTime->GetEnd(), NULL, false);
+        return true;
+    }
+    bool eventFound = false;
+    bool dummyAtStart = false;
+    const cEvent *startEvent = Schedule->GetEventAround(myTime->GetStart());
+    if (startEvent != NULL) {
+        eventFound = true;
+    } else {
+        for (int i=1; i<6; i++) {
+            startEvent = Schedule->GetEventAround(myTime->GetStart()+i*5*60);
+            if (startEvent) {
+                eventFound = true;
+                dummyAtStart = true;
+                break;
+            }
+        }
+    } 
+    if (eventFound) {
+        bool col = true;
+        if (dummyAtStart) {
+            addDummyGrid(myTime->GetStart(), startEvent->StartTime(), NULL, col);
+            col = !col;
+        }
+        bool dummyNeeded = true;
+        bool toFarInFuture = false;
+        time_t endLast = myTime->GetStart();
+        const cEvent *event = startEvent;
+        const cEvent *eventLast = NULL;
+        for (; event; event = Schedule->Events()->Next(event)) {
+            if (endLast < event->StartTime()) {
+                //gap, dummy needed
+                time_t endTime = event->StartTime();
+                if (endTime > myTime->GetEnd()) {
+                    endTime = myTime->GetEnd();
+                    toFarInFuture = true;
+                }
+                addDummyGrid(endLast, endTime, NULL, col);
+                col = !col;
+            }
+            if (toFarInFuture) {
+                break;
+            }
+            addEpgGrid(event, NULL, col);
+            col = !col;
+            endLast = event->EndTime();
+            if (event->EndTime() > myTime->GetEnd()) {
+                dummyNeeded = false;
+                break;
+            }
+            eventLast = event;
+        }
+        if (dummyNeeded) {
+            addDummyGrid(eventLast->EndTime(), myTime->GetEnd(), NULL, col);
+        }
+        return true;
+    } else {
+        addDummyGrid(myTime->GetStart(), myTime->GetEnd(), NULL, false);
+        return true;
+    }
+    return false;
 }
 
 void cChannelColumn::drawGrids() {
-	for (cEpgGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
-		grid->SetViewportHeight();
-		grid->PositionPixmap();
-		grid->Draw();
-	}
+    for (cGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
+        grid->SetViewportHeight();
+        grid->PositionPixmap();
+        grid->Draw();
+    }
 }
 
 int cChannelColumn::getX() {
-	return tvguideConfig.timeColWidth + num*tvguideConfig.colWidth;
+    return geoManager.timeLineWidth + num*geoManager.colWidth;
+}
+
+int cChannelColumn::getY() {
+    return geoManager.statusHeaderHeight +  geoManager.timeLineHeight + num*geoManager.rowHeight;
 }
 
-cEpgGrid * cChannelColumn::getActive() {
-	cMyTime t;
-	t.Now();
-	for (cEpgGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
-		if (grid->isActiveInitial(t.Get()))
-			return grid;
-	}
-	return grids.First();
+cGrid * cChannelColumn::getActive() {
+    cMyTime t;
+    t.Now();
+    for (cGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
+        if (grid->Match(t.Get()))
+            return grid;
+    }
+    return grids.First();
 }
 
-cEpgGrid * cChannelColumn::getNext(cEpgGrid *activeGrid) {
-	if (activeGrid == NULL)
-		return NULL;
-	cEpgGrid *next = grids.Next(activeGrid);
-	if (next)
-		return next;
-	return NULL;
+cGrid * cChannelColumn::getNext(cGrid *activeGrid) {
+    if (activeGrid == NULL)
+        return NULL;
+    cGrid *next = grids.Next(activeGrid);
+    if (next)
+        return next;
+    return NULL;
 }
 
-cEpgGrid * cChannelColumn::getPrev(cEpgGrid *activeGrid) {
-	if (activeGrid == NULL)
-		return NULL;
-	cEpgGrid *prev = grids.Prev(activeGrid);
-	if (prev)
-		return prev;
-	return NULL;
+cGrid * cChannelColumn::getPrev(cGrid *activeGrid) {
+    if (activeGrid == NULL)
+        return NULL;
+    cGrid *prev = grids.Prev(activeGrid);
+    if (prev)
+        return prev;
+    return NULL;
 }
 
-cEpgGrid * cChannelColumn::getNeighbor(cEpgGrid *activeGrid) {
-	if (!activeGrid)
-		return NULL;
-	cEpgGrid *neighbor = NULL;
-	int overlap = 0;
-	int overlapNew = 0;
-	cEpgGrid *grid = NULL;
-	grid = grids.First();
-	if (grid) {
-		for (; grid; grid = grids.Next(grid)) {
-			if ( (grid->StartTime() == activeGrid->StartTime()) ) {
-				neighbor = grid;
-				break;
-			}
-			overlapNew = activeGrid->calcOverlap(grid);
-			if (overlapNew > overlap) {
-				neighbor = grid;
-				overlap = overlapNew;
-			}
-		}
-	}
-	if (!neighbor)
-		neighbor = grids.First();
-	return neighbor;
+cGrid * cChannelColumn::getNeighbor(cGrid *activeGrid) {
+    if (!activeGrid)
+        return NULL;
+    cGrid *neighbor = NULL;
+    int overlap = 0;
+    int overlapNew = 0;
+    cGrid *grid = NULL;
+    grid = grids.First();
+    if (grid) {
+        for (; grid; grid = grids.Next(grid)) {
+            if ( (grid->StartTime() == activeGrid->StartTime()) ) {
+                neighbor = grid;
+                break;
+            }
+            overlapNew = activeGrid->calcOverlap(grid);
+            if (overlapNew > overlap) {
+                neighbor = grid;
+                overlap = overlapNew;
+            }
+        }
+    }
+    if (!neighbor)
+        neighbor = grids.First();
+    return neighbor;
+}
+
+bool cChannelColumn::isFirst(cGrid *grid) {
+    if (grid == grids.First())
+        return true;
+    return false;
 }
 
 void cChannelColumn::AddNewGridsAtStart() {
-	cEpgGrid *firstGrid = NULL;
-	firstGrid = grids.First();
-	if (firstGrid == NULL) {
-		//no epg, completely new.
-		schedules = cSchedules::Schedules(schedulesLock);
-		const cSchedule *Schedule = NULL;
-		Schedule = schedules->GetSchedule(channel);
-		if (!Schedule)
-			return;
-		const cEvent *event = Schedule->GetEventAround(myTime->GetStart());
-		if (!event)
-			return;
-		cEpgGrid *grid = new cEpgGrid(this, event);
-		grid->setText();
-		grid->SetColor(true);
-		grids.Ins(grid, grids.First());
-		return;
-	} else {
-		//if first event is long enough, nothing to do.
-		if (firstGrid->StartTime() <= myTime->GetStart()) {
-			return;
-		}
-		//if not, i have to add new ones to the list
-		schedules = cSchedules::Schedules(schedulesLock);
-		const cSchedule *Schedule = NULL;
-		Schedule = schedules->GetSchedule(channel);
-		if (!Schedule)
-			return;
-		bool col = !(firstGrid->IsColor1());
-		for (const cEvent *event = Schedule->GetEventAround(firstGrid->StartTime()-60); event; event = Schedule->Events()->Prev(event)) {
-			if (!event)
-				return;
-			cEpgGrid *grid = new cEpgGrid(this, event);
-			grid->setText();
-			grid->SetColor(col);
-			col = !col;
-			grids.Ins(grid, firstGrid);
-			firstGrid = grid;
-			if (event->StartTime() <= myTime->GetStart()) {
-				break;
-			}
-		}
-	}
+    cGrid *firstGrid = NULL;
+    firstGrid = grids.First();
+    if (firstGrid == NULL)
+        return;
+    //if first event is long enough, nothing to do.
+    if (firstGrid->StartTime() <= myTime->GetStart()) {
+        return;
+    }
+    //if not, i have to add new ones to the list
+    schedules = cSchedules::Schedules(*schedulesLock);
+    const cSchedule *Schedule = NULL;
+    Schedule = schedules->GetSchedule(channel);
+    if (!Schedule) {
+        if (firstGrid->isDummy()) {
+            firstGrid->SetStartTime(myTime->GetStart());
+            firstGrid->SetEndTime(myTime->GetEnd());
+        }
+        return;
+    }
+    bool col = !(firstGrid->IsColor1());
+    bool dummyNeeded = true;
+    for (const cEvent *event = Schedule->GetEventAround(firstGrid->StartTime()-60); event; event = Schedule->Events()->Prev(event)) {
+        if (!event)
+            break;
+        if (event->EndTime() < myTime->GetStart()) {
+            break;
+        }
+        cGrid *grid = addEpgGrid(event, firstGrid, col);
+        col = !col;
+        firstGrid = grid;
+        if (event->StartTime() <= myTime->GetStart()) {
+            dummyNeeded = false;
+            break;
+        }
+    }
+    if (dummyNeeded) {
+        firstGrid = grids.First();
+        if (firstGrid->isDummy()) {
+            firstGrid->SetStartTime(myTime->GetStart());
+            if (firstGrid->EndTime() >= myTime->GetEnd())
+                firstGrid->SetEndTime(myTime->GetEnd());
+        } else {
+            addDummyGrid(myTime->GetStart(), firstGrid->StartTime(), firstGrid, col);
+        }
+    }
 }
 
 void cChannelColumn::AddNewGridsAtEnd() {
-	cEpgGrid *lastGrid = NULL;
-	lastGrid = grids.Last();
-	if (lastGrid == NULL)
-		return;
-	//if last event is long enough, nothing to do.
-	if (lastGrid->EndTime() > myTime->GetStop()) {
-		return;
-	}
-	//if not, i have to add new ones to the list
-	schedules = cSchedules::Schedules(schedulesLock);
-	const cSchedule *Schedule = NULL;
-	Schedule = schedules->GetSchedule(channel);
-	if (!Schedule)
-		return;
-	bool col = !(lastGrid->IsColor1());
-	for (const cEvent *event = Schedule->GetEventAround(lastGrid->EndTime()+60); event; event = Schedule->Events()->Next(event)) {
-		if (!event)
-			return;
-		cEpgGrid *grid = new cEpgGrid(this, event);
-		grid->setText();
-		grid->SetColor(col);
-		col = !col;
-		grids.Add(grid);
-		if (event->EndTime() > myTime->GetStop()) {
-			break;
-		}
-	}
+    cGrid *lastGrid = NULL;
+    lastGrid = grids.Last();
+    if (lastGrid == NULL)
+        return;
+    //if last event is long enough, nothing to do.
+    if (lastGrid->EndTime() >= myTime->GetEnd()) {
+        return;
+    }
+    //if not, i have to add new ones to the list
+    schedules = cSchedules::Schedules(*schedulesLock);
+    const cSchedule *Schedule = NULL;
+    Schedule = schedules->GetSchedule(channel);
+    if (!Schedule) {
+        if (lastGrid->isDummy()) {
+            lastGrid->SetStartTime(myTime->GetStart());
+            lastGrid->SetEndTime(myTime->GetEnd());
+        }
+        return;
+    }
+    bool col = !(lastGrid->IsColor1());
+    bool dummyNeeded = true;
+    for (const cEvent *event = Schedule->GetEventAround(lastGrid->EndTime()+60); event; event = Schedule->Events()->Next(event)) {
+        if (!event)
+            break;
+        if (event->StartTime() > myTime->GetEnd()) {
+            break;
+        }
+        addEpgGrid(event, NULL, col);
+        col = !col;
+        if (event->EndTime() > myTime->GetEnd()) {
+            dummyNeeded = false;
+            break;
+        }
+    }
+    if (dummyNeeded) {
+        lastGrid = grids.Last();
+        if (lastGrid->isDummy()) {
+            lastGrid->SetEndTime(myTime->GetEnd());
+            if (lastGrid->StartTime() <= myTime->GetStart())
+                lastGrid->SetStartTime(myTime->GetStart());
+        } else {
+            addDummyGrid(lastGrid->EndTime(), myTime->GetEnd(), NULL, col);
+        }
+    }
 }
 
 void cChannelColumn::ClearOutdatedStart() {
-	bool goOn = true;
-	cEpgGrid *firstGrid = NULL;
-	while (goOn) {
-		firstGrid = grids.First();	
-		if ((firstGrid != NULL)&&(firstGrid->EndTime() < myTime->GetStart())) {
-			grids.Del(firstGrid);
-			firstGrid = NULL;
-		} else {
-			goOn = false;
-		}
-	}
+    cGrid *firstGrid = NULL;
+    while (true) {
+        firstGrid = grids.First();
+        if (!firstGrid)
+            break;
+        if (firstGrid->EndTime() <= myTime->GetStart()) {
+            grids.Del(firstGrid);
+            firstGrid = NULL;
+        } else {
+            if (firstGrid->isDummy()) {
+                firstGrid->SetStartTime(myTime->GetStart());
+                cGrid *next = getNext(firstGrid);
+                if (next) {
+                    firstGrid->SetEndTime(next->StartTime());
+                } else {
+                    firstGrid->SetEndTime(myTime->GetEnd());
+                }
+            }
+            break;
+        }
+    }
 }
 
 void cChannelColumn::ClearOutdatedEnd() {
-	bool goOn = true;
-	cEpgGrid *lastGrid = NULL;
-	while (goOn) {
-		lastGrid = grids.Last();	
-		if ((lastGrid != NULL)&&(lastGrid->StartTime() > myTime->GetStop())) {
-			grids.Del(lastGrid);
-			lastGrid = NULL;
-		} else {
-			goOn = false;
-		}
-	}
+    cGrid *lastGrid = NULL;
+    while (true) {
+        lastGrid = grids.Last();    
+        if (!lastGrid)
+            break;
+        if (lastGrid->StartTime() >= myTime->GetEnd()) {
+            grids.Del(lastGrid);
+            lastGrid = NULL;
+        } else {
+            if (lastGrid->isDummy()) {
+                lastGrid->SetEndTime(myTime->GetEnd());
+                cGrid *prev = getPrev(lastGrid);
+                if (prev) {
+                    lastGrid->SetStartTime(prev->EndTime());
+                } else {
+                    lastGrid->SetStartTime(myTime->GetStart());
+                }
+            }
+            break;
+        }
+    }
 }
 
-void cChannelColumn::dumpGrids() {
-	esyslog("------Channel %s ---------", channel->Name());
-	
-	for (cEpgGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
-		grid->debug();
-	}
-	
+cGrid *cChannelColumn::addEpgGrid(const cEvent *event, cGrid *firstGrid, bool color) {
+    cGrid *grid = new cEpgGrid(this, event);
+    grid->setText();
+    grid->SetColor(color);
+    if (!firstGrid)
+        grids.Add(grid);
+    else
+        grids.Ins(grid, firstGrid);
+    return grid;
 }
+
+cGrid *cChannelColumn::addDummyGrid(time_t start, time_t end, cGrid *firstGrid, bool color) {
+    cGrid *dummy = new cDummyGrid(this, start, end);
+    dummy->setText();
+    dummy->SetColor(color);
+    if (!firstGrid)
+        grids.Add(dummy);
+    else
+        grids.Ins(dummy, firstGrid);
+    return dummy;
+}
+
+void cChannelColumn::SetTimers() {
+    hasTimer = channel->HasTimer();
+    hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);
+    for (cGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
+        bool gridHadTimer = grid->HasTimer();
+        grid->SetTimer();
+        if (gridHadTimer != grid->HasTimer())
+            grid->SetDirty();
+        bool gridHadSwitchTimer = grid->HasSwitchTimer();
+        grid->SetSwitchTimer();
+        if (gridHadSwitchTimer != grid->HasSwitchTimer())
+            grid->SetDirty();
+        grid->Draw();
+    }
+}
+
+void cChannelColumn::dumpGrids() {
+    esyslog("tvguide: ------Channel %s %d: %d entires ---------", channel->Name(), num, grids.Count());
+    int i=1;
+    for (cGrid *grid = grids.First(); grid; grid = grids.Next(grid)) {
+        esyslog("tvguide: grid %d: start: %s, stop: %s", i, *cMyTime::printTime(grid->StartTime()), *cMyTime::printTime(grid->EndTime()));
+        i++;
+    }
+}
\ No newline at end of file
diff --git a/channelcolumn.h b/channelcolumn.h
index 2b1fdbd..0e1d138 100644
--- a/channelcolumn.h
+++ b/channelcolumn.h
@@ -1,42 +1,62 @@
 #ifndef __TVGUIDE_CHANNELCOLUMN_H
 #define __TVGUIDE_CHANNELCOLUMN_H
 
+#include <vdr/tools.h>
+#include "grid.h"
+#include "epggrid.h"
+#include "headergrid.h"
+#include "switchtimer.h"
+
+class cGrid;
 class cEpgGrid;
+class cHeaderGrid;
+
 // --- cChannelColumn  -------------------------------------------------------------
 
 class cChannelColumn : public cListObject, public cStyledPixmap {
-friend class cEpgGrid;
 private:
-    cPixmap *pixmapLogo;
-	cMyTime *myTime;
-	int num;
-	cChannel *channel;
-	cList<cEpgGrid> grids;
-	cSchedulesLock schedulesLock;
-	const cSchedules *schedules;
-	bool hasTimer;
+    cMyTime *myTime;
+    int num;
+    const cChannel *channel;
+    cHeaderGrid *header;
+    cList<cGrid> grids;
+    cSchedulesLock *schedulesLock;
+    const cSchedules *schedules;
+    bool hasTimer;
+    bool hasSwitchTimer;
+    cGrid *addEpgGrid(const cEvent *event, cGrid *firstGrid, bool color);
+    cGrid *addDummyGrid(time_t start, time_t end, cGrid *firstGrid, bool color);
 public:
-	cChannelColumn(int num, cChannel *channel, cMyTime *myTime);
-	virtual ~cChannelColumn(void);
-	void createHeader();
-	void drawHeader();
-	bool readGrids();
-	void drawGrids();
-	int getX();
-	cChannel * getChannel() {return channel;}
-	cEpgGrid * getActive();
-	cEpgGrid * getNext(cEpgGrid *activeGrid);
-	cEpgGrid * getPrev(cEpgGrid *activeGrid);
-	cEpgGrid * getNeighbor(cEpgGrid *activeGrid);
-	void AddNewGridsAtStart();
-	void AddNewGridsAtEnd();
-	void ClearOutdatedStart();
-	void ClearOutdatedEnd();
-	int GetNum() {return num;};
-	void SetNum(int num) {this->num = num;};
-	void setTimer() {hasTimer = true;};
-	void clearGrids();
-	void dumpGrids();
+    cChannelColumn(int num, const cChannel *channel, cMyTime *myTime);
+    virtual ~cChannelColumn(void);
+    void createHeader();
+    void drawHeader();
+    bool readGrids();
+    void drawGrids();
+    int getX();
+    int getY();
+    int Start() { return myTime->GetStart(); };
+    int Stop()  { return myTime->GetEnd(); };
+    const char* Name() { return channel->Name(); };
+    const cChannel * getChannel() {return channel;}
+    cGrid * getActive();
+    cGrid * getNext(cGrid *activeGrid);
+    cGrid * getPrev(cGrid *activeGrid);
+    cGrid * getNeighbor(cGrid *activeGrid);
+    bool isFirst(cGrid *grid);
+    void AddNewGridsAtStart();
+    void AddNewGridsAtEnd();
+    void ClearOutdatedStart();
+    void ClearOutdatedEnd();
+    int GetNum() {return num;};
+    void SetNum(int num) {this->num = num;};
+    void setTimer() {hasTimer = channel->HasTimer();};
+    bool HasTimer() { return hasTimer; };
+    void setSwitchTimer() {hasSwitchTimer = SwitchTimers.ChannelInSwitchList(channel);};
+    bool HasSwitchTimer() { return hasSwitchTimer; };
+    void SetTimers();
+    void clearGrids();
+    void dumpGrids();
 };
 
-#endif //__TVGUIDE_CHANNELCOLUMN_H
\ No newline at end of file
+#endif //__TVGUIDE_CHANNELCOLUMN_H
diff --git a/channelgroup.c b/channelgroup.c
new file mode 100644
index 0000000..3278f8c
--- /dev/null
+++ b/channelgroup.c
@@ -0,0 +1,98 @@
+#include <algorithm>
+#include "channelgroup.h"
+#include "tools.h"
+
+cChannelGroup::cChannelGroup(const char *name) {
+    channelStart = 0;
+    channelStop = 0;
+    this->name = name;
+}
+
+cChannelGroup::~cChannelGroup(void) {
+}
+
+void cChannelGroup::Dump(void) {
+    esyslog("tvguide: Group %s, startChannel %d, stopChannel %d", name, channelStart, channelStop);
+}
+
+// --- cChannelGroupGrid  -------------------------------------------------------------
+
+cChannelGroupGrid::cChannelGroupGrid(const char *name) {
+    this->name = name;
+}
+
+cChannelGroupGrid::~cChannelGroupGrid(void) {
+}
+
+void cChannelGroupGrid::SetBackground() {
+    if (isColor1) {
+        color = theme.Color(clrGrid1);
+        colorBlending = theme.Color(clrGrid1Blending);
+    } else {
+        color = theme.Color(clrGrid2);
+        colorBlending = theme.Color(clrGrid2Blending);
+    }
+}
+
+void cChannelGroupGrid::SetGeometry(int start, int end) {
+    int x, y, width, height;
+    if (tvguideConfig.displayMode == eVertical) {
+        x = geoManager.timeLineWidth + start*geoManager.colWidth;
+        y = geoManager.statusHeaderHeight;
+        width = (end - start + 1) * geoManager.colWidth;
+        height = geoManager.channelGroupsHeight;
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        x = 0;
+        y = geoManager.statusHeaderHeight +  geoManager.timeLineHeight + start*geoManager.rowHeight;
+        width = geoManager.channelGroupsWidth;
+        height = (end - start + 1) * geoManager.rowHeight;
+    }
+    pixmap = osdManager.requestPixmap(1, cRect(x, y, width, height));
+}
+
+void cChannelGroupGrid::Draw(void) {
+    if (tvguideConfig.style == eStyleGraphical) {
+        drawBackgroundGraphical(bgChannelGroup);
+    } else {
+        drawBackground();
+        drawBorder();
+    }
+    tColor colorText = theme.Color(clrFont);
+    tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+    if (tvguideConfig.displayMode == eVertical) {
+        DrawVertical(colorText, colorTextBack);
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        DrawHorizontal(colorText, colorTextBack);
+    }
+}
+
+void cChannelGroupGrid::DrawVertical(tColor colorText, tColor colorTextBack) {
+    int textY = (Height() - fontManager.FontChannelGroups->Height()) / 2;
+    cString text = CutText(name, Width() - 4, fontManager.FontChannelGroups).c_str();
+    int textWidth = fontManager.FontChannelGroups->Width(*text);
+    int x = (Width() - textWidth) / 2;
+    pixmap->DrawText(cPoint(x, textY), *text, colorText, colorTextBack, fontManager.FontChannelGroups);
+}
+
+void cChannelGroupGrid::DrawHorizontal(tColor colorText, tColor colorTextBack) {
+    std::string nameUpper = name;
+    std::transform(nameUpper.begin(), nameUpper.end(),nameUpper.begin(), ::toupper);
+    int numChars = nameUpper.length();
+    int charHeight = fontManager.FontChannelGroupsHorizontal->Height();
+    int textHeight = numChars * charHeight;
+    int y = 5;
+    if ((textHeight +5) < Height()) {
+        y = (Height() - textHeight) / 2;
+    }
+    for (int i=0; i < numChars; i++) {
+        if (((y + 2*charHeight) > Height()) && ((i+1)<numChars)) {
+            int x = (Width() - fontManager.FontChannelGroupsHorizontal->Width("...")) / 2;
+            pixmap->DrawText(cPoint(x, y), "...", colorText, colorTextBack, fontManager.FontChannelGroupsHorizontal);
+            break;
+        }
+        cString currentChar = cString::sprintf("%c", nameUpper.at(i));
+        int x = (Width() - fontManager.FontChannelGroupsHorizontal->Width(*currentChar)) / 2;
+        pixmap->DrawText(cPoint(x, y), *currentChar, colorText, colorTextBack, fontManager.FontChannelGroupsHorizontal);
+        y += fontManager.FontChannelGroupsHorizontal->Height();
+    }
+}
diff --git a/channelgroup.h b/channelgroup.h
new file mode 100644
index 0000000..e09f6de
--- /dev/null
+++ b/channelgroup.h
@@ -0,0 +1,44 @@
+#ifndef __TVGUIDE_CHANNELGROUP_H
+#define __TVGUIDE_CHANNELGROUP_H
+
+#include <vdr/tools.h>
+#include "styledpixmap.h"
+
+
+// --- cChannelGroup  -------------------------------------------------------------
+
+class cChannelGroup {
+private:
+    int channelStart;
+    int channelStop;
+    const char *name;
+public:
+    cChannelGroup(const char *name);
+    virtual ~cChannelGroup(void);
+    void SetChannelStart(int start) { channelStart = start; };
+    int StartChannel(void) { return channelStart; };
+    void SetChannelStop(int stop) { channelStop = stop; };
+    int StopChannel(void) { return channelStop; };
+    const char* GetName(void) { return name; };
+    void Dump(void);
+};
+
+// --- cChannelGroupGrid  -------------------------------------------------------------
+
+class cChannelGroupGrid : public cListObject, public cStyledPixmap {
+private:
+    const char *name;
+    bool isColor1;
+    void DrawHorizontal(tColor colorText, tColor colorTextBack);
+    void DrawVertical(tColor colorText, tColor colorTextBack);
+public:
+    cChannelGroupGrid(const char *name);
+    virtual ~cChannelGroupGrid(void);
+    void SetColor(bool color) {isColor1 = color;};
+    void SetBackground(void);
+    void SetGeometry(int start, int end);
+    void Draw(void);
+};
+
+
+#endif //__TVGUIDE_CHANNELGROUP_H
\ No newline at end of file
diff --git a/channelgroups.c b/channelgroups.c
new file mode 100644
index 0000000..6767cee
--- /dev/null
+++ b/channelgroups.c
@@ -0,0 +1,143 @@
+#include <vector>
+#include "channelgroups.h"
+
+cChannelGroups::cChannelGroups(void) {
+}
+
+cChannelGroups::~cChannelGroups(void) {
+}
+
+void cChannelGroups::ReadChannelGroups(void) {
+    bool setStart = false;
+    int lastChannelNumber = 0;
+    const cChannel *first = Channels.First();
+    if (!first->GroupSep()) {
+        channelGroups.push_back(cChannelGroup(tr("Main Program")));
+        setStart = true;
+    }    
+    for (const cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) {
+        if (setStart && (channelGroups.size() > 0)) {
+            channelGroups[channelGroups.size()-1].SetChannelStart(channel->Number());
+            setStart = false;
+        }
+        if (channel->GroupSep()) {
+            if (channelGroups.size() > 0) {
+                channelGroups[channelGroups.size()-1].SetChannelStop(lastChannelNumber);
+            }
+            channelGroups.push_back(cChannelGroup(channel->Name()));
+            setStart = true;
+        } else {
+            lastChannelNumber = channel->Number();
+        }
+    }
+    if (channelGroups.size() > 0) {
+        channelGroups[channelGroups.size()-1].SetChannelStop(lastChannelNumber);
+        if ((tvguideConfig.hideLastGroup)&&(channelGroups.size() > 1)) {
+            channelGroups.pop_back();
+        }
+    }
+}
+
+int cChannelGroups::GetGroup(const cChannel *channel) {
+    int channelNumber = channel->Number();
+    int numGroups = channelGroups.size();
+    if (numGroups) {
+        for (int i=0; i<numGroups; i++) {
+            if ((channelGroups[i].StartChannel() <= channelNumber) && ((channelGroups[i].StopChannel() >= channelNumber))) {
+                return i;
+            }
+        }
+    }
+    return -1;
+}
+
+const char* cChannelGroups::GetPrev(int group) {
+    if (group > 0) {
+        return channelGroups[group-1].GetName();
+    }
+    return "";
+}
+
+const char* cChannelGroups::GetNext(int group) {
+    if (group > -1) {
+        if ((group+1) < channelGroups.size())
+            return channelGroups[group+1].GetName();
+    }
+    return "";
+}
+
+int cChannelGroups::GetPrevGroupChannelNumber(const cChannel *channel) {
+    int currentGroup = GetGroup(channel);
+    if (currentGroup == -1)
+        return 0;
+    if (currentGroup > 0) {
+        return channelGroups[currentGroup-1].StartChannel();
+    }
+    return 0;
+}
+
+int cChannelGroups::GetNextGroupChannelNumber(const cChannel *channel) {
+    int currentGroup = GetGroup(channel);
+    if (currentGroup == -1)
+        return 0;
+    if ((currentGroup+1) < channelGroups.size()) {
+        return channelGroups[currentGroup+1].StartChannel();
+    }
+    return 0;
+}
+
+bool cChannelGroups::IsInLastGroup(const cChannel *channel) {
+    if (!tvguideConfig.hideLastGroup)
+        return false;
+    if (channelGroups.size() > 0) {
+        if (channel->Number() > channelGroups[channelGroups.size()-1].StopChannel()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void cChannelGroups::DrawChannelGroups(const cChannel *start, const cChannel *stop) {
+    groupGrids.Clear();
+    int group = GetGroup(start);
+    int groupLast = group;
+    int line = 0;
+    int lineStart = 0;
+    for (const cChannel *channel = Channels.Next(start); channel; channel = Channels.Next(channel)) {
+        if (channel->GroupSep())
+            continue;
+        group = GetGroup(channel);
+        if (group != groupLast) {
+            CreateGroupGrid(channelGroups[groupLast].GetName(), group, lineStart, line);
+            lineStart = line + 1;
+        }
+        line++;
+        groupLast = group;
+        if (channel == stop) {
+            CreateGroupGrid(channelGroups[groupLast].GetName(), group+1, lineStart, line);
+            break;
+        }
+    }
+    
+}
+
+void cChannelGroups::CreateGroupGrid(const char *name, int number, int start, int end) {
+    cChannelGroupGrid *groupGrid = new cChannelGroupGrid(name);
+    groupGrid->SetColor(number%2);
+    groupGrid->SetBackground();
+    groupGrid->SetGeometry(start, end);
+    groupGrid->Draw();
+    groupGrids.Add(groupGrid);
+}
+
+int cChannelGroups::GetLastValidChannel(void) {
+    if (channelGroups.size() > 0)
+        return channelGroups[channelGroups.size()-1].StopChannel();
+    return 0;
+}
+
+void cChannelGroups::DumpGroups(void) {
+    for (std::vector<cChannelGroup>::iterator group = channelGroups.begin(); group!=channelGroups.end(); ++group) {
+        group->Dump();
+    }
+}
diff --git a/channelgroups.h b/channelgroups.h
new file mode 100644
index 0000000..02b146d
--- /dev/null
+++ b/channelgroups.h
@@ -0,0 +1,30 @@
+#ifndef __TVGUIDE_CHANNELGROUPS_H
+#define __TVGUIDE_CHANNELGROUPS_H
+
+#include <vector>
+#include <vdr/channels.h>
+#include "channelgroup.h"
+
+// --- cChannelGroups  -------------------------------------------------------------
+
+class cChannelGroups {
+private:
+    std::vector<cChannelGroup> channelGroups;
+    cList<cChannelGroupGrid> groupGrids;
+public:
+    cChannelGroups(void);
+    virtual ~cChannelGroups(void);
+    void ReadChannelGroups(void);
+    const char* GetPrev(int group);
+    const char* GetNext(int group);
+    int GetGroup(const cChannel *channel);
+    int GetPrevGroupChannelNumber(const cChannel *channel);
+    int GetNextGroupChannelNumber(const cChannel *channel);
+    bool IsInLastGroup(const cChannel *channel);
+    void DrawChannelGroups(const cChannel *start, const cChannel *stop);
+    void CreateGroupGrid(const char *name, int number, int start, int end);
+    int GetLastValidChannel(void);
+    void DumpGroups(void);
+};
+
+#endif //__TVGUIDE_CHANNELGROUPS_H
diff --git a/channeljump.c b/channeljump.c
new file mode 100644
index 0000000..58fa77f
--- /dev/null
+++ b/channeljump.c
@@ -0,0 +1,90 @@
+#include <vdr/channels.h>
+#include "config.h"
+#include "geometrymanager.h"
+#include "osdmanager.h"
+#include "fontmanager.h"
+#include "channelgroups.h"
+#include "channeljump.h"
+
+cChannelJump::cChannelJump(cChannelGroups *channelGroups) {
+    this->channelGroups = channelGroups;
+    pixmapText = NULL;
+    channel = 0;
+	if (!tvguideConfig.hideLastGroup) {
+        maxChannels = Channels.MaxNumber();
+	} else {
+        maxChannels = channelGroups->GetLastValidChannel();
+    }
+    timeout = Setup.ChannelEntryTimeout;
+    startTime = cTimeMs::Now();
+    SetPixmaps();
+    Draw();
+}
+
+cChannelJump::~cChannelJump(void) {
+    osdManager.releasePixmap(pixmapBack);
+    osdManager.releasePixmap(pixmapText);
+}
+
+void cChannelJump::SetPixmaps(void) {
+	int x = (geoManager.osdWidth - geoManager.channelJumpWidth)/2;
+	int y = (geoManager.osdHeight - geoManager.channelJumpHeight)/2;
+	
+	pixmapBack = osdManager.requestPixmap(4, cRect(x, y, geoManager.channelJumpWidth, geoManager.channelJumpHeight));
+	pixmap = osdManager.requestPixmap(5, cRect(x, y, geoManager.channelJumpWidth, geoManager.channelJumpHeight));
+	pixmapText = osdManager.requestPixmap(6, cRect(x, y, geoManager.channelJumpWidth, geoManager.channelJumpHeight));
+}
+
+void cChannelJump::Draw(void) {
+	if (tvguideConfig.style == eStyleGraphical) {
+        drawBackgroundGraphical(bgChannelJump);
+	} else {
+        pixmap->Fill(theme.Color(clrBackground));
+        drawBorder();
+	}
+	pixmapBack->Fill(clrTransparent);
+	pixmapBack->DrawRectangle(cRect(5, Height()/2, Width()-10, Height()-3), theme.Color(clrBackground));
+}
+
+void cChannelJump::DrawText(void) {
+    pixmapText->Fill(clrTransparent);
+
+    cString header = cString::sprintf("%s:", tr("Channel"));
+
+	const cFont *font = fontManager.FontMessageBox;
+	const cFont *fontHeader = fontManager.FontMessageBoxLarge;
+
+	int xHeader = (Width() - fontHeader->Width(*header)) / 2;
+	int yHeader = (Height()/2 - fontHeader->Height()) / 2;
+	pixmapText->DrawText(cPoint(xHeader, yHeader), *header, theme.Color(clrFont), clrTransparent, fontHeader);
+
+	cString strChannel = BuildChannelString();
+	int xChannel = (Width() - font->Width(*strChannel)) / 2;
+	int yChannel = Height()/2 + (Height()/2 - font->Height()) / 2;
+	pixmapText->DrawText(cPoint(xChannel, yChannel), *strChannel, theme.Color(clrFont), clrTransparent, font);
+
+}
+
+void cChannelJump::Set(int num) {
+    startTime = cTimeMs::Now();
+    if (channel == 0) {
+	    channel = num;
+	    return;
+    }
+    int newChannel = channel * 10 + num;
+    if (newChannel <= maxChannels)
+    	channel = newChannel;
+}
+
+cString cChannelJump::BuildChannelString(void) {
+	if (channel*10 <= maxChannels)
+		return cString::sprintf("%d-", channel);
+	else
+		return cString::sprintf("%d", channel); 
+}
+
+ bool cChannelJump::TimeOut(void) {
+ 	if ((cTimeMs::Now() - startTime) > timeout)
+	 	return true;
+	return false;
+ }
\ No newline at end of file
diff --git a/channeljump.h b/channeljump.h
new file mode 100644
index 0000000..6bb988f
--- /dev/null
+++ b/channeljump.h
@@ -0,0 +1,29 @@
+#ifndef __TVGUIDE_CHANNELJUMP_H
+#define __TVGUIDE_CHANNELJUMP_H
+
+#include "styledpixmap.h"
+
+// --- cChannelJump  -------------------------------------------------------------
+
+class cChannelJump : public cStyledPixmap {
+private:
+    int channel;
+    cChannelGroups *channelGroups;
+    int maxChannels;
+    int startTime;
+    int timeout;
+    cPixmap *pixmapBack;
+    cPixmap *pixmapText;
+    void SetPixmaps(void);
+    void Draw(void);
+    cString BuildChannelString(void);
+public:
+    cChannelJump(cChannelGroups *channelGroups);
+    virtual ~cChannelJump(void);
+    void Set(int num);
+    void DrawText(void);
+    bool TimeOut(void);
+    int GetChannel(void) { return channel; };
+};
+
+#endif //__TVGUIDE_CHANNELJUMP_H
\ No newline at end of file
diff --git a/config.c b/config.c
index c146d53..76d01c7 100644
--- a/config.c
+++ b/config.c
@@ -1,176 +1,334 @@
+#include <string>
 #include "config.h"
 
-enum {
-	e12Hours,
-	e24Hours
-};
-
 cTvguideConfig::cTvguideConfig() {
-	osdWidth = 0; 
-	osdHeight = 0;
-	colWidth = 0;
-	channelCols = 5;
-	displayTime = 160;
-	minuteHeight = 0;
-	timeColWidth = 120;
-	headerHeight = 150;
-	footerHeight = 80;
-	stepMinutes = 30;
-	bigStepHours = 3;
-	hugeStepHours = 24;
-	jumpChannels = 5;
-	hideChannelLogos = 0;
-	logoWidth = 130;
-	logoHeight = 100;
-	logoExtension = 0;
-	hideEpgImages = 0;
-	epgImageWidth = 315;
-	epgImageHeight = 240;
-	fontIndex = 0;
-	fontNameDefault = "VDRSymbols Sans:Book";
-	fontHeaderSize = 33;
-	fontGridSize = 27;
-	fontGridSmallSize = 24;
-	fontTimeLineWeekdaySize = 40;
-	fontTimeLineDateSize = 33;
-	fontTimeLineTimeSize = 0;
-	fontTimeLineTimeSizeDef12 = 24;
-	fontTimeLineTimeSizeDef24 = 33;
-	fontButtonSize = 33;
-	fontDetailViewSize = 33;
-	fontDetailHeaderSize = 40;
-	fontMessageBoxSize = 33;
-	fontMessageBoxLargeSize = 40;
-
-
-	FontHeader = NULL;
-	FontGrid = NULL;
-	FontGridSmall = NULL;
-	FontTimeLineWeekday = NULL;
-	FontTimeLineDate = NULL;
-	FontTimeLineTime = NULL;
-	FontButton = NULL;
-	FontDetailView = NULL;
-	FontDetailHeader = NULL;
-	FontMessageBox = NULL;
-	FontMessageBoxLarge = NULL;
-	
-	timeFormat = 1;
-	themeIndex = 0;
-	useBlending = 1;
-	roundedCorners = 0;
+    debugImageLoading = 0;
+    showMainMenuEntry = 1;
+    replaceOriginalSchedule = 0;
+    displayMode = eHorizontal;
+    showTimeInGrid = 1;
+    channelCols = 5;
+    channelRows = 10;
+    displayTime = 160;
+    displayStatusHeader = 1;
+    displayChannelGroups = 1;
+    displayTimeBase = 1;
+    headerHeightPercent = 20;
+    channelGroupsPercent = 5;
+    epgViewBorder = 50;
+    scaleVideo = 1;
+    decorateVideo = 1;
+    timeLineWidthPercent = 8;
+    timeLineHeightPercent = 4;
+    displayChannelName = 1;
+    channelHeaderWidthPercent = 20;
+    channelHeaderHeightPercent = 15;
+    footerHeightPercent = 7;
+    stepMinutes = 30;
+    bigStepHours = 3;
+    hugeStepHours = 24;
+    channelJumpMode = eNumJump;
+    jumpChannels = 0;
+    blueKeyMode = 2;
+    closeOnSwitch = 1;
+    numkeyMode = 0;
+    useRemoteTimers = 0;
+    hideLastGroup = 0;
+    hideChannelLogos = 0;
+    logoWidthRatio = 13;
+    logoHeightRatio = 10;
+    logoExtension = 0;
+    hideEpgImages = 0;
+    epgImageWidth = 315;
+    epgImageHeight = 240;
+    numAdditionalEPGPictures = 9;
+    epgImageWidthLarge = 525;
+    epgImageHeightLarge = 400;
+    detailedViewScrollStep = 5;
+    instRecFolderMode = eFolderRoot;
+    instRecFixedFolder = "";
+    favWhatsOnNow = 1;
+    favWhatsOnNext = 1;
+    favUseTime1 = 0;
+    favUseTime2 = 0;
+    favUseTime3 = 0;
+    favUseTime4 = 0;
+    favTime1 = 0;
+    favTime2 = 0;
+    favTime3 = 0;
+    favTime4 = 0;
+    descUser1 = "";
+    descUser2 = "";
+    descUser3 = "";
+    descUser4 = "";
+    favLimitChannels = 0;
+    favStartChannel = 0;
+    favStopChannel = 0;
+    fontIndex = 0;
+    fontNameDefault = "VDRSymbols Sans:Book";
+    FontButtonDelta = 0;
+    FontDetailViewDelta = 0;
+    FontDetailViewSmallDelta = 0;
+    FontDetailHeaderDelta = 0;
+    FontMessageBoxDelta = 0;
+    FontMessageBoxLargeDelta = 0;
+    FontStatusHeaderDelta = 0;
+    FontStatusHeaderLargeDelta = 0;
+    FontChannelHeaderDelta = 0;
+    FontChannelGroupsDelta = 0;
+    FontGridDelta = 0;
+    FontGridSmallDelta = 0;
+    FontTimeLineWeekdayDelta = 0;
+    FontTimeLineDateDelta = 0;
+    FontTimeLineTimeDelta = 0;
+    FontChannelHeaderHorizontalDelta = 0;
+    FontChannelGroupsHorizontalDelta = 0;
+    FontGridHorizontalDelta = 0;
+    FontGridHorizontalSmallDelta = 0;
+    FontTimeLineDateHorizontalDelta = 0;
+    FontTimeLineTimeHorizontalDelta = 0;
+    FontRecMenuItemDelta = 0;
+    FontRecMenuItemSmallDelta = 0;
+    FontRecMenuItemLargeDelta = 0;
+    timeFormat = 1;
+    useNopacityTheme = 1;
+    themeIndex = -1;
+    themeIndexCurrent = -1;
+    themeName = "";
+    nOpacityTheme = "";
+    style = eStyleBlendingDefault;
+    roundedCorners = 0;
+    displayRerunsDetailEPGView = 1;
+    numReruns = 5;
+    useSubtitleRerun = 1;
+    numLogosInitial = 30;
+    numLogosMax = 50;
+    limitLogoCache = 1;
+    logoPathSet = false;
+    imagesPathSet = false;
+    iconsPathSet = false;
 }
 
 cTvguideConfig::~cTvguideConfig() {
-	delete FontHeader;
-	delete FontGrid;
-	delete FontGridSmall;
-	delete FontTimeLineWeekday;
-	delete FontTimeLineDate;
-	delete FontTimeLineTime;
-	delete FontButton;
-	delete FontDetailView;
-	delete FontDetailHeader;
-	delete FontMessageBox;
-	delete FontMessageBoxLarge;
 }
 
-void cTvguideConfig::setDynamicValues(int width, int height) {
-	osdWidth = width;
-	osdHeight = height;
-	colWidth = (osdWidth - timeColWidth) / channelCols;
-	minuteHeight = (osdHeight - headerHeight - footerHeight) / displayTime;
-	
-	if (!fontTimeLineTimeSize) {
-		if (timeFormat == e12Hours) {
-			fontTimeLineTimeSize = fontTimeLineTimeSizeDef12;
-		} else if (timeFormat == e24Hours) {
-			fontTimeLineTimeSize = fontTimeLineTimeSizeDef24;
-		}
-	} else if ((fontTimeLineTimeSize == fontTimeLineTimeSizeDef12) && (timeFormat == e24Hours)) {
-		fontTimeLineTimeSize = fontTimeLineTimeSizeDef24;
-	} else if ((fontTimeLineTimeSize == fontTimeLineTimeSizeDef24) && (timeFormat == e12Hours)) {
-		fontTimeLineTimeSize = fontTimeLineTimeSizeDef12;
-	}
-	cString fontname;
-	if (fontIndex == 0) {
-		fontname = fontNameDefault;
-	} else {
-		cStringList availableFonts;
-		cFont::GetAvailableFontNames(&availableFonts);
-		if (availableFonts[fontIndex-1]) {
-			fontname = availableFonts[fontIndex-1];
-		} else 
-			fontname = fontNameDefault;
-	}
-	cFont *test = NULL;
-	test = cFont::CreateFont(*fontname, fontHeaderSize);
-	if (!test) {
-		fontname = DefaultFontSml;
-	}
-	delete test;
-	FontHeader = cFont::CreateFont(*fontname, fontHeaderSize);
-	FontGrid = cFont::CreateFont(*fontname, fontGridSize);
-	FontGridSmall = cFont::CreateFont(*fontname, fontGridSmallSize);
-	FontTimeLineWeekday = cFont::CreateFont(*fontname, fontTimeLineWeekdaySize);
-	FontTimeLineDate = cFont::CreateFont(*fontname, fontTimeLineDateSize);
-	FontTimeLineTime = cFont::CreateFont(*fontname, fontTimeLineTimeSize);
-	FontButton = cFont::CreateFont(*fontname, fontButtonSize);
-	FontDetailView = cFont::CreateFont(*fontname, fontDetailViewSize);
-	FontDetailHeader = cFont::CreateFont(*fontname, fontDetailHeaderSize);
-	FontMessageBox = cFont::CreateFont(*fontname, fontMessageBoxSize);
-	FontMessageBoxLarge = cFont::CreateFont(*fontname, fontMessageBoxLargeSize);	
+void cTvguideConfig::setDynamicValues() {
+    numGrids = (displayMode == eVertical)?channelCols:channelRows;
+    jumpChannels = numGrids;
+}
+
+bool cTvguideConfig::LoadTheme() {
+    //is correct theme already loaded?
+    if (nOpacityTheme.size() == 0)
+        nOpacityTheme = Setup.OSDTheme;
+    if ((themeIndex > -1) && (themeIndex == themeIndexCurrent)) {
+        if (!nOpacityTheme.compare(Setup.OSDTheme)) {
+            return false;
+        } else {
+            nOpacityTheme = Setup.OSDTheme;
+        }
+    }
+    //Load available Themes
+    cThemes themes;
+    themes.Load(*cString("tvguide"));
+    int numThemesAvailable = themes.NumThemes();
+
+    //Check for nOpacity Theme
+    if (useNopacityTheme) {
+        std::string nOpacity = "nOpacity";
+        std::string currentSkin = Setup.OSDSkin;
+        std::string currentSkinTheme = Setup.OSDTheme;
+        if (!currentSkin.compare(nOpacity)) {
+            for (int curThemeIndex = 0; curThemeIndex < numThemesAvailable; curThemeIndex++) {
+                std::string curThemeName = themes.Name(curThemeIndex);
+                if (!curThemeName.compare(currentSkinTheme)) {
+                    themeIndex = curThemeIndex;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (themeIndex == -1) {
+        for (int curThemeIndex = 0; curThemeIndex < numThemesAvailable; curThemeIndex++) {
+            std::string curThemeName = themes.Name(curThemeIndex);
+            if (!curThemeName.compare("default")) {
+                themeIndex = curThemeIndex;
+                break;
+            }
+        }
+
+    }
+
+    if (themeIndex == -1)
+        themeIndex = 0;
+
+    themeIndexCurrent = themeIndex;
+
+    const char *themePath = themes.FileName(themeIndex);
+    if (access(themePath, F_OK) == 0) {
+        ::theme.Load(themePath);
+        themeName = themes.Name(themeIndex);        
+    }
+    esyslog("tvguide: set Theme to %s", *themeName);
+    return true;
+}
+
+
+void cTvguideConfig::SetStyle(void) {
+    if (theme.Color(clrStyle) == CLR_STYLE_FLAT) {
+        style = eStyleFlat;
+        esyslog("tvguide: set flat style");
+    } else if (theme.Color(clrStyle) == CLR_STYLE_BLENDING_DEFAULT) {
+        style = eStyleBlendingDefault;
+        esyslog("tvguide: set blending style");
+    } else if (theme.Color(clrStyle) == CLR_STYLE_GRAPHICAL) {
+        style = eStyleGraphical;
+        esyslog("tvguide: set graphical style");
+    } else {
+        style = eStyleBlendingMagick;
+        esyslog("tvguide: set magick blending style");
+    }
+    
 }
 
 void cTvguideConfig::SetLogoPath(cString path) {
-	logoPath = path;
+    logoPath = checkSlashAtEnd(*path);
+    logoPathSet = true;
+    esyslog("tvguide: Logo Path set to %s", *logoPath);
 }
 
 void cTvguideConfig::SetImagesPath(cString path) {
-	epgImagePath = path;
+    epgImagePath = checkSlashAtEnd(*path);
+    imagesPathSet = true;
+    esyslog("tvguide: EPG Image Path set to %s", *epgImagePath);
 }
 
-void cTvguideConfig::loadTheme() {
-	cThemes themes;
-	themes.Load(*cString("tvguide"));
-	const char *FileName = themes.FileName(themeIndex);
-	if (access(FileName, F_OK) == 0) {
-		::theme.Load(FileName);
-	}
+void cTvguideConfig::SetIconsPath(cString path) {
+    iconPath = checkSlashAtEnd(*path);
+    iconsPathSet = true;
+    esyslog("tvguide: Icon Path set to %s", *iconPath);
 }
 
-bool cTvguideConfig::SetupParse(const char *Name, const char *Value) {
-	if      (strcmp(Name, "timeFormat") == 0)               timeFormat = atoi(Value);
-	else if (strcmp(Name, "themeIndex") == 0)         		themeIndex = atoi(Value);
-	else if (strcmp(Name, "useBlending") == 0)         		useBlending = atoi(Value);
-	else if (strcmp(Name, "roundedCorners") == 0)         	roundedCorners = atoi(Value);
-	else if (strcmp(Name, "channelCols") == 0)         		channelCols = atoi(Value);
-	else if (strcmp(Name, "displayTime") == 0)         		displayTime = atoi(Value);
-	else if (strcmp(Name, "hideChannelLogos") == 0)         hideChannelLogos = atoi(Value);
-	else if (strcmp(Name, "logoExtension") == 0) 			logoExtension = atoi(Value);
-	else if (strcmp(Name, "logoWidth") == 0) 				logoWidth = atoi(Value);
-	else if (strcmp(Name, "logoHeight") == 0) 				logoHeight = atoi(Value);
-	else if (strcmp(Name, "bigStepHours") == 0) 			bigStepHours = atoi(Value);
-	else if (strcmp(Name, "hugeStepHours") == 0) 			hugeStepHours = atoi(Value);
-	else if (strcmp(Name, "jumpChannels") == 0) 			jumpChannels = atoi(Value);
-	else if (strcmp(Name, "hideEpgImages") == 0)         	hideEpgImages = atoi(Value);
-	else if (strcmp(Name, "epgImageWidth") == 0) 			epgImageWidth = atoi(Value);
-	else if (strcmp(Name, "epgImageHeight") == 0) 			epgImageHeight = atoi(Value);
-	else if (strcmp(Name, "timeColWidth") == 0) 			timeColWidth = atoi(Value);
-	else if (strcmp(Name, "headerHeight") == 0) 			headerHeight = atoi(Value);
-	else if (strcmp(Name, "footerHeight") == 0) 			footerHeight = atoi(Value);	
-	else if (strcmp(Name, "fontIndex") == 0) 				fontIndex = atoi(Value);	
-	else if (strcmp(Name, "fontHeaderSize") == 0) 			fontHeaderSize = atoi(Value);	
-	else if (strcmp(Name, "fontGridSize") == 0) 			fontGridSize = atoi(Value);	
-	else if (strcmp(Name, "fontGridSmallSize") == 0) 		fontGridSmallSize = atoi(Value);	
-	else if (strcmp(Name, "fontTimeLineWeekdaySize") == 0) 	fontTimeLineWeekdaySize = atoi(Value);	
-	else if (strcmp(Name, "fontTimeLineDateSize") == 0) 	fontTimeLineDateSize = atoi(Value);
-	else if (strcmp(Name, "fontTimeLineTimeSize") == 0) 	fontTimeLineTimeSize = atoi(Value);	
-	else if (strcmp(Name, "fontButtonSize") == 0) 			fontButtonSize = atoi(Value);	
-	else if (strcmp(Name, "fontDetailViewSize") == 0) 		fontDetailViewSize = atoi(Value);	
-	else if (strcmp(Name, "fontDetailHeaderSize") == 0) 	fontDetailHeaderSize = atoi(Value);	
-	else if (strcmp(Name, "fontMessageBoxSize") == 0) 		fontMessageBoxSize = atoi(Value);	
-	else if (strcmp(Name, "fontMessageBoxLargeSize") == 0) 	fontMessageBoxLargeSize = atoi(Value);	
-	else return false;
-	return true;
+void cTvguideConfig::SetDefaultPathes(void) {
+    logoPathDefault = cString::sprintf("%s/logos/", cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
+    iconPathDefault = cString::sprintf("%s/icons/", cPlugin::ResourceDirectory(PLUGIN_NAME_I18N));
+    epgImagePathDefault = cString::sprintf("%s/epgimages/", cPlugin::CacheDirectory(PLUGIN_NAME_I18N));
+
+    if (!logoPathSet) {
+        logoPath = logoPathDefault;
+    }
+    if (!imagesPathSet) {
+        epgImagePath = epgImagePathDefault;
+    }
+    if (!iconsPathSet) {
+        iconPath = iconPathDefault;
+    }
 }
+
+cString cTvguideConfig::checkSlashAtEnd(std::string path) {
+    try {
+        if (!(path.at(path.size()-1) == '/'))
+            return cString::sprintf("%s/", path.c_str());
+    } catch (...) {return path.c_str();}
+    return path.c_str();
+}
+
+bool cTvguideConfig::SetupParse(const char *Name, const char *Value) {
+    if      (strcmp(Name, "timeFormat") == 0)               timeFormat = atoi(Value);
+    else if (strcmp(Name, "debugImageLoading") == 0)        debugImageLoading = atoi(Value);
+    else if (strcmp(Name, "showMainMenuEntry") == 0)        showMainMenuEntry = atoi(Value);
+    else if (strcmp(Name, "replaceOriginalSchedule") == 0)  replaceOriginalSchedule = atoi(Value);
+    else if (strcmp(Name, "useNopacityTheme") == 0)         useNopacityTheme = atoi(Value);   
+    else if (strcmp(Name, "themeIndex") == 0)               themeIndex = atoi(Value);
+    else if (strcmp(Name, "displayMode") == 0)              displayMode = atoi(Value);
+    else if (strcmp(Name, "showTimeInGrid") == 0)           showTimeInGrid = atoi(Value);
+    else if (strcmp(Name, "displayStatusHeader") == 0)      displayStatusHeader = atoi(Value);
+    else if (strcmp(Name, "displayChannelGroups") == 0)     displayChannelGroups = atoi(Value);
+    else if (strcmp(Name, "displayTimeBase") == 0)          displayTimeBase = atoi(Value);
+    else if (strcmp(Name, "headerHeightPercent") == 0)      headerHeightPercent = atoi(Value);
+    else if (strcmp(Name, "channelGroupsPercent") == 0)     channelGroupsPercent = atoi(Value);
+    else if (strcmp(Name, "epgViewBorder") == 0)            epgViewBorder = atoi(Value);
+    else if (strcmp(Name, "scaleVideo") == 0)               scaleVideo = atoi(Value);
+    else if (strcmp(Name, "decorateVideo") == 0)            decorateVideo = atoi(Value);
+    else if (strcmp(Name, "roundedCorners") == 0)           roundedCorners = atoi(Value);
+    else if (strcmp(Name, "channelCols") == 0)              channelCols = atoi(Value);
+    else if (strcmp(Name, "channelRows") == 0)              channelRows = atoi(Value);
+    else if (strcmp(Name, "displayTime") == 0)              displayTime = atoi(Value);
+    else if (strcmp(Name, "hideChannelLogos") == 0)         hideChannelLogos = atoi(Value);
+    else if (strcmp(Name, "logoExtension") == 0)            logoExtension = atoi(Value);
+    else if (strcmp(Name, "logoWidthRatio") == 0)           logoWidthRatio = atoi(Value);
+    else if (strcmp(Name, "logoHeightRatio") == 0)          logoHeightRatio = atoi(Value);
+    else if (strcmp(Name, "bigStepHours") == 0)             bigStepHours = atoi(Value);
+    else if (strcmp(Name, "hugeStepHours") == 0)            hugeStepHours = atoi(Value);
+    else if (strcmp(Name, "channelJumpMode") == 0)          channelJumpMode = atoi(Value);
+    else if (strcmp(Name, "blueKeyMode") == 0)              blueKeyMode = atoi(Value);
+    else if (strcmp(Name, "numkeyMode") == 0)               numkeyMode = atoi(Value);
+    else if (strcmp(Name, "closeOnSwitch") == 0)            closeOnSwitch = atoi(Value);
+    else if (strcmp(Name, "useRemoteTimers") == 0)          useRemoteTimers = atoi(Value);
+    else if (strcmp(Name, "hideLastGroup") == 0)            hideLastGroup = atoi(Value);
+    else if (strcmp(Name, "hideEpgImages") == 0)            hideEpgImages = atoi(Value);
+    else if (strcmp(Name, "epgImageWidth") == 0)            epgImageWidth = atoi(Value);
+    else if (strcmp(Name, "epgImageHeight") == 0)           epgImageHeight = atoi(Value);
+    else if (strcmp(Name, "numAdditionalEPGPictures") == 0) numAdditionalEPGPictures = atoi(Value);
+    else if (strcmp(Name, "epgImageWidthLarge") == 0)       epgImageWidthLarge = atoi(Value);
+    else if (strcmp(Name, "epgImageHeightLarge") == 0)      epgImageHeightLarge = atoi(Value);
+    else if (strcmp(Name, "detailedViewScrollStep") == 0)   detailedViewScrollStep = atoi(Value);
+    else if (strcmp(Name, "timeLineWidthPercent") == 0)     timeLineWidthPercent = atoi(Value);
+    else if (strcmp(Name, "timeLineHeightPercent") == 0)    timeLineHeightPercent = atoi(Value);
+    else if (strcmp(Name, "displayChannelName") == 0)       displayChannelName = atoi(Value);
+    else if (strcmp(Name, "channelHeaderWidthPercent") == 0)  channelHeaderWidthPercent = atoi(Value);
+    else if (strcmp(Name, "channelHeaderHeightPercent") == 0) channelHeaderHeightPercent = atoi(Value);
+    else if (strcmp(Name, "footerHeightPercent") == 0)      footerHeightPercent = atoi(Value);
+    else if (strcmp(Name, "instRecFolderMode") == 0)        instRecFolderMode = atoi(Value);
+    else if (strcmp(Name, "instRecFixedFolder") == 0)       instRecFixedFolder = Value;
+    else if (strcmp(Name, "favWhatsOnNow") == 0)            favWhatsOnNow = atoi(Value);
+    else if (strcmp(Name, "favWhatsOnNext") == 0)           favWhatsOnNext = atoi(Value);
+    else if (strcmp(Name, "favUseTime1") == 0)              favUseTime1 = atoi(Value);
+    else if (strcmp(Name, "favUseTime2") == 0)              favUseTime2 = atoi(Value);
+    else if (strcmp(Name, "favUseTime3") == 0)              favUseTime3 = atoi(Value);
+    else if (strcmp(Name, "favUseTime4") == 0)              favUseTime4 = atoi(Value);
+    else if (strcmp(Name, "favTime1") == 0)                 favTime1 = atoi(Value);
+    else if (strcmp(Name, "favTime2") == 0)                 favTime2 = atoi(Value);
+    else if (strcmp(Name, "favTime3") == 0)                 favTime3 = atoi(Value);
+    else if (strcmp(Name, "favTime4") == 0)                 favTime4 = atoi(Value);
+    else if (strcmp(Name, "descUser1") == 0)                descUser1 = Value;
+    else if (strcmp(Name, "descUser2") == 0)                descUser2 = Value;
+    else if (strcmp(Name, "descUser3") == 0)                descUser3 = Value;
+    else if (strcmp(Name, "descUser4") == 0)                descUser4 = Value;
+    else if (strcmp(Name, "favLimitChannels") == 0)         favLimitChannels = atoi(Value);
+    else if (strcmp(Name, "favStartChannel") == 0)          favStartChannel = atoi(Value);
+    else if (strcmp(Name, "favStopChannel") == 0)           favStopChannel = atoi(Value);
+    else if (strcmp(Name, "fontIndex") == 0)                fontIndex = atoi(Value);
+    else if (strcmp(Name, "FontButtonDelta") == 0)          FontButtonDelta = atoi(Value);
+    else if (strcmp(Name, "FontDetailViewDelta") == 0)      FontDetailViewDelta = atoi(Value);
+    else if (strcmp(Name, "FontDetailHeaderDelta") == 0)    FontDetailHeaderDelta = atoi(Value);
+    else if (strcmp(Name, "FontMessageBoxDelta") == 0)      FontMessageBoxDelta = atoi(Value);  
+    else if (strcmp(Name, "FontMessageBoxLargeDelta") == 0) FontMessageBoxLargeDelta = atoi(Value); 
+    else if (strcmp(Name, "FontStatusHeaderDelta") == 0)    FontStatusHeaderDelta = atoi(Value);    
+    else if (strcmp(Name, "FontStatusHeaderLargeDelta") == 0) FontStatusHeaderLargeDelta = atoi(Value);
+    else if (strcmp(Name, "FontChannelHeaderDelta") == 0)   FontChannelHeaderDelta = atoi(Value);
+    else if (strcmp(Name, "FontChannelGroupsDelta") == 0)   FontChannelGroupsDelta = atoi(Value);
+    else if (strcmp(Name, "FontGridDelta") == 0)            FontGridDelta = atoi(Value);    
+    else if (strcmp(Name, "FontGridSmallDelta") == 0)       FontGridSmallDelta = atoi(Value);   
+    else if (strcmp(Name, "FontTimeLineWeekdayDelta") == 0) FontTimeLineWeekdayDelta = atoi(Value); 
+    else if (strcmp(Name, "FontTimeLineDateDelta") == 0)    FontTimeLineDateDelta = atoi(Value);    
+    else if (strcmp(Name, "FontTimeLineTimeDelta") == 0)    FontTimeLineTimeDelta = atoi(Value);
+    else if (strcmp(Name, "FontChannelHeaderHorizontalDelta") == 0) FontChannelHeaderHorizontalDelta = atoi(Value);
+    else if (strcmp(Name, "FontChannelGroupsHorizontalDelta") == 0) FontChannelGroupsHorizontalDelta = atoi(Value);
+    else if (strcmp(Name, "FontGridHorizontalDelta") == 0)  FontGridHorizontalDelta = atoi(Value);
+    else if (strcmp(Name, "FontGridHorizontalSmallDelta") == 0) FontGridHorizontalSmallDelta = atoi(Value);
+    else if (strcmp(Name, "FontTimeLineDateHorizontalDelta") == 0) FontTimeLineDateHorizontalDelta = atoi(Value);
+    else if (strcmp(Name, "FontTimeLineTimeHorizontalDelta") == 0) FontTimeLineTimeHorizontalDelta = atoi(Value);
+    else if (strcmp(Name, "FontRecMenuItemDelta") == 0)     FontRecMenuItemDelta = atoi(Value);
+    else if (strcmp(Name, "FontRecMenuItemSmallDelta") == 0) FontRecMenuItemSmallDelta = atoi(Value);
+    else if (strcmp(Name, "FontRecMenuItemLargeDelta") == 0) FontRecMenuItemLargeDelta = atoi(Value);
+    else if (strcmp(Name, "displayRerunsDetailEPGView") == 0) displayRerunsDetailEPGView = atoi(Value);
+    else if (strcmp(Name, "numReruns") == 0)                numReruns = atoi(Value);
+    else if (strcmp(Name, "useSubtitleRerun") == 0)         useSubtitleRerun = atoi(Value);
+    else if (strcmp(Name, "numLogosInitial") == 0)         numLogosInitial = atoi(Value);
+    else if (strcmp(Name, "numLogosMax") == 0)             numLogosMax = atoi(Value);
+    else if (strcmp(Name, "limitLogoCache") == 0)          limitLogoCache = atoi(Value);
+    else return false;
+    return true;
+}
\ No newline at end of file
diff --git a/config.h b/config.h
index 0e184c8..7ebb49f 100644
--- a/config.h
+++ b/config.h
@@ -1,67 +1,255 @@
 #ifndef __TVGUIDE_CONFIG_H
 #define __TVGUIDE_CONFIG_H
 
+#include <vdr/themes.h>
+#include <vdr/plugin.h>
+#include "osdmanager.h"
+#include "geometrymanager.h"
+#include "fontmanager.h"
+#include "imagecache.h"
+
+enum {
+    e12Hours,
+    e24Hours
+};
+
+enum {
+    eVertical,
+    eHorizontal
+};
+
+enum {
+    eNumJump,
+    eGroupJump
+};
+
+enum {
+    eStyleGraphical,
+    eStyleBlendingMagick,
+    eStyleBlendingDefault,
+    eStyleFlat
+};
+
+
+enum eBlueKeyMode {
+    eBlueKeySwitch = 0,
+    eBlueKeyEPG,
+    eBlueKeyFavorites
+};
+
+enum eInstRecFolderMode {
+    eFolderRoot = 0,
+    eFolderSelect,
+    eFolderFixed
+};
+
 class cTvguideConfig {
-	public:
-		cTvguideConfig();
-		~cTvguideConfig();
-		void SetLogoPath(cString path);
-		void SetImagesPath(cString path);
-		int osdWidth; 
-		int osdHeight;
-		int colWidth;
-		int channelCols;
-		int displayTime;
-		int minuteHeight;
-		int timeColWidth;
-		int headerHeight;
-		int footerHeight;
-		int stepMinutes;
-		int bigStepHours;
-		int hugeStepHours;
-		int jumpChannels;
-		int hideChannelLogos;
-		int logoWidth;
-		int logoHeight;
-		cString logoPath;
-		int logoExtension;
-		int hideEpgImages;
-		int epgImageWidth;
-		int epgImageHeight;
-		cString epgImagePath;
-		int fontIndex;
-		const char *fontNameDefault;
-		int fontHeaderSize;
-		int fontGridSize;
-		int fontGridSmallSize;
-		int fontTimeLineWeekdaySize;
-		int fontTimeLineDateSize;
-		int fontTimeLineTimeSize;
-		int fontTimeLineTimeSizeDef12;
-		int fontTimeLineTimeSizeDef24;
-		int fontButtonSize;
-		int fontDetailViewSize;
-		int fontDetailHeaderSize;
-		int fontMessageBoxSize;
-		int fontMessageBoxLargeSize;
-		const cFont *FontHeader;
-		const cFont *FontGrid;
-		const cFont *FontGridSmall;
-		const cFont *FontTimeLineWeekday;
-		const cFont *FontTimeLineDate;
-		const cFont *FontTimeLineTime;
-		const cFont *FontButton;
-		const cFont *FontDetailView;
-		const cFont *FontDetailHeader;
-		const cFont *FontMessageBox;
-		const cFont *FontMessageBoxLarge;
-		int timeFormat;
-		int themeIndex;
-		int useBlending;
-		int roundedCorners;
-		void setDynamicValues(int width, int height);
-		bool SetupParse(const char *Name, const char *Value);
-		void loadTheme();
+    private:
+        cString checkSlashAtEnd(std::string path);
+    public:
+        cTvguideConfig();
+        ~cTvguideConfig();
+        int debugImageLoading;
+        int showMainMenuEntry;
+        int replaceOriginalSchedule;
+        int displayMode;
+        int showTimeInGrid;
+        int channelCols;
+        int channelRows;
+        int numGrids;
+        int displayTime;
+        int displayStatusHeader;
+        int displayChannelGroups;
+        int displayTimeBase;
+        int headerHeightPercent;
+        int channelGroupsPercent;
+        int epgViewBorder;
+        int scaleVideo;
+        int decorateVideo;
+        int timeLineWidthPercent;
+        int timeLineHeightPercent;
+        int displayChannelName;
+        int channelHeaderWidthPercent;
+        int channelHeaderHeightPercent;
+        int footerHeightPercent;
+        int stepMinutes;
+        int bigStepHours;
+        int hugeStepHours;
+        int channelJumpMode;
+        int jumpChannels;
+        int blueKeyMode;
+        int closeOnSwitch;
+        int numkeyMode;
+        int useRemoteTimers;
+        int hideLastGroup;
+        int hideChannelLogos;
+        int logoWidthRatio;
+        int logoHeightRatio;
+        cString logoPath;
+        int logoExtension;
+        int hideEpgImages;
+        int epgImageWidth;
+        int epgImageHeight;
+        int numAdditionalEPGPictures;
+        int epgImageWidthLarge;
+        int epgImageHeightLarge;
+        int detailedViewScrollStep;
+        cString epgImagePath;
+        cString iconPath;
+        cString logoPathDefault;
+        cString iconPathDefault;
+        cString epgImagePathDefault;
+        int instRecFolderMode;
+        std::string instRecFixedFolder;
+        int favWhatsOnNow;
+        int favWhatsOnNext;
+        int favUseTime1;
+        int favUseTime2;
+        int favUseTime3;
+        int favUseTime4;
+        int favTime1;
+        int favTime2;
+        int favTime3;
+        int favTime4;
+        std::string descUser1;
+        std::string descUser2;
+        std::string descUser3;
+        std::string descUser4;
+        int favLimitChannels;
+        int favStartChannel;
+        int favStopChannel;
+        int fontIndex;
+        const char *fontNameDefault;
+        int FontButtonDelta;
+        int FontDetailViewDelta;
+        int FontDetailViewSmallDelta;
+        int FontDetailHeaderDelta;
+        int FontMessageBoxDelta;
+        int FontMessageBoxLargeDelta;
+        int FontStatusHeaderDelta;
+        int FontStatusHeaderLargeDelta;
+        int FontChannelHeaderDelta;
+        int FontChannelGroupsDelta;
+        int FontGridDelta;
+        int FontGridSmallDelta;
+        int FontTimeLineWeekdayDelta;
+        int FontTimeLineDateDelta;
+        int FontTimeLineTimeDelta;
+        int FontChannelHeaderHorizontalDelta;
+        int FontChannelGroupsHorizontalDelta;
+        int FontGridHorizontalDelta;
+        int FontGridHorizontalSmallDelta;
+        int FontTimeLineDateHorizontalDelta;
+        int FontTimeLineTimeHorizontalDelta;
+        int FontRecMenuItemDelta;
+        int FontRecMenuItemSmallDelta;
+        int FontRecMenuItemLargeDelta;
+        int timeFormat;
+        int useNopacityTheme;
+        int themeIndex;
+        int themeIndexCurrent;
+        cString themeName;
+        std::string nOpacityTheme;
+        int style;
+        int roundedCorners;
+        int displayRerunsDetailEPGView;
+        int numReruns;
+        int useSubtitleRerun;
+        int numLogosInitial;
+        int numLogosMax;
+        int limitLogoCache;
+        bool logoPathSet;
+        bool imagesPathSet;
+        bool iconsPathSet;
+        bool LoadTheme();
+        void SetStyle(void);
+        void setDynamicValues(void);
+        void SetLogoPath(cString path);
+        void SetImagesPath(cString path);
+        void SetIconsPath(cString path);
+        void SetDefaultPathes(void);
+        bool SetupParse(const char *Name, const char *Value);
 };
 
+#ifdef DEFINE_CONFIG
+    cTvguideConfig tvguideConfig;
+    cOsdManager osdManager;
+    cGeometryManager geoManager;
+    cFontManager fontManager;
+    cImageCache imgCache;
+    cTheme theme;
+    cPlugin* pRemoteTimers = NULL;
+#else
+    extern cTvguideConfig tvguideConfig;
+    extern cOsdManager osdManager;
+    extern cGeometryManager geoManager;
+    extern cFontManager fontManager;
+    extern cImageCache imgCache;
+    extern cTheme theme;
+    extern cPlugin* pRemoteTimers;
+#endif
+
+
+// --- Theme -------------------------------------------------------------
+//Style SETUP
+#define CLR_STYLE_BLENDING_MAGICK   0xFFFFFFFF
+#define CLR_STYLE_BLENDING_DEFAULT  0xAAAAAAAA
+#define CLR_STYLE_GRAPHICAL         0x66666666
+#define CLR_STYLE_FLAT              0x00000000
+
+THEME_CLR(theme, clrStyle, CLR_STYLE_BLENDING_DEFAULT);
+THEME_CLR(theme, clrBackgroundOSD, 0xB012273f);
+THEME_CLR(theme, clrBackground, 0xFF12273f);
+THEME_CLR(theme, clrGrid1, 0x00000000);
+THEME_CLR(theme, clrGrid1Blending, 0x00000000);
+THEME_CLR(theme, clrGrid2, 0x00000000);
+THEME_CLR(theme, clrGrid2Blending, 0x00000000);
+THEME_CLR(theme, clrHighlight, 0xAA3A3A55);
+THEME_CLR(theme, clrHighlightBlending, 0xDD000000);
+THEME_CLR(theme, clrGridFontBack, clrTransparent);
+THEME_CLR(theme, clrGridActiveFontBack, 0xFFAFD533);
+THEME_CLR(theme, clrFont, clrWhite);
+THEME_CLR(theme, clrFontActive, 0xFF363636);
+THEME_CLR(theme, clrFontHeader, 0xFF363636);
+THEME_CLR(theme, clrFontButtons, clrWhite);
+THEME_CLR(theme, clrStatusHeader, 0x00000000);
+THEME_CLR(theme, clrStatusHeaderBlending, 0x00000000);
+THEME_CLR(theme, clrHeader, 0x00000000);
+THEME_CLR(theme, clrHeaderBlending, 0x00000000);
+THEME_CLR(theme, clrBorder, 0x00000000);
+THEME_CLR(theme, clrTimeline1, clrWhite);
+THEME_CLR(theme, clrTimeline1Blending, 0xFF828282);
+THEME_CLR(theme, clrTimeline2, clrBlack);
+THEME_CLR(theme, clrTimeline2Blending, 0xFF3F3F3F);
+THEME_CLR(theme, clrTimeBase, 0xA0FF0000);
+THEME_CLR(theme, clrTabInactive, 0xA01F3D7A);
+THEME_CLR(theme, clrButtonRed, 0xFFFF0000);
+THEME_CLR(theme, clrButtonRedBorder, 0x00000000);
+THEME_CLR(theme, clrButtonGreen, 0x00000000);
+THEME_CLR(theme, clrButtonGreenBorder, 0x00000000);
+THEME_CLR(theme, clrButtonYellow, 0x00000000);
+THEME_CLR(theme, clrButtonYellowBorder, 0x00000000);
+THEME_CLR(theme, clrButtonBlue, 0x00000000);
+THEME_CLR(theme, clrButtonBlueBorder, 0x00000000);
+THEME_CLR(theme, clrButtonBlend, 0xDD000000);
+THEME_CLR(theme, clrRecMenuBackground, 0xAA000000);
+THEME_CLR(theme, clrRecMenuTimerConflictBackground, 0xFFCCCCCC);
+THEME_CLR(theme, clrRecMenuTimerConflictBar, 0xFF222222);
+THEME_CLR(theme, clrRecMenuTimerConflictOverlap, 0xAAFF0000);
+THEME_CLR(theme, clrRecMenuDayActive, 0xFF00FF00);
+THEME_CLR(theme, clrRecMenuDayInactive, 0xFFFF0000);
+THEME_CLR(theme, clrRecMenuDayHighlight, 0x44FFFFFF);
+THEME_CLR(theme, clrRecMenuTextBack, 0xFF000000);
+THEME_CLR(theme, clrRecMenuTextActiveBack, 0xFF939376);
+THEME_CLR(theme, clrRecMenuKeyboardBack, 0xFF000000);
+THEME_CLR(theme, clrRecMenuKeyboardBorder, clrWhite);
+THEME_CLR(theme, clrRecMenuKeyboardHigh, 0x40BB0000);
+THEME_CLR(theme, clrButtonRedKeyboard, 0xFFBB0000);
+THEME_CLR(theme, clrButtonGreenKeyboard, 0xFF00BB00);
+THEME_CLR(theme, clrButtonYellowKeyboard, 0xFFBBBB00);
+THEME_CLR(theme, clrRecMenuTimelineTimer, 0xB012273f);
+THEME_CLR(theme, clrRecMenuTimelineBack, 0xFF828282);
+THEME_CLR(theme, clrRecMenuTimelineActive, 0xFF3F3F3F);
+THEME_CLR(theme, clrRecMenuTimelineConflict, 0x30FF0000);
+THEME_CLR(theme, clrRecMenuTimelineConflictOverlap, 0x90FF0000);
 #endif //__TVGUIDE_CONFIG_H
\ No newline at end of file
diff --git a/detailview.c b/detailview.c
index e867315..ca351ab 100644
--- a/detailview.c
+++ b/detailview.c
@@ -1,196 +1,159 @@
 #include "detailview.h"
 
-cDetailView::cDetailView(cEpgGrid *grid) {
-	this->grid = grid;
-	this->event = grid->GetEvent();
-	imgScrollBar = NULL;
-	FrameTime = 40; // ms
-	FadeTime = 500; // ms
-	borderWidth = 100; //px
-	headerHeight = max (80 + tvguideConfig.logoHeight +	3 * tvguideConfig.FontDetailHeader->Height(), // border + logo + 3 Lines
-						80 + tvguideConfig.epgImageHeight);
-	description.Set(event->Description(), tvguideConfig.FontDetailView, tvguideConfig.osdWidth-2*borderWidth - 50 - 40);
-	contentScrollable = setContentDrawportHeight();
-	createPixmaps();
+cDetailView::cDetailView(const cEvent *event, cFooter *footer) {
+    this->event = event;
+    this->footer = footer;
 }
 
 cDetailView::~cDetailView(void){
-	delete header;
-	osdManager.releasePixmap(headerLogo);
-    osdManager.releasePixmap(headerBack);
-	osdManager.releasePixmap(content);
-	osdManager.releasePixmap(scrollBar);
-	osdManager.releasePixmap(footer);
-	delete imgScrollBar;
+    Cancel(-1);
+    while (Active())
+        cCondWait::SleepMs(10);
+    footer->LeaveDetailedViewMode(Channels.GetByChannelID(event->ChannelID()));
+    if (view)
+        delete view;
 }
 
-bool cDetailView::setContentDrawportHeight() {
-	int linesContent = description.Lines() + 1;
-	heightContent = linesContent * tvguideConfig.FontDetailView->Height();
-	if (heightContent > (tvguideConfig.osdHeight - 2 * borderWidth - headerHeight))
-		return true;
-	else
-		return false;
+void cDetailView::InitiateView(void) {
+    static cPlugin *pScraper2Vdr = cPluginManager::GetPlugin("scraper2vdr");
+    ScraperGetEventType call;
+    if (!event)
+        return;
+    call.event = event;
+    if (!pScraper2Vdr) {
+        view = new cEPGView();
+    } else if (pScraper2Vdr->Service("GetEventType", &call)) {
+        if (call.type == tMovie) {
+            view = new cMovieView(call.movieId);
+        } else if (call.type == tSeries) {
+            view = new cSeriesView(call.seriesId, call.episodeId);
+        }
+    } else {
+        view = new cEPGView();                
+    }
+    view->SetTitle(event->Title());
+    view->SetSubTitle(event->ShortText());
+    view->SetInfoText(event->Description());
+    cString dateTime;
+    time_t vps = event->Vps();
+    if (vps) {
+        dateTime = cString::sprintf("%s  %s - %s (%d %s) VPS: %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString(), event->Duration()/60, tr("min"), *TimeString(vps));
+    } else {
+        dateTime = cString::sprintf("%s  %s - %s (%d %s)", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString(), event->Duration()/60, tr("min"));
+    }
+    view->SetDateTime(*dateTime);
+    view->SetChannel(Channels.GetByChannelID(event->ChannelID(), true));
+    view->SetEventID(event->EventID());
+    view->SetEvent(event);
 }
 
-void cDetailView::createPixmaps() {
-	int scrollBarWidth = 50;
-	
-	header = new cStyledPixmap(osdManager.requestPixmap(5, cRect(borderWidth, borderWidth, tvguideConfig.osdWidth - 2*borderWidth, headerHeight), cRect::Null, "detailViewHeader"), "detailViewHeader");
-	header->SetAlpha(0);
-	headerLogo = osdManager.requestPixmap(6, cRect(borderWidth, borderWidth, tvguideConfig.osdWidth - 2*borderWidth, headerHeight), cRect::Null, "detailViewHeaderLogo");
-    headerLogo->Fill(clrTransparent);
-	headerLogo->SetAlpha(0);
-	headerBack = osdManager.requestPixmap(4, cRect(borderWidth, borderWidth, tvguideConfig.osdWidth - 2*borderWidth, headerHeight), cRect::Null, "detailViewHeaderBack");
-	headerBack->SetAlpha(0);
-    headerBack->Fill(clrBlack);
-    header->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
-	content = osdManager.requestPixmap(5, cRect(borderWidth, borderWidth + headerHeight, tvguideConfig.osdWidth - 2*borderWidth - scrollBarWidth, tvguideConfig.osdHeight-2*borderWidth-headerHeight),
-									cRect(0,0, tvguideConfig.osdWidth - 2*borderWidth - scrollBarWidth, max(heightContent, tvguideConfig.osdHeight-2*borderWidth-headerHeight)));	
-	content->SetAlpha(0);
-	header->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
-	
-	scrollBar = osdManager.requestPixmap(5, cRect(tvguideConfig.osdWidth-borderWidth-scrollBarWidth, borderWidth + headerHeight, scrollBarWidth, tvguideConfig.osdHeight-2*borderWidth-headerHeight));
-	scrollBar->SetAlpha(0);
-	
-	footer = osdManager.requestPixmap(5, cRect(borderWidth, borderWidth + headerHeight + content->ViewPort().Height(), tvguideConfig.osdWidth - 2*borderWidth, 3));
-	footer->SetAlpha(0);
-	footer->Fill(theme.Color(clrBorder));
-}
+std::string cDetailView::LoadReruns(void) {
+    if (!event)
+        return "";
+    
+    cPlugin *epgSearchPlugin = cPluginManager::GetPlugin("epgsearch");
+    if (!epgSearchPlugin)
+        return "";
 
-void cDetailView::drawHeader() {
-    header->drawBackground();
-	header->drawBoldBorder();
-	
-	int lineHeight = tvguideConfig.FontDetailHeader->Height();
-	int offset = 30;
-	cImageLoader imgLoader;
-	if (tvguideConfig.hideChannelLogos) {
-		header->DrawText(cPoint(20, offset + 10), grid->column->getChannel()->Name(), theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailHeader);
-		offset += lineHeight + 10;
-	} else {
-		if (imgLoader.LoadLogo(grid->column->getChannel()->Name())) {
-			cImage logo = imgLoader.GetImage();
-			headerLogo->DrawImage(cPoint(20, 20), logo);
-		}
-		offset += tvguideConfig.logoHeight;
-	}
-	
-	if (!tvguideConfig.hideEpgImages) {
-		if (imgLoader.LoadEPGImage(event->EventID())) {
-			cImage epgImage = imgLoader.GetImage();
-			int epgImageX = header->Width() - 30 - tvguideConfig.epgImageWidth;
-			int epgImageY = (header->Height() - 10 - tvguideConfig.epgImageHeight) / 2;
-			header->DrawRectangle(cRect(epgImageX-2, epgImageY-2, tvguideConfig.epgImageWidth + 4, tvguideConfig.epgImageHeight + 4), theme.Color(clrBorder));
-			header->DrawImage(cPoint(epgImageX, epgImageY), epgImage);
-		}
-	}
-	
-	header->DrawText(cPoint(20, offset), event->Title(), theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailHeader);
-	cString datetime = cString::sprintf("%s, %s - %s (%d min)", *event->GetDateString(),  *event->GetTimeString(), *event->GetEndTimeString(), event->Duration()/60);
-	header->DrawText(cPoint(20, offset + lineHeight), *datetime, theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailView);
-	header->DrawText(cPoint(20, offset + 2 * lineHeight), event->ShortText(), theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailView);
-}
+    if (isempty(event->Title()))
+        return "";
+    
+    std::stringstream sstrReruns;
+    sstrReruns << tr("Reruns of ") << "\"" << event->Title() << "\":" << std::endl << std::endl;
 
-void cDetailView::drawContent() {
-	content->Fill(theme.Color(clrBorder));
-	content->DrawRectangle(cRect(2, 0, content->ViewPort().Width() - 2, content->DrawPort().Height()), theme.Color(clrBackground));
-	
-	int textHeight = tvguideConfig.FontDetailView->Height();
-	int textLines = description.Lines();
-	
-	for (int i=0; i<textLines; i++) {
-		content->DrawText(cPoint(20, 20 + i*textHeight), description.GetLine(i), theme.Color(clrFont), clrTransparent, tvguideConfig.FontDetailView);
-	}
-}
+    Epgsearch_searchresults_v1_0 data;
+    std::string strQuery = event->Title();
 
-void cDetailView::drawScrollbar() {
-	scrollBar->Fill(theme.Color(clrBorder));
-	double scrollBarOffset = 0.0;
-	if (contentScrollable) {
-		heightScrollbar =  ( (double)scrollBar->ViewPort().Height() ) / (double)heightContent * ( (double)scrollBar->ViewPort().Height() );
-		scrollBarOffset = (-1.0)*(double)content->DrawPort().Point().Y() / (double)(content->DrawPort().Height() - (tvguideConfig.osdHeight-2*borderWidth-headerHeight));
-		scrollBarOffset *= ( (double)scrollBar->ViewPort().Height()-7.0  - heightScrollbar); 
-		scrollBarOffset++;
-	} else {
-		heightScrollbar =  scrollBar->ViewPort().Height();
-	}
-	scrollBar->DrawRectangle(cRect(3,0,scrollBar->ViewPort().Width()-6, scrollBar->ViewPort().Height()), theme.Color(clrBackground));
-	if (imgScrollBar == NULL) {
-		imgScrollBar = createScrollbar(scrollBar->ViewPort().Width()-10, heightScrollbar, theme.Color(clrHighlight), theme.Color(clrHighlightBlending));
-	}
-	scrollBar->DrawImage(cPoint(5, 2 + scrollBarOffset), *imgScrollBar);
-}
+    if (tvguideConfig.displayRerunsDetailEPGView > 0) {
+        if (tvguideConfig.useSubtitleRerun == 2 && !isempty(event->ShortText())) {
+            strQuery += "~";
+            strQuery += event->ShortText();
+        }
+        data.useSubTitle = true;
+    } else {
+        data.useSubTitle = false;
+    }
+    data.query = (char *)strQuery.c_str();
+    data.mode = 0;
+    data.channelNr = 0;
+    data.useTitle = true;
+    data.useDescription = false;
 
-void cDetailView::scrollUp() {
-	if (contentScrollable) {
-		int newDrawportHeight = content->DrawPort().Point().Y() + tvguideConfig.FontDetailView->Height();
-		content->SetDrawPortPoint(cPoint(0, min(newDrawportHeight,0)));
-		drawScrollbar();
-	}
-}
+    bool foundRerun = false;
+    if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) {
+        cList<Epgsearch_searchresults_v1_0::cServiceSearchResult>* list = data.pResultList;
+        if (list && (list->Count() > 1)) {
+            foundRerun = true;
+            int i = 0;
+            for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r && i < tvguideConfig.numReruns; r = list->Next(r)) {
+                if ((event->ChannelID() == r->event->ChannelID()) && (event->StartTime() == r->event->StartTime()))
+                    continue;
+                i++;
+                sstrReruns  << *DayDateTime(r->event->StartTime());
+                cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true);
+                if (channel) {
+                    sstrReruns << ", " << trVDR("Channel") << " " << channel->Number() << ":";
+                    sstrReruns << " " << channel->ShortName(true);
+                }
+                sstrReruns << "\n" << r->event->Title();
+                if (!isempty(r->event->ShortText()))
+                    sstrReruns << "~" << r->event->ShortText();
+                sstrReruns << std::endl << std::endl;
+            }
+            delete list;
+        }
+    }
 
-void cDetailView::scrollDown() {
-	if (contentScrollable) {
-		int newDrawportHeight = content->DrawPort().Point().Y() - tvguideConfig.FontDetailView->Height();
-		int maxDrawportHeight = (content->DrawPort().Height() - (tvguideConfig.osdHeight-2*borderWidth-headerHeight));
-		content->SetDrawPortPoint(cPoint(0, max(newDrawportHeight,(-1)*maxDrawportHeight)));
-		drawScrollbar();
-	}
+    if (!foundRerun) {
+        sstrReruns << std::endl << tr("No reruns found");        
+    }
+    return sstrReruns.str();
 }
 
-cImage *cDetailView::createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend) {
-	cImage *image = new cImage(cSize(width, height));
-	image->Fill(clrBgr);
-	if (tvguideConfig.useBlending) {
-		int numSteps = 64;
-		int alphaStep = 0x03;
-		if (height < 30)
-			return image;
-		else if (height < 100) {
-			numSteps = 32;
-			alphaStep = 0x06;
-		}
-		int stepY = 0.5*height / numSteps;
-		if (stepY == 0)
-			stepY = 1;
-		int alpha = 0x40;
-		tColor clr;
-		for (int i = 0; i<numSteps; i++) {
-			clr = AlphaBlend(clrBgr, clrBlend, alpha);
-			for (int y = i*stepY; y < (i+1)*stepY; y++) {
-				for (int x=0; x<width; x++) {
-					image->SetPixel(cPoint(x,y), clr);
-				}
-			}
-			alpha += alphaStep;
-		}
-	}
-	return image;
-}
 
 void cDetailView::Action(void) {
-	drawHeader();
-	drawContent();
-	drawScrollbar();
-	uint64_t Start = cTimeMs::Now();
-	while (true) {
-		uint64_t Now = cTimeMs::Now();
-		cPixmap::Lock();
-		double t = min(double(Now - Start) / FadeTime, 1.0);
-	    int Alpha = t * ALPHA_OPAQUE;
-	    header->SetAlpha(Alpha);
-        headerBack->SetAlpha(Alpha);
-        headerLogo->SetAlpha(Alpha);
-		content->SetAlpha(Alpha);
-		scrollBar->SetAlpha(Alpha);
-		footer->SetAlpha(Alpha);
-		osdManager.flush();
-		cPixmap::Unlock();
-        int Delta = cTimeMs::Now() - Now;
-        if (Delta < FrameTime)
-           cCondWait::SleepMs(FrameTime - Delta);
-		if ((Now - Start) > FadeTime)
-			break;
+    InitiateView();
+    if (!view)
+        return;
+    view->SetFonts();
+    view->SetGeometry();
+    view->LoadMedia();
+    view->Start();
+    if (event)
+        view->SetAdditionalInfoText(LoadReruns());
+}
+
+eOSState cDetailView::ProcessKey(eKeys Key) {
+    eOSState state = osContinue;
+    if (Running())
+        return state;
+    switch (Key & ~k_Repeat) {
+        case kUp: {
+            bool scrolled = view->KeyUp();
+            if (scrolled) {
+                view->DrawScrollbar();
+                osdManager.flush();
+            }
+            break; }
+        case kDown: {
+            bool scrolled = view->KeyDown();
+            if (scrolled) {
+                view->DrawScrollbar();
+                osdManager.flush();
+            }
+            break; }
+        case kLeft:
+            view->KeyLeft();
+            view->Start();
+            break;
+        case kRight:
+            view->KeyRight();
+            view->Start();
+            break;
+        case kOk:
+        case kBack:
+            state = osEnd;
+            break;
     }
+    return state;
 }
\ No newline at end of file
diff --git a/detailview.h b/detailview.h
index f8219d5..58f653e 100644
--- a/detailview.h
+++ b/detailview.h
@@ -1,41 +1,28 @@
 #ifndef __TVGUIDE_DETAILVIEW_H
 #define __TVGUIDE_DETAILVIEW_H
 
-// --- cDetailView  -------------------------------------------------------------
+#include <vdr/plugin.h>
+#include <vdr/epg.h>
+#include "config.h"
+#include "tools.h"
+#include "styledpixmap.h"
+#include "footer.h"
+#include "view.h"
 
-class cEpgGrid;
+// --- cDetailView  -------------------------------------------------------------
 
-class cDetailView : public cThread  {
+class cDetailView : public cThread {
 private:
-	cEpgGrid *grid;
-	cStyledPixmap *header;
-	cPixmap *headerLogo;
-	cPixmap *headerBack;
-	cPixmap *content;
-	cPixmap *scrollBar;
-	cPixmap *footer;
-	const cEvent *event;
-	cImage *imgScrollBar;
-	int FrameTime;
-	int FadeTime;
-	cTextWrapper description;
-	int borderWidth;
-	int headerHeight;
-	bool setContentDrawportHeight();
-	int heightContent;
-	int heightScrollbar;
-	bool contentScrollable;
-	virtual void Action(void);
-	void drawHeader();
-	void drawContent();
-	void drawScrollbar();
-	cImage *createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend);
+    const cEvent *event;
+    cFooter *footer;
+    cView *view;
+    void InitiateView(void);
+    std::string LoadReruns(void);
+    void Action(void);
 public:
-	cDetailView(cEpgGrid *grid);
-	virtual ~cDetailView(void);
-	void createPixmaps();
-	void scrollUp();
-	void scrollDown();
+    cDetailView(const cEvent *event, cFooter *footer);
+    virtual ~cDetailView(void);
+    eOSState ProcessKey(eKeys Key);
 };
 
 #endif //__TVGUIDE_DETAILVIEW_H
\ No newline at end of file
diff --git a/dummygrid.c b/dummygrid.c
new file mode 100644
index 0000000..2ab9056
--- /dev/null
+++ b/dummygrid.c
@@ -0,0 +1,111 @@
+#include "dummygrid.h"
+
+cDummyGrid::cDummyGrid(cChannelColumn *c, time_t start, time_t end) : cGrid(c) {
+    this->start = start;
+    this->end = end;
+    strText = tr("No EPG Information available");
+    dummy = true;
+    hasTimer = false;
+}
+
+cDummyGrid::~cDummyGrid(void) {
+}
+
+time_t cDummyGrid::Duration(void) { 
+    //max Duration 5h
+    if (end - start > 18000)
+        return 18000;
+    return (end - start); 
+};
+
+void cDummyGrid::SetViewportHeight() {
+    int viewportHeightOld = viewportHeight;
+    viewportHeight = Duration() / 60 * geoManager.minutePixel;
+    if (viewportHeight != viewportHeightOld)
+        dirty = true;
+}
+
+void cDummyGrid::PositionPixmap() {
+    int x0, y0;
+    if (tvguideConfig.displayMode == eVertical) {
+        x0 = column->getX();
+        y0 = geoManager.statusHeaderHeight + geoManager.channelHeaderHeight + geoManager.channelGroupsHeight;
+        if ( column->Start() < StartTime() ) {
+            y0 += (StartTime() - column->Start())/60*geoManager.minutePixel;
+        }
+        if (!pixmap) {
+            pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, geoManager.colWidth, viewportHeight));
+        } else if (dirty) {
+            osdManager.releasePixmap(pixmap);
+            pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, geoManager.colWidth, viewportHeight));
+        } else {
+            pixmap->SetViewPort(cRect(x0, y0, geoManager.colWidth, viewportHeight));
+        }
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        x0 = geoManager.channelHeaderWidth + geoManager.channelGroupsWidth;
+        y0 = column->getY();
+        if ( column->Start() < StartTime() ) {
+            x0 += (StartTime() - column->Start())/60*geoManager.minutePixel;
+        }
+        if (!pixmap) {
+            pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, viewportHeight, geoManager.rowHeight));
+        } else if (dirty) {
+            osdManager.releasePixmap(pixmap);
+            pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, viewportHeight, geoManager.rowHeight));
+        } else {
+            pixmap->SetViewPort(cRect(x0, y0, viewportHeight, geoManager.rowHeight));
+        }
+    }
+}
+
+void cDummyGrid::setText() {
+    if (tvguideConfig.displayMode == eVertical) {
+        text->Set(*strText, fontManager.FontGrid, geoManager.colWidth-2*borderWidth);
+    }
+}
+
+void cDummyGrid::drawText() {
+    tColor colorText = (active)?theme.Color(clrFontActive):theme.Color(clrFont);
+    tColor colorTextBack;
+    if (tvguideConfig.style == eStyleFlat)
+        colorTextBack = color;
+    else if (tvguideConfig.style == eStyleGraphical)
+        colorTextBack = (active)?theme.Color(clrGridActiveFontBack):theme.Color(clrGridFontBack);
+    else
+        colorTextBack = clrTransparent;
+    if (tvguideConfig.displayMode == eVertical) {
+        if (Height()/geoManager.minutePixel < 6)
+            return;
+        int textHeight = fontManager.FontGrid->Height();
+        int textLines = text->Lines();
+        for (int i=0; i<textLines; i++) {
+            pixmap->DrawText(cPoint(borderWidth, borderWidth + i*textHeight), text->GetLine(i), colorText, colorTextBack, fontManager.FontGrid);
+        
+        }
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        if (Width()/geoManager.minutePixel < 10) {
+            int titleY = (geoManager.rowHeight - fontManager.FontGridHorizontal->Height())/2;
+            pixmap->DrawText(cPoint(borderWidth - 2, titleY), "...", colorText, colorTextBack, fontManager.FontGridHorizontal);
+            return;
+        }
+        int titleY = (geoManager.rowHeight - fontManager.FontGridHorizontal->Height())/2;
+        pixmap->DrawText(cPoint(borderWidth, titleY), *strText, colorText, colorTextBack, fontManager.FontGridHorizontal);
+    }
+}
+cString cDummyGrid::getText(void) {
+    return strText;
+}
+
+cString cDummyGrid::getTimeString(void) {
+    return cString::sprintf("%s - %s", *TimeString(start), *TimeString(end));
+}
+
+void cDummyGrid::debug() {
+    esyslog("tvguide dummygrid: %s: %s, %s, viewportHeight: %d px, Duration: %ld min, active: %d", 
+                column->Name(),
+                *cMyTime::printTime(start), 
+                *cMyTime::printTime(end), 
+                viewportHeight, 
+                Duration()/60,
+                active);
+}
\ No newline at end of file
diff --git a/dummygrid.h b/dummygrid.h
new file mode 100644
index 0000000..f0837f6
--- /dev/null
+++ b/dummygrid.h
@@ -0,0 +1,34 @@
+#ifndef __TVGUIDE_DUMMYGRID_H
+#define __TVGUIDE_DUMMYGRID_H
+
+#include "grid.h"
+#include "channelcolumn.h"
+
+// --- cDummyGrid  -------------------------------------------------------------
+
+class cDummyGrid : public cGrid {
+private:
+    time_t start;
+    time_t end;
+    cString strText;
+    void drawText();
+    time_t Duration(void);
+public:
+    cDummyGrid(cChannelColumn *c, time_t start, time_t end);
+    virtual ~cDummyGrid(void);
+    void SetViewportHeight();
+    void PositionPixmap();
+    void setText(void);
+    const cEvent *GetEvent() {return NULL;};
+    time_t StartTime() { return start; };
+    time_t EndTime() { return end; };
+    void SetStartTime(time_t start) { this->start = start; };
+    void SetEndTime(time_t end) { this->end = end; };
+    int calcOverlap(cGrid *neighbor);
+    void setTimer() {};
+    cString getText(void);
+    cString getTimeString(void);
+    void debug();
+};
+
+#endif //__TVGUIDE_DUMMYGRID_H
\ No newline at end of file
diff --git a/epggrid.c b/epggrid.c
index 8c8109d..7a21834 100644
--- a/epggrid.c
+++ b/epggrid.c
@@ -1,146 +1,169 @@
+#include "services/remotetimers.h"
 #include "channelcolumn.h"
+#include "tools.h"
 #include "epggrid.h"
 
-cEpgGrid::cEpgGrid(cChannelColumn *c, const cEvent *event) {
-	this->event = event;
-	this->column = c;
-	text = new cTextWrapper();
-	extText = new cTextWrapper();
-	dirty = true;
-	active = false;
-	viewportHeight = 0;
-	borderWidth = 10;
-	hasTimer = false;
-	if (column->hasTimer)
-		hasTimer = event->HasTimer();		
+cEpgGrid::cEpgGrid(cChannelColumn *c, const cEvent *event)  : cGrid(c) {
+    this->event = event;
+    extText = new cTextWrapper();
+    hasTimer = false;
+    SetTimer();
+    hasSwitchTimer = false;
+    SetSwitchTimer();
+    dummy = false;
 }
 
 cEpgGrid::~cEpgGrid(void) {
-	delete text;
-	delete extText;
+    delete extText;
 }
 
 void cEpgGrid::SetViewportHeight() {
-	int viewportHeightOld = viewportHeight;
-	if ( column->myTime->GetStart() > event->StartTime() ) {
-		viewportHeight = (min(event->EndTime(), column->myTime->GetStop()) - column->myTime->GetStart()) /60;
-	} else if ( column->myTime->GetStop() < event->EndTime() ) {
-		viewportHeight = (column->myTime->GetStop() - event->StartTime()) /60;
-	} else {
-		viewportHeight = event->Duration() / 60;
-	}
-	if (viewportHeight != viewportHeightOld)
-		dirty = true;
+    int viewportHeightOld = viewportHeight;
+    if ( column->Start() > StartTime() ) {
+        viewportHeight = (min((int)EndTime(), column->Stop()) - column->Start()) /60;
+    } else if ( column->Stop() < EndTime() ) {
+        viewportHeight = (column->Stop() - StartTime()) /60;
+        if (viewportHeight < 0) viewportHeight = 0;
+    } else {
+        viewportHeight = Duration() / 60;
+    }
+    viewportHeight *= geoManager.minutePixel;
+    if (viewportHeight != viewportHeightOld)
+        dirty = true;
 }
 
 void cEpgGrid::PositionPixmap() {
-	int x0 = column->getX();
-	int y0 = tvguideConfig.headerHeight;
-	if ( column->myTime->GetStart() < event->StartTime() ) {
-		y0 += (event->StartTime() - column->myTime->GetStart())/60*tvguideConfig.minuteHeight;
-	}
+    int x0, y0;
+    if (tvguideConfig.displayMode == eVertical) {
+        int x0 = column->getX();
+        int y0 = geoManager.statusHeaderHeight + geoManager.channelHeaderHeight + geoManager.channelGroupsHeight;
+        if ( column->Start() < StartTime() ) {
+            y0 += (StartTime() - column->Start())/60*geoManager.minutePixel;
+        }
+        if (!pixmap) {
+            pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, geoManager.colWidth, viewportHeight), 
+                                                cRect(0, 0, geoManager.colWidth, Duration()/60*geoManager.minutePixel));
+        } else {
+            pixmap->SetViewPort(cRect(x0, y0, geoManager.colWidth, viewportHeight));
+        }
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        int x0 = geoManager.channelHeaderWidth + geoManager.channelGroupsWidth;
+        int y0 = column->getY();
+        if ( column->Start() < StartTime() ) {
+            x0 += (StartTime() - column->Start())/60*geoManager.minutePixel;
+        }
+        if (!pixmap) {
+            pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, viewportHeight, geoManager.rowHeight), 
+                                                cRect(0, 0, Duration()/60*geoManager.minutePixel, geoManager.rowHeight));
+        } else {
+            pixmap->SetViewPort(cRect(x0, y0, viewportHeight, geoManager.rowHeight ));
+        }
+   }
 
-	if (!pixmap) {
-		caller = cString::sprintf("epggrid %s %s", column->channel->Name(), event->Title());
-		pixmap = osdManager.requestPixmap(-1, cRect(x0, y0, tvguideConfig.colWidth, viewportHeight * tvguideConfig.minuteHeight), 
-											cRect(0, 0, tvguideConfig.colWidth, event->Duration()/60*tvguideConfig.minuteHeight), *caller);
-	} else {
-		pixmap->SetViewPort(cRect(x0, y0, tvguideConfig.colWidth, viewportHeight * tvguideConfig.minuteHeight));
-	}
 }
 
-void cEpgGrid::setBackground() {
-	if (active) {
-		color = theme.Color(clrHighlight);
-		colorBlending = theme.Color(clrHighlightBlending);
-	} else {
-		if (isColor1) {
-			color = theme.Color(clrGrid1);
-			colorBlending = theme.Color(clrGrid1Blending);
-		} else {
-			color = theme.Color(clrGrid2);
-			colorBlending = theme.Color(clrGrid2Blending);
-		}
-	}
-}
-
-void cEpgGrid::Draw() {
-	if (!pixmap) {
-		return;
-	}
-	if (dirty) {
-		setBackground();
-		drawBackground();
-		drawText();
-		if (hasTimer) 
-			DrawRecIcon();
-		drawBorder();
-		pixmap->SetLayer(1);
-		dirty = false;
-	}
+void cEpgGrid::SetTimer() {
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        RemoteTimers_Event_v1_0 rt;
+        rt.event = event;
+        if (pRemoteTimers->Service("RemoteTimers::GetTimerByEvent-v1.0", &rt))
+            hasTimer = true;
+	else
+	    hasTimer = false;
+    } else if (column->HasTimer()) {
+        hasTimer = event->HasTimer();
+    } else {
+        hasTimer = false;
+    }
 }
 
-void cEpgGrid::DrawRecIcon() {
-	cString recIconText("REC");
-	int width = tvguideConfig.FontGrid->Width(*recIconText)+2*borderWidth;
-	int height = tvguideConfig.FontGrid->Height()+10;
-	pixmap->DrawRectangle( cRect(pixmap->ViewPort().Width() - width - borderWidth,  pixmap->ViewPort().Height() - height - borderWidth, width, height), theme.Color(clrButtonRed));
-	pixmap->DrawText(cPoint(pixmap->ViewPort().Width() - width, pixmap->ViewPort().Height() - height - borderWidth/2), *recIconText, theme.Color(clrFont), clrTransparent, tvguideConfig.FontGrid);	
+void cEpgGrid::SetSwitchTimer() {
+    if (column->HasSwitchTimer()) {
+        hasSwitchTimer = SwitchTimers.EventInSwitchList(event);
+    } else {
+        hasSwitchTimer = false;
+    }
 }
 
 void cEpgGrid::setText() {
-	cString strText;
-	strText = cString::sprintf("%s - %s:\n%s", *(event->GetTimeString()), *(event->GetEndTimeString()), event->Title());
-	text->Set(*(strText), tvguideConfig.FontGrid, tvguideConfig.colWidth-2*borderWidth);
-	extText->Set(event->ShortText(), tvguideConfig.FontGridSmall, tvguideConfig.colWidth-2*borderWidth);
+    if (tvguideConfig.displayMode == eVertical) {
+        cString strText;
+        strText = cString::sprintf("%s - %s:\n%s", *(event->GetTimeString()), *(event->GetEndTimeString()), event->Title());
+        text->Set(*(strText), fontManager.FontGrid, geoManager.colWidth-2*borderWidth);
+        extText->Set(event->ShortText(), fontManager.FontGridSmall, geoManager.colWidth-2*borderWidth);
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        timeString = cString::sprintf("%s - %s", *(event->GetTimeString()), *(event->GetEndTimeString()));
+    }
 }
 
 void cEpgGrid::drawText() {
-	int gridHeight = pixmap->ViewPort().Height();
-	if (gridHeight/tvguideConfig.minuteHeight < 6)
-		return;
-	int textHeight = tvguideConfig.FontGrid->Height();
-	int textLines = text->Lines();
-	for (int i=0; i<textLines; i++) {
-		pixmap->DrawText(cPoint(borderWidth, borderWidth + i*textHeight), text->GetLine(i), theme.Color(clrFont), clrTransparent, tvguideConfig.FontGrid);
-	}
-	int extTextLines = extText->Lines();
-	int offset = (textLines+1)*textHeight - 0.5*textHeight;
-	textHeight = tvguideConfig.FontGridSmall->Height();
-	if ((pixmap->ViewPort().Height()-textHeight-10) > offset) {
-		for (int i=0; i<extTextLines; i++) {
-			pixmap->DrawText(cPoint(borderWidth, borderWidth + offset + i*textHeight), extText->GetLine(i), theme.Color(clrFont), clrTransparent, tvguideConfig.FontGridSmall);
-		}
-	}
+    tColor colorText = (active)?theme.Color(clrFontActive):theme.Color(clrFont);
+    tColor colorTextBack;
+    if (tvguideConfig.style == eStyleFlat)
+        colorTextBack = color;
+    else if (tvguideConfig.style == eStyleGraphical)
+        colorTextBack = (active)?theme.Color(clrGridActiveFontBack):theme.Color(clrGridFontBack);
+    else
+        colorTextBack = clrTransparent;
+    if (tvguideConfig.displayMode == eVertical) {
+        if (Height()/geoManager.minutePixel < 6)
+            return;
+        int textHeight = fontManager.FontGrid->Height();
+        int textLines = text->Lines();
+        for (int i=0; i<textLines; i++) {
+            pixmap->DrawText(cPoint(borderWidth, borderWidth + i*textHeight), text->GetLine(i), colorText, colorTextBack, fontManager.FontGrid);
+        }
+        int extTextLines = extText->Lines();
+        int offset = (textLines+1)*textHeight - 0.5*textHeight;
+        textHeight = fontManager.FontGridSmall->Height();
+        if ((Height()-textHeight-10) > offset) {
+            for (int i=0; i<extTextLines; i++) {
+                pixmap->DrawText(cPoint(borderWidth, borderWidth + offset + i*textHeight), extText->GetLine(i), colorText, colorTextBack, fontManager.FontGridSmall);
+            }
+        }
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        if (Width()/geoManager.minutePixel < 10) {
+            int titleY = (geoManager.rowHeight - fontManager.FontGridHorizontal->Height())/2;
+            pixmap->DrawText(cPoint(borderWidth - 2, titleY), "...", colorText, colorTextBack, fontManager.FontGridHorizontal);
+            return;
+        }
+        cString strTitle = CutText(event->Title(), viewportHeight, fontManager.FontGridHorizontal).c_str();
+        int titleY = 0;
+        if (tvguideConfig.showTimeInGrid) {
+            pixmap->DrawText(cPoint(borderWidth, borderWidth), *timeString, colorText, colorTextBack, fontManager.FontGridHorizontalSmall);
+            titleY = fontManager.FontGridHorizontalSmall->Height() + (geoManager.rowHeight - fontManager.FontGridHorizontalSmall->Height() - fontManager.FontGridHorizontal->Height())/2;
+        } else {
+            titleY = (geoManager.rowHeight - fontManager.FontGridHorizontal->Height())/2;
+        }
+        pixmap->DrawText(cPoint(borderWidth, titleY), *strTitle, colorText, colorTextBack, fontManager.FontGridHorizontal);
+    }
+    if (hasSwitchTimer) 
+        drawIcon("Switch", theme.Color(clrButtonYellow));
+    if (hasTimer) 
+        drawIcon("REC", theme.Color(clrButtonRed));
 }
 
-int cEpgGrid::calcOverlap(cEpgGrid *neighbor) {
-	int overlap = 0;
-	if (intersects(neighbor)) {
-		if ((event->StartTime() <= neighbor->StartTime()) && (event->EndTime() <= neighbor->EndTime())) {
-			overlap = event->EndTime() - neighbor->StartTime();
-		} else if ((event->StartTime() >= neighbor->StartTime()) && (event->EndTime() >= neighbor->EndTime())) {
-			overlap = neighbor->EndTime() - event->StartTime();
-		} else if ((event->StartTime() >= neighbor->StartTime()) && (event->EndTime() <= neighbor->EndTime())) {
-			overlap = event->Duration();
-		} else if ((event->StartTime() <= neighbor->StartTime()) && (event->EndTime() >= neighbor->EndTime())) {
-			overlap = neighbor->EndTime() - neighbor->StartTime();
-		}
-	}
-	return overlap;
+void cEpgGrid::drawIcon(cString iconText, tColor color) {
+    
+    const cFont *font = (tvguideConfig.displayMode == eVertical)
+                        ?fontManager.FontGrid
+                        :fontManager.FontGridHorizontalSmall;
+    int textWidth = font->Width(*iconText)+2*borderWidth;
+    int textHeight = font->Height()+10;
+    pixmap->DrawRectangle( cRect(Width() - textWidth - borderWidth, Height() - textHeight - borderWidth, textWidth, textHeight), color);
+    pixmap->DrawText(cPoint(Width() - textWidth, Height() - textHeight - borderWidth/2), *iconText, theme.Color(clrFont), color, font);   
 }
 
-bool cEpgGrid::intersects(cEpgGrid *neighbor) {
-	return ! ( (neighbor->EndTime() <= event->StartTime()) || (neighbor->StartTime() >= event->EndTime()) ); 
-}
-
-bool cEpgGrid::isActiveInitial(time_t t) {
-	if ((event->StartTime() < t) && (event->EndTime() > t))
-		return true;
-	else
-		return false;
+cString cEpgGrid::getTimeString(void) {
+    return cString::sprintf("%s - %s", *(event->GetTimeString()), *(event->GetEndTimeString()));
 }
 
 void cEpgGrid::debug() {
-	esyslog("tvguide Grid: %s, %s, viewportHeight: %d, Duration: %d", *(event->GetTimeString()), event->Title(), viewportHeight, event->Duration()/60);
-}
\ No newline at end of file
+    esyslog("tvguide epggrid: %s: %s, %s, viewportHeight: %d px, Duration: %d min, active: %d", 
+                column->Name(),
+                *(event->GetTimeString()), 
+                event->Title(), 
+                viewportHeight, 
+                event->Duration()/60,
+                active);
+}
diff --git a/epggrid.h b/epggrid.h
index 00160dc..95f40ea 100644
--- a/epggrid.h
+++ b/epggrid.h
@@ -1,44 +1,32 @@
 #ifndef __TVGUIDE_EPGGRID_H
 #define __TVGUIDE_EPGGRID_H
 
+#include <vdr/epg.h>
+#include "grid.h"
+
 // --- cEpgGrid  -------------------------------------------------------------
 
-class cEpgGrid : public cListObject, public cStyledPixmap {
+class cEpgGrid : public cGrid {
 private:
-	const cEvent *event;
-	cTextWrapper *text;
-	cTextWrapper *extText;
-	int viewportHeight;
-	int borderWidth;
-	void drawText();
-	void setBackground();
-	bool isColor1;
-	bool active;
-	bool dirty;
-	bool intersects(cEpgGrid *neighbor);
-	bool hasTimer;
-	void DrawRecIcon();
+    const cEvent *event;
+    cTextWrapper *extText;
+    cString timeString;
+    void drawText();
+    void drawIcon(cString iconText, tColor color);
+    time_t Duration(void) { return event->Duration(); };
 public:
-	cEpgGrid(cChannelColumn *c, const cEvent *event);
-	virtual ~cEpgGrid(void);
-	cChannelColumn *column;
-	void SetViewportHeight();
-	void PositionPixmap();
-	void setText();
-	void Draw();
-	void SetDirty() {dirty = true;};
-	void SetActive() {dirty = true; active = true;};
-	void SetInActive() {dirty = true; active = false;};
-	void SetColor(bool color) {isColor1 = color;};
-	bool IsColor1() {return isColor1;};
-	int GetViewportHeight() {return viewportHeight;};
-	const cEvent *GetEvent() {return event;};
-	bool isActiveInitial(time_t t);
-	time_t StartTime() { return event->StartTime(); };
-	time_t EndTime() { return event->EndTime(); };
-	int calcOverlap(cEpgGrid *neighbor);
-	void setTimer() {hasTimer = true;};
-	void debug();
+    cEpgGrid(cChannelColumn *c, const cEvent *event);
+    virtual ~cEpgGrid(void);
+    void SetViewportHeight();
+    void PositionPixmap();
+    void setText(void);
+    const cEvent *GetEvent() {return event;};
+    time_t StartTime() { return event->StartTime(); };
+    time_t EndTime() { return event->EndTime(); };
+    void SetTimer();
+    void SetSwitchTimer();
+    cString getTimeString(void);
+    void debug();
 };
 
 #endif //__TVGUIDE_EPGGRID_H
\ No newline at end of file
diff --git a/fontmanager.c b/fontmanager.c
new file mode 100644
index 0000000..b55621a
--- /dev/null
+++ b/fontmanager.c
@@ -0,0 +1,96 @@
+#include "geometrymanager.h"
+#include "config.h"
+#include "fontmanager.h"
+
+cFontManager::cFontManager() {
+}
+
+cFontManager::~cFontManager() {
+    DeleteFonts();
+}
+
+void cFontManager::SetFonts() {
+    InitialiseFontType();
+    //Common Fonts
+    FontButton = CreateFont(geoManager.footerHeight/3 + 4 + tvguideConfig.FontButtonDelta);
+    FontDetailView = CreateFont(geoManager.osdHeight/30 + tvguideConfig.FontDetailViewDelta);
+    FontDetailViewSmall = CreateFont(geoManager.osdHeight/40 + tvguideConfig.FontDetailViewSmallDelta);
+    FontDetailHeader = CreateFont(geoManager.osdHeight/27 + tvguideConfig.FontDetailHeaderDelta);
+    FontDetailHeaderLarge = CreateFont(geoManager.osdHeight/20 + tvguideConfig.FontDetailHeaderDelta);
+    FontMessageBox = CreateFont(geoManager.osdHeight/33 + tvguideConfig.FontMessageBoxDelta);
+    FontMessageBoxLarge = CreateFont(geoManager.osdHeight/30 + tvguideConfig.FontMessageBoxLargeDelta);    
+    FontStatusHeader = CreateFont(geoManager.statusHeaderHeight/6 - 4 + tvguideConfig.FontStatusHeaderDelta);
+    FontStatusHeaderLarge = CreateFont(geoManager.statusHeaderHeight/5 + tvguideConfig.FontStatusHeaderLargeDelta);
+    //Fonts for vertical Display 
+    FontChannelHeader = CreateFont(geoManager.colWidth/10 + tvguideConfig.FontChannelHeaderDelta);
+    FontChannelGroups = CreateFont(geoManager.colWidth/8 + tvguideConfig.FontChannelGroupsDelta);
+    FontGrid = CreateFont(geoManager.colWidth/12 + tvguideConfig.FontGridDelta);
+    FontGridSmall = CreateFont(geoManager.colWidth/12 + tvguideConfig.FontGridSmallDelta);
+    FontTimeLineWeekday = CreateFont(geoManager.timeLineWidth/3 + tvguideConfig.FontTimeLineWeekdayDelta);
+    FontTimeLineDate = CreateFont(geoManager.timeLineWidth/4 + tvguideConfig.FontTimeLineDateDelta);
+    FontTimeLineTime = CreateFont(geoManager.timeLineWidth/4 + tvguideConfig.FontTimeLineTimeDelta);
+    //Fonts for horizontal Display 
+    FontChannelHeaderHorizontal = CreateFont(geoManager.rowHeight/3 + tvguideConfig.FontChannelHeaderHorizontalDelta);
+    FontChannelGroupsHorizontal = CreateFont(geoManager.rowHeight/3 + 5 + tvguideConfig.FontChannelGroupsHorizontalDelta);
+    FontGridHorizontal = CreateFont(geoManager.rowHeight/3 + 5 + tvguideConfig.FontGridHorizontalDelta);
+    FontGridHorizontalSmall = CreateFont(geoManager.rowHeight/4 + tvguideConfig.FontGridHorizontalSmallDelta);
+    FontTimeLineDateHorizontal = CreateFont(geoManager.timeLineHeight/2 + 5 + tvguideConfig.FontTimeLineDateHorizontalDelta);
+    FontTimeLineTimeHorizontal = CreateFont(geoManager.timeLineHeight/2 + tvguideConfig.FontTimeLineTimeHorizontalDelta);
+    //Fonts for RecMenu
+    FontRecMenuItem = CreateFont(geoManager.osdHeight/30 + tvguideConfig.FontRecMenuItemDelta);
+    FontRecMenuItemSmall = CreateFont(geoManager.osdHeight/40 + tvguideConfig.FontRecMenuItemSmallDelta);
+    FontRecMenuItemLarge = CreateFont(geoManager.osdHeight/25 + tvguideConfig.FontRecMenuItemLargeDelta);
+}
+
+void cFontManager::DeleteFonts() {
+    delete FontButton;
+    delete FontDetailView;
+    delete FontDetailViewSmall;
+    delete FontDetailHeader;
+    delete FontDetailHeaderLarge;
+    delete FontMessageBox;
+    delete FontMessageBoxLarge;
+    delete FontStatusHeader;
+    delete FontStatusHeaderLarge;
+    delete FontChannelHeader;
+    delete FontChannelGroups;
+    delete FontGrid;
+    delete FontGridSmall;
+    delete FontTimeLineWeekday;
+    delete FontTimeLineDate;
+    delete FontTimeLineTime;
+    delete FontChannelHeaderHorizontal;
+    delete FontChannelGroupsHorizontal;
+    delete FontGridHorizontal;
+    delete FontGridHorizontalSmall;
+    delete FontTimeLineDateHorizontal;
+    delete FontTimeLineTimeHorizontal;
+    delete FontRecMenuItem;
+    delete FontRecMenuItemSmall;
+    delete FontRecMenuItemLarge;
+}
+
+void cFontManager::InitialiseFontType(void) {
+    if (tvguideConfig.fontIndex == 0) {
+        fontName = tvguideConfig.fontNameDefault;
+    } else {
+        cStringList availableFonts;
+        cFont::GetAvailableFontNames(&availableFonts);
+        if (availableFonts[tvguideConfig.fontIndex-1]) {
+            fontName = availableFonts[tvguideConfig.fontIndex-1];
+        } else 
+            fontName = tvguideConfig.fontNameDefault;
+    }
+    cFont *test = NULL;
+    test = cFont::CreateFont(*fontName, 30);
+    if (!test) {
+        fontName = DefaultFontSml;
+    }
+    delete test;
+    esyslog("tvguide: Set Font to %s", *fontName);
+}
+
+cFont *cFontManager::CreateFont(int size) {
+    return cFont::CreateFont(*fontName, size);
+}
+
diff --git a/fontmanager.h b/fontmanager.h
new file mode 100644
index 0000000..7253043
--- /dev/null
+++ b/fontmanager.h
@@ -0,0 +1,41 @@
+#ifndef __TVGUIDE_FONTMANAGER_H
+#define __TVGUIDE_FONTMANAGER_H
+
+#include <vdr/skins.h>
+
+class cFontManager {
+		cString fontName;
+        void InitialiseFontType(void);
+        cFont *CreateFont(int size);
+    public:
+        cFontManager();
+        ~cFontManager();
+        void SetFonts(void);
+        void DeleteFonts(void);
+        cFont *FontChannelHeader;
+        cFont *FontChannelHeaderHorizontal;
+        cFont *FontChannelGroups;
+        cFont *FontChannelGroupsHorizontal;
+        cFont *FontStatusHeader;
+        cFont *FontStatusHeaderLarge;
+        cFont *FontGrid;
+        cFont *FontGridSmall;
+        cFont *FontGridHorizontal;
+        cFont *FontGridHorizontalSmall;
+        cFont *FontTimeLineWeekday;
+        cFont *FontTimeLineDate;
+        cFont *FontTimeLineDateHorizontal;
+        cFont *FontTimeLineTime;
+        cFont *FontTimeLineTimeHorizontal;
+        cFont *FontButton;
+        cFont *FontDetailView;
+        cFont *FontDetailViewSmall;
+        cFont *FontDetailHeader;
+        cFont *FontDetailHeaderLarge;
+        cFont *FontMessageBox;
+        cFont *FontMessageBoxLarge;
+        cFont *FontRecMenuItem;
+        cFont *FontRecMenuItemSmall;
+        cFont *FontRecMenuItemLarge;
+};
+#endif //__TVGUIDE_FONTMANAGER_H
\ No newline at end of file
diff --git a/footer.c b/footer.c
index 6b908e8..7a5b9e5 100644
--- a/footer.c
+++ b/footer.c
@@ -1,53 +1,167 @@
+#include <string>
+#include "imageloader.h"
+#include "tools.h"
 #include "footer.h"
 
-cFooter::cFooter() {
-    buttonBorder = 20;
-	buttonWidth = (tvguideConfig.osdWidth - tvguideConfig.timeColWidth - 5*buttonBorder)/4;
-	buttonHeight= tvguideConfig.footerHeight - 2*buttonBorder;
-    buttonY = (tvguideConfig.footerHeight - buttonHeight)/2;
-	
-    footer = osdManager.requestPixmap(2, cRect( tvguideConfig.timeColWidth, 
-                                                tvguideConfig.osdHeight - tvguideConfig.footerHeight, 
-                                                tvguideConfig.osdWidth - tvguideConfig.timeColWidth, 
-                                                tvguideConfig.footerHeight),
-                                         cRect::Null, "footer");
+cFooter::cFooter(cChannelGroups *channelGroups) {
+    this->channelGroups = channelGroups;
+    currentGroup = -1;
+    buttonY = (geoManager.footerHeight - geoManager.buttonHeight)/2;
+    SetButtonPositions();
+    footer = osdManager.requestPixmap(2, cRect( 0, 
+                                                geoManager.footerY, 
+                                                geoManager.osdWidth, 
+                                                geoManager.footerHeight),
+                                         cRect::Null);
     footer->Fill(clrTransparent);
 }
 
 cFooter::~cFooter(void) {
-    osdManager.releasePixmap(footer, "footer");;
+    osdManager.releasePixmap(footer);
 }
 
 void cFooter::drawRedButton() {
-    cString text(tr("Set Timer"));
-    DrawButton(*text, theme.Color(clrButtonRed), theme.Color(clrButtonRedBorder), 0);
+    cString text(tr("Search & Rec"));
+    DrawButton(*text, theme.Color(clrButtonRed), theme.Color(clrButtonRedBorder), oeButtonRed, positionButtons[0]);
 }
 
 void cFooter::drawGreenButton() {
     cString text = cString::sprintf("%d %s", tvguideConfig.jumpChannels, tr("Channels back"));
-    DrawButton(*text, theme.Color(clrButtonGreen), theme.Color(clrButtonGreenBorder), 1);
+    DrawButton(*text, theme.Color(clrButtonGreen), theme.Color(clrButtonGreenBorder), oeButtonGreen, positionButtons[1]);
+}
+
+void cFooter::drawGreenButton(const char *text) {
+    std::string cuttedText = CutText(text, geoManager.buttonWidth-6, fontManager.FontButton);
+    DrawButton(cuttedText.c_str(), theme.Color(clrButtonGreen), theme.Color(clrButtonGreenBorder), oeButtonGreen, positionButtons[1]);
 }
 
 void cFooter::drawYellowButton() {
     cString text = cString::sprintf("%d %s", tvguideConfig.jumpChannels, tr("Channels forward"));
-    DrawButton(*text, theme.Color(clrButtonYellow), theme.Color(clrButtonYellowBorder), 2);
+    DrawButton(*text, theme.Color(clrButtonYellow), theme.Color(clrButtonYellowBorder), oeButtonYellow, positionButtons[2]);
 }
 
-void cFooter::drawBlueButton() {
-    cString text(tr("Switch to Channel"));
-    DrawButton(*text, theme.Color(clrButtonBlue), theme.Color(clrButtonBlueBorder), 3);
+void cFooter::drawYellowButton(const char *text) {
+    std::string cuttedText = CutText(text, geoManager.buttonWidth-6, fontManager.FontButton);
+    DrawButton(cuttedText.c_str(), theme.Color(clrButtonYellow), theme.Color(clrButtonYellowBorder), oeButtonYellow, positionButtons[2]);
 }
 
-void cFooter::DrawButton(const char *text, tColor color, tColor borderColor, int num) {
-    
-    int left = num * buttonWidth + (num + 1) * buttonBorder;
-    footer->DrawRectangle(cRect(left, buttonY, buttonWidth, buttonHeight), borderColor);
-    
-    cImageLoader imgLoader;
-    imgLoader.DrawBackground(theme.Color(clrButtonBlend), color, buttonWidth-4, buttonHeight-4);
-    footer->DrawImage(cPoint(left+2, buttonY+2), imgLoader.GetImage());    
+void cFooter::drawBlueButton(bool detailedEPG) {
+    cString text;
+    if (tvguideConfig.blueKeyMode == eBlueKeySwitch)
+        text = tr("Switch to Channel");
+    else if (tvguideConfig.blueKeyMode == eBlueKeyEPG) {
+        if (!detailedEPG)
+            text = tr("Detailed EPG");
+        else
+            text = tr("Close detailed EPG");
+    } else if (tvguideConfig.blueKeyMode == eBlueKeyFavorites) {
+        if (!detailedEPG)
+            text = tr("Favorites");
+        else
+            text = tr("Switch to Channel");
+    }
+    DrawButton(*text, theme.Color(clrButtonBlue), theme.Color(clrButtonBlueBorder), oeButtonBlue, positionButtons[3]);
+}
+
+void cFooter::UpdateGroupButtons(const cChannel *channel, bool force) {
+    if (!channel)
+        return;
+    int group = channelGroups->GetGroup(channel);
+    if ((group != currentGroup) || force) {
+        currentGroup = group;
+        drawGreenButton(channelGroups->GetPrev(group));
+        drawYellowButton(channelGroups->GetNext(group));
+    }
+}
+
+void cFooter::SetDetailedViewMode(bool fromRecMenu) {
+    ClearButton(positionButtons[1]);
+    ClearButton(positionButtons[2]);
+    if (fromRecMenu) {
+        ClearButton(positionButtons[0]);
+        ClearButton(positionButtons[3]);
+    } else if (tvguideConfig.blueKeyMode != eBlueKeySwitch) {
+        ClearButton(positionButtons[3]);
+        drawBlueButton(true);
+    }
+}
+
+void cFooter::LeaveDetailedViewMode(const cChannel *channel) {
+    drawRedButton();
+    drawBlueButton();
+    if (tvguideConfig.channelJumpMode == eNumJump) {
+        drawGreenButton();
+        drawYellowButton();
+    } else {
+        UpdateGroupButtons(channel, true);
+    }
+}
+
+void cFooter::SetButtonPositions(void) {
+    for (int i=0; i < 4; i++) {
+        positionButtons[i] = -1;
+    }
+    /*
+    red button = 0
+    green button = 1
+    yellow button = 2
+    blue button = 3
+    */
+    for (int button=0; button<4; button++) {
+        if (Setup.ColorKey0 == button) {
+            positionButtons[button] = 0;
+            continue;
+        }
+        if (Setup.ColorKey1 == button) {
+            positionButtons[button] = 1;
+            continue;
+        }
+        if (Setup.ColorKey2 == button) {
+            positionButtons[button] = 2;
+            continue;
+        }
+        if (Setup.ColorKey3 == button) {
+            positionButtons[button] = 3;
+            continue;
+        }
+    }
+}
+
+void cFooter::DrawButton(const char *text, tColor color, tColor borderColor, eOsdElementType buttonType, int num) {
+    tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+    int left = num * geoManager.buttonWidth + (2 * num + 1) * geoManager.buttonBorder;
+
+    if ((tvguideConfig.style == eStyleBlendingMagick) || (tvguideConfig.style == eStyleBlendingDefault)) {
+        cImageLoader imgLoader;
+        imgLoader.DrawBackground(theme.Color(clrButtonBlend), color, geoManager.buttonWidth-4, geoManager.buttonHeight-4);
+        footer->DrawRectangle(cRect(left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight), borderColor);
+        footer->DrawImage(cPoint(left+2, buttonY+2), imgLoader.GetImage());    
+        if (tvguideConfig.roundedCorners) {
+            int borderRadius = 12;
+            int borderWidth = 2;
+            DrawRoundedCorners(footer, left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight, borderRadius, borderWidth, borderColor);
+        }
+    } else if (tvguideConfig.style == eStyleGraphical) {
+        cImage *button = imgCache.GetOsdElement(buttonType);
+        if (button) {
+            footer->DrawImage(cPoint(left, buttonY), *button);    
+        }
+    } else {
+        footer->DrawRectangle(cRect(left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight), borderColor); 
+        footer->DrawRectangle(cRect(left+1, buttonY+1, geoManager.buttonWidth-2, geoManager.buttonHeight-2), color);
+        if (tvguideConfig.roundedCorners) {
+            int borderRadius = 12;
+            int borderWidth = 1;
+            DrawRoundedCorners(footer, left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight, borderRadius, borderWidth, borderColor);
+        }
+    }
     
-    int textWidth = tvguideConfig.FontButton->Width(text);
-    int textHeight = tvguideConfig.FontButton->Height();
-    footer->DrawText(cPoint(left + (buttonWidth-textWidth)/2, buttonY + (buttonHeight-textHeight)/2), text, theme.Color(clrFontButtons), clrTransparent, tvguideConfig.FontButton);
+    int textWidth = fontManager.FontButton->Width(text);
+    int textHeight = fontManager.FontButton->Height();
+    footer->DrawText(cPoint(left + (geoManager.buttonWidth-textWidth)/2, buttonY + (geoManager.buttonHeight-textHeight)/2), text, theme.Color(clrFontButtons), colorTextBack, fontManager.FontButton);
+}
+
+void cFooter::ClearButton(int num) {
+    int left = num * geoManager.buttonWidth + (2 * num + 1) * geoManager.buttonBorder;
+    footer->DrawRectangle(cRect(left, buttonY, geoManager.buttonWidth, geoManager.buttonHeight), clrTransparent); 
 }
\ No newline at end of file
diff --git a/footer.h b/footer.h
index 805ab0a..e923476 100644
--- a/footer.h
+++ b/footer.h
@@ -1,23 +1,33 @@
 #ifndef __TVGUIDE_FOOTER_H
 #define __TVGUIDE_FOOTER_H
 
+#include <vdr/osd.h>
+#include "channelgroups.h"
+
 // --- cFooter  -------------------------------------------------------------
 
 class cFooter  {
 private:
-	cPixmap *footer;
-	int buttonWidth;
-    int buttonHeight;
+    cPixmap *footer;
     int buttonY;
-    int buttonBorder;
-    void DrawButton(const char *text, tColor color, tColor borderColor, int num);
+    int positionButtons[4];
+    cChannelGroups *channelGroups;
+    int currentGroup;
+    void SetButtonPositions(void);
+    void DrawButton(const char *text, tColor color, tColor borderColor, eOsdElementType buttonType, int num);
+    void ClearButton(int num);
 public:
-	cFooter();
-	virtual ~cFooter(void);
-	void drawRedButton();
-	void drawGreenButton();
-	void drawYellowButton();
-	void drawBlueButton();
+    cFooter(cChannelGroups *channelGroups);
+    virtual ~cFooter(void);
+    void drawRedButton();
+    void drawGreenButton();
+    void drawGreenButton(const char *text);
+    void drawYellowButton();
+    void drawYellowButton(const char *text);
+    void drawBlueButton(bool detailedEPG = false);
+    void UpdateGroupButtons(const cChannel *channel, bool force = false);
+    void SetDetailedViewMode(bool fromRecMenu = false);
+    void LeaveDetailedViewMode(const cChannel *channel);
 };
 
 #endif //__TVGUIDE_FOOTER_H
\ No newline at end of file
diff --git a/geometrymanager.c b/geometrymanager.c
new file mode 100644
index 0000000..94d47b7
--- /dev/null
+++ b/geometrymanager.c
@@ -0,0 +1,74 @@
+#include <vdr/osd.h>
+
+#include "config.h"
+#include "geometrymanager.h"
+
+cGeometryManager::cGeometryManager() {
+    osdWidth = 0;
+    osdHeight = 0;
+}
+
+cGeometryManager::~cGeometryManager() {
+}
+
+bool cGeometryManager::SetGeometry(int osdWidth, int osdHeight, bool force) {
+	if (!force && (this->osdWidth == osdWidth) && (this->osdHeight == osdHeight)) {
+		esyslog("tvgudie: GeoManager SetGeometry nothing to change");
+		return false;
+	}
+	this->osdWidth = osdWidth;
+	this->osdHeight = osdHeight;
+	esyslog("tvguide: Set OSD to %d x %d px", osdWidth, osdHeight);
+
+	statusHeaderHeight = (tvguideConfig.displayStatusHeader)?(tvguideConfig.headerHeightPercent * osdHeight / 100):0;
+    tvFrameWidth = statusHeaderHeight * 16 / 9;
+    headerContentWidth = (tvguideConfig.scaleVideo)?(osdWidth -  tvFrameWidth):osdWidth;
+    channelGroupsWidth = (tvguideConfig.displayChannelGroups)?(tvguideConfig.channelGroupsPercent * osdWidth / 100):0;
+    channelGroupsHeight = (tvguideConfig.displayChannelGroups)?(tvguideConfig.channelGroupsPercent * osdHeight / 100):0;
+    channelHeaderWidth = tvguideConfig.channelHeaderWidthPercent * osdWidth / 100;
+    channelHeaderHeight = tvguideConfig.channelHeaderHeightPercent * osdHeight / 100;
+    timeLineWidth = tvguideConfig.timeLineWidthPercent * osdWidth / 100;
+    timeLineHeight = tvguideConfig.timeLineHeightPercent * osdHeight / 100;
+    clockWidth = tvFrameWidth / 3;
+    clockHeight = timeLineHeight;
+    footerHeight = tvguideConfig.footerHeightPercent * osdHeight / 100;
+    footerY = osdHeight - footerHeight;
+
+    if (tvguideConfig.displayMode == eVertical) {
+        colWidth = (osdWidth - timeLineWidth) / tvguideConfig.channelCols;
+        rowHeight = 0;
+        minutePixel = (osdHeight - statusHeaderHeight - channelGroupsHeight - channelHeaderHeight - footerHeight) / tvguideConfig.displayTime;
+        channelLogoWidth = colWidth;
+        channelLogoHeight = channelHeaderHeight;
+        logoWidth = channelLogoWidth/2 - 15;
+        logoHeight = logoWidth * tvguideConfig.logoHeightRatio / tvguideConfig.logoWidthRatio;
+        timeLineGridWidth = timeLineWidth;
+        timeLineGridHeight = minutePixel*30;
+        dateVieverWidth = timeLineWidth;
+        dateVieverHeight = channelHeaderHeight + channelGroupsHeight;
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        colWidth = 0;
+        rowHeight = (osdHeight - statusHeaderHeight - timeLineHeight - footerHeight) / tvguideConfig.channelRows;
+        minutePixel = (osdWidth - channelHeaderWidth - channelGroupsWidth) / tvguideConfig.displayTime;
+        channelLogoWidth = channelHeaderWidth;
+        channelLogoHeight = rowHeight;
+        logoWidth = channelLogoHeight * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+        logoHeight = channelLogoHeight;
+        timeLineGridWidth = geoManager.minutePixel*30;
+        timeLineGridHeight = geoManager.timeLineHeight;
+        dateVieverWidth = channelHeaderWidth + channelGroupsWidth;
+        dateVieverHeight = timeLineHeight;
+    }
+    buttonBorder = footerHeight / 6;
+    buttonWidth = osdWidth / 4 - 2 * buttonBorder;
+    buttonHeight = footerHeight - 3 * buttonBorder;
+
+    epgViewHeaderHeight = tvguideConfig.headerHeightPercent * osdHeight / 100;
+
+    borderRecMenus = 10;
+
+    channelJumpWidth = osdWidth * 30 / 100;
+    channelJumpHeight = osdHeight * 20 / 100;
+
+    return true;
+}
\ No newline at end of file
diff --git a/geometrymanager.h b/geometrymanager.h
new file mode 100644
index 0000000..ecd31b9
--- /dev/null
+++ b/geometrymanager.h
@@ -0,0 +1,54 @@
+#ifndef __TVGUIDE_GEOMETRYMANAGER_H
+#define __TVGUIDE_GEOMETRYMANAGER_H
+
+class cGeometryManager {
+private:
+public:
+	cGeometryManager(void);
+	~cGeometryManager();
+	bool SetGeometry(int osdWidth, int osdHeight, bool force = false);
+    //Common
+	int osdWidth;
+	int osdHeight;
+	int statusHeaderHeight;
+    int tvFrameWidth;
+    int headerContentWidth;
+    //ChannelGroups
+	int	channelGroupsWidth;
+    int channelGroupsHeight;
+    //ContentHeader
+    int channelHeaderWidth;
+    int channelHeaderHeight;
+    int logoWidth;
+    int logoHeight;
+    //Content
+    int colWidth;
+    int rowHeight;
+    int minutePixel;
+    int channelLogoWidth;
+    int channelLogoHeight;
+    //Timeline
+    int timeLineWidth;
+    int timeLineHeight;
+    int timeLineGridWidth;
+    int timeLineGridHeight;
+    int dateVieverWidth;
+    int dateVieverHeight;
+    int clockWidth;
+    int clockHeight;
+    //Footer
+    int footerY;
+    int footerHeight;
+    int buttonWidth;
+    int buttonHeight;
+    int buttonBorder;
+    //Detailed EPG View
+    int epgViewHeaderHeight;
+    //Recording Menus
+    int borderRecMenus;
+    //Channel Jump
+    int channelJumpWidth;
+    int channelJumpHeight;
+};
+
+#endif //__TVGUIDE_GEOMETRYMANAGER_H
\ No newline at end of file
diff --git a/grid.c b/grid.c
new file mode 100644
index 0000000..9a878d4
--- /dev/null
+++ b/grid.c
@@ -0,0 +1,82 @@
+#include "channelcolumn.h"
+#include "grid.h"
+
+cGrid::cGrid(cChannelColumn *c) {
+    this->column = c;
+    text = new cTextWrapper();
+    dirty = true;
+    active = false;
+    viewportHeight = 0;
+    borderWidth = 10;
+}
+
+cGrid::~cGrid(void) {
+    delete text;
+}
+
+void cGrid::setBackground() {
+    if (active) {
+        color = theme.Color(clrHighlight);
+        colorBlending = theme.Color(clrHighlightBlending);
+    } else {
+        if (isColor1) {
+            color = theme.Color(clrGrid1);
+            colorBlending = theme.Color(clrGrid1Blending);
+        } else {
+            color = theme.Color(clrGrid2);
+            colorBlending = theme.Color(clrGrid2Blending);
+        }
+    }
+}
+
+void cGrid::Draw() {
+    if (!pixmap) {
+        return;
+    }
+    if (dirty) {
+        if (tvguideConfig.style == eStyleGraphical) {
+            drawBackgroundGraphical(bgGrid, active);
+            drawText();
+        } else {
+            setBackground();
+            drawBackground();
+            drawText();
+            drawBorder();
+        }
+        pixmap->SetLayer(1);
+        dirty = false;
+    }
+}
+
+bool cGrid::isFirst(void) {
+    if (column->isFirst(this))
+        return true;
+    return false;
+}
+
+bool cGrid::Match(time_t t) {
+    if ((StartTime() < t) && (EndTime() > t))
+        return true;
+    else
+        return false;
+}
+
+int cGrid::calcOverlap(cGrid *neighbor) {
+    int overlap = 0;
+    if (intersects(neighbor)) {
+        if ((StartTime() <= neighbor->StartTime()) && (EndTime() <= neighbor->EndTime())) {
+            overlap = EndTime() - neighbor->StartTime();
+        } else if ((StartTime() >= neighbor->StartTime()) && (EndTime() >= neighbor->EndTime())) {
+            overlap = neighbor->EndTime() - StartTime();
+        } else if ((StartTime() >= neighbor->StartTime()) && (EndTime() <= neighbor->EndTime())) {
+            overlap = Duration();
+        } else if ((StartTime() <= neighbor->StartTime()) && (EndTime() >= neighbor->EndTime())) {
+            overlap = neighbor->EndTime() - neighbor->StartTime();
+        }
+    }
+    return overlap;
+}
+
+bool cGrid::intersects(cGrid *neighbor) {
+    return ! ( (neighbor->EndTime() <= StartTime()) || (neighbor->StartTime() >= EndTime()) ); 
+}
diff --git a/grid.h b/grid.h
new file mode 100644
index 0000000..bd35af1
--- /dev/null
+++ b/grid.h
@@ -0,0 +1,58 @@
+#ifndef __TVGUIDE_GRID_H
+#define __TVGUIDE_GRID_H
+
+#include <vdr/tools.h>
+#include "styledpixmap.h"
+
+class cChannelColumn;
+
+// --- cEpgGrid  -------------------------------------------------------------
+
+class cGrid : public cListObject, public cStyledPixmap {
+protected:
+    cTextWrapper *text;
+    int viewportHeight;
+    int borderWidth;
+    void setBackground();
+    bool isColor1;
+    bool active;
+    bool dirty;
+    bool hasTimer;
+    bool hasSwitchTimer;
+    bool intersects(cGrid *neighbor);
+    virtual time_t Duration(void) {};
+    virtual void drawText(void) {};
+    bool dummy;
+public:
+    cGrid(cChannelColumn *c);
+    virtual ~cGrid(void);
+    cChannelColumn *column;
+    virtual void SetViewportHeight() {};
+    virtual void PositionPixmap() {};
+    virtual void setText(void) {};
+    void Draw();
+    void SetDirty() {dirty = true;};
+    void SetActive() {dirty = true; active = true;};
+    void SetInActive() {dirty = true; active = false;};
+    void SetColor(bool color) {isColor1 = color;};
+    bool IsColor1() {return isColor1;};
+    bool isFirst(void);
+    virtual const cEvent *GetEvent() {};
+    bool Match(time_t t);
+    virtual time_t StartTime() {};
+    virtual time_t EndTime() {};
+    virtual void SetStartTime(time_t start) {};
+    virtual void SetEndTime(time_t end) {};
+    int calcOverlap(cGrid *neighbor);
+    virtual void SetTimer() {};
+    virtual void SetSwitchTimer() {};
+    virtual cString getText(void) { return cString("");};
+    virtual cString getTimeString(void) { return cString("");};
+    bool Active(void) { return active; };
+    bool HasTimer() {return hasTimer;};
+    bool HasSwitchTimer() {return hasSwitchTimer;};
+    bool isDummy() { return dummy; };
+    virtual void debug() {};
+};
+
+#endif //__TVGUIDE_GRID_H
\ No newline at end of file
diff --git a/headergrid.c b/headergrid.c
new file mode 100644
index 0000000..ec6a991
--- /dev/null
+++ b/headergrid.c
@@ -0,0 +1,128 @@
+#include "imageloader.h"
+#include "tools.h"
+#include "headergrid.h"
+
+cHeaderGrid::cHeaderGrid(void) : cGrid(NULL) {
+    pixmap = NULL;
+    pixmapLogo = NULL;
+}
+
+cHeaderGrid::~cHeaderGrid(void) {
+    osdManager.releasePixmap(pixmapLogo);
+}
+
+void cHeaderGrid::createBackground(int num) {
+    color = theme.Color(clrHeader);
+    colorBlending = theme.Color(clrHeaderBlending);
+    int x, y;
+    if (tvguideConfig.displayMode == eVertical) {
+        x = geoManager.timeLineWidth + num*geoManager.colWidth;
+        y = geoManager.statusHeaderHeight + geoManager.channelGroupsHeight;
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        x = geoManager.channelGroupsWidth;
+        y = geoManager.statusHeaderHeight + geoManager.timeLineHeight + num*geoManager.rowHeight;
+    }
+    pixmap = osdManager.requestPixmap(1, cRect(x, y, geoManager.channelLogoWidth, geoManager.channelLogoHeight));
+    pixmapLogo = osdManager.requestPixmap(2, cRect(x, y, geoManager.channelLogoWidth, geoManager.channelLogoHeight));
+    if ((!pixmap) || (!pixmapLogo)){
+        return;
+    }
+    pixmapLogo->Fill(clrTransparent);
+    if (tvguideConfig.style == eStyleGraphical) {
+        drawBackgroundGraphical(bgChannelHeader);
+    } else {
+        drawBackground();
+        drawBorder();
+    }
+}
+
+void cHeaderGrid::drawChannel(const cChannel *channel) {
+    if (tvguideConfig.displayMode == eVertical) {
+        drawChannelVertical(channel);
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        drawChannelHorizontal(channel);
+    }
+}
+
+void cHeaderGrid::drawChannelHorizontal(const cChannel *channel) {
+    int logoWidth = geoManager.logoWidth;
+    int logoX = tvguideConfig.displayChannelName?2:(Width()-logoWidth)/2;
+    int textX = 5;
+    int textY = (Height() - fontManager.FontChannelHeaderHorizontal->Height())/2;
+    bool logoFound = false;
+    if (!tvguideConfig.hideChannelLogos) {
+        cImage *logo = imgCache.GetLogo(channel);
+        if (logo) {
+            pixmapLogo->DrawImage(cPoint(logoX, 0), *logo);
+            logoFound = true;
+        }
+    }
+    bool drawText = false;
+    int textWidthMax = Width() - 10;
+    if (!logoFound) {
+        drawText = true;
+    } else  if (tvguideConfig.displayChannelName) {
+        drawText = true;
+        textX += logoWidth;
+        textWidthMax -= logoWidth;
+    }
+    if (drawText) {
+        tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+        cString strChannel = cString::sprintf("%d %s", channel->Number(), channel->Name());
+        strChannel = CutText(*strChannel, textWidthMax, fontManager.FontChannelHeaderHorizontal).c_str();
+        pixmap->DrawText(cPoint(textX, textY), *strChannel, theme.Color(clrFontHeader), colorTextBack, fontManager.FontChannelHeaderHorizontal);
+    }
+}
+
+void cHeaderGrid::drawChannelVertical(const cChannel *channel) {
+    int logoWidth = geoManager.logoWidth;
+    int logoHeight = geoManager.logoHeight;
+    cTextWrapper tw;
+    cString headerText = cString::sprintf("%d - %s", channel->Number(), channel->Name());
+    tw.Set(*headerText, fontManager.FontChannelHeader, geoManager.colWidth - 8);
+    int lines = tw.Lines();
+    int lineHeight = fontManager.FontChannelHeader->Height();
+    int yStart = (geoManager.channelHeaderHeight - lines*lineHeight)/2 + 8;
+    bool logoFound = false;
+    if (!tvguideConfig.hideChannelLogos) {
+        cImage *logo = imgCache.GetLogo(channel);
+        if (logo) {
+                pixmapLogo->DrawImage(cPoint((Width() - logoWidth)/2, 4), *logo);
+                logoFound = true;
+        }
+    }
+    bool drawText = false;
+    if (!logoFound) {
+        drawText = true;
+    } else if (tvguideConfig.displayChannelName) {
+        drawText = true;
+        yStart = logoHeight;
+    }
+    if (!drawText)
+        return;
+    tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+    for (int i=0; i<lines; i++) {
+        int textWidth = fontManager.FontChannelHeader->Width(tw.GetLine(i));
+        int xText = (geoManager.colWidth - textWidth) / 2;
+        if (xText < 0) 
+            xText = 0;
+        pixmap->DrawText(cPoint(xText, yStart + i*lineHeight), tw.GetLine(i), theme.Color(clrFontHeader), colorTextBack, fontManager.FontChannelHeader);
+    }
+}
+
+void cHeaderGrid::setPosition(int num) {
+    int x, y, width, height;
+    if (tvguideConfig.displayMode == eVertical) {
+        x = geoManager.timeLineWidth + num*geoManager.colWidth;
+        y = geoManager.statusHeaderHeight + geoManager.channelGroupsHeight;
+        width = geoManager.colWidth;
+        height = geoManager.channelHeaderHeight;
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        x = geoManager.channelGroupsWidth;
+        y = geoManager.statusHeaderHeight + geoManager.timeLineHeight + num*geoManager.rowHeight;
+        width = geoManager.channelHeaderWidth;
+        height = geoManager.rowHeight;
+    }
+    pixmap->SetViewPort(cRect(x, y, width, height));
+    pixmapLogo->SetViewPort(cRect(x, y, width, height));
+}
diff --git a/headergrid.h b/headergrid.h
new file mode 100644
index 0000000..a4f0962
--- /dev/null
+++ b/headergrid.h
@@ -0,0 +1,21 @@
+#ifndef __TVGUIDE_HEADERGRID_H
+#define __TVGUIDE_HEADERGRID_H
+
+#include "grid.h"
+
+// --- cHeaderGrid  -------------------------------------------------------------
+
+class cHeaderGrid : public cGrid {
+private:
+    cPixmap *pixmapLogo;
+    void drawChannelHorizontal(const cChannel *channel);
+    void drawChannelVertical(const cChannel *channel);
+public:
+    cHeaderGrid(void);
+    virtual ~cHeaderGrid(void);
+    void createBackground(int num);
+    void drawChannel(const cChannel *channel);
+    void setPosition(int num);
+};
+
+#endif //__TVGUIDE_HEADERGRID_H
\ No newline at end of file
diff --git a/icons/darkredNG/osdElements/button_30percent.png b/icons/darkredNG/osdElements/button_30percent.png
new file mode 100644
index 0000000..58f0281
Binary files /dev/null and b/icons/darkredNG/osdElements/button_30percent.png differ
diff --git a/icons/darkredNG/osdElements/button_70percent.png b/icons/darkredNG/osdElements/button_70percent.png
new file mode 100644
index 0000000..7234f08
Binary files /dev/null and b/icons/darkredNG/osdElements/button_70percent.png differ
diff --git a/icons/darkredNG/osdElements/button_active_30percent.png b/icons/darkredNG/osdElements/button_active_30percent.png
new file mode 100644
index 0000000..1b5aab0
Binary files /dev/null and b/icons/darkredNG/osdElements/button_active_30percent.png differ
diff --git a/icons/darkredNG/osdElements/button_active_70percent.png b/icons/darkredNG/osdElements/button_active_70percent.png
new file mode 100644
index 0000000..ba09ea0
Binary files /dev/null and b/icons/darkredNG/osdElements/button_active_70percent.png differ
diff --git a/icons/darkredNG/osdElements/buttonblue.png b/icons/darkredNG/osdElements/buttonblue.png
new file mode 100644
index 0000000..ac3536c
Binary files /dev/null and b/icons/darkredNG/osdElements/buttonblue.png differ
diff --git a/icons/darkredNG/osdElements/buttongreen.png b/icons/darkredNG/osdElements/buttongreen.png
new file mode 100644
index 0000000..e598518
Binary files /dev/null and b/icons/darkredNG/osdElements/buttongreen.png differ
diff --git a/icons/darkredNG/osdElements/buttonred.png b/icons/darkredNG/osdElements/buttonred.png
new file mode 100644
index 0000000..152acad
Binary files /dev/null and b/icons/darkredNG/osdElements/buttonred.png differ
diff --git a/icons/darkredNG/osdElements/buttonyellow.png b/icons/darkredNG/osdElements/buttonyellow.png
new file mode 100644
index 0000000..1b448c9
Binary files /dev/null and b/icons/darkredNG/osdElements/buttonyellow.png differ
diff --git a/icons/darkredNG/osdElements/channel_jump.png b/icons/darkredNG/osdElements/channel_jump.png
new file mode 100644
index 0000000..7f45bd4
Binary files /dev/null and b/icons/darkredNG/osdElements/channel_jump.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_bottom.png b/icons/darkredNG/osdElements/channelgroup_bottom.png
new file mode 100644
index 0000000..7127ea7
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_bottom.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_head.png b/icons/darkredNG/osdElements/channelgroup_head.png
new file mode 100644
index 0000000..bce9d22
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_head.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_horizontal.png b/icons/darkredNG/osdElements/channelgroup_horizontal.png
new file mode 100644
index 0000000..13d733c
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_left.png b/icons/darkredNG/osdElements/channelgroup_left.png
new file mode 100644
index 0000000..df495b1
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_left.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_right.png b/icons/darkredNG/osdElements/channelgroup_right.png
new file mode 100644
index 0000000..42dcf6d
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_right.png differ
diff --git a/icons/darkredNG/osdElements/channelgroup_vertical.png b/icons/darkredNG/osdElements/channelgroup_vertical.png
new file mode 100644
index 0000000..43778d0
Binary files /dev/null and b/icons/darkredNG/osdElements/channelgroup_vertical.png differ
diff --git a/icons/darkredNG/osdElements/channellogoback_horizontal.png b/icons/darkredNG/osdElements/channellogoback_horizontal.png
new file mode 100644
index 0000000..d9bb54a
Binary files /dev/null and b/icons/darkredNG/osdElements/channellogoback_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/channellogoback_vertical.png b/icons/darkredNG/osdElements/channellogoback_vertical.png
new file mode 100644
index 0000000..06684cc
Binary files /dev/null and b/icons/darkredNG/osdElements/channellogoback_vertical.png differ
diff --git a/icons/darkredNG/osdElements/clock.png b/icons/darkredNG/osdElements/clock.png
new file mode 100644
index 0000000..2e8686e
Binary files /dev/null and b/icons/darkredNG/osdElements/clock.png differ
diff --git a/icons/darkredNG/osdElements/date_vertical.png b/icons/darkredNG/osdElements/date_vertical.png
new file mode 100644
index 0000000..58a72e4
Binary files /dev/null and b/icons/darkredNG/osdElements/date_vertical.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_bottom.png b/icons/darkredNG/osdElements/grid_active_bottom.png
new file mode 100644
index 0000000..08de467
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_bottom.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_head.png b/icons/darkredNG/osdElements/grid_active_head.png
new file mode 100644
index 0000000..060a908
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_head.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_horizontal.png b/icons/darkredNG/osdElements/grid_active_horizontal.png
new file mode 100644
index 0000000..9319d6b
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_left.png b/icons/darkredNG/osdElements/grid_active_left.png
new file mode 100644
index 0000000..7852d94
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_left.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_right.png b/icons/darkredNG/osdElements/grid_active_right.png
new file mode 100644
index 0000000..73dfbd0
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_right.png differ
diff --git a/icons/darkredNG/osdElements/grid_active_vertical.png b/icons/darkredNG/osdElements/grid_active_vertical.png
new file mode 100644
index 0000000..6d96d34
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_active_vertical.png differ
diff --git a/icons/darkredNG/osdElements/grid_bottom.png b/icons/darkredNG/osdElements/grid_bottom.png
new file mode 100644
index 0000000..82c20c4
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_bottom.png differ
diff --git a/icons/darkredNG/osdElements/grid_head.png b/icons/darkredNG/osdElements/grid_head.png
new file mode 100644
index 0000000..f434c11
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_head.png differ
diff --git a/icons/darkredNG/osdElements/grid_horizontal.png b/icons/darkredNG/osdElements/grid_horizontal.png
new file mode 100644
index 0000000..6f28550
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/grid_left.png b/icons/darkredNG/osdElements/grid_left.png
new file mode 100644
index 0000000..df80f91
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_left.png differ
diff --git a/icons/darkredNG/osdElements/grid_right.png b/icons/darkredNG/osdElements/grid_right.png
new file mode 100644
index 0000000..d39470f
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_right.png differ
diff --git a/icons/darkredNG/osdElements/grid_vertical.png b/icons/darkredNG/osdElements/grid_vertical.png
new file mode 100644
index 0000000..6ad219d
Binary files /dev/null and b/icons/darkredNG/osdElements/grid_vertical.png differ
diff --git a/icons/darkredNG/osdElements/recmenu_background.png b/icons/darkredNG/osdElements/recmenu_background.png
new file mode 100644
index 0000000..2ab2573
Binary files /dev/null and b/icons/darkredNG/osdElements/recmenu_background.png differ
diff --git a/icons/darkredNG/osdElements/statusheader_content_full.png b/icons/darkredNG/osdElements/statusheader_content_full.png
new file mode 100644
index 0000000..7fd6885
Binary files /dev/null and b/icons/darkredNG/osdElements/statusheader_content_full.png differ
diff --git a/icons/darkredNG/osdElements/statusheader_content_windowed.png b/icons/darkredNG/osdElements/statusheader_content_windowed.png
new file mode 100644
index 0000000..56a60a7
Binary files /dev/null and b/icons/darkredNG/osdElements/statusheader_content_windowed.png differ
diff --git a/icons/darkredNG/osdElements/statusheader_tvframe.png b/icons/darkredNG/osdElements/statusheader_tvframe.png
new file mode 100644
index 0000000..261fea3
Binary files /dev/null and b/icons/darkredNG/osdElements/statusheader_tvframe.png differ
diff --git a/icons/darkredNG/osdElements/timeline1_horizontal.png b/icons/darkredNG/osdElements/timeline1_horizontal.png
new file mode 100644
index 0000000..9240b37
Binary files /dev/null and b/icons/darkredNG/osdElements/timeline1_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/timeline1_vertical.png b/icons/darkredNG/osdElements/timeline1_vertical.png
new file mode 100644
index 0000000..5466546
Binary files /dev/null and b/icons/darkredNG/osdElements/timeline1_vertical.png differ
diff --git a/icons/darkredNG/osdElements/timeline2_horizontal.png b/icons/darkredNG/osdElements/timeline2_horizontal.png
new file mode 100644
index 0000000..4364677
Binary files /dev/null and b/icons/darkredNG/osdElements/timeline2_horizontal.png differ
diff --git a/icons/darkredNG/osdElements/timeline2_vertical.png b/icons/darkredNG/osdElements/timeline2_vertical.png
new file mode 100644
index 0000000..dfa06c9
Binary files /dev/null and b/icons/darkredNG/osdElements/timeline2_vertical.png differ
diff --git a/icons/darkredNG/recmenuicons/activetimer.png b/icons/darkredNG/recmenuicons/activetimer.png
new file mode 100644
index 0000000..af4c33c
Binary files /dev/null and b/icons/darkredNG/recmenuicons/activetimer.png differ
diff --git a/icons/darkredNG/recmenuicons/arrow_left.png b/icons/darkredNG/recmenuicons/arrow_left.png
new file mode 100644
index 0000000..57800c7
Binary files /dev/null and b/icons/darkredNG/recmenuicons/arrow_left.png differ
diff --git a/icons/darkredNG/recmenuicons/arrow_right.png b/icons/darkredNG/recmenuicons/arrow_right.png
new file mode 100644
index 0000000..ea45f3a
Binary files /dev/null and b/icons/darkredNG/recmenuicons/arrow_right.png differ
diff --git a/icons/darkredNG/recmenuicons/delete_active.png b/icons/darkredNG/recmenuicons/delete_active.png
new file mode 100644
index 0000000..f473717
Binary files /dev/null and b/icons/darkredNG/recmenuicons/delete_active.png differ
diff --git a/icons/darkredNG/recmenuicons/delete_inactive.png b/icons/darkredNG/recmenuicons/delete_inactive.png
new file mode 100644
index 0000000..21b0a88
Binary files /dev/null and b/icons/darkredNG/recmenuicons/delete_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/edit_active.png b/icons/darkredNG/recmenuicons/edit_active.png
new file mode 100644
index 0000000..ec39699
Binary files /dev/null and b/icons/darkredNG/recmenuicons/edit_active.png differ
diff --git a/icons/darkredNG/recmenuicons/edit_inactive.png b/icons/darkredNG/recmenuicons/edit_inactive.png
new file mode 100644
index 0000000..71f016c
Binary files /dev/null and b/icons/darkredNG/recmenuicons/edit_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/icon_backspace.png b/icons/darkredNG/recmenuicons/icon_backspace.png
new file mode 100644
index 0000000..6065fa3
Binary files /dev/null and b/icons/darkredNG/recmenuicons/icon_backspace.png differ
diff --git a/icons/darkredNG/recmenuicons/icon_del_ins.png b/icons/darkredNG/recmenuicons/icon_del_ins.png
new file mode 100644
index 0000000..f05a96b
Binary files /dev/null and b/icons/darkredNG/recmenuicons/icon_del_ins.png differ
diff --git a/icons/darkredNG/recmenuicons/icon_shift.png b/icons/darkredNG/recmenuicons/icon_shift.png
new file mode 100644
index 0000000..15ae851
Binary files /dev/null and b/icons/darkredNG/recmenuicons/icon_shift.png differ
diff --git a/icons/darkredNG/recmenuicons/info_active.png b/icons/darkredNG/recmenuicons/info_active.png
new file mode 100644
index 0000000..c88f76d
Binary files /dev/null and b/icons/darkredNG/recmenuicons/info_active.png differ
diff --git a/icons/darkredNG/recmenuicons/info_inactive.png b/icons/darkredNG/recmenuicons/info_inactive.png
new file mode 100644
index 0000000..37eeed2
Binary files /dev/null and b/icons/darkredNG/recmenuicons/info_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/no.png b/icons/darkredNG/recmenuicons/no.png
new file mode 100644
index 0000000..47cdba0
Binary files /dev/null and b/icons/darkredNG/recmenuicons/no.png differ
diff --git a/icons/darkredNG/recmenuicons/record_active.png b/icons/darkredNG/recmenuicons/record_active.png
new file mode 100644
index 0000000..476da99
Binary files /dev/null and b/icons/darkredNG/recmenuicons/record_active.png differ
diff --git a/icons/darkredNG/recmenuicons/record_inactive.png b/icons/darkredNG/recmenuicons/record_inactive.png
new file mode 100644
index 0000000..2a91da3
Binary files /dev/null and b/icons/darkredNG/recmenuicons/record_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/search_active.png b/icons/darkredNG/recmenuicons/search_active.png
new file mode 100644
index 0000000..7bf7bc7
Binary files /dev/null and b/icons/darkredNG/recmenuicons/search_active.png differ
diff --git a/icons/darkredNG/recmenuicons/search_inactive.png b/icons/darkredNG/recmenuicons/search_inactive.png
new file mode 100644
index 0000000..4a210bb
Binary files /dev/null and b/icons/darkredNG/recmenuicons/search_inactive.png differ
diff --git a/icons/darkredNG/recmenuicons/yes.png b/icons/darkredNG/recmenuicons/yes.png
new file mode 100644
index 0000000..2f1af98
Binary files /dev/null and b/icons/darkredNG/recmenuicons/yes.png differ
diff --git a/icons/default/osdElements/button_30percent.png b/icons/default/osdElements/button_30percent.png
new file mode 100644
index 0000000..565d16e
Binary files /dev/null and b/icons/default/osdElements/button_30percent.png differ
diff --git a/icons/default/osdElements/button_70percent.png b/icons/default/osdElements/button_70percent.png
new file mode 100644
index 0000000..7a43e01
Binary files /dev/null and b/icons/default/osdElements/button_70percent.png differ
diff --git a/icons/default/osdElements/button_active_30percent.png b/icons/default/osdElements/button_active_30percent.png
new file mode 100644
index 0000000..97392fd
Binary files /dev/null and b/icons/default/osdElements/button_active_30percent.png differ
diff --git a/icons/default/osdElements/button_active_70percent.png b/icons/default/osdElements/button_active_70percent.png
new file mode 100644
index 0000000..22d167e
Binary files /dev/null and b/icons/default/osdElements/button_active_70percent.png differ
diff --git a/icons/default/osdElements/buttonblue.png b/icons/default/osdElements/buttonblue.png
new file mode 100644
index 0000000..ac3536c
Binary files /dev/null and b/icons/default/osdElements/buttonblue.png differ
diff --git a/icons/default/osdElements/buttongreen.png b/icons/default/osdElements/buttongreen.png
new file mode 100644
index 0000000..e598518
Binary files /dev/null and b/icons/default/osdElements/buttongreen.png differ
diff --git a/icons/default/osdElements/buttonred.png b/icons/default/osdElements/buttonred.png
new file mode 100644
index 0000000..152acad
Binary files /dev/null and b/icons/default/osdElements/buttonred.png differ
diff --git a/icons/default/osdElements/buttonyellow.png b/icons/default/osdElements/buttonyellow.png
new file mode 100644
index 0000000..1b448c9
Binary files /dev/null and b/icons/default/osdElements/buttonyellow.png differ
diff --git a/icons/default/osdElements/channel_jump.png b/icons/default/osdElements/channel_jump.png
new file mode 100644
index 0000000..9e417d4
Binary files /dev/null and b/icons/default/osdElements/channel_jump.png differ
diff --git a/icons/default/osdElements/channelgroup_bottom.png b/icons/default/osdElements/channelgroup_bottom.png
new file mode 100644
index 0000000..c37ba42
Binary files /dev/null and b/icons/default/osdElements/channelgroup_bottom.png differ
diff --git a/icons/default/osdElements/channelgroup_head.png b/icons/default/osdElements/channelgroup_head.png
new file mode 100644
index 0000000..75ee8a8
Binary files /dev/null and b/icons/default/osdElements/channelgroup_head.png differ
diff --git a/icons/default/osdElements/channelgroup_horiziontal.png b/icons/default/osdElements/channelgroup_horiziontal.png
new file mode 100644
index 0000000..ead7606
Binary files /dev/null and b/icons/default/osdElements/channelgroup_horiziontal.png differ
diff --git a/icons/default/osdElements/channelgroup_horizontal.png b/icons/default/osdElements/channelgroup_horizontal.png
new file mode 100644
index 0000000..ead7606
Binary files /dev/null and b/icons/default/osdElements/channelgroup_horizontal.png differ
diff --git a/icons/default/osdElements/channelgroup_left.png b/icons/default/osdElements/channelgroup_left.png
new file mode 100644
index 0000000..30e1b45
Binary files /dev/null and b/icons/default/osdElements/channelgroup_left.png differ
diff --git a/icons/default/osdElements/channelgroup_right.png b/icons/default/osdElements/channelgroup_right.png
new file mode 100644
index 0000000..d89657c
Binary files /dev/null and b/icons/default/osdElements/channelgroup_right.png differ
diff --git a/icons/default/osdElements/channelgroup_vertical.png b/icons/default/osdElements/channelgroup_vertical.png
new file mode 100644
index 0000000..64134c7
Binary files /dev/null and b/icons/default/osdElements/channelgroup_vertical.png differ
diff --git a/icons/default/osdElements/channelgroups_vertical.png b/icons/default/osdElements/channelgroups_vertical.png
new file mode 100644
index 0000000..474c558
Binary files /dev/null and b/icons/default/osdElements/channelgroups_vertical.png differ
diff --git a/icons/default/osdElements/channellogoback_horizontal.png b/icons/default/osdElements/channellogoback_horizontal.png
new file mode 100644
index 0000000..2df7f52
Binary files /dev/null and b/icons/default/osdElements/channellogoback_horizontal.png differ
diff --git a/icons/default/osdElements/channellogoback_vertical.png b/icons/default/osdElements/channellogoback_vertical.png
new file mode 100644
index 0000000..669beeb
Binary files /dev/null and b/icons/default/osdElements/channellogoback_vertical.png differ
diff --git a/icons/default/osdElements/clock.png b/icons/default/osdElements/clock.png
new file mode 100644
index 0000000..3df1dae
Binary files /dev/null and b/icons/default/osdElements/clock.png differ
diff --git a/icons/default/osdElements/date_vertical.png b/icons/default/osdElements/date_vertical.png
new file mode 100644
index 0000000..58a72e4
Binary files /dev/null and b/icons/default/osdElements/date_vertical.png differ
diff --git a/icons/default/osdElements/grid_active_bottom.png b/icons/default/osdElements/grid_active_bottom.png
new file mode 100644
index 0000000..28fb443
Binary files /dev/null and b/icons/default/osdElements/grid_active_bottom.png differ
diff --git a/icons/default/osdElements/grid_active_head.png b/icons/default/osdElements/grid_active_head.png
new file mode 100644
index 0000000..a494d95
Binary files /dev/null and b/icons/default/osdElements/grid_active_head.png differ
diff --git a/icons/default/osdElements/grid_active_horizontal.png b/icons/default/osdElements/grid_active_horizontal.png
new file mode 100644
index 0000000..368309f
Binary files /dev/null and b/icons/default/osdElements/grid_active_horizontal.png differ
diff --git a/icons/default/osdElements/grid_active_left.png b/icons/default/osdElements/grid_active_left.png
new file mode 100644
index 0000000..0548e21
Binary files /dev/null and b/icons/default/osdElements/grid_active_left.png differ
diff --git a/icons/default/osdElements/grid_active_right.png b/icons/default/osdElements/grid_active_right.png
new file mode 100644
index 0000000..2aee1d6
Binary files /dev/null and b/icons/default/osdElements/grid_active_right.png differ
diff --git a/icons/default/osdElements/grid_active_vertical.png b/icons/default/osdElements/grid_active_vertical.png
new file mode 100644
index 0000000..6aba9d1
Binary files /dev/null and b/icons/default/osdElements/grid_active_vertical.png differ
diff --git a/icons/default/osdElements/grid_bottom.png b/icons/default/osdElements/grid_bottom.png
new file mode 100644
index 0000000..e90e05e
Binary files /dev/null and b/icons/default/osdElements/grid_bottom.png differ
diff --git a/icons/default/osdElements/grid_head.png b/icons/default/osdElements/grid_head.png
new file mode 100644
index 0000000..4196cd8
Binary files /dev/null and b/icons/default/osdElements/grid_head.png differ
diff --git a/icons/default/osdElements/grid_horizontal.png b/icons/default/osdElements/grid_horizontal.png
new file mode 100644
index 0000000..6bccb3f
Binary files /dev/null and b/icons/default/osdElements/grid_horizontal.png differ
diff --git a/icons/default/osdElements/grid_left.png b/icons/default/osdElements/grid_left.png
new file mode 100644
index 0000000..7b17046
Binary files /dev/null and b/icons/default/osdElements/grid_left.png differ
diff --git a/icons/default/osdElements/grid_right.png b/icons/default/osdElements/grid_right.png
new file mode 100644
index 0000000..17fe003
Binary files /dev/null and b/icons/default/osdElements/grid_right.png differ
diff --git a/icons/default/osdElements/grid_vertical.png b/icons/default/osdElements/grid_vertical.png
new file mode 100644
index 0000000..e7192ac
Binary files /dev/null and b/icons/default/osdElements/grid_vertical.png differ
diff --git a/icons/default/osdElements/grids_vertical.png b/icons/default/osdElements/grids_vertical.png
new file mode 100644
index 0000000..a481f27
Binary files /dev/null and b/icons/default/osdElements/grids_vertical.png differ
diff --git a/icons/default/osdElements/recmenu_background.png b/icons/default/osdElements/recmenu_background.png
new file mode 100644
index 0000000..018260b
Binary files /dev/null and b/icons/default/osdElements/recmenu_background.png differ
diff --git a/icons/default/osdElements/statusheader_content_full.png b/icons/default/osdElements/statusheader_content_full.png
new file mode 100644
index 0000000..18c6552
Binary files /dev/null and b/icons/default/osdElements/statusheader_content_full.png differ
diff --git a/icons/default/osdElements/statusheader_content_windowed.png b/icons/default/osdElements/statusheader_content_windowed.png
new file mode 100644
index 0000000..24fd20c
Binary files /dev/null and b/icons/default/osdElements/statusheader_content_windowed.png differ
diff --git a/icons/default/osdElements/statusheader_tvframe.png b/icons/default/osdElements/statusheader_tvframe.png
new file mode 100644
index 0000000..cdb800c
Binary files /dev/null and b/icons/default/osdElements/statusheader_tvframe.png differ
diff --git a/icons/default/osdElements/timeline1_horizontal.png b/icons/default/osdElements/timeline1_horizontal.png
new file mode 100644
index 0000000..9240b37
Binary files /dev/null and b/icons/default/osdElements/timeline1_horizontal.png differ
diff --git a/icons/default/osdElements/timeline1_vertical.png b/icons/default/osdElements/timeline1_vertical.png
new file mode 100644
index 0000000..5466546
Binary files /dev/null and b/icons/default/osdElements/timeline1_vertical.png differ
diff --git a/icons/default/osdElements/timeline2_horizontal.png b/icons/default/osdElements/timeline2_horizontal.png
new file mode 100644
index 0000000..4364677
Binary files /dev/null and b/icons/default/osdElements/timeline2_horizontal.png differ
diff --git a/icons/default/osdElements/timeline2_vertical.png b/icons/default/osdElements/timeline2_vertical.png
new file mode 100644
index 0000000..dfa06c9
Binary files /dev/null and b/icons/default/osdElements/timeline2_vertical.png differ
diff --git a/icons/default/recmenuicons/activetimer.png b/icons/default/recmenuicons/activetimer.png
new file mode 100644
index 0000000..af4c33c
Binary files /dev/null and b/icons/default/recmenuicons/activetimer.png differ
diff --git a/icons/default/recmenuicons/arrow_left.png b/icons/default/recmenuicons/arrow_left.png
new file mode 100644
index 0000000..57800c7
Binary files /dev/null and b/icons/default/recmenuicons/arrow_left.png differ
diff --git a/icons/default/recmenuicons/arrow_right.png b/icons/default/recmenuicons/arrow_right.png
new file mode 100644
index 0000000..ea45f3a
Binary files /dev/null and b/icons/default/recmenuicons/arrow_right.png differ
diff --git a/icons/default/recmenuicons/delete_active.png b/icons/default/recmenuicons/delete_active.png
new file mode 100644
index 0000000..f473717
Binary files /dev/null and b/icons/default/recmenuicons/delete_active.png differ
diff --git a/icons/default/recmenuicons/delete_inactive.png b/icons/default/recmenuicons/delete_inactive.png
new file mode 100644
index 0000000..21b0a88
Binary files /dev/null and b/icons/default/recmenuicons/delete_inactive.png differ
diff --git a/icons/default/recmenuicons/edit_active.png b/icons/default/recmenuicons/edit_active.png
new file mode 100644
index 0000000..ec39699
Binary files /dev/null and b/icons/default/recmenuicons/edit_active.png differ
diff --git a/icons/default/recmenuicons/edit_inactive.png b/icons/default/recmenuicons/edit_inactive.png
new file mode 100644
index 0000000..71f016c
Binary files /dev/null and b/icons/default/recmenuicons/edit_inactive.png differ
diff --git a/icons/default/recmenuicons/icon_backspace.png b/icons/default/recmenuicons/icon_backspace.png
new file mode 100644
index 0000000..6065fa3
Binary files /dev/null and b/icons/default/recmenuicons/icon_backspace.png differ
diff --git a/icons/default/recmenuicons/icon_del_ins.png b/icons/default/recmenuicons/icon_del_ins.png
new file mode 100644
index 0000000..f05a96b
Binary files /dev/null and b/icons/default/recmenuicons/icon_del_ins.png differ
diff --git a/icons/default/recmenuicons/icon_shift.png b/icons/default/recmenuicons/icon_shift.png
new file mode 100644
index 0000000..15ae851
Binary files /dev/null and b/icons/default/recmenuicons/icon_shift.png differ
diff --git a/icons/default/recmenuicons/info_active.png b/icons/default/recmenuicons/info_active.png
new file mode 100644
index 0000000..c88f76d
Binary files /dev/null and b/icons/default/recmenuicons/info_active.png differ
diff --git a/icons/default/recmenuicons/info_inactive.png b/icons/default/recmenuicons/info_inactive.png
new file mode 100644
index 0000000..37eeed2
Binary files /dev/null and b/icons/default/recmenuicons/info_inactive.png differ
diff --git a/icons/default/recmenuicons/no.png b/icons/default/recmenuicons/no.png
new file mode 100644
index 0000000..47cdba0
Binary files /dev/null and b/icons/default/recmenuicons/no.png differ
diff --git a/icons/default/recmenuicons/record_active.png b/icons/default/recmenuicons/record_active.png
new file mode 100644
index 0000000..476da99
Binary files /dev/null and b/icons/default/recmenuicons/record_active.png differ
diff --git a/icons/default/recmenuicons/record_inactive.png b/icons/default/recmenuicons/record_inactive.png
new file mode 100644
index 0000000..2a91da3
Binary files /dev/null and b/icons/default/recmenuicons/record_inactive.png differ
diff --git a/icons/default/recmenuicons/search_active.png b/icons/default/recmenuicons/search_active.png
new file mode 100644
index 0000000..7bf7bc7
Binary files /dev/null and b/icons/default/recmenuicons/search_active.png differ
diff --git a/icons/default/recmenuicons/search_inactive.png b/icons/default/recmenuicons/search_inactive.png
new file mode 100644
index 0000000..4a210bb
Binary files /dev/null and b/icons/default/recmenuicons/search_inactive.png differ
diff --git a/icons/default/recmenuicons/yes.png b/icons/default/recmenuicons/yes.png
new file mode 100644
index 0000000..2f1af98
Binary files /dev/null and b/icons/default/recmenuicons/yes.png differ
diff --git a/icons/recmenuicons/activetimer.png b/icons/recmenuicons/activetimer.png
new file mode 100644
index 0000000..af4c33c
Binary files /dev/null and b/icons/recmenuicons/activetimer.png differ
diff --git a/icons/recmenuicons/arrow_left.png b/icons/recmenuicons/arrow_left.png
new file mode 100644
index 0000000..57800c7
Binary files /dev/null and b/icons/recmenuicons/arrow_left.png differ
diff --git a/icons/recmenuicons/arrow_right.png b/icons/recmenuicons/arrow_right.png
new file mode 100644
index 0000000..ea45f3a
Binary files /dev/null and b/icons/recmenuicons/arrow_right.png differ
diff --git a/icons/recmenuicons/delete_active.png b/icons/recmenuicons/delete_active.png
new file mode 100644
index 0000000..f473717
Binary files /dev/null and b/icons/recmenuicons/delete_active.png differ
diff --git a/icons/recmenuicons/delete_inactive.png b/icons/recmenuicons/delete_inactive.png
new file mode 100644
index 0000000..21b0a88
Binary files /dev/null and b/icons/recmenuicons/delete_inactive.png differ
diff --git a/icons/recmenuicons/edit_active.png b/icons/recmenuicons/edit_active.png
new file mode 100644
index 0000000..ec39699
Binary files /dev/null and b/icons/recmenuicons/edit_active.png differ
diff --git a/icons/recmenuicons/edit_inactive.png b/icons/recmenuicons/edit_inactive.png
new file mode 100644
index 0000000..71f016c
Binary files /dev/null and b/icons/recmenuicons/edit_inactive.png differ
diff --git a/icons/recmenuicons/icon_backspace.png b/icons/recmenuicons/icon_backspace.png
new file mode 100644
index 0000000..6065fa3
Binary files /dev/null and b/icons/recmenuicons/icon_backspace.png differ
diff --git a/icons/recmenuicons/icon_del_ins.png b/icons/recmenuicons/icon_del_ins.png
new file mode 100644
index 0000000..f05a96b
Binary files /dev/null and b/icons/recmenuicons/icon_del_ins.png differ
diff --git a/icons/recmenuicons/icon_shift.png b/icons/recmenuicons/icon_shift.png
new file mode 100644
index 0000000..15ae851
Binary files /dev/null and b/icons/recmenuicons/icon_shift.png differ
diff --git a/icons/recmenuicons/info_active.png b/icons/recmenuicons/info_active.png
new file mode 100644
index 0000000..c88f76d
Binary files /dev/null and b/icons/recmenuicons/info_active.png differ
diff --git a/icons/recmenuicons/info_inactive.png b/icons/recmenuicons/info_inactive.png
new file mode 100644
index 0000000..37eeed2
Binary files /dev/null and b/icons/recmenuicons/info_inactive.png differ
diff --git a/icons/recmenuicons/no.png b/icons/recmenuicons/no.png
new file mode 100644
index 0000000..47cdba0
Binary files /dev/null and b/icons/recmenuicons/no.png differ
diff --git a/icons/recmenuicons/record_active.png b/icons/recmenuicons/record_active.png
new file mode 100644
index 0000000..476da99
Binary files /dev/null and b/icons/recmenuicons/record_active.png differ
diff --git a/icons/recmenuicons/record_inactive.png b/icons/recmenuicons/record_inactive.png
new file mode 100644
index 0000000..2a91da3
Binary files /dev/null and b/icons/recmenuicons/record_inactive.png differ
diff --git a/icons/recmenuicons/search_active.png b/icons/recmenuicons/search_active.png
new file mode 100644
index 0000000..7bf7bc7
Binary files /dev/null and b/icons/recmenuicons/search_active.png differ
diff --git a/icons/recmenuicons/search_inactive.png b/icons/recmenuicons/search_inactive.png
new file mode 100644
index 0000000..4a210bb
Binary files /dev/null and b/icons/recmenuicons/search_inactive.png differ
diff --git a/icons/recmenuicons/yes.png b/icons/recmenuicons/yes.png
new file mode 100644
index 0000000..2f1af98
Binary files /dev/null and b/icons/recmenuicons/yes.png differ
diff --git a/imagecache.c b/imagecache.c
new file mode 100644
index 0000000..eb3117c
--- /dev/null
+++ b/imagecache.c
@@ -0,0 +1,715 @@
+#include <string>
+#include <sstream>
+#include <map>
+#include <vdr/channels.h>
+#include "config.h"
+#include "imagescaler.h"
+#include "tools.h"
+#include "imagecache.h"
+
+cImageCache::cImageCache() : cImageMagickWrapper() {
+    tempStaticLogo = NULL;
+    groupsHead = NULL;
+    groupsBottom = NULL;
+    groupsLeft = NULL;
+    groupsRight = NULL;
+    imgLeft = NULL;
+    imgLeftActive = NULL;
+    imgRight = NULL;
+    imgRightActive = NULL;
+    imgHead = NULL;
+    imgHeadActive = NULL;
+    imgBottom = NULL;
+    imgBottomActive = NULL;
+}
+
+cImageCache::~cImageCache() {
+    Clear();
+}
+
+void cImageCache::CreateCache(void) {
+    if (tvguideConfig.style != eStyleGraphical)
+        return;
+    esyslog("tvguide: Creating Image Cache");
+    int start = cTimeMs::Now();
+    int startNext = cTimeMs::Now();
+    CreateOsdIconCache();
+    esyslog("tvguide: Osd Icon Cash created in %d ms", int(cTimeMs::Now()-startNext));
+    startNext = cTimeMs::Now();
+    PrepareGridIconCache();
+    CreateGridIconCache();
+    esyslog("tvguide: Grid Icon Cash created in %d ms", int(cTimeMs::Now()-startNext));
+    startNext = cTimeMs::Now();
+    CreateChannelGroupCache();
+    esyslog("tvguide: Channelgroup Cash created in %d ms", int(cTimeMs::Now()-startNext));
+    startNext = cTimeMs::Now();
+    CreateLogoCache();
+    esyslog("tvguide: Logo Cash created in %d ms", int(cTimeMs::Now()-startNext));
+    startNext = cTimeMs::Now();
+    esyslog("tvguide: Complete Image Cash created in %d ms", int(cTimeMs::Now()-start));
+}
+
+void cImageCache::CreateOsdIconCache(void) {
+    bool success = false;
+    //Status Header
+    std::string imgStatusHeaderContentFull = "osdElements/statusheader_content_full";
+    std::string imgStatusHeaderContentWindowed = "osdElements/statusheader_content_windowed";
+    std::string imgStatusHeaderTVFrame = "osdElements/statusheader_tvframe";
+    success = LoadIcon(imgStatusHeaderContentFull);
+    if (success)
+        InsertIntoOsdElementCache(oeStatusHeaderContentFull, geoManager.headerContentWidth, geoManager.statusHeaderHeight);
+    success = LoadIcon(imgStatusHeaderContentWindowed);
+    if (success)
+        InsertIntoOsdElementCache(oeStatusHeaderContentWindowed, geoManager.headerContentWidth, geoManager.statusHeaderHeight);
+    success = LoadIcon(imgStatusHeaderTVFrame);
+    if (success)
+        InsertIntoOsdElementCache(oeStatusHeaderTVFrame, geoManager.tvFrameWidth, geoManager.statusHeaderHeight);
+   
+
+    //Color Buttons
+    std::string imgButtonRed = "osdElements/buttonred";
+    std::string imgButtonGreen = "osdElements/buttongreen";
+    std::string imgButtonYellow = "osdElements/buttonyellow";
+    std::string imgButtonBlue = "osdElements/buttonblue";
+    success = LoadIcon(imgButtonRed);
+    if (success)
+        InsertIntoOsdElementCache(oeButtonRed, geoManager.buttonWidth, geoManager.buttonHeight);
+    success = LoadIcon(imgButtonGreen);
+    if (success)
+        InsertIntoOsdElementCache(oeButtonGreen, geoManager.buttonWidth, geoManager.buttonHeight);
+    success = LoadIcon(imgButtonYellow);
+    if (success)
+        InsertIntoOsdElementCache(oeButtonYellow, geoManager.buttonWidth, geoManager.buttonHeight);
+    success = LoadIcon(imgButtonBlue);
+    if (success)
+        InsertIntoOsdElementCache(oeButtonBlue, geoManager.buttonWidth, geoManager.buttonHeight);
+
+    //Channel Logo Background
+    if (tvguideConfig.displayMode == eHorizontal) {
+        success = LoadIcon("osdElements/channellogoback_horizontal");
+    } else {
+        success = LoadIcon("osdElements/channellogoback_vertical");        
+    }
+    if (success)
+        InsertIntoOsdElementCache(oeLogoBack, geoManager.channelLogoWidth, geoManager.channelLogoHeight);
+
+    //Timeline Elements
+    std::string imgTimeline1, imgTimeline2, imgDateViewer;
+    if (tvguideConfig.displayMode == eHorizontal) {
+        imgTimeline1 = "osdElements/timeline1_horizontal";
+        imgTimeline2 = "osdElements/timeline2_horizontal";
+        imgDateViewer = "osdElements/timeline2_horizontal";
+    } else {
+        imgTimeline1 = "osdElements/timeline1_vertical";
+        imgTimeline2 = "osdElements/timeline2_vertical";
+        imgDateViewer = "osdElements/date_vertical";
+    }
+    std::string imgClock = "osdElements/clock";
+    success = LoadIcon(imgTimeline1);
+    if (success)
+        InsertIntoOsdElementCache(oeTimeline1, geoManager.timeLineGridWidth, geoManager.timeLineGridHeight);
+    success = LoadIcon(imgTimeline2);
+    if (success)
+        InsertIntoOsdElementCache(oeTimeline2, geoManager.timeLineGridWidth, geoManager.timeLineGridHeight);
+    success = LoadIcon(imgDateViewer);
+    if (success)
+        InsertIntoOsdElementCache(oeDateViewer, geoManager.dateVieverWidth, geoManager.dateVieverHeight);
+    success = LoadIcon(imgClock);
+    if (success)
+        InsertIntoOsdElementCache(oeClock, geoManager.clockWidth, geoManager.clockHeight);
+
+    //Channel Jump
+    success = LoadIcon("osdElements/channel_jump");
+    if (success)
+        InsertIntoOsdElementCache(oeChannelJump, geoManager.channelJumpWidth, geoManager.channelJumpHeight);
+}
+
+void cImageCache::PrepareGridIconCache(void) {
+    bool success = false;
+    //Create Buffers for Background
+    gridsAvailable = true;
+    std::string grid, grid_active;
+    if (tvguideConfig.displayMode == eHorizontal) {
+        grid = "osdElements/grid_horizontal";
+        grid_active = "osdElements/grid_active_horizontal";
+    } else {
+        grid = "osdElements/grid_vertical";
+        grid_active = "osdElements/grid_active_vertical";        
+    }
+    success = LoadIcon(grid);
+    if (success) {
+        bufferGrid = buffer;
+    } else {
+        gridsAvailable = false;
+    }
+    success = LoadIcon(grid_active);
+    if (success) {
+        bufferGridActive = buffer;
+    } else {
+        gridsAvailable = false;
+    }
+    //Create Grid Background Templates
+    imgLeft = NULL;
+    imgLeftActive = NULL;
+    imgRight = NULL;
+    imgRightActive = NULL;
+    imgHead = NULL;
+    imgHeadActive = NULL;
+    imgBottom = NULL;
+    imgBottomActive = NULL;
+
+    if (tvguideConfig.displayMode == eHorizontal) {
+        std::string left = "osdElements/grid_left";
+        std::string right = "osdElements/grid_right";
+        std::string left_active = "osdElements/grid_active_left";
+        std::string right_active = "osdElements/grid_active_right";
+        cornerWidth = 0;
+        cornerHeight = geoManager.rowHeight;
+        //first image determinates width
+        success = LoadIcon(left);
+        if (!success)
+            return;
+        int widthOriginal = 0;
+        int heightOriginal = 0;
+        widthOriginal = buffer.columns();
+        heightOriginal = buffer.rows();
+        cornerWidth = widthOriginal * cornerHeight / heightOriginal;
+        imgLeft = CreateImage(cornerWidth, cornerHeight, false);
+        success = LoadIcon(right);
+        if (success)
+            imgRight = CreateImage(cornerWidth, cornerHeight, false);
+        success = LoadIcon(left_active);
+        if (success)
+            imgLeftActive = CreateImage(cornerWidth, cornerHeight, false);
+        success = LoadIcon(right_active);
+        if (success)
+            imgRightActive = CreateImage(cornerWidth, cornerHeight, false);
+    } else {
+        std::string head = "osdElements/grid_head";
+        std::string bottom = "osdElements/grid_bottom";
+        std::string head_active = "osdElements/grid_active_head";
+        std::string bottom_active = "osdElements/grid_active_bottom";
+        cornerWidth = geoManager.colWidth;
+        cornerHeight = 0;
+        //first image determinates height
+        success = LoadIcon(head);
+        if (!success)
+            return;
+        int widthOriginal = 0;
+        int heightOriginal = 0;
+        widthOriginal = buffer.columns();
+        heightOriginal = buffer.rows();
+        cornerHeight = heightOriginal * cornerWidth / widthOriginal;
+        imgHead = CreateImage(cornerWidth, cornerHeight, false);
+        success = LoadIcon(bottom);
+        if (success)
+            imgBottom = CreateImage(cornerWidth, cornerHeight, false);
+        success = LoadIcon(head_active);
+        if (success)
+            imgHeadActive = CreateImage(cornerWidth, cornerHeight, false);
+        success = LoadIcon(bottom_active);
+        if (success)
+            imgBottomActive = CreateImage(cornerWidth, cornerHeight, false);
+    }
+}
+
+void cImageCache::CreateGridIconCache(void) {
+    if (tvguideConfig.displayMode == eHorizontal) {
+        int gridHeight = geoManager.rowHeight;
+        for (int minutes = 5; minutes <= 120; minutes += 5) {
+            GetGrid(minutes * geoManager.minutePixel, gridHeight, false);
+        }
+    } else {
+        int gridWidth = geoManager.colWidth;
+        for (int minutes = 5; minutes <= 120; minutes += 5) {
+            GetGrid(gridWidth, minutes * geoManager.minutePixel, false);
+        }
+    }
+}
+
+void cImageCache::CreateChannelGroupCache(void) {
+    bool success = false;
+    groupsHead = NULL;
+    groupsBottom = NULL;
+    groupsLeft = NULL;
+    groupsRight = NULL;
+    if (tvguideConfig.displayMode == eHorizontal) {
+        std::string channelGroupHead = "osdElements/channelgroup_head";
+        std::string channelGroupBottom = "osdElements/channelgroup_bottom";
+        int width = geoManager.channelGroupsWidth;
+        int heightHeadBottom = 0;
+        success = LoadIcon(channelGroupHead);
+        if (success) {
+            int widthOriginal = buffer.columns();
+            int heightOriginal = buffer.rows();
+            heightHeadBottom = heightOriginal * width / widthOriginal;
+            groupsHead = CreateImage(width, heightHeadBottom, false);
+        }
+        success = LoadIcon(channelGroupBottom);
+        if (success && heightHeadBottom) {
+            groupsBottom = CreateImage(width, heightHeadBottom, false);
+        }
+        for (int size = 1; size <= tvguideConfig.numGrids; ++size) {
+            InsertIntoGroupsCacheHorizontal(size);
+        }
+    } else {
+        std::string channelGroupLeft = "osdElements/channelgroup_left";
+        std::string channelGroupRight = "osdElements/channelgroup_right";
+        int widthHeadBottom = 0;
+        int height = geoManager.channelGroupsHeight;
+        success = LoadIcon(channelGroupLeft);
+        if (success) {
+            int widthOriginal = buffer.columns();
+            int heightOriginal = buffer.rows();
+            widthHeadBottom = widthOriginal * height / heightOriginal;
+            groupsLeft = CreateImage(widthHeadBottom, height, false);
+        }
+        success = LoadIcon(channelGroupRight);
+        if (success && widthHeadBottom) {
+            groupsRight = CreateImage(widthHeadBottom, height, false);
+        }
+        for (int size = 1; size <= tvguideConfig.numGrids; ++size) {
+            InsertIntoGroupsCacheVertical(size);
+        }
+    }
+    
+}
+
+void cImageCache::CreateLogoCache(void) {
+    if (tvguideConfig.hideChannelLogos)
+        return;
+    if (tvguideConfig.numLogosInitial > 0) {
+        int channelsCached = 0;
+        for (const cChannel *channel = Channels.First(); channel; channel = Channels.Next(channel)) {
+            if (channelsCached >= tvguideConfig.numLogosInitial)
+                break;
+            if (!channel->GroupSep()) {
+                bool success = LoadLogo(channel);
+                if (success) {
+                    channelsCached++;
+                    InsertIntoLogoCache(*channel->GetChannelID().ToString());
+                }
+            }
+
+        }
+    }
+}
+
+
+cImage *cImageCache::GetOsdElement(eOsdElementType type) {
+	std::map<eOsdElementType, cImage*>::iterator hit = osdElementCache.find(type);
+    if (hit != osdElementCache.end()) {
+        return (cImage*)hit->second;
+    }
+    return NULL;
+}
+
+cImage *cImageCache::GetGrid(int width, int height, bool active) {
+    if (!gridsAvailable)
+        return NULL;
+    std::stringstream gridImageName;
+    gridImageName << width << "x" << height;
+    if (active)
+        gridImageName << "active";
+    std::string gridImg = gridImageName.str();
+    std::map<std::string, cImage*>::iterator hit = gridCache.find(gridImg);
+    if (hit != gridCache.end()) {
+        return (cImage*)hit->second;
+    } else {
+        InsertIntoGridCache(gridImg, width, height, active);
+        hit = gridCache.find(gridImg);
+        if (hit != gridCache.end()) {
+            return (cImage*)hit->second;
+        }
+    }
+    return NULL;
+}
+
+cImage *cImageCache::GetChannelGroup(int width, int height) {
+    std::stringstream groupName;
+    groupName << width << "x" << height;
+    std::map<std::string, cImage*>::iterator hit = groupsCache.find(groupName.str());
+    if (hit != groupsCache.end()) {
+        return (cImage*)hit->second;
+    }
+    return NULL;
+}
+
+cImage *cImageCache::GetLogo(const cChannel *channel) {
+    if (!channel)
+        return NULL;
+
+    std::map<std::string, cImage*>::iterator hit = logoCache.find(*channel->GetChannelID().ToString());
+
+    if (hit != logoCache.end()) {
+        return (cImage*)hit->second;
+    } else {
+        bool success = LoadLogo(channel);
+        if (success) {
+            if ((tvguideConfig.limitLogoCache) && (logoCache.size() >= tvguideConfig.numLogosMax)) {
+            //logo cache is full, don't cache anymore
+                if (tempStaticLogo) {
+                    delete tempStaticLogo;
+                    tempStaticLogo = NULL;
+                }
+                tempStaticLogo = CreateImage(geoManager.logoWidth, geoManager.logoHeight);
+                return tempStaticLogo;
+            } else {
+            //add requested logo to cache
+                InsertIntoLogoCache(*channel->GetChannelID().ToString());
+                hit = logoCache.find(*channel->GetChannelID().ToString());
+                if (hit != logoCache.end()) {
+                    return (cImage*)hit->second;
+                }
+            }
+        }
+    }
+    return NULL;
+}
+
+cImage *cImageCache::GetIcon(std::string name, int width, int height) {
+    std::stringstream iconName;
+    iconName << name << width << "x" << height;
+    std::map<std::string, cImage*>::iterator hit = iconCache.find(iconName.str());
+    if (hit != iconCache.end()) {
+        return (cImage*)hit->second;
+    } else {
+        std::stringstream iconPath;
+        iconPath << "recmenuicons/" << name;
+        bool success = LoadIcon(iconPath.str());
+        if (success) {
+            cImage *image = CreateImage(width, height);
+            iconCache.insert(std::pair<std::string, cImage*>(iconName.str(), image));
+            hit = iconCache.find(iconName.str());
+            if (hit != iconCache.end()) {
+                return (cImage*)hit->second;
+            }
+        }
+    }
+    return NULL;
+}
+
+void cImageCache::InsertIntoOsdElementCache(eOsdElementType type, int width, int height) {
+    cImage *image = CreateImage(width, height, false);
+    if (image)
+        osdElementCache.insert(std::pair<eOsdElementType, cImage*>(type, image));
+}
+
+void cImageCache::InsertIntoGridCache(std::string name, int width, int height, bool active) {
+    cImage *image = CreateGrid(width, height, active);
+    if (image) {
+        if (tvguideConfig.displayMode == eHorizontal) {
+            AddCornersHorizontal(image, active);
+        } else {
+            AddCornersVertical(image, active);
+        }
+        gridCache.insert(std::pair<std::string, cImage*>(name, image));
+    }
+}
+
+cImage *cImageCache::CreateGrid(int width, int height, bool active) {
+    if (width > geoManager.osdWidth || width < 6 || height > geoManager.osdHeight || height < 6)
+        return NULL;
+    Image *currentGridBuffer = NULL;
+    if (active)
+        currentGridBuffer = &bufferGridActive;
+    else
+        currentGridBuffer = &bufferGrid;
+    int w, h;
+    w = currentGridBuffer->columns();
+    h = currentGridBuffer->rows();
+    const PixelPacket *pixels = currentGridBuffer->getConstPixels(0, 0, w, h);
+    cImage *image = NULL;
+    image = new cImage(cSize(width, height));
+    if (!image)
+        return NULL;
+    tColor *imgData = (tColor *)image->Data();
+    if (w != width || h != height) {
+        ImageScaler scaler;
+        scaler.SetImageParameters(imgData, width, width, height, w, h);
+        for (const void *pixels_end = &pixels[w*h]; pixels < pixels_end; ++pixels)
+            scaler.PutSourcePixel(pixels->blue / ((MaxRGB + 1) / 256),
+                                  pixels->green / ((MaxRGB + 1) / 256),
+                                  pixels->red / ((MaxRGB + 1) / 256),
+                                  ~((unsigned char)(pixels->opacity / ((MaxRGB + 1) / 256))));
+        return image;
+    }
+    for (const void *pixels_end = &pixels[width*height]; pixels < pixels_end; ++pixels)
+        *imgData++ = ((~int(pixels->opacity / ((MaxRGB + 1) / 256)) << 24) |
+                      (int(pixels->green / ((MaxRGB + 1) / 256)) << 8) |
+                      (int(pixels->red / ((MaxRGB + 1) / 256)) << 16) |
+                      (int(pixels->blue / ((MaxRGB + 1) / 256)) ));
+    return image;
+}
+
+void cImageCache::AddCornersHorizontal(cImage *img, bool active) {
+    int imgWidth = img->Width();
+    cImage *cornerLeft = NULL;
+    cImage *cornerRight = NULL;
+    if (active) {
+        cornerLeft = imgLeftActive;
+        cornerRight = imgRightActive;
+    } else {
+        cornerLeft = imgLeft;
+        cornerRight = imgRight;
+    }
+    if (!cornerLeft || !cornerRight)
+        return;
+    int maxX = min(cornerWidth, imgWidth);
+    for (int row = 0; row < cornerHeight; row++) {
+        for (int col = 0; col < maxX; ++col) {
+            img->SetPixel(cPoint(col, row), cornerLeft->GetPixel(cPoint(col, row)));
+            img->SetPixel(cPoint(imgWidth - maxX + col, row), cornerRight->GetPixel(cPoint(col, row)));
+        }
+    }
+}
+
+void cImageCache::AddCornersVertical(cImage *img, bool active) {
+    int imgHeight = img->Height();
+    cImage *cornerHead = NULL;
+    cImage *cornerBottom = NULL;
+    if (active) {
+        cornerHead = imgHeadActive;
+        cornerBottom = imgBottomActive;
+    } else {
+        cornerHead = imgHead;
+        cornerBottom = imgBottom;
+    }
+    if (!cornerHead || !cornerBottom)
+        return;
+    int maxY = min(cornerHeight, imgHeight);
+    for (int row = 0; row < maxY; row++) {
+        for (int col = 0; col < cornerWidth; ++col) {
+            img->SetPixel(cPoint(col, row), cornerHead->GetPixel(cPoint(col, row)));
+            img->SetPixel(cPoint(col, imgHeight - maxY + row), cornerBottom->GetPixel(cPoint(col, row)));
+        }
+    } 
+}
+
+void cImageCache::InsertIntoGroupsCacheHorizontal(int size) {
+    int width = geoManager.channelGroupsWidth;
+    bool success = LoadIcon("osdElements/channelgroup_horizontal");
+    if (success) {
+        int height = size * geoManager.rowHeight;
+        std::stringstream name;
+        name << width << "x" << height;
+        cImage *image = CreateImage(width, height, false);
+        if (image) {
+            AddCornersGroupHorizontal(image);
+            groupsCache.insert(std::pair<std::string, cImage*>(name.str(), image));
+        }
+    }
+}
+
+void cImageCache::InsertIntoGroupsCacheVertical(int size) {
+    int height = geoManager.channelGroupsHeight;
+    bool success = LoadIcon("osdElements/channelgroup_vertical");
+    if (success) {
+        int width = size * geoManager.colWidth;
+        std::stringstream name;
+        name << width << "x" << height;
+        cImage *image = CreateImage(width, height, false);
+        if (image) {
+            AddCornersGroupVertical(image);
+            groupsCache.insert(std::pair<std::string, cImage*>(name.str(), image));
+        }
+    }
+}
+
+void cImageCache::AddCornersGroupHorizontal(cImage *img) {
+    if (!groupsHead || !groupsBottom  || !img)
+        return;
+    int imgWidth = img->Width();
+    int imgHeight = img->Height();
+    int heightHeadBottom = groupsHead->Height();
+    int maxY = min(heightHeadBottom, imgHeight);
+    for (int row = 0; row < maxY; row++) {
+        for (int col = 0; col < imgWidth; ++col) {
+            img->SetPixel(cPoint(col, row), groupsHead->GetPixel(cPoint(col, row)));
+            img->SetPixel(cPoint(col, imgHeight - maxY + row), groupsBottom->GetPixel(cPoint(col, row)));
+        }
+    }
+}
+
+void cImageCache::AddCornersGroupVertical(cImage *img) {
+    if (!groupsLeft || !groupsRight  || !img)
+        return;
+    int imgWidth = img->Width();
+    int imgHeight = img->Height();
+    int widthLeftRight = groupsLeft->Width();
+    int maxX = min(widthLeftRight, imgWidth);
+    for (int row = 0; row < imgHeight; row++) {
+        for (int col = 0; col < maxX; ++col) {
+            img->SetPixel(cPoint(col, row), groupsLeft->GetPixel(cPoint(col, row)));
+            img->SetPixel(cPoint(imgWidth - maxX + col, row), groupsRight->GetPixel(cPoint(col, row)));
+        }
+    }
+}
+
+bool cImageCache::LoadIcon(std::string name) {
+    bool success = false;
+    if (tvguideConfig.iconsPathSet) {
+        cString iconPathTheme = cString::sprintf("%s%s/", *tvguideConfig.iconPath, *tvguideConfig.themeName);
+        success = LoadImage(name, *iconPathTheme, "png");
+        if (success) {
+            return true;
+        } else {
+            success = LoadImage(name, *tvguideConfig.iconPath, "png");
+            if (success) {
+                return true;
+            }
+        }
+    }
+    if (!success) {
+        cString iconPathTheme = cString::sprintf("%s%s/", *tvguideConfig.iconPathDefault, *tvguideConfig.themeName);
+        success = LoadImage(name, *iconPathTheme, "png");
+        if (success) {
+            return true;
+        } else {
+            success = LoadImage(name, *tvguideConfig.iconPathDefault, "png");
+            if (success) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool cImageCache::LoadLogo(const cChannel *channel) {
+    if (!channel)
+        return false;
+    std::string channelID = StrToLowerCase(*(channel->GetChannelID().ToString()));
+    std::string logoLower = StrToLowerCase(channel->Name());
+    bool success = false;
+    cString extension;
+    if (tvguideConfig.logoExtension == 0) {
+        extension = "png";
+    } else if (tvguideConfig.logoExtension == 1) {
+        extension = "jpg";
+    }
+
+    if (tvguideConfig.logoPathSet) {
+        success = LoadImage(channelID.c_str(), *tvguideConfig.logoPath, *extension);
+        if (success)
+            return true;
+        success = LoadImage(logoLower.c_str(), *tvguideConfig.logoPath, *extension);
+        if (success)
+            return true;
+    }
+    success = LoadImage(channelID.c_str(), *tvguideConfig.logoPathDefault, *extension);
+    if (success)
+        return true;
+    success = LoadImage(logoLower.c_str(), *tvguideConfig.logoPathDefault, *extension);
+    return success;
+}
+
+void cImageCache::InsertIntoLogoCache(std::string channelID) {
+    cImage *image = CreateImage(geoManager.logoWidth, geoManager.logoHeight);
+    logoCache.insert(std::pair<std::string, cImage*>(channelID, image));
+}
+
+std::string cImageCache::GetCacheSize(eCacheType type) {
+    std::stringstream result;
+    int sizeByte = 0;
+    int numImages = 0;
+    if (type == ctOsdElement) {
+        for(std::map<eOsdElementType, cImage*>::const_iterator it = osdElementCache.begin(); it != osdElementCache.end(); it++) {
+            cImage *img = (cImage*)it->second;
+            if (img)
+                sizeByte += img->Width() * img->Height() * sizeof(tColor);
+        }
+        numImages = osdElementCache.size();
+    } else if ((type == ctGrid) || (type == ctLogo) || (type == ctChannelGroup) || (type == ctIcon)) {
+        std::map<std::string, cImage*> *cache;
+        if (type == ctGrid)
+            cache = &gridCache;
+        else if (type == ctLogo)
+            cache = &logoCache;
+        else if (type == ctChannelGroup)
+            cache = &groupsCache;
+        else if (type == ctIcon)
+            cache = &iconCache;
+
+        for(std::map<std::string, cImage*>::const_iterator it = cache->begin(); it != cache->end(); it++) {
+            cImage *img = (cImage*)it->second;
+            if (img)
+                sizeByte += img->Width() * img->Height() * sizeof(tColor);
+        }
+        numImages = cache->size();
+    }
+    result << numImages << " " << tr("images") << " / " << sizeByte/1024 << " KByte";
+    return result.str();
+}
+
+void cImageCache::Clear(void) {
+	for(std::map<eOsdElementType, cImage*>::const_iterator it = osdElementCache.begin(); it != osdElementCache.end(); it++) {
+        cImage *img = (cImage*)it->second;
+        delete img;
+    }
+    osdElementCache.clear();
+    
+    for(std::map<std::string, cImage*>::const_iterator it = gridCache.begin(); it != gridCache.end(); it++) {
+        cImage *img = (cImage*)it->second;
+        delete img;
+    }
+    gridCache.clear();
+
+    for(std::map<std::string, cImage*>::const_iterator it = groupsCache.begin(); it != groupsCache.end(); it++) {
+        cImage *img = (cImage*)it->second;
+        delete img;
+    }
+    groupsCache.clear();
+
+    for(std::map<std::string, cImage*>::const_iterator it = logoCache.begin(); it != logoCache.end(); it++) {
+        cImage *img = (cImage*)it->second;
+        delete img;
+    }
+    logoCache.clear();
+
+    for(std::map<std::string, cImage*>::const_iterator it = iconCache.begin(); it != iconCache.end(); it++) {
+        cImage *img = (cImage*)it->second;
+        delete img;
+    }
+    iconCache.clear();
+    
+    if (tempStaticLogo)
+        delete tempStaticLogo;
+    if (groupsHead)
+        delete groupsHead;
+    if (groupsBottom)
+        delete groupsBottom;
+    if (groupsLeft)
+        delete groupsLeft;
+    if (groupsRight)
+        delete groupsRight;
+    if (imgLeft)
+        delete imgLeft;
+    if (imgLeftActive)
+        delete imgLeftActive;
+    if (imgRight)
+        delete imgRight;
+    if (imgRightActive)
+        delete imgRightActive;
+    if (imgHead)
+        delete imgHead;
+    if (imgHeadActive)
+        delete imgHeadActive;
+    if (imgBottom)
+        delete imgBottom;
+    if (imgBottomActive)
+        delete imgBottomActive;
+    
+    tempStaticLogo = NULL;
+    groupsHead = NULL;
+    groupsBottom = NULL;
+    groupsLeft = NULL;
+    groupsRight = NULL;
+    imgLeft = NULL;
+    imgLeftActive = NULL;
+    imgRight = NULL;
+    imgRightActive = NULL;
+    imgHead = NULL;
+    imgHeadActive = NULL;
+    imgBottom = NULL;
+    imgBottomActive = NULL;
+}
diff --git a/imagecache.h b/imagecache.h
new file mode 100644
index 0000000..365e910
--- /dev/null
+++ b/imagecache.h
@@ -0,0 +1,92 @@
+#ifndef __TVGUIDE_IMAGECACHE_H
+#define __TVGUIDE_IMAGECACHE_H
+
+#define X_DISPLAY_MISSING
+
+#include <map>
+#include <vector>
+#include "imagemagickwrapper.h"
+
+enum eCacheType {
+    ctOsdElement = 0,
+    ctGrid,
+    ctLogo,
+    ctChannelGroup,
+    ctIcon,
+};
+
+enum eOsdElementType {
+    oeNone = -1,
+    oeStatusHeaderContentFull,
+    oeStatusHeaderContentWindowed,
+    oeStatusHeaderTVFrame,
+    oeButtonRed,
+    oeButtonGreen,
+    oeButtonYellow,
+    oeButtonBlue,
+    oeLogoBack,
+    oeTimeline1,
+    oeTimeline2,
+    oeDateViewer,
+    oeClock,
+    oeChannelJump,
+};
+
+class cImageCache : public cImageMagickWrapper {
+public:
+    cImageCache();
+    ~cImageCache();
+    void CreateCache(void);
+    cImage *GetOsdElement(eOsdElementType type);
+    cImage *GetGrid(int width, int height, bool active);
+    cImage *GetChannelGroup(int width, int height);
+    cImage *GetLogo(const cChannel *channel);
+    cImage *GetIcon(std::string name, int width, int height);
+    std::string GetCacheSize(eCacheType type);
+    void Clear(void);
+private:
+    cImage *tempStaticLogo;
+    Image bufferGrid;
+    Image bufferGridActive;
+    bool gridsAvailable;
+    int cornerWidth;
+    int cornerHeight;
+    cImage *imgLeft;
+    cImage *imgLeftActive;
+    cImage *imgRight;
+    cImage *imgRightActive;
+    cImage *imgHead;
+    cImage *imgHeadActive;
+    cImage *imgBottom;
+    cImage *imgBottomActive;
+    cImage *imgChannelgroupHead;
+    cImage *imgChannelgroupBottom;
+    cImage *groupsHead;
+    cImage *groupsBottom;
+    cImage *groupsLeft;
+    cImage *groupsRight;
+	std::map<eOsdElementType, cImage*> osdElementCache;
+    std::map<std::string, cImage*> gridCache;
+    std::map<std::string, cImage*> groupsCache;
+    std::map<std::string, cImage*> logoCache;
+    std::map<std::string, cImage*> iconCache;
+    void CreateOsdIconCache(void);
+    void PrepareGridIconCache(void);
+    void CreateGridIconCache(void);
+    void CreateChannelGroupCache(void);
+    void CreateLogoCache(void);
+	bool LoadIcon(std::string name);
+	void InsertIntoOsdElementCache(eOsdElementType type, int width=0, int height=0);
+    void InsertIntoGridCache(std::string name, int width, int height, bool active);
+    cImage *CreateGrid(int width, int height, bool active);
+    void AddCornersHorizontal(cImage *img, bool active);
+    void AddCornersVertical(cImage *img, bool active);
+    void InsertIntoGroupsCacheHorizontal(int size);
+    void InsertIntoGroupsCacheVertical(int size);
+    void AddCornersGroupHorizontal(cImage *img);
+    void AddCornersGroupVertical(cImage *img);
+    bool LoadLogo(const cChannel *channel);
+    void InsertIntoLogoCache(std::string channelID);
+};
+
+#endif //__TVGUIDE_IMAGECACHE_H
\ No newline at end of file
diff --git a/imageloader.c b/imageloader.c
index 02586d6..6ca5d69 100644
--- a/imageloader.c
+++ b/imageloader.c
@@ -1,8 +1,12 @@
-#include "imageloader.h"
 #include <math.h>
 #include <string>
 #include <dirent.h>
 #include <iostream>
+#include <vdr/channels.h>
+
+#include "config.h"
+#include "imageloader.h"
+#include "tools.h"
 
 using namespace Magick;
 
@@ -13,31 +17,54 @@ cImageLoader::cImageLoader() {
 cImageLoader::~cImageLoader() {
 }
 
-bool cImageLoader::LoadLogo(const char *logo, int width = tvguideConfig.logoWidth, int height = tvguideConfig.logoHeight) {
-    if ((width == 0)||(height==0))
+bool cImageLoader::LoadLogo(const cChannel *channel, int width, int height) {
+    if (!channel || (width == 0)||(height==0))
         return false;
-    std::string logoLower = logo;
-    toLowerCase(logoLower);
+    std::string channelID = StrToLowerCase(*(channel->GetChannelID().ToString()));
+    std::string logoLower = StrToLowerCase(channel->Name());
     cString extension;
     if (tvguideConfig.logoExtension == 0) {
-		extension = "png";
-	} else if (tvguideConfig.logoExtension == 1) {
-		extension = "jpg";
-	}
-    if (!LoadImage(logoLower.c_str(), tvguideConfig.logoPath, extension))
-        return false;
-    if (height != 0 || width != 0) {
-        buffer.sample( Geometry(width, height));
+        extension = "png";
+    } else if (tvguideConfig.logoExtension == 1) {
+        extension = "jpg";
+    }
+    bool success = false;
+    if (tvguideConfig.logoPathSet) {
+        success = LoadImage(channelID.c_str(), *tvguideConfig.logoPath, *extension);
+        if (!success) {
+            success = LoadImage(logoLower.c_str(), *tvguideConfig.logoPath, *extension);
+        }
     }
+    if (!success)
+        success = LoadImage(channelID.c_str(), *tvguideConfig.logoPathDefault, *extension);
+    if (!success)
+        success = LoadImage(logoLower.c_str(), *tvguideConfig.logoPathDefault, *extension);
+    if (success)
+        buffer.sample(Geometry(width, height));
+    return success;
+}
+
+bool cImageLoader::LoadEPGImage(int eventID, int width, int height) {
+    if ((width == 0)||(height==0))
+        return false;
+    bool success = false;
+    success = LoadImage(*cString::sprintf("%d", eventID), *tvguideConfig.epgImagePath, "jpg");
+    if (!success)
+        success = LoadImage(*cString::sprintf("%d_0", eventID), *tvguideConfig.epgImagePath, "jpg");
+    if (!success)
+        return false;
+    buffer.sample( Geometry(width, height));
     return true;
 }
 
-bool cImageLoader::LoadEPGImage(int eventID) {
-    int width = tvguideConfig.epgImageWidth;
-    int height = tvguideConfig.epgImageHeight;
+bool cImageLoader::LoadAdditionalEPGImage(cString name) {
+    int width = tvguideConfig.epgImageWidthLarge;
+    int height = tvguideConfig.epgImageHeightLarge;
     if ((width == 0)||(height==0))
         return false;
-    if (!LoadImage(cString::sprintf("%d", eventID), tvguideConfig.epgImagePath, "jpg"))
+    bool success = false;
+    success = LoadImage(*name, *tvguideConfig.epgImagePath, "jpg");
+    if (!success)
         return false;
     if (height != 0 || width != 0) {
         buffer.sample( Geometry(width, height));
@@ -45,17 +72,72 @@ bool cImageLoader::LoadEPGImage(int eventID) {
     return true;
 }
 
+bool cImageLoader::LoadPoster(const char *poster, int width, int height) {
+    if (LoadImage(poster)) {
+        buffer.sample(Geometry(width, height));
+        return true;
+    }
+    return false;
+}
+
+bool cImageLoader::LoadIcon(const char *cIcon, int size) {
+    if (size==0)
+        return false;
+    bool success = false;
+    if (tvguideConfig.iconsPathSet) {
+        cString iconPathTheme = cString::sprintf("%s%s/recmenuicons/", *tvguideConfig.iconPath, *tvguideConfig.themeName);
+        success = LoadImage(cIcon, *iconPathTheme, "png");
+        if (!success) {
+            cString iconPath = cString::sprintf("%srecmenuicons/", *tvguideConfig.iconPath);
+            success = LoadImage(cIcon, *iconPath, "png");
+        }
+    }
+    if (!success) {
+        cString iconPathTheme = cString::sprintf("%s%s/recmenuicons/", *tvguideConfig.iconPathDefault, *tvguideConfig.themeName);
+        success = LoadImage(cIcon, *iconPathTheme, "png");
+        if (!success) {
+            cString iconPath = cString::sprintf("%srecmenuicons/", *tvguideConfig.iconPathDefault);
+            success = LoadImage(cIcon, *iconPath, "png");
+        }
+    }
+    if (!success)
+        return false;
+    buffer.sample(Geometry(size, size));
+    return true;
+}
+
+bool cImageLoader::LoadOsdElement(cString name, int width, int height) {
+    if ((width == 0)||(height==0))
+        return false;
+    bool success = false;
+    if (tvguideConfig.iconsPathSet) {
+        cString path = cString::sprintf("%s%s%s", *tvguideConfig.iconPath, *tvguideConfig.themeName, "/osdElements/");
+        success = LoadImage(*name, *path, "png");
+        if (!success) {
+            path = cString::sprintf("%s%s", *tvguideConfig.iconPath, "/osdElements/");
+            success = LoadImage(*name, *path, "png");
+        }
+    }
+    if (!success) {
+        cString path = cString::sprintf("%s%s%s", *tvguideConfig.iconPathDefault, *tvguideConfig.themeName, "/osdElements/");
+        success = LoadImage(*name, *path, "png");
+    }
+    if (!success) {
+        cString path = cString::sprintf("%s%s", *tvguideConfig.iconPathDefault, "/osdElements/");
+        success = LoadImage(*name, *path, "png");
+    }
+    if (!success)
+        return false;
+    Geometry size(width, height);
+    size.aspect(true);
+    buffer.sample(size);
+    return true;
+}
+
 bool cImageLoader::DrawBackground(tColor back, tColor blend, int width, int height) {
-    if ((width == 0) || (height == 0))
+    if ((width < 1) || (height < 1) || (width > 1920) || (height > 1080))
         return false;
-    Color Back = Argb2Color(back);
-    Color Blend = Argb2Color(blend);
-    Image tmp(Geometry(width, height), Blend);
-    double arguments[9] = {0.0,(double)height,0.0,-1*(double)width,0.0,0.0,1.5*(double)width,0.0,1.0};
-    tmp.sparseColor(MatteChannel, BarycentricColorInterpolate, 9, arguments);
-    Image tmp2(Geometry(width, height), Back);
-    tmp.composite(tmp2, 0, 0, OverlayCompositeOp);
-    buffer = tmp;
+    CreateGradient(back, blend, width, height, 0.8, 0.8);
     return true;
 }
 
@@ -78,30 +160,27 @@ cImage cImageLoader::GetImage() {
     return image;
 }
 
-Color cImageLoader::Argb2Color(tColor col) {
-    tIndex alpha = (col & 0xFF000000) >> 24;
-    tIndex red = (col & 0x00FF0000) >> 16;
-    tIndex green = (col & 0x0000FF00) >> 8;
-    tIndex blue = (col & 0x000000FF);
-    Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255);
-    return color;
-}
+void cImageLoader::CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor) {
+    Color Back = Argb2Color(back);
+    Color Blend = Argb2Color(blend);
+    int maxw = MaxRGB * wfactor;
+    int maxh = MaxRGB * hfactor;
 
-void cImageLoader::toLowerCase(std::string &str) {
-    const int length = str.length();
-    for(int i=0; i < length; ++i) {
-        str[i] = std::tolower(str[i]);
+    Image imgblend(Geometry(width, height), Blend);
+    imgblend.modifyImage();
+    imgblend.type(TrueColorMatteType);
+    PixelPacket *pixels = imgblend.getPixels(0, 0, width, height);
+    for (int x = 0; x < width; x++) {
+        for (int y = 0; y < height; y++) {
+            PixelPacket *pixel = pixels + y * width + x;
+            int opacity = (maxw / width * x + maxh - maxh / height * y) / 2;
+            pixel->opacity = (opacity <= MaxRGB) ? opacity : MaxRGB;
+        }
     }
-}
+    imgblend.syncPixels();
 
-bool cImageLoader::LoadImage(cString FileName, cString Path, cString Extension) {
-    try {
-        cString File = cString::sprintf("%s%s.%s", *Path, *FileName, *Extension);
-        dsyslog("tvguide: trying to load: %s", *File);
-        buffer.read(*File);
-        dsyslog("tvguide: %s sucessfully loaded", *File);
-    } catch (...) {     
-        return false;
-    }
-    return true;
-}
+    Image imgback(Geometry(width, height), Back);
+    imgback.composite(imgblend, 0, 0, OverCompositeOp);
+
+    buffer = imgback;
+}
\ No newline at end of file
diff --git a/imageloader.h b/imageloader.h
index 23faf65..942986f 100644
--- a/imageloader.h
+++ b/imageloader.h
@@ -6,22 +6,24 @@
 #include <vdr/osd.h>
 #include <vdr/skins.h>
 #include <Magick++.h>
+#include "imagemagickwrapper.h"
 
 using namespace Magick;
  
-class cImageLoader {
+class cImageLoader  : public cImageMagickWrapper {
 public:
     cImageLoader();
     ~cImageLoader();
     cImage GetImage();
-    bool LoadLogo(const char *logo, int width, int height);
-    bool LoadEPGImage(int eventID);
+    bool LoadLogo(const cChannel *channel, int width, int height);
+    bool LoadEPGImage(int eventID, int width, int height);
+    bool LoadAdditionalEPGImage(cString name);
+    bool LoadPoster(const char *poster, int width, int height);
+    bool LoadIcon(const char *cIcon, int size);
+    bool LoadOsdElement(cString name, int width, int height);
     bool DrawBackground(tColor back, tColor blend, int width, int height);
 private:
-    Image buffer;
-    Color Argb2Color(tColor col);
-    void toLowerCase(std::string &str);
-    bool LoadImage(cString FileName, cString Path, cString Extension);
+    void CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor);
 };
 
 #endif //_TVGUIDE_IMAGELOADER_H
diff --git a/imagemagickwrapper.c b/imagemagickwrapper.c
new file mode 100644
index 0000000..753b678
--- /dev/null
+++ b/imagemagickwrapper.c
@@ -0,0 +1,162 @@
+#include <string>
+#include <sstream>
+#include "imagemagickwrapper.h"
+#include "config.h"
+#include "imagescaler.h"
+
+cImageMagickWrapper::cImageMagickWrapper() {
+    InitializeMagick(NULL);
+}
+
+cImageMagickWrapper::~cImageMagickWrapper() {
+}
+
+cImage *cImageMagickWrapper::CreateImage(int width, int height, bool preserveAspect) {
+    int w, h;
+    w = buffer.columns();
+    h = buffer.rows();
+    if ((w == 0)||(h==0))
+        return NULL;
+    if (width == 0)
+        width = w;
+    if (height == 0)
+        height = h;
+    if (preserveAspect) {
+        unsigned scale_w = 1000 * width / w;
+        unsigned scale_h = 1000 * height / h;
+        if (scale_w > scale_h)
+          width = w * height / h;
+        else
+          height = h * width / w;
+    }
+    const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
+    cImage *image = NULL;
+    image = new cImage(cSize(width, height));
+    if (!image)
+        return NULL;
+    tColor *imgData = (tColor *)image->Data();
+    if (w != width || h != height) {
+        ImageScaler scaler;
+        scaler.SetImageParameters(imgData, width, width, height, w, h);
+        for (const void *pixels_end = &pixels[w*h]; pixels < pixels_end; ++pixels)
+            scaler.PutSourcePixel(pixels->blue / ((MaxRGB + 1) / 256),
+                                  pixels->green / ((MaxRGB + 1) / 256),
+                                  pixels->red / ((MaxRGB + 1) / 256),
+                                  ~((unsigned char)(pixels->opacity / ((MaxRGB + 1) / 256))));
+        return image;
+    }
+    for (const void *pixels_end = &pixels[width*height]; pixels < pixels_end; ++pixels)
+        *imgData++ = ((~int(pixels->opacity / ((MaxRGB + 1) / 256)) << 24) |
+                      (int(pixels->green / ((MaxRGB + 1) / 256)) << 8) |
+                      (int(pixels->red / ((MaxRGB + 1) / 256)) << 16) |
+                      (int(pixels->blue / ((MaxRGB + 1) / 256)) ));
+    return image;
+}
+
+cImage cImageMagickWrapper::CreateImageCopy() {
+    int w, h;
+    w = buffer.columns();
+    h = buffer.rows();
+    cImage image (cSize(w, h));
+    const PixelPacket *pixels = buffer.getConstPixels(0, 0, w, h);
+    for (int iy = 0; iy < h; ++iy) {
+        for (int ix = 0; ix < w; ++ix) {
+            tColor col = (~int(pixels->opacity * 255 / MaxRGB) << 24)
+            | (int(pixels->green * 255 / MaxRGB) << 8)
+            | (int(pixels->red * 255 / MaxRGB) << 16)
+            | (int(pixels->blue * 255 / MaxRGB) );
+            image.SetPixel(cPoint(ix, iy), col);
+            ++pixels;
+        }
+    }
+    return image;
+}
+
+bool cImageMagickWrapper::LoadImage(std::string FileName, std::string Path, std::string Extension) {
+    try {
+        std::stringstream sstrImgFile;
+        sstrImgFile << Path << FileName << "." << Extension;
+        std::string imgFile = sstrImgFile.str();
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: trying to load: %s", imgFile.c_str());
+        buffer.read(imgFile.c_str());
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: %s sucessfully loaded", imgFile.c_str());
+    } catch( Magick::Warning &warning ) {
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: Magick Warning: %s", warning.what());
+        return true;
+    } catch( Magick::Error &error ) {
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: Magick Error: %s", error.what());
+        return false;
+    } catch(...) {
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: an unknown Magick error occured during image loading");
+        return false;
+    }
+    return true;
+}
+
+bool cImageMagickWrapper::LoadImage(const char *fullpath) {
+    if ((fullpath == NULL) || (strlen(fullpath) < 5))
+        return false;
+    try {
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: trying to load: %s", fullpath);
+        buffer.read(fullpath);
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: %s sucessfully loaded", fullpath);
+    } catch( Magick::Warning &warning ) {
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: Magick Warning: %s", warning.what());
+        return true;
+    } catch( Magick::Error &error ) {
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: Magick Error: %s", error.what());
+        return false;
+    } catch(...) {
+        if (tvguideConfig.debugImageLoading)
+            esyslog("tvguide: an unknown Magick error occured during image loading");
+        return false;
+    }
+    return true;
+}
+
+Color cImageMagickWrapper::Argb2Color(tColor col) {
+    tIndex alpha = (col & 0xFF000000) >> 24;
+    tIndex red = (col & 0x00FF0000) >> 16;
+    tIndex green = (col & 0x0000FF00) >> 8;
+    tIndex blue = (col & 0x000000FF);
+    Color color(MaxRGB*red/255, MaxRGB*green/255, MaxRGB*blue/255, MaxRGB*(0xFF-alpha)/255);
+    return color;
+}
+
+void cImageMagickWrapper::CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor) {
+    Color Back = Argb2Color(back);
+    Color Blend = Argb2Color(blend);
+    int maxw = MaxRGB * wfactor;
+    int maxh = MaxRGB * hfactor;
+
+    Image imgblend(Geometry(width, height), Blend);
+    imgblend.modifyImage();
+    imgblend.type(TrueColorMatteType);
+    PixelPacket *pixels = imgblend.getPixels(0, 0, width, height);
+    for (int x = 0; x < width; x++) {
+        for (int y = 0; y < height; y++) {
+            PixelPacket *pixel = pixels + y * width + x;
+            int opacity = (maxw / width * x + maxh - maxh / height * y) / 2;
+            pixel->opacity = (opacity <= MaxRGB) ? opacity : MaxRGB;
+        }
+    }
+    imgblend.syncPixels();
+
+    Image imgback(Geometry(width, height), Back);
+    imgback.composite(imgblend, 0, 0, OverCompositeOp);
+
+    buffer = imgback;
+}
+
+void cImageMagickWrapper::CreateBackground(tColor back, tColor blend, int width, int height) {
+    CreateGradient(back, blend, width, height, 0.8, 0.8);
+}
\ No newline at end of file
diff --git a/imagemagickwrapper.h b/imagemagickwrapper.h
new file mode 100644
index 0000000..eafb69a
--- /dev/null
+++ b/imagemagickwrapper.h
@@ -0,0 +1,27 @@
+#ifndef __TVGUIDE_IMAGEMAGICKWRAPPER_H
+#define __TVGUIDE_IMAGEMAGICKWRAPPER_H
+
+#define X_DISPLAY_MISSING
+
+#include <Magick++.h>
+#include <vdr/osd.h>
+
+using namespace Magick;
+
+class cImageMagickWrapper {
+private:
+    void CreateGradient(tColor back, tColor blend, int width, int height, double wfactor, double hfactor);
+public:
+    cImageMagickWrapper();
+    ~cImageMagickWrapper();
+protected:
+    Image buffer;
+    Color Argb2Color(tColor col);
+    cImage *CreateImage(int width, int height, bool preserveAspect = true);
+    cImage CreateImageCopy(void);
+    bool LoadImage(std::string FileName, std::string Path, std::string Extension);
+    bool LoadImage(const char *fullpath);
+    void CreateBackground(tColor back, tColor blend, int width, int height);
+};
+
+#endif //__TVGUIDE_IMAGEMAGICKWRAPPER_H
diff --git a/imagescaler.c b/imagescaler.c
new file mode 100644
index 0000000..cebe912
--- /dev/null
+++ b/imagescaler.c
@@ -0,0 +1,149 @@
+
+#include "imagescaler.h"
+
+#include <cstdlib>
+#include <cmath>
+
+ImageScaler::ImageScaler() :
+	m_memory(NULL),
+	m_hor_filters(NULL),
+	m_ver_filters(NULL),
+	m_buffer(NULL),
+	m_dst_image(NULL),
+	m_dst_stride(0),
+	m_dst_width(0),
+	m_dst_height(0),
+	m_src_width(0),
+	m_src_height(0),
+	m_src_x(0),
+	m_src_y(0),
+	m_dst_x(0),
+	m_dst_y(0) {
+}
+
+ImageScaler::~ImageScaler() {
+	if ( m_memory ) free( m_memory );
+}
+
+// sin(x)/(x)
+static float sincf( float x ) {
+	if ( fabsf(x) < 0.05f ) return 1.0f - (1.0f/6.0f)*x*x;  // taylor series approximation to avoid 0/0
+	return sin(x)/x;
+}
+
+static void CalculateFilters( ImageScaler::Filter *filters, int dst_size, int src_size ) {
+	const float fc = dst_size >= src_size ? 1.0f : ((float) dst_size)/((float) src_size);
+
+	for (int i = 0; i < dst_size; i++) {
+		const int    d          = 2*dst_size;                     // sample position denominator
+		const int    e          = (2*i+1) * src_size - dst_size;  // sample position enumerator
+		int          offset     =  e / d;                         // truncated sample position
+		const float  sub_offset = ((float) (e - offset*d)) / ((float) d);  // exact sample position is (float) e/d = offset + sub_offset
+
+		// calculate filter coefficients
+		float  h[4];
+		for (int j=0; j<4; j++) {
+			const float t = 3.14159265359f * (sub_offset+(1-j));
+			h[j] = sincf( fc * t ) * cosf( 0.25f * t );             // sinc-lowpass and cos-window
+		}
+
+		// ensure that filter does not reach out off image bounds:
+		while ( offset < 1 ) {
+			h[0] += h[1];
+			h[1] = h[2];
+			h[2] = h[3];
+			h[3] = 0.0f;
+			offset++;
+		}
+
+		while ( offset+3 > src_size ) {
+			h[3] += h[2];
+			h[2] = h[1];
+			h[1] = h[0];
+			h[0] = 0.0f;
+			offset--;
+		}
+
+		// coefficients are normalized to sum up to 2048
+		const float  norm = 2048.0f / ( h[0] + h[1] + h[2] + h[3] );
+
+		offset--;  // offset of fist used pixel
+
+		filters[i].m_offset = offset + 4;  // store offset of first unused pixel
+
+		for (int j=0; j<4; j++) {
+			const float t = norm * h[j];
+			filters[i].m_coeff[(offset+j) & 3] = (int) ((t > 0.0f) ?  (t+0.5f) : (t-0.5f));  // consider ring buffer index permutations
+		}
+	}
+
+	// set end marker
+	filters[dst_size].m_offset = (unsigned) -1;
+
+}
+
+void ImageScaler::SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height ) {
+	m_src_x = 0;
+	m_src_y = 0;
+	m_dst_x = 0;
+	m_dst_y = 0;
+
+	m_dst_image  = dst_image;
+	m_dst_stride = dst_stride;
+
+	// if image dimensions do not change we can keep the old filter coefficients
+	if ( (src_width == m_src_width) && (src_height == m_src_height) && (dst_width == m_dst_width) && (dst_height == m_dst_height) ) return;
+
+	m_dst_width  = dst_width;
+	m_dst_height = dst_height;
+	m_src_width  = src_width;
+	m_src_height = src_height;
+
+	if ( m_memory ) free( m_memory );
+
+	const unsigned  hor_filters_size = (m_dst_width  + 1) * sizeof(Filter);  // reserve one extra position for end marker
+	const unsigned  ver_filters_size = (m_dst_height + 1) * sizeof(Filter);
+	const unsigned  buffer_size      = 4 * m_dst_width * sizeof(TmpPixel);
+
+	char *p = (char *) malloc( hor_filters_size + ver_filters_size + buffer_size );
+
+	m_memory = p;
+
+	m_hor_filters = (Filter   *) p;  p += hor_filters_size;
+	m_ver_filters = (Filter   *) p;  p += ver_filters_size;
+	m_buffer      = (TmpPixel *) p;
+
+	CalculateFilters( m_hor_filters, m_dst_width , m_src_width  );
+	CalculateFilters( m_ver_filters, m_dst_height, m_src_height );
+}
+
+// shift range to 0..255 and clamp overflows
+static unsigned shift_clamp( int x ) {
+	x = ( x + (1<<21) ) >> 22;
+	if ( x <   0 ) return   0;
+	if ( x > 255 ) return 255;
+	return x;
+}
+
+void ImageScaler::NextSourceLine() {
+	m_dst_x = 0;
+	m_src_x = 0;
+	m_src_y++;
+
+	while ( m_ver_filters[m_dst_y].m_offset == m_src_y ) {
+		const int        h0  = m_ver_filters[m_dst_y].m_coeff[0];
+		const int        h1  = m_ver_filters[m_dst_y].m_coeff[1];
+		const int        h2  = m_ver_filters[m_dst_y].m_coeff[2];
+		const int        h3  = m_ver_filters[m_dst_y].m_coeff[3];
+		const TmpPixel  *src = m_buffer;
+		unsigned        *dst = m_dst_image + m_dst_stride * m_dst_y;
+
+		for (unsigned i=0; i<m_dst_width; i++) {
+			const ImageScaler::TmpPixel t( src[0]*h0 + src[1]*h1 + src[2]*h2 + src[3]*h3 );
+			src += 4;
+			dst[i] = shift_clamp(t[0]) | (shift_clamp(t[1])<<8) | (shift_clamp(t[2])<<16) | (shift_clamp(t[3])<<24);
+		}
+
+		m_dst_y++;
+	}
+}
diff --git a/imagescaler.h b/imagescaler.h
new file mode 100644
index 0000000..f2de6ba
--- /dev/null
+++ b/imagescaler.h
@@ -0,0 +1,97 @@
+#ifndef _ImageScaler_h
+#define _ImageScaler_h
+
+/*!
+ * this class scales images consisting of 4 components (RGBA)
+ * to an arbitrary size using a 4-tap filter
+ */
+class ImageScaler {
+public:
+
+	struct Filter {
+		unsigned  m_offset;
+		short     m_coeff[4];
+	};
+
+	ImageScaler();
+	~ImageScaler();
+
+	//! set destination image and source image size
+	void SetImageParameters( unsigned *dst_image, unsigned dst_stride, unsigned dst_width, unsigned dst_height, unsigned src_width, unsigned src_height );
+
+	/*! process one pixel of source image; destination image is written while input is processed
+	 * SetImageParameters() must be called first
+	 */
+	void PutSourcePixel( unsigned char c0, unsigned char c1, unsigned char c2, unsigned char c3 ) {
+		m_hbuf[ (m_src_x++) & 3 ].Set( c0, c1, c2, c3 );
+
+		TmpPixel      *bp = m_buffer + 4 * m_dst_x + (m_src_y & 3);
+		const Filter  *fh;
+
+		while ( (fh=m_hor_filters+m_dst_x)->m_offset == m_src_x ) {
+			*bp = m_hbuf[0]*fh->m_coeff[0] + m_hbuf[1]*fh->m_coeff[1] + m_hbuf[2]*fh->m_coeff[2] + m_hbuf[3]*fh->m_coeff[3];
+			m_dst_x++;
+			bp += 4;
+		}
+
+		if ( m_src_x == m_src_width ) NextSourceLine();
+	}
+
+private:
+
+	//! temporary image pixel class - a 4-element integer vector
+	class TmpPixel {
+	public:
+		TmpPixel() {
+		}
+
+		TmpPixel( int c0, int c1, int c2, int c3 ) {
+			Set(c0,c1,c2,c3);
+		}
+
+		void Set( int c0, int c1, int c2, int c3 ) {
+			m_comp[0] = c0;
+			m_comp[1] = c1;
+			m_comp[2] = c2;
+			m_comp[3] = c3;
+		}
+
+		TmpPixel operator*( int s ) const {
+			return TmpPixel( m_comp[0]*s, m_comp[1]*s, m_comp[2]*s, m_comp[3]*s );
+		}
+
+		TmpPixel operator+( const TmpPixel &x ) const {
+			return TmpPixel( m_comp[0] + x[0], m_comp[1] + x[1], m_comp[2] + x[2], m_comp[3] + x[3] );
+		}
+
+		// return component i=[0..3] - No range check!
+		int operator[](unsigned i) const {
+			return m_comp[i];
+		}
+
+	private:
+		int  m_comp[4];
+	};
+
+	//! this is called whenever one input line is processed completely
+	void NextSourceLine();
+
+	TmpPixel   m_hbuf[4];      //! ring buffer for 4 input pixels
+	char      *m_memory;       //! buffer container
+	Filter    *m_hor_filters;  //! buffer for horizontal filters (one for each output image column)
+	Filter    *m_ver_filters;  //! buffer for vertical   filters (one for each output image row)
+	TmpPixel  *m_buffer;       //! buffer contains 4 horizontally filtered input lines, multiplexed
+	unsigned  *m_dst_image;    //! pointer to destination image
+	unsigned   m_dst_stride;   //! destination image stride
+	unsigned   m_dst_width;    //! destination image width
+	unsigned   m_dst_height;   //! destination image height
+	unsigned   m_src_width;    //! source image width
+	unsigned   m_src_height;   //! source image height
+	unsigned   m_src_x;        //! x position of next source image pixel
+	unsigned   m_src_y;        //! y position of source image line currently beeing processed
+	unsigned   m_dst_x;        //! x position of next destination image pixel
+	unsigned   m_dst_y;        //! x position of next destination image line
+};
+
+#endif  // _ImageScaler_h
+
diff --git a/messagebox.c b/messagebox.c
deleted file mode 100644
index 3f727d4..0000000
--- a/messagebox.c
+++ /dev/null
@@ -1,114 +0,0 @@
-#include "messagebox.h"
-
-cMessageBoxThread::cMessageBoxThread(cPixmap *content, int displayTime) {
-	this->content = content;
-	FrameTime = 30; // ms
-	FadeTime = 200; // ms
-	this->displayTime = displayTime;
-}
-
-cMessageBoxThread::~cMessageBoxThread(void) {
-	Cancel(0);
-}
-
-void cMessageBoxThread::Action(void) {
-	uint64_t Start = cTimeMs::Now();
-	while (Running()) {
-		uint64_t Now = cTimeMs::Now();
-		cPixmap::Lock();
-		double t = min(double(Now - Start) / FadeTime, 1.0);
-	    int Alpha = t * ALPHA_OPAQUE;
-		if (content) {
-			content->SetAlpha(Alpha);
-			osdManager.flush();
-		}
-		cPixmap::Unlock();
-        int Delta = cTimeMs::Now() - Now;
-        if (Delta < FrameTime)
-           cCondWait::SleepMs(FrameTime - Delta);
-		if ((Now - Start) > FadeTime)
-			break;
-    }
-	cCondWait::SleepMs(displayTime - 2*FadeTime);
-	Start = cTimeMs::Now();
-	while (Running()) {
-		uint64_t Now = cTimeMs::Now();
-		cPixmap::Lock();
-		double t = min(double(Now - Start) / FadeTime, 1.0);
-	    int Alpha = (1-t) * ALPHA_OPAQUE;
-		if (content) {
-			content->SetAlpha(Alpha);
-			osdManager.flush();
-		}
-		cPixmap::Unlock();
-        int Delta = cTimeMs::Now() - Now;
-        if (Delta < FrameTime)
-           cCondWait::SleepMs(FrameTime - Delta);
-		if ((Now - Start) > FadeTime)
-			break;
-    }
-	osdManager.flush();
-}
-
-//--cMessageBox-------------------------------------------------------------
-cMutex cMessageBox::mutex;
-cMessageBoxThread *cMessageBox::msgboxThread = NULL;
-cPixmap *cMessageBox::content = NULL;
-
-bool cMessageBox::Start(int displayTime, cString msg) {
-	cMutexLock MutexLock(&mutex);
-	int width = (tvguideConfig.osdWidth - 600)/2;
-	if (!content) {
-		int height = 400;
-		content = osdManager.requestPixmap(5, cRect((tvguideConfig.osdWidth - width)/2, 
-													(tvguideConfig.osdHeight- height)/2, 
-													width, height), 
-													cRect::Null, "msgbox");
-	}
-	if (msgboxThread) {
-		delete msgboxThread;
-		msgboxThread = NULL;
-	}
-	if (!msgboxThread) {
-		msgboxThread = new cMessageBoxThread(content, displayTime);
-		cTextWrapper message;
-		message.Set(msg, tvguideConfig.FontMessageBox, width - 40);
-		int textHeight = tvguideConfig.FontMessageBox->Height();
-		int textLines = message.Lines();
-		int height = textLines * (textHeight+20);
-		cPixmap::Lock();
-		content->SetViewPort(cRect((tvguideConfig.osdWidth - width)/2,(tvguideConfig.osdHeight- height)/2, width, height));
-		content->SetAlpha(0);
-		content->Fill(theme.Color(clrBorder));
-		content->DrawRectangle(cRect(2,2,width-4, height-4), theme.Color(clrBackground));
-		int textWidth = 0;
-		for (int i=0; i<textLines; i++) {
-			textWidth = tvguideConfig.FontMessageBox->Width(message.GetLine(i));
-			content->DrawText(cPoint((width - textWidth)/2, 20 + i*textHeight), message.GetLine(i), theme.Color(clrFont), clrTransparent, tvguideConfig.FontMessageBox);
-		}
-		cPixmap::Unlock();
-		msgboxThread->Start();
-        return true;
-	}
-	return false;
-}
-
-void cMessageBox::Stop(void) {
-	cMutexLock MutexLock(&mutex);
-	if (msgboxThread) {
-		delete msgboxThread;
-		msgboxThread = NULL;
-	}
-}
-
-void cMessageBox::Destroy(void) {
-	cMutexLock MutexLock(&mutex);
-	if (msgboxThread) {
-		delete msgboxThread;
-		msgboxThread = NULL;
-	}
-	if (content) {
-		osdManager.releasePixmap(content, "msgboxDestroy");
-		content = NULL;
-	}
-}
diff --git a/messagebox.h b/messagebox.h
deleted file mode 100644
index 8b9ab23..0000000
--- a/messagebox.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __TVGUIDE_MESSAGEBOX_H
-#define __TVGUIDE_MESSAGEBOX_H
-
-class cMessageBoxThreadPool;
-
-// --- cMessageBox  -------------------------------------------------------------
-
-class cMessageBoxThread : public cThread {
-private:
-	cPixmap *content;
-	int FadeTime;
-	int FrameTime;
-	int displayTime;
-	virtual void Action(void);
-public:
-	cMessageBoxThread(cPixmap *content, int displayTime);
-	virtual ~cMessageBoxThread(void);
-};
-
-class cMessageBox {
-private:
-	static cMutex mutex;
-	static cMessageBoxThread *msgboxThread;
-	static cPixmap *content;
-public:
-	static bool Start(int displayTime, cString msg);
-	static void Stop(void);
-	static void Destroy(void);
-};
-
-#endif //__TVGUIDE_MESSAGEBOX_H
\ No newline at end of file
diff --git a/osdmanager.c b/osdmanager.c
index fb0ec6e..eefedf4 100644
--- a/osdmanager.c
+++ b/osdmanager.c
@@ -1,52 +1,38 @@
-#ifndef __TVGUIDE_OSDMANAGER_H
-#define __TVGUIDE_OSDMANAGER_H
-
-class cOsdManager {
-	private:
-		cOsd *osd;
-		int activePixmaps;
-	public:
-		cOsdManager(void);
-		bool setOsd();
-		void setBackground();
-		void flush() {osd->Flush();};
-		cPixmap *requestPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null, const char *caller = "anonymous");
-		void releasePixmap(cPixmap *pixmap, const char *caller = "anonymous");
-		void deleteOsd() {delete osd;};
-		int Width() { return osd->Width(); };
-		int Height() { return osd->Height(); };
-};
-
-#endif //__TVGUIDE_OSDMANAGER_H
+#include "config.h"
+#include "osdmanager.h"
 
 cOsdManager::cOsdManager(void) {
-	activePixmaps = 0;
 }
 
 bool cOsdManager::setOsd() {
-	osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
-	if (osd) {
-		tArea Area = { 0, 0, cOsd::OsdWidth(), cOsd::OsdHeight(),  32 };
-		if (osd->SetAreas(&Area, 1) == oeOk) {	
-			return true;
-		}
-	}
-	return false;
+    osd = cOsdProvider::NewOsd(cOsd::OsdLeft(), cOsd::OsdTop());
+    if (osd) {
+        tArea Area = { 0, 0, cOsd::OsdWidth(), cOsd::OsdHeight(),  32 };
+        if (osd->SetAreas(&Area, 1) == oeOk) {  
+            return true;
+        }
+    }
+    return false;
 }
 
 void cOsdManager::setBackground() {
-	osd->DrawRectangle(0, 0, cOsd::OsdWidth(), cOsd::OsdHeight(), theme.Color(clrBackgroundOSD));
+    
+    if (tvguideConfig.displayStatusHeader && tvguideConfig.scaleVideo) {
+        int widthStatus = cOsd::OsdWidth() - geoManager.statusHeaderHeight * 16 / 9;
+        osd->DrawRectangle(0, 0, widthStatus, geoManager.statusHeaderHeight, theme.Color(clrBackgroundOSD));
+        osd->DrawRectangle(0, geoManager.statusHeaderHeight, Width(), Height(), theme.Color(clrBackgroundOSD));    
+    }
+    else
+        osd->DrawRectangle(0, 0, Width(), Height(), theme.Color(clrBackgroundOSD));
+    
+}
+
+cPixmap *cOsdManager::requestPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort) {
+    return osd->CreatePixmap(Layer, ViewPort, DrawPort);
 }
-cPixmap *cOsdManager::requestPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort, const char *caller) {
-	if (activePixmaps >= 64)
-		return NULL;
-	activePixmaps++;
-	//esyslog("tvguide: Pixmap angefordert von %s, verwendet: %d", caller, activePixmaps);
-	return osd->CreatePixmap(Layer, ViewPort, DrawPort);
-	}
 
-void cOsdManager::releasePixmap(cPixmap *pixmap, const char *caller) {
-	activePixmaps--;
-	//esyslog("tvguide: Pixmap geloescht von %s, verwendet: %d", caller, activePixmaps);	
-	osd->DestroyPixmap(pixmap);
+void cOsdManager::releasePixmap(cPixmap *pixmap) {
+    if (!pixmap)
+        return;
+    osd->DestroyPixmap(pixmap);
 }
\ No newline at end of file
diff --git a/osdmanager.h b/osdmanager.h
new file mode 100644
index 0000000..a0c7936
--- /dev/null
+++ b/osdmanager.h
@@ -0,0 +1,23 @@
+#ifndef __TVGUIDE_OSDMANAGER_H
+#define __TVGUIDE_OSDMANAGER_H
+
+#include <vdr/osd.h>
+
+class cOsdManager {
+    private:
+        cOsd *osd;
+    public:
+        cOsdManager(void);
+        bool setOsd();
+        void setBackground();
+        void flush() {osd->Flush();};
+        cPixmap *requestPixmap(int Layer, const cRect &ViewPort, const cRect &DrawPort = cRect::Null);
+        void releasePixmap(cPixmap *pixmap);
+        void deleteOsd() {delete osd;};
+        int Width() { return osd->Width(); };
+        int Height() { return osd->Height(); };
+        int Top() { return osd->Top(); };
+        int Left() { return osd->Left(); };
+};
+
+#endif //__TVGUIDE_OSDMANAGER_H
diff --git a/po/ca_ES.po b/po/ca_ES.po
new file mode 100644
index 0000000..6f8c6fb
--- /dev/null
+++ b/po/ca_ES.po
@@ -0,0 +1,958 @@
+# VDR plugin language source file.
+msgid ""
+msgstr ""
+"Project-Id-Version: vdr-tvguide 0.0.1\n"
+"Report-Msgid-Bugs-To: <see README>\n"
+"POT-Creation-Date: 2014-05-10 17:24+0200\n"
+"PO-Revision-Date: 2013-09-21 17:49+0200\n"
+"Last-Translator: My friend <Sampep> Thanks David <Gabychan> <gbonich at gmail.com>\n"
+"Language-Team: \n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Catala\n"
+"X-Poedit-Country: Catalunya\n"
+"X-Poedit-SourceCharset: utf-8\n"
+
+msgid "Main Program"
+msgstr "Programa principal"
+
+msgid "Channel"
+msgstr "Canal"
+
+msgid "min"
+msgstr "min"
+
+msgid "Reruns of "
+msgstr ""
+
+msgid "No reruns found"
+msgstr ""
+
+msgid "No EPG Information available"
+msgstr "No hi ha informació EPG"
+
+msgid "Search & Rec"
+msgstr "Cerca & Enregistra"
+
+msgid "Channels back"
+msgstr "Canals enrere"
+
+msgid "Channels forward"
+msgstr "Canals endavant"
+
+msgid "Switch to Channel"
+msgstr "Canvia al canal"
+
+msgid "Detailed EPG"
+msgstr "EPG Detallat"
+
+msgid "Close detailed EPG"
+msgstr ""
+
+msgid "Favorites"
+msgstr ""
+
+msgid "images"
+msgstr ""
+
+msgid "root video folder"
+msgstr "Directori principal per a vídeo"
+
+msgid "Transp."
+msgstr "Transp."
+
+msgid "Timer Conflict"
+msgstr "Temporitzador en conflicte"
+
+msgid "all Channels"
+msgstr "tots els canals"
+
+msgid "unknown channel"
+msgstr "canal desconegut"
+
+msgid "Duration"
+msgstr "Durada"
+
+msgid "recorded at"
+msgstr "enregistrat a"
+
+msgid "from"
+msgstr "des de"
+
+msgid "Timers for"
+msgstr ""
+
+msgid "Rec"
+msgstr ""
+
+msgid "No Timers active"
+msgstr ""
+
+msgid "inactive"
+msgstr ""
+
+msgid "active timers"
+msgstr ""
+
+msgid "recordings done"
+msgstr ""
+
+msgid "What's on now"
+msgstr ""
+
+msgid "What's on next"
+msgstr ""
+
+msgid "Instant Record"
+msgstr "Enregistra a l'instant"
+
+msgid "Delete Timer"
+msgstr "Esborra temporitzador"
+
+msgid "Edit Timer"
+msgstr "Edita temporitzador"
+
+msgid "Timer Timeline"
+msgstr ""
+
+msgid "Create Search Timer"
+msgstr "Cerca temporitzadors"
+
+msgid "Search Timers"
+msgstr ""
+
+msgid "Create Series Timer"
+msgstr "Programa enregistrament de Sèries"
+
+msgid "Create Switch Timer"
+msgstr "Canvia temporitzadors"
+
+msgid "Delete Switch Timer"
+msgstr "Esborra canvis de temporitzadors"
+
+msgid "Search"
+msgstr "Cerca"
+
+msgid "Check for Timer Conflicts"
+msgstr "Comprova conflictes de temporitzadors"
+
+msgid "Search in Recordings"
+msgstr "Cerca a les gravacions"
+
+msgid "Set Folder for"
+msgstr "Programa carpeta per"
+
+msgid "Timer created"
+msgstr "Temporitzador creat"
+
+msgid "Timer NOT created"
+msgstr "Temporitzador NO creat"
+
+msgid "OK"
+msgstr "OK"
+
+msgid "Timer deleted"
+msgstr "Temporitzador esborrat"
+
+msgid "Timer"
+msgstr "Temporitzador"
+
+msgid "still recording - really delete?"
+msgstr "gravació en curs - segur que vols esborrar-la?"
+
+msgid "Yes"
+msgstr "Sí"
+
+msgid "No"
+msgstr "No"
+
+msgid "One"
+msgstr "Un"
+
+msgid "detected"
+msgstr "detectat"
+
+msgid "Timer Conflicts"
+msgstr "Conflicte al temporitzador"
+
+msgid "Show conflict"
+msgstr "Mostra conflicte"
+
+msgid "timers involved"
+msgstr "temporitzadors involucrats"
+
+msgid "Ignore Conflicts"
+msgstr "Ignora conflictes"
+
+msgid "Ignore Conflict"
+msgstr "Ignora conflicte"
+
+msgid "No Timer Conflicts found"
+msgstr "No s'han trobat conflictes"
+
+msgid "Close"
+msgstr "Tanca"
+
+msgid "reruns for"
+msgstr ""
+
+msgid "rerun for"
+msgstr ""
+
+msgid "found"
+msgstr ""
+
+msgid "Ignore reruns"
+msgstr ""
+
+msgid "No reruns found for Event"
+msgstr ""
+
+msgid "Timer for"
+msgstr ""
+
+msgid "replaced by rerun"
+msgstr ""
+
+msgid "Timer Active"
+msgstr "Temporitzador actiu"
+
+msgid "Priority"
+msgstr "Prioritat"
+
+msgid "Lifetime"
+msgstr "Temps restant"
+
+msgid "Day"
+msgstr "dia"
+
+msgid "Timer start time"
+msgstr "Inici temporitzador"
+
+msgid "Timer stop time"
+msgstr "Final temporitzador"
+
+msgid "Timer File"
+msgstr ""
+
+msgid "New Folder"
+msgstr ""
+
+msgid "Save"
+msgstr "Desa"
+
+msgid "Cancel"
+msgstr "Cancel·la"
+
+msgid "Create Series Timer based on"
+msgstr "Programa enregistrament de Sèries segons"
+
+msgid "Series Timer start time"
+msgstr "Inici temporitzador Sèries"
+
+msgid "Series Timer stop time"
+msgstr "Final temporitzador Sèries"
+
+msgid "Days to record"
+msgstr "Dies a enregistrar"
+
+msgid "Day to start"
+msgstr "Dia d'inici"
+
+msgid "Create Timer"
+msgstr "Crea temporitzador"
+
+msgid "Series Timer created"
+msgstr "Sèrie programada"
+
+msgid "Start"
+msgstr "Inici"
+
+msgid "Stop"
+msgstr "Final"
+
+msgid "Configure Search Timer based on"
+msgstr "Configura cerca de temporitzadors segons"
+
+msgid "Search Expression:"
+msgstr "Cerca expressió:"
+
+msgid "Continue"
+msgstr "Continua"
+
+msgid "Configure Search Timer for Search String"
+msgstr "Configura cerca de temporitzadors amb text"
+
+msgid "Manually configure Options"
+msgstr "Opcions de configuració manual"
+
+msgid "Use Template"
+msgstr "Utilitza plantilla"
+
+msgid "EPGSearch Search Timers"
+msgstr ""
+
+msgid "No Search Timers Configured"
+msgstr ""
+
+msgid "Configure Search Timer Options"
+msgstr ""
+
+msgid "Save Search Timer"
+msgstr ""
+
+msgid "Search String"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Search Mode"
+msgstr "Mode de cerca"
+
+msgid "Use Title"
+msgstr "Utilitza títol"
+
+msgid "Use Subtitle"
+msgstr "Utilitza subtítol"
+
+msgid "Use Description"
+msgstr "Utilitza descripció"
+
+msgid "Limit Channels"
+msgstr "Canals restringits"
+
+msgid "Use Time"
+msgstr "Utilitza temps"
+
+msgid "Display advanced Options"
+msgstr ""
+
+msgid "Limit Days of the Week"
+msgstr ""
+
+msgid "Time margin for start in minutes"
+msgstr ""
+
+msgid "Time margin for stop in minutes"
+msgstr ""
+
+msgid "Series Recording"
+msgstr ""
+
+msgid "Folder"
+msgstr ""
+
+msgid "Use VPS"
+msgstr ""
+
+msgid "Avoid Repeats"
+msgstr ""
+
+msgid "Use in Favorites"
+msgstr ""
+
+msgid "Hide advanced Options"
+msgstr ""
+
+msgid "Display Results for Search Timer"
+msgstr "Mostra resultats de la cerca"
+
+msgid "Start Channel"
+msgstr "Inicia canal"
+
+msgid "Stop Channel"
+msgstr "Atura canal"
+
+msgid "Start after"
+msgstr "Comença després"
+
+msgid "Start before"
+msgstr "Comença abans"
+
+msgid "Select Days"
+msgstr ""
+
+msgid "Number of allowed repeats"
+msgstr ""
+
+msgid "Compare Title"
+msgstr ""
+
+msgid "Compare Subtitle"
+msgstr ""
+
+msgid "Compare Description"
+msgstr ""
+
+msgid "Really delete Search Timer"
+msgstr ""
+
+msgid "Delete only Search Timer"
+msgstr ""
+
+msgid "Delete Search Timer and created Timers"
+msgstr ""
+
+msgid "Search Timer sucessfully created."
+msgstr "S'ha creat cerca de temporitzador"
+
+msgid "Search Timer update initialised"
+msgstr "Actualització de temporitzador iniciada"
+
+msgid "Search Timer NOT sucessfully created"
+msgstr "No s'ha creat cerca de temporitzador"
+
+msgid "Creating Search Timer"
+msgstr "Creant cerca de temporitzador"
+
+msgid "Search Term"
+msgstr "Cercant terme"
+
+msgid "Using Template"
+msgstr "Utilitzant plantilla"
+
+msgid "Use other Template"
+msgstr "Utilitza una altra plantilla"
+
+msgid "search results for Favorite"
+msgstr ""
+
+msgid "search result for Favorite"
+msgstr ""
+
+msgid "search results for Search Timer"
+msgstr "cerca resultats per temporitzador"
+
+msgid "search result for Search Timer"
+msgstr "cerca resultat per temporitzador"
+
+msgid "Nothing found for Search String"
+msgstr "No s'ha trobat la cadena de text"
+
+msgid "Configure Options for Switchtimer"
+msgstr "Opcions de configuració de canvi de temporitzador"
+
+msgid "Minutes before switching"
+msgstr "Minuts abans del canvi"
+
+msgid "switch"
+msgstr "canvia"
+
+msgid "announce only"
+msgstr "només anunci"
+
+msgid "ask for switch"
+msgstr "pregunta pel canvi"
+
+msgid "Switch Mode"
+msgstr "Mode de canvi"
+
+msgid "Create"
+msgstr "Crea"
+
+msgid "Switch Timer sucessfully created"
+msgstr "Canvi de temporitzador creat"
+
+msgid "Switch Timer NOT sucessfully created"
+msgstr "No s'ha creat el canvi de temporitzador"
+
+msgid "Switch Timer deleted"
+msgstr "Canvi de temporitzador esborrat"
+
+msgid "Channel to Search"
+msgstr "Canal a cercar"
+
+msgid "Search in title"
+msgstr "Cerca al títol"
+
+msgid "Search in Subtitle"
+msgstr "Cerca al subtítol"
+
+msgid "Search in Description"
+msgstr "Cerca a la descripció"
+
+msgid "Show Search Options"
+msgstr "Mostra opcions de cerca"
+
+msgid "Perform Search"
+msgstr "Realitza la cerca"
+
+msgid "search results for"
+msgstr "resultats de cerca per"
+
+msgid "search result for"
+msgstr "resultat de cerca per"
+
+msgid "Adapt Search"
+msgstr "Cerca adaptada"
+
+msgid "Search String has to have at least three letters"
+msgstr ""
+
+msgid "Found"
+msgstr "Trobada"
+
+msgid "recording"
+msgstr "gravació"
+
+msgid "recordings"
+msgstr "gravacions"
+
+msgid "for"
+msgstr "per"
+
+msgid "No recordings found for"
+msgstr "No s'han trobat gravacions per"
+
+msgid "No Favorites available"
+msgstr ""
+
+msgid "whole term must appear"
+msgstr "expressió completa"
+
+msgid "all terms must exist"
+msgstr "totes les paraules"
+
+msgid "one term must exist"
+msgstr "alguna paraula"
+
+msgid "exact match"
+msgstr "coincidència exacta"
+
+msgid "regular expression"
+msgstr "expressió regular"
+
+msgid "General Settings"
+msgstr "Preferències"
+
+msgid "Screen Presentation"
+msgstr "Presentació de pantalla"
+
+msgid "Fonts and Fontsizes"
+msgstr "Tipus i mida de lletra"
+
+msgid "Recording Menus and Favorites"
+msgstr ""
+
+msgid "Image Loading and Caching"
+msgstr ""
+
+msgid "x channels back / forward"
+msgstr "x canals enrere / endavant"
+
+msgid "previous / next channel group"
+msgstr "anterior / següent grup de canals"
+
+msgid "Blue: Channel Switch, Ok: Detailed EPG"
+msgstr "Blau: Canvi de canal, OK: EPG detallat"
+
+msgid "Blue: Detailed EPG, Ok: Channel Switch"
+msgstr "Blau: EPG detallat, OK: Canvi de canal"
+
+msgid "Blue: Favorites / Switch, Ok: Detailed EPG"
+msgstr ""
+
+msgid "Timely Jump"
+msgstr ""
+
+msgid "Jump to specific channel"
+msgstr ""
+
+msgid "never"
+msgstr "mai"
+
+msgid "if exists"
+msgstr "si existeix"
+
+msgid "always"
+msgstr "sempre"
+
+msgid "Show Main Menu Entry"
+msgstr "Mostra entrada del menú principal"
+
+msgid "Replace VDR Schedules Menu"
+msgstr "Canvia el menú Programació VDR"
+
+msgid "Use appropriate nOpacity Theme"
+msgstr ""
+
+msgid "Theme"
+msgstr "Plantilla"
+
+msgid "Time to display in minutes"
+msgstr "Temps a mostrar en minuts"
+
+msgid "Rounded Corners"
+msgstr "Cantells rodons"
+
+msgid "Channel Jump Mode (Keys Green / Yellow)"
+msgstr "Mode de salt de canal (Botons Verd / Groc)"
+
+msgid "Keys Blue and OK"
+msgstr "Botons Blau i OK"
+
+msgid "Close TVGuide after channel switch"
+msgstr "Tanca GuiaTV després del canvi de canal"
+
+msgid "Functionality of numeric Keys"
+msgstr ""
+
+msgid "Hide last Channel Group"
+msgstr "Amaga el darrer grup de canals"
+
+msgid "Big Step (Keys 1 / 3) in hours"
+msgstr "Salt (Botons 1 / 3) en hores"
+
+msgid "Huge Step (Keys 4 / 6) in hours"
+msgstr "Salt (Botons 4 / 6) en hores"
+
+msgid "Time Format (12h/24h)"
+msgstr "Format de temps (12h/24h)"
+
+msgid "EPG Window Text Scrolling Speed"
+msgstr ""
+
+msgid "Display Reruns in detailed EPG View"
+msgstr "Mostre reemissions a l'EPG detallat"
+
+msgid "Number of reruns to display"
+msgstr "Nombre de reemissions a mostrar"
+
+msgid "Use Subtitle for reruns"
+msgstr "Utilitza subtítol per reemissions"
+
+msgid "Display Mode"
+msgstr "Mode de visualització"
+
+msgid "Height of Channel Header (Perc. of osd height)"
+msgstr "Alçada de la capçalera del Canal (% alçada OSD)"
+
+msgid "Width of Timeline (Perc. of osd width)"
+msgstr "Amplada cronologia (% amplada OSD)"
+
+msgid "Number of Channels to display"
+msgstr "Nombre de Canals a mostrar"
+
+msgid "Width of Channel Header (Perc. of osd width)"
+msgstr "Amplada de la capçalera del Canal (% amplada OSD)"
+
+msgid "Height of Timeline (Perc. of osd height)"
+msgstr "Alçada cronologia (% alçada OSD)"
+
+msgid "Display time in EPG Grids"
+msgstr "Mostra el temps a l'EPG"
+
+msgid "Height of Headers (Status Header and EPG View, Perc. of osd height)"
+msgstr ""
+
+msgid "Height of Footer (Perc. of osd height)"
+msgstr ""
+
+msgid "Display status header"
+msgstr "Mostra capçalera d'estat"
+
+msgid "Scale video to upper right corner"
+msgstr "Escala de vídeo a cantonada superior dreta"
+
+msgid "Rounded corners around video frame"
+msgstr "Cantells rodons als fotogrames de vídeo"
+
+msgid "Display Channel Names in Header"
+msgstr "Mostra nom del canal a la capçalera"
+
+msgid "Display channel groups"
+msgstr "Mostra grups de canals"
+
+msgid "Height of channel groups (Perc. of osd height)"
+msgstr "Alçada dels grups de canals (% alçada OSD)"
+
+msgid "Width of channel groups (Perc. of osd width)"
+msgstr "Amplada dels grups de canals (% amplada OSD)"
+
+msgid "Display current time baseline"
+msgstr ""
+
+msgid "Show Channel Logos"
+msgstr "Mosta Logotip del canal"
+
+msgid "Logo Path used"
+msgstr "Origen logotip utilitzat"
+
+msgid "Logo Extension"
+msgstr "Extensió del Logotip"
+
+msgid "Logo width ratio"
+msgstr "Proporció amplada logotip"
+
+msgid "Logo height ratio"
+msgstr "Proporció alçada logotip"
+
+msgid "Text Border in Detailed View (pixel)"
+msgstr ""
+
+msgid "Show EPG Images"
+msgstr "Mostra imatges EPG"
+
+msgid "EPG Images Path used"
+msgstr "Origen imatges EPG utilitzades"
+
+msgid "EPG Image width"
+msgstr "Amplada imatge EPG"
+
+msgid "EPG Image height"
+msgstr "Alçada imatge EPG"
+
+msgid "Number of additional EPG Images"
+msgstr "Nombre addicional d'imatges EPG"
+
+msgid "Additional EPG Image width"
+msgstr "Amplada imatge addicional EPG"
+
+msgid "Additional EPG Image height"
+msgstr "Alçada imatge addicional EPG"
+
+msgid "Font"
+msgstr "Font"
+
+msgid "Status Header Font Size"
+msgstr "Mida de la Font - capçalera d'estat"
+
+msgid "Status Header Large Font Size"
+msgstr "Mida de la Font gran - capçalera d'estat"
+
+msgid "Detail EPG View Font Size"
+msgstr "Mida de la Font - EPG detallat"
+
+msgid "Detail EPG View Header Font Size"
+msgstr "Mida de la Font - capçalera EPG detallat"
+
+msgid "Message Font Size"
+msgstr "Mida de la Font - missatges"
+
+msgid "Message Large Font Size"
+msgstr "Mida de la Font gran - missatges"
+
+msgid "Button Font Size"
+msgstr "Mida de la Font dels botons"
+
+msgid "Channel Header Font Size"
+msgstr "Mida de la Font - capçalera canal"
+
+msgid "Channel Groups Font Size"
+msgstr "Mida de la Font - grups de canals"
+
+msgid "Grid Font Size"
+msgstr "Mida de la Font - graelles"
+
+msgid "Grid Font Small Size"
+msgstr "Mida de la Font petita - graelles"
+
+msgid "Timeline Weekday Font Size"
+msgstr "Mida de la Font - dia setmana cronologia"
+
+msgid "Timeline Date Font Size"
+msgstr "Mida de la Font - data cronologia"
+
+msgid "Timeline Time Font Size"
+msgstr "Mida de la Font - temps cronologia"
+
+msgid "Search & Recording Menu Font Size"
+msgstr "Mida de la Font - Menú Cerca & Enregistra"
+
+msgid "Search & Recording Menu Small Font Size"
+msgstr "Mida de la Font petita - Menú Cerca & Enregistra"
+
+msgid "Search & Recording Menu Header Font Size"
+msgstr ""
+
+msgid "Always use root video folder"
+msgstr ""
+
+msgid "Select from folder list"
+msgstr ""
+
+msgid "Use fixed folder"
+msgstr ""
+
+msgid "Folder for instant Recordings"
+msgstr ""
+
+msgid "Use Remotetimers"
+msgstr "Utilitza temporitzadors remots"
+
+msgid "Use \"What's on now\" in favorites"
+msgstr ""
+
+msgid "Use \"What's on next\" in favorites"
+msgstr ""
+
+msgid "Use user defined time 1 in favorites"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Use user defined time 2 in favorites"
+msgstr ""
+
+msgid "Use user defined time 3 in favorites"
+msgstr ""
+
+msgid "Use user defined time 4 in favorites"
+msgstr ""
+
+msgid "Limit channels in favorites"
+msgstr ""
+
+msgid "Create Log Messages for image loading"
+msgstr ""
+
+msgid "Limit Logo Cache"
+msgstr ""
+
+msgid "Maximal number of logos to cache"
+msgstr ""
+
+msgid "Number of  logos to cache at start"
+msgstr ""
+
+msgid "Cache Sizes"
+msgstr ""
+
+msgid "OSD Element Cache"
+msgstr ""
+
+msgid "Logo cache"
+msgstr ""
+
+msgid "EPG Grid Cache"
+msgstr ""
+
+msgid "Channel Groups Cache"
+msgstr ""
+
+msgid "Recording Menus Icon Cache"
+msgstr ""
+
+msgid "No Cast available"
+msgstr ""
+
+msgid "Cast"
+msgstr ""
+
+msgid "EPG Info"
+msgstr ""
+
+msgid "Reruns"
+msgstr ""
+
+msgid "Recording Information"
+msgstr ""
+
+msgid "Image Galery"
+msgstr ""
+
+msgid "TheTVDB Info"
+msgstr ""
+
+msgid "TheTVDB Information"
+msgstr ""
+
+msgid "Episode"
+msgstr ""
+
+msgid "Season"
+msgstr ""
+
+msgid "Episode Overview"
+msgstr ""
+
+msgid "First aired"
+msgstr ""
+
+msgid "Guest Stars"
+msgstr ""
+
+msgid "TheMovieDB Rating"
+msgstr ""
+
+msgid "Series Overview"
+msgstr ""
+
+msgid "Genre"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "TheMovieDB Information"
+msgstr ""
+
+msgid "Original Title"
+msgstr ""
+
+msgid "Tagline"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "yes"
+msgstr ""
+
+msgid "no"
+msgstr ""
+
+msgid "Adult"
+msgstr ""
+
+msgid "Collection"
+msgstr ""
+
+msgid "Budget"
+msgstr ""
+
+msgid "Revenue"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Release Date"
+msgstr ""
+
+msgid "Runtime"
+msgstr ""
+
+msgid "minutes"
+msgstr ""
+
+msgid "TheMovieDB Popularity"
+msgstr ""
+
+msgid "TheMovieDB Vote Average"
+msgstr ""
+
+#~ msgid "RERUNS OF THIS SHOW"
+#~ msgstr "REEMISSIONS"
+
+#~ msgid "Actors"
+#~ msgstr "Actors"
+
+#~ msgid "Use folders for instant records"
+#~ msgstr "Utilitza carpetes per gravacions a l'instant"
+
+#~ msgid "Height of status header (Perc. of osd height)"
+#~ msgstr "Alçada capçalera d'estat (% alçada OSD)"
+
+#~ msgid "Configure Search Timer Options for Search String"
+#~ msgstr "Configura opcions de cerca de temporitzadors amb text"
diff --git a/po/de_DE.po b/po/de_DE.po
index 0a4c8ed..d2e7cdf 100755
--- a/po/de_DE.po
+++ b/po/de_DE.po
@@ -3,7 +3,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: vdr-tvguide 0.0.1\n"
 "Report-Msgid-Bugs-To: <see README>\n"
-"POT-Creation-Date: 2013-01-17 14:01+0100\n"
+"POT-Creation-Date: 2014-05-10 17:24+0200\n"
 "PO-Revision-Date: 2012-08-25 17:49+0200\n"
 "Last-Translator: Horst\n"
 "Language-Team: \n"
@@ -12,8 +12,26 @@ msgstr ""
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-msgid "Set Timer"
-msgstr "Aufnehmen"
+msgid "Main Program"
+msgstr "Hauptprogramm"
+
+msgid "Channel"
+msgstr "Kanal"
+
+msgid "min"
+msgstr "min"
+
+msgid "Reruns of "
+msgstr "Wiederholungen von "
+
+msgid "No reruns found"
+msgstr "Keine Wiederholungen gefunden"
+
+msgid "No EPG Information available"
+msgstr "Keine EPG Daten verfügbar"
+
+msgid "Search & Rec"
+msgstr "Suchen & Aufn."
 
 msgid "Channels back"
 msgstr "Kanäle zurück"
@@ -24,6 +42,486 @@ msgstr "Kanäle vor"
 msgid "Switch to Channel"
 msgstr "Umschalten"
 
+msgid "Detailed EPG"
+msgstr "Detailiertes EPG"
+
+msgid "Close detailed EPG"
+msgstr "Det. EPG schließen"
+
+msgid "Favorites"
+msgstr "Favoriten"
+
+msgid "images"
+msgstr "Bilder"
+
+msgid "root video folder"
+msgstr "Video Hauptverzeichnis"
+
+msgid "Transp."
+msgstr "Transp."
+
+msgid "Timer Conflict"
+msgstr "Timer Konflikt"
+
+msgid "all Channels"
+msgstr "alle Kanäle"
+
+msgid "unknown channel"
+msgstr "unbekannter Kanal"
+
+msgid "Duration"
+msgstr "Dauer"
+
+msgid "recorded at"
+msgstr "aufgenommen am"
+
+msgid "from"
+msgstr "von"
+
+msgid "Timers for"
+msgstr "Timer für"
+
+msgid "Rec"
+msgstr "Aufn"
+
+msgid "No Timers active"
+msgstr "Keine Timer aktiv"
+
+msgid "inactive"
+msgstr "inaktiv"
+
+msgid "active timers"
+msgstr "aktive Timer"
+
+msgid "recordings done"
+msgstr "erledigte Aufnahmen"
+
+msgid "What's on now"
+msgstr "Was läuft jetzt?"
+
+msgid "What's on next"
+msgstr "Was läuft als nächstes?"
+
+msgid "Instant Record"
+msgstr "Aufnahme"
+
+msgid "Delete Timer"
+msgstr "Timer löschen"
+
+msgid "Edit Timer"
+msgstr "Timer bearbeiten"
+
+msgid "Timer Timeline"
+msgstr "Timer Tagesübersicht"
+
+msgid "Create Search Timer"
+msgstr "Suchtimer anlegen"
+
+msgid "Search Timers"
+msgstr "Suchtimer"
+
+msgid "Create Series Timer"
+msgstr "Serientimer anlegen"
+
+msgid "Create Switch Timer"
+msgstr "Umschalttimer anlegen"
+
+msgid "Delete Switch Timer"
+msgstr "Umschalttimer löschen"
+
+msgid "Search"
+msgstr "Suchen"
+
+msgid "Check for Timer Conflicts"
+msgstr "Auf Timerkonflikte prüfen"
+
+msgid "Search in Recordings"
+msgstr "In Aufnahmen suchen"
+
+msgid "Set Folder for"
+msgstr "Verzeichnis festlegen für"
+
+msgid "Timer created"
+msgstr "Timer angelegt"
+
+msgid "Timer NOT created"
+msgstr "Timer NICHT angelegt"
+
+msgid "OK"
+msgstr "OK"
+
+msgid "Timer deleted"
+msgstr "Timer gelöscht"
+
+msgid "Timer"
+msgstr "Timer"
+
+msgid "still recording - really delete?"
+msgstr "Aufzeichnung läuft - wirklich löschen?"
+
+msgid "Yes"
+msgstr "Ja"
+
+msgid "No"
+msgstr "Nein"
+
+msgid "One"
+msgstr "Ein"
+
+msgid "detected"
+msgstr "gefunden"
+
+msgid "Timer Conflicts"
+msgstr "Timerkonflikte"
+
+msgid "Show conflict"
+msgstr "Konflikt zeigen"
+
+msgid "timers involved"
+msgstr "Timer beteiligt"
+
+msgid "Ignore Conflicts"
+msgstr "Konflikte ignorieren"
+
+msgid "Ignore Conflict"
+msgstr "Konflikt ignorieren"
+
+msgid "No Timer Conflicts found"
+msgstr "Keine Timerkonflikte gefunden"
+
+msgid "Close"
+msgstr "Schließen"
+
+msgid "reruns for"
+msgstr "Wiederholungen für"
+
+msgid "rerun for"
+msgstr "Wiederholung für"
+
+msgid "found"
+msgstr "gefunden"
+
+msgid "Ignore reruns"
+msgstr "Wiederholungen ignorieren"
+
+msgid "No reruns found for Event"
+msgstr "Keine Wiederholungen gefunden für"
+
+msgid "Timer for"
+msgstr "Timer für"
+
+msgid "replaced by rerun"
+msgstr "ersetzt durch Wiederholung"
+
+msgid "Timer Active"
+msgstr "Timer aktiv"
+
+msgid "Priority"
+msgstr "Priorität"
+
+msgid "Lifetime"
+msgstr "Lebensdauer"
+
+msgid "Day"
+msgstr "Tag"
+
+msgid "Timer start time"
+msgstr "Timer Start Zeit"
+
+msgid "Timer stop time"
+msgstr "Timer Stop Zeit"
+
+msgid "Timer File"
+msgstr "Timer Datei"
+
+msgid "New Folder"
+msgstr "Neues Verzeichnis"
+
+msgid "Save"
+msgstr "Speichern"
+
+msgid "Cancel"
+msgstr "Abbrechen"
+
+msgid "Create Series Timer based on"
+msgstr "Serientimer anlegen basierend auf"
+
+msgid "Series Timer start time"
+msgstr "Serientimer Start Zeit"
+
+msgid "Series Timer stop time"
+msgstr "Serientimer Stop Zeit"
+
+msgid "Days to record"
+msgstr "Tage"
+
+msgid "Day to start"
+msgstr "Beginnen am"
+
+msgid "Create Timer"
+msgstr "Timer anlegen"
+
+msgid "Series Timer created"
+msgstr "Serientimer angelegt"
+
+msgid "Start"
+msgstr "Start"
+
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Configure Search Timer based on"
+msgstr "Suchtimer konfigurieren basierend auf"
+
+msgid "Search Expression:"
+msgstr "Suchausdruck:"
+
+msgid "Continue"
+msgstr "Weiter"
+
+msgid "Configure Search Timer for Search String"
+msgstr "Suchtimer konfigurieren für Suchbegriff"
+
+msgid "Manually configure Options"
+msgstr "Optionen manuell konfigurieren"
+
+msgid "Use Template"
+msgstr "Template benutzen"
+
+msgid "EPGSearch Search Timers"
+msgstr "EPGSearch Suchtimer"
+
+msgid "No Search Timers Configured"
+msgstr "Keine Suchtimer angelegt"
+
+msgid "Configure Search Timer Options"
+msgstr "Suchtimer konfigurieren"
+
+msgid "Save Search Timer"
+msgstr "Suchtimer speichern"
+
+msgid "Search String"
+msgstr "Suchbegriff"
+
+msgid "Active"
+msgstr "Aktiv"
+
+msgid "Search Mode"
+msgstr "Suchmodus"
+
+msgid "Use Title"
+msgstr "Titel benutzen"
+
+msgid "Use Subtitle"
+msgstr "Untertitel benutzen"
+
+msgid "Use Description"
+msgstr "Beschreibung benutzen"
+
+msgid "Limit Channels"
+msgstr "Kanäle einschränken"
+
+msgid "Use Time"
+msgstr "Zeit benutzen"
+
+msgid "Display advanced Options"
+msgstr "Erweiterte Optionen anzeigen"
+
+msgid "Limit Days of the Week"
+msgstr "Wochentage beschränken"
+
+msgid "Time margin for start in minutes"
+msgstr "Zeit vor Start in Minuten"
+
+msgid "Time margin for stop in minutes"
+msgstr "Zeit nach Ende in Minuten"
+
+msgid "Series Recording"
+msgstr "Serienaufnahme"
+
+msgid "Folder"
+msgstr "Verzeichnis"
+
+msgid "Use VPS"
+msgstr "VPS benutzen"
+
+msgid "Avoid Repeats"
+msgstr "Wiederholungen vermeiden"
+
+msgid "Use in Favorites"
+msgstr "Als Favorit benutzen"
+
+msgid "Hide advanced Options"
+msgstr "Erweiterte Optionen ausblenden"
+
+msgid "Display Results for Search Timer"
+msgstr "Ergebnisse für Suchtimer anzeigen"
+
+msgid "Start Channel"
+msgstr "Startkanal"
+
+msgid "Stop Channel"
+msgstr "Stopkanal"
+
+msgid "Start after"
+msgstr "Beginn nach"
+
+msgid "Start before"
+msgstr "Beginn vor"
+
+msgid "Select Days"
+msgstr "Tage bestimmen"
+
+msgid "Number of allowed repeats"
+msgstr "Anzahl erlaubter Wiederholungen"
+
+msgid "Compare Title"
+msgstr "Titel vergleichen"
+
+msgid "Compare Subtitle"
+msgstr "Untertitel vergleichen"
+
+msgid "Compare Description"
+msgstr "Beschreibung vergleichen"
+
+msgid "Really delete Search Timer"
+msgstr "Suchtimer wirklich löschen"
+
+msgid "Delete only Search Timer"
+msgstr "Nur Suchtimer löschen"
+
+msgid "Delete Search Timer and created Timers"
+msgstr "Suchtimer und erzeugte Timer löschen"
+
+msgid "Search Timer sucessfully created."
+msgstr "Suchtimer erfolgreich angelegt"
+
+msgid "Search Timer update initialised"
+msgstr "Suchtimer update initialisiert"
+
+msgid "Search Timer NOT sucessfully created"
+msgstr "Suchtimer NICHT erfolgreich angelegt"
+
+msgid "Creating Search Timer"
+msgstr "Suchtimer anlegen"
+
+msgid "Search Term"
+msgstr "Suchbegriff"
+
+msgid "Using Template"
+msgstr "Template"
+
+msgid "Use other Template"
+msgstr "Anderes Template benutzen"
+
+msgid "search results for Favorite"
+msgstr "Suchergebnisse für Favorit"
+
+msgid "search result for Favorite"
+msgstr "Suchergebnis für Favorit"
+
+msgid "search results for Search Timer"
+msgstr "Treffer für Suchtimer"
+
+msgid "search result for Search Timer"
+msgstr "Treffer für Suchtimer"
+
+msgid "Nothing found for Search String"
+msgstr "Keine Treffer für Suchbegriff"
+
+msgid "Configure Options for Switchtimer"
+msgstr "Optionen für Umschalttimer konfigurieren"
+
+msgid "Minutes before switching"
+msgstr "Minuten vor umschalten"
+
+msgid "switch"
+msgstr "umschalten"
+
+msgid "announce only"
+msgstr "nur ankündigen"
+
+msgid "ask for switch"
+msgstr "vor umschalten fragen"
+
+msgid "Switch Mode"
+msgstr "Umschaltmodus"
+
+msgid "Create"
+msgstr "Anlegen"
+
+msgid "Switch Timer sucessfully created"
+msgstr "Umschalttimer erfolgreich angelegt"
+
+msgid "Switch Timer NOT sucessfully created"
+msgstr "Umschalttimer NICHT erfolgreich angelegt"
+
+msgid "Switch Timer deleted"
+msgstr "Umschalttimer gelöscht"
+
+msgid "Channel to Search"
+msgstr "Suche auf Kanal"
+
+msgid "Search in title"
+msgstr "In Titel suchen"
+
+msgid "Search in Subtitle"
+msgstr "In Untertitel suchen"
+
+msgid "Search in Description"
+msgstr "In Beschreibung suchen"
+
+msgid "Show Search Options"
+msgstr "Suchoptionen anzeigen"
+
+msgid "Perform Search"
+msgstr "Suche ausführen"
+
+msgid "search results for"
+msgstr "Suchergebnisse für"
+
+msgid "search result for"
+msgstr "Suchergebnis für"
+
+msgid "Adapt Search"
+msgstr "Suche anpassen"
+
+msgid "Search String has to have at least three letters"
+msgstr "Suchausdruck muss mindestens drei Zeichen haben"
+
+msgid "Found"
+msgstr " "
+
+msgid "recording"
+msgstr "Aufnahme gefunden"
+
+msgid "recordings"
+msgstr "Aufnahmen gefunden"
+
+msgid "for"
+msgstr "für"
+
+msgid "No recordings found for"
+msgstr "Keine Aufnahmen gefunden für"
+
+msgid "No Favorites available"
+msgstr "Keine Favoriten verfügbar"
+
+msgid "whole term must appear"
+msgstr "vollständiger Ausdruck"
+
+msgid "all terms must exist"
+msgstr "alle Worte"
+
+msgid "one term must exist"
+msgstr "ein Wort"
+
+msgid "exact match"
+msgstr "exakt"
+
+msgid "regular expression"
+msgstr "Regulärer Ausdruck"
+
 msgid "General Settings"
 msgstr "Allgemeine Einstellungen"
 
@@ -33,14 +531,74 @@ msgstr "Anzeigeoptionen"
 msgid "Fonts and Fontsizes"
 msgstr "Schriften und Schriftgrößen"
 
-msgid "Number of Channels / Columns"
-msgstr "Anzahl der Kanäle bzw. Spalten"
+msgid "Recording Menus and Favorites"
+msgstr "Aufzeichnungsmenü und Favoriten"
+
+msgid "Image Loading and Caching"
+msgstr "Image Loading und Caching"
+
+msgid "x channels back / forward"
+msgstr "x Kanäle zurück / vor"
+
+msgid "previous / next channel group"
+msgstr "vorherige / nächste Kanalgruppe"
+
+msgid "Blue: Channel Switch, Ok: Detailed EPG"
+msgstr "Blau: Umschalten, OK: Detailiertes EPG"
+
+msgid "Blue: Detailed EPG, Ok: Channel Switch"
+msgstr "Blau: Detailiertes EPG, OK: Umschalten"
+
+msgid "Blue: Favorites / Switch, Ok: Detailed EPG"
+msgstr "Blau: Favoriten / Umschalten, OK: Det. EPG"
+
+msgid "Timely Jump"
+msgstr "Zeitsprung"
+
+msgid "Jump to specific channel"
+msgstr "Sprung zu deinem bestimmten Kanal"
+
+msgid "never"
+msgstr "nie"
+
+msgid "if exists"
+msgstr "falls vorhanden"
+
+msgid "always"
+msgstr "immer"
+
+msgid "Show Main Menu Entry"
+msgstr "Hauptmenüeintrag anzeigen"
+
+msgid "Replace VDR Schedules Menu"
+msgstr "VDR Programm Menü ersetzen"
+
+msgid "Use appropriate nOpacity Theme"
+msgstr "Entsprechendes nOpacity Theme benutzen"
+
+msgid "Theme"
+msgstr "Theme"
+
+msgid "Time to display in minutes"
+msgstr "Angezeigte Zeitspanne in Minuten"
+
+msgid "Rounded Corners"
+msgstr "Abgerundete Ecken"
+
+msgid "Channel Jump Mode (Keys Green / Yellow)"
+msgstr "Kanalsprung Modus (Tasten grün / gelb)"
+
+msgid "Keys Blue and OK"
+msgstr "Tasten Blau und OK"
 
-msgid "Channels to Jump (Keys Green / Yellow)"
-msgstr "Kanalsprung (Tasten Grün / Gelb)"
+msgid "Close TVGuide after channel switch"
+msgstr "TVGuide nach Umschalten schließen"
 
-msgid "Time to display vertically in minutes"
-msgstr "Vertikal angezeigte Zeit (in Minuten)"
+msgid "Functionality of numeric Keys"
+msgstr "Funktion der Nummerntasten"
+
+msgid "Hide last Channel Group"
+msgstr "Letzte Kanalgruppe verstecken"
 
 msgid "Big Step (Keys 1 / 3) in hours"
 msgstr "Großer Sprung (Tasten 1 / 3) in Stunden"
@@ -51,23 +609,68 @@ msgstr "Sehr großer Sprung (Tasten 4 / 6) in Stunden"
 msgid "Time Format (12h/24h)"
 msgstr "Zeitformat (12h/24h)"
 
-msgid "Theme"
-msgstr "Theme"
+msgid "EPG Window Text Scrolling Speed"
+msgstr "Text Scroll Geschwindigkeit des EPG Fensters"
 
-msgid "Use color gradients"
-msgstr "Farbverläufe verwenden"
+msgid "Display Reruns in detailed EPG View"
+msgstr "Wiederholungen in der detailierten EPG Ansicht anzeigen"
 
-msgid "Rounded Corners"
-msgstr "Abgerundete Ecken"
+msgid "Number of reruns to display"
+msgstr "Anzahl der dargestellten Wiederholungen"
+
+msgid "Use Subtitle for reruns"
+msgstr "Untertitel für Wiederholungssuche nutzen"
+
+msgid "Display Mode"
+msgstr "Anzeigemodus"
+
+msgid "Height of Channel Header (Perc. of osd height)"
+msgstr "Höhe des Kanalheaders (% der OSD Höhe)"
+
+msgid "Width of Timeline (Perc. of osd width)"
+msgstr "Breite der Zeitleiste (% der OSD Breite)"
+
+msgid "Number of Channels to display"
+msgstr "Anzahl der angezeigten Kanäle"
+
+msgid "Width of Channel Header (Perc. of osd width)"
+msgstr "Breite des Kanalheaders (% der OSD Breite)"
+
+msgid "Height of Timeline (Perc. of osd height)"
+msgstr "Höhe der Zeitleiste (% der OSD Höhe)"
+
+msgid "Display time in EPG Grids"
+msgstr "Zeit in EPG Grids anzeigen"
+
+msgid "Height of Headers (Status Header and EPG View, Perc. of osd height)"
+msgstr "Höhe der Header (Status Header und EPG View, % der OSD Höhe)"
+
+msgid "Height of Footer (Perc. of osd height)"
+msgstr "Höhe des Footers (% der OSD Höhe)"
+
+msgid "Display status header"
+msgstr "Status Header anzeigen"
 
-msgid "Width of Timeline"
-msgstr "Breite der Zeitleiste"
+msgid "Scale video to upper right corner"
+msgstr "Video in obere rechte Ecke skalieren"
 
-msgid "Height of Header"
-msgstr "Höhe des Headers"
+msgid "Rounded corners around video frame"
+msgstr "Abgerundete Ecken um Videofenster"
 
-msgid "Height of Footer"
-msgstr "Höhe des Footers"
+msgid "Display Channel Names in Header"
+msgstr "Kanalnamen im Header anzeigen"
+
+msgid "Display channel groups"
+msgstr "Kanalgruppen anzeigen"
+
+msgid "Height of channel groups (Perc. of osd height)"
+msgstr "Höhe der Kanalgruppen (% der OSD Höhe)"
+
+msgid "Width of channel groups (Perc. of osd width)"
+msgstr "Breite der Kanalgruppen (% der OSD Breite)"
+
+msgid "Display current time baseline"
+msgstr "Linie für aktuelle Uhrzeit anzeigen"
 
 msgid "Show Channel Logos"
 msgstr "Kanallogos anzeigen"
@@ -78,17 +681,20 @@ msgstr "Benutzer Pfad für Kanallogos"
 msgid "Logo Extension"
 msgstr "Logo Extension"
 
-msgid "Logo width"
-msgstr "Breite der Logos"
+msgid "Logo width ratio"
+msgstr "Logo Breitenverhältnis"
+
+msgid "Logo height ratio"
+msgstr "Logo Höhenverhältnis"
 
-msgid "Logo height"
-msgstr "Höhe der Logos"
+msgid "Text Border in Detailed View (pixel)"
+msgstr "Rand im detailierten EPG View"
 
 msgid "Show EPG Images"
 msgstr "EPG Bilder anzeigen"
 
 msgid "EPG Images Path used"
-msgstr "benutzer EPG Bilder Pfad"
+msgstr "Benutzer EPG Bilder Pfad"
 
 msgid "EPG Image width"
 msgstr "Breite der EPG Bilder"
@@ -96,12 +702,45 @@ msgstr "Breite der EPG Bilder"
 msgid "EPG Image height"
 msgstr "Höhe der EPG Bilder"
 
+msgid "Number of additional EPG Images"
+msgstr "Anzahl zusätzlicher EPG Bilder"
+
+msgid "Additional EPG Image width"
+msgstr "Breite der zus. EPG Bilder"
+
+msgid "Additional EPG Image height"
+msgstr "Höhe der zus. EPG Bilder"
+
 msgid "Font"
 msgstr "Schriftart"
 
+msgid "Status Header Font Size"
+msgstr "Status Header Schriftgröße"
+
+msgid "Status Header Large Font Size"
+msgstr "Status Header große Schriftgröße"
+
+msgid "Detail EPG View Font Size"
+msgstr "Detailierte EPG Ansicht Schriftgröße"
+
+msgid "Detail EPG View Header Font Size"
+msgstr "Detailierte EPG Ansicht Header Schriftgröße"
+
+msgid "Message Font Size"
+msgstr "Nachrichten Schriftgröße"
+
+msgid "Message Large Font Size"
+msgstr "Nachrichten große Schriftgröße"
+
+msgid "Button Font Size"
+msgstr "Button Schriftgröße"
+
 msgid "Channel Header Font Size"
 msgstr "Kanal Header Schriftgröße"
 
+msgid "Channel Groups Font Size"
+msgstr "Kanalgruppen Schriftgröße"
+
 msgid "Grid Font Size"
 msgstr "Grid Schriftgröße"
 
@@ -117,23 +756,186 @@ msgstr "Zeitleiste Datum Schriftgröße"
 msgid "Timeline Time Font Size"
 msgstr "Zeitleiste Zeit Schriftgröße"
 
-msgid "Button Font Size"
-msgstr "Button Schriftgröße"
+msgid "Search & Recording Menu Font Size"
+msgstr "Suchen & Aufnehmen Menu Schriftgröße"
 
-msgid "Detail EPG View Font Size"
-msgstr "Detailierte EPG Ansicht Schriftgröße"
+msgid "Search & Recording Menu Small Font Size"
+msgstr "Suchen & Aufnehmen Menu kleine Schriftgröße"
 
-msgid "Detail EPG View Header Font Size"
-msgstr "Detailierte EPG Ansicht Header Schriftgröße"
+msgid "Search & Recording Menu Header Font Size"
+msgstr "Suchen & Aufnehmen Menu Header Schriftgröße"
 
-msgid "Message Font Size"
-msgstr "Nachrichten Schriftgröße"
+msgid "Always use root video folder"
+msgstr "Immer root video Verzeichnis benutzen"
 
-msgid "Message Large Font Size"
-msgstr "Nachrichten große Schriftgröße"
+msgid "Select from folder list"
+msgstr "Verzeichnis aus Liste auswählen"
+
+msgid "Use fixed folder"
+msgstr "Festes Verzeichnis benutzen"
+
+msgid "Folder for instant Recordings"
+msgstr "Verzeichnis für Sofortaufnahmen"
+
+msgid "Use Remotetimers"
+msgstr "RemoteTimers benutzen"
+
+msgid "Use \"What's on now\" in favorites"
+msgstr "\"Was läuft jetzt\" in Favoriten benutzen"
+
+msgid "Use \"What's on next\" in favorites"
+msgstr "\"Was läuft als nächstes\" in Favoriten benutzen"
+
+msgid "Use user defined time 1 in favorites"
+msgstr "Benutzerdef. Zeit 1 in Favoriten benutzen"
+
+msgid "Description"
+msgstr "Beschreibung"
+
+msgid "Time"
+msgstr "Zeit"
+
+msgid "Use user defined time 2 in favorites"
+msgstr "Benutzerdef. Zeit 2 in Favoriten benutzen"
+
+msgid "Use user defined time 3 in favorites"
+msgstr "Benutzerdef. Zeit 3 in Favoriten benutzen"
+
+msgid "Use user defined time 4 in favorites"
+msgstr "Benutzerdef. Zeit 4 in Favoriten benutzen"
+
+msgid "Limit channels in favorites"
+msgstr "Kanäle in Favoriten beschränken"
+
+msgid "Create Log Messages for image loading"
+msgstr "Log Nachrichten für das Laden der Bilder erzeugen"
+
+msgid "Limit Logo Cache"
+msgstr "Logo Cash beschränken"
+
+msgid "Maximal number of logos to cache"
+msgstr "Maximale Anzahl Logos"
+
+msgid "Number of  logos to cache at start"
+msgstr "Anzahl der zu cachenden Logos beim Start"
+
+msgid "Cache Sizes"
+msgstr "Cache Größe"
+
+msgid "OSD Element Cache"
+msgstr "OSD Element Cache"
+
+msgid "Logo cache"
+msgstr "Logo Cache"
+
+msgid "EPG Grid Cache"
+msgstr "EPG Grid Cache"
+
+msgid "Channel Groups Cache"
+msgstr "Kanalgruppen Cache"
+
+msgid "Recording Menus Icon Cache"
+msgstr "Recording Menüs Icon Cache"
+
+msgid "No Cast available"
+msgstr "Keine Besetzung vorhanden"
+
+msgid "Cast"
+msgstr "Besetzung"
+
+msgid "EPG Info"
+msgstr "EPG Info"
+
+msgid "Reruns"
+msgstr "Wiederholungen"
+
+msgid "Recording Information"
+msgstr ""
+
+msgid "Image Galery"
+msgstr "Bildergalerie"
+
+msgid "TheTVDB Info"
+msgstr "TheTVDB Info"
+
+msgid "TheTVDB Information"
+msgstr "TheTVDB Information"
+
+msgid "Episode"
+msgstr "Episode"
+
+msgid "Season"
+msgstr "Staffel"
+
+msgid "Episode Overview"
+msgstr "Episodenüberblick"
+
+msgid "First aired"
+msgstr "Erstausstrahlung"
+
+msgid "Guest Stars"
+msgstr "Gast Stars"
+
+msgid "TheMovieDB Rating"
+msgstr "TheMovieDB Wertung"
+
+msgid "Series Overview"
+msgstr "Serienüberblick"
+
+msgid "Genre"
+msgstr "Genre"
+
+msgid "Network"
+msgstr "Sendeanstalt"
+
+msgid "Status"
+msgstr "Status"
+
+msgid "TheMovieDB Information"
+msgstr "TheMovieDB Information"
+
+msgid "Original Title"
+msgstr "Original Titel"
+
+msgid "Tagline"
+msgstr "Zusammenfassung"
+
+msgid "Overview"
+msgstr "Überblick"
+
+msgid "yes"
+msgstr "Ja"
+
+msgid "no"
+msgstr "Nein"
+
+msgid "Adult"
+msgstr "Nur für Erwachsene"
+
+msgid "Collection"
+msgstr "Kollektion"
+
+msgid "Budget"
+msgstr "Budget"
+
+msgid "Revenue"
+msgstr "Einnahmen"
+
+msgid "Homepage"
+msgstr "Homepage"
+
+msgid "Release Date"
+msgstr "Veröffentlicht"
+
+msgid "Runtime"
+msgstr "Laufzeit"
+
+msgid "minutes"
+msgstr "Minuten"
+
+msgid "TheMovieDB Popularity"
+msgstr "TheMovieDB Popularität"
 
-msgid "Timer not set! There is already a timer for this item."
-msgstr "Timer wurde nicht gesetzt! Es existiert bereits ein Timer für diese Sendung"
+msgid "TheMovieDB Vote Average"
+msgstr "TheMovieDB durchschnittliche Bewertung"
 
-msgid "Timer set"
-msgstr "Timer gesetzt"
diff --git a/po/ru_RU.po b/po/ru_RU.po
new file mode 100644
index 0000000..57bfa4d
--- /dev/null
+++ b/po/ru_RU.po
@@ -0,0 +1,955 @@
+# VDR plugin language source file.
+msgid ""
+msgstr ""
+"Project-Id-Version: vdr-tvguide 1.0.0\n"
+"Report-Msgid-Bugs-To: <see README>\n"
+"POT-Creation-Date: 2014-05-10 17:24+0200\n"
+"PO-Revision-Date: 2013-09-25 17:49+0400\n"
+"Last-Translator: AmiD, ilya\n"
+"Language-Team: Russia-Cherepovets(wm.amid at gmail.com)\n"
+"Language: ru\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Main Program"
+msgstr "Основная программа"
+
+msgid "Channel"
+msgstr "Канал"
+
+msgid "min"
+msgstr "мин"
+
+msgid "Reruns of "
+msgstr ""
+
+msgid "No reruns found"
+msgstr ""
+
+msgid "No EPG Information available"
+msgstr "Нет доступной EPG информации"
+
+msgid "Search & Rec"
+msgstr "Поиск & Запись"
+
+msgid "Channels back"
+msgstr "Предыдущих каналов"
+
+msgid "Channels forward"
+msgstr "Следующих каналов"
+
+msgid "Switch to Channel"
+msgstr "Переключиться"
+
+msgid "Detailed EPG"
+msgstr "Подробный EPG"
+
+msgid "Close detailed EPG"
+msgstr ""
+
+msgid "Favorites"
+msgstr ""
+
+msgid "images"
+msgstr ""
+
+msgid "root video folder"
+msgstr "Главная видео директория"
+
+msgid "Transp."
+msgstr "Трансп."
+
+msgid "Timer Conflict"
+msgstr "Таймер-конфликт"
+
+msgid "all Channels"
+msgstr "все каналы"
+
+msgid "unknown channel"
+msgstr "неизвестный канал"
+
+msgid "Duration"
+msgstr "Продолжительность"
+
+msgid "recorded at"
+msgstr "записано"
+
+msgid "from"
+msgstr "от"
+
+msgid "Timers for"
+msgstr ""
+
+msgid "Rec"
+msgstr ""
+
+msgid "No Timers active"
+msgstr ""
+
+msgid "inactive"
+msgstr ""
+
+msgid "active timers"
+msgstr ""
+
+msgid "recordings done"
+msgstr ""
+
+msgid "What's on now"
+msgstr ""
+
+msgid "What's on next"
+msgstr ""
+
+msgid "Instant Record"
+msgstr "Записать"
+
+msgid "Delete Timer"
+msgstr "Удалить таймер"
+
+msgid "Edit Timer"
+msgstr "Редактировать таймер"
+
+msgid "Timer Timeline"
+msgstr ""
+
+msgid "Create Search Timer"
+msgstr "Создать поисковый таймер"
+
+msgid "Search Timers"
+msgstr ""
+
+msgid "Create Series Timer"
+msgstr "Создать циклический таймер"
+
+msgid "Create Switch Timer"
+msgstr "Создать таймер переключения"
+
+msgid "Delete Switch Timer"
+msgstr "Удалить таймер переключения"
+
+msgid "Search"
+msgstr "Поиск"
+
+msgid "Check for Timer Conflicts"
+msgstr "Поиск таймер-конфликтов"
+
+msgid "Search in Recordings"
+msgstr "Искать в записях"
+
+msgid "Set Folder for"
+msgstr "Укажите каталог для"
+
+msgid "Timer created"
+msgstr "Таймер создан"
+
+msgid "Timer NOT created"
+msgstr "Таймер НЕ создан"
+
+msgid "OK"
+msgstr "OK"
+
+msgid "Timer deleted"
+msgstr "Таймер удален"
+
+msgid "Timer"
+msgstr "Таймер"
+
+msgid "still recording - really delete?"
+msgstr "Идет запись - уверены что хотите удалить?"
+
+msgid "Yes"
+msgstr "Да"
+
+msgid "No"
+msgstr "Нет"
+
+msgid "One"
+msgstr "Один"
+
+msgid "detected"
+msgstr "обнаружен"
+
+msgid "Timer Conflicts"
+msgstr "Таймер-конфликты"
+
+msgid "Show conflict"
+msgstr "Показать конфликты"
+
+msgid "timers involved"
+msgstr "Таймер"
+
+msgid "Ignore Conflicts"
+msgstr "Игнорировать конфликты"
+
+msgid "Ignore Conflict"
+msgstr "Игнорировать конфликт"
+
+msgid "No Timer Conflicts found"
+msgstr "Таймер-конфликты не найдены"
+
+msgid "Close"
+msgstr "Закрыть"
+
+msgid "reruns for"
+msgstr ""
+
+msgid "rerun for"
+msgstr ""
+
+msgid "found"
+msgstr ""
+
+msgid "Ignore reruns"
+msgstr ""
+
+msgid "No reruns found for Event"
+msgstr ""
+
+msgid "Timer for"
+msgstr ""
+
+msgid "replaced by rerun"
+msgstr ""
+
+msgid "Timer Active"
+msgstr "Таймер активен"
+
+msgid "Priority"
+msgstr "Приоритет"
+
+msgid "Lifetime"
+msgstr "Срок хранения (дней)"
+
+msgid "Day"
+msgstr "День"
+
+msgid "Timer start time"
+msgstr "Время c"
+
+msgid "Timer stop time"
+msgstr "Время до"
+
+msgid "Timer File"
+msgstr ""
+
+msgid "New Folder"
+msgstr ""
+
+msgid "Save"
+msgstr "Сохранить"
+
+msgid "Cancel"
+msgstr "Отменить"
+
+msgid "Create Series Timer based on"
+msgstr "Настроить циклический таймер"
+
+msgid "Series Timer start time"
+msgstr "Время с"
+
+msgid "Series Timer stop time"
+msgstr "Время до"
+
+msgid "Days to record"
+msgstr "Дни недели"
+
+msgid "Day to start"
+msgstr "Начиная с"
+
+msgid "Create Timer"
+msgstr "Создать"
+
+msgid "Series Timer created"
+msgstr "Циклический таймер создан"
+
+msgid "Start"
+msgstr "Старт"
+
+msgid "Stop"
+msgstr "Стоп"
+
+msgid "Configure Search Timer based on"
+msgstr "Настроить поисковый таймер"
+
+msgid "Search Expression:"
+msgstr "Искать выражение:"
+
+msgid "Continue"
+msgstr "Продолжить"
+
+msgid "Configure Search Timer for Search String"
+msgstr "Настройка таймера поиска по ключевым словам"
+
+msgid "Manually configure Options"
+msgstr "Ручная настройка параметров"
+
+msgid "Use Template"
+msgstr "Использовать шаблоны"
+
+msgid "EPGSearch Search Timers"
+msgstr ""
+
+msgid "No Search Timers Configured"
+msgstr ""
+
+msgid "Configure Search Timer Options"
+msgstr ""
+
+msgid "Save Search Timer"
+msgstr ""
+
+msgid "Search String"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Search Mode"
+msgstr "Режим поиска"
+
+msgid "Use Title"
+msgstr "Искать в названиях"
+
+msgid "Use Subtitle"
+msgstr "Искать в эпизодах"
+
+msgid "Use Description"
+msgstr "Искать в описаниях"
+
+msgid "Limit Channels"
+msgstr "Ограничить список каналов"
+
+msgid "Use Time"
+msgstr "Время"
+
+msgid "Display advanced Options"
+msgstr ""
+
+msgid "Limit Days of the Week"
+msgstr ""
+
+msgid "Time margin for start in minutes"
+msgstr ""
+
+msgid "Time margin for stop in minutes"
+msgstr ""
+
+msgid "Series Recording"
+msgstr ""
+
+msgid "Folder"
+msgstr ""
+
+msgid "Use VPS"
+msgstr ""
+
+msgid "Avoid Repeats"
+msgstr ""
+
+msgid "Use in Favorites"
+msgstr ""
+
+msgid "Hide advanced Options"
+msgstr ""
+
+msgid "Display Results for Search Timer"
+msgstr "Тест"
+
+msgid "Start Channel"
+msgstr "С канала"
+
+msgid "Stop Channel"
+msgstr "По канал"
+
+msgid "Start after"
+msgstr "С"
+
+msgid "Start before"
+msgstr "До"
+
+msgid "Select Days"
+msgstr ""
+
+msgid "Number of allowed repeats"
+msgstr ""
+
+msgid "Compare Title"
+msgstr ""
+
+msgid "Compare Subtitle"
+msgstr ""
+
+msgid "Compare Description"
+msgstr ""
+
+msgid "Really delete Search Timer"
+msgstr ""
+
+msgid "Delete only Search Timer"
+msgstr ""
+
+msgid "Delete Search Timer and created Timers"
+msgstr ""
+
+msgid "Search Timer sucessfully created."
+msgstr "Поисковый таймер создан"
+
+msgid "Search Timer update initialised"
+msgstr "Поисковый таймер обновляется"
+
+msgid "Search Timer NOT sucessfully created"
+msgstr "Поисковый таймер НЕ создан"
+
+msgid "Creating Search Timer"
+msgstr "Создается поисковый таймер"
+
+msgid "Search Term"
+msgstr "Ключевое слово"
+
+msgid "Using Template"
+msgstr "Использовать шаблон"
+
+msgid "Use other Template"
+msgstr "Использовать другие шаблоны"
+
+msgid "search results for Favorite"
+msgstr ""
+
+msgid "search result for Favorite"
+msgstr ""
+
+msgid "search results for Search Timer"
+msgstr "Совпадений найдено"
+
+msgid "search result for Search Timer"
+msgstr "Совпадение найдено"
+
+msgid "Nothing found for Search String"
+msgstr "Совпадений НЕ найдено"
+
+msgid "Configure Options for Switchtimer"
+msgstr "Настройка таймера переключения"
+
+msgid "Minutes before switching"
+msgstr "Минут до события"
+
+msgid "switch"
+msgstr "Переключить"
+
+msgid "announce only"
+msgstr "Только предупредить"
+
+msgid "ask for switch"
+msgstr "Спросить о переключении"
+
+msgid "Switch Mode"
+msgstr "Режим переключения"
+
+msgid "Create"
+msgstr "Создать"
+
+msgid "Switch Timer sucessfully created"
+msgstr "Таймер переключения создан"
+
+msgid "Switch Timer NOT sucessfully created"
+msgstr "Таймер переключения НЕ был создан!"
+
+msgid "Switch Timer deleted"
+msgstr "Таймер переключения удален"
+
+msgid "Channel to Search"
+msgstr "Канал для поиска"
+
+msgid "Search in title"
+msgstr "Искать в названиях"
+
+msgid "Search in Subtitle"
+msgstr "Искать в эпизодах"
+
+msgid "Search in Description"
+msgstr "Искать в описаниях"
+
+msgid "Show Search Options"
+msgstr "Показать параметры поиска"
+
+msgid "Perform Search"
+msgstr "Найти"
+
+msgid "search results for"
+msgstr "Найдено по запросу"
+
+msgid "search result for"
+msgstr "Найден по запросу"
+
+msgid "Adapt Search"
+msgstr "Изменить"
+
+msgid "Search String has to have at least three letters"
+msgstr ""
+
+msgid "Found"
+msgstr "Найдено"
+
+msgid "recording"
+msgstr "запись"
+
+msgid "recordings"
+msgstr "записей"
+
+msgid "for"
+msgstr "для"
+
+msgid "No recordings found for"
+msgstr "Не найдено записей:"
+
+msgid "No Favorites available"
+msgstr ""
+
+msgid "whole term must appear"
+msgstr "фраза"
+
+msgid "all terms must exist"
+msgstr "все слова"
+
+msgid "one term must exist"
+msgstr "хотя бы одно слово"
+
+msgid "exact match"
+msgstr "точное совпадение"
+
+msgid "regular expression"
+msgstr "регулярные выражения"
+
+msgid "General Settings"
+msgstr "Основные настройки"
+
+msgid "Screen Presentation"
+msgstr "Графические настройки"
+
+msgid "Fonts and Fontsizes"
+msgstr "Шрифты и размер шрифтов"
+
+msgid "Recording Menus and Favorites"
+msgstr ""
+
+msgid "Image Loading and Caching"
+msgstr ""
+
+msgid "x channels back / forward"
+msgstr "x Каналов Назад/Вперед"
+
+msgid "previous / next channel group"
+msgstr "Предыдущая/Следующая группа"
+
+msgid "Blue: Channel Switch, Ok: Detailed EPG"
+msgstr "Синяя: Переключить канал, OK: Подробный EPG"
+
+msgid "Blue: Detailed EPG, Ok: Channel Switch"
+msgstr "Синяя: Подробный EPG, OK: Переключить канал"
+
+msgid "Blue: Favorites / Switch, Ok: Detailed EPG"
+msgstr ""
+
+msgid "Timely Jump"
+msgstr ""
+
+msgid "Jump to specific channel"
+msgstr ""
+
+msgid "never"
+msgstr "никогда"
+
+msgid "if exists"
+msgstr "если существует"
+
+msgid "always"
+msgstr "всегда"
+
+msgid "Show Main Menu Entry"
+msgstr "Показывать пункт в главном меню"
+
+msgid "Replace VDR Schedules Menu"
+msgstr "Заменять телегид VDR"
+
+msgid "Use appropriate nOpacity Theme"
+msgstr ""
+
+msgid "Theme"
+msgstr "Тема"
+
+msgid "Time to display in minutes"
+msgstr "Время показа в минутах"
+
+msgid "Rounded Corners"
+msgstr "Закруглять углы"
+
+msgid "Channel Jump Mode (Keys Green / Yellow)"
+msgstr "Режим прокрутки каналов (Зеленая/Желтая кнопки)"
+
+msgid "Keys Blue and OK"
+msgstr "Синяя кнопка и OK"
+
+msgid "Close TVGuide after channel switch"
+msgstr "Закрывать TVGuide при переключении канала"
+
+msgid "Functionality of numeric Keys"
+msgstr ""
+
+msgid "Hide last Channel Group"
+msgstr "Скрывать последнюю группу каналов"
+
+msgid "Big Step (Keys 1 / 3) in hours"
+msgstr "Прыжок (Кнопки 1 / 3) в часах"
+
+msgid "Huge Step (Keys 4 / 6) in hours"
+msgstr "Большой прыжок (Кнопки 4 / 6) в часах"
+
+msgid "Time Format (12h/24h)"
+msgstr "Формат времени (12h/24h)"
+
+msgid "EPG Window Text Scrolling Speed"
+msgstr ""
+
+msgid "Display Reruns in detailed EPG View"
+msgstr "Показывать повторы в подробном EPG"
+
+msgid "Number of reruns to display"
+msgstr "Кол-во"
+
+msgid "Use Subtitle for reruns"
+msgstr "Показывать эпизод"
+
+msgid "Display Mode"
+msgstr "Режим отображения"
+
+msgid "Height of Channel Header (Perc. of osd height)"
+msgstr "Высота заголовка канала (% от высоты OSD)"
+
+msgid "Width of Timeline (Perc. of osd width)"
+msgstr "Ширина таймлинии (% от ширины OSD)"
+
+msgid "Number of Channels to display"
+msgstr "Кол-во отображаемых каналов"
+
+msgid "Width of Channel Header (Perc. of osd width)"
+msgstr "Ширина заголовка канала (% от ширины OSD)"
+
+msgid "Height of Timeline (Perc. of osd height)"
+msgstr "Высота таймлинии (% от высоты OSD)"
+
+msgid "Display time in EPG Grids"
+msgstr "Показывать время в сетке EPG"
+
+msgid "Height of Headers (Status Header and EPG View, Perc. of osd height)"
+msgstr ""
+
+msgid "Height of Footer (Perc. of osd height)"
+msgstr ""
+
+msgid "Display status header"
+msgstr "Показывать верхнюю панель"
+
+msgid "Scale video to upper right corner"
+msgstr "Показывать видео в правом верхнем углу"
+
+msgid "Rounded corners around video frame"
+msgstr "Скруглять углы видео рамки"
+
+msgid "Display Channel Names in Header"
+msgstr "Показывать наименования каналов в верхней панели"
+
+msgid "Display channel groups"
+msgstr "Показывать группы каналов"
+
+msgid "Height of channel groups (Perc. of osd height)"
+msgstr "Высота группы каналов (% от высоты OSD)"
+
+msgid "Width of channel groups (Perc. of osd width)"
+msgstr "Ширина группы каналов (% от ширины OSD)"
+
+msgid "Display current time baseline"
+msgstr ""
+
+msgid "Show Channel Logos"
+msgstr "Показывать логотипы каналов"
+
+msgid "Logo Path used"
+msgstr "Путь к папке с логотипами"
+
+msgid "Logo Extension"
+msgstr "Расширения файлов с логотипами"
+
+msgid "Logo width ratio"
+msgstr "Ширина логотипов"
+
+msgid "Logo height ratio"
+msgstr "Высота логотипов"
+
+msgid "Text Border in Detailed View (pixel)"
+msgstr ""
+
+msgid "Show EPG Images"
+msgstr "Показывать картинки EPG"
+
+msgid "EPG Images Path used"
+msgstr "Путь к папке с картинками EPG"
+
+msgid "EPG Image width"
+msgstr "Ширина картирок EPG (пикселей)"
+
+msgid "EPG Image height"
+msgstr "Высота картинок EPG (пикселей)"
+
+msgid "Number of additional EPG Images"
+msgstr "Кол-во дополнительных EPG картинок"
+
+msgid "Additional EPG Image width"
+msgstr "Ширина дополнительных EPG картинок"
+
+msgid "Additional EPG Image height"
+msgstr "Высота дополнительных EPG картинок"
+
+msgid "Font"
+msgstr "Шрифт"
+
+msgid "Status Header Font Size"
+msgstr "Размер шрифта в верхней панели"
+
+msgid "Status Header Large Font Size"
+msgstr "Размер крупного шрифта в верхней панели"
+
+msgid "Detail EPG View Font Size"
+msgstr "Размер шрифта подробный EPG"
+
+msgid "Detail EPG View Header Font Size"
+msgstr "Размер шрифта верхней панели меню подробный EPG"
+
+msgid "Message Font Size"
+msgstr "Размер шрифта сообщений"
+
+msgid "Message Large Font Size"
+msgstr "Размер крупного шрифта сообщений"
+
+msgid "Button Font Size"
+msgstr "Размер шрифта кнопок"
+
+msgid "Channel Header Font Size"
+msgstr "Размер шрифта названий каналов"
+
+msgid "Channel Groups Font Size"
+msgstr "Размер шрифта групп каналов"
+
+msgid "Grid Font Size"
+msgstr "Размер шрифта сетки"
+
+msgid "Grid Font Small Size"
+msgstr "Размер маленького шрифта сетки"
+
+msgid "Timeline Weekday Font Size"
+msgstr "Размер шрифта таймлинии"
+
+msgid "Timeline Date Font Size"
+msgstr "Размер шрифта даты таймлинии"
+
+msgid "Timeline Time Font Size"
+msgstr "Размер шрифта времени таймлинии"
+
+msgid "Search & Recording Menu Font Size"
+msgstr "Размер шрифта меню Поиск & Запись"
+
+msgid "Search & Recording Menu Small Font Size"
+msgstr "Размер маленького шрифта меню Поиск & Запись"
+
+msgid "Search & Recording Menu Header Font Size"
+msgstr ""
+
+msgid "Always use root video folder"
+msgstr ""
+
+msgid "Select from folder list"
+msgstr ""
+
+msgid "Use fixed folder"
+msgstr ""
+
+msgid "Folder for instant Recordings"
+msgstr ""
+
+msgid "Use Remotetimers"
+msgstr "RemoteTimers benutzen"
+
+msgid "Use \"What's on now\" in favorites"
+msgstr ""
+
+msgid "Use \"What's on next\" in favorites"
+msgstr ""
+
+msgid "Use user defined time 1 in favorites"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Use user defined time 2 in favorites"
+msgstr ""
+
+msgid "Use user defined time 3 in favorites"
+msgstr ""
+
+msgid "Use user defined time 4 in favorites"
+msgstr ""
+
+msgid "Limit channels in favorites"
+msgstr ""
+
+msgid "Create Log Messages for image loading"
+msgstr ""
+
+msgid "Limit Logo Cache"
+msgstr ""
+
+msgid "Maximal number of logos to cache"
+msgstr ""
+
+msgid "Number of  logos to cache at start"
+msgstr ""
+
+msgid "Cache Sizes"
+msgstr ""
+
+msgid "OSD Element Cache"
+msgstr ""
+
+msgid "Logo cache"
+msgstr ""
+
+msgid "EPG Grid Cache"
+msgstr ""
+
+msgid "Channel Groups Cache"
+msgstr ""
+
+msgid "Recording Menus Icon Cache"
+msgstr ""
+
+msgid "No Cast available"
+msgstr ""
+
+msgid "Cast"
+msgstr ""
+
+msgid "EPG Info"
+msgstr ""
+
+msgid "Reruns"
+msgstr ""
+
+msgid "Recording Information"
+msgstr ""
+
+msgid "Image Galery"
+msgstr ""
+
+msgid "TheTVDB Info"
+msgstr ""
+
+msgid "TheTVDB Information"
+msgstr ""
+
+msgid "Episode"
+msgstr ""
+
+msgid "Season"
+msgstr ""
+
+msgid "Episode Overview"
+msgstr ""
+
+msgid "First aired"
+msgstr ""
+
+msgid "Guest Stars"
+msgstr ""
+
+msgid "TheMovieDB Rating"
+msgstr ""
+
+msgid "Series Overview"
+msgstr ""
+
+msgid "Genre"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "TheMovieDB Information"
+msgstr ""
+
+msgid "Original Title"
+msgstr ""
+
+msgid "Tagline"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "yes"
+msgstr ""
+
+msgid "no"
+msgstr ""
+
+msgid "Adult"
+msgstr ""
+
+msgid "Collection"
+msgstr ""
+
+msgid "Budget"
+msgstr ""
+
+msgid "Revenue"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Release Date"
+msgstr ""
+
+msgid "Runtime"
+msgstr ""
+
+msgid "minutes"
+msgstr ""
+
+msgid "TheMovieDB Popularity"
+msgstr ""
+
+msgid "TheMovieDB Vote Average"
+msgstr ""
+
+#~ msgid "RERUNS OF THIS SHOW"
+#~ msgstr "ПОВТОРЫ ЭТОЙ ПЕРЕДАЧИ"
+
+#~ msgid "Actors"
+#~ msgstr "Актеры"
+
+#~ msgid "Use folders for instant records"
+#~ msgstr "Использовать директории для быстрой записи"
+
+#~ msgid "Height of status header (Perc. of osd height)"
+#~ msgstr "Высота верхней панели (% от высоты OSD)"
+
+#~ msgid "Configure Search Timer Options for Search String"
+#~ msgstr "Настроить параметры таймера"
diff --git a/po/sk_SK.po b/po/sk_SK.po
new file mode 100644
index 0000000..27cb5f8
--- /dev/null
+++ b/po/sk_SK.po
@@ -0,0 +1,955 @@
+# VDR plugin language source file.
+msgid ""
+msgstr ""
+"Project-Id-Version: vdr-tvguide 1.1.0\n"
+"Report-Msgid-Bugs-To: <see README>\n"
+"POT-Creation-Date: 2014-05-10 17:24+0200\n"
+"PO-Revision-Date: 2013-09-15 00:12+0100\n"
+"Last-Translator: Milan Hrala <hrala.milan at gmail.com>\n"
+"Language-Team: \n"
+"Language: sk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-2\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "Main Program"
+msgstr "Hlavn� program"
+
+msgid "Channel"
+msgstr "Kan�l"
+
+msgid "min"
+msgstr "min"
+
+msgid "Reruns of "
+msgstr ""
+
+msgid "No reruns found"
+msgstr ""
+
+msgid "No EPG Information available"
+msgstr "�iadne EPG �daje nie s� k dispoz�cii"
+
+msgid "Search & Rec"
+msgstr "Hlada� & Nahra�"
+
+msgid "Channels back"
+msgstr "kan�lov sp�"
+
+msgid "Channels forward"
+msgstr "kan�lov dopredu"
+
+msgid "Switch to Channel"
+msgstr "Prepn�� na kan�l"
+
+msgid "Detailed EPG"
+msgstr "Podrobn� EPG"
+
+msgid "Close detailed EPG"
+msgstr ""
+
+msgid "Favorites"
+msgstr ""
+
+msgid "images"
+msgstr ""
+
+msgid "root video folder"
+msgstr "Hlavn� video adres�r"
+
+msgid "Transp."
+msgstr "Transp."
+
+msgid "Timer Conflict"
+msgstr "Konflikt pl�nu"
+
+msgid "all Channels"
+msgstr "v�etky kan�ly"
+
+msgid "unknown channel"
+msgstr "nezn�my Kanal"
+
+msgid "Duration"
+msgstr "D�ka"
+
+msgid "recorded at"
+msgstr "Zaznamenan�"
+
+msgid "from"
+msgstr "z"
+
+msgid "Timers for"
+msgstr ""
+
+msgid "Rec"
+msgstr ""
+
+msgid "No Timers active"
+msgstr ""
+
+msgid "inactive"
+msgstr ""
+
+msgid "active timers"
+msgstr ""
+
+msgid "recordings done"
+msgstr ""
+
+msgid "What's on now"
+msgstr ""
+
+msgid "What's on next"
+msgstr ""
+
+msgid "Instant Record"
+msgstr "Okam�ite nahra�"
+
+msgid "Delete Timer"
+msgstr "Vymaza� pl�n nahr�vania"
+
+msgid "Edit Timer"
+msgstr "Upravi� pl�n nahr�vania"
+
+msgid "Timer Timeline"
+msgstr ""
+
+msgid "Create Search Timer"
+msgstr "Vytvori� vyh�ad�va� pl�nov nahr�vania"
+
+msgid "Search Timers"
+msgstr ""
+
+msgid "Create Series Timer"
+msgstr "Vytvori� s�riov� pl�n nahr�vania"
+
+msgid "Create Switch Timer"
+msgstr "Vytvori� prep�nac� pl�n"
+
+msgid "Delete Switch Timer"
+msgstr "Vymaza� prep�nac� pl�n"
+
+msgid "Search"
+msgstr "H�ada�"
+
+msgid "Check for Timer Conflicts"
+msgstr "Skontrolova� konflikty pl�nu"
+
+msgid "Search in Recordings"
+msgstr "Vyh�ada� v nahr�vkach"
+
+msgid "Set Folder for"
+msgstr "Nastavi� adres�r pre"
+
+msgid "Timer created"
+msgstr "Pl�n vytvoren�"
+
+msgid "Timer NOT created"
+msgstr "Pl�n nie je vytvoren�"
+
+msgid "OK"
+msgstr "OK"
+
+msgid "Timer deleted"
+msgstr "Pl�n vymazan�"
+
+msgid "Timer"
+msgstr "Pl�n"
+
+msgid "still recording - really delete?"
+msgstr "Pr�ve nahr�va - naozaj zmaza�?"
+
+msgid "Yes"
+msgstr "�no"
+
+msgid "No"
+msgstr "Nie"
+
+msgid "One"
+msgstr "Jeden"
+
+msgid "detected"
+msgstr "n�jden�ch"
+
+msgid "Timer Conflicts"
+msgstr "Konflikty pl�nov"
+
+msgid "Show conflict"
+msgstr "Zobrazi� konflikt"
+
+msgid "timers involved"
+msgstr "pl�ny komplikovan�"
+
+msgid "Ignore Conflicts"
+msgstr "Ignorova� konflikty"
+
+msgid "Ignore Conflict"
+msgstr "Ignorova� konflikt"
+
+msgid "No Timer Conflicts found"
+msgstr "Nena�li sa �iadne konflikty pl�nu"
+
+msgid "Close"
+msgstr "Zavrie�"
+
+msgid "reruns for"
+msgstr ""
+
+msgid "rerun for"
+msgstr ""
+
+msgid "found"
+msgstr ""
+
+msgid "Ignore reruns"
+msgstr ""
+
+msgid "No reruns found for Event"
+msgstr ""
+
+msgid "Timer for"
+msgstr ""
+
+msgid "replaced by rerun"
+msgstr ""
+
+msgid "Timer Active"
+msgstr "Pl�n akt�vny"
+
+msgid "Priority"
+msgstr "Priorita"
+
+msgid "Lifetime"
+msgstr "�ivotnos�"
+
+msgid "Day"
+msgstr "De�"
+
+msgid "Timer start time"
+msgstr "Pl�n za��na"
+
+msgid "Timer stop time"
+msgstr "Pl�n kon��"
+
+msgid "Timer File"
+msgstr ""
+
+msgid "New Folder"
+msgstr ""
+
+msgid "Save"
+msgstr "Ulo�i�"
+
+msgid "Cancel"
+msgstr "Zru�i�"
+
+msgid "Create Series Timer based on"
+msgstr "Vytvorenie pl�nu na z�klade s�rie"
+
+msgid "Series Timer start time"
+msgstr "S�riov� pl�n za��na"
+
+msgid "Series Timer stop time"
+msgstr "S�riov� pl�n kon��"
+
+msgid "Days to record"
+msgstr "Dni"
+
+msgid "Day to start"
+msgstr "Za��na d�a"
+
+msgid "Create Timer"
+msgstr "Vytvori� pl�n"
+
+msgid "Series Timer created"
+msgstr "Vytvoren� s�riov� pl�n"
+
+msgid "Start"
+msgstr "�tart"
+
+msgid "Stop"
+msgstr "Stop"
+
+msgid "Configure Search Timer based on"
+msgstr "Vyh�ad�vanie pl�nu nastavi� na z�klade"
+
+msgid "Search Expression:"
+msgstr "H�adan� v�raz:"
+
+msgid "Continue"
+msgstr "�al�ie"
+
+msgid "Configure Search Timer for Search String"
+msgstr "Konfigur�cia vyh�ad�vania pl�nu pre h�adan� k���ov� slovo "
+
+msgid "Manually configure Options"
+msgstr "Ru�ne konfigurova� mo�nosti"
+
+msgid "Use Template"
+msgstr "pou�itie �abl�ny"
+
+msgid "EPGSearch Search Timers"
+msgstr ""
+
+msgid "No Search Timers Configured"
+msgstr ""
+
+msgid "Configure Search Timer Options"
+msgstr ""
+
+msgid "Save Search Timer"
+msgstr ""
+
+msgid "Search String"
+msgstr ""
+
+msgid "Active"
+msgstr ""
+
+msgid "Search Mode"
+msgstr "Re�im vyh�ad�vania"
+
+msgid "Use Title"
+msgstr "Pou�i� n�zov"
+
+msgid "Use Subtitle"
+msgstr "Pou�i� titulky"
+
+msgid "Use Description"
+msgstr "Pou�i� popis"
+
+msgid "Limit Channels"
+msgstr "Obmedzi� kan�ly"
+
+msgid "Use Time"
+msgstr "Pou�i� �as"
+
+msgid "Display advanced Options"
+msgstr ""
+
+msgid "Limit Days of the Week"
+msgstr ""
+
+msgid "Time margin for start in minutes"
+msgstr ""
+
+msgid "Time margin for stop in minutes"
+msgstr ""
+
+msgid "Series Recording"
+msgstr ""
+
+msgid "Folder"
+msgstr ""
+
+msgid "Use VPS"
+msgstr ""
+
+msgid "Avoid Repeats"
+msgstr ""
+
+msgid "Use in Favorites"
+msgstr ""
+
+msgid "Hide advanced Options"
+msgstr ""
+
+msgid "Display Results for Search Timer"
+msgstr "Pozrie� v�sledky pre vyh�ad�vanie pl�nov"
+
+msgid "Start Channel"
+msgstr "Od kan�lu"
+
+msgid "Stop Channel"
+msgstr "Po kan�l"
+
+msgid "Start after"
+msgstr "Za�iatok po"
+
+msgid "Start before"
+msgstr "Za�iatok pred"
+
+msgid "Select Days"
+msgstr ""
+
+msgid "Number of allowed repeats"
+msgstr ""
+
+msgid "Compare Title"
+msgstr ""
+
+msgid "Compare Subtitle"
+msgstr ""
+
+msgid "Compare Description"
+msgstr ""
+
+msgid "Really delete Search Timer"
+msgstr ""
+
+msgid "Delete only Search Timer"
+msgstr ""
+
+msgid "Delete Search Timer and created Timers"
+msgstr ""
+
+msgid "Search Timer sucessfully created."
+msgstr "Vyh�ad�va� pl�nu vytvoren�."
+
+msgid "Search Timer update initialised"
+msgstr "Vyhlad�va� pl�nu inicializovan�"
+
+msgid "Search Timer NOT sucessfully created"
+msgstr "Vyh�ad�va� pl�nu nie je kompletne vytvoren�"
+
+msgid "Creating Search Timer"
+msgstr "Vytvorenie vyh�ad�vacieho pl�nu"
+
+msgid "Search Term"
+msgstr "k���ov� slovo"
+
+msgid "Using Template"
+msgstr "�abl�na"
+
+msgid "Use other Template"
+msgstr "Pou�i� in� �abl�nu"
+
+msgid "search results for Favorite"
+msgstr ""
+
+msgid "search result for Favorite"
+msgstr ""
+
+msgid "search results for Search Timer"
+msgstr "n�jden� v�sledky vyh�ad�vania pl�nu"
+
+msgid "search result for Search Timer"
+msgstr "n�jden� v�sledok vyh�ad�vania pl�nu"
+
+msgid "Nothing found for Search String"
+msgstr "H�adan� v�raz sa nena�iel"
+
+msgid "Configure Options for Switchtimer"
+msgstr "Konfigurova� mo�nosti pre prep�nac� pl�n"
+
+msgid "Minutes before switching"
+msgstr "Min�ty pred prepnut�m"
+
+msgid "switch"
+msgstr "Prepn��"
+
+msgid "announce only"
+msgstr "iba ozn�mi�"
+
+msgid "ask for switch"
+msgstr "op�ta� sa na prepnutie"
+
+msgid "Switch Mode"
+msgstr "Prep�nac� re�im"
+
+msgid "Create"
+msgstr "Vytvori�"
+
+msgid "Switch Timer sucessfully created"
+msgstr "Prepnutie je napl�novan�"
+
+msgid "Switch Timer NOT sucessfully created"
+msgstr "Pl�n prepnutia nie je vytvoren�"
+
+msgid "Switch Timer deleted"
+msgstr "Pl�n prepnutia vymazan�"
+
+msgid "Channel to Search"
+msgstr "H�ada� na kan�le"
+
+msgid "Search in title"
+msgstr "H�ada� v n�zve"
+
+msgid "Search in Subtitle"
+msgstr "H�ada� v titulk�ch"
+
+msgid "Search in Description"
+msgstr "H�ada� v popise"
+
+msgid "Show Search Options"
+msgstr "Zobrazi� mo�nosti vyh�ad�vania"
+
+msgid "Perform Search"
+msgstr "Vykona� vyh�ad�vanie"
+
+msgid "search results for"
+msgstr "vyh�adan� v�sledky pre"
+
+msgid "search result for"
+msgstr "vyh�adan� v�sledok pre"
+
+msgid "Adapt Search"
+msgstr "Prisp�sobi� vyh�ad�vanie"
+
+msgid "Search String has to have at least three letters"
+msgstr ""
+
+msgid "Found"
+msgstr "N�jden�"
+
+msgid "recording"
+msgstr "nahr�vka"
+
+msgid "recordings"
+msgstr "nahr�vky"
+
+msgid "for"
+msgstr "pre"
+
+msgid "No recordings found for"
+msgstr "Nena�li sa nahr�vky s n�zvom "
+
+msgid "No Favorites available"
+msgstr ""
+
+msgid "whole term must appear"
+msgstr "kompletn� v�raz"
+
+msgid "all terms must exist"
+msgstr "v�etky slov�"
+
+msgid "one term must exist"
+msgstr "jeden pojem mus� existova�"
+
+msgid "exact match"
+msgstr "presn� zhoda"
+
+msgid "regular expression"
+msgstr "regul�rny v�raz"
+
+msgid "General Settings"
+msgstr "V�eobecn� nastavenia"
+
+msgid "Screen Presentation"
+msgstr "Mo�nosti zobrazenia"
+
+msgid "Fonts and Fontsizes"
+msgstr "P�sma a ve�kosti p�sma"
+
+msgid "Recording Menus and Favorites"
+msgstr ""
+
+msgid "Image Loading and Caching"
+msgstr ""
+
+msgid "x channels back / forward"
+msgstr "x kan�lov sp� / vpred"
+
+msgid "previous / next channel group"
+msgstr "Predch�dzaj�ce / �al�ie skupiny kan�lov"
+
+msgid "Blue: Channel Switch, Ok: Detailed EPG"
+msgstr "Modr�: Prepn�� kan�l, OK: Podrobn� EPG"
+
+msgid "Blue: Detailed EPG, Ok: Channel Switch"
+msgstr "Modr�: podrobn� EPG, OK: prepn�� kan�l"
+
+msgid "Blue: Favorites / Switch, Ok: Detailed EPG"
+msgstr ""
+
+msgid "Timely Jump"
+msgstr ""
+
+msgid "Jump to specific channel"
+msgstr ""
+
+msgid "never"
+msgstr "nikdy"
+
+msgid "if exists"
+msgstr "ak s� k dispoz�cii"
+
+msgid "always"
+msgstr "v�dy"
+
+msgid "Show Main Menu Entry"
+msgstr "Zobrazi� v hlavnom menu"
+
+msgid "Replace VDR Schedules Menu"
+msgstr "Zameni� VDR menu (tv program)"
+
+msgid "Use appropriate nOpacity Theme"
+msgstr ""
+
+msgid "Theme"
+msgstr "T�ma"
+
+msgid "Time to display in minutes"
+msgstr "Zobrazen� �as v min�tach"
+
+msgid "Rounded Corners"
+msgstr "Zaoblen� rohy"
+
+msgid "Channel Jump Mode (Keys Green / Yellow)"
+msgstr "Re��m skoku kan�la (kl�vesy zelen� / �lt�)"
+
+msgid "Keys Blue and OK"
+msgstr "Tla�idl� modr� a OK"
+
+msgid "Close TVGuide after channel switch"
+msgstr "Zavrie� TVGuide po prepnut� kan�lu"
+
+msgid "Functionality of numeric Keys"
+msgstr ""
+
+msgid "Hide last Channel Group"
+msgstr "Skry� posledn� skupinu kan�lov"
+
+msgid "Big Step (Keys 1 / 3) in hours"
+msgstr "Ve�k� skoky (tla�idl� 1 / 3) v hodin�ch"
+
+msgid "Huge Step (Keys 4 / 6) in hours"
+msgstr "Ve�mi ve�k� skoky (tla�idl� 4 / 6) v hodin�ch"
+
+msgid "Time Format (12h/24h)"
+msgstr "Form�t �asu (12h/24h)"
+
+msgid "EPG Window Text Scrolling Speed"
+msgstr ""
+
+msgid "Display Reruns in detailed EPG View"
+msgstr "Repr�zy v podrobnom zobrazen� rel�cie EPG"
+
+msgid "Number of reruns to display"
+msgstr "Po�et zobrazovan�ch repr�z"
+
+msgid "Use Subtitle for reruns"
+msgstr "Titulky pre vyh�adanie repr�z"
+
+msgid "Display Mode"
+msgstr "Re��m zobrazenia"
+
+msgid "Height of Channel Header (Perc. of osd height)"
+msgstr "V��ka hlavi�ky kan�lov (% z OSD v��ky)"
+
+msgid "Width of Timeline (Perc. of osd width)"
+msgstr "��rka �asovej osi (% z OSD v��ky)"
+
+msgid "Number of Channels to display"
+msgstr "Po�et zobrazen�ch kan�lov"
+
+msgid "Width of Channel Header (Perc. of osd width)"
+msgstr "��rka hlavi�ky kan�lov (% z OSD ��rky)"
+
+msgid "Height of Timeline (Perc. of osd height)"
+msgstr "V��ka �asovej osi (% z OSD v��ky)"
+
+msgid "Display time in EPG Grids"
+msgstr "Zobrazi� �as v EPG mrie�ke"
+
+msgid "Height of Headers (Status Header and EPG View, Perc. of osd height)"
+msgstr ""
+
+msgid "Height of Footer (Perc. of osd height)"
+msgstr ""
+
+msgid "Display status header"
+msgstr "Zobrazi� stavov� hlavi�ku"
+
+msgid "Scale video to upper right corner"
+msgstr "�k�lovateln� video v pravom hornom rohu"
+
+msgid "Rounded corners around video frame"
+msgstr "Zaoblen� rohy do okna videa"
+
+msgid "Display Channel Names in Header"
+msgstr "Zobrazi� men� kan�lu v hlavi�ke"
+
+msgid "Display channel groups"
+msgstr "Zobrazi� skupiny kan�lov"
+
+msgid "Height of channel groups (Perc. of osd height)"
+msgstr "V��ka skupiny kan�la (% z OSD v��ky)"
+
+msgid "Width of channel groups (Perc. of osd width)"
+msgstr "��rka skupiny kan�la (% z OSD ��rky)"
+
+msgid "Display current time baseline"
+msgstr ""
+
+msgid "Show Channel Logos"
+msgstr "Zobrazi� log� kan�lov"
+
+msgid "Logo Path used"
+msgstr "Umiestnenie pou�it�ho loga"
+
+msgid "Logo Extension"
+msgstr "Logo pr�pona"
+
+msgid "Logo width ratio"
+msgstr "��rka loga"
+
+msgid "Logo height ratio"
+msgstr "V��ka loga"
+
+msgid "Text Border in Detailed View (pixel)"
+msgstr ""
+
+msgid "Show EPG Images"
+msgstr "Zobrazi� EPG obr�zky"
+
+msgid "EPG Images Path used"
+msgstr "Umiestnenie EPG obr�zkov"
+
+msgid "EPG Image width"
+msgstr "��rka EPG obr�zku"
+
+msgid "EPG Image height"
+msgstr "V��ka EPG obr�zku"
+
+msgid "Number of additional EPG Images"
+msgstr "Po�et �al��ch EPG obr�zkov"
+
+msgid "Additional EPG Image width"
+msgstr "��rka �al��ch EPG obr�zkov"
+
+msgid "Additional EPG Image height"
+msgstr "V��ka �al��ch EPG obr�zkov"
+
+msgid "Font"
+msgstr "P�smo"
+
+msgid "Status Header Font Size"
+msgstr "Ve�kos� p�sma stavovej hlavi�ky"
+
+msgid "Status Header Large Font Size"
+msgstr "Ve�kos� ve�k�ho p�sma stavovej hlavi�ky"
+
+msgid "Detail EPG View Font Size"
+msgstr "Ve�kos� p�sma v detailnom EPG poh�ade"
+
+msgid "Detail EPG View Header Font Size"
+msgstr "Ve�kos� p�sma hlavi�ky v detailnom EPG poh�ade"
+
+msgid "Message Font Size"
+msgstr "Ve�kos� p�sma spr�vy"
+
+msgid "Message Large Font Size"
+msgstr "Ve�kos� ve�k�ho p�sma spr�vy"
+
+msgid "Button Font Size"
+msgstr "Ve�kos� p�sma tla�idla"
+
+msgid "Channel Header Font Size"
+msgstr "Ve�kos� p�sma hlavi�ky kan�la"
+
+msgid "Channel Groups Font Size"
+msgstr "Ve�kos� p�sma skup�n kan�lu"
+
+msgid "Grid Font Size"
+msgstr "Ve�kos� p�sma mrie�ky"
+
+msgid "Grid Font Small Size"
+msgstr "Ve�kos� mal�ho p�sma mrie�ky"
+
+msgid "Timeline Weekday Font Size"
+msgstr "Ve�kos� p�sma d�a �asovej osi"
+
+msgid "Timeline Date Font Size"
+msgstr "Ve�kos� p�sma d�tumu �asovej osi"
+
+msgid "Timeline Time Font Size"
+msgstr "Ve�kos� p�sma hod�n �asovej osi"
+
+msgid "Search & Recording Menu Font Size"
+msgstr "H�ada� & Nahra� menu p�smo"
+
+msgid "Search & Recording Menu Small Font Size"
+msgstr "H�ada� & Nahra� menu mal� p�smo"
+
+msgid "Search & Recording Menu Header Font Size"
+msgstr ""
+
+msgid "Always use root video folder"
+msgstr ""
+
+msgid "Select from folder list"
+msgstr ""
+
+msgid "Use fixed folder"
+msgstr ""
+
+msgid "Folder for instant Recordings"
+msgstr ""
+
+msgid "Use Remotetimers"
+msgstr "Pou�i� vzdialen� pl�nova�"
+
+msgid "Use \"What's on now\" in favorites"
+msgstr ""
+
+msgid "Use \"What's on next\" in favorites"
+msgstr ""
+
+msgid "Use user defined time 1 in favorites"
+msgstr ""
+
+msgid "Description"
+msgstr ""
+
+msgid "Time"
+msgstr ""
+
+msgid "Use user defined time 2 in favorites"
+msgstr ""
+
+msgid "Use user defined time 3 in favorites"
+msgstr ""
+
+msgid "Use user defined time 4 in favorites"
+msgstr ""
+
+msgid "Limit channels in favorites"
+msgstr ""
+
+msgid "Create Log Messages for image loading"
+msgstr ""
+
+msgid "Limit Logo Cache"
+msgstr ""
+
+msgid "Maximal number of logos to cache"
+msgstr ""
+
+msgid "Number of  logos to cache at start"
+msgstr ""
+
+msgid "Cache Sizes"
+msgstr ""
+
+msgid "OSD Element Cache"
+msgstr ""
+
+msgid "Logo cache"
+msgstr ""
+
+msgid "EPG Grid Cache"
+msgstr ""
+
+msgid "Channel Groups Cache"
+msgstr ""
+
+msgid "Recording Menus Icon Cache"
+msgstr ""
+
+msgid "No Cast available"
+msgstr ""
+
+msgid "Cast"
+msgstr ""
+
+msgid "EPG Info"
+msgstr ""
+
+msgid "Reruns"
+msgstr ""
+
+msgid "Recording Information"
+msgstr ""
+
+msgid "Image Galery"
+msgstr ""
+
+msgid "TheTVDB Info"
+msgstr ""
+
+msgid "TheTVDB Information"
+msgstr ""
+
+msgid "Episode"
+msgstr ""
+
+msgid "Season"
+msgstr ""
+
+msgid "Episode Overview"
+msgstr ""
+
+msgid "First aired"
+msgstr ""
+
+msgid "Guest Stars"
+msgstr ""
+
+msgid "TheMovieDB Rating"
+msgstr ""
+
+msgid "Series Overview"
+msgstr ""
+
+msgid "Genre"
+msgstr ""
+
+msgid "Network"
+msgstr ""
+
+msgid "Status"
+msgstr ""
+
+msgid "TheMovieDB Information"
+msgstr ""
+
+msgid "Original Title"
+msgstr ""
+
+msgid "Tagline"
+msgstr ""
+
+msgid "Overview"
+msgstr ""
+
+msgid "yes"
+msgstr ""
+
+msgid "no"
+msgstr ""
+
+msgid "Adult"
+msgstr ""
+
+msgid "Collection"
+msgstr ""
+
+msgid "Budget"
+msgstr ""
+
+msgid "Revenue"
+msgstr ""
+
+msgid "Homepage"
+msgstr ""
+
+msgid "Release Date"
+msgstr ""
+
+msgid "Runtime"
+msgstr ""
+
+msgid "minutes"
+msgstr ""
+
+msgid "TheMovieDB Popularity"
+msgstr ""
+
+msgid "TheMovieDB Vote Average"
+msgstr ""
+
+#~ msgid "RERUNS OF THIS SHOW"
+#~ msgstr "Repr�za tohto programu"
+
+#~ msgid "Actors"
+#~ msgstr "Herci"
+
+#~ msgid "Use folders for instant records"
+#~ msgstr "Pou�i� adres�re pre okam�it� nahr�vky"
+
+#~ msgid "Height of status header (Perc. of osd height)"
+#~ msgstr "V��ka stavovej hlavi�ky (% z OSD v��ky)"
+
+#~ msgid "Configure Search Timer Options for Search String"
+#~ msgstr "Konfigurova� mo�nosti pl�nov pre vyh�ad�vanie k���ov�ch slov"
diff --git a/recmanager.c b/recmanager.c
new file mode 100644
index 0000000..7ad6f4c
--- /dev/null
+++ b/recmanager.c
@@ -0,0 +1,714 @@
+#define __STL_CONFIG_H
+
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+
+#include <vdr/menu.h>
+#include "services/remotetimers.h"
+#include "tools.h"
+#include "switchtimer.h"
+#include "timerconflict.h"
+#include "recmanager.h"
+
+static int CompareRecording(const void *p1, const void *p2) {
+   return (int)((*(cRecording **)p1)->Start() - (*(cRecording **)p2)->Start());
+}
+
+cRecManager::cRecManager(void) {
+    epgSearchPlugin = NULL;
+    epgSearchAvailable = false;
+}
+
+cRecManager::~cRecManager(void) {
+}
+
+void cRecManager::SetEPGSearchPlugin(void) {
+	epgSearchPlugin = cPluginManager::GetPlugin("epgsearch");
+	if (epgSearchPlugin) {
+		epgSearchAvailable = true;
+	}
+}
+
+bool cRecManager::RefreshRemoteTimers(void) {
+    cString errorMsg;
+    if (!pRemoteTimers->Service("RemoteTimers::RefreshTimers-v1.0", &errorMsg)) {
+        esyslog("tvguide: %s", *errorMsg);
+        return false;
+    }
+    return true;
+}
+
+bool cRecManager::CheckEventForTimer(const cEvent *event) {
+    bool hasTimer = false;
+    
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        RemoteTimers_GetMatch_v1_0 rtMatch;
+        rtMatch.event = event;
+        pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+        if (rtMatch.timerMatch == tmFull)
+            hasTimer = true;
+    } else
+        hasTimer = event->HasTimer();
+
+    return hasTimer;
+}
+
+cTimer *cRecManager::GetTimerForEvent(const cEvent *event) {
+    cTimer *timer = NULL;
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        RemoteTimers_GetMatch_v1_0 rtMatch;
+        rtMatch.event = event;
+        pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+        timer = rtMatch.timer;
+    } else
+        timer = Timers.GetMatch(event);    
+    return timer;
+}
+
+cTimer *cRecManager::createTimer(const cEvent *event, std::string path) {
+    cTimer *timer = NULL;
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        timer = createRemoteTimer(event, path);
+    } else {
+        timer = createLocalTimer(event, path);
+    }
+    return timer;
+}
+
+cTimer *cRecManager::createLocalTimer(const cEvent *event, std::string path) {
+    cTimer *timer = new cTimer(event);
+    cTimer *t = Timers.GetTimer(timer);
+    if (t) {
+        t->OnOff();
+        t->SetEventFromSchedule();
+        delete timer;
+        timer = t;
+        isyslog("timer %s reactivated", *t->ToDescr());
+    } else {
+        Timers.Add(timer);
+        isyslog("timer %s added (active)", *timer->ToDescr());
+    }
+    SetTimerPath(timer, event, path);
+    Timers.SetModified();
+    return timer;
+}
+
+cTimer *cRecManager::createRemoteTimer(const cEvent *event, std::string path) {
+    cTimer *t = new cTimer(event);
+    SetTimerPath(t, event, path);
+    RemoteTimers_Timer_v1_0 rt;
+    rt.timer = t;
+    pRemoteTimers->Service("RemoteTimers::GetTimer-v1.0", &rt.timer);
+    if (rt.timer) {
+        rt.timer->OnOff();
+        if (!pRemoteTimers->Service("RemoteTimers::ModTimer-v1.0", &rt))
+            rt.timer = NULL;
+    } else {
+        rt.timer = t;
+        if (!pRemoteTimers->Service("RemoteTimers::NewTimer-v1.0", &rt))
+            isyslog("%s", *rt.errorMsg);
+    }
+    RefreshRemoteTimers();
+    return rt.timer;
+}
+
+void cRecManager::SetTimerPath(cTimer *timer, const cEvent *event, std::string path) {
+    if (tvguideConfig.instRecFolderMode == eFolderFixed) {
+        Epgsearch_services_v1_2 *epgSearch = new Epgsearch_services_v1_2;
+        std::string recDir = tvguideConfig.instRecFixedFolder;
+        std::replace(recDir.begin(), recDir.end(), '/', '~');
+        if (strchr(recDir.c_str(), '%') != NULL) {
+            if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+                std::string newFileName = epgSearch->handler->Evaluate(recDir, event);
+                if (strchr(newFileName.c_str(), '%') == NULL) // only set directory to new value if all categories could have been replaced
+                    timer->SetFile(newFileName.c_str());
+                else 
+                    esyslog("tvguide: timer path not set because replacing variable was not successfull: %s", newFileName.c_str());
+            }
+        } else {
+            cString newFileName;
+            if (recDir.size() > 0) {
+                newFileName = cString::sprintf("%s~%s", recDir.c_str(), timer->File());
+                timer->SetFile(*newFileName);
+            }
+        }
+        return;
+    }
+    //Set choosen path
+    cString newFileName;
+    if (path.size() > 0) {
+        std::replace(path.begin(), path.end(), '/', '~');
+        newFileName = cString::sprintf("%s~%s", path.c_str(), timer->File());
+    } else {
+        newFileName = event->Title();
+    }
+    timer->SetFile(*newFileName);
+}
+
+void cRecManager::DeleteTimer(int timerID) {
+    cTimer *t = Timers.Get(timerID);
+    if (!t)
+        return;
+    DeleteTimer(t);
+}
+
+void cRecManager::DeleteTimer(const cEvent *event) {
+    if (!event)
+        return;
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        DeleteRemoteTimer(event);
+    } else {
+        DeleteLocalTimer(event);
+    }
+}
+
+void cRecManager::DeleteLocalTimer(const cEvent *event) {
+    cTimer *t = Timers.GetMatch(event);
+    if (!t)
+        return;
+    DeleteTimer(t);
+}
+
+
+void cRecManager::DeleteTimer(cTimer *timer) {
+    if (timer->Recording()) {
+        timer->Skip();
+        cRecordControls::Process(time(NULL));
+    }
+    isyslog("timer %s deleted", *timer->ToDescr());
+    Timers.Del(timer, true);
+    Timers.SetModified();
+}
+
+void cRecManager::DeleteRemoteTimer(const cEvent *event) {
+    RemoteTimers_GetMatch_v1_0 rtMatch;
+    rtMatch.event = event;
+    pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+    if (rtMatch.timer) {
+        RemoteTimers_Timer_v1_0 rt;
+        rt.timer = rtMatch.timer;
+        isyslog("remotetimer %s deleted", *rt.timer->ToDescr());
+        if (!pRemoteTimers->Service("RemoteTimers::DelTimer-v1.0", &rt))
+            isyslog("remotetimer error");
+        RefreshRemoteTimers();
+    }
+}
+
+void cRecManager::SaveTimer(cTimer *timer, cTimer newTimerSettings) {
+    if (!timer)
+        return;
+    
+    bool active = newTimerSettings.HasFlags(tfActive);
+    int prio = newTimerSettings.Priority();
+    int lifetime = newTimerSettings.Lifetime();
+    time_t day = newTimerSettings.Day();
+    int start = newTimerSettings.Start();
+    int stop = newTimerSettings.Stop();
+    std::string fileName = newTimerSettings.File();
+
+    timer->SetDay(day);
+    timer->SetStart(start);
+    timer->SetStop(stop);
+    timer->SetPriority(prio);
+    timer->SetLifetime(lifetime);
+    timer->SetFile(fileName.c_str());
+    
+    if (timer->HasFlags(tfActive) && !active)
+        timer->ClrFlags(tfActive);
+    else if (!timer->HasFlags(tfActive) && active)
+        timer->SetFlags(tfActive);
+    
+    timer->SetEventFromSchedule();
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        RemoteTimers_Timer_v1_0 rt;
+        rt.timer = timer;
+        if (!pRemoteTimers->Service("RemoteTimers::ModTimer-v1.0", &rt))
+            rt.timer = NULL;
+        RefreshRemoteTimers();
+    } else {
+        Timers.SetModified();
+    }          
+}
+
+
+bool cRecManager::IsRecorded(const cEvent *event) {
+    cTimer *timer = Timers.GetMatch(event);
+    if (!timer)
+        return false;
+    return timer->Recording();
+}
+
+cTVGuideTimerConflicts *cRecManager::CheckTimerConflict(void) {
+    cTVGuideTimerConflicts *conflictList = new cTVGuideTimerConflicts();
+    if (!epgSearchAvailable)
+        return conflictList;
+    Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+    if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+        std::list<std::string> conflicts = epgSearch->handler->TimerConflictList();
+        int numConflicts = conflicts.size();
+        if (numConflicts == 0)
+            return conflictList;
+        for (std::list<std::string>::iterator it=conflicts.begin(); it != conflicts.end(); ++it) {
+            conflictList->AddConflict(*it);
+        }
+    }
+    delete epgSearch;
+    conflictList->CalculateConflicts();
+    return conflictList;
+}
+
+void cRecManager::CreateSeriesTimer(cTimer *seriesTimer) {
+    seriesTimer->SetEventFromSchedule();
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        RemoteTimers_Timer_v1_0 rt;
+        rt.timer = seriesTimer;
+        if (!pRemoteTimers->Service("RemoteTimers::NewTimer-v1.0", &rt))
+            isyslog("%s", *rt.errorMsg);
+        RefreshRemoteTimers();
+    } else {
+        Timers.Add(seriesTimer);
+        Timers.SetModified();
+    }
+}
+
+
+void cRecManager::ReadEPGSearchTemplates(std::vector<TVGuideEPGSearchTemplate> *epgTemplates) {
+    cString ConfigDir = cPlugin::ConfigDirectory("epgsearch");
+    cString epgsearchConf = "epgsearchtemplates.conf";
+    cString fileName = AddDirectory(*ConfigDir,  *epgsearchConf);
+    if (access(fileName, F_OK) == 0) {
+        FILE *f = fopen(fileName, "r");
+        if (f) {
+            char *s;
+            cReadLine ReadLine;
+            while ((s = ReadLine.Read(f)) != NULL) {
+                char *p = strchr(s, '#');
+                if (p)
+                    *p = 0;
+                stripspace(s);
+                try {
+                    if (!isempty(s)) {
+                        std::string templ = s;
+                        int posID = templ.find_first_of(":");
+                        int posName = templ.find_first_of(":", posID+1);
+                        std::string name = templ.substr(posID+1, posName - posID - 1);
+                        std::string templValue = templ.substr(posName);
+                        TVGuideEPGSearchTemplate tmp;
+                        tmp.name = name;
+                        tmp.templValue = templValue;
+                        epgTemplates->push_back(tmp);
+                    }
+                } catch (...){}
+            }
+        }
+    }
+}
+
+const cEvent **cRecManager::PerformSearchTimerSearch(std::string epgSearchString, int &numResults) {
+    if (!epgSearchAvailable)
+        return NULL;
+    const cEvent **searchResults = NULL;
+    Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+    if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+        std::list<std::string> results = epgSearch->handler->QuerySearch(epgSearchString);
+        numResults = results.size();
+        if (numResults > 0) {
+            searchResults = new const cEvent *[numResults];
+            cSchedulesLock schedulesLock;
+            const cSchedules *schedules;
+            schedules = cSchedules::Schedules(schedulesLock);
+            const cEvent *event = NULL;
+            int index=0;
+            for (std::list<std::string>::iterator it=results.begin(); it != results.end(); ++it) {
+                try {
+                    splitstring s(it->c_str());
+                    std::vector<std::string> flds = s.split(':', 1);
+                    int eventID = atoi(flds[1].c_str());
+                    std::string channelID = flds[7];
+                    tChannelID chanID = tChannelID::FromString(channelID.c_str());
+                    cChannel *channel = Channels.GetByChannelID(chanID);
+                    if (channel) {
+                        const cSchedule *Schedule = NULL;
+                        Schedule = schedules->GetSchedule(channel);
+                        event = Schedule->GetEvent(eventID);
+                        if (event) {
+                            searchResults[index] = event;                        
+                        } else
+                            return NULL;
+                    } else
+                        return NULL;
+                    index++;
+                } catch (...){}
+            }
+        }
+    }
+    return searchResults;
+}
+
+const cEvent **cRecManager::PerformSearch(Epgsearch_searchresults_v1_0 data, int &numResults) {
+    if (epgSearchAvailable) {
+        if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) {
+            cList<Epgsearch_searchresults_v1_0::cServiceSearchResult> *list = data.pResultList;
+            if (!list)
+                return NULL;
+            int numElements = list->Count();
+            const cEvent **searchResults = NULL;
+            if (numElements > 0) {
+                searchResults = new const cEvent *[numElements];
+                numResults = numElements;
+                int index = 0;
+                for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r ; r = list->Next(r)) {
+                    searchResults[index] = r->event;
+                    index++;
+                }
+            }
+            delete list;
+            return searchResults;
+        }
+    }
+    return NULL;
+}
+
+void cRecManager::GetSearchTimers(std::vector<cTVGuideSearchTimer> *searchTimer) {
+    if (!epgSearchAvailable) {
+            return;
+    }
+    Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+    if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+        std::list<std::string> searchTimerList;
+        searchTimerList = epgSearch->handler->SearchTimerList();
+        for(std::list<std::string>::iterator it = searchTimerList.begin(); it != searchTimerList.end(); it++) {
+            cTVGuideSearchTimer timer;
+            timer.SetEPGSearchString(it->c_str());
+            if (timer.Parse())
+                searchTimer->push_back(timer);
+        }
+    }
+    std::sort(searchTimer->begin(), searchTimer->end());
+}
+
+int cRecManager::CreateSearchTimer(std::string epgSearchString) {
+    int timerID = -1;
+    if (!epgSearchAvailable)
+        return timerID;
+    Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+    if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+        timerID = epgSearch->handler->AddSearchTimer(epgSearchString);
+    }
+    return timerID;
+}
+
+bool cRecManager::SaveSearchTimer(cTVGuideSearchTimer *searchTimer) {
+    if (!epgSearchAvailable)
+        return false;
+    Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+    if (searchTimer->GetID() > -1) {
+        if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+            bool success = epgSearch->handler->ModSearchTimer(searchTimer->BuildSearchString());
+            if (success) {
+                esyslog("tvguide: search timer with id %d sucessfully modified", searchTimer->GetID());
+                return true;
+            } else {
+                esyslog("tvguide: error modifying search timer with id %d, build string %s", searchTimer->GetID(), searchTimer->BuildSearchString().c_str());
+                return false;
+            }
+        }
+    } else {
+        if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+            int timerID = epgSearch->handler->AddSearchTimer(searchTimer->BuildSearchString());
+            if (timerID >=0) {
+                esyslog("tvguide: search timer with id %d sucessfully created", timerID);
+                return true;
+            } else {
+                esyslog("tvguide: error creating search timer, build string %s", searchTimer->BuildSearchString().c_str());
+                return false;
+            }
+        }
+    }
+    return false;
+}
+
+void cRecManager::DeleteSearchTimer(cTVGuideSearchTimer *searchTimer, bool delTimers) {
+    if (!epgSearchAvailable)
+        return;
+    int searchTimerID = searchTimer->GetID();
+    if (delTimers) {
+        cTimer *timer = Timers.First();
+        while(timer) {
+            if (!timer->Recording()) {
+                char* searchID = GetAuxValue(timer, "s-id");
+                if (searchID) {
+                    if (searchTimerID == atoi(searchID)) {
+                        cTimer* timerNext = Timers.Next(timer);
+                        DeleteTimer(timer);
+                        timer = timerNext;
+                    } else {
+                        timer = Timers.Next(timer);
+                    }
+                    free(searchID);
+                } else {
+                    timer = Timers.Next(timer);
+                }
+            } else {
+                timer = Timers.Next(timer);
+            }
+        }
+    }
+    Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+    if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+        bool success = epgSearch->handler->DelSearchTimer(searchTimerID);
+        if (success) {
+            esyslog("tvguide: search timer \"%s\" sucessfully deleted", searchTimer->SearchString().c_str());
+        } else {
+            esyslog("tvguide: error deleting search timer \"%s\"", searchTimer->SearchString().c_str());
+        }
+    }   
+}
+
+void cRecManager::UpdateSearchTimers(void) {
+    if (epgSearchAvailable) {
+        Epgsearch_updatesearchtimers_v1_0 data;
+        data.showMessage = false;
+        epgSearchPlugin->Service("Epgsearch-updatesearchtimers-v1.0", &data);
+    }
+}
+
+// announceOnly: 0 = switch, 1 = announce only, 2 = ask for switch
+bool cRecManager::CreateSwitchTimer(const cEvent *event, cSwitchTimer switchTimer) {
+    if (epgSearchAvailable && event) {
+        Epgsearch_switchtimer_v1_0 data;
+        data.event = event;
+        data.mode = 1;
+        data.switchMinsBefore = switchTimer.switchMinsBefore;
+        data.announceOnly = switchTimer.announceOnly;
+        data.success = false;
+        epgSearchPlugin->Service("Epgsearch-switchtimer-v1.0", &data);
+        cSwitchTimer *t = new cSwitchTimer(event);
+        SwitchTimers.Add(t);
+        return data.success;
+    }
+    return false;
+}
+
+void cRecManager::DeleteSwitchTimer(const cEvent *event) {
+    SwitchTimers.DeleteSwitchTimer(event);
+    if (epgSearchAvailable) {
+        Epgsearch_switchtimer_v1_0 data;
+        data.event = event;
+        data.mode = 2;
+        data.switchMinsBefore = 0;
+        data.announceOnly = 0;
+        data.success = false;
+        epgSearchPlugin->Service("Epgsearch-switchtimer-v1.0", &data);
+    }
+}
+
+cRecording **cRecManager::SearchForRecordings(std::string searchString, int &numResults) {
+    
+    cRecording **matchingRecordings = NULL;
+    int num = 0;
+    numResults = 0;
+    
+    for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
+        std::string s1 = recording->Name();
+        std::string s2 = searchString;
+        if (s1.empty() || s2.empty()) continue;
+        
+        // tolerance for fuzzy searching: 90% of the shorter text length, but at least 1
+        int tolerance = std::max(1, (int)std::min(s1.size(), s2.size()) / 10); 
+
+        bool match = FindIgnoreCase(s1, s2) >= 0 || FindIgnoreCase(s2, s1) >= 0;
+        
+        if (!match) {
+            AFUZZY af = { NULL, NULL, NULL, NULL, NULL, NULL, { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 };
+            if (s1.size() > 32) s1 = s1.substr(0, 32);
+            afuzzy_init(s1.c_str(), tolerance, 0, &af);
+            /* Checking substring */
+            int res = afuzzy_checkSUB(s2.c_str(), &af);
+            afuzzy_free(&af);
+            match = (res > 0);
+        }
+        
+        if (!match) {
+            AFUZZY af = { NULL, NULL, NULL, NULL, NULL, NULL, { 0 }, { 0 }, 0, 0, 0, 0, 0, 0 };
+            if (s2.size() > 32) s2 = s2.substr(0, 32);
+            afuzzy_init(s2.c_str(), tolerance, 0, &af);
+            /* Checking substring */
+            int res = afuzzy_checkSUB(s1.c_str(), &af);
+            afuzzy_free(&af);
+            match = (res > 0);
+        }
+        
+        if (match) {
+            matchingRecordings = (cRecording **)realloc(matchingRecordings, (num + 1) * sizeof(cRecording *));
+            matchingRecordings[num++] = recording;
+        }
+    }
+    if (num > 0) {
+        qsort(matchingRecordings, num, sizeof(cRecording *), CompareRecording);
+        numResults = num;
+        return matchingRecordings;
+    }
+    return NULL;
+}
+
+const cEvent **cRecManager::LoadReruns(const cEvent *event, int &numResults) {
+    if (epgSearchAvailable && !isempty(event->Title())) {
+        Epgsearch_searchresults_v1_0 data;
+        std::string strQuery = event->Title();
+        if (tvguideConfig.useSubtitleRerun > 0) {
+            if (tvguideConfig.useSubtitleRerun == 2 || !isempty(event->ShortText()))
+                strQuery += "~";
+            if (!isempty(event->ShortText()))
+                strQuery += event->ShortText();
+                data.useSubTitle = true;
+        } else {
+            data.useSubTitle = false;
+        }
+        data.query = (char *)strQuery.c_str();
+        data.mode = 0;
+        data.channelNr = 0;
+        data.useTitle = true;
+        data.useDescription = false;
+        
+        if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) {
+            cList<Epgsearch_searchresults_v1_0::cServiceSearchResult>* list = data.pResultList;
+            if (!list)
+                return NULL;
+            const cEvent **searchResults = NULL;
+            int numElements = list->Count();
+            if (numElements > 0) {
+                searchResults = new const cEvent *[numElements];
+                int index = 0;
+                for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r; r = list->Next(r)) {
+                    if ((event->ChannelID() == r->event->ChannelID()) && (event->StartTime() == r->event->StartTime()))
+                        continue;
+                    searchResults[index] = r->event;
+                    index++;
+                }
+                delete list;
+                numResults = index;
+                return searchResults;
+            }
+        }
+    }
+    return NULL;
+}
+
+void cRecManager::GetFavorites(std::vector<cTVGuideSearchTimer> *favorites) {
+    if (!epgSearchAvailable) {
+            return;
+    }
+    Epgsearch_services_v1_1 *epgSearch = new Epgsearch_services_v1_1;
+    if (epgSearchPlugin->Service("Epgsearch-services-v1.1", epgSearch)) {
+        std::list<std::string> searchTimerList;
+        searchTimerList = epgSearch->handler->SearchTimerList();
+        for(std::list<std::string>::iterator it = searchTimerList.begin(); it != searchTimerList.end(); it++) {
+            cTVGuideSearchTimer timer;
+            timer.SetEPGSearchString(it->c_str());
+            if (timer.Parse()) {
+                if (timer.UseInFavorites())
+                    favorites->push_back(timer);
+            }
+        }
+    }
+
+}
+
+const cEvent **cRecManager::WhatsOnNow(bool nowOrNext, int &numResults) {
+    std::vector<const cEvent*> tmpResults;
+    cSchedulesLock schedulesLock;
+    const cSchedules *schedules = cSchedules::Schedules(schedulesLock);
+    const cChannel *startChannel = NULL, *stopChannel = NULL;
+    if (tvguideConfig.favLimitChannels) {
+        startChannel = Channels.GetByNumber(tvguideConfig.favStartChannel);
+        stopChannel = Channels.GetByNumber(tvguideConfig.favStopChannel);
+    }
+    if (!startChannel)
+        startChannel = Channels.First();
+
+    for (const cChannel *channel = startChannel; channel; channel = Channels.Next(channel)) {
+        if (channel->GroupSep()) continue;
+        const cSchedule *Schedule = schedules->GetSchedule(channel);
+        if (!Schedule) continue;
+
+        const cEvent *event = NULL;
+        if (nowOrNext)
+            event = Schedule->GetPresentEvent();
+        else
+            event = Schedule->GetFollowingEvent();
+        if (event) {
+            tmpResults.push_back(event);
+        }
+        if (stopChannel && (stopChannel->Number() <= channel->Number()))
+            break;
+    }
+    numResults = tmpResults.size();
+    const cEvent **results = new const cEvent *[numResults];
+    for (int i=0; i<numResults; i++) {
+        results[i] = tmpResults[i];        
+    }
+
+    return results;
+}
+
+const cEvent **cRecManager::UserDefinedTime(int userTime, int &numResults) {
+    std::vector<const cEvent*> tmpResults;
+    int favTime = 0;
+    if (userTime == 1) {
+        favTime = tvguideConfig.favTime1;
+    } else if (userTime == 2) {
+        favTime = tvguideConfig.favTime2;
+    } else if (userTime == 3) {
+        favTime = tvguideConfig.favTime3;
+    } else if (userTime == 4) {
+        favTime = tvguideConfig.favTime4;
+    }
+
+    time_t now = time(0);
+    tm *midn = localtime(&now);
+    midn->tm_sec = 0;
+    midn->tm_min = 0;
+    midn->tm_hour = 0;
+    time_t midnight = mktime(midn);
+    int hours = favTime/100;
+    int mins = favTime - hours * 100;
+    time_t searchTime = midnight + hours*60*60 + mins*60;
+    if (searchTime < now)
+        searchTime += 24*60*60;
+
+    cSchedulesLock schedulesLock;
+    const cSchedules *schedules = cSchedules::Schedules(schedulesLock);
+    const cChannel *startChannel = NULL, *stopChannel = NULL;
+    if (tvguideConfig.favLimitChannels) {
+        startChannel = Channels.GetByNumber(tvguideConfig.favStartChannel);
+        stopChannel = Channels.GetByNumber(tvguideConfig.favStopChannel);
+    }
+    if (!startChannel)
+        startChannel = Channels.First();
+
+    for (const cChannel *channel = startChannel; channel; channel = Channels.Next(channel)) {
+        if (channel->GroupSep()) continue;
+        const cSchedule *Schedule = schedules->GetSchedule(channel);
+        if (!Schedule) continue;
+        const cEvent *event = Schedule->GetEventAround(searchTime);
+        if (!event) continue;
+        //if event is more or less over (only 15mns left), take next
+        if ((event->EndTime() - searchTime) < 15*60) {
+            event = Schedule->Events()->Next(event);
+        }
+        if (event)
+            tmpResults.push_back(event);
+        if (stopChannel && (stopChannel->Number() <= channel->Number()))
+            break;
+    }
+
+    numResults = tmpResults.size();
+    const cEvent **results = new const cEvent *[numResults];
+    for (int i=0; i<numResults; i++) {
+        results[i] = tmpResults[i];        
+    }
+    return results;
+}
diff --git a/recmanager.h b/recmanager.h
new file mode 100644
index 0000000..a144071
--- /dev/null
+++ b/recmanager.h
@@ -0,0 +1,63 @@
+#ifndef __TVGUIDE_RECMMANAGER_H
+#define __TVGUIDE_RECMMANAGER_H
+
+#include <string>
+#include <vector>
+#include <vdr/plugin.h>
+#include "services/epgsearch.h"
+#include "detailview.h"
+#include "recmenu.h"
+#include "searchtimer.h"
+#include "switchtimer.h"
+#include "timerconflict.h"
+
+struct TVGuideEPGSearchTemplate {
+public:
+    std::string name;
+    std::string templValue;
+};
+
+// --- cRecManager  -------------------------------------------------------------
+class cRecManager   {
+private:
+    cPlugin *epgSearchPlugin;
+    bool epgSearchAvailable;
+public:
+    cRecManager(void);
+    void SetEPGSearchPlugin(void);
+    bool EpgSearchAvailable(void) {return epgSearchAvailable;};
+    bool RefreshRemoteTimers(void);
+    bool CheckEventForTimer(const cEvent *event);
+    cTimer *GetTimerForEvent(const cEvent *event);
+    cTimer *createTimer(const cEvent *event, std::string path = "");
+    cTimer *createLocalTimer(const cEvent *event, std::string path);
+    cTimer *createRemoteTimer(const cEvent *event, std::string path);
+    void SetTimerPath(cTimer *timer, const cEvent *event, std::string path);
+    void DeleteTimer(cTimer *timer);
+    void DeleteTimer(int timerID);
+    void DeleteTimer(const cEvent *event);
+    void DeleteLocalTimer(const cEvent *event);
+    void DeleteRemoteTimer(const cEvent *event);
+    void SaveTimer(cTimer *timer, cTimer newTimerSettings);
+    bool IsRecorded(const cEvent *event);
+    cTVGuideTimerConflicts *CheckTimerConflict(void);
+    void CreateSeriesTimer(cTimer *seriesTimer);
+    const cEvent **PerformSearchTimerSearch(std::string epgSearchString, int &numResults);
+    const cEvent **PerformSearch(Epgsearch_searchresults_v1_0 data, int &numResults);
+    void ReadEPGSearchTemplates(std::vector<TVGuideEPGSearchTemplate> *epgTemplates);
+    void GetSearchTimers(std::vector<cTVGuideSearchTimer> *timers);
+    int CreateSearchTimer(std::string epgSearchString);
+    bool SaveSearchTimer(cTVGuideSearchTimer *searchTimer);
+    void DeleteSearchTimer(cTVGuideSearchTimer *searchTimer, bool delTimers);
+    void UpdateSearchTimers(void);
+    bool CreateSwitchTimer(const cEvent *event, cSwitchTimer switchTimer);
+    void DeleteSwitchTimer(const cEvent *event);
+    cRecording **SearchForRecordings(std::string searchString, int &numResults);
+    const cEvent **LoadReruns(const cEvent *event, int &numResults);
+    void GetFavorites(std::vector<cTVGuideSearchTimer> *favorites);
+    const cEvent **WhatsOnNow(bool nowOrNext, int &numResults);
+    const cEvent **UserDefinedTime(int userTime, int &numResults);
+    virtual ~cRecManager  (void);
+};
+
+#endif //__TVGUIDE_RECMMANAGER_H
\ No newline at end of file
diff --git a/recmenu.c b/recmenu.c
new file mode 100644
index 0000000..1c8166c
--- /dev/null
+++ b/recmenu.c
@@ -0,0 +1,695 @@
+#include <list>
+#include "recmenu.h"
+
+// --- cRecMenu  -------------------------------------------------------------
+
+cRecMenu::cRecMenu(void) {
+    border = geoManager.borderRecMenus;
+    height = 2*border;
+    headerHeight = 0;
+    footerHeight = 0;
+    currentHeight = 0;
+    deleteMenuItems = true;
+    scrollable = false;
+    scrollbarWidth = 3 * border;
+    pixmapScrollBar = NULL;
+    imgScrollBar = NULL;
+    startIndex = 0;
+    stopIndex = 0;
+    numItems = 0;
+    header = NULL;
+    footer = NULL;
+}
+
+cRecMenu::~cRecMenu(void) {
+    if (header)
+        delete header;
+    ClearMenuItems(true);
+    if (footer)
+        delete footer;
+    if (pixmapScrollBar)
+        osdManager.releasePixmap(pixmapScrollBar);
+    if (imgScrollBar)
+        delete imgScrollBar;
+}
+
+void cRecMenu::SetWidthPercent(int percentOSDWidth) {
+    width = geoManager.osdWidth * percentOSDWidth / 100; 
+    x = (geoManager.osdWidth - width) / 2;
+}
+
+void cRecMenu::SetWidthPixel(int pixel) {
+    width = pixel;
+    x = (geoManager.osdWidth - width) / 2;
+}
+
+int cRecMenu::CalculateOptimalWidth(void) {
+    int optWidth = 0;
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        int itemWidth = (*item)->GetWidth();
+        if (itemWidth > optWidth)
+            optWidth = itemWidth;
+    }
+    return optWidth;
+}
+
+bool cRecMenu::CalculateHeight(bool reDraw) {
+    int newHeight = 2*border;
+    if (header)
+        newHeight += headerHeight;
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        newHeight += (*item)->GetHeight(); 
+    }
+    if (footer)
+        newHeight += footerHeight;
+
+    y = (geoManager.osdHeight - newHeight) / 2;
+
+    if (newHeight != height) {
+        height = newHeight;
+        if (scrollable && !reDraw) {
+            width += scrollbarWidth + border;
+        }
+        return true;
+    }
+    return false;
+}
+
+void cRecMenu::CreatePixmap(void) {
+    if (pixmap)
+        osdManager.releasePixmap(pixmap);
+    pixmap = osdManager.requestPixmap(3, cRect(x, y, width, height));
+    if (scrollable) {
+        int scrollBarX = x + width - scrollbarWidth - border;
+        int scrollBarY = y + border + headerHeight;
+        int scrollBarHeight = height - headerHeight - footerHeight - 2 * border;
+        if (pixmapScrollBar)
+            osdManager.releasePixmap(pixmapScrollBar);
+        pixmapScrollBar = osdManager.requestPixmap(4, cRect(scrollBarX, scrollBarY, scrollbarWidth, scrollBarHeight));
+    } else 
+        pixmapScrollBar = NULL;
+}
+
+void cRecMenu::SetHeader(cRecMenuItem *header) { 
+    this->header = header; 
+    headerHeight = header->GetHeight();
+    height += headerHeight;
+}
+
+void cRecMenu::SetFooter(cRecMenuItem *footer) {
+    this->footer = footer;
+    footerHeight = footer->GetHeight();
+    height += footerHeight;
+}
+
+void cRecMenu::ClearMenuItems(bool destructor) { 
+    for (std::list<cRecMenuItem*>::iterator it = menuItems.begin(); it != menuItems.end(); it++) {
+        if (deleteMenuItems)
+            delete *it;
+        else if (!destructor)
+            (*it)->Hide();
+    }
+    menuItems.clear();
+};
+
+void cRecMenu::InitMenu(bool complete) {
+    currentHeight = 0;
+    numItems = 0;
+    if (scrollable) {
+        width -= scrollbarWidth + border;
+        osdManager.releasePixmap(pixmapScrollBar);
+        pixmapScrollBar = NULL;
+        delete imgScrollBar;
+        imgScrollBar = NULL;
+    }
+    osdManager.releasePixmap(pixmap);
+    pixmap = NULL;
+    for (std::list<cRecMenuItem*>::iterator it = menuItems.begin(); it != menuItems.end(); it++) {
+        if (deleteMenuItems)
+            delete *it;
+        else
+            (*it)->Hide();
+    }
+    menuItems.clear();
+    if (complete) {
+        startIndex = 0;
+        stopIndex = 0;
+        scrollable = false;
+    } else {
+        stopIndex = startIndex;
+    }
+
+}
+
+
+void cRecMenu::AddMenuItem(cRecMenuItem *item, bool inFront) {
+    item->Show();
+    if (!inFront)
+        menuItems.push_back(item);
+    else
+        menuItems.push_front(item);
+}
+
+bool cRecMenu::AddMenuItemInitial(cRecMenuItem *item, bool inFront) {
+    currentHeight += item->GetHeight();
+    int totalHeight = headerHeight + footerHeight + currentHeight + 2*border;
+    if (totalHeight >= geoManager.osdHeight - 10) {
+        scrollable = true;
+        currentHeight -= item->GetHeight();
+        if (deleteMenuItems) {
+            delete item;
+        }
+        return false;
+    }
+    numItems++;
+    if (!inFront) {
+        stopIndex++;
+        menuItems.push_back(item);
+    } else {
+        startIndex--;
+        menuItems.push_front(item);
+    }
+    return true;
+}
+
+void cRecMenu::Activate(cRecMenuItem *itemOld, cRecMenuItem *item) {
+    itemOld->setInactive();
+    itemOld->setBackground();
+    itemOld->Draw();
+    item->setActive();
+    item->setBackground();
+    item->Draw();
+}
+
+bool cRecMenu::ActivatePrev(void) {
+    cRecMenuItem *activeItem = GetActiveMenuItem();
+    if (!scrollable && footer && footer->isActive()) {
+        if (menuItems.size() > 0) {
+            cRecMenuItem *itemLast = menuItems.back();
+            Activate(footer, itemLast);
+            return true;
+        }
+    } else if (activeItem) {
+        cRecMenuItem *prev = NULL;
+        bool foundActive = false;
+        for (std::list<cRecMenuItem*>::iterator item = menuItems.end(); item != menuItems.begin(); ) {
+            item--;
+            if (*item == activeItem) {
+                foundActive = true;
+                continue;
+            }
+            if (!foundActive)
+                continue;
+            if ((*item)->isSelectable()) {
+                prev = *item;
+                break;
+            }
+        }    
+        if (prev) {
+            Activate(activeItem , prev);
+            return true;
+        }
+    }
+    return false;
+}
+
+bool cRecMenu::ScrollUp(void) {
+    if (footer && footer->isActive()) {
+        if (menuItems.size() > 0)
+            Activate(footer, menuItems.back());
+    } else {
+        //get perv x items
+        int numNewItems = numItems / 2;
+        int numAdded = 0;
+        cRecMenuItem *newItem = NULL;
+        while (newItem = GetMenuItem(startIndex-1)) {
+            AddMenuItem(newItem, true);
+            cRecMenuItem *last = menuItems.back();
+            if (deleteMenuItems) {
+                delete last;
+            } else {
+                last->setInactive();
+                last->Hide();
+            }
+            menuItems.pop_back();
+            stopIndex--;
+            startIndex--;
+            numAdded++;
+            if (numAdded >= numNewItems)
+                break;
+        }
+        if (numAdded != 0) {
+            scrollable = true;
+            if (CalculateHeight(true))
+                CreatePixmap();
+            Arrange(deleteMenuItems);
+            Display(deleteMenuItems);
+            ActivatePrev();
+        } else {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool cRecMenu::ActivateNext(void) {
+    cRecMenuItem *activeItem = GetActiveMenuItem();
+    if (activeItem) {
+        cRecMenuItem *next = NULL;
+        bool foundActive = false;
+        for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+            if (*item == activeItem) {
+                foundActive = true;
+                continue;
+            }
+            if (!foundActive)
+                continue;
+            if ((*item)->isSelectable()) {
+                next = *item;
+                break;
+            }
+        }    
+        if (next) {
+            Activate(activeItem , next);
+            return true;
+        } else if (!scrollable && footer && footer->isSelectable() && !footer->isActive()) {
+            Activate(activeItem , footer);
+            return true;
+        }
+    } 
+    return false;
+}
+
+bool cRecMenu::ScrollDown(void) {
+    //get next x items
+    int numNewItems = numItems / 2;
+    int numAdded = 0;
+    cRecMenuItem *newItem = NULL;
+    while (newItem = GetMenuItem(stopIndex)) {
+        menuItems.push_back(newItem);
+        cRecMenuItem *first = menuItems.front();
+        if (deleteMenuItems) {
+            delete first;
+        } else {
+            first->setInactive();
+            first->Hide();
+        }
+        menuItems.pop_front();
+        startIndex++;
+        stopIndex++;
+        numAdded++;
+        if (numAdded >= numNewItems)
+            break;
+    }
+    if (numAdded != 0) {
+        scrollable = true;
+        if (CalculateHeight(true))
+            CreatePixmap();
+        Arrange(deleteMenuItems);
+        Display(deleteMenuItems);
+        ActivateNext();
+    } else {
+        //last item reached, activate footer if not already active
+        if ((footer) && !(footer->isActive())) {
+            cRecMenuItem *activeItem = GetActiveMenuItem();
+            Activate(activeItem , footer);
+        } else {
+            return false;
+        }
+    }
+    return true;
+}
+
+void cRecMenu::PageUp(void) {
+    cRecMenuItem *activeItem = GetActiveMenuItem();
+    if (!activeItem)
+        return;
+    if (!scrollable) {
+        JumpBegin();
+        return;
+    }
+    if (footer && activeItem == footer) {
+        Activate(footer, menuItems.front());
+        return;
+    }
+    int newActive = GetActive() - numItems;
+    if (newActive < 0)
+        newActive = 0;
+    activeItem->setInactive();
+    activeItem->setBackground();
+    ClearMenuItems();
+    currentHeight = 0;
+    stopIndex = startIndex;
+    numItems = 0;
+    cRecMenuItem *newItem = NULL;
+    bool spaceLeft = true;
+    while (newItem = GetMenuItem(startIndex-1)) {
+        if (startIndex-1 == newActive)
+            newItem->setActive();
+        spaceLeft = AddMenuItemInitial(newItem, true);
+        if (!spaceLeft)
+            break;
+    }
+    if (spaceLeft) {
+        while (newItem = GetMenuItem(stopIndex)) {
+            spaceLeft = AddMenuItemInitial(newItem);
+            if (!spaceLeft)
+                break;
+        }
+    }
+    if (GetActive() == numItems)
+            menuItems.front()->setActive();
+    if (CalculateHeight(true))
+        CreatePixmap();
+    Arrange(deleteMenuItems);
+    Display(deleteMenuItems);
+}
+
+void cRecMenu::PageDown(void) {
+    cRecMenuItem *activeItem = GetActiveMenuItem();
+    if (!activeItem)
+        return;
+    if (footer && activeItem == footer) {
+        return;
+    }
+    if (!scrollable) {
+        JumpEnd();
+        return;
+    }
+    int newActive = GetActive() + numItems;
+    activeItem->setInactive();
+    activeItem->setBackground();
+    ClearMenuItems();
+    currentHeight = 0;
+    numItems = 0;
+    startIndex = stopIndex;
+    cRecMenuItem *newItem = NULL;
+    bool spaceLeft = true;
+    while (newItem = GetMenuItem(stopIndex)) {
+        if (stopIndex == newActive)
+            newItem->setActive();
+        spaceLeft = AddMenuItemInitial(newItem);
+        if (!spaceLeft)
+            break;
+    }
+    if (spaceLeft) {
+        while (newItem = GetMenuItem(startIndex-1)) {
+            spaceLeft = AddMenuItemInitial(newItem, true);
+            if (!spaceLeft)
+                break;
+        }
+    }
+    if (GetActive() == GetTotalNumMenuItems())
+            menuItems.back()->setActive();
+    if (CalculateHeight(true))
+        CreatePixmap();
+    Arrange(deleteMenuItems);
+    Display(deleteMenuItems);
+}
+
+void cRecMenu::JumpBegin(void) {
+    cRecMenuItem *activeItem = GetActiveMenuItem();
+    if (!scrollable) {
+        cRecMenuItem *firstSelectable= NULL;
+        for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+            if ((*item)->isSelectable()) {
+                firstSelectable = *item;
+                break;
+            }
+        }
+        if (activeItem && firstSelectable) {
+            Activate(activeItem , firstSelectable);
+        }
+    } else {
+        activeItem->setInactive();
+        activeItem->setBackground();
+        if (footer)
+            footer->Draw();
+        ClearMenuItems();
+        int currentItem = 0;
+        cRecMenuItem *newItem = NULL;
+        while (newItem = GetMenuItem(currentItem)) {
+            AddMenuItem(newItem);
+            currentItem++;
+            if (currentItem >= numItems)
+                break;
+        }
+        Arrange(true);
+        startIndex = 0;
+        stopIndex = numItems-1;
+        cRecMenuItem *first = menuItems.front();
+        first->setActive();
+        first->setBackground();
+        first->Draw();
+        Display(true);    
+    }
+}
+
+void cRecMenu::JumpEnd(void) {
+    cRecMenuItem *activeItem = GetActiveMenuItem();
+    if (!activeItem)
+        return;
+    if (!scrollable) {
+        cRecMenuItem *lastSelectable= NULL;
+        if (footer && footer->isSelectable()) {
+            lastSelectable = footer;
+        } else {
+            for (std::list<cRecMenuItem*>::iterator item = menuItems.end(); item != menuItems.begin(); ) {
+                item--;
+                if ((*item)->isSelectable()) {
+                    lastSelectable = *item;
+                    break;
+                }
+            }
+        }
+        if (lastSelectable) {
+            Activate(activeItem , lastSelectable);
+        }
+    } else {
+        activeItem->setInactive();
+        activeItem->setBackground();
+        ClearMenuItems();
+        int totalNumItems = GetTotalNumMenuItems();
+        int currentItem = totalNumItems-1;
+        int itemsAdded = 0;
+        cRecMenuItem *newItem = NULL;
+        while (newItem = GetMenuItem(currentItem)) {
+            AddMenuItem(newItem, true);
+            currentItem--;
+            itemsAdded++;
+            if (itemsAdded >= numItems)
+                break;
+        }
+        Arrange(true);
+        stopIndex = totalNumItems;
+        startIndex = stopIndex - numItems;
+        if (footer) {
+            footer->setActive();
+            footer->setBackground();
+            footer->Draw();
+        } else {
+            cRecMenuItem *last = menuItems.back();
+            last->setActive();
+            last->setBackground();
+            last->Draw();
+        }
+        Display(true);
+    }
+}
+
+void cRecMenu::Arrange(bool scroll) {
+    int xElement = x + border;
+    int yElement = y + border;
+    int widthElement = width - 2 * border;
+    if (scrollable)
+        widthElement -= scrollbarWidth + border;
+
+    if (header) {
+        if (!scroll) {
+            header->SetGeometry(xElement, yElement, widthElement);
+            header->SetPixmaps();
+            header->setBackground();
+        }
+        yElement += header->GetHeight();
+    }
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        (*item)->SetGeometry(xElement, yElement, widthElement);
+        (*item)->SetPixmaps();
+        yElement += (*item)->GetHeight();
+    }
+    if (footer && !scroll) {
+        footer->SetGeometry(xElement, yElement, widthElement);
+        footer->SetPixmaps();
+        footer->setBackground();
+    }
+}
+
+void cRecMenu::Display(bool scroll) {
+    if (tvguideConfig.style == eStyleGraphical) {
+        drawBackgroundGraphical(bgRecMenuBack);
+    } else {
+        pixmap->Fill(theme.Color(clrBackground));
+        drawBorder();
+    }
+    if (header && !scroll) {
+        header->setBackground();
+        header->Draw();
+    }
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        (*item)->setBackground();
+        (*item)->Show();
+        (*item)->Draw();
+    }
+    if (footer && !scroll) {
+        footer->setBackground();
+        footer->Draw();
+    }
+    if (scrollable)
+        DrawScrollBar();
+}
+
+void cRecMenu::Hide(void) {
+    pixmap->SetLayer(-1);
+    if (pixmapScrollBar)
+        pixmapScrollBar->SetLayer(-1);
+    if (header)
+        header->Hide();
+    if (footer)
+        footer->Hide();
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        (*item)->Hide();
+    }
+}
+
+void cRecMenu::Show(void) {
+    pixmap->SetLayer(3);
+    if (pixmapScrollBar)
+        pixmapScrollBar->SetLayer(3);
+    if (header)
+        header->Show();
+    if (footer)
+        footer->Show();
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        (*item)->Show();
+    }
+}
+
+void cRecMenu::UpdateActiveMenuItem(void) {
+    cRecMenuItem *activeItem = GetActiveMenuItem();
+    if (activeItem)
+        activeItem->Draw();   
+}
+
+
+void cRecMenu::DrawScrollBar(void) {
+    pixmapScrollBar->Fill(theme.Color(clrBorder));
+    pixmapScrollBar->DrawRectangle(cRect(2,2,pixmapScrollBar->ViewPort().Width()-4, pixmapScrollBar->ViewPort().Height() - 4), theme.Color(clrBackground));
+    
+    int totalNumItems = GetTotalNumMenuItems();
+    if (imgScrollBar == NULL) {
+        int scrollBarImgHeight = (pixmapScrollBar->ViewPort().Height() - 8) * numItems / totalNumItems;
+        imgScrollBar = createScrollbar(pixmapScrollBar->ViewPort().Width()-8, scrollBarImgHeight, theme.Color(clrHighlight), theme.Color(clrHighlightBlending));
+    }
+    int offset = (pixmapScrollBar->ViewPort().Height() - 8) * startIndex / totalNumItems;
+    pixmapScrollBar->DrawImage(cPoint(4, 2 + offset), *imgScrollBar);
+}
+
+cRecMenuItem *cRecMenu::GetActiveMenuItem(void) {
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        if ((*item)->isActive())
+            return *item;
+    }
+    if (footer && footer->isActive())
+        return footer;
+    return NULL;
+}
+
+cRecMenuItem *cRecMenu::GetMenuItemAt(int num) {
+    int current = 0;
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        if (current == num)
+            return *item;
+        current++;
+    }
+    return NULL;
+}
+
+int cRecMenu::GetActive(void) {
+    int numActive = startIndex;
+    for (std::list<cRecMenuItem*>::iterator item = menuItems.begin(); item != menuItems.end(); item++) {
+        if ((*item)->isActive()) {
+            break;
+        }
+        numActive++;
+    }
+    return numActive;
+}
+
+eRecMenuState cRecMenu::ProcessKey(eKeys Key) {
+    cRecMenuItem *activeItem = GetActiveMenuItem();
+    eRecMenuState state = rmsContinue;
+    if (!activeItem)
+        return state;
+
+    state = activeItem->ProcessKey(Key);
+    if (state == rmsRefresh) {
+        CreateMenuItems();
+        Display();
+    } else if (state == rmsNotConsumed) {
+        switch (Key & ~k_Repeat) {
+            case kUp:       
+                if (!ActivatePrev())
+                    if (!ScrollUp())
+                        JumpEnd();
+                state = rmsConsumed;
+                break;
+            case kDown:
+                if (!ActivateNext())
+                    if (!ScrollDown())
+                        JumpBegin();
+                state = rmsConsumed;
+                break;
+            case kLeft:
+                PageUp();
+                state = rmsConsumed;
+                break;
+            case kRight:
+                PageDown();
+                state = rmsConsumed;
+                break;
+            default:
+                break;
+        }
+    }
+    return state;
+}
+
+cImage *cRecMenu::createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend) {
+    cImage *image = new cImage(cSize(width, height));
+    image->Fill(clrBgr);
+    if (tvguideConfig.style != eStyleFlat) {
+        int numSteps = 64;
+        int alphaStep = 0x03;
+        if (height < 30)
+            return image;
+        else if (height < 100) {
+            numSteps = 32;
+            alphaStep = 0x06;
+        }
+        int stepY = 0.5*height / numSteps;
+        if (stepY == 0)
+            stepY = 1;
+        int alpha = 0x40;
+        tColor clr;
+        for (int i = 0; i<numSteps; i++) {
+            clr = AlphaBlend(clrBgr, clrBlend, alpha);
+            for (int y = i*stepY; y < (i+1)*stepY; y++) {
+                for (int x=0; x<width; x++) {
+                    image->SetPixel(cPoint(x,y), clr);
+                }
+            }
+            alpha += alphaStep;
+        }
+    }
+    return image;
+}
\ No newline at end of file
diff --git a/recmenu.h b/recmenu.h
new file mode 100644
index 0000000..eb819ee
--- /dev/null
+++ b/recmenu.h
@@ -0,0 +1,66 @@
+#ifndef __TVGUIDE_RECMENU_H
+#define __TVGUIDE_RECMENU_H
+
+#include "recmenuitem.h"
+
+// --- cRecMenu  -------------------------------------------------------------
+
+class cRecMenu : public cStyledPixmap {
+private:
+    std::list<cRecMenuItem*> menuItems;
+    int scrollbarWidth;
+    int numItems;
+    int startIndex, stopIndex;
+    void Activate(cRecMenuItem *itemOld, cRecMenuItem *item);
+    bool ActivateNext(void);
+    bool ActivatePrev(void);
+    bool ScrollUp(void);
+    bool ScrollDown(void);
+    void PageUp(void);
+    void PageDown(void);
+    void JumpBegin(void);
+    void JumpEnd(void);
+protected:
+    int x, y;
+    int width, height;
+    int headerHeight, footerHeight;
+    int currentHeight;
+    bool deleteMenuItems;
+    cPixmap *pixmapScrollBar;
+    cImage *imgScrollBar;
+    int border;
+    bool scrollable;
+    cRecMenuItem *header;
+    cRecMenuItem *footer;
+    void SetWidthPercent(int percentOSDWidth);
+    void SetWidthPixel(int pixel);
+    int CalculateOptimalWidth(void);
+    bool CalculateHeight(bool reDraw = false);
+    void CreatePixmap(void);
+    void SetHeader(cRecMenuItem *header);
+    void SetFooter(cRecMenuItem *footer);
+    void ClearMenuItems(bool destructor = false);
+    void InitMenu(bool complete);
+    bool AddMenuItemInitial(cRecMenuItem *item, bool inFront = false);
+    void AddMenuItem(cRecMenuItem *item, bool inFront = false);
+    void DrawScrollBar(void);
+    cImage *createScrollbar(int width, int height, tColor clrBgr, tColor clrBlend);
+    void Arrange(bool scroll = false);
+    virtual cRecMenuItem *GetMenuItem(int number) { return NULL; };
+    cRecMenuItem *GetActiveMenuItem(void);
+    cRecMenuItem *GetMenuItemAt(int num);
+    int GetCurrentNumMenuItems(void) { return menuItems.size(); };
+    virtual int GetTotalNumMenuItems(void) { return 0; };
+    virtual void CreateMenuItems(void) {};
+    int GetStartIndex(void) { return startIndex; };
+    int GetActive(void);
+public:
+    cRecMenu(void);
+    virtual ~cRecMenu(void);
+    void Display(bool scroll = false);
+    void Hide(void);
+    void Show(void);
+    void UpdateActiveMenuItem(void);
+    virtual eRecMenuState ProcessKey(eKeys Key);
+};
+#endif //__TVGUIDE_RECMENU_H
\ No newline at end of file
diff --git a/recmenuitem.c b/recmenuitem.c
new file mode 100644
index 0000000..6e4d31f
--- /dev/null
+++ b/recmenuitem.c
@@ -0,0 +1,2902 @@
+#include <math.h>
+#include <vdr/remote.h>
+#include "imageloader.h"
+#include "imagecache.h"
+#include "tools.h"
+#include "recmenus.h"
+#include "recmenuitem.h"
+
+// --- cRecMenuItem  -------------------------------------------------------------
+
+cRecMenuItem::cRecMenuItem(void) {
+    height = 0;
+    action = rmsNotConsumed;
+    defaultBackground = true;
+    drawn = false;
+    font = fontManager.FontRecMenuItem;
+    fontSmall = fontManager.FontRecMenuItemSmall;
+    fontLarge = fontManager.FontRecMenuItemLarge;
+}
+
+cRecMenuItem::~cRecMenuItem(void) {
+}
+
+void cRecMenuItem::SetGeometry(int x, int y, int width) {
+    this->x = x;
+    this->y = y;
+    this->width = width;
+    
+}
+
+void cRecMenuItem::SetPixmaps(void) {
+    if (!pixmap)
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+    else
+        pixmap->SetViewPort(cRect(x, y, width, height));
+}
+
+void cRecMenuItem::setBackground(void) {
+    if (tvguideConfig.style == eStyleGraphical) {
+        if (defaultBackground) {
+            drawBackgroundGraphical(bgButton, active);
+        }
+        colorTextBack = clrTransparent;
+        colorText = (active)?theme.Color(clrFontActive):theme.Color(clrFont);
+    } else {
+        if (active) {
+            color = theme.Color(clrHighlight);
+            colorBlending = theme.Color(clrHighlightBlending);
+            colorText = theme.Color(clrFontActive);
+        } else {
+            color = theme.Color(clrGrid1);
+            colorBlending = theme.Color(clrGrid1Blending);
+            colorText = theme.Color(clrFont);
+        }
+        colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+        if (defaultBackground) {
+            drawBackground();
+            drawBorder();
+        }
+    }
+}
+
+// --- cRecMenuItemButton  -------------------------------------------------------
+
+cRecMenuItemButton::cRecMenuItemButton(const char *text, eRecMenuState action, bool active, bool halfWidth, bool alignLeft, bool largeFont) {
+    selectable = true;
+    this->text = text;
+    this->action = action;
+    this->active = active;
+    fontButtons = (largeFont)?fontLarge:font;
+    height = 3 * fontButtons->Height() / 2;
+    this->halfWidth = halfWidth;
+    this->alignLeft = alignLeft;
+    pixmapText = NULL;
+}
+
+cRecMenuItemButton::~cRecMenuItemButton(void) {
+    if (pixmapText)
+        osdManager.releasePixmap(pixmapText);
+}
+
+int cRecMenuItemButton::GetWidth(void) {
+    return fontButtons->Width(*text);    
+}
+
+void cRecMenuItemButton::SetPixmaps(void) {
+    if (halfWidth) {
+        x += width / 4;
+        width = width / 2;
+    }
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapText->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemButton::Draw(void) {
+    pixmapText->Fill(clrTransparent);
+    int y = (height - fontButtons->Height()) / 2;
+    int x;
+    if (!alignLeft)
+        x = (width - fontButtons->Width(*text)) / 2;
+    else
+        x = 10;
+    pixmapText->DrawText(cPoint(x, y), *text, colorText, colorTextBack, fontButtons);
+}
+
+void cRecMenuItemButton::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapText) pixmapText->SetLayer(-1);
+}
+
+void cRecMenuItemButton::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapText) pixmapText->SetLayer(5);
+}
+
+eRecMenuState cRecMenuItemButton::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kOk:
+            return action;
+            break;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+
+// --- cRecMenuItemButtonYesNo  -------------------------------------------------------
+cRecMenuItemButtonYesNo::cRecMenuItemButtonYesNo(cString textYes,
+                                                 cString textNo,
+                                                 eRecMenuState actionYes, 
+                                                 eRecMenuState actionNo,
+                                                 bool active) {
+    selectable = true;
+    this->textYes = textYes;
+    this->textNo = textNo;
+    this->action = actionYes;
+    this->actionNo = actionNo;
+    this->active = active;
+    yesActive = true;
+    height = 3 * font->Height() / 2;
+    pixmapNo = NULL;
+}
+
+cRecMenuItemButtonYesNo::~cRecMenuItemButtonYesNo(void) {
+    if (pixmapNo)
+        delete pixmapNo;
+}
+
+void cRecMenuItemButtonYesNo::SetPixmaps(void) {
+    int buttonWidth = 44 * width / 100;
+    int yesX = x + width / 25;
+    int noX = x + 52 * width / 100;
+    int yPixmaps = y + geoManager.borderRecMenus / 2;
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(yesX, yPixmaps, buttonWidth, height));
+        pixmapNo = new cStyledPixmap(osdManager.requestPixmap(4, cRect(noX, yPixmaps, buttonWidth, height)));    
+    } else {
+        pixmap->SetViewPort(cRect(yesX, yPixmaps, buttonWidth, height));
+        pixmapNo->SetViewPort(cRect(noX, yPixmaps, buttonWidth, height));
+    }
+}
+
+void cRecMenuItemButtonYesNo::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapNo) pixmapNo->SetLayer(-1);
+}
+
+void cRecMenuItemButtonYesNo::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapNo) pixmapNo->SetLayer(4);
+}
+
+void cRecMenuItemButtonYesNo::setBackground() {
+    if (tvguideConfig.style == eStyleGraphical) {
+        drawBackgroundGraphical(bgButton, yesActive&&active);
+        colorTextBack = clrTransparent;
+        colorTextNoBack = clrTransparent;
+        colorText = (active&&yesActive)?theme.Color(clrFontActive):theme.Color(clrFont);
+        colorTextNo = (active&&!yesActive)?theme.Color(clrFontActive):theme.Color(clrFont);
+        pixmapNo->drawBackgroundGraphical(bgButton, active&&!yesActive);
+    } else {
+        tColor colorNoBack;
+        if (active) {
+            if (yesActive) {
+                color = theme.Color(clrHighlight);
+                colorBlending = theme.Color(clrHighlightBlending);
+                colorText = theme.Color(clrFontActive);
+                colorNoBack = theme.Color(clrGrid1);
+                pixmapNo->setColor( colorNoBack,
+                                    theme.Color(clrGrid1Blending));
+                colorTextNo = theme.Color(clrFont);
+            } else {
+                color = theme.Color(clrGrid1);
+                colorBlending = theme.Color(clrGrid1Blending);
+                colorText = theme.Color(clrFont);
+                colorNoBack = theme.Color(clrHighlight);
+                pixmapNo->setColor( colorNoBack,
+                                    theme.Color(clrHighlightBlending));
+                colorTextNo = theme.Color(clrFontActive);
+            }
+        } else {
+            color = theme.Color(clrGrid1);
+            colorBlending = theme.Color(clrGrid1Blending);
+            colorText = theme.Color(clrFont);
+            colorNoBack = theme.Color(clrGrid1);
+            pixmapNo->setColor( colorNoBack,
+                                theme.Color(clrGrid1Blending));
+            colorTextNo = theme.Color(clrFont);
+        }
+        colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+        colorTextNoBack = (tvguideConfig.style == eStyleFlat)?colorNoBack:clrTransparent;
+        drawBackground();
+        drawBorder();
+        pixmapNo->drawBackground();
+        pixmapNo->drawBorder();
+    }
+}
+
+void cRecMenuItemButtonYesNo::Draw(void) {
+    int textYesX = (pixmap->ViewPort().Width() - font->Width(*textYes)) / 2;
+    int textNoX = (pixmapNo->Width() - font->Width(*textNo)) / 2;
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(textYesX, textY), *textYes, colorText, colorTextBack, font);
+    pixmapNo->DrawText(cPoint(textNoX, textY), *textNo, colorTextNo, colorTextNoBack, font);
+}
+
+eRecMenuState cRecMenuItemButtonYesNo::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+            if (!yesActive) {
+                yesActive = true;
+                setBackground();
+                Draw();
+                return rmsConsumed;
+            } else
+                return rmsNotConsumed;
+            break;
+        case kRight:
+            if (yesActive) {
+                yesActive = false;
+                setBackground();
+                Draw();
+                return rmsConsumed;
+            } else
+                return rmsNotConsumed;
+            break;
+        case kOk:
+            if (yesActive)
+                return action;
+            return actionNo;
+            break;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemInfo  -------------------------------------------------------
+cRecMenuItemInfo::cRecMenuItemInfo(const char *text, bool largeFont) {
+    selectable = false;
+    active = false;
+    this->text = text;
+    fontInfo = (largeFont) ? fontLarge : font;
+    border = 10;
+}
+
+cRecMenuItemInfo::~cRecMenuItemInfo(void) {
+}
+
+void cRecMenuItemInfo::CalculateHeight(int textWidth) {
+    wrapper.Set(*text, fontInfo, textWidth);
+    height = fontInfo->Height() * wrapper.Lines() + 2*border;
+}
+
+void cRecMenuItemInfo::setBackground(void) {
+    pixmap->Fill(clrTransparent);
+    cRecMenuItem::setBackground();
+}
+
+void cRecMenuItemInfo::Draw(void) {
+    int lines = wrapper.Lines();
+    int lineHeight = fontInfo->Height();
+    int x = 0;
+    int y = border;
+    for (int i = 0; i < lines; i++) {
+        x = (width - fontInfo->Width(wrapper.GetLine(i))) / 2;
+        pixmap->DrawText(cPoint(x,y), wrapper.GetLine(i), theme.Color(clrFont), clrTransparent, fontInfo);
+        y += lineHeight;
+    }
+}
+
+// --- cRecMenuItemInt  -------------------------------------------------------
+cRecMenuItemInt::cRecMenuItemInt(cString text,
+                                int initialVal,
+                                int minVal,
+                                int maxVal,
+                                bool active, 
+                                int *callback,
+                                eRecMenuState action) {
+    selectable = true;
+    this->text = text;
+    this->currentVal = initialVal;
+    this->minVal = minVal;
+    this->maxVal = maxVal;
+    this->active = active;
+    this->callback = callback;
+    this->action = action;
+    height = 3 * font->Height() / 2;
+    pixmapVal = NULL;
+    fresh = true;
+}
+
+cRecMenuItemInt::~cRecMenuItemInt(void) {
+    if (pixmapVal)
+        osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemInt::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapVal->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemInt::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemInt::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemInt::setBackground() {
+    cRecMenuItem::setBackground();
+    fresh = true;
+}
+
+void cRecMenuItemInt::Draw(void) {
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+    DrawValue();    
+}
+
+void cRecMenuItemInt::DrawValue(void) {
+    pixmapVal->Fill(clrTransparent);
+    cString textVal = cString::sprintf("%d", currentVal);
+    int textX = width - font->Width(*textVal) - 10;
+    int textY = (height - font->Height()) / 2;
+    pixmapVal->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font);
+}
+
+eRecMenuState cRecMenuItemInt::ProcessKey(eKeys Key) {
+    int oldValue = currentVal;
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+            fresh = true;
+            if (currentVal > minVal) {
+                currentVal--;
+                if (callback)
+                    *callback = currentVal;
+                DrawValue();
+            }
+            return rmsConsumed;
+            break;
+        case kRight:
+            fresh = true;
+            if (currentVal < maxVal) {
+                currentVal++;
+                if (callback)
+                    *callback = currentVal;
+                DrawValue();
+            }
+            return rmsConsumed;
+            break;
+        case k0 ... k9:
+            if (fresh) {
+               currentVal = 0;
+               fresh = false;
+            }
+            currentVal = currentVal * 10 + (Key - k0);
+            if (!((currentVal >= minVal) &&  (currentVal <= maxVal)))
+                currentVal = oldValue;
+            if (callback)
+                *callback = currentVal;
+            DrawValue();
+            return rmsConsumed;
+            break;
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemBool  -------------------------------------------------------
+cRecMenuItemBool::cRecMenuItemBool(cString text,
+                                   bool initialVal,
+                                   bool refresh,
+                                   bool active,
+                                   bool *callback,
+                                   eRecMenuState action) {
+    selectable = true;
+    this->text = text;
+    this->yes = initialVal;
+    this->refresh = refresh;
+    this->active = active;
+    this->callback = callback;
+    this->action = action;
+    height = 3 * font->Height() / 2;
+    pixmapVal = NULL;
+}
+
+cRecMenuItemBool::~cRecMenuItemBool(void) {
+    if (pixmapVal)
+        osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemBool::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapVal->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemBool::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemBool::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemBool::Draw(void) {
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+    DrawValue();    
+}
+
+void cRecMenuItemBool::DrawValue(void) {
+    pixmapVal->Fill(clrTransparent);
+    std::string strIcon = yes?"yes":"no";
+    int iconSize = height - 8;
+    int iconX = width - iconSize - 10;
+    int iconY = (height - iconSize) / 2;
+    
+    cImage *imgYesNo = imgCache.GetIcon(strIcon, iconSize, iconSize);
+    if (imgYesNo) {
+        pixmapVal->DrawImage(cPoint(iconX, iconY), *imgYesNo);
+    }
+}
+
+eRecMenuState cRecMenuItemBool::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+        case kRight:
+            yes = !yes;
+            if (callback)
+                *callback = yes;
+            DrawValue();
+            if (refresh)
+                return rmsRefresh;
+            else
+                return rmsConsumed;
+            break;
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemSelect  -------------------------------------------------------
+cRecMenuItemSelect::cRecMenuItemSelect(cString text,
+                                       std::vector<std::string> Strings,
+                                       int initialVal,
+                                       bool active,
+                                       int *callback,
+                                       eRecMenuState action) {
+    selectable = true;
+    this->text = text;
+    strings = Strings;
+    numValues = Strings.size();
+    if ((initialVal < 0) || (initialVal > numValues-1))
+        this->currentVal = 0;
+    else
+        this->currentVal = initialVal;
+    this->active = active;
+    this->callback = callback;
+    this->action = action;
+    height = 3 * font->Height() / 2;
+    pixmapVal = NULL;
+}
+
+cRecMenuItemSelect::~cRecMenuItemSelect(void) {
+    if (pixmapVal)
+        osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemSelect::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapVal->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemSelect::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemSelect::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemSelect::Draw(void) {
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+    DrawValue();    
+}
+
+void cRecMenuItemSelect::DrawValue(void) {
+    pixmapVal->Fill(clrTransparent);
+    std::string textVal = strings[currentVal];
+    int iconSize = min(128, height);
+    int textX = width - font->Width(textVal.c_str()) - iconSize;
+    int textY = (height - font->Height()) / 2;
+    pixmapVal->DrawText(cPoint(textX, textY), textVal.c_str(), colorText, clrTransparent, font);
+    int iconLeftX = textX - iconSize;
+    int iconRightX = width - iconSize;
+    int iconY = (height - iconSize) / 2;
+    
+    cImage *imgLeft = imgCache.GetIcon("arrow_left", iconSize, iconSize);
+    if (imgLeft) {
+        pixmapVal->DrawImage(cPoint(iconLeftX, iconY), *imgLeft);
+    }
+    cImage *imgRight = imgCache.GetIcon("arrow_right", iconSize, iconSize);
+    if (imgRight) {
+        pixmapVal->DrawImage(cPoint(iconRightX, iconY), *imgRight);
+    }
+}
+
+eRecMenuState cRecMenuItemSelect::ProcessKey(eKeys Key) {
+    int oldValue = currentVal;
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+            currentVal--;
+            if (currentVal<0)
+                currentVal = numValues - 1;
+            if (callback)
+                *callback = currentVal;
+            DrawValue();
+            return rmsConsumed;
+            break;
+        case kRight:
+            currentVal = (currentVal+1)%numValues;
+            if (callback)
+                *callback = currentVal;
+            DrawValue();
+            return rmsConsumed;
+            break;
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemSelectDirectory  -------------------------------------------------------
+cRecMenuItemSelectDirectory::cRecMenuItemSelectDirectory(cString text,
+                                                         std::string originalFolder,
+                                                         bool active,
+                                                         char *callback,
+                                                         eRecMenuState action,
+                                                         bool isSearchTimer) {
+    selectable = true;
+    this->text = text;
+    this->originalFolder = originalFolder;
+    this->active = active;
+    this->callback = callback;
+    this->action = action;
+    height = 3 * font->Height() / 2;
+    pixmapVal = NULL;
+    folders.push_back(tr("root video folder"));
+    if (isSearchTimer && tvguideConfig.instRecFixedFolder.size() > 0)
+        folders.push_back(tvguideConfig.instRecFixedFolder);
+    ReadRecordingDirectories(&folders, NULL, "");
+    numValues = folders.size();
+    this->currentVal = GetInitial();
+}
+
+cRecMenuItemSelectDirectory::~cRecMenuItemSelectDirectory(void) {
+    if (pixmapVal)
+        osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemSelectDirectory::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapVal->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemSelectDirectory::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemSelectDirectory::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemSelectDirectory::Draw(void) {
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+    DrawValue();    
+}
+
+void cRecMenuItemSelectDirectory::DrawValue(void) {
+    pixmapVal->Fill(clrTransparent);
+    int iconSize = min(128, height);
+    int textX = width - font->Width(folders[currentVal].c_str()) - iconSize;
+    int textY = (height - font->Height()) / 2;
+    pixmapVal->DrawText(cPoint(textX, textY), folders[currentVal].c_str(), colorText, clrTransparent, font);
+    int iconLeftX = textX - iconSize;
+    int iconRightX = width - iconSize;
+    int iconY = (height - iconSize) / 2;
+    
+    cImage *imgLeft = imgCache.GetIcon("arrow_left", iconSize, iconSize);
+    if (imgLeft) {
+        pixmapVal->DrawImage(cPoint(iconLeftX, iconY), *imgLeft);
+    }
+    cImage *imgRight = imgCache.GetIcon("arrow_right", iconSize, iconSize);
+    if (imgRight) {
+        pixmapVal->DrawImage(cPoint(iconRightX, iconY), *imgRight);
+    }
+
+}
+
+eRecMenuState cRecMenuItemSelectDirectory::ProcessKey(eKeys Key) {
+    int oldValue = currentVal;
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+            currentVal--;
+            if (currentVal<0)
+                currentVal = numValues - 1;
+            if (callback) {
+                SetCallback();
+            }
+            DrawValue();
+            return rmsConsumed;
+            break;
+        case kRight: {
+            currentVal = (currentVal+1)%numValues;
+            if (callback) {
+                SetCallback();
+            }
+            DrawValue();
+            return rmsConsumed;
+            break; }
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+void cRecMenuItemSelectDirectory::SetCallback(void) {
+    std::string newFolder = folders[currentVal];
+    if (!newFolder.compare(tr("root video folder")))
+        newFolder = "";
+    strncpy(callback, newFolder.c_str(), TEXTINPUTLENGTH);
+}
+
+int cRecMenuItemSelectDirectory::GetInitial(void) {
+    if (originalFolder.size() == 0)
+        return 0;
+    for (int i=0; i < numValues; i++) {
+        if (!folders[i].compare(originalFolder)) {
+            return i;
+        }
+    }
+    return 0;
+}
+
+
+// --- cRecMenuItemText  -------------------------------------------------------
+cRecMenuItemText::cRecMenuItemText(cString title,
+                                   char *initialVal,
+                                   int length,
+                                   bool active,
+                                   char *callback) {
+    selectable = true;
+    this->title = title;
+    value = initialVal;
+    this->active = active;
+    this->callback = callback;
+    height = 3 * font->Height();
+    pixmapVal = NULL;
+    pixmapKeyboard = NULL;
+    pixmapKeyboardHighlight = NULL;
+    pixmapKeyboardIcons = NULL;
+    keyboardWidth = 50;
+    gridHeight = 3 * fontSmall->Height();
+    keyboardHeight = 5 * gridHeight;
+    
+    this->length = length;
+    allowed = trVDR(FileNameChars);
+    pos = -1;
+    offset = 0;
+    insert = uppercase = false;
+    newchar = true;
+    lengthUtf8 = 0;
+    valueUtf8 = NULL;
+    allowedUtf8 = NULL;
+    charMapUtf8 = NULL;
+    currentCharUtf8 = NULL;
+    lastKey = kNone;
+    keyboardDrawn = false;
+}
+
+cRecMenuItemText::~cRecMenuItemText(void) {
+    if (pixmapVal)
+        osdManager.releasePixmap(pixmapVal);
+    if (pixmapKeyboard)
+        delete pixmapKeyboard;
+    if (pixmapKeyboardHighlight)
+        osdManager.releasePixmap(pixmapKeyboardHighlight);
+    if (pixmapKeyboardIcons)
+        osdManager.releasePixmap(pixmapKeyboardIcons);    
+    delete[] valueUtf8;
+    delete[] allowedUtf8;
+    delete[] charMapUtf8;
+}
+
+void cRecMenuItemText::SetPixmaps(void) {
+    int xPixmapVal = x + 20;
+    int yPixmapVal = y + height / 2 + 10;
+    int widthPixmapVal = width - 40;
+    int heightPixmapVal = height / 2 - 20;
+    int keyboardX = x + (100 - keyboardWidth)*width / 100;
+    int keyboardY = y + height;
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapVal = osdManager.requestPixmap(5, cRect(xPixmapVal, yPixmapVal, widthPixmapVal, heightPixmapVal));
+        pixmapKeyboard = new cStyledPixmap(osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight)));
+        pixmapKeyboardHighlight = osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+        pixmapKeyboardIcons = osdManager.requestPixmap(-1, cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapVal->SetViewPort(cRect(xPixmapVal, yPixmapVal, widthPixmapVal, heightPixmapVal));
+        pixmapKeyboard->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+        pixmapKeyboardHighlight->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+        pixmapKeyboardIcons->SetViewPort(cRect(keyboardX, keyboardY, keyboardWidth*width/100, keyboardHeight));
+    }
+    pixmapKeyboardIcons->Fill(clrTransparent);
+}
+
+void cRecMenuItemText::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapVal) pixmapVal->SetLayer(-1);
+    if (pixmapKeyboard) pixmapKeyboard->SetLayer(-1);
+    if (pixmapKeyboardHighlight) pixmapKeyboardHighlight->SetLayer(-1);
+    if (pixmapKeyboardIcons) pixmapKeyboardIcons->SetLayer(-1);
+}
+
+void cRecMenuItemText::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemText::setBackground() {
+    if (!active) {
+        DeactivateKeyboard();
+    }
+    cRecMenuItem::setBackground();
+}
+
+void cRecMenuItemText::Draw(void) {
+    int textY = (height/2 - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *title, colorText, colorTextBack, font);
+    DrawValue(value);    
+}
+
+void cRecMenuItemText::DrawValue(char *newValue) {
+    tColor clrBack = InEditMode()?theme.Color(clrRecMenuTextActiveBack):theme.Color(clrRecMenuTextBack);
+    pixmapVal->Fill(clrBack);
+    int textX = pixmapVal->DrawPort().Width() - font->Width(newValue) - 10;
+    int textY = (pixmapVal->DrawPort().Height() - font->Height()) / 2;
+    pixmapVal->DrawText(cPoint(textX, textY), newValue, colorText, clrBack, font);
+}
+
+void cRecMenuItemText::ActivateKeyboard(void) {
+    pixmapKeyboard->SetLayer(6);
+    pixmapKeyboardHighlight->SetLayer(6);
+    pixmapKeyboardIcons->SetLayer(6);
+    pixmapKeyboardHighlight->Fill(clrTransparent);
+    
+    if (keyboardDrawn)
+        return;
+    
+    pixmapKeyboard->setColor(theme.Color(clrRecMenuKeyboardBack), theme.Color(clrRecMenuKeyboardBack));
+    pixmapKeyboard->drawBackground();
+       
+    int widthKeyBoard = pixmapKeyboard->Width();
+    gridWidth = widthKeyBoard / 3;
+        
+    pixmapKeyboard->DrawRectangle(cRect(0, 0, widthKeyBoard, keyboardHeight), theme.Color(clrRecMenuKeyboardBorder));
+    int num = 1;
+    for (int row = 0; row < 5; row++) {
+        for (int col = 0; col < 3; col++) {
+            int X = col*gridWidth;
+            int Y = row*gridHeight;
+            tColor clrBack = theme.Color(clrRecMenuKeyboardBack);
+            if (num==13)
+                clrBack = theme.Color(clrButtonRedKeyboard);
+            else if (num==14)
+                clrBack = theme.Color(clrButtonGreenKeyboard);
+            else if (num==15)
+                clrBack = theme.Color(clrButtonYellowKeyboard);
+            pixmapKeyboard->DrawRectangle(cRect(X+2, Y+2, gridWidth-4, gridHeight-4), clrBack);
+            pixmapKeyboard->DrawEllipse(cRect(X, Y, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-2);
+            pixmapKeyboard->DrawEllipse(cRect(X, Y+gridHeight-20, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-3);
+            pixmapKeyboard->DrawEllipse(cRect(X+gridWidth-20, Y+gridHeight-20, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-4);
+            pixmapKeyboard->DrawEllipse(cRect(X+gridWidth-20, Y, 20, 20), theme.Color(clrRecMenuKeyboardBorder),-1);
+            bool draw = false;
+            bool drawIcon = false;
+            cString strNum;
+            std::string strIcon;
+            if (num<10) {
+                strNum = *cString::sprintf("%d", num);
+                draw = true;
+            } else if (num == 11) {
+                strNum = *cString::sprintf("%d", 0);
+                draw = true;
+            } else if (num==13) {
+                strIcon = "icon_shift";
+                drawIcon = true;
+            } else if (num==14) {
+                strIcon = "icon_del_ins";
+                drawIcon = true;
+            } else if (num==15) {
+                strIcon = "icon_backspace";
+                drawIcon = true;
+            }
+            if (draw) {
+                int numX = X + (gridWidth - font->Width(*strNum))/2;
+                int numY = Y + font->Height() / 4;
+                pixmapKeyboard->DrawText(cPoint(numX, numY), *strNum, colorText, colorTextBack, font);
+                char *smsKeys = GetSMSKeys(num);
+                int smsKeysX = X + (gridWidth - fontSmall->Width(smsKeys))/2;
+                int smsKeysY = Y + gridHeight - fontSmall->Height() - 10;
+                pixmapKeyboard->DrawText(cPoint(smsKeysX, smsKeysY), smsKeys, theme.Color(clrRecMenuKeyboardBorder), theme.Color(clrRecMenuKeyboardBack), fontSmall);
+                delete[] smsKeys;
+            }
+            if (drawIcon) {
+                int iconSize = gridHeight - 10;
+                cImage *imgIcon = imgCache.GetIcon(strIcon, iconSize, iconSize);
+                if (imgIcon) {
+                    int iconX = X + (gridWidth - iconSize) / 2;
+                    pixmapKeyboardIcons->DrawImage(cPoint(iconX, Y + 5), *imgIcon);
+                }
+            }
+            num++;
+        }
+    }
+    keyboardDrawn = true;
+}
+
+void cRecMenuItemText::DeactivateKeyboard(void) {
+    pixmapKeyboard->SetLayer(-1);
+    pixmapKeyboardHighlight->SetLayer(-1);
+    pixmapKeyboardIcons->SetLayer(-1);
+}
+
+void cRecMenuItemText::HighlightSMSKey(int num) {
+    int x = 0;
+    int y = 0;
+    if (num == 0) {
+        x = gridWidth;
+        y = 3 * gridHeight;
+    } else {
+        x = (num-1)%3 * gridWidth;
+        y = (num-1)/3 * gridHeight;
+    }
+    pixmapKeyboardHighlight->DrawRectangle(cRect(x, y, gridWidth, gridHeight), theme.Color(clrRecMenuKeyboardHigh));
+}
+
+void cRecMenuItemText::ClearSMSKey(void) {
+    pixmapKeyboardHighlight->Fill(clrTransparent);    
+}
+
+
+char *cRecMenuItemText::GetSMSKeys(int num) {
+    if (num == 11)
+        num = 0;
+    if (num > 9)
+        return NULL;
+    
+    currentCharUtf8 = charMapUtf8;
+    int pos = num;
+    while (pos > 0 && *currentCharUtf8) {
+        if (*currentCharUtf8++ == '\t')
+            pos--;
+    }
+    while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8)) {
+        currentCharUtf8++;
+    }
+    uint *startCharUtf8 = currentCharUtf8;
+    int numChars = 0;
+    bool specialChar = false;
+    while(*currentCharUtf8 && *currentCharUtf8 != '\t' && IsAllowed(*currentCharUtf8)) {
+        currentCharUtf8++;
+        if (Utf8CharSet(*currentCharUtf8) > 1)
+            specialChar = true;
+        numChars++;
+    }
+    char buf[100];
+    char *p = buf;
+    int addition = 0;
+    if (specialChar)
+        addition = 1;
+    Utf8FromArray(startCharUtf8, p, numChars+addition);
+    int maxChars = min(numChars+1+addition, 8);
+    char *smskey = new char[maxChars];
+    Utf8Strn0Cpy(smskey, p, maxChars);
+    return smskey;
+}
+
+void cRecMenuItemText::EnterEditMode(void) {
+    if (!valueUtf8) {
+        valueUtf8 = new uint[length];
+        lengthUtf8 = Utf8ToArray(value, valueUtf8, length);
+        int l = strlen(allowed) + 1;
+        allowedUtf8 = new uint[l];
+        Utf8ToArray(allowed, allowedUtf8, l);
+        const char *charMap = trVDR("CharMap$ 0\t-.,1#~\\^$[]|()*+?{}/:%@&\tabc2\tdef3\tghi4\tjkl5\tmno6\tpqrs7\ttuv8\twxyz9");
+        l = strlen(charMap) + 1;
+        charMapUtf8 = new uint[l];
+        Utf8ToArray(charMap, charMapUtf8, l);
+        currentCharUtf8 = charMapUtf8;
+        AdvancePos();
+    }
+}
+
+void cRecMenuItemText::LeaveEditMode(bool SaveValue) {
+    if (valueUtf8) {
+        if (SaveValue) {
+            Utf8FromArray(valueUtf8, value, length);
+            stripspace(value);
+            if (callback) {
+                strncpy(callback, value, TEXTINPUTLENGTH); 
+            }
+        }
+        lengthUtf8 = 0;
+        delete[] valueUtf8;
+        valueUtf8 = NULL;
+        delete[] allowedUtf8;
+        allowedUtf8 = NULL;
+        delete[] charMapUtf8;
+        charMapUtf8 = NULL;
+        pos = -1;
+        offset = 0;
+        newchar = true;
+    }
+}
+
+void cRecMenuItemText::AdvancePos(void) {
+    if (pos < length - 2 && pos < lengthUtf8) {
+        if (++pos >= lengthUtf8) {
+            if (pos >= 2 && valueUtf8[pos - 1] == ' ' && valueUtf8[pos - 2] == ' ')
+                pos--; // allow only two blanks at the end
+            else {
+                valueUtf8[pos] = ' ';
+                valueUtf8[pos + 1] = 0;
+                lengthUtf8++;
+            }
+        }
+    }
+    newchar = true;
+    if (!insert && Utf8is(alpha, valueUtf8[pos]))
+        uppercase = Utf8is(upper, valueUtf8[pos]);
+}
+
+uint cRecMenuItemText::Inc(uint c, bool Up) {
+    uint *p = IsAllowed(c);
+    if (!p)
+        p = allowedUtf8;
+    if (Up) {
+        if (!*++p)
+            p = allowedUtf8;
+    } else if (--p < allowedUtf8) {
+        p = allowedUtf8;
+        while (*p && *(p + 1))
+            p++;
+    }
+    return *p;
+}
+
+void cRecMenuItemText::Type(uint c) {
+    if (insert && lengthUtf8 < length - 1)
+        Insert();
+    valueUtf8[pos] = c;
+    if (pos < length - 2)
+        pos++;
+    if (pos >= lengthUtf8) {
+        valueUtf8[pos] = ' ';
+        valueUtf8[pos + 1] = 0;
+        lengthUtf8 = pos + 1;
+    }
+}
+
+void cRecMenuItemText::Insert(void) {
+    memmove(valueUtf8 + pos + 1, valueUtf8 + pos, (lengthUtf8 - pos + 1) * sizeof(*valueUtf8));
+    lengthUtf8++;
+    valueUtf8[pos] = ' ';
+}
+
+void cRecMenuItemText::Delete(void) {
+    memmove(valueUtf8 + pos, valueUtf8 + pos + 1, (lengthUtf8 - pos) * sizeof(*valueUtf8));
+    lengthUtf8--;
+}
+
+uint *cRecMenuItemText::IsAllowed(uint c) {
+    if (allowedUtf8) {
+        for (uint *a = allowedUtf8; *a; a++) {
+            if (c == *a)
+                return a;
+        }
+    }
+    return NULL;
+}
+
+void cRecMenuItemText::SetText(void) {
+    if (InEditMode()) {
+        int textAreaWidth = width - 20;
+        textAreaWidth -= font->Width("[]");
+        textAreaWidth -= font->Width("<>"); // reserving this anyway make the whole thing simpler
+        if (pos < offset)
+            offset = pos;
+        int WidthFromOffset = 0;
+        int EndPos = lengthUtf8;
+        for (int i = offset; i < lengthUtf8; i++) {
+            WidthFromOffset += font->Width(valueUtf8[i]);
+            if (WidthFromOffset > textAreaWidth) {
+                if (pos >= i) {
+                    do {
+                        WidthFromOffset -= font->Width(valueUtf8[offset]);
+                        offset++;
+                    } while (WidthFromOffset > textAreaWidth && offset < pos);
+                    EndPos = pos + 1;
+                } else {
+                    EndPos = i;
+                    break;
+                }
+            }
+        }
+        char buf[1000];
+        char *p = buf;
+        if (offset)
+            *p++ = '<';
+        p += Utf8FromArray(valueUtf8 + offset, p, sizeof(buf) - (p - buf), pos - offset);
+        *p++ = '[';
+        if (insert && newchar)
+            *p++ = ']';
+        p += Utf8FromArray(&valueUtf8[pos], p, sizeof(buf) - (p - buf), 1);
+        if (!(insert && newchar))
+            *p++ = ']';
+        p += Utf8FromArray(&valueUtf8[pos + 1], p, sizeof(buf) - (p - buf), EndPos - pos - 1);
+        if (EndPos != lengthUtf8)
+            *p++ = '>';
+        *p = 0;
+        DrawValue(buf);
+    } else {
+        DrawValue(value);
+    }
+}
+
+eRecMenuState cRecMenuItemText::ProcessKey(eKeys Key) {
+    bool consumed = false;
+    bool SameKey = NORMALKEY(Key) == lastKey;
+    ClearSMSKey();
+    if (Key != kNone) {
+        lastKey = NORMALKEY(Key);
+    } else if (!newchar && k0 <= lastKey && lastKey <= k9 && autoAdvanceTimeout.TimedOut()) {
+        AdvancePos();
+        newchar = true;
+        currentCharUtf8 = NULL;
+        SetText();
+        return rmsConsumed;
+    }
+
+    switch ((int)Key) {
+        case kRed:   // Switch between upper- and lowercase characters
+            if (InEditMode()) {
+                if (!insert || !newchar) {
+                    uppercase = !uppercase;
+                    valueUtf8[pos] = uppercase ? Utf8to(upper, valueUtf8[pos]) : Utf8to(lower, valueUtf8[pos]);
+                }
+                consumed = true;
+            }
+            break;
+        case kGreen: // Toggle insert/overwrite modes
+            if (InEditMode()) {
+                insert = !insert;
+                newchar = true;
+                consumed = true;
+            }
+            break;
+        case kYellow|k_Repeat:
+        case kYellow: // Remove the character at the current position; in insert mode it is the character to the right of the cursor
+            if (InEditMode()) {
+                if (lengthUtf8 > 1) {
+                    if (!insert || pos < lengthUtf8 - 1)
+                        Delete();
+                    else if (insert && pos == lengthUtf8 - 1)
+                        valueUtf8[pos] = ' '; // in insert mode, deleting the last character replaces it with a blank to keep the cursor position
+                    // reduce position, if we removed the last character
+                    if (pos == lengthUtf8)
+                        pos--;
+                } else if (lengthUtf8 == 1)
+                    valueUtf8[0] = ' '; // This is the last character in the string, replace it with a blank
+                if (Utf8is(alpha, valueUtf8[pos]))
+                    uppercase = Utf8is(upper, valueUtf8[pos]);
+                newchar = true;
+                consumed = true;
+            }
+            break;
+        case kLeft|k_Repeat:
+        case kLeft:
+            
+            if (pos > 0) {
+                if (!insert || newchar)
+                    pos--;
+                newchar = true;
+                if (!insert && Utf8is(alpha, valueUtf8[pos]))
+                    uppercase = Utf8is(upper, valueUtf8[pos]);
+            }
+            consumed = true;
+            break;
+        case kRight|k_Repeat:
+        case kRight: 
+            if (InEditMode()) {
+                AdvancePos();
+            } else {
+                EnterEditMode();
+                ActivateKeyboard();
+            }
+            consumed = true;
+            break;
+        case kUp|k_Repeat:
+        case kUp:
+        case kDown|k_Repeat:
+        case kDown:  
+            if (InEditMode()) {
+                if (insert && newchar) {
+                // create a new character in insert mode
+                    if (lengthUtf8 < length - 1)
+                        Insert();
+                    }
+                    if (uppercase)
+                        valueUtf8[pos] = Utf8to(upper, Inc(Utf8to(lower, valueUtf8[pos]), NORMALKEY(Key) == kUp));
+                    else
+                        valueUtf8[pos] =               Inc(              valueUtf8[pos],  NORMALKEY(Key) == kUp);
+                        newchar = false;
+                consumed = true;
+            }
+            break;
+        case k0|k_Repeat ... k9|k_Repeat:
+        case k0 ... k9: {
+            if (InEditMode()) {
+                if (Setup.NumberKeysForChars) {
+                    HighlightSMSKey(NORMALKEY(Key) - k0);
+                    if (!SameKey) {
+                        if (!newchar)
+                            AdvancePos();
+                        currentCharUtf8 = NULL;
+                    }
+                    if (!currentCharUtf8 || !*currentCharUtf8 || *currentCharUtf8 == '\t') {
+                    // find the beginning of the character map entry for Key
+                        int n = NORMALKEY(Key) - k0;
+                        currentCharUtf8 = charMapUtf8;
+                        while (n > 0 && *currentCharUtf8) {
+                            if (*currentCharUtf8++ == '\t')
+                                n--;
+                        }
+                        // find first allowed character
+                        while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8))
+                            currentCharUtf8++;
+                    }
+                    if (*currentCharUtf8 && *currentCharUtf8 != '\t') {
+                        if (insert && newchar) {
+                        // create a new character in insert mode
+                            if (lengthUtf8 < length - 1)
+                                Insert();
+                        }
+                        valueUtf8[pos] = *currentCharUtf8;
+                        if (uppercase)
+                            valueUtf8[pos] = Utf8to(upper, valueUtf8[pos]);
+                        // find next allowed character
+                        do {
+                            currentCharUtf8++;
+                        } while (*currentCharUtf8 && *currentCharUtf8 != '\t' && !IsAllowed(*currentCharUtf8));
+                        newchar = false;
+                        autoAdvanceTimeout.Set(AUTO_ADVANCE_TIMEOUT);
+                    }
+                } else {
+                    Type('0' + NORMALKEY(Key) - k0);
+                }
+                consumed = true;
+            }                
+            break; }
+        case kBack:
+        case kOk:    
+            if (InEditMode()) {
+                LeaveEditMode(Key == kOk);
+                DeactivateKeyboard();
+            } else {
+	    	EnterEditMode();
+		ActivateKeyboard();
+	    }
+	    consumed = true;
+	    break;
+        default:
+            if (InEditMode() && BASICKEY(Key) == kKbd) {
+                int c = KEYKBD(Key);
+                if (c <= 0xFF) { 
+                    if (IsAllowed(Utf8to(lower, c)))
+                        Type(c);
+                    else {
+                        switch (c) {
+                            case 0x7F: // backspace
+                                if (pos > 0) {
+                                    pos--;
+                                    ProcessKey(kYellow);
+                                }
+                                break;
+                            default: ;
+                        }
+                    }
+                } else {
+                    switch (c) {
+                        case kfHome: pos = 0; break;
+                        case kfEnd:  pos = lengthUtf8 - 1; break;
+                        case kfIns:  ProcessKey(kGreen);
+                        case kfDel:  ProcessKey(kYellow);
+                        default: ;
+                    }
+                }
+                consumed = true;
+            }
+            break;
+    }
+    SetText();
+    if (consumed)
+        return rmsConsumed;
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemTime  -------------------------------------------------------
+cRecMenuItemTime::cRecMenuItemTime(cString text,
+                                   int initialVal,
+                                   bool active,
+                                   int *callback,
+                                   eRecMenuState action) {
+    selectable = true;
+    this->text = text;
+    this->value = initialVal;
+    hh = value / 100;
+    mm = value % 100;
+    pos = 0;
+    fresh = true;
+    this->active = active;
+    this->callback = callback;
+    this->action = action;
+    height = 3 * font->Height() / 2;
+    pixmapVal = NULL;
+}
+
+cRecMenuItemTime::~cRecMenuItemTime(void) {
+    if (pixmapVal)
+        osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemTime::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapVal->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemTime::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemTime::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemTime::Draw(void) {
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+    DrawValue();    
+}
+
+void cRecMenuItemTime::DrawValue(void) {
+    pixmapVal->Fill(clrTransparent);
+    char buf[10];
+    switch (pos) {
+        case 1:  snprintf(buf, sizeof(buf), "%01d-:--", hh / 10); break;
+        case 2:  snprintf(buf, sizeof(buf), "%02d:--", hh); break;
+        case 3:  snprintf(buf, sizeof(buf), "%02d:%01d-", hh, mm / 10); break;
+        default: snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm);
+    }
+    int textX = width - font->Width(buf) - 10;
+    int textY = (height - font->Height()) / 2;
+    pixmapVal->DrawText(cPoint(textX, textY), buf, colorText, clrTransparent, font);
+}
+
+eRecMenuState cRecMenuItemTime::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kLeft|k_Repeat:
+        case kLeft: {
+            if (--mm < 0) {
+                mm = 59;
+                if (--hh < 0)
+                    hh = 23;
+            }
+            fresh = true;
+            value = hh * 100 + mm;
+            if (callback)
+                *callback = value;
+            DrawValue();
+            return rmsConsumed;
+            break; }
+        case kRight|k_Repeat:
+        case kRight: {
+            if (++mm > 59) {
+                mm = 0;
+                if (++hh > 23)
+                    hh = 0;
+            }
+            fresh = true;
+            value = hh * 100 + mm;
+            DrawValue();
+            if (callback)
+                *callback = value;
+            return rmsConsumed;
+            break; }
+        case k0|k_Repeat ... k9|k_Repeat:
+        case k0 ... k9: {
+            if (fresh || pos > 3) {
+                pos = 0;
+                fresh = false;
+            }
+            int n = Key - k0;
+            switch (pos) {
+                case 0: 
+                    if (n <= 2) {
+                        hh = n * 10;
+                        mm = 0;
+                        pos++;
+                    }
+                    break;
+                case 1: 
+                    if (hh + n <= 23) {
+                        hh += n;
+                        pos++;
+                    }
+                  break;
+                case 2: 
+                    if (n <= 5) {
+                        mm += n * 10;
+                        pos++;
+                    }
+                    break;
+                case 3: 
+                    if (mm + n <= 59) {
+                        mm += n;
+                        pos++;
+                    }
+                    break;
+                default: ;
+            }
+            value = hh * 100 + mm;
+            if (callback)
+                *callback = value;
+            DrawValue();
+            return rmsConsumed;
+            break; }
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemDay  -------------------------------------------------------
+cRecMenuItemDay::cRecMenuItemDay(cString text,
+                                 time_t initialVal,
+                                 bool active,
+                                 time_t *callback,
+                                 eRecMenuState action) {
+    selectable = true;
+    this->text = text;
+    this->currentVal = cTimer::SetTime(initialVal, 0);
+    this->active = active;
+    this->callback = callback;
+    this->action = action;
+    height = 3 * font->Height() / 2;
+    pixmapVal = NULL;
+}
+
+cRecMenuItemDay::~cRecMenuItemDay(void) {
+    if (pixmapVal)
+        osdManager.releasePixmap(pixmapVal);
+}
+
+void cRecMenuItemDay::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapVal = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapVal->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemDay::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapVal) pixmapVal->SetLayer(-1);
+}
+
+void cRecMenuItemDay::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapVal) pixmapVal->SetLayer(5);
+}
+
+void cRecMenuItemDay::Draw(void) {
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+    DrawValue();    
+}
+
+void cRecMenuItemDay::DrawValue(void) {
+    pixmapVal->Fill(clrTransparent);
+    cString textVal = DateString(currentVal);
+    int textX = width - font->Width(*textVal) - 10;
+    int textY = (height - font->Height()) / 2;
+    pixmapVal->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font);
+}
+
+eRecMenuState cRecMenuItemDay::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+            currentVal -= 60*60*24;
+            if (callback)
+                *callback = currentVal;
+            DrawValue();
+            return rmsConsumed;
+            break;
+        case kRight:
+            currentVal += 60*60*24;
+            if (callback)
+                *callback = currentVal;
+            DrawValue();
+            return rmsConsumed;
+            break;
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemTimer  -------------------------------------------------------
+cRecMenuItemTimer::cRecMenuItemTimer(const cTimer *timer, 
+                                     eRecMenuState action1, 
+                                     eRecMenuState action2,
+                                     eRecMenuState action3,
+                                     eRecMenuState action4,
+                                     time_t conflictStart,
+                                     time_t conflictStop,
+                                     time_t overlapStart,
+                                     time_t overlapStop,
+                                     bool active) {
+    selectable = true;
+    this->timer = timer;
+    this->action = action1;
+    this->action2 = action2;
+    this->action3 = action3;
+    this->action4 = action4;
+    iconActive = 0;
+    this->conflictStart = conflictStart;
+    this->conflictStop = conflictStop;
+    this->overlapStart = overlapStart;
+    this->overlapStop = overlapStop;
+    this->active = active;
+    height = 3 * font->Height();
+    pixmapIcons = NULL;
+}
+
+cRecMenuItemTimer::~cRecMenuItemTimer(void) {
+    if (pixmapIcons)
+        osdManager.releasePixmap(pixmapIcons);
+    if (pixmapStatus)
+        osdManager.releasePixmap(pixmapStatus);
+}
+
+void cRecMenuItemTimer::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapStatus = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapStatus->SetViewPort(cRect(x, y, width, height));
+        pixmapIcons->SetViewPort(cRect(x, y, width, height));
+    }
+    pixmapStatus->Fill(clrTransparent);
+    pixmapIcons->Fill(clrTransparent);
+}
+
+void cRecMenuItemTimer::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapStatus) pixmapStatus->SetLayer(-1);
+    if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemTimer::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapStatus) pixmapStatus->SetLayer(5);
+    if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+void cRecMenuItemTimer::Draw(void) {
+    const cChannel *channel = timer->Channel();
+    int channelTransponder = 0;
+    cString channelName = "";
+    if (channel) {
+        channelTransponder = channel->Transponder();
+        channelName = channel->Name();
+    }
+    int logoX = DrawIcons();
+    int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+    cImageLoader imgLoader;
+    if (!tvguideConfig.hideChannelLogos) {
+        if (imgLoader.LoadLogo(channel, logoWidth, height)) {
+            cImage logo = imgLoader.GetImage();
+            pixmapIcons->DrawImage(cPoint(logoX, 0), logo);
+            logoX += logoWidth + 5;
+        }
+    }
+    int textX = logoX;
+    int textHeightLine1 = (height/2 - font->Height()) / 2;
+    int textHeightLine2 = height/2 - 5 + (height/4 - fontSmall->Height()) / 2;
+    int textHeightLine3 = 3*height/4 - 5 + (height/4 - fontSmall->Height()) / 2;
+    const cEvent *event = timer->Event();
+    std::string timerTitle = "";
+    if (event) {
+        timerTitle = event->Title();
+        timerTitle = CutText(timerTitle, (70 * width / 100) - textX, font);
+    }
+    cString timeStart = DayDateTime(timer->StartTime());
+    cString timeEnd = TimeString(timer->StopTime());
+    cString timerTime = cString::sprintf("%s - %s", *timeStart, *timeEnd);
+    cString channelInfo = cString::sprintf("%s, %s %d", *channelName, tr("Transp."), channelTransponder); 
+    pixmapIcons->DrawText(cPoint(textX, textHeightLine1), timerTitle.c_str(), colorText, colorTextBack, font);
+    pixmapIcons->DrawText(cPoint(textX, textHeightLine2), *timerTime, colorText, colorTextBack, fontSmall);
+    pixmapIcons->DrawText(cPoint(textX, textHeightLine3), *channelInfo, colorText, colorTextBack, fontSmall);
+
+    DrawTimerConflict();
+}
+
+int cRecMenuItemTimer::DrawIcons(void) {
+    int iconsX = 10;
+    int iconSize = height/2;
+    int iconY = (height - iconSize) / 2;
+    std::string iconInfo, iconDelete, iconEdit, iconSearch;
+    if (active) {
+        iconInfo = (iconActive==0)?"info_active":"info_inactive";
+        iconDelete = (iconActive==1)?"delete_active":"delete_inactive";
+        iconEdit = (iconActive==2)?"edit_active":"edit_inactive";
+        iconSearch = (iconActive==3)?"search_active":"search_inactive";
+    } else {
+        iconInfo = "info_inactive";
+        iconDelete = "delete_inactive";
+        iconEdit = "edit_inactive";
+        iconSearch = "search_inactive";
+    }
+    
+    cImage *imgInfo = imgCache.GetIcon(iconInfo, iconSize, iconSize);
+    if (imgInfo) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgInfo);
+        iconsX += iconSize + 5;
+    }
+    cImage *imgDelete = imgCache.GetIcon(iconDelete, iconSize, iconSize);
+    if (imgDelete) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgDelete);
+        iconsX += iconSize + 5;
+    }
+    cImage *imgEdit = imgCache.GetIcon(iconEdit, iconSize, iconSize);
+    if (imgEdit) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgEdit);
+        iconsX += iconSize + 5;
+    }
+    cImage *imgSearch = imgCache.GetIcon(iconSearch, iconSize, iconSize);
+    if (imgSearch) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgSearch);
+        iconsX += iconSize + 5;
+    }
+    return iconsX;
+}
+
+void cRecMenuItemTimer::DrawTimerConflict(void) {
+    int widthConfl = 30 * width / 100;
+    int xConfl = width - widthConfl;
+    int heightConflBar = height / 4;
+    int yConflBar = (height - heightConflBar) / 2;
+    pixmapStatus->DrawRectangle(cRect(xConfl, 0, widthConfl, height), theme.Color(clrRecMenuTimerConflictBackground));
+    
+    int completeWidthSecs = conflictStop - conflictStart;
+    int xConfBar = xConfl + (timer->StartTime() - conflictStart) * widthConfl / completeWidthSecs;
+    int widthConfBar = (timer->StopTime() - timer->StartTime()) * widthConfl / completeWidthSecs;
+    pixmapStatus->DrawRectangle(cRect(xConfBar, yConflBar, widthConfBar, heightConflBar), theme.Color(clrRecMenuTimerConflictBar));
+
+    int xOverlap = xConfl + (overlapStart - conflictStart) * widthConfl / completeWidthSecs;
+    int widthOverlap = (overlapStop - overlapStart) * widthConfl / completeWidthSecs;
+    
+    pixmapIcons->DrawRectangle(cRect(xOverlap, 0, widthOverlap, height), theme.Color(clrRecMenuTimerConflictOverlap));
+
+    pixmapStatus->DrawRectangle(cRect(xConfl-3,2,1,height-4), theme.Color(clrBorder));
+    pixmapStatus->DrawRectangle(cRect(xConfl-2,0,2,height), theme.Color(clrBackground));
+}
+
+eRecMenuState cRecMenuItemTimer::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+            if (iconActive > 0) {
+                iconActive--;
+                DrawIcons();
+                return rmsConsumed;
+            } else 
+                return rmsNotConsumed;
+            break;
+        case kRight:
+            if (iconActive < 3) {
+                iconActive++;
+                DrawIcons();
+                return rmsConsumed;
+            } else 
+                return rmsNotConsumed;
+            break;
+        case kOk:
+            if (iconActive == 0)
+                return action;
+            else if (iconActive == 1)
+                return action2;
+            else if (iconActive == 2)
+                return action3;
+            else if (iconActive == 3)
+                return action4;
+            break;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemTimerConflictHeader -------------------------------------------------------
+
+cRecMenuItemTimerConflictHeader::cRecMenuItemTimerConflictHeader(time_t conflictStart,
+                                                                 time_t conflictStop,
+                                                                 time_t overlapStart,
+                                                                 time_t overlapStop) {
+    selectable = false;
+    active = false;
+    this->conflictStart = conflictStart;
+    this->conflictStop = conflictStop;
+    this->overlapStart = overlapStart;
+    this->overlapStop = overlapStop;
+    height = 3*font->Height()/2;
+    pixmapStatus = NULL;
+}
+
+cRecMenuItemTimerConflictHeader::~cRecMenuItemTimerConflictHeader(void) {
+    if (pixmapStatus)
+        osdManager.releasePixmap(pixmapStatus);
+}
+
+void cRecMenuItemTimerConflictHeader::SetPixmaps(void) {
+    pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+    pixmapStatus = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    pixmapStatus->Fill(clrTransparent);
+}
+
+void cRecMenuItemTimerConflictHeader::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapStatus) pixmapStatus->SetLayer(-1);
+}
+
+void cRecMenuItemTimerConflictHeader::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapStatus) pixmapStatus->SetLayer(5);
+}
+
+void cRecMenuItemTimerConflictHeader::setBackground(void) {
+    pixmap->Fill(clrTransparent);
+    cRecMenuItem::setBackground();
+}
+
+void cRecMenuItemTimerConflictHeader::Draw(void) {
+    int widthConfl = 30 * width / 100;
+    int xConfl = width - widthConfl;
+    cString headerText = tr("Timer Conflict");
+    int xHeader = (xConfl - font->Width(*headerText)) / 2;
+    int yHeader = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(xHeader, yHeader), *headerText, theme.Color(clrFont), colorTextBack, font);
+    
+    pixmap->DrawRectangle(cRect(xConfl, 0, widthConfl, height), theme.Color(clrRecMenuTimerConflictBackground));
+    
+    int completeWidthSecs = conflictStop - conflictStart;
+    int xOverlap = xConfl + (overlapStart - conflictStart) * widthConfl / completeWidthSecs;
+    int yOverlap = height - fontSmall->Height();
+    int widthOverlap = (overlapStop - overlapStart) * widthConfl / completeWidthSecs;
+    
+    pixmapStatus->DrawRectangle(cRect(xOverlap, yOverlap, widthOverlap, height), theme.Color(clrRecMenuTimerConflictOverlap));
+
+    cString strConflStart = TimeString(conflictStart);
+    cString strConflStop = TimeString(conflictStop);
+    cString strOverlapStart = TimeString(overlapStart);
+    cString strOverlapStop = TimeString(overlapStop);
+    int y1 = 5;
+    int y2 = yOverlap;
+    int xConflStart = xConfl + 2;
+    int xConflStop = width - fontSmall->Width(*strConflStop) - 2;
+    int xOverlapStart = xOverlap - fontSmall->Width(*strOverlapStart) - 2;
+    int xOverlapStop = xOverlap + widthOverlap + 2;
+    pixmap->DrawText(cPoint(xConflStart, y1), *strConflStart, theme.Color(clrRecMenuTimerConflictBar), theme.Color(clrRecMenuTimerConflictBackground), fontSmall);
+    pixmap->DrawText(cPoint(xConflStop, y1), *strConflStop, theme.Color(clrRecMenuTimerConflictBar), theme.Color(clrRecMenuTimerConflictBackground), fontSmall);
+    pixmap->DrawText(cPoint(xOverlapStart, y2), *strOverlapStart, theme.Color(clrRecMenuTimerConflictOverlap), theme.Color(clrRecMenuTimerConflictBackground), fontSmall);
+    pixmap->DrawText(cPoint(xOverlapStop, y2), *strOverlapStop, theme.Color(clrRecMenuTimerConflictOverlap), theme.Color(clrRecMenuTimerConflictBackground), fontSmall);
+}
+
+// --- cRecMenuItemEvent  -------------------------------------------------------
+cRecMenuItemEvent::cRecMenuItemEvent(const cEvent *event, 
+                                     eRecMenuState action1, 
+                                     eRecMenuState action2, 
+                                     bool active) {
+    selectable = true;
+    this->event = event;
+    this->action = action1;
+    this->action2 = action2;
+    iconActive = 0;
+    this->active = active;
+    height = font->Height() + 2*fontSmall->Height() + 10;
+    pixmapText = NULL;
+    pixmapIcons = NULL;
+}
+
+cRecMenuItemEvent::~cRecMenuItemEvent(void) {
+    if (pixmapIcons)
+        osdManager.releasePixmap(pixmapIcons);
+    if (pixmapText)
+        osdManager.releasePixmap(pixmapText);
+}
+
+void cRecMenuItemEvent::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        pixmapText->Fill(clrTransparent);
+        pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+        pixmapIcons->Fill(clrTransparent);
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapText->SetViewPort(cRect(x, y, width, height));
+        pixmapIcons->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemEvent::Draw(void) {
+    if (!event)
+        return;
+    int logoX = DrawIcons();
+    const cChannel *channel = Channels.GetByChannelID(event->ChannelID());
+    cString channelName = "";
+    if (channel)
+        channelName = channel->Name();
+    int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+    cImageLoader imgLoader;
+    if (!tvguideConfig.hideChannelLogos) {
+        if (imgLoader.LoadLogo(channel, logoWidth, height)) {
+            cImage logo = imgLoader.GetImage();
+            pixmapText->DrawImage(cPoint(logoX, 0), logo);
+            logoX += logoWidth + 5;
+        }
+    }
+    
+    int textX = logoX;
+    int textHeightLine1 = 5;
+    int textHeightLine2 = 5 + fontSmall->Height();
+    int textHeightLine3 = height - fontSmall->Height() - 5;
+
+    cString title = event->Title();
+    cString desc = event->ShortText();
+    cString start = DayDateTime(event->StartTime());
+    cString end = event->GetEndTimeString();
+
+    colorText = active?theme.Color(clrFontActive):theme.Color(clrFont);
+    cString info = cString::sprintf("%s - %s, %s", *start, *end, *channelName);
+    pixmapText->DrawText(cPoint(textX, textHeightLine1), *info, colorText, clrTransparent, fontSmall);
+    pixmapText->DrawText(cPoint(textX, textHeightLine2), *title, colorText, clrTransparent, font);
+    pixmapText->DrawText(cPoint(textX, textHeightLine3), *desc, colorText, clrTransparent, fontSmall);
+}
+
+int cRecMenuItemEvent::DrawIcons(void) {
+    pixmapIcons->Fill(clrTransparent);
+    int iconsX = 10;
+    int iconSize = height / 2;
+    int iconY = (height - iconSize) / 2;
+    std::string iconInfo;
+    if (active) {
+        iconInfo = (iconActive==0)?"info_active":"info_inactive";
+    } else {
+        iconInfo = "info_inactive";
+    }
+    cImage *imgInfo = imgCache.GetIcon(iconInfo, iconSize, iconSize);
+    if (imgInfo) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgInfo);
+        iconsX += iconSize + 5;
+    }
+
+    iconY = height - iconSize - 10;
+    if (event->HasTimer()) {
+        cImage *imgHasTimer = imgCache.GetIcon("activetimer", iconSize, iconSize);
+        if (imgHasTimer) {
+            pixmapIcons->DrawImage(cPoint(width - iconSize - 10, iconY), *imgHasTimer);
+        }
+    } else if (action2 != rmsDisabled) {
+        std::string iconRec = active ? "record_active" : "record_inactive";
+        cImage *imgRec = imgCache.GetIcon(iconRec, iconSize, iconSize);
+        if (imgRec) {
+            pixmapIcons->DrawImage(cPoint(width - iconSize - 10, iconY), *imgRec);
+        }
+    }
+
+
+    return iconsX;
+}
+
+void cRecMenuItemEvent::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapText) pixmapText->SetLayer(-1);
+    if (pixmapIcons) pixmapIcons->SetLayer(-1);    
+}
+
+void cRecMenuItemEvent::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapText) pixmapText->SetLayer(5);
+    if (pixmapIcons) pixmapIcons->SetLayer(6);    
+}
+
+eRecMenuState cRecMenuItemEvent::ProcessKey(eKeys Key) {
+    bool consumed = false;
+    switch (Key & ~k_Repeat) {
+        case kOk:
+            return action;
+            break;
+        case kRed:
+            if (!event->HasTimer())
+                return action2;
+            break;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemChannelChooser -------------------------------------------------------
+cRecMenuItemChannelChooser::cRecMenuItemChannelChooser(cString text,
+                                                       cChannel *initialChannel,
+                                                       bool active,
+                                                       int *callback,
+                                                       eRecMenuState action) {
+    selectable = true;
+    this->text = text;
+    this->channel = initialChannel;
+    if (initialChannel)
+        initialChannelSet = true;
+    else
+        initialChannelSet = false;
+    channelNumber = 0;
+    fresh = true;
+    this->active = active;
+    this->callback = callback;
+    this->action = action;
+    height = 2 * font->Height();
+    pixmapChannel = NULL;
+}
+
+cRecMenuItemChannelChooser::~cRecMenuItemChannelChooser(void) {
+    if (pixmapChannel)
+        osdManager.releasePixmap(pixmapChannel);
+}
+
+void cRecMenuItemChannelChooser::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapChannel = osdManager.requestPixmap(5, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapChannel->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemChannelChooser::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapChannel) pixmapChannel->SetLayer(-1);
+}
+
+void cRecMenuItemChannelChooser::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapChannel) pixmapChannel->SetLayer(5);
+}
+
+void cRecMenuItemChannelChooser::Draw(void) {
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+    DrawValue();    
+}
+
+void cRecMenuItemChannelChooser::DrawValue(void) {
+    pixmapChannel->Fill(clrTransparent);
+    int textY = (height - font->Height()) / 2;
+    if (channel) {
+        cString textVal = cString::sprintf("%d - %s", channel->Number(), channel->Name());
+        int textX = width - font->Width(*textVal) - 10;
+        pixmapChannel->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font);
+        int logoWidth = height * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+        int logoX = textX - logoWidth - 10;
+        cImageLoader imgLoader;
+        if (imgLoader.LoadLogo(channel, logoWidth, height)) {
+            cImage logo = imgLoader.GetImage();
+            pixmapChannel->DrawImage(cPoint(logoX, 0), logo);
+        }
+    } else {
+        cString textVal = tr("all Channels");
+        int textX = width - font->Width(*textVal) - 10;
+        pixmapChannel->DrawText(cPoint(textX, textY), *textVal, colorText, clrTransparent, font);
+    }
+}
+
+int cRecMenuItemChannelChooser::GetIntValue(void) { 
+    if (channel)
+        return channel->Number(); 
+    return 0;
+}
+
+
+eRecMenuState cRecMenuItemChannelChooser::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kLeft: {
+            fresh = true;
+            if (!channel)
+                return rmsConsumed;
+            cChannel *prev = channel;
+            cChannel *firstChannel = Channels.First();
+            if(firstChannel->GroupSep())
+                firstChannel = Channels.Next(firstChannel);
+            if (prev == firstChannel) {
+                if (!initialChannelSet)
+                    channel = NULL;
+            } else {
+                while (prev = Channels.Prev(prev)) {
+                    if(!prev->GroupSep()) {
+                        channel = prev;
+                        break;
+                    }    
+                }
+            }
+            if (callback) {
+                if (channel)
+                    *callback = channel->Number();
+                else
+                    *callback = 0;
+            }
+            DrawValue();
+            return rmsConsumed;
+            break; }
+        case kRight: {
+            fresh = true;
+            if (!channel) {
+                channel = Channels.First();
+                if(channel->GroupSep())
+                    channel = Channels.Next(channel);
+            } else {
+                cChannel *next = channel;
+                while (next = Channels.Next(next)) {
+                    if(!next->GroupSep()) {
+                        channel = next;
+                        break;
+                    }    
+                }
+            }
+            if (callback) {
+                if (channel)
+                    *callback = channel->Number();
+                else
+                    *callback = 0;
+            }
+            DrawValue();
+            return rmsConsumed;
+            break; }
+        case k0 ... k9: {
+            if (fresh) {
+               channelNumber = 0;
+               fresh = false;
+            }
+            channelNumber = channelNumber * 10 + (Key - k0);
+            cChannel *chanNew = Channels.GetByNumber(channelNumber);
+            if (chanNew) {
+                channel = chanNew;
+                DrawValue();
+                if (callback)
+                    *callback = channel->Number();
+            }
+            return rmsConsumed;
+            break; }
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemDayChooser -------------------------------------------------------
+cRecMenuItemDayChooser::cRecMenuItemDayChooser(cString text,
+                                               int weekdays,
+                                               bool active,
+                                               int *callback) {
+    selectable = true;
+    this->text = text;
+    if (weekdays < 1)
+        weekdays *= -1;
+    this->weekdays = weekdays;
+    this->active = active;
+    this->callback = callback;
+    height = 2 * font->Height();
+    selectedDay = 0;
+    pixmapWeekdays = NULL;
+    pixmapWeekdaysSelect = NULL;
+}
+
+cRecMenuItemDayChooser::~cRecMenuItemDayChooser(void) {
+    if (pixmapWeekdays)
+        osdManager.releasePixmap(pixmapWeekdays);
+    if (pixmapWeekdaysSelect)
+        osdManager.releasePixmap(pixmapWeekdaysSelect);
+}
+
+void cRecMenuItemDayChooser::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapWeekdays = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        pixmapWeekdaysSelect = osdManager.requestPixmap(6, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapWeekdays->SetViewPort(cRect(x, y, width, height));
+        pixmapWeekdaysSelect->SetViewPort(cRect(x, y, width, height));
+    }
+    SetSizes();
+}
+
+void cRecMenuItemDayChooser::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapWeekdays) pixmapWeekdays->SetLayer(-1);
+    if (pixmapWeekdaysSelect) pixmapWeekdaysSelect->SetLayer(-1);
+}
+
+void cRecMenuItemDayChooser::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapWeekdays) pixmapWeekdays->SetLayer(5);
+    if (pixmapWeekdaysSelect) pixmapWeekdaysSelect->SetLayer(6);
+}
+
+void cRecMenuItemDayChooser::SetSizes(void) {
+    days = trVDR("MTWTFSS");
+    int maxWidth = 0;
+    for (unsigned i=0; i<days.length(); ++i) {
+        int charWidth = font->Width(days.at(i));
+        if (charWidth > maxWidth)
+            maxWidth = charWidth;
+    }    
+    daysSize = min(maxWidth + 15, height-4);
+    daysX = width - 10 - 7*daysSize;
+    daysY = (height  - daysSize) / 2;
+}
+
+void cRecMenuItemDayChooser::setBackground() {
+    cRecMenuItem::setBackground();
+    if (active) {
+        DrawHighlight(selectedDay);
+    } else {
+        DrawHighlight(-1);
+    }
+}
+
+void cRecMenuItemDayChooser::Draw(void) {
+    int textY = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(10, textY), *text, colorText, colorTextBack, font);
+    DrawDays();
+}
+
+void cRecMenuItemDayChooser::DrawDays(void) {
+    pixmapWeekdays->Fill(clrTransparent);
+    int textY = (height - font->Height()) / 2;
+    pixmapWeekdays->DrawRectangle(cRect(daysX, daysY, 7*daysSize, daysSize), theme.Color(clrBorder));
+    int currentX = daysX;
+    for (unsigned day=0; day<days.length(); ++day) {
+        cString strDay = cString::sprintf("%c", days.at(day));
+        pixmapWeekdays->DrawRectangle(cRect(currentX+2, daysY+2, daysSize-4, daysSize-4), theme.Color(clrBackground));
+        tColor colorDay = WeekDaySet(day)?theme.Color(clrRecMenuDayActive)
+                                         :theme.Color(clrRecMenuDayInactive);
+        int textX = currentX + (daysSize - font->Width(*strDay)) / 2;
+        pixmapWeekdays->DrawText(cPoint(textX, textY), *strDay, colorDay, clrTransparent, font);
+        currentX += daysSize;
+    }
+}
+
+void cRecMenuItemDayChooser::DrawHighlight(int day) {
+    pixmapWeekdaysSelect->Fill(clrTransparent);
+    if (day > -1) {
+        int currentX = daysX + day*daysSize;
+        pixmapWeekdaysSelect->DrawRectangle(cRect(currentX, daysY, daysSize, daysSize), theme.Color(clrRecMenuDayHighlight));
+    }
+}
+
+bool cRecMenuItemDayChooser::WeekDaySet(unsigned day) {
+    return weekdays & (1 << day);
+}
+
+void cRecMenuItemDayChooser::ToggleDay(void) {
+    bool dayActive = WeekDaySet(selectedDay);
+    int dayBit = pow(2, selectedDay);
+    if (dayActive) {
+        weekdays -= dayBit;
+    } else {
+        weekdays += dayBit;
+    }
+    if (callback) {
+        *callback = weekdays;
+    }
+}
+
+eRecMenuState cRecMenuItemDayChooser::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kLeft: {
+            selectedDay--;
+            if (selectedDay<0)
+                selectedDay += 7;
+            DrawHighlight(selectedDay);
+            return rmsConsumed;
+            break; }
+        case kRight: {
+            selectedDay = (selectedDay+1)%7;
+            DrawHighlight(selectedDay);
+            return rmsConsumed;
+            break; }
+        case kOk:
+            ToggleDay();
+            DrawDays();
+            return rmsConsumed;
+            break;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemRecording  -------------------------------------------------------
+cRecMenuItemRecording::cRecMenuItemRecording(cRecording *recording, bool active) {
+    selectable = true;
+    this->recording = recording;
+    this->active = active;
+    height = font->Height() + 2*fontSmall->Height() + 10;
+    pixmapText = NULL;
+}
+
+cRecMenuItemRecording::~cRecMenuItemRecording(void) {
+    if (pixmapText)
+        osdManager.releasePixmap(pixmapText);
+}
+
+void cRecMenuItemRecording::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        pixmapText->Fill(clrTransparent);
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapText->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemRecording::Draw(void) {
+    if (!recording)
+        return;
+    const cRecordingInfo *recInfo = recording->Info();
+    cChannel *channel = Channels.GetByChannelID(recInfo->ChannelID());
+    cString channelName = tr("unknown channel");
+    if (channel)
+        channelName = channel->Name();
+    cString name = recording->Name();
+    cString dateTime = cString::sprintf("%s, %s", *DateString(recording->Start()), *TimeString(recording->Start()));
+    
+    int recDuration = recording->LengthInSeconds() / 60;
+    
+    cString recDetails = cString::sprintf("%s: %d %s, %s %s %s \"%s\"", tr("Duration"), recDuration, tr("min"), tr("recorded at"), *dateTime, tr("from"), *channelName);
+    recDetails = CutText(*recDetails, width - 40, fontSmall).c_str();
+    int text1Y = (height/2 - font->Height()) / 2 + 5;
+    int text2Y = height/2 + (height/2 - fontSmall->Height())/2 - 5;
+    colorText = active?theme.Color(clrFontActive):theme.Color(clrFont);
+    pixmapText->DrawText(cPoint(10, text1Y), *name, colorText, clrTransparent, font);
+    pixmapText->DrawText(cPoint(10, text2Y), *recDetails, colorText, clrTransparent, fontSmall);
+}
+
+void cRecMenuItemRecording::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapText) pixmapText->SetLayer(-1);
+}
+
+void cRecMenuItemRecording::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapText) pixmapText->SetLayer(5);
+}
+
+// --- cRecMenuItemTimelineHeader  -------------------------------------------------------
+cRecMenuItemTimelineHeader::cRecMenuItemTimelineHeader(time_t day, std::vector<cTVGuideTimerConflict*> conflictsToday) {
+    conflicts = conflictsToday;
+    pixmapTimeline = NULL;
+    pixmapTimerInfo = NULL;
+    pixmapTimerConflicts = NULL;
+    timer = NULL;
+    this->day = day;
+    selectable = false;
+    active = false;
+    height = 5 * font->Height();
+    timelineDrawn = false;
+}
+
+cRecMenuItemTimelineHeader::~cRecMenuItemTimelineHeader(void) {
+    if (pixmapTimeline)
+        osdManager.releasePixmap(pixmapTimeline);
+    if (pixmapTimerInfo)
+        osdManager.releasePixmap(pixmapTimerInfo);
+    if (pixmapTimerConflicts)
+        osdManager.releasePixmap(pixmapTimerConflicts);
+}
+
+void cRecMenuItemTimelineHeader::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapTimeline = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        pixmapTimerInfo = osdManager.requestPixmap(6, cRect(x, y + 3 * font->Height() / 2, width, 2 * font->Height()));
+        if (conflicts.size() > 0) {
+            pixmapTimerConflicts = osdManager.requestPixmap(6, cRect(x, y, width, height));
+        }
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapTimeline->SetViewPort(cRect(x, y, width, height));
+        pixmapTimerInfo->SetViewPort(cRect(x, y + 3 * font->Height() / 2, width, 2 * font->Height()));
+        if (pixmapTimerConflicts)
+            pixmapTimerConflicts->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemTimelineHeader::RefreshTimerDisplay(void) {
+    if (!pixmapTimerInfo)
+        return;
+    if (timer)
+        DrawCurrentTimer();
+    else
+        pixmapTimerInfo->Fill(clrTransparent);
+}
+
+void cRecMenuItemTimelineHeader::Draw(void) {
+    if (!timelineDrawn) {
+        DrawTimeline();
+        timelineDrawn = true;
+    }
+    DrawTimerConflicts();
+    pixmap->Fill(clrTransparent);
+    cString headerText = tr("Timers for");
+    cString dateText = DateString(day);
+    cString header = cString::sprintf("%s: %s", *headerText, *dateText);
+    int xText = (width - fontLarge->Width(*header)) / 2;
+    int yText = (height/4 - fontLarge->Height())/2;
+    pixmap->DrawText(cPoint(xText, yText), *header, colorText, clrTransparent, fontLarge);
+
+    DrawCurrentTimer();
+}
+
+void cRecMenuItemTimelineHeader::DrawCurrentTimer(void) {
+    pixmapTimerInfo->Fill(clrTransparent);
+    if (!timer)
+        return;
+    int infoHeight = pixmapTimerInfo->ViewPort().Height();
+    const cEvent *event = timer->Event();
+    const cChannel *channel = timer->Channel();
+    int x = 0;
+    if (channel) {
+        int logoWidth = infoHeight * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+        bool logoDrawn = false;
+        cImageLoader imgLoader;
+        if (!tvguideConfig.hideChannelLogos) {
+            if (imgLoader.LoadLogo(channel, logoWidth, infoHeight)) {
+                cImage logo = imgLoader.GetImage();
+                pixmapTimerInfo->DrawImage(cPoint(0, 0), logo);
+                x += logoWidth + 10;
+                logoDrawn = true;
+            }
+        }
+        if (tvguideConfig.hideChannelLogos || !logoDrawn) {
+            int channelNameWidth = fontSmall->Width(channel->Name());
+            pixmapTimerInfo->DrawText(cPoint(10, (infoHeight - fontSmall->Height())/2), channel->Name(), colorText, clrTransparent, fontSmall);
+            x += channelNameWidth + 20;
+        }
+    }
+
+    cString timerStartTime = TimeString(timer->StartTime());
+    cString timerStopTime = TimeString(timer->StopTime());
+    cString channelInfo = cString::sprintf("%s %d", tr("Transp."), timer->Channel()->Transponder());
+
+    if (event) {
+        cString title;
+        if (event->ShortText()) {
+            title = cString::sprintf("%s - %s", event->Title(), event->ShortText());
+        } else {
+            title = event->Title();
+        }
+        std::string titleCut = CutText(*title, width - x, font);
+        cString infoString = cString::sprintf("%s: %s - %s (%s. %s - %s), %s", *event->GetDateString(), *event->GetTimeString(), *event->GetEndTimeString(), tr("Rec"), *timerStartTime, *timerStopTime, *channelInfo);
+        pixmapTimerInfo->DrawText(cPoint(x, 0), *infoString, colorText, clrTransparent, font);
+        pixmapTimerInfo->DrawText(cPoint(x, font->Height()), titleCut.c_str(), colorText, clrTransparent, font);
+    } else {
+        cString infoString = cString::sprintf("%s. %s - %s, %s", tr("Rec"), *timerStartTime, *timerStopTime, *channelInfo);
+        pixmapTimerInfo->DrawText(cPoint(x, 0), *infoString, colorText, clrTransparent, font);
+    }
+}
+
+void cRecMenuItemTimelineHeader::DrawTimeline(void) {
+    pixmapTimeline->Fill(clrTransparent);
+    width5Mins = (float)width * 5.0 / 24.0 / 60.0;
+    int widthHour = 12 * width5Mins;
+    x0 = (width - 24*widthHour)/2;
+    int barHeight = fontSmall->Height();
+    int y = height - barHeight;
+    tColor col1 = theme.Color(clrTimeline1);
+    tColor col2 = theme.Color(clrTimeline2);
+    tColor colCurText = col1;
+    tColor colCurBack = col2;
+    int x = x0;
+    for (int hour = 0; hour < 24; hour++) {
+        pixmapTimeline->DrawRectangle(cRect(x, y, widthHour, barHeight), colCurBack);
+        cString hourText = cString::sprintf("%d", hour);
+        int xDelta = (widthHour - fontSmall->Width(*hourText)) / 2;
+        pixmapTimeline->DrawText(cPoint(x + xDelta, y), *hourText, colCurText, colCurBack, fontSmall);
+        x += widthHour;
+        colCurText = (colCurText==col1)?col2:col1;
+        colCurBack = (colCurBack==col1)?col2:col1;
+    }
+    pixmapTimeline->DrawRectangle(cRect(x0, height-2, width - 2*x0, 2), col2);
+}
+
+void cRecMenuItemTimelineHeader::DrawTimerConflicts(void) {
+    if (!pixmapTimerConflicts)
+        return;
+    pixmapTimerConflicts->Fill(clrTransparent);
+    int numConflicts = conflicts.size();
+    int barHeight = fontSmall->Height();
+    int y = height - barHeight;
+    for (int conflict = 0; conflict < numConflicts; conflict++) {
+        int confStart = conflicts[conflict]->timeStart - day;
+        int confStop = conflicts[conflict]->timeStop - day;
+        int overlapStart = conflicts[conflict]->overlapStart - day;
+        int overlapStop = conflicts[conflict]->overlapStop - day;
+        if (confStart < 0)
+            confStart = 0;
+        if (confStop > 24*60*60)
+            confStop = 24 * 60 * 60;
+        if (overlapStart < 0)
+            overlapStart  = 0;
+        if (overlapStop > 24*60*60)
+            overlapStop  = 24 * 60 * 60;
+        confStart = confStart / 60;
+        confStop = confStop / 60;
+        overlapStart = overlapStart / 60;
+        overlapStop = overlapStop / 60;
+        int xStartConflict = x0 + confStart * width5Mins / 5;
+        int xStopConflict = x0 + confStop * width5Mins / 5;
+        int xStartOverlap = x0 + overlapStart * width5Mins / 5;
+        int xStopOverlap = x0 + overlapStop * width5Mins / 5;
+        pixmapTimerConflicts->DrawRectangle(cRect(xStartConflict, y, xStopConflict - xStartConflict, barHeight), theme.Color(clrRecMenuTimelineConflict));
+        pixmapTimerConflicts->DrawRectangle(cRect(xStartOverlap, y, xStopOverlap - xStartOverlap, barHeight), theme.Color(clrRecMenuTimelineConflictOverlap));
+    }
+}
+
+void cRecMenuItemTimelineHeader::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapTimeline) pixmapTimeline->SetLayer(-1);
+    if (pixmapTimerInfo) pixmapTimerInfo->SetLayer(-1);
+    if (pixmapTimerConflicts) pixmapTimerConflicts->SetLayer(-1);
+}
+
+void cRecMenuItemTimelineHeader::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapTimeline) pixmapTimeline->SetLayer(5);
+    if (pixmapTimerInfo) pixmapTimerInfo->SetLayer(6);
+    if (pixmapTimerConflicts) pixmapTimerConflicts->SetLayer(6);
+}
+
+
+// --- cRecMenuItemTimelineTimer  -------------------------------------------------------
+cRecMenuItemTimelineTimer::cRecMenuItemTimelineTimer(cTimer *timer, time_t start, time_t stop,  std::vector<cTVGuideTimerConflict*> conflictsToday, cRecMenuItemTimelineHeader *header, bool active) {
+    conflicts = conflictsToday;
+    defaultBackground = false;
+    pixmapBack = NULL;
+    pixmapTimerConflicts = NULL;
+    this->timer = timer;
+    this->start = start;
+    this->stop = stop;
+    this->header = header;
+    selectable = true;
+    this->active = active;
+    height = geoManager.osdHeight / 16;
+}
+
+cRecMenuItemTimelineTimer::~cRecMenuItemTimelineTimer(void) {
+    if (pixmapBack)
+        osdManager.releasePixmap(pixmapBack);
+    if (pixmapTimerConflicts)
+        osdManager.releasePixmap(pixmapTimerConflicts);
+}
+
+void cRecMenuItemTimelineTimer::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmapBack = osdManager.requestPixmap(4, cRect(x, y, width, height)); 
+        pixmap = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        if (conflicts.size() > 0) {
+            pixmapTimerConflicts = osdManager.requestPixmap(6, cRect(x, y, width, height));
+        }        
+    } else {
+        pixmapBack->SetViewPort(cRect(x, y, width, height));
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        if (pixmapTimerConflicts)
+            pixmapTimerConflicts->SetViewPort(cRect(x, y, width, height));
+            
+    }
+    width5Mins = (float)width * 5.0 / 24.0 / 60.0;
+    x0 = (width - 24*12*width5Mins)/2;
+}
+
+void cRecMenuItemTimelineTimer::Draw(void) {
+    DrawBackground();
+    if (!timer) {
+        DrawNoTimerInfo();
+        return;
+    }
+    if (!drawn) {
+        pixmap->Fill(clrTransparent);
+        DrawTimeScale();
+        DrawTimerBar();
+        DrawTimerConflicts();
+        drawn = true;
+    }
+}
+
+void cRecMenuItemTimelineTimer::DrawBackground(void) {
+    tColor backgroundColor = (active)?theme.Color(clrRecMenuTimelineActive):theme.Color(clrRecMenuTimelineBack);
+    pixmapBack->Fill(clrTransparent);
+    pixmapBack->DrawRectangle(cRect(x0, 0, width - 2 * x0, height), backgroundColor);
+}
+
+void cRecMenuItemTimelineTimer::DrawTimeScale(void) {
+    int x = x0;
+    for (int hour = 0; hour < 25; hour++) {
+        int xModified = (hour%2) ? x - 1 : x ;
+        pixmap->DrawRectangle(cRect(xModified,0,1,height), theme.Color(clrTimeline2));
+        x += width5Mins*12;
+    }
+}
+
+void cRecMenuItemTimelineTimer::DrawTimerBar(void) {
+    time_t timerStart = timer->StartTime() - start;
+    time_t timerStop = timer->StopTime() - start;
+    if (timerStart < 0)
+        timerStart = 0;
+    if (timerStop > 24*60*60)
+        timerStop = 24 * 60 * 60;
+    timerStart = timerStart / 60;
+    timerStop = timerStop / 60;
+    int xStart = x0 + timerStart * width5Mins / 5;
+    int xStop = x0 + timerStop * width5Mins / 5;
+    pixmap->DrawRectangle(cRect(xStart, height / 4, xStop - xStart, height / 2), theme.Color(clrRecMenuTimelineTimer));
+}
+
+void cRecMenuItemTimelineTimer::DrawTimerConflicts(void) {
+    if (!pixmapTimerConflicts)
+        return;
+    pixmapTimerConflicts->Fill(clrTransparent);
+    int numConflicts = conflicts.size();
+    for (int conflict = 0; conflict < numConflicts; conflict++) {
+        int confStart = conflicts[conflict]->timeStart - start;
+        int confStop = conflicts[conflict]->timeStop - start;
+        int overlapStart = conflicts[conflict]->overlapStart - start;
+        int overlapStop = conflicts[conflict]->overlapStop - start;
+        if (confStart < 0)
+            confStart = 0;
+        if (confStop > 24*60*60)
+            confStop = 24 * 60 * 60;
+        if (overlapStart < 0)
+            overlapStart  = 0;
+        if (overlapStop > 24*60*60)
+            overlapStop  = 24 * 60 * 60;
+        confStart = confStart / 60;
+        confStop = confStop / 60;
+        overlapStart = overlapStart / 60;
+        overlapStop = overlapStop / 60;
+        int xStartConflict = x0 + confStart * width5Mins / 5;
+        int xStopConflict = x0 + confStop * width5Mins / 5;
+        int xStartOverlap = x0 + overlapStart * width5Mins / 5;
+        int xStopOverlap = x0 + overlapStop * width5Mins / 5;
+        pixmapTimerConflicts->DrawRectangle(cRect(xStartConflict, 0, xStopConflict - xStartConflict, height), theme.Color(clrRecMenuTimelineConflict));
+        pixmapTimerConflicts->DrawRectangle(cRect(xStartOverlap, 0, xStopOverlap - xStartOverlap, height), theme.Color(clrRecMenuTimelineConflictOverlap));
+    }
+}
+
+void cRecMenuItemTimelineTimer::DrawNoTimerInfo(void) {
+    pixmap->Fill(clrTransparent);
+    cString noTimersText = tr("No Timers active");
+    int widthText = font->Width(*noTimersText);
+    int x = (width - widthText) / 2;
+    int y = (height - font->Height()) / 2;
+    pixmap->DrawText(cPoint(x, y), *noTimersText, colorText, clrTransparent, font);
+}
+
+void cRecMenuItemTimelineTimer::setActive(void) {
+    active = true;
+    header->SetCurrentTimer(timer);
+    header->RefreshTimerDisplay();
+}
+
+void cRecMenuItemTimelineTimer::setInactive(void) {
+    active = false;
+    header->UnsetCurrentTimer();
+    header->RefreshTimerDisplay();
+}
+
+void cRecMenuItemTimelineTimer::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapBack) pixmapBack->SetLayer(-1);
+    if (pixmapTimerConflicts) pixmapTimerConflicts->SetLayer(-1);
+}
+
+void cRecMenuItemTimelineTimer::Show(void) { 
+    if (pixmap) pixmap->SetLayer(5);
+    if (pixmapBack) pixmapBack->SetLayer(4);
+    if (pixmapTimerConflicts) pixmapTimerConflicts->SetLayer(6);
+}
+
+cTimer *cRecMenuItemTimelineTimer::GetTimerValue(void) {
+    return timer;    
+}
+
+eRecMenuState cRecMenuItemTimelineTimer::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kOk:
+            return rmsTimelineTimerEdit;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+
+// --- cRecMenuItemSearchTimer  -------------------------------------------------------
+cRecMenuItemSearchTimer::cRecMenuItemSearchTimer(cTVGuideSearchTimer timer, 
+                                                 eRecMenuState action1,
+                                                 eRecMenuState action2,
+                                                 eRecMenuState action3,
+                                                 bool active) {
+    this->timer = timer;
+    this->action = action1;
+    this->action2 = action2;
+    this->action3 = action3;
+    pixmapText = NULL;
+    pixmapIcons = NULL;
+    selectable = true;
+    this->active = active;
+    iconActive = 0;
+    height = 2 * font->Height();;
+}
+
+cRecMenuItemSearchTimer::~cRecMenuItemSearchTimer(void) {
+    if (pixmapText)
+        osdManager.releasePixmap(pixmapText);
+    if (pixmapIcons)
+        osdManager.releasePixmap(pixmapIcons);
+}
+
+void cRecMenuItemSearchTimer::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapText->SetViewPort(cRect(x, y, width, height));
+        pixmapIcons->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemSearchTimer::Draw(void) {
+    int textX = DrawIcons();
+    pixmapText->Fill(clrTransparent);
+    textX += 20;
+    cString label;
+    if (timer.Active()) {
+        label = cString::sprintf("\"%s\"", timer.SearchString().c_str());
+    } else {
+        label = cString::sprintf("\"%s\" (%s)", timer.SearchString().c_str(), tr("inactive"));
+    }
+    int numTimersActive = timer.GetNumTimers();
+    int numRecordings = timer.GetNumRecordings();
+    cString info = cString::sprintf("%s: %d, %s: %d", tr("active timers"), numTimersActive, tr("recordings done"), numRecordings);
+    pixmapText->DrawText(cPoint(textX, 5 + (height/2 - font->Height())/2), *label, colorText, clrTransparent, font);
+    pixmapText->DrawText(cPoint(textX, height/2 + (height/2 - fontSmall->Height())/2), *info, colorText, clrTransparent, fontSmall);
+}
+
+void cRecMenuItemSearchTimer::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapText) pixmapText->SetLayer(-1);
+    if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemSearchTimer::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapText) pixmapText->SetLayer(5);
+    if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+int cRecMenuItemSearchTimer::DrawIcons(void) {
+    pixmapIcons->Fill(clrTransparent);
+    int iconsX = 10;
+    int iconSize = height / 2;
+    int iconY = (height - iconSize) / 2;
+    std::string iconEdit, iconDelete, iconSearch;
+    if (active) {
+        iconSearch = (iconActive==0)?"search_active":"search_inactive";
+        iconEdit = (iconActive==1)?"edit_active":"edit_inactive";
+        iconDelete = (iconActive==2)?"delete_active":"delete_inactive";
+    } else {
+        iconSearch = "search_inactive";
+        iconEdit = "edit_inactive";
+        iconDelete = "delete_inactive";
+    }
+    cImage *imgSearch = imgCache.GetIcon(iconSearch, iconSize, iconSize);
+    if (imgSearch) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgSearch);
+        iconsX += iconSize + 10;
+    }
+    cImage *imgEdit = imgCache.GetIcon(iconEdit, iconSize, iconSize);
+    if (imgEdit) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgEdit);
+        iconsX += iconSize + 10;
+    }
+    cImage *imgDel = imgCache.GetIcon(iconDelete, iconSize, iconSize);
+    if (imgDel) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgDel);
+        iconsX += iconSize + 10;
+    }
+    return iconsX;
+}
+
+eRecMenuState cRecMenuItemSearchTimer::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+            if (iconActive > 0) {
+                iconActive--;
+                DrawIcons();
+                return rmsConsumed;
+            }
+            return rmsNotConsumed;
+            break;
+        case kRight: {
+            if (iconActive < 2) {
+                iconActive++;
+                DrawIcons();
+                return rmsConsumed;
+            }   
+            return rmsNotConsumed;
+            break; }
+        case kOk:
+            if (iconActive == 0)
+                return action;
+            else if (iconActive == 1)
+                return action2;
+            else if (iconActive == 2)
+                return action3;
+            break;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemFavorite  -------------------------------------------------------
+cRecMenuItemFavorite::cRecMenuItemFavorite(cTVGuideSearchTimer favorite, 
+                                           eRecMenuState action1,
+                                           bool active) {
+    this->favorite = favorite;
+    this->action = action1;
+    pixmapText = NULL;
+    pixmapIcons = NULL;
+    selectable = true;
+    this->active = active;
+    height = 2 * font->Height();;
+}
+
+cRecMenuItemFavorite::~cRecMenuItemFavorite(void) {
+    if (pixmapText)
+        osdManager.releasePixmap(pixmapText);
+    if (pixmapIcons)
+        osdManager.releasePixmap(pixmapIcons);
+}
+
+void cRecMenuItemFavorite::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapText->SetViewPort(cRect(x, y, width, height));
+        pixmapIcons->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemFavorite::Draw(void) {
+    int textX = DrawIcons();
+    pixmapText->Fill(clrTransparent);
+    textX += 20;
+    cString label = cString::sprintf("\"%s\"", favorite.SearchString().c_str());
+    pixmapText->DrawText(cPoint(textX, (height - fontLarge->Height())/2), *label, colorText, clrTransparent, fontLarge);
+}
+
+void cRecMenuItemFavorite::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapText) pixmapText->SetLayer(-1);
+    if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemFavorite::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapText) pixmapText->SetLayer(5);
+    if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+int cRecMenuItemFavorite::DrawIcons(void) {
+    pixmapIcons->Fill(clrTransparent);
+    int iconsX = 10;
+    int iconSize = height / 2;
+    int iconY = (height - iconSize) / 2;
+    std::string iconSearch;
+    iconSearch = active ? "search_active" : "search_inactive" ;
+    cImage *imgSearch = imgCache.GetIcon(iconSearch, iconSize, iconSize);
+    if (imgSearch) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgSearch);
+        iconsX += iconSize + 10;
+    }
+    return iconsX;
+}
+
+eRecMenuState cRecMenuItemFavorite::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
+
+// --- cRecMenuItemFavoriteStatic  -------------------------------------------------------
+cRecMenuItemFavoriteStatic::cRecMenuItemFavoriteStatic(std::string text, eRecMenuState action, bool active) {
+    this->text = text;
+    this->action = action;
+    pixmapText = NULL;
+    pixmapIcons = NULL;
+    selectable = true;
+    this->active = active;
+    height = 2 * font->Height();;
+}
+
+cRecMenuItemFavoriteStatic::~cRecMenuItemFavoriteStatic(void) {
+    if (pixmapText)
+        osdManager.releasePixmap(pixmapText);
+    if (pixmapIcons)
+        osdManager.releasePixmap(pixmapIcons);
+}
+
+void cRecMenuItemFavoriteStatic::SetPixmaps(void) {
+    if (!pixmap) {
+        pixmap = osdManager.requestPixmap(4, cRect(x, y, width, height));
+        pixmapText = osdManager.requestPixmap(5, cRect(x, y, width, height));
+        pixmapIcons = osdManager.requestPixmap(6, cRect(x, y, width, height));
+    } else {
+        pixmap->SetViewPort(cRect(x, y, width, height));
+        pixmapText->SetViewPort(cRect(x, y, width, height));
+        pixmapIcons->SetViewPort(cRect(x, y, width, height));
+    }
+}
+
+void cRecMenuItemFavoriteStatic::Draw(void) {
+    int textX = DrawIcons();
+    pixmapText->Fill(clrTransparent);
+    textX += 20;
+    pixmapText->DrawText(cPoint(textX, (height - fontLarge->Height())/2), text.c_str(), colorText, clrTransparent, fontLarge);
+}
+
+void cRecMenuItemFavoriteStatic::Hide(void) { 
+    if (pixmap) pixmap->SetLayer(-1);
+    if (pixmapText) pixmapText->SetLayer(-1);
+    if (pixmapIcons) pixmapIcons->SetLayer(-1);
+}
+
+void cRecMenuItemFavoriteStatic::Show(void) { 
+    if (pixmap) pixmap->SetLayer(4);
+    if (pixmapText) pixmapText->SetLayer(5);
+    if (pixmapIcons) pixmapIcons->SetLayer(6);
+}
+
+int cRecMenuItemFavoriteStatic::DrawIcons(void) {
+    pixmapIcons->Fill(clrTransparent);
+    int iconsX = 10;
+    int iconSize = height / 2;
+    int iconY = (height - iconSize) / 2;
+    std::string iconSearch;
+    iconSearch = active ? "search_active" : "search_inactive" ;
+    cImage *imgSearch = imgCache.GetIcon(iconSearch, iconSize, iconSize);
+    if (imgSearch) {
+        pixmapIcons->DrawImage(cPoint(iconsX, iconY), *imgSearch);
+        iconsX += iconSize + 10;
+    }
+    return iconsX;
+}
+
+eRecMenuState cRecMenuItemFavoriteStatic::ProcessKey(eKeys Key) {
+    switch (Key & ~k_Repeat) {
+        case kOk:
+            return action;
+        default:
+            break;
+    }
+    return rmsNotConsumed;
+}
\ No newline at end of file
diff --git a/recmenuitem.h b/recmenuitem.h
new file mode 100644
index 0000000..9df37db
--- /dev/null
+++ b/recmenuitem.h
@@ -0,0 +1,684 @@
+#ifndef __TVGUIDE_RECMENUITEM_H
+#define __TVGUIDE_RECMENUITEM_H
+
+#define AUTO_ADVANCE_TIMEOUT 1500
+
+#include <string>
+#include <vdr/tools.h> 
+#include "styledpixmap.h"
+#include "timerconflict.h"
+#include "searchtimer.h"
+
+enum eRecMenuState {
+    rmsConsumed,
+    rmsNotConsumed,
+    rmsRefresh,
+    rmsContinue,
+    rmsClose,
+    rmsDisabled,
+    //INSTANT TIMER
+    rmsInstantRecord,
+    rmsInstantRecordFolder,
+    rmsIgnoreTimerConflict,
+    rmsDeleteTimerConflictMenu,
+    rmsEditTimerConflictMenu,
+    rmsSearchRerunsTimerConflictMenu,
+    rmsSaveTimerConflictMenu,
+    rmsTimerConflictShowInfo,
+    rmsDeleteTimer,
+    rmsDeleteTimerConfirmation,
+    rmsEditTimer,
+    rmsSaveTimer,
+    //SEARCH
+    rmsSearch,
+    rmsSearchWithOptions,
+    rmsSearchPerform,
+    rmsSearchShowInfo,
+    rmsSearchRecord,
+    rmsSearchRecordConfirm,
+    rmsSearchNothingFoundConfirm,
+    //SERIES TIMER
+    rmsSeriesTimer,
+    rmsSeriesTimerFolder,
+    rmsSeriesTimerCreate,
+    //SEARCHTIMER
+    rmsSearchTimer,
+    rmsSearchTimerOptions,
+    rmsSearchTimers,
+    rmsSearchTimerEdit,
+    rmsSearchTimerEditAdvanced,
+    rmsSearchTimerTest,
+    rmsSearchTimerSave,
+    rmsSearchTimerCreateWithTemplate,
+    rmsSearchTimerDeleteConfirm,
+    rmsSearchTimerDelete,
+    rmsSearchTimerDeleteWithTimers,
+    rmsSearchTimerRecord,
+    //SWITCHTIMER
+    rmsSwitchTimer,
+    rmsSwitchTimerCreate,
+    rmsSwitchTimerDelete,
+    //RECORDINGS SEARCH
+    rmsRecordingSearch,
+    rmsRecordingSearchResult,
+    //TIMER CONFLICTS
+    rmsTimerConflict,
+    rmsTimerConflicts,
+    rmsTimerConflictIgnoreReruns,
+    rmsTimerConflictRecordRerun,
+    //TIMELINE
+    rmsTimeline,
+    rmsTimelineTimerEdit,
+    rmsTimelineTimerSave,
+    rmsTimelineTimerDelete,
+    //FAVORITES
+    rmsFavoritesRecord,
+    rmsFavoritesRecordConfirm,
+    rmsFavoritesNow,
+    rmsFavoritesNext,    
+    rmsFavoritesUser1,
+    rmsFavoritesUser2,
+    rmsFavoritesUser3,
+    rmsFavoritesUser4,
+};
+
+enum eDependend {
+    eGreater,
+    eLower,
+};
+
+// --- cRecMenuItem  -------------------------------------------------------------
+class cRecMenuItem : public cListObject, public cStyledPixmap {
+protected:
+    int x, y;
+    int width, height;
+    bool selectable;
+    bool active;
+    bool defaultBackground;
+    bool drawn;
+    eRecMenuState action;
+    tColor colorText;
+    tColor colorTextBack;
+    const cFont *font;
+    const cFont *fontSmall;
+    const cFont *fontLarge;
+public:
+    cRecMenuItem(void);
+    virtual ~cRecMenuItem(void);
+    void SetGeometry(int x, int y, int width);
+    virtual void SetPixmaps(void);
+    virtual int GetHeight(void) { return height; };
+    virtual int GetWidth(void) { return 0; };
+    virtual void CalculateHeight(int textWidth) {};
+    virtual void setActive(void) { this->active = true; }
+    virtual void setInactive(void) { this->active = false; }
+    bool isSelectable(void) { return selectable; }
+    bool isActive(void) { return active; }
+    virtual void setBackground(void);
+    virtual void Draw(void) {};
+    virtual void Hide(void) { if (pixmap) pixmap->SetLayer(-1);};
+    virtual void Show(void) { if (pixmap) pixmap->SetLayer(4);};
+    virtual int GetIntValue(void) { return -1; };
+    virtual time_t GetTimeValue(void) { return 0; };
+    virtual bool GetBoolValue(void) { return false; };
+    virtual cString GetStringValue(void) { return cString(""); };
+    virtual const cEvent *GetEventValue(void) { return NULL; };
+    virtual cTimer *GetTimerValue(void) { return NULL; };
+    virtual eRecMenuState ProcessKey(eKeys Key) { return rmsNotConsumed; };
+};
+
+// --- cRecMenuItemButton  -------------------------------------------------------
+class cRecMenuItemButton : public cRecMenuItem {
+private:
+    cString text;
+    bool halfWidth;
+    bool alignLeft;
+    const cFont *fontButtons;
+    cPixmap *pixmapText;
+public:
+    cRecMenuItemButton(const char *text, eRecMenuState action, bool active, bool halfWidth = false, bool alignLeft = false, bool largeFont = false);
+    virtual ~cRecMenuItemButton(void);
+    int GetWidth(void);
+    void SetPixmaps(void);
+    void Draw(void);
+    void Hide(void);
+    void Show(void);
+    cString GetStringValue(void) { return text; };
+    eRecMenuState ProcessKey(eKeys Key);
+};
+
+// --- cRecMenuItemButtonYesNo  -------------------------------------------------------
+class cRecMenuItemButtonYesNo : public cRecMenuItem {
+private:
+    cString textYes;
+    cString textNo;
+    eRecMenuState actionNo;
+    bool yesActive;
+    cStyledPixmap *pixmapNo;
+    tColor colorTextNo;
+    tColor colorTextNoBack;
+public:
+    cRecMenuItemButtonYesNo(cString textYes,
+                            cString textNo,
+                            eRecMenuState actionYes, 
+                            eRecMenuState actionNo,
+                            bool active);
+    virtual ~cRecMenuItemButtonYesNo(void);
+    void SetPixmaps(void);
+    void setBackground(void);
+    void Hide(void);
+    void Show(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+};
+
+// --- cRecMenuItemInfo  -------------------------------------------------------
+class cRecMenuItemInfo : public cRecMenuItem {
+private:
+    cString text;
+    cTextWrapper wrapper;
+    int border;
+    const cFont *fontInfo;
+public:
+    cRecMenuItemInfo(const char *text, bool largeFont = false);
+    virtual ~cRecMenuItemInfo(void);
+    void setBackground(void);
+    void CalculateHeight(int textWidth);
+    void Draw(void);
+};
+
+// --- cRecMenuItemInt  -------------------------------------------------------
+class cRecMenuItemInt : public cRecMenuItem {
+private:
+    cString text;
+    int currentVal;
+    int *callback;
+    int minVal;
+    int maxVal;
+    cPixmap *pixmapVal;
+    bool fresh;
+    void DrawValue(void);
+public:
+    cRecMenuItemInt(cString text,
+                    int initialVal,
+                    int minVal,
+                    int maxVal,
+                    bool active = false,
+                    int *callback = NULL,
+                    eRecMenuState action = rmsNotConsumed);
+    virtual ~cRecMenuItemInt(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    void setBackground(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+    int GetIntValue(void) { return currentVal; };
+};
+
+// --- cRecMenuItemBool  -------------------------------------------------------
+class cRecMenuItemBool : public cRecMenuItem {
+private:
+    cString text;
+    bool yes;
+    bool *callback;
+    cPixmap *pixmapVal;
+    bool refresh;
+    void DrawValue(void);
+public:
+    cRecMenuItemBool(cString text,
+                     bool initialVal,
+                     bool refresh = false,
+                     bool active = false,
+                     bool *callback = NULL,
+                     eRecMenuState action = rmsNotConsumed);
+    virtual ~cRecMenuItemBool(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+    bool GetBoolValue(void) { return yes; };
+};
+
+// --- cRecMenuItemSelect  -------------------------------------------------------
+class cRecMenuItemSelect : public cRecMenuItem {
+private:
+    cString text;
+    int currentVal;
+    int *callback;
+    std::vector<std::string> strings;
+    int numValues;
+    cPixmap *pixmapVal;
+    void DrawValue(void);
+public:
+    cRecMenuItemSelect(cString text,
+                       std::vector<std::string> Strings,
+                       int initialVal,
+                       bool active = false,
+                       int *callback = NULL,
+                       eRecMenuState action = rmsNotConsumed);
+    virtual ~cRecMenuItemSelect(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+    int GetIntValue(void) { return currentVal; };
+    cString GetStringValue(void) { return strings[currentVal].c_str(); };
+};
+
+// --- cRecMenuItemSelectDirectory  -------------------------------------------------------
+class cRecMenuItemSelectDirectory : public cRecMenuItem {
+private:
+    cString text;
+    std::string originalFolder;
+    std::vector<std::string> folders;
+    int currentVal;
+    char *callback;
+    int numValues;
+    cPixmap *pixmapVal;
+    void DrawValue(void);
+    int GetInitial(void);
+    void SetCallback(void);
+public:
+    cRecMenuItemSelectDirectory(cString text,
+                                std::string originalFolder,
+                                bool active = false,
+                                char *callback = NULL,
+                                eRecMenuState action = rmsNotConsumed,
+                                bool isSearchTimer = false);
+    virtual ~cRecMenuItemSelectDirectory(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+};
+
+// --- cRecMenuItemText  -------------------------------------------------------
+class cRecMenuItemText : public cRecMenuItem {
+private:
+    cString title;
+    char *value;
+    char *callback;
+    int length;
+    const char *allowed;
+    int pos, offset;
+    bool insert, newchar, uppercase;
+    int lengthUtf8;
+    uint *valueUtf8;
+    uint *allowedUtf8;
+    uint *charMapUtf8;
+    uint *currentCharUtf8;
+    eKeys lastKey;
+    cTimeMs autoAdvanceTimeout;
+    cPixmap *pixmapVal;
+    cStyledPixmap *pixmapKeyboard;
+    cPixmap *pixmapKeyboardHighlight;
+    cPixmap *pixmapKeyboardIcons;
+    int keyboardWidth;
+    int gridWidth;
+    int gridHeight;
+    int keyboardHeight;
+    bool keyboardDrawn;
+    uint *IsAllowed(uint c);
+    void AdvancePos(void);
+    uint Inc(uint c, bool Up);
+    void Type(uint c);
+    void Insert(void);
+    void Delete(void);
+    void EnterEditMode(void);
+    void LeaveEditMode(bool SaveValue = false);
+    bool InEditMode(void) { return valueUtf8 != NULL; };    
+    void SetText(void);
+    void ActivateKeyboard(void);
+    void DeactivateKeyboard(void);
+    void HighlightSMSKey(int num);
+    void ClearSMSKey(void);
+    char *GetSMSKeys(int num);
+    void DrawValue(char *newValue);
+public:
+    cRecMenuItemText(cString title,
+                     char *initialVal,
+                     int length,
+                     bool active = false,
+                     char *callback = NULL);
+    virtual ~cRecMenuItemText(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    void setBackground(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+    cString GetStringValue(void) { return value; };
+};
+
+
+// --- cRecMenuItemTime  -------------------------------------------------------
+class cRecMenuItemTime : public cRecMenuItem {
+private:
+    cString text;
+    int value;
+    int *callback;
+    int mm;
+    int hh;
+    int pos;
+    bool fresh;
+    cPixmap *pixmapVal;
+    void DrawValue(void);
+public:
+    cRecMenuItemTime(cString text,
+                    int initialVal,
+                    bool active = false,
+                    int *callback = NULL,
+                    eRecMenuState action = rmsNotConsumed);
+    virtual ~cRecMenuItemTime(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+    int GetIntValue(void) { return value; };
+};
+
+// --- cRecMenuItemDay  -------------------------------------------------------
+class cRecMenuItemDay : public cRecMenuItem {
+private:
+    cString text;
+    time_t currentVal;
+    time_t *callback;
+    cPixmap *pixmapVal;
+    void DrawValue(void);
+public:
+    cRecMenuItemDay(cString text,
+                    time_t initialVal,
+                    bool active = false,
+                    time_t *callback = NULL,
+                    eRecMenuState action = rmsNotConsumed);
+    virtual ~cRecMenuItemDay(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+    time_t GetTimeValue(void) { return currentVal; };
+};
+
+// --- cRecMenuItemTimer  -------------------------------------------------------
+class cRecMenuItemTimer : public cRecMenuItem {
+private:
+    const cTimer *timer;
+    eRecMenuState action2;
+    eRecMenuState action3;
+    eRecMenuState action4;
+    int iconActive;
+    cPixmap *pixmapIcons;
+    cPixmap *pixmapStatus;
+    time_t conflictStart;
+    time_t conflictStop;
+    time_t overlapStart;
+    time_t overlapStop;
+    int DrawIcons(void);
+    void DrawTimerConflict(void);
+public:
+    cRecMenuItemTimer(const cTimer *timer, 
+                      eRecMenuState action1, 
+                      eRecMenuState action2,
+                      eRecMenuState action3,
+                      eRecMenuState action4,
+                      time_t conflictStart,
+                      time_t conflictStop,
+                      time_t overlapStart,
+                      time_t overlapStop,
+                      bool active);
+    virtual ~cRecMenuItemTimer(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+};
+
+// --- cRecMenuItemTimerConflictHeader -------------------------------------------------------
+
+class cRecMenuItemTimerConflictHeader: public cRecMenuItem {
+private:
+    cPixmap *pixmapStatus;
+    time_t conflictStart;
+    time_t conflictStop;
+    time_t overlapStart;
+    time_t overlapStop;
+public:
+    cRecMenuItemTimerConflictHeader(time_t conflictStart,
+                                    time_t conflictStop,
+                                    time_t overlapStart,
+                                    time_t overlapStop);
+    virtual ~cRecMenuItemTimerConflictHeader(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void);
+    void setBackground(void);
+    void Draw(void);
+};
+
+// --- cRecMenuItemEvent  -------------------------------------------------------
+class cRecMenuItemEvent : public cRecMenuItem {
+private:
+    const cEvent *event;
+    eRecMenuState action2;
+    int iconActive;
+    cPixmap *pixmapText;
+    cPixmap *pixmapIcons;
+    int DrawIcons(void);
+public:
+    cRecMenuItemEvent(const cEvent *event, 
+                      eRecMenuState action1, 
+                      eRecMenuState action2, 
+                      bool active);
+    virtual ~cRecMenuItemEvent(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void); 
+    const cEvent *GetEventValue(void) { return event; };
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+};
+
+// --- cRecMenuItemChannelChooser -------------------------------------------------------
+class cRecMenuItemChannelChooser : public cRecMenuItem {
+private:
+    cString text;
+    cChannel *channel;
+    int channelNumber;
+    int *callback;
+    bool initialChannelSet;
+    bool fresh;
+    cPixmap *pixmapChannel;
+    void DrawValue(void);
+public:
+    cRecMenuItemChannelChooser (cString text,
+                                cChannel *initialChannel,
+                                bool active = false,
+                                int *callback = NULL,
+                                eRecMenuState action = rmsNotConsumed);
+    virtual ~cRecMenuItemChannelChooser(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void); 
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+    int GetIntValue(void);
+};
+
+// --- cRecMenuItemDayChooser -------------------------------------------------------
+class cRecMenuItemDayChooser : public cRecMenuItem {
+private:
+    cString text;
+    int weekdays;
+    int *callback;
+    bool epgsearchMode;
+    std::string days;
+    int daysX;
+    int daysY;
+    int daysSize;
+    int selectedDay;
+    cPixmap *pixmapWeekdays;
+    cPixmap *pixmapWeekdaysSelect;
+    void SetSizes(void);
+    void DrawDays(void);
+    void DrawHighlight(int day);
+    void ToggleDay(void);
+    bool WeekDaySet(unsigned day);
+public:
+    cRecMenuItemDayChooser (cString text,
+                            int weekdays,
+                            bool active = false,
+                            int *callback = NULL);
+    virtual ~cRecMenuItemDayChooser(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void); 
+    void setBackground(void);
+    eRecMenuState ProcessKey(eKeys Key);
+    void Draw(void);
+    int GetIntValue(void) { return weekdays;} ;
+};
+
+// --- cRecMenuItemRecording  -------------------------------------------------------
+class cRecMenuItemRecording : public cRecMenuItem {
+private:
+    cRecording *recording;
+    cPixmap *pixmapText;
+public:
+    cRecMenuItemRecording(cRecording *recording, bool active);
+    virtual ~cRecMenuItemRecording(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void); 
+    void Draw(void);
+};
+
+// --- cRecMenuItemTimelineHeader  -------------------------------------------------------
+class cRecMenuItemTimelineHeader : public cRecMenuItem {
+private:
+    time_t day;
+    cTimer *timer;
+    std::vector<cTVGuideTimerConflict*> conflicts;
+    cPixmap *pixmapTimeline;
+    cPixmap *pixmapTimerInfo;
+    cPixmap *pixmapTimerConflicts;
+    int width5Mins;
+    int x0;
+    bool timelineDrawn;
+    void DrawTimeline(void);
+    void DrawTimerConflicts(void);
+    void DrawCurrentTimer(void);
+public:
+    cRecMenuItemTimelineHeader(time_t day, std::vector<cTVGuideTimerConflict*> conflictsToday);
+    virtual ~cRecMenuItemTimelineHeader(void);
+    void SetDay(time_t day) { this->day = day; };
+    void SetPixmaps(void);
+    void SetCurrentTimer(cTimer *timer) { this->timer = timer; };
+    void UnsetCurrentTimer(void) { timer = NULL; };
+    void RefreshTimerDisplay(void);
+    void Hide(void);
+    void Show(void); 
+    void Draw(void);
+};
+
+// --- cRecMenuItemTimelineTimer  -------------------------------------------------------
+class cRecMenuItemTimelineTimer : public cRecMenuItem {
+private:
+    cTimer *timer;
+    std::vector<cTVGuideTimerConflict*> conflicts;
+    cPixmap *pixmapBack;
+    cPixmap *pixmapTimerConflicts;
+    cRecMenuItemTimelineHeader *header;
+    int x0;
+    int width5Mins;
+    time_t start;
+    time_t stop;
+    void DrawBackground(void);
+    void DrawTimerBar(void);
+    void DrawTimeScale(void);
+    void DrawTimerConflicts(void);
+    void DrawNoTimerInfo(void);
+public:
+    cRecMenuItemTimelineTimer(cTimer *timer, time_t start, time_t stop, std::vector<cTVGuideTimerConflict*> conflictsToday, cRecMenuItemTimelineHeader *header, bool active);
+    virtual ~cRecMenuItemTimelineTimer(void);
+    void setActive(void);
+    void setInactive(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void); 
+    void Draw(void);
+    cTimer *GetTimerValue(void);
+    eRecMenuState ProcessKey(eKeys Key);
+};
+
+// --- cRecMenuItemSearchTimer  -------------------------------------------------------
+class cRecMenuItemSearchTimer : public cRecMenuItem {
+private:
+    cTVGuideSearchTimer timer;
+    eRecMenuState action1;
+    eRecMenuState action2;
+    eRecMenuState action3;
+    int iconActive;
+    cPixmap *pixmapText;
+    cPixmap *pixmapIcons;
+    int DrawIcons(void);
+public:
+    cRecMenuItemSearchTimer(cTVGuideSearchTimer timer, 
+                            eRecMenuState action1,
+                            eRecMenuState action2,
+                            eRecMenuState action3,
+                            bool active);
+    virtual ~cRecMenuItemSearchTimer(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void); 
+    void Draw(void);
+    cTVGuideSearchTimer GetTimer(void) { return timer; };
+    eRecMenuState ProcessKey(eKeys Key);
+};
+
+// --- cRecMenuItemFavorite  -------------------------------------------------------
+class cRecMenuItemFavorite : public cRecMenuItem {
+private:
+    cTVGuideSearchTimer favorite;
+    eRecMenuState action1;
+    cPixmap *pixmapText;
+    cPixmap *pixmapIcons;
+    int DrawIcons(void);
+public:
+    cRecMenuItemFavorite(cTVGuideSearchTimer favorite, 
+                         eRecMenuState action1,
+                         bool active);
+    virtual ~cRecMenuItemFavorite(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void); 
+    void Draw(void);
+    cTVGuideSearchTimer GetFavorite(void) { return favorite; };
+    eRecMenuState ProcessKey(eKeys Key);
+};
+
+// --- cRecMenuItemFavoriteStatic  -------------------------------------------------------
+class cRecMenuItemFavoriteStatic : public cRecMenuItem {
+private:
+    std::string text;
+    cPixmap *pixmapText;
+    cPixmap *pixmapIcons;
+    int DrawIcons(void);
+public:
+    cRecMenuItemFavoriteStatic(std::string text, eRecMenuState action, bool active);
+    virtual ~cRecMenuItemFavoriteStatic(void);
+    void SetPixmaps(void);
+    void Hide(void);
+    void Show(void); 
+    void Draw(void);
+    eRecMenuState ProcessKey(eKeys Key);
+};
+
+#endif //__TVGUIDE_RECMENUITEM_H
\ No newline at end of file
diff --git a/recmenumanager.c b/recmenumanager.c
new file mode 100644
index 0000000..edabf4d
--- /dev/null
+++ b/recmenumanager.c
@@ -0,0 +1,893 @@
+#include "recmenu.h" 
+#include "recmenus.h"
+#include "switchtimer.h"
+#include "timerconflict.h"
+#include "recmenumanager.h"
+
+cRecMenuManager::cRecMenuManager(void) {
+    footer = NULL;
+    active = false;
+    activeMenu = NULL;
+    activeMenuBuffer = NULL;
+    activeMenuBuffer2 = NULL;
+    recManager = new cRecManager();
+    recManager->SetEPGSearchPlugin();
+    timerConflicts = NULL;
+    detailViewActive = false;
+}
+
+cRecMenuManager::~cRecMenuManager(void) {
+    if (activeMenu) {
+        active = false;
+        delete activeMenu;
+        activeMenu = NULL;
+    }
+    if (timerConflicts) {
+        delete timerConflicts;
+        timerConflicts = NULL;
+    }
+    delete recManager;
+}
+
+void cRecMenuManager::Start(const cEvent *event) {
+    active = true;
+    activeMenuBuffer = NULL;
+    detailViewActive = false;
+    SetBackground();
+    this->event = event;
+    activeMenu = new cRecMenuMain(recManager->EpgSearchAvailable(), recManager->CheckEventForTimer(event), SwitchTimers.EventInSwitchList(event));
+    activeMenu->Display();
+    osdManager.flush();
+}
+
+void cRecMenuManager::StartFavorites(void) {
+    active = true;
+    activeMenuBuffer = NULL;
+    detailViewActive = false;
+    SetBackground();
+    std::vector<cTVGuideSearchTimer> favorites;
+    recManager->GetFavorites(&favorites);
+    activeMenu = new cRecMenuFavorites(favorites);
+    activeMenu->Display();
+    osdManager.flush();
+}
+
+
+void cRecMenuManager::Close(void) {
+    event = NULL;
+    active = false;
+    if (activeMenu) {
+        delete activeMenu;
+        activeMenu = NULL;
+    }
+    if (timerConflicts) {
+        delete timerConflicts;
+        timerConflicts = NULL;
+    }
+    DeleteBackground();
+}
+
+void cRecMenuManager::SetBackground(void) {
+    int backgroundWidth = geoManager.osdWidth;
+    int backgroundHeight = geoManager.osdHeight;
+    pixmapBackground = osdManager.requestPixmap(3, cRect(0, 0, backgroundWidth, backgroundHeight));
+    pixmapBackground->Fill(theme.Color(clrRecMenuBackground));
+    if (tvguideConfig.scaleVideo) {
+        int tvHeight = geoManager.statusHeaderHeight;
+        int tvWidth = tvHeight * 16 / 9;
+        int tvX = geoManager.osdWidth - tvWidth;
+        pixmapBackground->DrawRectangle(cRect(tvX, 0, tvWidth, tvHeight), clrTransparent);
+    }
+}
+
+void cRecMenuManager::DeleteBackground(void) {
+    osdManager.releasePixmap(pixmapBackground);
+}
+
+eOSState cRecMenuManager::StateMachine(eRecMenuState nextState) {
+    eOSState state = osContinue;
+    switch (nextState) {
+        /*************************************************************************************** 
+        *    INSTANT RECORDING 
+        ****************************************************************************************/
+        case rmsInstantRecord: {
+        //caller: main menu or folder chooser
+        //Creating timer for active Event, if no conflict, confirm and exit
+            std::string recFolder = "";
+            if (cRecMenuAskFolder *menu = dynamic_cast<cRecMenuAskFolder*>(activeMenu)) {
+                recFolder = menu->GetFolder();
+            }
+            delete activeMenu;
+            cTimer *timer = recManager->createTimer(event, recFolder);
+            if (!DisplayTimerConflict(timer)) {
+                activeMenu = new cRecMenuConfirmTimer(event);
+                activeMenu->Display();
+            }
+            break; }
+        case rmsInstantRecordFolder:
+        //caller: main menu
+        //Asking for Folder
+            delete activeMenu;
+            activeMenu = new cRecMenuAskFolder(event, rmsInstantRecord);
+            activeMenu->Display();
+            break;
+        case rmsIgnoreTimerConflict:
+        //caller: cRecMenuTimerConflict
+        //Confirming created Timer
+            delete activeMenu;
+            activeMenu = new cRecMenuConfirmTimer(event);
+            activeMenu->Display();
+            break;
+        case rmsTimerConflictShowInfo: {
+            //caller: cRecMenuTimerConflict
+            int timerIndex;
+            if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenu)) {
+                timerIndex = menu->GetTimerConflictIndex();
+            } else break;
+            int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex);
+            cTimer *t = Timers.Get(timerID);
+            if (t) {
+                const cEvent *ev = t->Event();
+                if (ev) {
+                    DisplayDetailedView(ev);
+                }
+            }
+            break; }
+        case rmsDeleteTimerConflictMenu: {
+            //caller: cRecMenuTimerConflict
+            //delete timer out of current timer conflict
+            int timerIndex;
+            if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenu)) {
+                timerIndex = menu->GetTimerConflictIndex();
+            } else break;
+            int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex);
+            recManager->DeleteTimer(timerID);
+            delete activeMenu;
+            if (!DisplayTimerConflict(timerID)) {
+                activeMenu = new cRecMenuConfirmTimer(event);
+                activeMenu->Display();
+            }
+            break; }
+        case rmsEditTimerConflictMenu: {
+            //caller: cRecMenuTimerConflict
+            //edit timer out of current timer conflict
+            int timerIndex;
+            if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenu)) {
+                timerIndex = menu->GetTimerConflictIndex();
+            } else break;
+            int timerID = timerConflicts->GetCurrentConflictTimerID(timerIndex);
+            cTimer *timer = Timers.Get(timerID);
+            if (timer) {
+                delete activeMenu;
+                activeMenu = new cRecMenuEditTimer(timer, rmsSaveTimerConflictMenu);
+                activeMenu->Display();
+            }
+            break; }
+        case rmsSaveTimerConflictMenu: {
+            //caller: cRecMenuEditTimer
+            //save timer from current timer conflict
+            cTimer timerModified;
+            cTimer *originalTimer;
+            if (cRecMenuEditTimer *menu = dynamic_cast<cRecMenuEditTimer*>(activeMenu)) {
+                timerModified = menu->GetTimer();
+                originalTimer = menu->GetOriginalTimer();
+            } else break;
+            recManager->SaveTimer(originalTimer, timerModified);
+            delete activeMenu;
+            if (!DisplayTimerConflict(originalTimer)) {
+                activeMenu = new cRecMenuConfirmTimer(event);
+                activeMenu->Display();
+            }
+            break; }
+        case rmsDeleteTimer:
+            //caller: main menu
+            //delete timer for active event
+            delete activeMenu;
+            if (recManager->IsRecorded(event)) {
+                activeMenu = new cRecMenuAskDeleteTimer(event);
+            } else {
+                recManager->DeleteTimer(event);
+                activeMenu = new cRecMenuConfirmDeleteTimer(event);
+            }
+            activeMenu->Display();
+            break;
+        case rmsDeleteTimerConfirmation:
+            //delete running timer for active event
+            recManager->DeleteTimer(event);
+            delete activeMenu;
+            activeMenu = new cRecMenuConfirmDeleteTimer(event);
+            activeMenu->Display();
+            break;
+        case rmsEditTimer: {
+            //edit timer for active event
+            cTimer *timer = recManager->GetTimerForEvent(event);
+            if (timer) {
+                delete activeMenu;
+                activeMenu = new cRecMenuEditTimer(timer, rmsSaveTimer);
+                activeMenu->Display();
+            }
+            break; }
+        case rmsSaveTimer: {
+            //caller: cRecMenuEditTimer
+            //save timer for active event
+            cTimer timerModified;
+            cTimer *originalTimer;
+            if (cRecMenuEditTimer *menu = dynamic_cast<cRecMenuEditTimer*>(activeMenu)) {
+                timerModified = menu->GetTimer();
+                originalTimer = menu->GetOriginalTimer();
+            } else break;
+            recManager->SaveTimer(originalTimer, timerModified);
+            state = osEnd;
+            Close();
+            break; }
+        /*************************************************************************************** 
+        *    SERIES TIMER
+        ****************************************************************************************/
+        case rmsSeriesTimer: {
+            //caller: main menu oder folder chooser
+            std::string recFolder = "";
+            if (cRecMenuAskFolder *menu = dynamic_cast<cRecMenuAskFolder*>(activeMenu)) {
+                recFolder = menu->GetFolder();
+            }
+            delete activeMenu;
+            cChannel *channel = Channels.GetByChannelID(event->ChannelID());
+            activeMenu = new cRecMenuSeriesTimer(channel, event, recFolder);
+            activeMenu->Display();
+            break; }
+        case rmsSeriesTimerFolder:
+            //caller: main menu
+            //Asking for Folder
+            delete activeMenu;
+            activeMenu = new cRecMenuAskFolder(event, rmsSeriesTimer);
+            activeMenu->Display();
+            break;
+        case rmsSeriesTimerCreate: {
+            //caller: cRecMenuSeriesTimer
+            cTimer *seriesTimer;
+            if (cRecMenuSeriesTimer *menu = dynamic_cast<cRecMenuSeriesTimer*>(activeMenu)) {
+                seriesTimer = menu->GetTimer();
+            } else break;
+            recManager->CreateSeriesTimer(seriesTimer);
+            delete activeMenu;
+            activeMenu = new cRecMenuConfirmSeriesTimer(seriesTimer);
+            activeMenu->Display();
+            break; }
+        /********************************************************************************************** 
+         *    SEARCH TIMER 
+         ***********************************************************************************************/
+        case rmsSearchTimer:
+            //Caller: main menu
+            //set search String for search timer
+            delete activeMenu;
+            activeMenu = new cRecMenuSearchTimer(event);
+            activeMenu->Display();
+            break;
+        case rmsSearchTimerOptions: {
+            //Caller: cRecMenuSearchTimer, cRecMenuSearchTimerTemplates
+            //Choose to set options manually or by template
+            std::string searchString;
+            cTVGuideSearchTimer searchTimer;
+            bool reload = false;
+            if (cRecMenuSearchTimer *menu = dynamic_cast<cRecMenuSearchTimer*>(activeMenu)) {
+                searchString = menu->GetSearchString();
+            } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast<cRecMenuSearchTimerTemplatesCreate*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+                reload = true;
+            } else break;
+            delete activeMenu;
+            if (searchString.size() < 4) {
+                activeMenu = new cRecMenuSearchTimer(event);
+            } else { 
+                if (!reload) {
+                    searchTimer.SetSearchString(searchString);
+                }
+                std::vector<TVGuideEPGSearchTemplate> epgSearchTemplates;
+                recManager->ReadEPGSearchTemplates(&epgSearchTemplates);
+                if (epgSearchTemplates.size() > 0) {
+                    activeMenu = new cRecMenuSearchTimerTemplates(searchTimer, epgSearchTemplates);
+                } else {
+                    activeMenu = new cRecMenuSearchTimerEdit(searchTimer, false);
+                }
+            }
+            activeMenu->Display();
+            break; }
+        case rmsSearchTimers: {
+            //caller: main menu
+            DisplaySearchTimerList();
+            break; }
+        case rmsSearchTimerEdit:
+        case rmsSearchTimerEditAdvanced: {
+            //caller: cRecMenuSearchTimers, cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplates
+            cTVGuideSearchTimer searchTimer;
+            bool advancedOptions = false;
+            if (cRecMenuSearchTimers *menu = dynamic_cast<cRecMenuSearchTimers*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+            } else if (cRecMenuSearchTimerEdit *menu = dynamic_cast<cRecMenuSearchTimerEdit*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+                advancedOptions = (nextState == rmsSearchTimerEditAdvanced)?true:false;
+            } else if (cRecMenuSearchTimerTemplates *menu = dynamic_cast<cRecMenuSearchTimerTemplates*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+            } else break;
+            delete activeMenu;
+            activeMenu = new cRecMenuSearchTimerEdit(searchTimer, advancedOptions);
+            activeMenu->Display();
+            break; }
+        case rmsSearchTimerTest: {
+            //caller: cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplatesCreate, cRecMenuSearchTimers, cRecMenuFavorites
+            //show results of currently choosen search timer
+            cTVGuideSearchTimer searchTimer;
+            eRecMenuState recState = rmsDisabled;
+            if (cRecMenuSearchTimerEdit *menu = dynamic_cast<cRecMenuSearchTimerEdit*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+                recState = rmsSearchTimerRecord;
+            } else if  (cRecMenuSearchTimers *menu = dynamic_cast<cRecMenuSearchTimers*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+                recState = rmsSearchTimerRecord;
+            } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast<cRecMenuSearchTimerTemplatesCreate*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+                TVGuideEPGSearchTemplate tmpl = menu->GetTemplate();
+                searchTimer.SetTemplate(tmpl.templValue);
+                searchTimer.Parse(true);
+            } else if (cRecMenuFavorites *menu = dynamic_cast<cRecMenuFavorites*>(activeMenu)) {
+                searchTimer = menu->GetFavorite();
+                recState = rmsFavoritesRecord;
+            } else break;
+            int numSearchResults = 0;
+            std::string searchString = searchTimer.BuildSearchString();
+            const cEvent **searchResult = recManager->PerformSearchTimerSearch(searchString, numSearchResults);
+            if (numSearchResults) {
+                activeMenuBuffer = activeMenu;
+                activeMenuBuffer->Hide();
+                activeMenu = new cRecMenuSearchTimerResults(searchTimer.SearchString(), searchResult, numSearchResults, "", recState);
+                activeMenu->Display();
+            } else {
+               activeMenuBuffer = activeMenu;
+               activeMenuBuffer->Hide();
+               activeMenu = new cRecMenuSearchTimerNothingFound(searchTimer.SearchString());
+               activeMenu->Display();
+            }
+            break; }
+        case rmsSearchTimerSave: {
+            //caller: cRecMenuSearchTimerEdit, cRecMenuSearchTimerTemplatesCreate
+            //create new or modify existing search timer
+            cTVGuideSearchTimer searchTimer;
+            if (cRecMenuSearchTimerEdit *menu = dynamic_cast<cRecMenuSearchTimerEdit*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+            } else if (cRecMenuSearchTimerTemplatesCreate *menu = dynamic_cast<cRecMenuSearchTimerTemplatesCreate*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+                TVGuideEPGSearchTemplate tmpl = menu->GetTemplate();
+                searchTimer.SetTemplate(tmpl.templValue);
+                searchTimer.Parse(true);
+            } else break;
+            bool success = recManager->SaveSearchTimer(&searchTimer);
+            recManager->UpdateSearchTimers();
+            if (searchTimer.GetID() >= 0) {
+                //Timer modified, show list
+                DisplaySearchTimerList();
+            } else {
+                //new timer, confirm
+                delete activeMenu;
+                activeMenu = new cRecMenuSearchTimerCreateConfirm(success);
+                activeMenu->Display();
+            }
+            break; }
+        case rmsSearchTimerCreateWithTemplate: {
+            //caller: cRecMenuSearchTimerTemplates
+            //create new search timer from template
+            TVGuideEPGSearchTemplate templ;
+            cTVGuideSearchTimer searchTimer;
+            if (cRecMenuSearchTimerTemplates *menu = dynamic_cast<cRecMenuSearchTimerTemplates*>(activeMenu)) {
+                templ = menu->GetTemplate();
+                searchTimer = menu->GetSearchTimer();
+            } else break;
+            delete activeMenu;
+            activeMenu = new cRecMenuSearchTimerTemplatesCreate(templ, searchTimer);
+            activeMenu->Display();
+            break; }
+        case rmsSearchTimerDeleteConfirm: {
+            //caller: cRecMenuSearchTimers
+            //Ask for confirmation and if timers created by this search timer should alo be deleted
+            cTVGuideSearchTimer searchTimer;
+            if (cRecMenuSearchTimers *menu = dynamic_cast<cRecMenuSearchTimers*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+            } else break;
+            activeMenuBuffer = activeMenu;
+            activeMenuBuffer->Hide();
+            activeMenu = new cRecMenuSearchTimerDeleteConfirm(searchTimer);
+            activeMenu->Display();
+            break; }
+        case rmsSearchTimerDelete: 
+        case rmsSearchTimerDeleteWithTimers: {
+            //caller: cRecMenuSearchTimerDeleteConfirm
+            //actually delete searchtimer
+            cTVGuideSearchTimer searchTimer;
+            if (cRecMenuSearchTimerDeleteConfirm *menu = dynamic_cast<cRecMenuSearchTimerDeleteConfirm*>(activeMenu)) {
+                searchTimer = menu->GetSearchTimer();
+            } else break;
+            bool delTimers = (nextState==rmsSearchTimerDeleteWithTimers)?true:false;
+            recManager->DeleteSearchTimer(&searchTimer, delTimers);
+            delete activeMenuBuffer;
+            activeMenuBuffer = NULL;
+            DisplaySearchTimerList();
+            break; }
+        case rmsSearchTimerRecord: {
+            //caller: cRecMenuSearchTimerResults
+            const cEvent *ev = NULL;
+            if (cRecMenuSearchTimerResults *menu = dynamic_cast<cRecMenuSearchTimerResults*>(activeMenu)) {
+                ev = menu->GetEvent();
+            } else break;
+            if (!ev)
+                break;
+            recManager->createTimer(ev, "");
+            activeMenuBuffer2 = activeMenu;
+            activeMenuBuffer2->Hide();
+            activeMenu = new cRecMenuSearchConfirmTimer(ev, rmsFavoritesRecordConfirm);
+            activeMenu->Display();
+            break; }
+        /********************************************************************************************** 
+         *    SWITCH TIMER 
+         ***********************************************************************************************/
+        case rmsSwitchTimer:
+            delete activeMenu;
+            activeMenu = new cRecMenuSwitchTimer();
+            activeMenu->Display();
+            break;
+        case rmsSwitchTimerCreate: {
+            cSwitchTimer switchTimer;
+            if (cRecMenuSwitchTimer *menu = dynamic_cast<cRecMenuSwitchTimer*>(activeMenu)) {
+                switchTimer = menu->GetSwitchTimer();
+            } else break;
+            bool success = recManager->CreateSwitchTimer(event, switchTimer);
+            delete activeMenu;
+            activeMenu = new cRecMenuSwitchTimerConfirm(success);
+            activeMenu->Display();
+            break; }
+        case rmsSwitchTimerDelete: 
+            recManager->DeleteSwitchTimer(event);
+            delete activeMenu;
+            activeMenu = new cRecMenuSwitchTimerDelete();
+            activeMenu->Display();
+            break;
+        /********************************************************************************************** 
+         *    RECORDINGS SEARCH 
+         ***********************************************************************************************/
+        case rmsRecordingSearch: {
+            //caller: main menu or rmsRecordingSearchResult
+            std::string searchString = event->Title();
+            if (cRecMenuRecordingSearchResults *menu = dynamic_cast<cRecMenuRecordingSearchResults*>(activeMenu)) {
+                searchString = menu->GetSearchString();
+            };
+            delete activeMenu;
+            activeMenu = new cRecMenuRecordingSearch(searchString);
+            activeMenu->Display();
+            break; }
+        case rmsRecordingSearchResult:  {
+            //caller: cRecMenuRecordingSearch
+            std::string searchString;
+            if (cRecMenuRecordingSearch *menu = dynamic_cast<cRecMenuRecordingSearch*>(activeMenu)) {
+                searchString = menu->GetSearchString();
+            } else break;
+            delete activeMenu;
+            if (searchString.size() < 4) {
+                activeMenu = new cRecMenuRecordingSearch(searchString);
+            } else {
+                int numSearchResults = 0;
+                cRecording **searchResult = recManager->SearchForRecordings(searchString, numSearchResults);
+                if (numSearchResults == 0) {
+                    activeMenu = new cRecMenuRecordingSearchNotFound(searchString);
+                } else {
+                    activeMenu = new cRecMenuRecordingSearchResults(searchString, searchResult, numSearchResults);
+                }
+            }
+            activeMenu->Display();
+            break; }
+        /********************************************************************************************** 
+         *    SEARCH 
+         ***********************************************************************************************/
+        case rmsSearch:
+        case rmsSearchWithOptions: {
+            //caller: main menu, cRecMenuSearch, cRecMenuSearchResults
+            bool withOptions = false;
+            std::string searchString = event->Title();
+            if (cRecMenuSearch *menu = dynamic_cast<cRecMenuSearch*>(activeMenu)) {
+                withOptions = true;
+                searchString = menu->GetSearchString();
+            } else if (cRecMenuSearchResults *menu = dynamic_cast<cRecMenuSearchResults*>(activeMenu)) {
+                searchString = menu->GetSearchString();
+            }
+            delete activeMenu;
+            activeMenu = new cRecMenuSearch(searchString, withOptions);
+            activeMenu->Display();
+            break; }
+        case rmsSearchPerform: {
+            //caller: cRecMenuSearch
+            Epgsearch_searchresults_v1_0 epgSearchData;
+            if (cRecMenuSearch *menu = dynamic_cast<cRecMenuSearch*>(activeMenu)) {
+                epgSearchData = menu->GetEPGSearchStruct();
+            } else break;
+            std::string searchString = epgSearchData.query;
+            if (searchString.size() < 3) {
+                activeMenuBuffer = activeMenu;
+                activeMenuBuffer->Hide();
+                activeMenu = new cRecMenuSearchNothingFound(searchString, true);
+            } else {
+                int numSearchResults = 0;
+                const cEvent **searchResult = recManager->PerformSearch(epgSearchData, numSearchResults);
+                if (searchResult) {
+                    delete activeMenu;
+                    activeMenu = new cRecMenuSearchResults(searchString, searchResult, numSearchResults);
+                } else {
+                    activeMenuBuffer = activeMenu;
+                    activeMenuBuffer->Hide();
+                    activeMenu = new cRecMenuSearchNothingFound(searchString);
+                }
+            }
+            activeMenu->Display();
+            break; }
+        case rmsSearchNothingFoundConfirm:
+            delete activeMenu;
+            activeMenu = activeMenuBuffer;
+            activeMenuBuffer = NULL;
+            activeMenu->Show();
+            break;
+        case rmsSearchShowInfo: {
+            //caller: cRecMenuSearchResults, cRecMenuSearchTimerResults
+            const cEvent *ev = NULL;
+            if (cRecMenuSearchResults *menu = dynamic_cast<cRecMenuSearchResults*>(activeMenu)) {
+                ev = menu->GetEvent();
+            } else if (cRecMenuSearchTimerResults *menu = dynamic_cast<cRecMenuSearchTimerResults*>(activeMenu)) {
+                ev = menu->GetEvent();
+            } else break;
+            if (ev) {
+               DisplayDetailedView(ev);
+            }
+            break;}
+        case rmsSearchRecord: {
+            //caller: cRecMenuSearchResults
+            const cEvent *ev = NULL;
+            if (cRecMenuSearchResults *menu = dynamic_cast<cRecMenuSearchResults*>(activeMenu)) {
+                ev = menu->GetEvent();
+            } else break;
+            if (!ev)
+                break;
+            recManager->createTimer(ev, "");
+            activeMenuBuffer = activeMenu;
+            activeMenuBuffer->Hide();
+            activeMenu = new cRecMenuSearchConfirmTimer(ev, rmsSearchRecordConfirm);
+            activeMenu->Display();
+            break;}
+        case rmsSearchRecordConfirm:
+            delete activeMenu;
+            activeMenu = activeMenuBuffer;
+            activeMenuBuffer = NULL;
+            activeMenu->UpdateActiveMenuItem();
+            activeMenu->Show();
+            break;
+        /********************************************************************************************** 
+         *    CHECK FOR TIMER CONFLICTS 
+         ***********************************************************************************************/
+        case rmsTimerConflicts: {
+            //caller: main menu
+            //Show timer conflict
+            if (timerConflicts) {
+                delete timerConflicts;
+            }
+            timerConflicts = recManager->CheckTimerConflict();
+            delete activeMenu;
+            int numConflicts = timerConflicts->NumConflicts();
+            if (numConflicts > 0) {
+                activeMenu = new cRecMenuTimerConflicts(timerConflicts);
+            } else {
+                activeMenu = new cRecMenuNoTimerConflict();
+            }
+            activeMenu->Display();
+            break; }
+        case rmsTimerConflict: {
+            //caller: cRecMenuTimerConflicts
+            //Show timer conflict
+            if (!timerConflicts)
+                break;
+            int timerConflict;
+            if (cRecMenuTimerConflicts *menu = dynamic_cast<cRecMenuTimerConflicts*>(activeMenu)) {
+                timerConflict = menu->GetTimerConflict();
+            } else break;
+            timerConflicts->SetCurrentConflict(timerConflict);
+            delete activeMenu;
+            activeMenu = new cRecMenuTimerConflict(timerConflicts->GetCurrentConflict());
+            activeMenu->Display();
+            break; }
+        case rmsSearchRerunsTimerConflictMenu: {
+            //caller: cRecMenuTimerConflict
+            //Show reruns for timer from timer conflict
+            if (!timerConflicts)
+                break;
+            int timerConflict;
+            if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenu)) {
+                timerConflict = menu->GetTimerConflictIndex();
+            } else break;
+            int timerID = timerConflicts->GetCurrentConflictTimerID(timerConflict);
+            cTimer *timer = Timers.Get(timerID);
+            if (timer) {
+                const cEvent *event = timer->Event();
+                if (event) {
+                    int numReruns = 0;
+                    const cEvent **reruns = recManager->LoadReruns(event, numReruns);
+                    if (reruns && (numReruns > 0)) {
+                        activeMenuBuffer = activeMenu;
+                        activeMenuBuffer->Hide();
+                        activeMenu = new cRecMenuRerunResults(event, reruns, numReruns);
+                        activeMenu->Display();
+                    } else {
+                        activeMenuBuffer = activeMenu;
+                        activeMenuBuffer->Hide();
+                        activeMenu = new cRecMenuNoRerunsFound((event->Title())?event->Title():"");
+                        activeMenu->Display();
+                    }
+                }
+            }
+            break; }
+        case rmsTimerConflictIgnoreReruns: {
+            delete activeMenu;
+            activeMenu = activeMenuBuffer;
+            activeMenuBuffer = NULL;
+            activeMenu->Show();
+            break; }
+        case rmsTimerConflictRecordRerun: {
+            //caller: cRecMenuRerunResults
+            //buffer: cRecMenuTimerConflict
+            if (!activeMenuBuffer)
+                break;
+            if (!timerConflicts)
+                break;
+            const cEvent *replace;
+            int originalConflictIndex;
+            if (cRecMenuRerunResults *menu = dynamic_cast<cRecMenuRerunResults*>(activeMenu)) {
+                replace = menu->GetRerunEvent();
+            } else break;
+            if (cRecMenuTimerConflict *menu = dynamic_cast<cRecMenuTimerConflict*>(activeMenuBuffer)) {
+                originalConflictIndex = menu->GetTimerConflictIndex();
+            } else break;
+            int originalTimerID = timerConflicts->GetCurrentConflictTimerID(originalConflictIndex);
+            cTimer *timerOriginal = Timers.Get(originalTimerID);
+            if (replace && timerOriginal) {
+                recManager->DeleteTimer(timerOriginal->Event());
+                recManager->createTimer(replace);
+                delete activeMenu;
+                if (activeMenuBuffer) {
+                    delete activeMenuBuffer;
+                    activeMenuBuffer = NULL;
+                }
+                activeMenu = new cRecMenuConfirmRerunUsed(timerOriginal->Event(), replace);
+                activeMenu->Display();
+            }
+            break; }
+        /********************************************************************************************** 
+         *    TIMELINE
+         ***********************************************************************************************/
+       case rmsTimeline: {
+            if (timerConflicts) {
+                delete timerConflicts;
+            }
+            timerConflicts = recManager->CheckTimerConflict();
+            delete activeMenu;
+            activeMenu = new cRecMenuTimeline(timerConflicts);
+            activeMenu->Display();
+            break; } 
+        case rmsTimelineTimerEdit: {
+            cTimer *timer;
+            if (cRecMenuTimeline *menu = dynamic_cast<cRecMenuTimeline*>(activeMenu)) {
+                timer = menu->GetTimer();
+            } else break;
+            if (timer) {
+                delete activeMenu;
+                activeMenu = new cRecMenuEditTimer(timer, rmsTimelineTimerSave);
+                activeMenu->Display();
+            }
+            break;}
+        case rmsTimelineTimerSave: {
+            cTimer timerModified;
+            cTimer *originalTimer;
+            if (cRecMenuEditTimer *menu = dynamic_cast<cRecMenuEditTimer*>(activeMenu)) {
+                timerModified = menu->GetTimer();
+                originalTimer = menu->GetOriginalTimer();
+            } else break;
+            recManager->SaveTimer(originalTimer, timerModified);
+            delete activeMenu;
+            if (timerConflicts) {
+                delete timerConflicts;
+            }
+            timerConflicts = recManager->CheckTimerConflict();
+            activeMenu = new cRecMenuTimeline(timerConflicts);
+            activeMenu->Display();
+            break; }
+        case rmsTimelineTimerDelete: {
+            cTimer *timer;
+            if (cRecMenuEditTimer *menu = dynamic_cast<cRecMenuEditTimer*>(activeMenu)) {
+                timer = menu->GetOriginalTimer();
+            } else break;
+            recManager->DeleteTimer(timer);
+            delete activeMenu;
+            if (timerConflicts) {
+                delete timerConflicts;
+            }
+            timerConflicts = recManager->CheckTimerConflict();
+            activeMenu = new cRecMenuTimeline(timerConflicts);
+            activeMenu->Display();
+            break; }
+        /********************************************************************************************** 
+         *    FAVORITES
+         *********************************************************************************************/
+        case rmsFavoritesRecord: {
+            //caller: cRecMenuSearchTimerResults
+            const cEvent *ev = NULL;
+            if (cRecMenuSearchTimerResults *menu = dynamic_cast<cRecMenuSearchTimerResults*>(activeMenu)) {
+                ev = menu->GetEvent();
+            } else break;
+            if (!ev)
+                break;
+            recManager->createTimer(ev, "");
+            activeMenuBuffer2 = activeMenu;
+            activeMenuBuffer2->Hide();
+            activeMenu = new cRecMenuSearchConfirmTimer(ev, rmsFavoritesRecordConfirm);
+            activeMenu->Display();
+            break;}
+        case rmsFavoritesRecordConfirm:
+            delete activeMenu;
+            activeMenu = activeMenuBuffer2;
+            activeMenuBuffer2 = NULL;
+            activeMenu->UpdateActiveMenuItem();
+            activeMenu->Show();
+            break;
+        case rmsFavoritesNow:
+        case rmsFavoritesNext: {
+            int numResults = 0;
+            bool nowOrNext;
+            std::string header;
+            if (nextState == rmsFavoritesNow) {
+                nowOrNext = true;
+                header = tr("What's on now");
+            } else {
+                nowOrNext = false;
+                header = tr("What's on next");
+            }
+            const cEvent **result = recManager->WhatsOnNow(nowOrNext, numResults);
+            DisplayFavoriteResults(header, result, numResults);
+            break; }
+        case rmsFavoritesUser1: {
+            int numResults = 0;
+            const cEvent **result = recManager->UserDefinedTime(1, numResults);
+            DisplayFavoriteResults(tvguideConfig.descUser1, result, numResults);
+            break; }
+        case rmsFavoritesUser2: {
+            int numResults = 0;
+            const cEvent **result = recManager->UserDefinedTime(2, numResults);
+            DisplayFavoriteResults(tvguideConfig.descUser2, result, numResults);
+            break; }
+        case rmsFavoritesUser3: {
+            int numResults = 0;
+            const cEvent **result = recManager->UserDefinedTime(3, numResults);
+            DisplayFavoriteResults(tvguideConfig.descUser3, result, numResults);
+            break; }
+        case rmsFavoritesUser4: {
+            int numResults = 0;
+            const cEvent **result = recManager->UserDefinedTime(4, numResults);
+            DisplayFavoriteResults(tvguideConfig.descUser4, result, numResults);
+            break; }
+
+        /********************************************************************************************** 
+         *    COMMON
+         *********************************************************************************************/
+        case rmsClose: {
+            if (activeMenuBuffer == NULL) {
+                state = osEnd;
+                Close();
+            } else {
+                delete activeMenu;
+                activeMenu = activeMenuBuffer;
+                activeMenuBuffer = NULL;
+                activeMenu->UpdateActiveMenuItem();
+                activeMenu->Show();
+                state = osContinue;
+            }
+            break; }
+        default:        
+            break;
+    }
+    return state;
+}
+
+void cRecMenuManager::DisplayFavoriteResults(std::string header, const cEvent **result, int numResults) {
+    if (numResults) {
+        activeMenuBuffer = activeMenu;
+        activeMenuBuffer->Hide();
+        activeMenu = new cRecMenuSearchTimerResults(header, result, numResults, "", rmsFavoritesRecord);
+        activeMenu->Display();
+    } else {
+        activeMenuBuffer = activeMenu;
+        activeMenuBuffer->Hide();
+        activeMenu = new cRecMenuSearchTimerNothingFound(header);
+        activeMenu->Display();
+    }
+}
+
+void cRecMenuManager::DisplaySearchTimerList(void) {
+    delete activeMenu;
+    std::vector<cTVGuideSearchTimer> searchTimers;
+    recManager->GetSearchTimers(&searchTimers);
+    activeMenu = new cRecMenuSearchTimers(searchTimers);
+    activeMenu->Display();
+}
+
+bool cRecMenuManager::DisplayTimerConflict(cTimer *timer) {
+    int timerID = 0;
+    for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) {
+        if (t == timer)
+            return DisplayTimerConflict(timerID);
+        timerID++;
+    }
+    return false;
+}
+
+bool cRecMenuManager::DisplayTimerConflict(int timerID) {
+    if (timerConflicts)
+        delete timerConflicts;
+    timerConflicts = recManager->CheckTimerConflict();
+    if (!timerConflicts)
+        return false;
+    int showTimerConflict = timerConflicts->GetCorrespondingConflict(timerID);
+    if (showTimerConflict > -1) {
+        timerConflicts->SetCurrentConflict(showTimerConflict);
+        cTVGuideTimerConflict *conflict = timerConflicts->GetCurrentConflict();
+        if (!conflict)
+            return false;
+        activeMenu = new cRecMenuTimerConflict(conflict);
+        activeMenu->Display();
+        return true;
+    }
+    return false;
+}
+
+void cRecMenuManager::DisplayDetailedView(const cEvent *ev) {
+    activeMenu->Hide();
+    detailView = new cDetailView(ev, footer);
+    footer->SetDetailedViewMode(true);
+    detailView->Start();
+    detailViewActive = true;
+}
+
+eOSState cRecMenuManager::ProcessKey(eKeys Key) {
+    eOSState state = osContinue;
+    eRecMenuState nextState = rmsContinue;
+    if (!activeMenu)
+        return state;
+    if (detailViewActive) {
+        state = detailView->ProcessKey(Key);
+        if (state == osEnd) {
+            delete detailView;
+            detailView = NULL;
+            detailViewActive = false;
+            activeMenu->Show();
+            state = osContinue;
+        }
+    } else {
+        nextState = activeMenu->ProcessKey(Key);
+        if ((nextState == rmsClose) || ((nextState == rmsNotConsumed)&&(Key == kBack))){
+            if (activeMenuBuffer == NULL) {
+                state = osEnd;
+                Close();
+            } else {
+                delete activeMenu;
+                activeMenu = activeMenuBuffer;
+                activeMenuBuffer = NULL;
+                activeMenu->UpdateActiveMenuItem();
+                activeMenu->Show();
+                state = osContinue;
+                osdManager.flush();
+            }
+            return state;
+        }
+        state = StateMachine(nextState);
+    }
+    osdManager.flush();
+    return state;
+}
\ No newline at end of file
diff --git a/recmenumanager.h b/recmenumanager.h
new file mode 100644
index 0000000..9448c12
--- /dev/null
+++ b/recmenumanager.h
@@ -0,0 +1,42 @@
+#ifndef __TVGUIDE_RECMENUMANAGER_H
+#define __TVGUIDE_RECMENUMANAGER_H
+
+#include "recmenu.h"
+#include "recmanager.h"
+#include "services/epgsearch.h"
+#include "footer.h"
+
+// --- cRecMenuManager  -------------------------------------------------------------
+class cRecMenuManager {
+private:
+    cFooter *footer;
+    bool active;
+    cRecMenu *activeMenu;
+    cRecMenu *activeMenuBuffer;
+    cRecMenu *activeMenuBuffer2;
+    const cEvent *event;
+    cRecManager *recManager;
+    cTVGuideTimerConflicts *timerConflicts;
+    cDetailView *detailView;
+    cPixmap *pixmapBackground;
+    bool detailViewActive;
+    void SetBackground(void);
+    void DeleteBackground(void);
+    void DisplaySearchTimerList(void);
+    bool DisplayTimerConflict(cTimer *timer);
+    bool DisplayTimerConflict(int timerID);
+    void DisplayDetailedView(const cEvent *ev);
+    void DisplayFavoriteResults(std::string header, const cEvent **result, int numResults);
+public:
+    cRecMenuManager(void);
+    virtual ~cRecMenuManager(void);
+    void SetFooter(cFooter *footer) { this->footer = footer; };
+    bool isActive(void) { return active; };
+    void Start(const cEvent *event);
+    void StartFavorites(void);
+    void Close(void);
+    eOSState StateMachine(eRecMenuState nextState);
+    eOSState ProcessKey(eKeys Key);
+};
+
+#endif //__TVGUIDE_RECMENUMANAGER_H
\ No newline at end of file
diff --git a/recmenus.c b/recmenus.c
new file mode 100644
index 0000000..701ffd9
--- /dev/null
+++ b/recmenus.c
@@ -0,0 +1,1561 @@
+#include "services/remotetimers.h"
+#include "tools.h"
+#include "recmenumanager.h"
+#include "recmenus.h"
+
+// --- cRecMenuMain  ---------------------------------------------------------
+cRecMenuMain::cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive) {
+    eRecMenuState action = rmsInstantRecord;
+    if (!timerActive) {
+        if (tvguideConfig.instRecFolderMode == eFolderSelect)
+            action = rmsInstantRecordFolder;
+        AddMenuItem(new cRecMenuItemButton(tr("Instant Record"), action, true, false, false, true));
+    } else {
+        AddMenuItem(new cRecMenuItemButton(tr("Delete Timer"), rmsDeleteTimer, true, false, false, true));
+        AddMenuItem(new cRecMenuItemButton(tr("Edit Timer"), rmsEditTimer, false, false, false, true));
+    }
+
+    AddMenuItem(new cRecMenuItemButton(tr("Timer Timeline"), rmsTimeline, false, false, false, true));
+
+    if (epgSearchAvailable) {
+        AddMenuItem(new cRecMenuItemButton(tr("Create Search Timer"), rmsSearchTimer, false, false, false, true));
+        AddMenuItem(new cRecMenuItemButton(tr("Search Timers"), rmsSearchTimers, false, false, false, true));
+    }
+
+    if (tvguideConfig.instRecFolderMode == eFolderSelect)
+        action = rmsSeriesTimerFolder;
+    else
+        action = rmsSeriesTimer;
+    AddMenuItem(new cRecMenuItemButton(tr("Create Series Timer"), action, false, false, false, true));
+
+    if (epgSearchAvailable) {
+        if (!switchTimerActive) {
+            AddMenuItem(new cRecMenuItemButton(tr("Create Switch Timer"), rmsSwitchTimer, false, false, false, true));
+        } else {
+            AddMenuItem(new cRecMenuItemButton(tr("Delete Switch Timer"), rmsSwitchTimerDelete, false, false, false, true));
+        }
+        AddMenuItem(new cRecMenuItemButton(tr("Search"), rmsSearch, false, false, false, true));
+    }
+
+    if (epgSearchAvailable) {
+        AddMenuItem(new cRecMenuItemButton(tr("Check for Timer Conflicts"), rmsTimerConflicts, false, false, false, true));
+    }
+
+    AddMenuItem(new cRecMenuItemButton(tr("Search in Recordings"), rmsRecordingSearch, false, false, false, true));
+
+    int menuWidth = CalculateOptimalWidth() + 4 * border;
+    SetWidthPixel(menuWidth);
+            
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+};
+
+/******************************************************************************************
+*   Instant Timer Menus
+******************************************************************************************/
+
+// --- cRecMenuAskFolder  ---------------------------------------------------------
+cRecMenuAskFolder::cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction) {
+    SetWidthPercent(80);
+    NextAction = nextAction;
+    cString message = tr("Set Folder for");
+    cString headerText = cString::sprintf("%s\n\"%s\"", *message, event->Title());
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*headerText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    
+    AddMenuItemInitial(new cRecMenuItemButton(tr("root video folder"), nextAction, true, false, true));
+    
+    ReadRecordingDirectories(&folders, NULL, "");
+    int numFolders = folders.size();
+    for (int i=0; i < numFolders; i++) {
+        if (!AddMenuItemInitial(new cRecMenuItemButton(folders[i].c_str(), nextAction, false, false, true)))
+            break;
+    }
+    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cRecMenuItem *cRecMenuAskFolder::GetMenuItem(int number) { 
+    if (number == 0) {
+        cRecMenuItem *result = new cRecMenuItemButton(tr("root video folder"), rmsInstantRecord, false, false, true);
+        return result;
+    } else if ((number > 0) && (number < folders.size()+1)) {
+        cRecMenuItem *result = new cRecMenuItemButton(folders[number-1].c_str(), rmsInstantRecord, false, false, true);
+        return result;
+    }
+    return NULL;
+}
+
+int cRecMenuAskFolder::GetTotalNumMenuItems(void) { 
+    return folders.size()+1;
+}
+
+std::string cRecMenuAskFolder::GetFolder(void) {
+    std::string folder = "";
+    int folderActive = GetActive();
+    if (folderActive > 0 && folderActive < folders.size() + 1)
+        folder = folders[folderActive - 1];
+    return folder;
+}
+
+// --- cRecMenuConfirmTimer  ---------------------------------------------------------
+cRecMenuConfirmTimer::cRecMenuConfirmTimer(const cEvent *event) {
+    SetWidthPercent(50);
+    cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
+    cString message;
+    bool eventHasTimer = false;
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        RemoteTimers_GetMatch_v1_0 rtMatch;
+        rtMatch.event = event;
+        pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+        if (rtMatch.timerMatch == tmFull) {
+            eventHasTimer = true;                
+        }
+    } else {
+        eventHasTimer = event->HasTimer();
+    }
+    if (eventHasTimer) {
+        message = tr("Timer created");
+    } else {
+        message = tr("Timer NOT created");
+    }
+    cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s", 
+                                    *message, 
+                                    *channelName,
+                                    *event->GetDateString(),
+                                    *event->GetTimeString(),
+                                    *event->GetEndTimeString(),
+                                    event->Title()
+                                );
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuConfirmDeleteTimer  ---------------------------------------------------------
+cRecMenuConfirmDeleteTimer::cRecMenuConfirmDeleteTimer(const cEvent *event) {
+    SetWidthPercent(50);
+    cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
+    cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s", 
+                                    tr("Timer deleted"), 
+                                    *channelName,
+                                    *event->GetDateString(),
+                                    *event->GetTimeString(),
+                                    *event->GetEndTimeString(),
+                                    event->Title()
+                                );
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 4 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuAskDeleteTimer ---------------------------------------------------------
+cRecMenuAskDeleteTimer::cRecMenuAskDeleteTimer(const cEvent *event) {
+    SetWidthPercent(50);
+    cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
+    cString text = cString::sprintf("%s \"%s, %s\" %s", 
+                                    tr("Timer"),
+                                    *channelName,
+                                    event->Title(),
+                                    tr("still recording - really delete?"));
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 4 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Yes"), tr("No"), rmsDeleteTimerConfirmation, rmsClose, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuTimerConflicts  ---------------------------------------------------------
+cRecMenuTimerConflicts::cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts) {
+    int numConflicts = conflicts->NumConflicts();
+    
+    cString text;
+    if (numConflicts == 1) {
+        text = cString::sprintf("%s %s %s", tr("One"), tr("Timer Conflict"), tr("detected"));
+    } else {
+        text = cString::sprintf("%d %s %s", conflicts->NumConflicts(), tr("Timer Conflicts"), tr("detected"));
+    }
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text, true);
+    
+    for (int i=0; i<numConflicts; i++) {
+        cTVGuideTimerConflict *conflict = conflicts->GetConflict(i);
+        if (!conflict)
+            continue;
+        cString dateTime = DayDateTime(conflict->time);
+        int numTimers = conflict->timerIDs.size();
+        cString textConflict = cString::sprintf("%s: %s (%d %s)", tr("Show conflict"), *dateTime, numTimers, tr("timers involved"));
+        bool isActive = (i==0)?true:false;
+        AddMenuItem(new cRecMenuItemButton(*textConflict, rmsTimerConflict, isActive));
+    }
+    
+    SetWidthPixel(CalculateOptimalWidth() + 4*border);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("Ignore Conflicts"), rmsClose, false));
+    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+int cRecMenuTimerConflicts::GetTimerConflict(void) {
+    return GetActive();
+}
+
+// --- cRecMenuTimerConflict  ---------------------------------------------------------
+cRecMenuTimerConflict::cRecMenuTimerConflict(cTVGuideTimerConflict *conflict) {
+    SetWidthPercent(95);
+    this->conflict = conflict;
+    SetHeader(new cRecMenuItemTimerConflictHeader(conflict->timeStart, 
+                                                  conflict->timeStop, 
+                                                  conflict->overlapStart, 
+                                                  conflict->overlapStop));
+    SetFooter(new cRecMenuItemButton(tr("Ignore Conflict"), rmsIgnoreTimerConflict, false, true));
+    int i=0;
+    for(std::vector<int>::iterator it = conflict->timerIDs.begin(); it != conflict->timerIDs.end(); it++) {
+        const cTimer *timer = Timers.Get(*it);
+        if (timer) {
+            if (!AddMenuItemInitial(new cRecMenuItemTimer(  timer,
+                                                      rmsTimerConflictShowInfo,
+                                                      rmsDeleteTimerConflictMenu, 
+                                                      rmsEditTimerConflictMenu,
+                                                      rmsSearchRerunsTimerConflictMenu,
+                                                      conflict->timeStart, 
+                                                      conflict->timeStop, 
+                                                      conflict->overlapStart, 
+                                                      conflict->overlapStop, 
+                                                      (!i)?true:false)
+            ))
+                break;
+            i++;
+        }
+    }
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+    
+cRecMenuItem *cRecMenuTimerConflict::GetMenuItem(int number) { 
+    if ((number >= 0) && (number < conflict->timerIDs.size())) {
+        const cTimer *timer = Timers.Get(conflict->timerIDs[number]);
+        cRecMenuItem *result = new cRecMenuItemTimer( timer,
+                                                      rmsTimerConflictShowInfo,
+                                                      rmsDeleteTimerConflictMenu, 
+                                                      rmsEditTimerConflictMenu,
+                                                      rmsSearchRerunsTimerConflictMenu,
+                                                      conflict->timeStart, 
+                                                      conflict->timeStop, 
+                                                      conflict->overlapStart, 
+                                                      conflict->overlapStop, 
+                                                      false);
+        return result;
+    }
+    return NULL;
+}
+
+int cRecMenuTimerConflict::GetTotalNumMenuItems(void) { 
+    return conflict->timerIDs.size(); 
+}
+
+int cRecMenuTimerConflict::GetTimerConflictIndex(void) {
+    return GetActive();
+}
+
+// --- cRecMenuNoTimerConflict ---------------------------------------------------------
+cRecMenuNoTimerConflict::cRecMenuNoTimerConflict(void) {
+    SetWidthPercent(50);
+    cString text = tr("No Timer Conflicts found");
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 4 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("Close"), rmsClose, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuRerunResults ---------------------------------------------------------
+cRecMenuRerunResults::cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns) {
+    this->reruns = reruns;
+    this->numReruns = numReruns;
+    SetWidthPercent(70);
+    this->numReruns = numReruns;
+    cString message1 = tr("reruns for");
+    cString message2 = tr("rerun for");
+    cString message3 = tr("found");
+    cString infoText = cString::sprintf("%d %s:\n\"%s\" %s", numReruns, (numReruns>1)?(*message1):(*message2), original->Title(), *message3);
+    cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    
+    cRecMenuItem *button = new cRecMenuItemButton(tr("Ignore reruns"), rmsTimerConflictIgnoreReruns, false);
+    SetFooter(button);
+    
+    if (reruns && (numReruns > 0)) {
+        for (int i=0; i<numReruns; i++) {
+            if (!AddMenuItemInitial(new cRecMenuItemEvent(reruns[i], rmsSearchShowInfo, rmsTimerConflictRecordRerun, (i==0)?true:false)))
+                break;
+        }
+    }
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cRecMenuItem *cRecMenuRerunResults::GetMenuItem(int number) {
+   if ((number >= 0) && (number < numReruns)) {
+        cRecMenuItem *result = new cRecMenuItemEvent(reruns[number], rmsSearchShowInfo, rmsTimerConflictRecordRerun, false);
+        return result;
+    }
+    return NULL;
+}
+
+int cRecMenuRerunResults::GetTotalNumMenuItems(void) {
+    return numReruns;
+}
+
+const cEvent *cRecMenuRerunResults::GetRerunEvent(void) {
+    cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem());
+    return activeItem->GetEventValue();
+}
+
+// --- cRecMenuNoRerunsFound  ---------------------------------------------------------
+cRecMenuNoRerunsFound::cRecMenuNoRerunsFound(cString searchString) {
+    SetWidthPercent(50);
+    cString message = tr("No reruns found for Event");
+    cString text = cString::sprintf("%s\n\"%s\"", 
+                                    *message, 
+                                    *searchString);
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsTimerConflictIgnoreReruns, true, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuConfirmRerunUsed  ---------------------------------------------------------
+cRecMenuConfirmRerunUsed::cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace) {
+    SetWidthPercent(70);
+    cString channelOrig = Channels.GetByChannelID(original->ChannelID())->Name();
+    cString channelReplace = Channels.GetByChannelID(replace->ChannelID())->Name();
+    cString message1 = tr("Timer for");
+    cString message2 = tr("replaced by rerun");
+    cString text = cString::sprintf("%s\n\"%s\", %s %s, %s\n%s\n\"%s\", %s %s, %s", 
+                                    *message1, 
+                                    original->Title(),
+                                    *original->GetDateString(),
+                                    *original->GetTimeString(),
+                                    *channelOrig,
+                                    *message2,
+                                    replace->Title(),
+                                    *replace->GetDateString(),
+                                    *replace->GetTimeString(),
+                                    *channelReplace);
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsTimerConflicts, true, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuEditTimer  ---------------------------------------------------------
+cRecMenuEditTimer::cRecMenuEditTimer(cTimer *timer, eRecMenuState nextState) {
+    SetWidthPercent(70);
+    if (!timer)
+        return;
+    originalTimer = timer;
+    cString title("");
+    cString channelName("");
+    if (timer->Event())
+        title = timer->Event()->Title();
+    if (timer->Channel())
+        channelName = timer->Channel()->Name();
+    cString infoText = cString::sprintf("%s:\n %s, %s", tr("Edit Timer"), *title, *channelName);
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItemInitial(infoItem);
+                
+    timerActive = false;
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        RemoteTimers_GetMatch_v1_0 rtMatch;
+        rtMatch.event = timer->Event();
+        pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+        if (rtMatch.timer) {
+            if (rtMatch.timerMatch == tmFull)
+                timerActive = true;
+        }
+    } else
+        timerActive = timer->HasFlags(tfActive);
+
+    day = timer->Day();
+    start = timer->Start();
+    stop = timer->Stop();
+    prio = timer->Priority();
+    lifetime = timer->Lifetime();
+    strncpy(folder, GetDirectoryFromTimer(timer->File()).c_str(), TEXTINPUTLENGTH);
+    
+    AddMenuItemInitial(new cRecMenuItemBool(tr("Timer Active"), timerActive, false, true, &timerActive));
+    AddMenuItemInitial(new cRecMenuItemInt(tr("Priority"), prio, 0, MAXPRIORITY, false, &prio));
+    AddMenuItemInitial(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, MAXLIFETIME, false, &lifetime));
+    AddMenuItemInitial(new cRecMenuItemDay(tr("Day"), day, false, &day));
+    AddMenuItemInitial(new cRecMenuItemTime(tr("Timer start time"), start, false, &start));
+    AddMenuItemInitial(new cRecMenuItemTime(tr("Timer stop time"), stop, false, &stop));
+    cString fileInfo = cString::sprintf("%s:\n%s", tr("Timer File"), timer->File());
+    cRecMenuItemInfo *fileInfoItem = new cRecMenuItemInfo(*fileInfo, false);
+    fileInfoItem->CalculateHeight(width - 2 * border);
+    AddMenuItemInitial(fileInfoItem);
+    AddMenuItemInitial(new cRecMenuItemSelectDirectory(tr("New Folder"), std::string(folder), false, folder));
+    if (nextState == rmsTimelineTimerSave) {
+        AddMenuItemInitial(new cRecMenuItemButton(tr("Delete Timer"), rmsTimelineTimerDelete, false, false));
+        AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsTimeline, false));
+    } else {
+        AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Save"), tr("Cancel"), nextState, rmsClose, false));
+    }
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cTimer *cRecMenuEditTimer::GetOriginalTimer(void) {
+    return originalTimer;
+}
+
+cTimer cRecMenuEditTimer::GetTimer(void) {
+    cTimer t;
+    if (timerActive)
+        t.SetFlags(tfActive);
+    else 
+        t.SetFlags(tfNone);
+    t.SetDay(day);
+    t.SetStart(start);
+    t.SetStop(stop);
+    t.SetPriority(prio);
+    t.SetLifetime(lifetime);
+    std::string newFolder(folder);
+    std::string newFile = originalTimer->File();
+    size_t found = newFile.find_last_of('~');
+    if (found != std::string::npos) {
+        std::string fileName = newFile.substr(found+1);
+        if (newFolder.size() > 0)
+            newFile = *cString::sprintf("%s~%s", newFolder.c_str(), fileName.c_str());
+        else
+            newFile = fileName;
+    } else {
+        if (newFolder.size() > 0)
+            newFile = *cString::sprintf("%s~%s", newFolder.c_str(), newFile.c_str());
+    }
+    std::replace(newFile.begin(), newFile.end(), '/', '~');
+    t.SetFile(newFile.c_str());
+    return t;
+}
+
+/******************************************************************************************
+*   Series Timer Menus
+******************************************************************************************/
+
+// --- cRecMenuSeriesTimer ---------------------------------------------------------
+cRecMenuSeriesTimer::cRecMenuSeriesTimer(cChannel *initialChannel, const cEvent *event, std::string folder) {
+    if (!initialChannel)
+        return;
+    timerActive = true;
+    channel = initialChannel->Number();
+    dayOfWeek = 127; 
+    priority =  MAXPRIORITY;
+    lifetime = MAXLIFETIME;
+    CalculateTimes(event);
+    this->folder = folder;
+
+    SetWidthPercent(70);
+    cString title = tr("Create Series Timer based on");
+    cString infoText = cString::sprintf("%s:\n%s", *title, event->Title());
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+
+    AddMenuItem(new cRecMenuItemBool(tr("Timer Active"), timerActive, false, false, &timerActive));
+    AddMenuItem(new cRecMenuItemChannelChooser(tr("Channel"), initialChannel, false, &channel));
+    AddMenuItem(new cRecMenuItemTime(tr("Series Timer start time"), start, false, &start));
+    AddMenuItem(new cRecMenuItemTime(tr("Series Timer stop time"), stop, false, &stop));
+    AddMenuItem(new cRecMenuItemDayChooser(tr("Days to record"), dayOfWeek, false, &dayOfWeek));
+    AddMenuItem(new cRecMenuItemDay(tr("Day to start"), tstart, false, &tstart));
+    AddMenuItem(new cRecMenuItemInt(tr("Priority"), priority, 0, MAXPRIORITY, false, &priority));
+    AddMenuItem(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, MAXLIFETIME, false, &lifetime));
+
+    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create Timer"), tr("Cancel"), rmsSeriesTimerCreate, rmsClose, true));
+
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cTimer *cRecMenuSeriesTimer::GetTimer(void) {
+    cChannel *chan = Channels.GetByNumber(channel);
+    cTimer *seriesTimer = new cTimer(NULL, NULL, chan);
+    cString fileName = "TITLE EPISODE";
+    if (folder.size() > 0) {
+        std::replace(folder.begin(), folder.end(), '/', '~');
+        fileName = cString::sprintf("%s~%s", folder.c_str(), *fileName);
+    }
+    seriesTimer->SetDay(tstart);
+    seriesTimer->SetStart(start);
+    seriesTimer->SetStop(stop);
+    seriesTimer->SetPriority(priority);
+    seriesTimer->SetLifetime(lifetime);
+    seriesTimer->SetWeekDays(dayOfWeek);
+    seriesTimer->SetFile(*fileName);
+    if (timerActive)
+        seriesTimer->SetFlags(tfActive);
+    else 
+        seriesTimer->SetFlags(tfNone);
+    return seriesTimer;
+}
+
+void cRecMenuSeriesTimer::CalculateTimes(const cEvent *event) {
+    tstart = event->StartTime();
+    tstart -= Setup.MarginStart * 60;
+    time_t tstop = tstart + event->Duration();
+    tstop  += Setup.MarginStop * 60;
+    
+    struct tm tm_r;
+    struct tm *time = localtime_r(&tstart, &tm_r);
+    start = time->tm_hour * 100 + time->tm_min;
+    time = localtime_r(&tstop, &tm_r);
+    stop = time->tm_hour * 100 + time->tm_min;
+    if (stop >= 2400)
+        stop -= 2400;
+}
+
+// --- cRecMenuConfirmSeriesTimer  ---------------------------------------------------------
+cRecMenuConfirmSeriesTimer::cRecMenuConfirmSeriesTimer(cTimer *seriesTimer) {
+    SetWidthPercent(50);
+    cString message = tr("Series Timer created");
+    cString infoText = message;
+    if (seriesTimer) {
+        cString days = cTimer::PrintDay(seriesTimer->Day(), seriesTimer->WeekDays(), true);
+        infoText = cString::sprintf("%s\n%s, %s: %s, %s: %s", *message, *days, tr("Start"), *TimeString(seriesTimer->StartTime()), tr("Stop"), *TimeString(seriesTimer->StopTime()));
+    }
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+/******************************************************************************************
+*   SearchTimer Menus
+******************************************************************************************/
+
+// --- cRecMenuSearchTimer  ---------------------------------------------------------
+cRecMenuSearchTimer::cRecMenuSearchTimer(const cEvent *event) {
+    SetWidthPercent(70);
+    cString message = tr("Configure Search Timer based on");
+    cString infoText = cString::sprintf("%s:\n\"%s\"", *message, event->Title());
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    strncpy(searchString, event->Title(), TEXTINPUTLENGTH);
+    AddMenuItemInitial(new cRecMenuItemText(tr("Search Expression:"), searchString, TEXTINPUTLENGTH, false));
+    AddMenuItemInitial(new cRecMenuItemButtonYesNo(tr("Continue"), tr("Cancel"), rmsSearchTimerOptions, rmsClose, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuSearchTimerTemplates  ---------------------------------------------------------
+cRecMenuSearchTimerTemplates::cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, std::vector<TVGuideEPGSearchTemplate> templates) {
+    this->searchTimer = searchTimer;
+    this->templates = templates;
+    SetWidthPercent(70);
+    cString message = tr("Configure Search Timer for Search String");
+    cString infoText = cString::sprintf("%s:\n%s", *message, searchTimer.SearchString().c_str());
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    
+    AddMenuItemInitial(new cRecMenuItemButton(tr("Manually configure Options"), rmsSearchTimerEdit, true));
+    
+    numTemplates = templates.size();
+    for (int i=0; i<numTemplates; i++) {
+        cString buttonText = cString::sprintf("%s \"%s\"", tr("Use Template"), templates[i].name.c_str());
+        if (!AddMenuItemInitial(new cRecMenuItemButton(*buttonText, rmsSearchTimerCreateWithTemplate, false)))
+            break;
+    }
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+    
+cRecMenuItem *cRecMenuSearchTimerTemplates::GetMenuItem(int number) {
+    if (number == 0) {
+        return new cRecMenuItemButton(tr("Manually configure Options"), rmsSearchTimerEdit, false);
+    } else if ((number > 0) && (number < numTemplates + 1)) {
+        cString buttonText = cString::sprintf("%s \"%s\"", tr("Use Template"), templates[number-1].name.c_str());
+        cRecMenuItem *templ = new cRecMenuItemButton(*buttonText, rmsSearchTimerCreateWithTemplate, false);
+        return templ;
+    }
+    return NULL;
+}
+
+int cRecMenuSearchTimerTemplates::GetTotalNumMenuItems(void) { 
+    return numTemplates + 1;
+}
+
+TVGuideEPGSearchTemplate cRecMenuSearchTimerTemplates::GetTemplate(void) {
+    TVGuideEPGSearchTemplate templ;
+    int tmplActive = GetActive() - 1;
+    if (tmplActive >= 0 && tmplActive < templates.size())
+        templ = templates[tmplActive];
+    return templ;
+}
+// --- cRecMenuSearchTimers  ---------------------------------------------------------
+cRecMenuSearchTimers::cRecMenuSearchTimers(std::vector<cTVGuideSearchTimer> searchTimers) {
+    this->searchTimers = searchTimers;
+    numSearchTimers = searchTimers.size();
+    SetWidthPercent(70);
+    cString headline;
+    if (numSearchTimers > 0) {
+        headline = tr("EPGSearch Search Timers");
+    } else {
+        headline = tr("No Search Timers Configured");
+    } 
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*headline, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (!numSearchTimers)?true:false);
+    SetFooter(button);
+    if (numSearchTimers > 0)
+        SetMenuItems();    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cRecMenuSearchTimers::~cRecMenuSearchTimers(void) {
+
+}
+
+void cRecMenuSearchTimers::SetMenuItems(void) {
+    for (int i = 0; i < numSearchTimers; i++) {
+        if (!AddMenuItemInitial(new cRecMenuItemSearchTimer(searchTimers[i], rmsSearchTimerTest, rmsSearchTimerEdit, rmsSearchTimerDeleteConfirm, (i==0)?true:false)))
+            break;
+    }
+}
+
+cTVGuideSearchTimer cRecMenuSearchTimers::GetSearchTimer(void) {
+    cRecMenuItemSearchTimer *activeItem = dynamic_cast<cRecMenuItemSearchTimer*>(GetActiveMenuItem());
+    return activeItem->GetTimer();
+}
+
+cRecMenuItem *cRecMenuSearchTimers::GetMenuItem(int number) {
+    if (number < 0 || number >= numSearchTimers)
+        return NULL;
+    return new cRecMenuItemSearchTimer(searchTimers[number], rmsSearchTimerTest, rmsSearchTimerEdit, rmsSearchTimerDeleteConfirm, false);
+}
+
+int cRecMenuSearchTimers::GetTotalNumMenuItems(void) {
+    return numSearchTimers;
+}
+
+// --- cRecMenuSearchTimerEdit  ---------------------------------------------------------
+cRecMenuSearchTimerEdit::cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, bool advancedOptions) {
+    deleteMenuItems = false;
+    this->advancedOptions = advancedOptions;
+    this->searchTimer = searchTimer;
+    strncpy(searchString, searchTimer.SearchString().c_str(), TEXTINPUTLENGTH);
+    timerActive = searchTimer.Active();
+    mode = searchTimer.SearchMode();
+    useTitle = searchTimer.UseTitle();
+    useSubtitle = searchTimer.UseSubtitle();
+    useDescription = searchTimer.UseDescription();
+    useChannel = searchTimer.UseChannel();
+    startChannel = searchTimer.StartChannel();
+    stopChannel = searchTimer.StopChannel();
+    useTime = searchTimer.UseTime();
+    startTime = searchTimer.StartTime();
+    stopTime = searchTimer.StopTime();
+    useDayOfWeek = searchTimer.UseDayOfWeek();
+    dayOfWeek = searchTimer.DayOfWeek();
+    priority = searchTimer.Priority();
+    lifetime = searchTimer.Lifetime();
+    useEpisode = searchTimer.UseEpisode();
+    std::string dir = searchTimer.Directory();
+    strncpy(directory, dir.c_str(), TEXTINPUTLENGTH);
+    marginStart = searchTimer.MarginStart();
+    marginStop = searchTimer.MarginStop();
+    useVPS = searchTimer.UseVPS();
+    avoidRepeats = searchTimer.AvoidRepeats();
+    allowedRepeats = searchTimer.AllowedRepeats();
+    compareTitle = searchTimer.CompareTitle();
+    compareSubtitle = searchTimer.CompareSubtitle();
+    compareSummary = searchTimer.CompareSummary();
+    useInFavorites = searchTimer.UseInFavorites();
+
+    SetWidthPercent(70);
+    cString infoText;
+    if (searchTimer.GetID() > -1) {
+        infoText = tr("Configure Search Timer Options");
+    } else {
+        infoText = tr("Create Search Timer");
+    }
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    cRecMenuItemButtonYesNo *footerButton = new cRecMenuItemButtonYesNo(tr("Save Search Timer"), tr("Cancel"), rmsSearchTimerSave, rmsSearchTimers, (advancedOptions)?false:true);
+    SetFooter(footerButton);
+    InitMenuItems();
+    CreateMenuItems();
+}
+
+cRecMenuSearchTimerEdit::~cRecMenuSearchTimerEdit(void) {
+    for (std::vector<cRecMenuItem*>::iterator it = mainMenuItems.begin(); it != mainMenuItems.end(); it++) {
+        delete *it;
+    }
+    mainMenuItems.clear();
+    for (std::vector<cRecMenuItem*>::iterator it = useChannelSubMenu.begin(); it != useChannelSubMenu.end(); it++) {
+        delete *it;
+    }
+    useChannelSubMenu.clear();
+    for (std::vector<cRecMenuItem*>::iterator it = useTimeSubMenu.begin(); it != useTimeSubMenu.end(); it++) {
+        delete *it;
+    }
+    useTimeSubMenu.clear();
+    for (std::vector<cRecMenuItem*>::iterator it = useDayOfWeekSubMenu.begin(); it != useDayOfWeekSubMenu.end(); it++) {
+        delete *it;
+    }
+    useDayOfWeekSubMenu.clear();
+    for (std::vector<cRecMenuItem*>::iterator it = avoidRepeatSubMenu.begin(); it != avoidRepeatSubMenu.end(); it++) {
+        delete *it;
+    }
+    avoidRepeatSubMenu.clear();
+    currentMenuItems.clear();
+}
+
+void cRecMenuSearchTimerEdit::InitMenuItems(void) {
+
+    useChannelPos = 6;
+    useTimePos = 7;
+    useDayOfWeekPos = 8;
+    avoidRepeatsPos = 14;
+
+    mainMenuItems.push_back(new cRecMenuItemText(tr("Search String"), searchString, TEXTINPUTLENGTH, false, searchString));
+    mainMenuItems.push_back(new cRecMenuItemBool(tr("Active"), timerActive, false, false, &timerActive, rmsSearchTimerSave));
+    std::vector<std::string> searchModes;
+    searchTimer.GetSearchModes(&searchModes);
+    mainMenuItems.push_back(new cRecMenuItemSelect(tr("Search Mode"), searchModes, mode, false, &mode, rmsSearchTimerSave));
+    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use Title"), useTitle, false, false, &useTitle, rmsSearchTimerSave));
+    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use Subtitle"), useSubtitle, false, false, &useSubtitle, rmsSearchTimerSave));
+    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use Description"), useDescription, false, false, &useDescription, rmsSearchTimerSave));
+    mainMenuItems.push_back(new cRecMenuItemBool(tr("Limit Channels"), useChannel, true, false, &useChannel, rmsSearchTimerSave));
+    mainMenuItems.push_back(new cRecMenuItemBool(tr("Use Time"), useTime, true, false, &useTime, rmsSearchTimerSave));
+    if (!advancedOptions) {
+        mainMenuItems.push_back(new cRecMenuItemButton(tr("Display advanced Options"), rmsSearchTimerEditAdvanced, false));
+    } else {
+        mainMenuItems.push_back(new cRecMenuItemBool(tr("Limit Days of the Week"), useDayOfWeek, true, false, &useDayOfWeek, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemInt(tr("Priority"), priority, 0, 99, false, &priority, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemInt(tr("Lifetime"), lifetime, 0, 99, false, &lifetime, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemInt(tr("Time margin for start in minutes"), marginStart, 0, 30, false, &marginStart, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemInt(tr("Time margin for stop in minutes"), marginStop, 0, 30, false, &marginStop, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemBool(tr("Series Recording"), useEpisode, false, false, &useEpisode, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemSelectDirectory(tr("Folder"), std::string(directory), false, directory, rmsSearchTimerSave, true));
+        mainMenuItems.push_back(new cRecMenuItemBool(tr("Use VPS"), useVPS, false, false, &useVPS, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemBool(tr("Avoid Repeats"), avoidRepeats, true, false, &avoidRepeats, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemBool(tr("Use in Favorites"), useInFavorites, false, false, &useInFavorites, rmsSearchTimerSave));
+        mainMenuItems.push_back(new cRecMenuItemButton(tr("Hide advanced Options"), rmsSearchTimerEdit, false));
+    }
+    mainMenuItems.push_back(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, false));
+
+    if (startChannel == 0)
+        startChannel = 1;
+    if (stopChannel == 0)
+        stopChannel = 1;
+    useChannelSubMenu.push_back(new cRecMenuItemChannelChooser(tr("Start Channel"), Channels.GetByNumber(startChannel), false, &startChannel, rmsSearchTimerSave));
+    useChannelSubMenu.push_back(new cRecMenuItemChannelChooser(tr("Stop Channel"), Channels.GetByNumber(stopChannel), false, &stopChannel, rmsSearchTimerSave));
+
+    useTimeSubMenu.push_back(new cRecMenuItemTime(tr("Start after"), startTime, false, &startTime, rmsSearchTimerSave));
+    useTimeSubMenu.push_back(new cRecMenuItemTime(tr("Start before"), stopTime, false, &stopTime, rmsSearchTimerSave));
+
+    if (advancedOptions) {
+        useDayOfWeekSubMenu.push_back(new cRecMenuItemDayChooser(tr("Select Days"), dayOfWeek, false, &dayOfWeek));
+        avoidRepeatSubMenu.push_back(new cRecMenuItemInt(tr("Number of allowed repeats"), allowedRepeats, 0, 30, false, &allowedRepeats, rmsSearchTimerSave));
+        avoidRepeatSubMenu.push_back(new cRecMenuItemBool(tr("Compare Title"), compareTitle, false, false, &compareTitle, rmsSearchTimerSave));
+        avoidRepeatSubMenu.push_back(new cRecMenuItemBool(tr("Compare Subtitle"), compareSubtitle, false, false, &compareSubtitle, rmsSearchTimerSave));
+        avoidRepeatSubMenu.push_back(new cRecMenuItemBool(tr("Compare Description"), compareSummary, false, false, &compareSummary, rmsSearchTimerSave));
+    }
+}
+
+
+void cRecMenuSearchTimerEdit::CreateMenuItems(void) {
+    bool reDraw = false;
+    if (GetCurrentNumMenuItems() > 0) {
+        InitMenu(false);
+        currentMenuItems.clear();
+        reDraw = true;
+    }
+    
+   int numMainMenuItems = mainMenuItems.size();
+    
+    for (int i = 0; i < numMainMenuItems; i++) {
+        currentMenuItems.push_back(mainMenuItems[i]);
+        if ((i == useChannelPos) && useChannel)
+            AddSubMenu(&useChannelSubMenu);
+        else if ((i == useTimePos) && useTime)
+            AddSubMenu(&useTimeSubMenu);
+        else if (advancedOptions && (i == useDayOfWeekPos) && useDayOfWeek)
+            AddSubMenu(&useDayOfWeekSubMenu);
+        else if (advancedOptions && (i == avoidRepeatsPos) && avoidRepeats)
+            AddSubMenu(&avoidRepeatSubMenu);
+    }    
+
+    int numMenuItemsAll = currentMenuItems.size();
+    int start = GetStartIndex();
+     for (int i = start; i < numMenuItemsAll; i++) {
+        if ((i == start) && !reDraw && advancedOptions) {
+            currentMenuItems[i]->setActive();
+        }
+        if (!AddMenuItemInitial(currentMenuItems[i])) {
+            break;
+        }
+    }
+    numMenuItems = currentMenuItems.size();
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+void cRecMenuSearchTimerEdit::AddSubMenu(std::vector<cRecMenuItem*> *subMenu) {
+    for (std::vector<cRecMenuItem*>::iterator it = subMenu->begin(); it < subMenu->end(); it++) {
+        currentMenuItems.push_back(*it);
+    }
+}
+
+
+cTVGuideSearchTimer cRecMenuSearchTimerEdit::GetSearchTimer(void) {
+    searchTimer.SetSearchString(searchString);
+    searchTimer.SetActive(timerActive);
+    searchTimer.SetSearchMode(mode);
+    searchTimer.SetUseTitle(useTitle);
+    searchTimer.SetUseSubtitle(useSubtitle);
+    searchTimer.SetUseDesription(useDescription);
+    searchTimer.SetUseChannel(useChannel);
+    if (useChannel) {
+        searchTimer.SetStartChannel(startChannel);
+        searchTimer.SetStopChannel(stopChannel);
+    }
+    searchTimer.SetUseTime(useTime);
+    if (useTime) {
+        searchTimer.SetStartTime(startTime);
+        searchTimer.SetStopTime(stopTime);
+    }
+    searchTimer.SetUseDayOfWeek(useDayOfWeek);
+    if (useDayOfWeek) {
+        searchTimer.SetDayOfWeek(dayOfWeek);
+    }
+    searchTimer.SetPriority(priority);
+    searchTimer.SetLifetime(lifetime);
+    searchTimer.SetUseEpisode(useEpisode);
+    std::string dir(directory);
+    std::replace(dir.begin(), dir.end(), '/', '~');
+    searchTimer.SetDirectory(dir);
+    searchTimer.SetMarginStart(marginStart);
+    searchTimer.SetMarginStop(marginStop);
+    searchTimer.SetUseVPS(useVPS);
+    searchTimer.SetAvoidRepeats(avoidRepeats);
+    if (avoidRepeats) {
+        searchTimer.SetAllowedRepeats(allowedRepeats);
+        searchTimer.SetCompareTitle(compareTitle);
+        searchTimer.SetCompareSubtitle(compareSubtitle);
+        searchTimer.SetCompareSummary(compareSummary);
+    }
+    searchTimer.SetUseInFavorites(useInFavorites);
+    return searchTimer;
+}
+
+int cRecMenuSearchTimerEdit::GetTotalNumMenuItems(void) { 
+    return numMenuItems; 
+}
+
+cRecMenuItem *cRecMenuSearchTimerEdit::GetMenuItem(int number) {
+    if ((number > -1) && (number < numMenuItems)) {
+        return currentMenuItems[number];
+    }
+    return NULL;
+}
+
+// --- cRecMenuSearchTimerDeleteConfirm ---------------------------------------------
+cRecMenuSearchTimerDeleteConfirm::cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer) {
+    this->searchTimer = searchTimer;
+    SetWidthPercent(70);
+    cString message = tr("Really delete Search Timer");
+    cString infoText = cString::sprintf("%s \"%s\"?", *message, searchTimer.SearchString().c_str());
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("Delete only Search Timer"), rmsSearchTimerDelete, true));
+    AddMenuItem(new cRecMenuItemButton(tr("Delete Search Timer and created Timers"), rmsSearchTimerDeleteWithTimers, false));
+    SetFooter(new cRecMenuItemButton(tr("Cancel"), rmsClose, false));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cRecMenuSearchTimerDeleteConfirm::~cRecMenuSearchTimerDeleteConfirm(void) {
+
+}
+
+cTVGuideSearchTimer cRecMenuSearchTimerDeleteConfirm::GetSearchTimer(void) {
+    return searchTimer;
+}
+
+// --- cRecMenuSearchTimerCreateConfirm  ---------------------------------------------------------
+cRecMenuSearchTimerCreateConfirm::cRecMenuSearchTimerCreateConfirm(bool success) {
+    SetWidthPercent(50);
+    
+    cString message1a = tr("Search Timer sucessfully created.");
+    cString message1b = tr ("Search Timer update initialised");
+    cString message1 = cString::sprintf("%s\n%s", *message1a, *message1b);
+    cString message2 = tr("Search Timer NOT sucessfully created");
+    cString infoText = success?message1:message2;
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
+    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuSearchTimerTemplatesCreate  ---------------------------------------------------------
+cRecMenuSearchTimerTemplatesCreate::cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer) {
+    this->templ = templ;
+    this->searchTimer = searchTimer;
+    SetWidthPercent(70);
+
+    cString message1 = tr("Creating Search Timer");
+    cString message2 = tr("Search Term");
+    cString message3 = tr("Using Template");
+    
+    cString infoText = cString::sprintf("%s\n%s: \"%s\"\n%s \"%s\"", *message1, *message2, searchTimer.SearchString().c_str(), *message3, templ.name.c_str());
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+
+    AddMenuItem(new cRecMenuItemButton(tr("Display Results for Search Timer"), rmsSearchTimerTest, true));
+    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create Search Timer"), tr("Use other Template"), rmsSearchTimerSave, rmsSearchTimerOptions, false));
+    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+
+// --- cRecMenuSearchTimerResults ---------------------------------------------------------
+cRecMenuSearchTimerResults::cRecMenuSearchTimerResults(std::string searchString, const cEvent **searchResults, int numResults, std::string templateName, eRecMenuState action2) {
+    this->searchResults = searchResults;
+    this->action2 = action2;
+    this->numResults = numResults;
+    SetWidthPercent(70);
+    cString message1 = "", message2 = "", message3 = "", infoText = "";
+    if (action2 == rmsFavoritesRecord) {
+        message1 = tr("search results for Favorite");
+        message2 = tr("search result for Favorite");
+    } else {
+        message1 = tr("search results for Search Timer");
+        message2 = tr("search result for Search Timer");
+        message3 = tr("Using Template");
+    }
+    if (templateName.size() > 0) {
+        infoText = cString::sprintf("%d %s:\n\"%s\"\n%s \"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str(), *message3, templateName.c_str());
+    } else {
+        infoText = cString::sprintf("%d %s:\n\"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str());
+    }
+    cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    
+    cRecMenuItem *buttons = new cRecMenuItemButton(tr("Close"), rmsClose, false);
+    SetFooter(buttons);
+    if (searchResults && (numResults > 0)) {
+        for (int i=0; i<numResults; i++) {
+            if (!AddMenuItemInitial(new cRecMenuItemEvent(searchResults[i], rmsSearchShowInfo, action2, (i==0)?true:false)))
+                break;
+        }
+    }
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+    
+cRecMenuItem *cRecMenuSearchTimerResults::GetMenuItem(int number) { 
+    if ((number >= 0) && (number < numResults)) {
+        cRecMenuItem *result = new cRecMenuItemEvent(searchResults[number], rmsSearchShowInfo, action2, false);
+        return result;
+    }
+    return NULL;
+}
+
+int cRecMenuSearchTimerResults::GetTotalNumMenuItems(void) { 
+    return numResults;
+}
+
+const cEvent *cRecMenuSearchTimerResults::GetEvent(void) {
+    const cEvent *ev = NULL;
+    if (cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem()))
+        ev = activeItem->GetEventValue();
+    return ev;
+}
+
+// --- cRecMenuSearchTimerNothingFound  ---------------------------------------------------------
+cRecMenuSearchTimerNothingFound::cRecMenuSearchTimerNothingFound(std::string searchString) {
+    SetWidthPercent(50);
+    cString message = tr("Nothing found for Search String");
+    cString text;
+    text = cString::sprintf("%s\n\"%s\"", 
+                            *message, 
+                            searchString.c_str());
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+/******************************************************************************************
+*   SwitchTimer Menus
+******************************************************************************************/
+
+// --- cRecMenuSwitchTimer  ---------------------------------------------------------
+cRecMenuSwitchTimer::cRecMenuSwitchTimer(void) {
+    switchMinsBefore = 2;
+    announceOnly = 0;
+
+    SetWidthPercent(60);
+    
+    cString infoText = tr("Configure Options for Switchtimer");
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+
+    AddMenuItem(new cRecMenuItemInt(tr("Minutes before switching"), switchMinsBefore, 0, 10, false, &switchMinsBefore));
+    std::vector<std::string> switchModes;
+    switchModes.push_back(tr("switch"));
+    switchModes.push_back(tr("announce only"));
+    switchModes.push_back(tr("ask for switch"));
+    AddMenuItem(new cRecMenuItemSelect(tr("Switch Mode"), switchModes, announceOnly, false, &announceOnly));
+    
+    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Create"), tr("Cancel"), rmsSwitchTimerCreate, rmsClose, true));
+    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cSwitchTimer cRecMenuSwitchTimer::GetSwitchTimer(void) {
+    cSwitchTimer st;
+    st.switchMinsBefore = switchMinsBefore;
+    st.announceOnly = announceOnly;
+    return st;
+}
+
+// --- cRecMenuSwitchTimerConfirm  ---------------------------------------------------------
+cRecMenuSwitchTimerConfirm::cRecMenuSwitchTimerConfirm(bool success) {
+    SetWidthPercent(50);
+    
+    cString message1 = tr("Switch Timer sucessfully created");
+    cString message2 = tr("Switch Timer NOT sucessfully created");
+    cString infoText = success?message1:message2;
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
+    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuSwitchTimerDelete  ---------------------------------------------------------
+cRecMenuSwitchTimerDelete::cRecMenuSwitchTimerDelete(void) {
+    SetWidthPercent(50);
+    
+    cString infoText = tr("Switch Timer deleted");
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true));
+    
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+/******************************************************************************************
+*   Search Menus
+******************************************************************************************/
+
+
+// --- cRecMenuSearch  ---------------------------------------------------------
+cRecMenuSearch::cRecMenuSearch(std::string searchString, bool withOptions) {
+    strncpy(this->searchString, searchString.c_str(), TEXTINPUTLENGTH);
+    mode = 0;
+    channelNr = 0;
+    useTitle = true;
+    useSubTitle = true;
+    useDescription = false;
+    SetWidthPercent(60);
+    cString infoText = tr("Search");
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), this->searchString, TEXTINPUTLENGTH, false, this->searchString));
+    if (withOptions) {
+        std::vector<std::string> searchModes;
+        cTVGuideSearchTimer searchTimer;
+        searchTimer.GetSearchModes(&searchModes);
+        AddMenuItemInitial(new cRecMenuItemSelect(tr("Search Mode"), searchModes, 0, false, &mode));
+        AddMenuItemInitial(new cRecMenuItemChannelChooser(tr("Channel to Search"), NULL, false, &channelNr));
+        AddMenuItemInitial(new cRecMenuItemBool(tr("Search in title"), true, false, false, &useTitle));
+        AddMenuItemInitial(new cRecMenuItemBool(tr("Search in Subtitle"), true, false, false, &useSubTitle));
+        AddMenuItemInitial(new cRecMenuItemBool(tr("Search in Description"), false, false, false, &useDescription));
+    } else {
+        AddMenuItemInitial(new cRecMenuItemButton(tr("Show Search Options"), rmsSearchWithOptions, false));
+    }
+    cRecMenuItemButtonYesNo *button = new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsSearchPerform, rmsClose, true);
+    SetFooter(button);
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+Epgsearch_searchresults_v1_0 cRecMenuSearch::GetEPGSearchStruct(void) {
+    Epgsearch_searchresults_v1_0 data;
+    data.query = searchString;
+    data.mode = mode;
+    data.channelNr = channelNr;
+    data.useTitle = useTitle;
+    data.useSubTitle = useSubTitle;
+    data.useDescription = useDescription;
+    return data;
+}
+
+
+// --- cRecMenuSearchResults  ---------------------------------------------------------
+cRecMenuSearchResults::cRecMenuSearchResults(std::string searchString, const cEvent **searchResults, int numResults) {
+    this->searchResults = searchResults;
+    SetWidthPercent(70);
+    this->searchString = searchString;
+    this->numResults = numResults;
+    cString message1 = tr("search results for");
+    cString message2 = tr("search result for");
+    cString infoText = cString::sprintf("%d %s:\n\"%s\"", numResults, (numResults>1)?(*message1):(*message2), searchString.c_str());
+    cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    
+    cRecMenuItem *buttons = new cRecMenuItemButtonYesNo(tr("Adapt Search"), tr("Close"), rmsSearch, rmsClose, false);
+    SetFooter(buttons);
+    if (searchResults && (numResults > 0)) {
+        for (int i=0; i<numResults; i++) {
+            if (!AddMenuItemInitial(new cRecMenuItemEvent(searchResults[i], rmsSearchShowInfo, rmsSearchRecord, (i==0)?true:false)))
+                break;
+        }
+    }
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cRecMenuItem *cRecMenuSearchResults::GetMenuItem(int number) { 
+    if ((number >= 0) && (number < numResults)) {
+        cRecMenuItem *result = new cRecMenuItemEvent(searchResults[number], rmsSearchShowInfo, rmsSearchRecord, false);
+        return result;
+    }
+    return NULL;
+}
+
+int cRecMenuSearchResults::GetTotalNumMenuItems(void) { 
+    return numResults;
+}
+
+const cEvent *cRecMenuSearchResults::GetEvent(void) {
+    const cEvent *ev = NULL;
+    if (cRecMenuItemEvent *activeItem = dynamic_cast<cRecMenuItemEvent*>(GetActiveMenuItem()))
+        ev = activeItem->GetEventValue();
+    return ev;
+}
+
+
+// --- cRecMenuSearchConfirmTimer  ---------------------------------------------------------
+cRecMenuSearchConfirmTimer::cRecMenuSearchConfirmTimer(const cEvent *event, eRecMenuState nextAction) {
+    SetWidthPercent(50);
+    cString channelName = Channels.GetByChannelID(event->ChannelID())->Name();
+    cString message = tr("Timer created");
+    cString text = cString::sprintf("%s\n%s\n%s %s - %s\n%s", 
+                                    *message, 
+                                    *channelName,
+                                    *event->GetDateString(),
+                                    *event->GetTimeString(),
+                                    *event->GetEndTimeString(),
+                                    event->Title()
+                                );
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), nextAction, true, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuSearchNothingFound  ---------------------------------------------------------
+cRecMenuSearchNothingFound::cRecMenuSearchNothingFound(std::string searchString, bool tooShort) {
+    SetWidthPercent(50);
+    cString text;
+    if (!tooShort) {
+        cString message = tr("Nothing found for Search String");
+        text = cString::sprintf("%s\n\"%s\"", 
+                                *message, 
+                                searchString.c_str());
+    } else {
+        cString message = tr("Search String has to have at least three letters");
+        text = cString::sprintf("%s\n\"%s\"", 
+                                *message, 
+                                searchString.c_str());
+
+    }
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsSearchNothingFoundConfirm, true, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+/******************************************************************************************
+*   Recording Search Menus
+******************************************************************************************/
+
+// --- cRecMenuRecordingSearch  ---------------------------------------------------------
+cRecMenuRecordingSearch::cRecMenuRecordingSearch(std::string search) {
+    strncpy(searchString, search.c_str(), TEXTINPUTLENGTH);
+    SetWidthPercent(60);
+    cString infoText = tr("Search in Recordings");
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    
+    AddMenuItem(new cRecMenuItemText(tr("Search Expression:"), searchString, TEXTINPUTLENGTH, false, searchString));
+    AddMenuItem(new cRecMenuItemButtonYesNo(tr("Perform Search"), tr("Cancel"), rmsRecordingSearchResult, rmsClose, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+// --- cRecMenuRecordingSearchResults  ---------------------------------------------------------
+cRecMenuRecordingSearchResults::cRecMenuRecordingSearchResults(std::string searchString, cRecording **searchResults, int numResults) {
+    this->searchString = searchString;
+    this->searchResults = searchResults;
+    SetWidthPercent(80);
+    cString message1 = tr("Found");
+    cString message2 = tr("recording");
+    cString message3 = tr("recordings");
+    cString message4 = tr("for");
+    this->numResults = numResults;
+    cString infoText = cString::sprintf("%s %d %s %s:\n\"%s\"", *message1, numResults, (numResults>1)?(*message3):(*message2), *message4, searchString.c_str());
+    cRecMenuItem *infoItem = new cRecMenuItemInfo(*infoText, true);
+    infoItem->CalculateHeight(width - 2 * border);
+    SetHeader(infoItem);
+    
+    cRecMenuItem *buttons = new cRecMenuItemButtonYesNo(tr("Adapt Search"), tr("Close"), rmsRecordingSearch, rmsClose, false);
+    SetFooter(buttons);
+    if (searchResults && (numResults > 0)) {
+        for (int i=0; i<numResults; i++) {
+            if (!AddMenuItemInitial(new cRecMenuItemRecording(searchResults[i], (i==0)?true:false)))
+                break;
+        }
+    }
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cRecMenuItem *cRecMenuRecordingSearchResults::GetMenuItem(int number) { 
+    if ((number >= 0) && (number < numResults)) {
+        cRecMenuItem *result = new cRecMenuItemRecording(searchResults[number], false);
+        return result;
+    }
+    return NULL;
+}
+
+int cRecMenuRecordingSearchResults::GetTotalNumMenuItems(void) { 
+    return numResults;
+}
+
+// --- cRecMenuRecordingSearchNotFound  ---------------------------------------------------------
+cRecMenuRecordingSearchNotFound::cRecMenuRecordingSearchNotFound(std::string searchString) {
+    SetWidthPercent(50);
+    cString message = tr("No recordings found for");
+    cString text = cString::sprintf("%s\n\"%s\"", 
+                                    *message, 
+                                    searchString.c_str());
+    cRecMenuItemInfo *infoItem = new cRecMenuItemInfo(*text);
+    infoItem->CalculateHeight(width - 2 * border);
+    AddMenuItem(infoItem);
+    AddMenuItem(new cRecMenuItemButton(tr("OK"), rmsClose, true, true));
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+/******************************************************************************************
+*   Timeline
+******************************************************************************************/
+
+// --- cRecMenuTimeline  ---------------------------------------------------------
+cRecMenuTimeline::cRecMenuTimeline(cTVGuideTimerConflicts *timerConflicts) {
+    this->timerConflicts = timerConflicts;
+    SetStartStop();
+    conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
+    GetTimersForDay();
+    SetWidthPercent(95);
+    header = new cRecMenuItemTimelineHeader(timeStart, conflictsToday);
+    SetHeader(header);
+    cRecMenuItem *footer = new cRecMenuItemButton(tr("Close"), rmsClose, false, true);
+    SetFooter(footer);
+    SetTimers();
+}
+
+void cRecMenuTimeline::SetStartStop(void) {
+    time_t now = time(0);
+    tm *timeStruct = localtime(&now);
+    timeStart = now - timeStruct->tm_hour * 3600 - timeStruct->tm_min * 60 - timeStruct->tm_sec;
+    today = timeStart;
+    timeStop = timeStart + 24*3600 - 1;
+}
+
+
+void cRecMenuTimeline::GetTimersForDay(void) {
+    timersToday.clear();
+    for (cTimer *t = Timers.First(); t; t = Timers.Next(t)) {
+        if (((t->StartTime() > timeStart) && (t->StartTime() <= timeStop)) || ((t->StopTime() > timeStart) && (t->StopTime() <= timeStop))) {
+            timersToday.push_back(t);
+        }
+    }
+    numTimersToday = timersToday.size();
+}
+
+void cRecMenuTimeline::SetTimers(void) {
+    ClearMenu();
+    if (numTimersToday == 0) {
+        AddMenuItem(new cRecMenuItemTimelineTimer(NULL, 0, 0, conflictsToday, header, false));
+        header->UnsetCurrentTimer();
+        footer->setActive();
+    } else {
+        for (int i=0; i<numTimersToday; i++) {
+            cRecMenuItemTimelineTimer *item = new cRecMenuItemTimelineTimer(timersToday[i], timeStart, timeStop, conflictsToday, header, false);
+            if (i==0)
+                item->setActive();
+            if (!AddMenuItemInitial(item))
+                break;
+        }
+        footer->setInactive();
+    }
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+void cRecMenuTimeline::PrevDay(void) {
+    if ((timeStart - 3600*24) < today)
+        return;
+    timeStart -= 3600*24;
+    timeStop -= 3600*24;
+    conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
+    SetWidthPercent(95);
+    header->SetDay(timeStart);
+    header->UnsetCurrentTimer();
+    header->RefreshTimerDisplay();
+    GetTimersForDay();
+    SetTimers();
+    Display();
+}
+
+void cRecMenuTimeline::NextDay(void) {
+    timeStart += 3600*24;
+    timeStop += 3600*24;
+    conflictsToday = timerConflicts->GetConflictsBetween(timeStart, timeStop);
+    SetWidthPercent(95);
+    header->SetDay(timeStart);
+    header->UnsetCurrentTimer();
+    header->RefreshTimerDisplay();
+    GetTimersForDay();
+    SetTimers();
+    Display();
+}
+
+cRecMenuItem *cRecMenuTimeline::GetMenuItem(int number) { 
+    if (number < 0)
+        return NULL;
+    if (number >= numTimersToday)
+        return NULL;
+    return new cRecMenuItemTimelineTimer(timersToday[number], timeStart, timeStop, conflictsToday, header, false);
+}
+
+int cRecMenuTimeline::GetTotalNumMenuItems(void) { 
+    return numTimersToday;
+}
+
+void cRecMenuTimeline::ClearMenu(void) {
+    InitMenu(true);
+    header->UnsetCurrentTimer();
+}
+
+cTimer *cRecMenuTimeline::GetTimer(void) {
+    if (cRecMenuItemTimelineTimer *activeItem = dynamic_cast<cRecMenuItemTimelineTimer*>(GetActiveMenuItem()))
+        return activeItem->GetTimerValue();
+    return NULL;
+}
+
+
+eRecMenuState cRecMenuTimeline::ProcessKey(eKeys Key) {
+    eRecMenuState state = rmsContinue;
+    switch (Key & ~k_Repeat) {
+        case kLeft:
+            PrevDay();
+            state = rmsConsumed;
+            break;
+        case kRight:
+            NextDay();
+            state = rmsConsumed;
+            break;
+        default:
+            break;
+    }
+    if (state != rmsConsumed) {
+        state = cRecMenu::ProcessKey(Key);
+    }
+    return state;
+}
+
+/******************************************************************************************
+*   Favorites
+******************************************************************************************/
+
+// --- cRecMenuFavorites  ---------------------------------------------------------
+
+cRecMenuFavorites::cRecMenuFavorites(std::vector<cTVGuideSearchTimer> favorites) {
+    deleteMenuItems = false;
+    this->favorites = favorites;
+    CreateFavoritesMenuItems();
+    numFavorites = myMenuItems.size();
+    SetWidthPercent(70);
+    cString header;
+    if (numFavorites > 0) {
+        header = tr("Favorites");
+    } else {
+        header = tr("No Favorites available");
+    }
+    cRecMenuItemInfo *headerItem = new cRecMenuItemInfo(*header, true);
+    headerItem->CalculateHeight(width - 2 * border);
+    SetHeader(headerItem);
+
+    cRecMenuItem *button = new cRecMenuItemButton(tr("Close"), rmsClose, (numFavorites==0)?true:false);
+    SetFooter(button);
+
+    for (int i=0; i<numFavorites; i++) {
+        if (i==0)
+            myMenuItems[i]->setActive();
+        if (!AddMenuItemInitial(myMenuItems[i]))
+            break;
+    }
+
+    CalculateHeight();
+    CreatePixmap();
+    Arrange();
+}
+
+cRecMenuFavorites::~cRecMenuFavorites(void) {
+    for (std::vector<cRecMenuItem*>::iterator it = myMenuItems.begin(); it != myMenuItems.end(); it++) {
+        delete *it;
+    }
+    myMenuItems.clear();
+}
+
+void cRecMenuFavorites::CreateFavoritesMenuItems(void) {
+    if (tvguideConfig.favWhatsOnNow) {
+        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(tr("What's on now"), rmsFavoritesNow, false));
+    }
+    if (tvguideConfig.favWhatsOnNext) {
+        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(tr("What's on next"), rmsFavoritesNext, false));
+    }
+    if (tvguideConfig.favUseTime1) {
+        std::string desc = *cString::sprintf("%s (%s)", tvguideConfig.descUser1.c_str(), NiceTime(tvguideConfig.favTime1).c_str());
+        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser1, false));
+    }
+    if (tvguideConfig.favUseTime2) {
+        std::string desc = *cString::sprintf("%s (%s)", tvguideConfig.descUser2.c_str(), NiceTime(tvguideConfig.favTime2).c_str());
+        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser2, false));
+    }
+    if (tvguideConfig.favUseTime3) {
+        std::string desc = *cString::sprintf("%s (%s)", tvguideConfig.descUser3.c_str(), NiceTime(tvguideConfig.favTime3).c_str());
+        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser3, false));
+    }
+    if (tvguideConfig.favUseTime4) {
+        std::string desc = *cString::sprintf("%s (%s)", tvguideConfig.descUser4.c_str(), NiceTime(tvguideConfig.favTime4).c_str());
+        myMenuItems.push_back(new cRecMenuItemFavoriteStatic(desc, rmsFavoritesUser4, false));
+    }
+
+    int numAdditionalFavs = favorites.size();
+    for (int i = 0; i < numAdditionalFavs; i++) {
+        myMenuItems.push_back(new cRecMenuItemFavorite(favorites[i], rmsSearchTimerTest, false));
+    }
+
+}
+
+std::string cRecMenuFavorites::NiceTime(int favTime) {
+    int hours = favTime/100;
+    int mins = favTime - hours * 100;
+    return *cString::sprintf("%02d:%02d", hours, mins);
+}
+
+cRecMenuItem *cRecMenuFavorites::GetMenuItem(int number) {
+    if (number > -1 && number < numFavorites)
+        return myMenuItems[number];
+    return NULL;
+}
+
+int cRecMenuFavorites::GetTotalNumMenuItems(void) {
+    return numFavorites;
+}
+
+cTVGuideSearchTimer cRecMenuFavorites::GetFavorite(void) {
+    cRecMenuItemFavorite *activeItem = dynamic_cast<cRecMenuItemFavorite*>(GetActiveMenuItem());
+    return activeItem->GetFavorite();
+}
\ No newline at end of file
diff --git a/recmenus.h b/recmenus.h
new file mode 100644
index 0000000..547eee3
--- /dev/null
+++ b/recmenus.h
@@ -0,0 +1,485 @@
+#ifndef __TVGUIDE_RECMENUS_H
+#define __TVGUIDE_RECMENUS_H
+
+#define TEXTINPUTLENGTH 256
+
+#include <vector>
+#include <functional>
+#include <vdr/epg.h>
+#include "services/epgsearch.h"
+#include "switchtimer.h"
+#include "recmanager.h"
+
+// --- cRecMenuMain  ---------------------------------------------------------
+class cRecMenuMain : public cRecMenu {
+public:
+    cRecMenuMain(bool epgSearchAvailable, bool timerActive, bool switchTimerActive);
+    virtual ~cRecMenuMain(void) {};
+};
+
+/******************************************************************************************
+*   Instant Timer Menus
+******************************************************************************************/
+
+
+// --- cRecMenuAskFolder  ---------------------------------------------------------
+class cRecMenuAskFolder: public cRecMenu {
+private:
+    std::vector<std::string> folders;
+    eRecMenuState NextAction;
+public:
+    cRecMenuAskFolder(const cEvent *event, eRecMenuState nextAction);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    virtual ~cRecMenuAskFolder(void) {};
+    std::string GetFolder(void);
+};
+
+// --- cRecMenuConfirmTimer  ---------------------------------------------------------
+class cRecMenuConfirmTimer: public cRecMenu {
+public:
+    cRecMenuConfirmTimer(const cEvent *event);
+    virtual ~cRecMenuConfirmTimer(void) {};
+};
+
+// --- cRecMenuConfirmDeleteTimer  ---------------------------------------------------------
+class cRecMenuConfirmDeleteTimer: public cRecMenu {
+public:
+    cRecMenuConfirmDeleteTimer(const cEvent *event);
+    virtual ~cRecMenuConfirmDeleteTimer(void) {};
+};
+
+// --- cRecMenuAskDeleteTimer ---------------------------------------------------------
+class cRecMenuAskDeleteTimer: public cRecMenu {
+public:
+    cRecMenuAskDeleteTimer(const cEvent *event);
+    virtual ~cRecMenuAskDeleteTimer(void) {};
+};
+
+// --- cRecMenuTimerConflicts  ---------------------------------------------------------
+class cRecMenuTimerConflicts: public cRecMenu {
+public:
+    cRecMenuTimerConflicts(cTVGuideTimerConflicts *conflicts);    
+    virtual ~cRecMenuTimerConflicts(void) {};
+    int GetTimerConflict(void);
+};
+
+// --- cRecMenuTimerConflict  ---------------------------------------------------------
+class cRecMenuTimerConflict: public cRecMenu {
+private:
+    cTVGuideTimerConflict *conflict;
+public:
+    cRecMenuTimerConflict(cTVGuideTimerConflict *conflict);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    virtual ~cRecMenuTimerConflict(void) {};
+    int GetTimerConflictIndex(void);
+};
+
+// --- cRecMenuNoTimerConflict ---------------------------------------------------------
+class cRecMenuNoTimerConflict: public cRecMenu {
+public:
+    cRecMenuNoTimerConflict(void);   
+    virtual ~cRecMenuNoTimerConflict(void) {};
+};
+
+// --- cRecMenuRerunResults  ---------------------------------------------------------
+class cRecMenuRerunResults: public cRecMenu {
+private:
+    const cEvent **reruns;
+    int numReruns;
+public:
+    cRecMenuRerunResults(const cEvent *original, const cEvent **reruns, int numReruns);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    virtual ~cRecMenuRerunResults(void) {
+        delete[] reruns;
+    };
+    const cEvent *GetRerunEvent(void);
+};
+
+// --- cRecMenuNoRerunsFound  ---------------------------------------------------------
+class cRecMenuNoRerunsFound: public cRecMenu {
+public:
+    cRecMenuNoRerunsFound(cString searchString);
+    virtual ~cRecMenuNoRerunsFound(void) {};
+};
+
+// --- cRecMenuConfirmRerunUsed  ---------------------------------------------------------
+class cRecMenuConfirmRerunUsed: public cRecMenu {
+public:
+    cRecMenuConfirmRerunUsed(const cEvent *original, const cEvent *replace);
+    virtual ~cRecMenuConfirmRerunUsed(void) {};
+};
+
+// --- cRecMenuEditTimer  ---------------------------------------------------------
+class cRecMenuEditTimer: public cRecMenu {
+private:
+    cTimer *originalTimer;
+    bool timerActive;
+    time_t day;
+    int start;
+    int stop;
+    int prio;
+    int lifetime;
+    char folder[TEXTINPUTLENGTH];
+public:
+    cRecMenuEditTimer(cTimer *timer, eRecMenuState nextState);
+    virtual ~cRecMenuEditTimer(void) {};
+    cTimer GetTimer(void);
+    cTimer *GetOriginalTimer(void);
+};
+
+/******************************************************************************************
+*   Series Timer Menus
+******************************************************************************************/
+
+
+// --- cRecMenuSeriesTimer ---------------------------------------------------------
+class cRecMenuSeriesTimer: public cRecMenu {
+    std::string folder;
+    bool timerActive;
+    int channel;
+    time_t tstart;
+    int start;
+    int stop;
+    int dayOfWeek;
+    int priority;
+    int lifetime;
+    void CalculateTimes(const cEvent *event);
+public:
+    cRecMenuSeriesTimer(cChannel *initialChannel, const cEvent *event, std::string folder);
+    virtual ~cRecMenuSeriesTimer(void) {};
+    cTimer *GetTimer(void);
+};
+
+// --- cRecMenuConfirmSeriesTimer  ---------------------------------------------------------
+class cRecMenuConfirmSeriesTimer: public cRecMenu {
+public:
+    cRecMenuConfirmSeriesTimer(cTimer *seriesTimer);    
+    virtual ~cRecMenuConfirmSeriesTimer(void) {};
+};
+
+/******************************************************************************************
+*   SearchTimer Menus
+******************************************************************************************/
+
+// --- cRecMenuSearchTimer  ---------------------------------------------------------
+class cRecMenuSearchTimer: public cRecMenu {
+private:
+    char searchString[TEXTINPUTLENGTH];
+public:
+    cRecMenuSearchTimer(const cEvent *event);
+    virtual ~cRecMenuSearchTimer(void) {};
+    std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuSearchTimerTemplates  ---------------------------------------------------------
+class cRecMenuSearchTimerTemplates: public cRecMenu {
+private:
+    int numTemplates;
+    cTVGuideSearchTimer searchTimer;
+    std::vector<TVGuideEPGSearchTemplate> templates;
+public:
+    cRecMenuSearchTimerTemplates(cTVGuideSearchTimer searchTimer, std::vector<TVGuideEPGSearchTemplate> templates);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    virtual ~cRecMenuSearchTimerTemplates(void) {};
+    cTVGuideSearchTimer GetSearchTimer(void) { return searchTimer; };
+    TVGuideEPGSearchTemplate GetTemplate(void);
+};
+
+
+// --- cRecMenuSearchTimers  ---------------------------------------------------------
+class cRecMenuSearchTimers: public cRecMenu {
+private:
+    int numSearchTimers;
+    std::vector<cTVGuideSearchTimer> searchTimers;
+    void SetMenuItems(void);
+public:
+    cRecMenuSearchTimers(std::vector<cTVGuideSearchTimer> searchTimers);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    cTVGuideSearchTimer GetSearchTimer(void);
+    virtual ~cRecMenuSearchTimers(void);
+};
+
+// --- cRecMenuSearchTimerEdit  ---------------------------------------------------------
+class cRecMenuSearchTimerEdit: public cRecMenu {
+private:
+    bool advancedOptions;
+    cTVGuideSearchTimer searchTimer;
+    std::vector<cRecMenuItem*> mainMenuItems;
+    std::vector<cRecMenuItem*> useChannelSubMenu;
+    std::vector<cRecMenuItem*> useTimeSubMenu;
+    std::vector<cRecMenuItem*> useDayOfWeekSubMenu;
+    std::vector<cRecMenuItem*> avoidRepeatSubMenu;
+    std::vector<cRecMenuItem*> currentMenuItems;
+    int numMenuItems;
+    int useChannelPos;
+    int useTimePos;
+    int useDayOfWeekPos;
+    int avoidRepeatsPos;
+    char searchString[TEXTINPUTLENGTH];
+    bool timerActive;
+    int mode;
+    bool useTitle;
+    bool useSubtitle;
+    bool useDescription;
+    bool useChannel;
+    int startChannel;
+    int stopChannel;
+    bool useTime;
+    int startTime;
+    int stopTime;
+    bool useDayOfWeek;
+    int dayOfWeek;
+    int priority;
+    int lifetime;
+    bool useEpisode;
+    char directory[TEXTINPUTLENGTH];
+    int marginStart;
+    int marginStop;
+    bool useVPS;
+    bool avoidRepeats;
+    int allowedRepeats;
+    bool compareTitle;
+    bool compareSubtitle;
+    bool compareSummary;
+    bool useInFavorites;
+    void InitMenuItems(void);
+    void AddSubMenu(std::vector<cRecMenuItem*> *subMenu);
+public:
+    cRecMenuSearchTimerEdit(cTVGuideSearchTimer searchTimer, bool advancedOptions);
+    void CreateMenuItems(void);
+    virtual ~cRecMenuSearchTimerEdit(void);
+    cTVGuideSearchTimer GetSearchTimer(void);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+};
+
+// --- cRecMenuSearchTimerDeleteConfirm ---------------------------------------------
+class cRecMenuSearchTimerDeleteConfirm: public cRecMenu {
+private:
+    cTVGuideSearchTimer searchTimer;
+public:
+    cRecMenuSearchTimerDeleteConfirm(cTVGuideSearchTimer searchTimer);
+    virtual ~cRecMenuSearchTimerDeleteConfirm(void);
+    cTVGuideSearchTimer GetSearchTimer(void);
+};
+
+// --- cRecMenuSearchTimerCreateConfirm  ---------------------------------------------------------
+class cRecMenuSearchTimerCreateConfirm: public cRecMenu {
+private:
+public:
+    cRecMenuSearchTimerCreateConfirm(bool success);
+    virtual ~cRecMenuSearchTimerCreateConfirm(void) {};
+};
+
+// --- cRecMenuSearchTimerTemplatesCreate  ---------------------------------------------------------
+class cRecMenuSearchTimerTemplatesCreate: public cRecMenu {
+private:
+    TVGuideEPGSearchTemplate templ;
+    cTVGuideSearchTimer searchTimer;
+public:
+    cRecMenuSearchTimerTemplatesCreate(TVGuideEPGSearchTemplate templ, cTVGuideSearchTimer searchTimer);
+    virtual ~cRecMenuSearchTimerTemplatesCreate(void) {};
+    cTVGuideSearchTimer GetSearchTimer(void) { return searchTimer; };
+    TVGuideEPGSearchTemplate GetTemplate(void) { return templ; };
+};
+
+// --- cRecMenuSearchTimerResults ---------------------------------------------------------
+class cRecMenuSearchTimerResults: public cRecMenu {
+private:
+    const cEvent **searchResults;
+    int numResults;
+    eRecMenuState action2;
+public:
+    cRecMenuSearchTimerResults(std::string searchString, const cEvent **searchResults, int numResults, std::string templateName = "", eRecMenuState action2 = rmsDisabled);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    virtual ~cRecMenuSearchTimerResults(void) {
+        delete[] searchResults;
+    };
+    const cEvent *GetEvent(void);
+};
+
+// --- cRecMenuSearchTimerNothingFound  ---------------------------------------------------------
+class cRecMenuSearchTimerNothingFound: public cRecMenu {
+public:
+    cRecMenuSearchTimerNothingFound(std::string searchString);
+    virtual ~cRecMenuSearchTimerNothingFound(void) {};
+};
+
+/******************************************************************************************
+*   SwitchTimer Menus
+******************************************************************************************/
+
+// --- cRecMenuSwitchTimer  ---------------------------------------------------------
+class cRecMenuSwitchTimer: public cRecMenu {
+private:
+    int switchMinsBefore;
+    int announceOnly;
+public:
+    cRecMenuSwitchTimer(void);
+    virtual ~cRecMenuSwitchTimer(void) {};
+    cSwitchTimer GetSwitchTimer(void);
+};
+
+// --- cRecMenuSwitchTimerConfirm  ---------------------------------------------------------
+class cRecMenuSwitchTimerConfirm: public cRecMenu {
+private:
+public:
+    cRecMenuSwitchTimerConfirm(bool success);
+    virtual ~cRecMenuSwitchTimerConfirm(void) {};
+};
+
+// --- cRecMenuSwitchTimerDelete  ---------------------------------------------------------
+class cRecMenuSwitchTimerDelete: public cRecMenu {
+private:
+public:
+    cRecMenuSwitchTimerDelete(void);
+    virtual ~cRecMenuSwitchTimerDelete(void) {};
+};
+
+/******************************************************************************************
+*   Search Menus
+******************************************************************************************/
+
+// --- cRecMenuSearch  ---------------------------------------------------------
+class cRecMenuSearch: public cRecMenu {
+private:
+    char searchString[TEXTINPUTLENGTH];
+    int mode;
+    int channelNr;
+    bool useTitle;
+    bool useSubTitle;
+    bool useDescription;
+public:
+    cRecMenuSearch(std::string searchString, bool withOptions);
+    virtual ~cRecMenuSearch(void) {};
+    Epgsearch_searchresults_v1_0 GetEPGSearchStruct(void);
+    std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuSearchResults  ---------------------------------------------------------
+class cRecMenuSearchResults: public cRecMenu {
+private:
+    std::string searchString;
+    const cEvent **searchResults;
+    int numResults;
+public:
+    cRecMenuSearchResults(std::string searchString, const cEvent **searchResults, int numResults);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    virtual ~cRecMenuSearchResults(void) {
+        delete[] searchResults;
+    };
+    const cEvent *GetEvent(void);
+    std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuSearchConfirmTimer  ---------------------------------------------------------
+class cRecMenuSearchConfirmTimer: public cRecMenu {
+public:
+    cRecMenuSearchConfirmTimer(const cEvent *event, eRecMenuState nextAction);
+    virtual ~cRecMenuSearchConfirmTimer(void) {};
+};
+
+// --- cRecMenuSearchNothingFound  ---------------------------------------------------------
+class cRecMenuSearchNothingFound: public cRecMenu {
+public:
+    cRecMenuSearchNothingFound(std::string searchString, bool tooShort = false);
+    virtual ~cRecMenuSearchNothingFound(void) {};
+};
+
+/******************************************************************************************
+*   Recording Search Menus
+******************************************************************************************/
+
+
+// --- cRecMenuRecordingSearch  ---------------------------------------------------------
+class cRecMenuRecordingSearch: public cRecMenu {
+private:
+    char searchString[TEXTINPUTLENGTH];
+public:
+    cRecMenuRecordingSearch(std::string search);
+    virtual ~cRecMenuRecordingSearch(void) {};
+    std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuRecordingSearchResults  ---------------------------------------------------------
+class cRecMenuRecordingSearchResults: public cRecMenu {
+private:
+    std::string searchString;
+    cRecording **searchResults;
+    int numResults;
+public:
+    cRecMenuRecordingSearchResults(std::string searchString, cRecording **searchResults, int numResults);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    virtual ~cRecMenuRecordingSearchResults(void) {
+        delete[] searchResults;
+    };
+    std::string GetSearchString(void) { return searchString; };
+};
+
+// --- cRecMenuRecordingSearchNotFound  ---------------------------------------------------------
+class cRecMenuRecordingSearchNotFound: public cRecMenu {
+public:
+    cRecMenuRecordingSearchNotFound(std::string searchString);
+    virtual ~cRecMenuRecordingSearchNotFound(void) {};
+};
+
+/******************************************************************************************
+*   Timeline
+******************************************************************************************/
+
+// --- cRecMenuTimeline  ---------------------------------------------------------
+class cRecMenuTimeline: public cRecMenu {
+private:
+    std::vector<cTimer*> timersToday;
+    int numTimersToday;
+    time_t today;
+    time_t timeStart;
+    time_t timeStop;
+    cTVGuideTimerConflicts *timerConflicts;
+    std::vector<cTVGuideTimerConflict*> conflictsToday;
+    cRecMenuItemTimelineHeader *header;
+    void SetStartStop(void);
+    void GetTimersForDay(void);
+    void SetTimers(void);
+    void PrevDay(void);
+    void NextDay(void);
+    void ClearMenu(void);
+public:
+    cRecMenuTimeline(cTVGuideTimerConflicts *timerConflicts);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    virtual ~cRecMenuTimeline(void) {
+    };
+    eRecMenuState ProcessKey(eKeys Key);
+    cTimer *GetTimer(void);
+};
+
+/******************************************************************************************
+*   Favorites
+******************************************************************************************/
+
+// --- cRecMenuFavorites  ---------------------------------------------------------
+class cRecMenuFavorites: public cRecMenu {
+private:
+    std::vector<cTVGuideSearchTimer> favorites;
+    std::vector<cRecMenuItem*> myMenuItems;
+    int numFavorites;
+    void CreateFavoritesMenuItems(void);
+    std::string NiceTime(int favTime);
+public:
+    cRecMenuFavorites(std::vector<cTVGuideSearchTimer> favorites);
+    cRecMenuItem *GetMenuItem(int number);
+    int GetTotalNumMenuItems(void);
+    cTVGuideSearchTimer GetFavorite(void);
+    virtual ~cRecMenuFavorites(void);
+};
+
+#endif //__TVGUIDE_RECMENUS_H
\ No newline at end of file
diff --git a/searchtimer.c b/searchtimer.c
new file mode 100644
index 0000000..7e9b4db
--- /dev/null
+++ b/searchtimer.c
@@ -0,0 +1,570 @@
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+#include <vdr/channels.h>
+#include <vdr/device.h>
+#include "tools.h"
+#include "searchtimer.h"
+
+// -- cTVGuideSearchTimer -----------------------------------------------------------------
+cTVGuideSearchTimer::cTVGuideSearchTimer(void) {
+    strTimer = "";
+    ID = -1;
+    searchString = "";
+    useTime = false;
+    startTime = 0000;
+    stopTime = 2359;
+    useChannel = false;
+    channelMin = Channels.GetByNumber(cDevice::CurrentChannel());
+    channelMax = Channels.GetByNumber(cDevice::CurrentChannel());
+    channelGroup = "";
+    useCase = false;
+    mode = 0;
+    useTitle = true;
+    useSubtitle = true;
+    useDescription = true;
+    useDuration = false;
+    minDuration = 0;
+    maxDuration = 2359;
+    useAsSearchTimer = true;
+    useDayOfWeek = false;
+    dayOfWeek = 0;
+    directory = "";
+    useEpisode = 0;
+    priority = 99;
+    lifetime = 99;
+    marginStart = 5;
+    marginStop = 5;
+    useVPS = false;
+    action = 0;
+    useExtEPGInfo = 0;
+    extEPGInfoValues = "";
+    avoidRepeats = 1;
+    allowedRepeats = 1;
+    compareTitle = 1;
+    compareSubtitle = 2;
+    compareSummary = 1;
+    catvaluesAvoidRepeat = 0;
+    repeatsWithinDays = 0;
+    delAfterDays = 0;
+    recordingsKeep = 0;
+    switchMinsBefore = 0;
+    pauseOnNrRecordings = 0;
+    blacklistMode = 0;
+    blacklists = "";
+    fuzzyTolerance = 0;
+    useInFavorites = 0;
+    menuTemplate = 0;
+    delMode = 0;
+    delAfterCountRecs = 0;
+    delAfterDaysOfFirstRec = 0;
+    useAsSearchTimerFrom = 0;
+    useAsSearchTimerTil = 0;
+    ignoreMissingEPGCats = 0;
+    unmuteSoundOnSwitch = 0;
+    compareSummaryMatchInPercent = 0;
+    contentsFilter = "";
+    compareDate = 0;
+}
+
+cTVGuideSearchTimer::~cTVGuideSearchTimer(void) {
+}
+
+bool cTVGuideSearchTimer::operator < (const cTVGuideSearchTimer& other) const {
+    std::string searchStringOther = other.SearchString();
+    searchStringOther = StrToLowerCase(searchStringOther);
+    std::string thisSearchString = StrToLowerCase(searchString);
+    int comp = thisSearchString.compare(searchStringOther);
+    if (comp < 0)
+        return true;
+    return false;
+}
+
+
+void cTVGuideSearchTimer::SetTemplate(std::string tmpl) {
+    std::stringstream searchTimerString;
+    searchTimerString << "0:";
+    searchTimerString << tmpl;
+    strTimer = searchTimerString.str();
+}
+
+int cTVGuideSearchTimer::DayOfWeek(void) {
+    int vdrDayOfWeek = 0;
+    if (dayOfWeek >= 0) {
+        vdrDayOfWeek = pow(2, (dayOfWeek+6)%7);
+    } else if (dayOfWeek < 0) {
+        int absDayOfWeek = abs(dayOfWeek);
+        for (int i=0; i < 7; i++) {
+            if (absDayOfWeek & (1 << i)) {
+                vdrDayOfWeek += pow(2, (i+6)%7);
+            }
+        }
+    }
+    return vdrDayOfWeek; 
+}
+
+void cTVGuideSearchTimer::SetDayOfWeek(int VDRDayOfWeek) { 
+    int epgSearchDayOfWeek = 0;
+    for (int i=0; i < 7; i++) {
+        if (VDRDayOfWeek & (1 << i)) {
+            epgSearchDayOfWeek += pow(2, (i+1)%7);
+        }
+    }
+    this->dayOfWeek = epgSearchDayOfWeek * (-1);
+}
+
+/*
+    0 - unique search timer id
+    1 - the search term
+    2 - use time? 0/1
+    3 - start time in HHMM
+    4 - stop time in HHMM
+    5 - use channel? 0 = no,  1 = Interval, 2 = Channel group, 3 = FTA only
+    6 - if 'use channel' = 1 then channel id[|channel id] in VDR format,
+        one entry or min/max entry separated with |, if 'use channel' = 2
+        then the channel group name
+    7 - match case? 0/1
+    8 - search mode:
+        0 - the whole term must appear as substring
+        1 - all single terms (delimiters are blank,',', ';', '|' or '~')
+            must exist as substrings.
+        2 - at least one term (delimiters are blank, ',', ';', '|' or '~')
+            must exist as substring.
+        3 - matches exactly
+        4 - regular expression   
+    9 - use title? 0/1
+    10 - use subtitle? 0/1
+    11 - use description? 0/1
+    12 - use duration? 0/1
+    13 - min duration in hhmm
+    14 - max duration in hhmm
+    15 - use as search timer? 0/1
+    16 - use day of week? 0/1
+    17 - day of week (0 = Sunday, 1 = Monday...;
+         -1 Sunday, -2 Monday, -4 Tuesday, ...; -7 Sun, Mon, Tue)
+    18 - use series recording? 0/1
+    19 - directory for recording
+    20 - priority of recording
+    21 - lifetime of recording
+    22 - time margin for start in minutes
+    23 - time margin for stop in minutes
+    24 - use VPS? 0/1
+    25 - action:
+         0 = create a timer
+         1 = announce only via OSD (no timer)
+         2 = switch only (no timer)
+         3 = announce via OSD and switch (no timer)
+         4 = announce via mail
+    26 - use extended EPG info? 0/1
+    27 - extended EPG info values. This entry has the following format
+         (delimiter is '|' for each category, '#' separates id and value):
+         1 - the id of the extended EPG info category as specified in
+             epgsearchcats.conf
+         2 - the value of the extended EPG info category
+             (a ':' will be translated to "!^colon^!", e.g. in "16:9")
+    28 - avoid repeats? 0/1
+    29 - allowed repeats
+    30 - compare title when testing for a repeat? 0/1
+    31 - compare subtitle when testing for a repeat? 0/1/2
+         0 - no
+         1 - yes
+         2 - yes, if present
+    32 - compare description when testing for a repeat? 0/1
+    33 - compare extended EPG info when testing for a repeat?
+         This entry is a bit field of the category IDs.
+    34 - accepts repeats only within x days
+    35 - delete a recording automatically after x days
+    36 - but keep this number of recordings anyway
+    37 - minutes before switch (if action = 2)
+    38 - pause if x recordings already exist
+    39 - blacklist usage mode (0 none, 1 selection, 2 all)
+    40 - selected blacklist IDs separated with '|'
+    41 - fuzzy tolerance value for fuzzy searching
+    42 - use this search in favorites menu (0 no, 1 yes)
+    43 - id of a menu search template
+    44 - auto deletion mode (0 don't delete search timer, 1 delete after given
+         count of recordings, 2 delete after given days after first recording)
+    45 - count of recordings after which to delete the search timer
+    46 - count of days after the first recording after which to delete the search
+         timer
+    47 - first day where the search timer is active (see parameter 16)
+    48 - last day where the search timer is active (see parameter 16)
+    49 - ignore missing EPG categories? 0/1
+    50 - unmute sound if off when used as switch timer
+    51 - percentage of match when comparing the summary of two events (with 'avoid repeats')
+    52 - HEX representation of the content descriptors, each descriptor ID is represented with 2 chars
+    53 - compare date when testing for a repeat? (0=no, 1=same day, 2=same week, 3=same month)
+*/
+bool cTVGuideSearchTimer::Parse(bool readTemplate) {
+    splitstring s(strTimer.c_str());
+    std::vector<std::string> values = s.split(':', 1);
+    int numValues = values.size();
+    if (numValues < 12)
+        return false;
+    for (int value = 0; value < numValues; value++) {
+    	switch (value) {
+    		case 0:
+                if (!readTemplate)
+                    ID = atoi(values[value].c_str());
+                break;
+    		case 1:
+                if (!readTemplate) {
+                    std::string searchStringMasked = values[value];
+                    std::replace(searchStringMasked.begin(), searchStringMasked.end(), '|', ':');
+                    searchString = searchStringMasked;
+                }
+                break;
+    		case 2:
+                useTime = atoi(values[value].c_str());
+                break;
+            case 3:
+                if (useTime) {
+				    startTime = atoi(values[value].c_str());
+				}
+				break;
+            case 4:
+                if (useTime) {
+				    stopTime = atoi(values[value].c_str());
+				}
+				break;
+    		case 5:
+                useChannel = atoi(values[value].c_str());
+                break;
+            case 6:
+                if (useChannel == 0) {
+                    channelMin = NULL;
+                    channelMax = NULL;
+                } else if (useChannel == 1) {
+                    char *channelMinbuffer = NULL;
+                    char *channelMaxbuffer = NULL;
+                    int channels = sscanf(values[value].c_str(), "%a[^|]|%a[^|]", &channelMinbuffer, &channelMaxbuffer);
+                    channelMin = Channels.GetByChannelID(tChannelID::FromString(channelMinbuffer), true, true);
+                    if (!channelMin) {
+                    	channelMin = channelMax = NULL;
+                        useChannel = 0;
+                    }
+                    if (channels == 1)
+                        channelMax = channelMin;
+                    else {
+                        channelMax = Channels.GetByChannelID(tChannelID::FromString(channelMaxbuffer), true, true);
+                        if (!channelMax) {
+                            channelMin = channelMax = NULL;
+                            useChannel = 0;
+                        }
+                    }
+                    free(channelMinbuffer);
+                    free(channelMaxbuffer);
+                } else if (useChannel == 2) {
+                	channelGroup = values[value];
+                }
+                break;
+           	case 7:
+           		useCase = atoi(values[value].c_str());
+                break;
+            case 8:  
+                mode = atoi(values[value].c_str());
+                break;
+            case 9: 
+                useTitle = atoi(values[value].c_str());
+                break;
+            case 10: 
+                useSubtitle = atoi(values[value].c_str());
+                break;
+            case 11: 
+                useDescription = atoi(values[value].c_str());
+                break;
+            case 12: 
+                useDuration = atoi(values[value].c_str());
+                break;
+            case 13: 
+                minDuration = atoi(values[value].c_str());
+                break;
+            case 14: 
+                maxDuration = atoi(values[value].c_str());
+                break;
+            case 15: 
+                useAsSearchTimer = atoi(values[value].c_str());
+                break;
+            case 16: 
+                useDayOfWeek = atoi(values[value].c_str());
+                break;
+            case 17: 
+                dayOfWeek = atoi(values[value].c_str());
+                break;
+            case 18: 
+                useEpisode = atoi(values[value].c_str());
+                break;
+            case 19:  
+                directory = values[value];
+                break;
+            case 20: 
+                priority = atoi(values[value].c_str());
+                break;
+            case 21: 
+                lifetime = atoi(values[value].c_str());
+                break;
+            case 22: 
+                marginStart = atoi(values[value].c_str());
+                break;
+            case 23: 
+                marginStop = atoi(values[value].c_str());
+                break;
+            case 24: 
+                useVPS = atoi(values[value].c_str());
+                break;
+            case 25: 
+                action = atoi(values[value].c_str());
+                break;
+            case 26: 
+                useExtEPGInfo = atoi(values[value].c_str());
+                break;
+            case 27: 
+                extEPGInfoValues = values[value];
+                break;
+            case 28: 
+                avoidRepeats = atoi(values[value].c_str());
+                break;
+            case 29: 
+                allowedRepeats = atoi(values[value].c_str());
+                break;
+            case 30: 
+                compareTitle = atoi(values[value].c_str());
+                break;
+            case 31: 
+                compareSubtitle = atoi(values[value].c_str());
+                break;
+            case 32: 
+                compareSummary = atoi(values[value].c_str());
+                break;
+            case 33: 
+                catvaluesAvoidRepeat = atol(values[value].c_str());
+                break;
+            case 34: 
+                repeatsWithinDays = atoi(values[value].c_str());
+                break;
+            case 35: 
+                delAfterDays = atoi(values[value].c_str());
+                break;
+            case 36:  
+                recordingsKeep = atoi(values[value].c_str());
+                break;
+            case 37: 
+                switchMinsBefore = atoi(values[value].c_str());
+                break;
+            case 38: 
+                pauseOnNrRecordings = atoi(values[value].c_str());
+                break;
+            case 39: 
+                blacklistMode = atoi(values[value].c_str());
+                break;
+            case 40:
+                blacklists = values[value];
+                break;
+            case 41: 
+                fuzzyTolerance = atoi(values[value].c_str());
+                break;
+            case 42: 
+                useInFavorites = atoi(values[value].c_str());
+                break;
+            case 43: 
+                menuTemplate = atoi(values[value].c_str());
+                break;
+            case 44: 
+                delMode = atoi(values[value].c_str());
+                break;
+            case 45: 
+                delAfterCountRecs = atoi(values[value].c_str());
+                break;
+            case 46: 
+                delAfterDaysOfFirstRec = atoi(values[value].c_str());
+                break;
+            case 47:
+                useAsSearchTimerFrom = atol(values[value].c_str());
+                break;
+            case 48:
+                useAsSearchTimerTil = atol(values[value].c_str());
+                break;
+            case 49:
+                ignoreMissingEPGCats = atoi(values[value].c_str());
+                break;
+            case 50:
+                unmuteSoundOnSwitch = atoi(values[value].c_str());
+                break;
+            case 51:
+                compareSummaryMatchInPercent = atoi(values[value].c_str());
+                break;
+            case 52:
+                contentsFilter = values[value];
+                break;
+            case 53:
+                compareDate = atoi(values[value].c_str());
+                break;
+            default:
+                break;
+        }
+    }
+    return true;
+}
+
+std::string cTVGuideSearchTimer::BuildSearchString(void) {
+    std::stringstream search;
+    // 0 - 2
+    if (ID > -1)
+        search << ID << ":";
+    else
+        search << ":";
+    std::string searchStringMasked = searchString;
+    std::replace(searchStringMasked.begin(), searchStringMasked.end(), ':', '|');
+    search << searchStringMasked << ":"; 
+    search << useTime << ":";
+    
+    // 3 - 6
+    if (useTime) {
+        search << *cString::sprintf("%04d", startTime) << ":";
+        search << *cString::sprintf("%04d", stopTime) << ":";
+    } else {
+        search << "::";
+    }
+
+    search << useChannel << ":";
+    if (useChannel == 1) {
+        if (channelMin && channelMax) {
+            if (channelMin->Number() < channelMax->Number())
+                search << std::string(channelMin->GetChannelID().ToString()) << "|" << std::string(channelMax->GetChannelID().ToString()) << ":";
+            else
+                search << std::string(channelMin->GetChannelID().ToString()) << ":";
+        } else {
+            search << "0:";
+        }
+    } else if (useChannel == 2) {
+        search << channelGroup << ":";
+    } else {
+        search << "0:";
+    }
+    // 7 - 14
+    search << useCase << ":";
+    search << mode << ":";
+    search << useTitle << ":";
+    search << useSubtitle << ":";
+    search << useDescription << ":";
+    search << useDuration << ":";
+    if (useDuration) {
+        search << *cString::sprintf("%04d", minDuration) << ":";
+        search << *cString::sprintf("%04d", maxDuration) << ":";
+    } else {
+        search << "::";
+    }
+    //15 - 53
+    search << useAsSearchTimer << ":";
+    search << useDayOfWeek << ":";
+    search << dayOfWeek << ":";
+    search << useEpisode << ":";
+    search << directory << ":";
+    search << priority << ":";
+    search << lifetime << ":";
+    search << marginStart << ":";
+    search << marginStop << ":";
+    search << useVPS << ":";
+    search << action << ":";
+    search << useExtEPGInfo << ":";
+    search << extEPGInfoValues << ":";
+    search << avoidRepeats << ":";
+    search << allowedRepeats << ":";
+    search << compareTitle << ":";
+    search << compareSubtitle << ":";
+    search << compareSummary << ":";
+    search << catvaluesAvoidRepeat << ":";
+    search << repeatsWithinDays << ":";
+    search << delAfterDays << ":";
+    search << recordingsKeep << ":";
+    search << switchMinsBefore << ":";
+    search << pauseOnNrRecordings << ":";
+    search << blacklistMode << ":";
+    search << blacklists << ":";
+    search << fuzzyTolerance << ":";
+    search << useInFavorites << ":";
+    search << menuTemplate << ":";
+    search << delMode << ":";
+    search << delAfterCountRecs << ":";
+    search << delAfterDaysOfFirstRec << ":";
+    search << useAsSearchTimerFrom << ":";
+    search << useAsSearchTimerTil << ":";
+    search << ignoreMissingEPGCats << ":";
+    search << unmuteSoundOnSwitch << ":";
+    search << compareSummaryMatchInPercent << ":";
+    search << contentsFilter << ":";
+    search << compareDate;
+
+    strTimer = search.str();
+    return strTimer;
+}
+
+bool cTVGuideSearchTimer::Active(void) {
+    if (useAsSearchTimer)
+        return true;
+    return false;
+}
+
+
+int cTVGuideSearchTimer::GetNumTimers(void) {
+    int numTimers = 0;
+    if (ID < 0)
+    	return numTimers;
+    for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
+        char* searchID = GetAuxValue(timer, "s-id");
+        if (!searchID) continue;
+      	if (ID == atoi(searchID))
+        	numTimers++;
+	    free(searchID);
+    }
+    return numTimers;
+}
+
+int cTVGuideSearchTimer::GetNumRecordings(void) {
+    int numRecordings = 0;
+    if (ID < 0)
+        return numRecordings;
+    for (cRecording *recording = Recordings.First(); recording; recording = Recordings.Next(recording)) {
+        if (recording->IsEdited()) 
+            continue;
+        if (!recording->Info()) 
+            continue;
+        char* searchID = GetAuxValue(recording, "s-id");
+        if (!searchID) continue;
+        if (ID == atoi(searchID))
+            numRecordings++;
+        free(searchID);
+    }
+    return numRecordings;
+}
+
+void cTVGuideSearchTimer::GetSearchModes(std::vector<std::string> *searchModes) {
+    searchModes->push_back(tr("whole term must appear"));
+    searchModes->push_back(tr("all terms must exist"));
+    searchModes->push_back(tr("one term must exist"));
+    searchModes->push_back(tr("exact match"));
+    searchModes->push_back(tr("regular expression"));
+}
+
+
+void cTVGuideSearchTimer::Dump(void) {
+    esyslog("tvguide searchtimer: strTimer: %s", strTimer.c_str());
+    esyslog("tvguide searchtimer: ID: %d", ID);
+    esyslog("tvguide searchtimer: searchString: %s", searchString.c_str());
+    esyslog("tvguide searchtimer: useTime: %d", useTime);
+    esyslog("tvguide searchtimer: startTime: %d", startTime);
+    esyslog("tvguide searchtimer: stopTime: %d", stopTime);
+    esyslog("tvguide searchtimer: useChannel: %d", useChannel);
+    if (channelMin)
+	    esyslog("tvguide searchtimer: channelMin: %s", channelMin->Name());
+    if (channelMax)
+	    esyslog("tvguide searchtimer: channelMax: %s", channelMax->Name());
+    esyslog("tvguide searchtimer: channelGroup: %s", channelGroup.c_str());
+    esyslog("tvguide searchtimer: useCase: %d", useCase);
+    esyslog("tvguide searchtimer: mode: %d", mode);
+    esyslog("tvguide searchtimer: useTitle: %d", useTitle);
+    esyslog("tvguide searchtimer: useSubtitle: %d", useSubtitle);
+    esyslog("tvguide searchtimer: useDescription: %d", useDescription);
+}
+
diff --git a/searchtimer.h b/searchtimer.h
new file mode 100644
index 0000000..f797ebd
--- /dev/null
+++ b/searchtimer.h
@@ -0,0 +1,136 @@
+#ifndef __TVGUIDE_SEARCHTIMER_H
+#define __TVGUIDE_SEARCHTIMER_H
+
+
+class cTVGuideSearchTimer {
+private:
+    std::string strTimer;
+    int         ID;
+    std::string searchString;
+    int         useTime;
+    int         startTime;
+    int      	stopTime;
+    int         useChannel;
+    cChannel 	*channelMin;
+    cChannel 	*channelMax;
+    std::string channelGroup;
+    int      	useCase;
+    int      	mode;
+    int         useTitle;
+    int         useSubtitle;
+    int         useDescription;
+    int         useDuration;
+    int         minDuration;
+    int         maxDuration;
+    int         useAsSearchTimer;
+    int         useDayOfWeek;
+    int         dayOfWeek;
+    int         useEpisode;
+    std::string directory;
+    int         priority;
+    int         lifetime;
+    int         marginStart;
+    int         marginStop;
+    int         useVPS;
+    int         action;
+    int         useExtEPGInfo;
+    std::string extEPGInfoValues;
+    int         avoidRepeats;
+    int         allowedRepeats;
+    int         compareTitle;
+    int         compareSubtitle;
+    int         compareSummary;
+    unsigned long catvaluesAvoidRepeat;
+    int         repeatsWithinDays;
+    int         delAfterDays;
+    int         recordingsKeep;
+    int         switchMinsBefore;
+    int         pauseOnNrRecordings;
+    int         blacklistMode;
+    std::string blacklists;
+    int         fuzzyTolerance;
+    int         useInFavorites;
+    int         menuTemplate;
+    int         delMode;
+    int         delAfterCountRecs;
+    int         delAfterDaysOfFirstRec;
+    int         useAsSearchTimerFrom;
+    int         useAsSearchTimerTil;
+    int         ignoreMissingEPGCats;
+    int         unmuteSoundOnSwitch;
+    int         compareSummaryMatchInPercent;
+    std::string contentsFilter;
+    int         compareDate;
+public:
+    cTVGuideSearchTimer(void);
+    virtual ~cTVGuideSearchTimer(void);
+    bool operator < (const cTVGuideSearchTimer& other) const;
+    void SetEPGSearchString(std::string strTimer) { this->strTimer = strTimer; };
+    void SetTemplate(std::string tmpl);
+    bool Parse(bool readTemplate = false);
+    std::string BuildSearchString(void);
+    int GetID(void) { return ID; };
+    //GETTER
+    std::string SearchString(void) const { return searchString; };
+    bool Active(void);
+    bool UseTitle(void) { return useTitle; };
+    bool UseSubtitle(void) { return useSubtitle; };
+    bool UseDescription(void) { return useDescription; };
+    int SearchMode(void) { return mode; };
+    bool UseChannel(void) { return useChannel; };
+    int StartChannel(void) { return (channelMin)?channelMin->Number():0; };
+    int StopChannel(void) { return (channelMax)?channelMax->Number():0; };
+    bool UseTime(void) { return useTime; };
+    int StartTime(void) { return startTime; };
+    int StopTime(void) { return stopTime; };
+    bool UseDayOfWeek(void) { return useDayOfWeek; };
+    int DayOfWeek(void);
+    int UseEpisode(void) { return useEpisode; };
+    std::string Directory(void) { return directory; };
+    int Priority(void) { return priority; };
+    int Lifetime(void) { return lifetime; };
+    int MarginStart(void) { return marginStart; };
+    int MarginStop(void) { return marginStop; };
+    bool UseVPS(void) { return useVPS; };
+    bool AvoidRepeats(void) { return avoidRepeats; };
+    int AllowedRepeats(void) { return allowedRepeats; };
+    bool CompareTitle(void) { return compareTitle; };
+    bool CompareSubtitle(void) { return compareSubtitle; };
+    bool CompareSummary(void) { return compareSummary; };
+    bool UseInFavorites(void) { return useInFavorites; };
+    //SETTER
+    void SetSearchString(std::string searchString) { this->searchString = searchString; };
+    void SetActive(bool active) { useAsSearchTimer = active; };
+    void SetSearchMode(int searchMode) { mode = searchMode; };
+    void SetUseTitle(bool useTitle) { this->useTitle = useTitle; };
+    void SetUseSubtitle(bool useSubtitle) { this->useSubtitle = useSubtitle; };
+    void SetUseDesription(bool useDescription) { this->useDescription = useDescription; };
+    void SetUseChannel(bool useChannel) { this->useChannel = useChannel; };
+    void SetStartChannel(int startChannel) { channelMin = Channels.GetByNumber(startChannel); };
+    void SetStopChannel(int stopChannel) { channelMax = Channels.GetByNumber(stopChannel); };
+    void SetUseTime(bool useTime) { this->useTime = useTime; };
+    void SetStartTime(int startTime) { this->startTime = startTime; };
+    void SetStopTime(int stopTime) { this->stopTime = stopTime; };
+    void SetUseDayOfWeek(bool useDayOfWeek) { this->useDayOfWeek = useDayOfWeek; };
+    void SetDayOfWeek(int VDRDayOfWeek);
+    void SetUseEpisode(int useEpisode) { this->useEpisode = useEpisode; };
+    void SetDirectory(std::string directory) { this-> directory = directory; };
+    void SetPriority(int priority) { this->priority = priority; };
+    void SetLifetime(int lifetime) { this->lifetime = lifetime; };
+    void SetMarginStart(int marginStart) { this->marginStart = marginStart; };
+    void SetMarginStop(int marginStop) { this->marginStop = marginStop; };
+    void SetUseVPS(bool useVPS) { this->useVPS = useVPS; };
+    void SetAvoidRepeats(bool avoidRepeats) { this->avoidRepeats = avoidRepeats; };
+    void SetAllowedRepeats(int allowedRepeats) { this->allowedRepeats = allowedRepeats; };
+    void SetCompareTitle(bool compareTitle) { this->compareTitle = compareTitle; };
+    void SetCompareSubtitle(bool compareSubtitle) { this->compareSubtitle = compareSubtitle; };
+    void SetCompareSummary(bool compareSummary) { this->compareSummary = compareSummary; };
+    void SetUseInFavorites(bool useInFavorites) { this->useInFavorites = useInFavorites; };
+    //COMMON
+    int GetNumTimers(void);
+    int GetNumRecordings(void);
+    void GetSearchModes(std::vector<std::string> *searchModes);
+    void Dump(void);
+};
+
+#endif //__TVGUIDE_SEARCHTIMER_H
diff --git a/services/epgsearch.h b/services/epgsearch.h
new file mode 100644
index 0000000..2669da4
--- /dev/null
+++ b/services/epgsearch.h
@@ -0,0 +1,202 @@
+/*                                                                  -*- c++ -*-
+Copyright (C) 2004-2013 Christian Wieninger
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+Or, point your browser to http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+
+The author can be reached at cwieninger at gmx.de
+
+The project's page is at http://winni.vdr-developer.org/epgsearch
+*/
+
+#ifndef EPGSEARCHSERVICES_INC
+#define EPGSEARCHSERVICES_INC
+
+#include <string>
+#include <list>
+#include <memory>
+#include <set>
+#include <vdr/osdbase.h>
+
+// Data structure for service "Epgsearch-search-v1.0"
+struct Epgsearch_search_v1_0
+{
+// in
+      char* query;               // search term
+      int mode;                  // search mode (0=phrase, 1=and, 2=or, 3=regular expression)
+      int channelNr;             // channel number to search in (0=any)
+      bool useTitle;             // search in title
+      bool useSubTitle;          // search in subtitle
+      bool useDescription;       // search in description
+// out
+      cOsdMenu* pResultMenu;   // pointer to the menu of results
+};
+
+// Data structure for service "Epgsearch-exttimeredit-v1.0"
+struct Epgsearch_exttimeredit_v1_0
+{
+// in
+      cTimer* timer;             // pointer to the timer to edit
+      bool bNew;                 // flag that indicates, if this is a new timer or an existing one
+      const cEvent* event;             // pointer to the event corresponding to this timer (may be NULL)
+// out
+      cOsdMenu* pTimerMenu;   // pointer to the menu of results
+};
+
+// Data structure for service "Epgsearch-enablesearchtimers-v1.0"
+struct Epgsearch_enablesearchtimers_v1_0
+{
+// in
+      bool enable;           // enable search timer thread?
+};
+
+// Data structure for service "Epgsearch-updatesearchtimers-v1.0"
+struct Epgsearch_updatesearchtimers_v1_0
+{
+// in
+      bool showMessage;           // inform via osd when finished?
+};
+
+// Data structure for service "Epgsearch-osdmessage-v1.0"
+struct Epgsearch_osdmessage_v1_0
+{
+// in
+      char* message;             // the message to display
+      eMessageType type;
+};
+
+// Data structure for service "EpgsearchMenu-v1.0"
+struct EpgSearchMenu_v1_0
+{
+// in
+// out
+      cOsdMenu* Menu;   // pointer to the menu
+};
+
+// Data structure for service "Epgsearch-lastconflictinfo-v1.0"
+struct Epgsearch_lastconflictinfo_v1_0
+{
+// in
+// out
+      time_t nextConflict;       // next conflict date, 0 if none
+      int relevantConflicts;     // number of relevant conflicts
+      int totalConflicts;        // total number of conflicts
+};
+
+// Data structure for service "Epgsearch-searchresults-v1.0"
+struct Epgsearch_searchresults_v1_0
+{
+// in
+      char* query;               // search term
+      int mode;                  // search mode (0=phrase, 1=and, 2=or, 3=regular expression)
+      int channelNr;             // channel number to search in (0=any)
+      bool useTitle;             // search in title
+      bool useSubTitle;          // search in subtitle
+      bool useDescription;       // search in description
+// out
+
+      class cServiceSearchResult : public cListObject
+      {
+        public:
+         const cEvent* event;
+         cServiceSearchResult(const cEvent* Event) : event(Event) {}
+      };
+
+      cList<cServiceSearchResult>* pResultList;   // pointer to the results
+};
+
+// Data structure for service "Epgsearch-switchtimer-v1.0"
+struct Epgsearch_switchtimer_v1_0
+{
+// in
+      const cEvent* event;
+      int mode;                  // mode (0=query existence, 1=add/modify, 2=delete)
+// in/out
+      int switchMinsBefore;
+      int announceOnly;
+// out
+      bool success;              // result
+};
+
+// Data structures for service "Epgsearch-services-v1.0"
+class cServiceHandler
+{
+  public:
+   virtual std::list<std::string> SearchTimerList() = 0;
+   // returns a list of search timer entries in the same format as used in epgsearch.conf
+   virtual int AddSearchTimer(const std::string&) = 0;
+   // adds a new search timer and returns its ID (-1 on error)
+   virtual bool ModSearchTimer(const std::string&) = 0;
+   // edits an existing search timer and returns success
+   virtual bool DelSearchTimer(int) = 0;
+   // deletes search timer with given ID and returns success
+   virtual std::list<std::string> QuerySearchTimer(int) = 0;
+   // returns the search result of the searchtimer with given ID in the same format as used in SVDRP command 'QRYS' (->MANUAL)
+   virtual std::list<std::string> QuerySearch(std::string) = 0;
+   // returns the search result of the searchtimer with given settings in the same format as used in SVDRP command 'QRYS' (->MANUAL)
+   virtual std::list<std::string> ExtEPGInfoList() = 0;
+   // returns a list of extended EPG categories in the same format as used in epgsearchcats.conf
+   virtual std::list<std::string> ChanGrpList() = 0;
+   // returns a list of channel groups maintained by epgsearch
+   virtual std::list<std::string> BlackList() = 0;
+   // returns a list of blacklists in the same format as used in epgsearchblacklists.conf
+   virtual std::set<std::string> DirectoryList() = 0;
+   // List of all recording directories used in recordings, timers, search timers or in epgsearchdirs.conf
+   virtual ~cServiceHandler() {}
+   // Read a setup value
+   virtual std::string ReadSetupValue(const std::string& entry) = 0;
+   // Write a setup value
+   virtual bool WriteSetupValue(const std::string& entry, const std::string& value) = 0;
+};
+
+struct Epgsearch_services_v1_0
+{
+// in/out
+      std::auto_ptr<cServiceHandler> handler;
+};
+
+// Data structures for service "Epgsearch-services-v1.1"
+class cServiceHandler_v1_1 : public cServiceHandler
+{
+  public:
+   // Get timer conflicts
+   virtual std::list<std::string> TimerConflictList(bool relOnly=false) = 0;
+   // Check if a conflict check is advised
+   virtual bool IsConflictCheckAdvised() = 0;
+};
+
+struct Epgsearch_services_v1_1
+{
+// in/out
+      std::auto_ptr<cServiceHandler_v1_1> handler;
+};
+
+// Data structures for service "Epgsearch-services-v1.2"
+class cServiceHandler_v1_2 : public cServiceHandler_v1_1
+{
+  public:
+  // List of all recording directories used in recordings, timers (and optionally search timers or in epgsearchdirs.conf)
+  virtual std::set<std::string> ShortDirectoryList() = 0;
+  // Evaluate an expression against an event
+  virtual std::string Evaluate(const std::string& expr, const cEvent* event) = 0;
+};
+
+struct Epgsearch_services_v1_2
+{
+// in/out
+      std::auto_ptr<cServiceHandler_v1_2> handler;
+};
+
+#endif
diff --git a/services/remotetimers.h b/services/remotetimers.h
new file mode 100644
index 0000000..cd86b7a
--- /dev/null
+++ b/services/remotetimers.h
@@ -0,0 +1,33 @@
+#ifndef REMOTETIMERSERVICES_INC
+#define REMOTETIMERSERVICES_INC
+
+#include <vdr/epg.h>
+#include <vdr/timers.h>
+
+// RemoteTimers services
+struct RemoteTimers_Event_v1_0 {
+    //in
+    const cEvent *event;
+    //out
+    cTimer *timer;
+    cString errorMsg;
+};
+
+struct RemoteTimers_GetMatch_v1_0 {
+    //in
+    const cEvent *event;
+    //out
+    cTimer *timer;
+    int timerMatch;
+    int timerType;
+    bool isRemote;
+};
+
+struct RemoteTimers_Timer_v1_0 {
+    //in+out
+    cTimer *timer;
+    //out
+    cString errorMsg;
+};
+
+#endif //REMOTETIMERSERVICES_INC
\ No newline at end of file
diff --git a/services/scraper2vdr.h b/services/scraper2vdr.h
new file mode 100644
index 0000000..703d077
--- /dev/null
+++ b/services/scraper2vdr.h
@@ -0,0 +1,194 @@
+#ifndef __SCRAPER2VDRSERVICES_H
+#define __SCRAPER2VDRSERVICES_H
+
+#include <vdr/epg.h>
+#include <vdr/recording.h>
+
+enum tvType {
+    tSeries,
+    tMovie,
+    tNone,
+};
+
+/*********************************************************************
+* Helper Structures
+*********************************************************************/
+class cTvMedia {
+public:
+	cTvMedia(void) {
+		path = "";
+		width = height = 0;
+	};
+    std::string path;
+    int width;
+    int height;
+};
+
+class cEpisode {
+public:
+    cEpisode(void) {
+        number = 0;
+        season = 0;
+        name = "";
+        firstAired = "";
+        guestStars = "";
+        overview = "";
+        rating = 0.0;
+    };
+    int number;
+    int season;
+    std::string name;
+    std::string firstAired;
+    std::string guestStars;
+    std::string overview;
+    float rating;
+    cTvMedia episodeImage;
+};
+
+class cActor {
+public:
+    cActor(void) {
+        name = "";
+        role = "";
+    };
+    std::string name;
+    std::string role;
+    cTvMedia actorThumb;
+};
+
+/*********************************************************************
+* Data Structures for Service Calls
+*********************************************************************/
+
+// Data structure for service "GetEventType"
+class ScraperGetEventType {
+public:
+	ScraperGetEventType(void) {
+		event = NULL;
+        recording = NULL;
+		type = tNone;
+		movieId = 0;
+		seriesId = 0;
+		episodeId = 0;
+	};
+// in
+    const cEvent *event;             // check type for this event 
+    const cRecording *recording;     // or for this recording
+//out
+    tvType type;                	 //typeSeries or typeMovie
+    int movieId;
+    int seriesId;
+    int episodeId;
+};
+
+//Data structure for full series and episode information
+class cMovie {
+public:
+    cMovie(void) {
+        title = "";
+        originalTitle = "";
+        tagline = "";    
+        overview = "";
+        adult = false;
+        collectionName = "";
+        budget = 0;
+        revenue = 0;
+        genres = "";
+        homepage = "";
+        releaseDate = "";
+        runtime = 0;
+        popularity = 0.0;
+        voteAverage = 0.0;
+    };
+//IN
+    int movieId;                    // movieId fetched from ScraperGetEventType
+//OUT    
+    std::string title;
+    std::string originalTitle;
+    std::string tagline;    
+    std::string overview;
+    bool adult;
+    std::string collectionName;
+    int budget;
+    int revenue;
+    std::string genres;
+    std::string homepage;
+    std::string releaseDate;
+    int runtime;
+    float popularity;
+    float voteAverage;
+    cTvMedia poster;
+    cTvMedia fanart;
+    cTvMedia collectionPoster;
+    cTvMedia collectionFanart;
+    std::vector<cActor> actors;
+};
+
+//Data structure for full series and episode information
+class cSeries {
+public:
+    cSeries(void) {
+        seriesId = 0;
+        episodeId = 0;
+        name = "";
+        overview = "";
+        firstAired = "";
+        network = "";
+        genre = "";
+        rating = 0.0;
+        status = "";
+    };
+//IN
+    int seriesId;                   // seriesId fetched from ScraperGetEventType
+    int episodeId;                  // episodeId fetched from ScraperGetEventType
+//OUT
+    std::string name;
+    std::string overview;
+    std::string firstAired;
+    std::string network;
+    std::string genre;
+    float rating;
+    std::string status;
+    cEpisode episode;
+    std::vector<cActor> actors;
+    std::vector<cTvMedia> posters;
+    std::vector<cTvMedia> banners;
+    std::vector<cTvMedia> fanarts;
+    cTvMedia seasonPoster;
+};
+
+// Data structure for service "GetPosterBanner"
+class ScraperGetPosterBanner {
+public:
+	ScraperGetPosterBanner(void) {
+		type = tNone;
+	};
+// in
+    const cEvent *event;             // check type for this event 
+//out
+    tvType type;                	 //typeSeries or typeMovie
+    cTvMedia poster;
+    cTvMedia banner;
+};
+
+// Data structure for service "GetPoster"
+class ScraperGetPoster {
+public:
+// in
+    const cEvent *event;             // check type for this event
+    const cRecording *recording;     // or for this recording
+//out
+    cTvMedia poster;
+};
+
+// Data structure for service "GetPosterThumb"
+class ScraperGetPosterThumb {
+public:
+// in
+    const cEvent *event;             // check type for this event
+    const cRecording *recording;     // or for this recording
+//out
+    cTvMedia poster;
+};
+
+#endif //__SCRAPER2VDRSERVICES_H
\ No newline at end of file
diff --git a/setup.c b/setup.c
index a8e57d6..c58af4d 100644
--- a/setup.c
+++ b/setup.c
@@ -1,86 +1,161 @@
 #include "setup.h"
 
 cTvguideSetup::cTvguideSetup() {
-	tmpTvguideConfig = tvguideConfig;
-	Setup();
+    tmpTvguideConfig = tvguideConfig;
+    Setup();
 }
 
 cTvguideSetup::~cTvguideSetup() {
+    geoManager.SetGeometry(cOsd::OsdWidth(), cOsd::OsdHeight(), true);
+    fontManager.DeleteFonts();
+    fontManager.SetFonts();
+    tvguideConfig.LoadTheme();
+    tvguideConfig.setDynamicValues();
+    imgCache.Clear();
+    imgCache.CreateCache();
 }
 
 
 void cTvguideSetup::Setup(void) {
-	int currentItem = Current();
-	Clear();
-	
-	Add(new cOsdItem(tr("General Settings")));
-	Add(new cOsdItem(tr("Screen Presentation")));
-	Add(new cOsdItem(tr("Fonts and Fontsizes")));
-	
-	SetCurrent(Get(currentItem));
-	Display();
+    int currentItem = Current();
+    Clear();
+    
+    Add(new cOsdItem(tr("General Settings")));
+    Add(new cOsdItem(tr("Screen Presentation")));
+    Add(new cOsdItem(tr("Fonts and Fontsizes")));
+    Add(new cOsdItem(tr("Recording Menus and Favorites")));
+    Add(new cOsdItem(tr("Image Loading and Caching")));
+
+    SetCurrent(Get(currentItem));
+    Display();
 }
 
 eOSState cTvguideSetup::ProcessKey(eKeys Key) {
-	bool hadSubMenu = HasSubMenu();	  
-	eOSState state = cMenuSetupPage::ProcessKey(Key);
-	if (hadSubMenu && Key == kOk)
-		Store();
-		
-	if (!hadSubMenu && (state == osUnknown || Key == kOk)) {
-		if ((Key == kOk && !hadSubMenu)) {
-			const char* ItemText = Get(Current())->Text();
-			if (strcmp(ItemText, tr("General Settings")) == 0)
-				state = AddSubMenu(new cMenuSetupGeneral(&tmpTvguideConfig));
-			if (strcmp(ItemText, tr("Screen Presentation")) == 0)
-				state = AddSubMenu(new cMenuSetupScreenLayout(&tmpTvguideConfig));
-			if (strcmp(ItemText, tr("Fonts and Fontsizes")) == 0)
-				state = AddSubMenu(new cMenuSetupFont(&tmpTvguideConfig));	
-		}
-	}	
-	return state;
+    bool hadSubMenu = HasSubMenu();   
+    eOSState state = cMenuSetupPage::ProcessKey(Key);
+    if (hadSubMenu && Key == kOk)
+        Store();
+        
+    if (!hadSubMenu && (state == osUnknown || Key == kOk)) {
+        if ((Key == kOk && !hadSubMenu)) {
+            const char* ItemText = Get(Current())->Text();
+            if (strcmp(ItemText, tr("General Settings")) == 0)
+                state = AddSubMenu(new cMenuSetupGeneral(&tmpTvguideConfig));
+            if (strcmp(ItemText, tr("Screen Presentation")) == 0)
+                state = AddSubMenu(new cMenuSetupScreenLayout(&tmpTvguideConfig));
+            if (strcmp(ItemText, tr("Fonts and Fontsizes")) == 0)
+                state = AddSubMenu(new cMenuSetupFont(&tmpTvguideConfig));
+            if (strcmp(ItemText, tr("Recording Menus and Favorites")) == 0)
+                state = AddSubMenu(new cMenuSetupFavorites(&tmpTvguideConfig));
+            if (strcmp(ItemText, tr("Image Loading and Caching")) == 0)
+                state = AddSubMenu(new cMenuSetupImageCache(&tmpTvguideConfig));  
+        }
+    }   
+    return state;
 }
 
 void cTvguideSetup::Store(void) {
 
-	tvguideConfig = tmpTvguideConfig;
-
-	SetupStore("themeIndex", tvguideConfig.themeIndex);
-	SetupStore("useBlending", tvguideConfig.useBlending);
-	SetupStore("roundedCorners", tvguideConfig.roundedCorners);
-	SetupStore("timeFormat", tvguideConfig.timeFormat);
-	SetupStore("channelCols", tvguideConfig.channelCols);
-	SetupStore("displayTime", tvguideConfig.displayTime);
-	SetupStore("bigStepHours", tvguideConfig.bigStepHours);
-	SetupStore("hugeStepHours", tvguideConfig.hugeStepHours);
-	SetupStore("jumpChannels", tvguideConfig.jumpChannels);
-	SetupStore("hideChannelLogos", tvguideConfig.hideChannelLogos);
-	SetupStore("logoExtension", tvguideConfig.logoExtension);
-	SetupStore("logoWidth", tvguideConfig.logoWidth);
-	SetupStore("logoHeight", tvguideConfig.logoHeight);
-	SetupStore("hideEpgImages", tvguideConfig.hideEpgImages);
-	SetupStore("epgImageWidth", tvguideConfig.epgImageWidth);
-	SetupStore("epgImageHeight", tvguideConfig.epgImageHeight);
-	SetupStore("epgImageHeight", tvguideConfig.epgImageHeight);
-	SetupStore("timeColWidth", tvguideConfig.timeColWidth);
-	SetupStore("headerHeight", tvguideConfig.headerHeight);
-	SetupStore("footerHeight", tvguideConfig.footerHeight);
-	SetupStore("fontIndex", tvguideConfig.fontIndex);
-	SetupStore("fontHeaderSize", tvguideConfig.fontHeaderSize);
-	SetupStore("fontGridSize", tvguideConfig.fontGridSize);
-	SetupStore("fontGridSmallSize", tvguideConfig.fontGridSmallSize);
-	SetupStore("fontTimeLineWeekdaySize", tvguideConfig.fontTimeLineWeekdaySize);
-	SetupStore("fontTimeLineDateSize", tvguideConfig.fontTimeLineDateSize);
-	SetupStore("fontTimeLineTimeSize", tvguideConfig.fontTimeLineTimeSize);
-	SetupStore("fontButtonSize", tvguideConfig.fontButtonSize);
-	SetupStore("fontDetailViewSize", tvguideConfig.fontDetailViewSize);
-	SetupStore("fontDetailHeaderSize", tvguideConfig.fontDetailHeaderSize);
-	SetupStore("fontMessageBoxSize", tvguideConfig.fontMessageBoxSize);
-	SetupStore("fontMessageBoxLargeSize", tvguideConfig.fontMessageBoxLargeSize);
+    tvguideConfig = tmpTvguideConfig;
+    SetupStore("debugImageLoading", tvguideConfig.debugImageLoading);
+    SetupStore("useNopacityTheme", tvguideConfig.useNopacityTheme);
+    SetupStore("themeIndex", tvguideConfig.themeIndex);
+    SetupStore("showMainMenuEntry", tvguideConfig.showMainMenuEntry);
+    SetupStore("replaceOriginalSchedule", tvguideConfig.replaceOriginalSchedule);
+    SetupStore("displayMode", tvguideConfig.displayMode);
+    SetupStore("showTimeInGrid", tvguideConfig.showTimeInGrid);
+    SetupStore("displayStatusHeader", tvguideConfig.displayStatusHeader);
+    SetupStore("displayChannelGroups", tvguideConfig.displayChannelGroups);
+    SetupStore("displayTimeBase", tvguideConfig.displayTimeBase);
+    SetupStore("headerHeightPercent", tvguideConfig.headerHeightPercent);
+    SetupStore("channelGroupsPercent", tvguideConfig.channelGroupsPercent);
+    SetupStore("epgViewBorder", tvguideConfig.epgViewBorder);
+    SetupStore("scaleVideo", tvguideConfig.scaleVideo);
+    SetupStore("decorateVideo", tvguideConfig.decorateVideo);
+    SetupStore("roundedCorners", tvguideConfig.roundedCorners);
+    SetupStore("timeFormat", tvguideConfig.timeFormat);
+    SetupStore("channelCols", tvguideConfig.channelCols);
+    SetupStore("channelRows", tvguideConfig.channelRows);
+    SetupStore("displayTime", tvguideConfig.displayTime);
+    SetupStore("bigStepHours", tvguideConfig.bigStepHours);
+    SetupStore("hugeStepHours", tvguideConfig.hugeStepHours);
+    SetupStore("channelJumpMode", tvguideConfig.channelJumpMode);
+    SetupStore("blueKeyMode", tvguideConfig.blueKeyMode);
+    SetupStore("numkeyMode", tvguideConfig.numkeyMode);
+    SetupStore("useRemoteTimers", tvguideConfig.useRemoteTimers);
+    SetupStore("closeOnSwitch", tvguideConfig.closeOnSwitch);
+    SetupStore("hideLastGroup", tvguideConfig.hideLastGroup);
+    SetupStore("hideChannelLogos", tvguideConfig.hideChannelLogos);
+    SetupStore("logoExtension", tvguideConfig.logoExtension);
+    SetupStore("logoWidthRatio", tvguideConfig.logoWidthRatio);
+    SetupStore("logoHeightRatio", tvguideConfig.logoHeightRatio);
+    SetupStore("hideEpgImages", tvguideConfig.hideEpgImages);
+    SetupStore("epgImageWidth", tvguideConfig.epgImageWidth);
+    SetupStore("epgImageHeight", tvguideConfig.epgImageHeight);
+    SetupStore("numAdditionalEPGPictures", tvguideConfig.numAdditionalEPGPictures);
+    SetupStore("epgImageWidthLarge", tvguideConfig.epgImageWidthLarge);
+    SetupStore("epgImageHeightLarge", tvguideConfig.epgImageHeightLarge);
+    SetupStore("detailedViewScrollStep", tvguideConfig.detailedViewScrollStep);
+    SetupStore("timeLineWidthPercent", tvguideConfig.timeLineWidthPercent);
+    SetupStore("timeLineHeightPercent", tvguideConfig.timeLineHeightPercent);
+    SetupStore("displayChannelName", tvguideConfig.displayChannelName);
+    SetupStore("channelHeaderWidthPercent", tvguideConfig.channelHeaderWidthPercent);
+    SetupStore("channelHeaderHeightPercent", tvguideConfig.channelHeaderHeightPercent);
+    SetupStore("footerHeightPercent", tvguideConfig.footerHeightPercent);
+    SetupStore("instRecFolderMode", tvguideConfig.instRecFolderMode);
+    SetupStore("instRecFixedFolder", tvguideConfig.instRecFixedFolder.c_str());
+    SetupStore("favWhatsOnNow", tvguideConfig.favWhatsOnNow);
+    SetupStore("favWhatsOnNext", tvguideConfig.favWhatsOnNext);
+    SetupStore("favUseTime1", tvguideConfig.favUseTime1);
+    SetupStore("favUseTime2", tvguideConfig.favUseTime2);
+    SetupStore("favUseTime3", tvguideConfig.favUseTime3);
+    SetupStore("favUseTime4", tvguideConfig.favUseTime4);
+    SetupStore("favTime1", tvguideConfig.favTime1);
+    SetupStore("favTime2", tvguideConfig.favTime2);
+    SetupStore("favTime3", tvguideConfig.favTime3);
+    SetupStore("favTime4", tvguideConfig.favTime4);
+    SetupStore("descUser1", tvguideConfig.descUser1.c_str());
+    SetupStore("descUser2", tvguideConfig.descUser2.c_str());
+    SetupStore("descUser3", tvguideConfig.descUser3.c_str());
+    SetupStore("descUser4", tvguideConfig.descUser4.c_str());
+    SetupStore("favLimitChannels", tvguideConfig.favLimitChannels);
+    SetupStore("favStartChannel", tvguideConfig.favStartChannel);
+    SetupStore("favStopChannel", tvguideConfig.favStopChannel);
+    SetupStore("fontIndex", tvguideConfig.fontIndex);
+    SetupStore("FontButtonDelta", tvguideConfig.FontButtonDelta);
+    SetupStore("FontDetailViewDelta", tvguideConfig.FontDetailViewDelta);
+    SetupStore("FontDetailHeaderDelta", tvguideConfig.FontDetailHeaderDelta);
+    SetupStore("FontMessageBoxDelta", tvguideConfig.FontMessageBoxDelta);
+    SetupStore("FontMessageBoxLargeDelta", tvguideConfig.FontMessageBoxLargeDelta);
+    SetupStore("FontStatusHeaderDelta", tvguideConfig.FontStatusHeaderDelta);
+    SetupStore("FontStatusHeaderLargeDelta", tvguideConfig.FontStatusHeaderLargeDelta);
+    SetupStore("FontChannelHeaderDelta", tvguideConfig.FontChannelHeaderDelta);
+    SetupStore("FontChannelGroupsDelta", tvguideConfig.FontChannelGroupsDelta);
+    SetupStore("FontGridDelta", tvguideConfig.FontGridDelta);
+    SetupStore("FontGridSmallDelta", tvguideConfig.FontGridSmallDelta);
+    SetupStore("FontTimeLineWeekdayDelta", tvguideConfig.FontTimeLineWeekdayDelta);
+    SetupStore("FontTimeLineDateDelta", tvguideConfig.FontTimeLineDateDelta);
+    SetupStore("FontTimeLineTimeDelta", tvguideConfig.FontTimeLineTimeDelta);
+    SetupStore("FontChannelHeaderHorizontalDelta", tvguideConfig.FontChannelHeaderHorizontalDelta);
+    SetupStore("FontChannelGroupsHorizontalDelta", tvguideConfig.FontChannelGroupsHorizontalDelta);
+    SetupStore("FontGridHorizontalDelta", tvguideConfig.FontGridHorizontalDelta);
+    SetupStore("FontGridHorizontalSmallDelta", tvguideConfig.FontGridHorizontalSmallDelta);
+    SetupStore("FontTimeLineDateHorizontalDelta", tvguideConfig.FontTimeLineDateHorizontalDelta);
+    SetupStore("FontTimeLineTimeHorizontalDelta", tvguideConfig.FontTimeLineTimeHorizontalDelta);
+    SetupStore("FontRecMenuItemDelta", tvguideConfig.FontRecMenuItemDelta);
+    SetupStore("FontRecMenuItemSmallDelta", tvguideConfig.FontRecMenuItemSmallDelta);
+    SetupStore("FontRecMenuItemLargeDelta", tvguideConfig.FontRecMenuItemLargeDelta);
+    SetupStore("displayRerunsDetailEPGView", tvguideConfig.displayRerunsDetailEPGView);
+    SetupStore("numReruns", tvguideConfig.numReruns);
+    SetupStore("useSubtitleRerun", tvguideConfig.useSubtitleRerun);
+    SetupStore("numLogosInitial", tvguideConfig.numLogosInitial);
+    SetupStore("numLogosMax", tvguideConfig.numLogosMax);
+    SetupStore("limitLogoCache", tvguideConfig.limitLogoCache);
 }
 
 cMenuSetupSubMenu::cMenuSetupSubMenu(const char* Title, cTvguideConfig* data) : cOsdMenu(Title, 30) {
-	tmpTvguideConfig = data;
+    tmpTvguideConfig = data;
+    indent = "    ";
 }
 
 cOsdItem *cMenuSetupSubMenu::InfoItem(const char *label, const char *value) {
@@ -103,110 +178,302 @@ eOSState cMenuSetupSubMenu::ProcessKey(eKeys Key) {
   return state;
 }
 
-//------------------------------------------------------------------------------------------------------------------
+//----- General Settings -------------------------------------------------------------------------------------------------------------
 
 cMenuSetupGeneral::cMenuSetupGeneral(cTvguideConfig* data)  : cMenuSetupSubMenu(tr("General Settings"), data) {
-	timeFormatItems[0] = "12h";
-	timeFormatItems[1] = "24h";
-
-	Set();
+    themes.Load(*cString("tvguide"));
+    timeFormatItems[0] = "12h";
+    timeFormatItems[1] = "24h";
+    jumpMode[0] = tr("x channels back / forward");
+    jumpMode[1] = tr("previous / next channel group");
+    blueMode[0] = tr("Blue: Channel Switch, Ok: Detailed EPG");
+    blueMode[1] = tr("Blue: Detailed EPG, Ok: Channel Switch");
+    blueMode[2] = tr("Blue: Favorites / Switch, Ok: Detailed EPG");
+    numMode[0] = tr("Timely Jump");
+    numMode[1] = tr("Jump to specific channel");
+    useSubtitleRerunTexts[0] = tr("never");
+    useSubtitleRerunTexts[1] = tr("if exists");
+    useSubtitleRerunTexts[2] = tr("always");
+    Set();
 }
 
 void cMenuSetupGeneral::Set(void) {
-	int currentItem = Current();
-	Clear();
-	
-	Add(new cMenuEditIntItem(tr("Number of Channels / Columns"), &tmpTvguideConfig->channelCols, 3, 8));
-	Add(new cMenuEditIntItem(tr("Channels to Jump (Keys Green / Yellow)"), &tmpTvguideConfig->jumpChannels, 2, 30));
-	Add(new cMenuEditIntItem(tr("Time to display vertically in minutes"), &tmpTvguideConfig->displayTime, 120, 320));
-	Add(new cMenuEditIntItem(tr("Big Step (Keys 1 / 3) in hours"), &tmpTvguideConfig->bigStepHours, 1, 12));
-	Add(new cMenuEditIntItem(tr("Huge Step (Keys 4 / 6) in hours"), &tmpTvguideConfig->hugeStepHours, 13, 48));
-	Add(new cMenuEditStraItem(tr("Time Format (12h/24h)"), &tmpTvguideConfig->timeFormat, 2,  timeFormatItems));
+    int currentItem = Current();
+    Clear();
+    Add(new cMenuEditBoolItem(tr("Show Main Menu Entry"), &tmpTvguideConfig->showMainMenuEntry));
+    Add(new cMenuEditBoolItem(tr("Replace VDR Schedules Menu"), &tmpTvguideConfig->replaceOriginalSchedule));
+    Add(new cMenuEditBoolItem(tr("Use appropriate nOpacity Theme"), &tmpTvguideConfig->useNopacityTheme));
+    if (!tmpTvguideConfig->useNopacityTheme) {
+        if (themes.NumThemes())
+            Add(new cMenuEditStraItem(cString::sprintf("%s%s", *indent, tr("Theme")), &tmpTvguideConfig->themeIndex, themes.NumThemes(), themes.Descriptions()));
+    }
+    Add(new cMenuEditIntItem(tr("Time to display in minutes"), &tmpTvguideConfig->displayTime, 60, 320));
+    Add(new cMenuEditBoolItem(tr("Rounded Corners"), &tmpTvguideConfig->roundedCorners));
+    
+    Add(new cMenuEditStraItem(tr("Channel Jump Mode (Keys Green / Yellow)"), &tmpTvguideConfig->channelJumpMode, 2,  jumpMode));
+    Add(new cMenuEditStraItem(tr("Keys Blue and OK"), &tmpTvguideConfig->blueKeyMode, 3,  blueMode));
+    Add(new cMenuEditBoolItem(tr("Close TVGuide after channel switch"), &tmpTvguideConfig->closeOnSwitch));
+    Add(new cMenuEditStraItem(tr("Functionality of numeric Keys"), &tmpTvguideConfig->numkeyMode, 2,  numMode));
+    Add(new cMenuEditBoolItem(tr("Hide last Channel Group"), &tmpTvguideConfig->hideLastGroup));
+    Add(new cMenuEditIntItem(tr("Big Step (Keys 1 / 3) in hours"), &tmpTvguideConfig->bigStepHours, 1, 12));
+    Add(new cMenuEditIntItem(tr("Huge Step (Keys 4 / 6) in hours"), &tmpTvguideConfig->hugeStepHours, 13, 48));
+    Add(new cMenuEditStraItem(tr("Time Format (12h/24h)"), &tmpTvguideConfig->timeFormat, 2,  timeFormatItems));
+    Add(new cMenuEditIntItem(tr("EPG Window Text Scrolling Speed"), &tmpTvguideConfig->detailedViewScrollStep, 1, 30));
+    Add(new cMenuEditBoolItem(tr("Display Reruns in detailed EPG View"), &tmpTvguideConfig->displayRerunsDetailEPGView));
+    if (tmpTvguideConfig->displayRerunsDetailEPGView) {
+        Add(new cMenuEditIntItem(cString::sprintf("%s%s", *indent, tr("Number of reruns to display")), &tmpTvguideConfig->numReruns, 1, 10));
+        Add(new cMenuEditStraItem(cString::sprintf("%s%s", *indent, tr("Use Subtitle for reruns")), &tmpTvguideConfig->useSubtitleRerun, 3, useSubtitleRerunTexts));
+    }
+    SetCurrent(Get(currentItem));
+    Display();
+}
 
-	SetCurrent(Get(currentItem));
-	Display();
+eOSState cMenuSetupGeneral::ProcessKey(eKeys Key) {
+    eOSState state = cOsdMenu::ProcessKey(Key);
+    if (Key == kOk) {
+        state = osBack;
+    } else if (Key != kNone) {
+        Set();
+    }
+    return state;
 }
 
-//------------------------------------------------------------------------------------------------------------------
+//----- Screen Presentation -------------------------------------------------------------------------------------------------------------
 
 cMenuSetupScreenLayout::cMenuSetupScreenLayout(cTvguideConfig* data)  : cMenuSetupSubMenu(tr("Screen Presentation"), data) {
-	themes.Load(*cString("tvguide"));
-	hideChannelLogosItems[0] = trVDR("yes");
-	hideChannelLogosItems[1] = trVDR("no");
-	logoExtensionItems[0] = "png";
-	logoExtensionItems[1] = "jpg";
-    blendingMethods[0] = "none";
-    blendingMethods[1] = "classic";
-    blendingMethods[2] = "nOpacity style";
-	Set();
+    displayModeItems[0] = "vertical";
+    displayModeItems[1] = "horizontal";
+    hideChannelLogosItems[0] = trVDR("yes");
+    hideChannelLogosItems[1] = trVDR("no");
+    logoExtensionItems[0] = "png";
+    logoExtensionItems[1] = "jpg";
+    Set();
 }
 
 void cMenuSetupScreenLayout::Set(void) {
-	int currentItem = Current();
-	Clear();
-	if (themes.NumThemes())
-		Add(new cMenuEditStraItem(tr("Theme"), &tmpTvguideConfig->themeIndex, themes.NumThemes(), themes.Descriptions()));
-	Add(new cMenuEditStraItem(tr("Use color gradients"), &tmpTvguideConfig->useBlending, 3, blendingMethods));
-	Add(new cMenuEditBoolItem(tr("Rounded Corners"), &tmpTvguideConfig->roundedCorners));
-	Add(new cMenuEditIntItem(tr("Width of Timeline"), &tmpTvguideConfig->timeColWidth, 50, 300));
-	Add(new cMenuEditIntItem(tr("Height of Header"), &tmpTvguideConfig->headerHeight, 50, 300));
-	Add(new cMenuEditIntItem(tr("Height of Footer"), &tmpTvguideConfig->footerHeight, 50, 300));
-	
-	const char *indent = "    ";
-	Add(new cMenuEditStraItem(tr("Show Channel Logos"), &tmpTvguideConfig->hideChannelLogos, 2,  hideChannelLogosItems));	
-	if (!tmpTvguideConfig->hideChannelLogos) {
-		Add(InfoItem(tr("Logo Path used"), *tvguideConfig.logoPath));
-		Add(new cMenuEditStraItem(*cString::sprintf("%s%s", indent, tr("Logo Extension")), &tmpTvguideConfig->logoExtension, 2,  logoExtensionItems));
-		Add(new cMenuEditIntItem(*cString::sprintf("%s%s", indent, tr("Logo width")), &tmpTvguideConfig->logoWidth, 0, 350));
-		Add(new cMenuEditIntItem(*cString::sprintf("%s%s", indent, tr("Logo height")), &tmpTvguideConfig->logoHeight, 0, 250));
-	}
-	
-	Add(new cMenuEditStraItem(tr("Show EPG Images"), &tmpTvguideConfig->hideEpgImages, 2,  hideChannelLogosItems));	
-	if (!tmpTvguideConfig->hideEpgImages) {
-		Add(InfoItem(tr("EPG Images Path used"), *tvguideConfig.epgImagePath));
-		Add(new cMenuEditIntItem(*cString::sprintf("%s%s", indent, tr("EPG Image width")), &tmpTvguideConfig->epgImageWidth, 0, 800));
-		Add(new cMenuEditIntItem(*cString::sprintf("%s%s", indent, tr("EPG Image height")), &tmpTvguideConfig->epgImageHeight, 0, 800));
-	}
-	
-	SetCurrent(Get(currentItem));
-	Display();
+    int currentItem = Current();
+    Clear();
+    
+    Add(new cMenuEditStraItem(tr("Display Mode"), &tmpTvguideConfig->displayMode, 2,  displayModeItems));
+    if (tmpTvguideConfig->displayMode == eVertical) {
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Height of Channel Header (Perc. of osd height)")), &tmpTvguideConfig->channelHeaderHeightPercent, 5, 30));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Width of Timeline (Perc. of osd width)")), &tmpTvguideConfig->timeLineWidthPercent, 5, 30));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Number of Channels to display")), &tmpTvguideConfig->channelCols, 3, 12));
+    } else if (tmpTvguideConfig->displayMode == eHorizontal) {
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Width of Channel Header (Perc. of osd width)")), &tmpTvguideConfig->channelHeaderWidthPercent, 5, 30));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Height of Timeline (Perc. of osd height)")), &tmpTvguideConfig->timeLineHeightPercent, 5, 30));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Number of Channels to display")), &tmpTvguideConfig->channelRows, 3, 12));
+        Add(new cMenuEditBoolItem(*cString::sprintf("%s%s", *indent, tr("Display time in EPG Grids")), &tmpTvguideConfig->showTimeInGrid));
+    }
+    Add(new cMenuEditIntItem(tr("Height of Headers (Status Header and EPG View, Perc. of osd height)"), &tmpTvguideConfig->headerHeightPercent, 10, 50));
+    Add(new cMenuEditIntItem(tr("Height of Footer (Perc. of osd height)"), &tmpTvguideConfig->footerHeightPercent, 3, 20));
+    
+    Add(new cMenuEditBoolItem(tr("Display status header"), &tmpTvguideConfig->displayStatusHeader));
+    if (tmpTvguideConfig->displayStatusHeader) {
+        Add(new cMenuEditBoolItem(*cString::sprintf("%s%s", *indent, tr("Scale video to upper right corner")), &tmpTvguideConfig->scaleVideo));
+        Add(new cMenuEditBoolItem(*cString::sprintf("%s%s", *indent, tr("Rounded corners around video frame")), &tmpTvguideConfig->decorateVideo));
+    }
+    
+    Add(new cMenuEditBoolItem(tr("Display Channel Names in Header"), &tmpTvguideConfig->displayChannelName));
+    Add(new cMenuEditBoolItem(tr("Display channel groups"), &tmpTvguideConfig->displayChannelGroups));
+    if (tmpTvguideConfig->displayChannelGroups) {
+        if (tmpTvguideConfig->displayMode == eVertical) {
+            Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Height of channel groups (Perc. of osd height)")), &tmpTvguideConfig->channelGroupsPercent, 3, 30));
+        } else if (tmpTvguideConfig->displayMode == eHorizontal) {
+            Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Width of channel groups (Perc. of osd width)")), &tmpTvguideConfig->channelGroupsPercent, 3, 30));
+        }
+    }
+    
+    Add(new cMenuEditBoolItem(tr("Display current time baseline"), &tmpTvguideConfig->displayTimeBase));
+    Add(new cMenuEditStraItem(tr("Show Channel Logos"), &tmpTvguideConfig->hideChannelLogos, 2,  hideChannelLogosItems));   
+    if (!tmpTvguideConfig->hideChannelLogos) {
+        Add(InfoItem(tr("Logo Path used"), *tvguideConfig.logoPath));
+        Add(new cMenuEditStraItem(*cString::sprintf("%s%s", *indent, tr("Logo Extension")), &tmpTvguideConfig->logoExtension, 2,  logoExtensionItems));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Logo width ratio")), &tmpTvguideConfig->logoWidthRatio, 1, 1000));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Logo height ratio")), &tmpTvguideConfig->logoHeightRatio, 1, 1000));
+    }
+    
+    Add(new cMenuEditIntItem(tr("Text Border in Detailed View (pixel)"), &tmpTvguideConfig->epgViewBorder, 0, 300));
+    
+    Add(new cMenuEditStraItem(tr("Show EPG Images"), &tmpTvguideConfig->hideEpgImages, 2,  hideChannelLogosItems)); 
+    if (!tmpTvguideConfig->hideEpgImages) {
+        Add(InfoItem(tr("EPG Images Path used"), *tvguideConfig.epgImagePath));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("EPG Image width")), &tmpTvguideConfig->epgImageWidth, 0, 800));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("EPG Image height")), &tmpTvguideConfig->epgImageHeight, 0, 800));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Number of additional EPG Images")), &tmpTvguideConfig->numAdditionalEPGPictures, 0, 20));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Additional EPG Image width")), &tmpTvguideConfig->epgImageWidthLarge, 1, 800));
+        Add(new cMenuEditIntItem(*cString::sprintf("%s%s", *indent, tr("Additional EPG Image height")), &tmpTvguideConfig->epgImageHeightLarge, 0, 800));
+    }
+    
+    SetCurrent(Get(currentItem));
+    Display();
 }
 
 eOSState cMenuSetupScreenLayout::ProcessKey(eKeys Key) {
-	eOSState state = cOsdMenu::ProcessKey(Key);
-	if (Key == kOk) {
-		state = osBack;
-	} else if (Key != kNone) {
-		Set();
-	}
-	return state;
+    eOSState state = cOsdMenu::ProcessKey(Key);
+    if (Key == kOk) {
+        state = osBack;
+    } else if (Key != kNone) {
+        Set();
+    }
+    return state;
 }
 
-//------------------------------------------------------------------------------------------------------------------
+//-----Fonts and Fontsizes -------------------------------------------------------------------------------------------------------
 
 cMenuSetupFont::cMenuSetupFont(cTvguideConfig* data)  : cMenuSetupSubMenu(tr("Fonts and Fontsizes"), data) {
-	cFont::GetAvailableFontNames(&fontNames);
-	fontNames.Insert(strdup(tvguideConfig.fontNameDefault));
-	Set();
+    cFont::GetAvailableFontNames(&fontNames);
+    fontNames.Insert(strdup(tvguideConfig.fontNameDefault));
+    Set();
 }
 
 void cMenuSetupFont::Set(void) {
-	int currentItem = Current();
-	Clear();
-	
-	Add(new cMenuEditStraItem(tr("Font"), &tmpTvguideConfig->fontIndex, fontNames.Size(), &fontNames[0]));
-	Add(new cMenuEditIntItem(tr("Channel Header Font Size"), &tmpTvguideConfig->fontHeaderSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Grid Font Size"), &tmpTvguideConfig->fontGridSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Grid Font Small Size"), &tmpTvguideConfig->fontGridSmallSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Timeline Weekday Font Size"), &tmpTvguideConfig->fontTimeLineWeekdaySize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Timeline Date Font Size"), &tmpTvguideConfig->fontTimeLineDateSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Timeline Time Font Size"), &tmpTvguideConfig->fontTimeLineTimeSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Button Font Size"), &tmpTvguideConfig->fontButtonSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Detail EPG View Font Size"), &tmpTvguideConfig->fontDetailViewSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Detail EPG View Header Font Size"), &tmpTvguideConfig->fontDetailHeaderSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Message Font Size"), &tmpTvguideConfig->fontMessageBoxSize, 10, 70));
-	Add(new cMenuEditIntItem(tr("Message Large Font Size"), &tmpTvguideConfig->fontMessageBoxLargeSize, 10, 70));
-	
-	SetCurrent(Get(currentItem));
-	Display();
-}
\ No newline at end of file
+    int currentItem = Current();
+    Clear();
+
+    Add(new cMenuEditStraItem(tr("Font"), &tmpTvguideConfig->fontIndex, fontNames.Size(), &fontNames[0]));
+    
+    Add(new cMenuEditIntItem(tr("Status Header Font Size"), &tmpTvguideConfig->FontStatusHeaderDelta, -30, 30));    
+    Add(new cMenuEditIntItem(tr("Status Header Large Font Size"), &tmpTvguideConfig->FontStatusHeaderLargeDelta, -30, 30));
+    Add(new cMenuEditIntItem(tr("Detail EPG View Font Size"), &tmpTvguideConfig->FontDetailViewDelta, -30, 30));
+    Add(new cMenuEditIntItem(tr("Detail EPG View Header Font Size"), &tmpTvguideConfig->FontDetailHeaderDelta, -30, 30));
+    Add(new cMenuEditIntItem(tr("Message Font Size"), &tmpTvguideConfig->FontMessageBoxDelta, -30, 30));
+    Add(new cMenuEditIntItem(tr("Message Large Font Size"), &tmpTvguideConfig->FontMessageBoxLargeDelta, -30, 30));
+    Add(new cMenuEditIntItem(tr("Button Font Size"), &tmpTvguideConfig->FontButtonDelta, -30, 30));
+
+
+    if (tmpTvguideConfig->displayMode == eVertical) {
+        Add(new cMenuEditIntItem(tr("Channel Header Font Size"), &tmpTvguideConfig->FontChannelHeaderDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Channel Groups Font Size"), &tmpTvguideConfig->FontChannelGroupsDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Grid Font Size"), &tmpTvguideConfig->FontGridDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Grid Font Small Size"), &tmpTvguideConfig->FontGridSmallDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Timeline Weekday Font Size"), &tmpTvguideConfig->FontTimeLineWeekdayDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Timeline Date Font Size"), &tmpTvguideConfig->FontTimeLineDateDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Timeline Time Font Size"), &tmpTvguideConfig->FontTimeLineTimeDelta, -30, 30));
+    } else if (tmpTvguideConfig->displayMode == eHorizontal) {
+        Add(new cMenuEditIntItem(tr("Channel Header Font Size"), &tmpTvguideConfig->FontChannelHeaderHorizontalDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Channel Groups Font Size"), &tmpTvguideConfig->FontChannelGroupsHorizontalDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Grid Font Size"), &tmpTvguideConfig->FontGridHorizontalDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Grid Font Small Size"), &tmpTvguideConfig->FontGridHorizontalSmallDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Timeline Date Font Size"), &tmpTvguideConfig->FontTimeLineDateHorizontalDelta, -30, 30));
+        Add(new cMenuEditIntItem(tr("Timeline Time Font Size"), &tmpTvguideConfig->FontTimeLineTimeHorizontalDelta, -30, 30));
+    }
+    
+    Add(new cMenuEditIntItem(tr("Search & Recording Menu Font Size"), &tmpTvguideConfig->FontRecMenuItemDelta, -30, 30));
+    Add(new cMenuEditIntItem(tr("Search & Recording Menu Small Font Size"), &tmpTvguideConfig->FontRecMenuItemSmallDelta, -30, 30));
+    Add(new cMenuEditIntItem(tr("Search & Recording Menu Header Font Size"), &tmpTvguideConfig->FontRecMenuItemLargeDelta, -30, 30));
+
+    SetCurrent(Get(currentItem));
+    Display();
+}
+
+//----- Recording Menus and Favorites -------------------------------------------------------------------------------------------------------
+
+cMenuSetupFavorites::cMenuSetupFavorites(cTvguideConfig* data)  : cMenuSetupSubMenu(tr("Recording Menus and Favorites"), data) {
+    strn0cpy(description1, data->descUser1.c_str(), sizeof(description1));
+    strn0cpy(description2, data->descUser2.c_str(), sizeof(description2));
+    strn0cpy(description3, data->descUser3.c_str(), sizeof(description3));
+    strn0cpy(description4, data->descUser4.c_str(), sizeof(description4));
+    recFolderMode[0] = tr("Always use root video folder");
+    recFolderMode[1] = tr("Select from folder list");
+    recFolderMode[2] = tr("Use fixed folder");
+    strn0cpy(fixedFolder, data->instRecFixedFolder.c_str(), sizeof(fixedFolder));
+    Set();
+}
+
+void cMenuSetupFavorites::Set(void) {
+    int currentItem = Current();
+    Clear();
+
+    Add(new cMenuEditStraItem(tr("Folder for instant Recordings"), &tmpTvguideConfig->instRecFolderMode, 3,  recFolderMode));
+    if (tmpTvguideConfig->instRecFolderMode == eFolderFixed) {
+        Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Folder")), fixedFolder, sizeof(fixedFolder), trVDR(FileNameChars)));
+    }
+    if (pRemoteTimers)
+        Add(new cMenuEditBoolItem(tr("Use Remotetimers"), &tmpTvguideConfig->useRemoteTimers));
+
+    Add(new cMenuEditBoolItem(tr("Use \"What's on now\" in favorites"), &tmpTvguideConfig->favWhatsOnNow));
+    Add(new cMenuEditBoolItem(tr("Use \"What's on next\" in favorites"), &tmpTvguideConfig->favWhatsOnNext));
+    Add(new cMenuEditBoolItem(tr("Use user defined time 1 in favorites"), &tmpTvguideConfig->favUseTime1));
+    if (tmpTvguideConfig->favUseTime1) {
+        Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Description")), description1, sizeof(description1), trVDR(FileNameChars)));
+        Add(new cMenuEditTimeItem(cString::sprintf("%s%s", *indent, tr("Time")), &tmpTvguideConfig->favTime1));
+    }
+    Add(new cMenuEditBoolItem(tr("Use user defined time 2 in favorites"), &tmpTvguideConfig->favUseTime2));
+    if (tmpTvguideConfig->favUseTime2) {
+        Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Description")), description2, sizeof(description2), trVDR(FileNameChars)));
+        Add(new cMenuEditTimeItem(cString::sprintf("%s%s", *indent, tr("Time")), &tmpTvguideConfig->favTime2));
+    }
+    Add(new cMenuEditBoolItem(tr("Use user defined time 3 in favorites"), &tmpTvguideConfig->favUseTime3));
+    if (tmpTvguideConfig->favUseTime3) {
+        Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Description")), description3, sizeof(description3), trVDR(FileNameChars)));
+        Add(new cMenuEditTimeItem(cString::sprintf("%s%s", *indent, tr("Time")), &tmpTvguideConfig->favTime3));
+    }
+    Add(new cMenuEditBoolItem(tr("Use user defined time 4 in favorites"), &tmpTvguideConfig->favUseTime4));
+    if (tmpTvguideConfig->favUseTime4) {
+        Add(new cMenuEditStrItem(cString::sprintf("%s%s", *indent, tr("Description")), description4, sizeof(description4), trVDR(FileNameChars)));
+        Add(new cMenuEditTimeItem(cString::sprintf("%s%s", *indent, tr("Time")), &tmpTvguideConfig->favTime4));
+    }
+    Add(new cMenuEditBoolItem(tr("Limit channels in favorites"), &tmpTvguideConfig->favLimitChannels));
+    if (tmpTvguideConfig->favLimitChannels) {
+        Add(new cMenuEditChanItem(tr("Start Channel"), &tmpTvguideConfig->favStartChannel));
+        Add(new cMenuEditChanItem(tr("Stop Channel"), &tmpTvguideConfig->favStopChannel));
+    }
+
+
+    SetCurrent(Get(currentItem));
+    Display();
+}
+
+eOSState cMenuSetupFavorites::ProcessKey(eKeys Key) {
+    int tmpFavUseTime1 = tmpTvguideConfig->favUseTime1;
+    int tmpFavUseTime2 = tmpTvguideConfig->favUseTime2;
+    int tmpFavUseTime3 = tmpTvguideConfig->favUseTime3;
+    int tmpFavUseTime4 = tmpTvguideConfig->favUseTime4;
+    int tmpFavLimitChannels = tmpTvguideConfig->favLimitChannels;
+    int tmpFolderMode = tmpTvguideConfig->instRecFolderMode;
+    eOSState state = cOsdMenu::ProcessKey(Key);
+    if (Key == kOk) {
+        tmpTvguideConfig->descUser1 = description1;
+        tmpTvguideConfig->descUser2 = description2;
+        tmpTvguideConfig->descUser3 = description3;
+        tmpTvguideConfig->descUser4 = description4;
+        tmpTvguideConfig->instRecFixedFolder = fixedFolder;
+    } else if ((Key == kLeft)||(Key == kRight)) {
+        if ((tmpFavUseTime1 != tmpTvguideConfig->favUseTime1) ||
+            (tmpFavUseTime2 != tmpTvguideConfig->favUseTime2) ||
+            (tmpFavUseTime3 != tmpTvguideConfig->favUseTime3) ||
+            (tmpFavUseTime4 != tmpTvguideConfig->favUseTime4) ||
+            (tmpFavLimitChannels != tmpTvguideConfig->favLimitChannels) ||
+            (tmpFolderMode != tmpTvguideConfig->instRecFolderMode) )
+            Set();
+    }
+    return state;
+}
+
+
+//-----Image Caching-------------------------------------------------------------------------------------------------------------
+cMenuSetupImageCache::cMenuSetupImageCache(cTvguideConfig* data)  : cMenuSetupSubMenu(tr("Image Loading and Caching"), data) {
+    Set();
+}
+
+void cMenuSetupImageCache::Set(void) {
+    int currentItem = Current();
+    Clear();
+    Add(new cMenuEditBoolItem(tr("Create Log Messages for image loading"), &tmpTvguideConfig->debugImageLoading));
+    Add(new cMenuEditBoolItem(tr("Limit Logo Cache"), &tmpTvguideConfig->limitLogoCache));
+    if (&tmpTvguideConfig->limitLogoCache) {
+        Add(new cMenuEditIntItem(cString::sprintf("%s%s", *indent, tr("Maximal number of logos to cache")), &tmpTvguideConfig->numLogosMax, 1, 9999));
+    }
+    Add(new cMenuEditIntItem(tr("Number of  logos to cache at start"), &tmpTvguideConfig->numLogosInitial, 0, 9999));
+
+    Add(InfoItem(tr("Cache Sizes"), ""));
+    Add(InfoItem(tr("OSD Element Cache"), (imgCache.GetCacheSize(ctOsdElement)).c_str()));
+    Add(InfoItem(tr("Logo cache"), (imgCache.GetCacheSize(ctLogo)).c_str()));
+    Add(InfoItem(tr("EPG Grid Cache"), (imgCache.GetCacheSize(ctGrid)).c_str()));
+    Add(InfoItem(tr("Channel Groups Cache"), (imgCache.GetCacheSize(ctChannelGroup)).c_str()));
+    Add(InfoItem(tr("Recording Menus Icon Cache"), (imgCache.GetCacheSize(ctIcon)).c_str()));
+
+    SetCurrent(Get(currentItem));
+    Display();
+}
diff --git a/setup.h b/setup.h
index ba81d8f..f7f8b2c 100644
--- a/setup.h
+++ b/setup.h
@@ -1,55 +1,85 @@
 #ifndef __TVGUIDE_SETUP_H
 #define __TVGUIDE_SETUP_H
 
+#include <vdr/menuitems.h>
+#include "config.h"
+
 class cTvguideSetup : public cMenuSetupPage {
-	public:
-		cTvguideSetup(void);
-		virtual ~cTvguideSetup();		
-	private:
-		cTvguideConfig tmpTvguideConfig;
-		void Setup(void);
-	protected:
-		virtual eOSState ProcessKey(eKeys Key);
-		virtual void Store(void);
+    public:
+        cTvguideSetup(void);
+        virtual ~cTvguideSetup();       
+    private:
+        cTvguideConfig tmpTvguideConfig;
+        void Setup(void);
+    protected:
+        virtual eOSState ProcessKey(eKeys Key);
+        virtual void Store(void);
 
 };
 
 class cMenuSetupSubMenu : public cOsdMenu {
-	protected:
-		cTvguideConfig *tmpTvguideConfig;
-		virtual eOSState ProcessKey(eKeys Key);
-		virtual void Set(void) = 0;
-		cOsdItem *InfoItem(const char *label, const char *value);
-	public:
-		cMenuSetupSubMenu(const char *Title, cTvguideConfig *data);
+    protected:
+        cTvguideConfig *tmpTvguideConfig;
+        virtual eOSState ProcessKey(eKeys Key);
+        virtual void Set(void) = 0;
+        cOsdItem *InfoItem(const char *label, const char *value);
+        cString indent;
+    public:
+        cMenuSetupSubMenu(const char *Title, cTvguideConfig *data);
 };
 
 class cMenuSetupGeneral : public cMenuSetupSubMenu {
-	protected:
-		const char * timeFormatItems[2];
-		void Set(void);
-	public:
-		cMenuSetupGeneral(cTvguideConfig *data);
+    protected:
+        virtual eOSState ProcessKey(eKeys Key);
+        cThemes themes;
+        const char * timeFormatItems[2];
+        const char * jumpMode[2];
+        const char * blueMode[3];
+        const char * numMode[2];
+        const char *useSubtitleRerunTexts[3];
+        void Set(void);
+    public:
+        cMenuSetupGeneral(cTvguideConfig *data);
 };
 
 class cMenuSetupScreenLayout : public cMenuSetupSubMenu {
-	protected:
-		virtual eOSState ProcessKey(eKeys Key);
-		cThemes themes;
-		const char * hideChannelLogosItems[2];
-		const char * logoExtensionItems[2];
-        const char * blendingMethods[3];
-		void Set(void);
-	public:
-		cMenuSetupScreenLayout(cTvguideConfig *data);
+    protected:
+        virtual eOSState ProcessKey(eKeys Key);
+        const char * displayModeItems[2];
+        const char * hideChannelLogosItems[2];
+        const char * logoExtensionItems[2];
+        void Set(void);
+    public:
+        cMenuSetupScreenLayout(cTvguideConfig *data);
 };
 
 class cMenuSetupFont : public cMenuSetupSubMenu {
-	protected:
-		cStringList fontNames;
-		void Set(void);
-	public:
-		cMenuSetupFont(cTvguideConfig *data);
+    protected:
+        cStringList fontNames;
+        void Set(void);
+    public:
+        cMenuSetupFont(cTvguideConfig *data);
+};
+
+class cMenuSetupFavorites : public cMenuSetupSubMenu {
+    protected:
+        char description1[256];
+        char description2[256];
+        char description3[256];
+        char description4[256];
+        const char * recFolderMode[3];
+        char fixedFolder[256];
+        void Set(void);
+        virtual eOSState ProcessKey(eKeys Key);
+    public:
+        cMenuSetupFavorites(cTvguideConfig *data);
+};
+
+class cMenuSetupImageCache : public cMenuSetupSubMenu {
+    protected:
+        void Set(void);
+    public:
+        cMenuSetupImageCache(cTvguideConfig *data);
 };
 
 #endif //__TVGUIDE_SETUP_H
\ No newline at end of file
diff --git a/statusheader.c b/statusheader.c
new file mode 100644
index 0000000..cac916e
--- /dev/null
+++ b/statusheader.c
@@ -0,0 +1,142 @@
+#include "tools.h"
+#include "services/scraper2vdr.h"
+#include "imageloader.h"
+#include "statusheader.h"
+
+cStatusHeader::cStatusHeader(void) {
+    color = theme.Color(clrStatusHeader);
+    colorBlending = theme.Color(clrStatusHeaderBlending);
+    height = geoManager.statusHeaderHeight;
+    width = geoManager.headerContentWidth;
+    tvFrameWidth = geoManager.tvFrameWidth;
+    pixmap = osdManager.requestPixmap(1, cRect(0, 0, width, height));
+    pixmapText = osdManager.requestPixmap(2, cRect(0, 0, width, height));
+    pixmapTVFrame = osdManager.requestPixmap(1, cRect(width, 0, tvFrameWidth, height));
+}
+
+cStatusHeader::~cStatusHeader(void) {
+    osdManager.releasePixmap(pixmapText);
+    osdManager.releasePixmap(pixmapTVFrame);
+    if (tvguideConfig.scaleVideo) {
+        cRect vidWin = cDevice::PrimaryDevice()->CanScaleVideo(cRect::Null);
+        cDevice::PrimaryDevice()->ScaleVideo(vidWin);
+    }
+}
+
+void cStatusHeader::Draw(void) {
+    pixmapText->Fill(clrTransparent);
+    pixmapTVFrame->Fill(clrTransparent);
+    if (tvguideConfig.style == eStyleGraphical) {
+        if (tvguideConfig.scaleVideo) {
+            drawBackgroundGraphical(bgStatusHeaderWindowed);
+            cImage *tvFrameBack = imgCache.GetOsdElement(oeStatusHeaderTVFrame);
+            if (tvFrameBack)
+                pixmapTVFrame->DrawImage(cPoint(0,0), *tvFrameBack);
+        } else {
+            drawBackgroundGraphical(bgStatusHeaderFull);
+        }
+    } else {
+        if (tvguideConfig.decorateVideo) {
+            DecorateVideoFrame();
+        }
+        drawBackground();
+        drawBorder();
+    }
+}
+
+void cStatusHeader::ScaleVideo(void) {
+    if (tvguideConfig.scaleVideo) {
+        int width = height * 16 / 9;
+        int x = osdManager.Left() + geoManager.osdWidth - width;
+        int y = osdManager.Top();
+        cRect availableRect(x, y, width, height);
+        cRect vidWin = cDevice::PrimaryDevice()->CanScaleVideo(availableRect);
+        cDevice::PrimaryDevice()->ScaleVideo(vidWin);
+    }
+}
+
+void cStatusHeader::DrawInfoText(cGrid *grid) {
+    int border = 10;
+    int textWidth = width - 2 * border - geoManager.clockWidth - 2;
+    tColor colorTextBack = (tvguideConfig.style == eStyleFlat)?color:clrTransparent;
+    pixmapText->Fill(clrTransparent);
+    int x = border;
+    int y = border;
+    if (!grid->isDummy()) {
+        const cEvent *event = grid->GetEvent();
+        int newX = DrawPoster(event, x, y, height-2*border, border);
+        if (newX > 0) {
+            textWidth -= (newX - x);
+            x += newX;
+        }
+        cString time = grid->getTimeString();
+        cString title("");
+        title = cString::sprintf(": %s", event->Title());
+        cString header = cString::sprintf("%s%s", *time, *title);
+        header = CutText(*header, textWidth, fontManager.FontStatusHeaderLarge).c_str();
+        pixmapText->DrawText(cPoint(x,y), *header, theme.Color(clrFont), colorTextBack, fontManager.FontStatusHeaderLarge);
+        y += fontManager.FontStatusHeaderLarge->Height() + border;
+        int heightText = pixmapText->ViewPort().Height() - y;
+        cTextWrapper description;
+        description.Set(event->Description(), fontManager.FontStatusHeader, textWidth);
+        int lineHeight = fontManager.FontStatusHeader->Height();
+        int textLines = description.Lines();
+        int maxLines = heightText / lineHeight;
+        int lines = min(textLines, maxLines);
+        for (int i = 0; i < lines-1; i++) {
+            pixmapText->DrawText(cPoint(x,y), description.GetLine(i), theme.Color(clrFont), colorTextBack, fontManager.FontStatusHeader);
+            y += lineHeight;
+        }
+        cString lastLine = description.GetLine(lines-1);
+        if (textLines > maxLines) {
+            lastLine = cString::sprintf("%s...", *lastLine);
+        }
+        pixmapText->DrawText(cPoint(x,y), *lastLine, theme.Color(clrFont), colorTextBack, fontManager.FontStatusHeader);
+    } else {
+        int heightText = pixmapText->ViewPort().Height() - y;
+        y += (heightText - fontManager.FontStatusHeaderLarge->Height() - 2*border)/2;
+        pixmapText->DrawText(cPoint(x,y), *grid->getText(), theme.Color(clrFont), colorTextBack, fontManager.FontStatusHeaderLarge);
+    }
+}
+
+int cStatusHeader::DrawPoster(const cEvent *event, int x, int y, int height, int border) {
+    bool hasPoster = false;
+    ScraperGetPoster posterScraper2Vdr;
+    int posterWidth = 0;
+    int posterHeight = 0;
+    static cPlugin *pScraper2Vdr = cPluginManager::GetPlugin("scraper2vdr");
+    if (pScraper2Vdr) {
+        posterScraper2Vdr.event = event;
+        posterScraper2Vdr.recording = NULL;
+        if (pScraper2Vdr->Service("GetPoster", &posterScraper2Vdr)) {
+            hasPoster = true;
+            int posterWidthOrig = posterScraper2Vdr.poster.width;
+            int posterHeightOrig = posterScraper2Vdr.poster.height;
+            posterHeight = height;
+            posterWidth = posterWidthOrig * ((double)posterHeight / (double)posterHeightOrig);
+        } else {
+            hasPoster = false;
+        }
+    }
+    if (hasPoster) {
+        cImageLoader imgLoader;
+        if (imgLoader.LoadPoster(posterScraper2Vdr.poster.path.c_str(), posterWidth, posterHeight)) {
+            pixmapText->DrawImage(cPoint(x, y), imgLoader.GetImage());
+            return posterWidth + border;
+        }
+    }
+    return 0;
+}
+
+void cStatusHeader::DecorateVideoFrame(void) {
+    int radius = 16;
+    int frame = 2;
+    pixmapTVFrame->DrawRectangle(cRect(0, 0, tvFrameWidth, frame), theme.Color(clrBackgroundOSD));
+    pixmapTVFrame->DrawEllipse(cRect(frame,frame,radius,radius), theme.Color(clrBackgroundOSD), -2);
+    pixmapTVFrame->DrawRectangle(cRect(tvFrameWidth - frame, frame, frame, height - 2*frame), theme.Color(clrBackgroundOSD));      
+    pixmapTVFrame->DrawEllipse(cRect(tvFrameWidth - radius - frame, frame, radius, radius), theme.Color(clrBackgroundOSD), -1);
+    pixmapTVFrame->DrawRectangle(cRect(0, frame, frame, height - 2*frame), theme.Color(clrBackgroundOSD)); 
+    pixmapTVFrame->DrawEllipse(cRect(frame, height - radius - frame, radius, radius), theme.Color(clrBackgroundOSD), -3);
+    pixmapTVFrame->DrawRectangle(cRect(0, height - frame, tvFrameWidth, frame), theme.Color(clrBackgroundOSD));
+    pixmapTVFrame->DrawEllipse(cRect(tvFrameWidth - radius - frame, height - radius - frame, radius, radius), theme.Color(clrBackgroundOSD), -4);
+}
\ No newline at end of file
diff --git a/statusheader.h b/statusheader.h
new file mode 100644
index 0000000..3096803
--- /dev/null
+++ b/statusheader.h
@@ -0,0 +1,25 @@
+#ifndef __TVGUIDE_STATUSHEADER_H
+#define __TVGUIDE_STATUSHEADER_H
+
+#include "styledpixmap.h"
+#include "grid.h"
+
+// --- cStatusHeader  -------------------------------------------------------------
+
+class cStatusHeader : public cStyledPixmap {
+private:
+    int width, height;
+    int tvFrameWidth;
+    cPixmap *pixmapText;
+    cPixmap *pixmapTVFrame;
+    int DrawPoster(const cEvent *event, int x, int y, int height, int border);
+    void DecorateVideoFrame(void);
+public:
+    cStatusHeader(void);
+    virtual ~cStatusHeader(void);
+    void Draw(void);
+    void ScaleVideo(void);
+    void DrawInfoText(cGrid *grid);
+};
+
+#endif //__TVGUIDE_STATUSHEADER_H
\ No newline at end of file
diff --git a/styledpixmap.c b/styledpixmap.c
index 1669501..73c9256 100644
--- a/styledpixmap.c
+++ b/styledpixmap.c
@@ -1,62 +1,123 @@
+#include "imageloader.h"
+#include "geometrymanager.h"
 #include "styledpixmap.h"
 
 cStyledPixmap::cStyledPixmap(void) {
-	pixmap = NULL;
-	caller = NULL;
+    pixmap = NULL;
 }
 
-cStyledPixmap::cStyledPixmap(cPixmap *pixmap, cString caller) {
-	this->pixmap = pixmap;
-	this->caller = caller;
+cStyledPixmap::cStyledPixmap(cPixmap *pixmap) {
+    this->pixmap = pixmap;
 }
 
 cStyledPixmap::~cStyledPixmap(void) {
-	if (pixmap)
-		osdManager.releasePixmap(pixmap, *caller);
+    if (pixmap)
+        osdManager.releasePixmap(pixmap);
 }
 
 void cStyledPixmap::setPixmap(cPixmap *pixmap) {
-	if (pixmap) {
-		this->pixmap = pixmap;
-	}
+    if (pixmap) {
+        this->pixmap = pixmap;
+    }
 }
 
 void cStyledPixmap::drawBackground() {
-    if (tvguideConfig.useBlending == 1){
-		drawBlendedBackground();
-	} else if (tvguideConfig.useBlending == 2){
-		drawSparsedBackground();
-	} else {
+    if (tvguideConfig.style == eStyleBlendingDefault){
+        drawBlendedBackground();
+    } else if (tvguideConfig.style == eStyleBlendingMagick){
+        drawSparsedBackground();
+    } else {
         pixmap->Fill(color);
     }
 }
 
+void cStyledPixmap::drawBackgroundGraphical(eBackgroundType type, bool active) {
+    cImage *back = NULL;
+    if (type == bgGrid) {
+        back = imgCache.GetGrid(pixmap->ViewPort().Width(), pixmap->ViewPort().Height(), active);
+    } else if (type == bgChannelHeader) {
+        back = imgCache.GetOsdElement(oeLogoBack);
+    } else if (type == bgChannelGroup) {
+        back = imgCache.GetChannelGroup(pixmap->ViewPort().Width(), pixmap->ViewPort().Height());
+    } else if (type == bgStatusHeaderWindowed) {
+        back = imgCache.GetOsdElement(oeStatusHeaderContentWindowed);
+    } else if (type == bgStatusHeaderFull) {
+        back = imgCache.GetOsdElement(oeStatusHeaderContentFull);
+    }  else if (type == bgClock) {
+        back = imgCache.GetOsdElement(oeClock);
+    } else if (type == bgButton) {
+        drawBackgroundButton(active);
+        return;
+    } else if (type == bgRecMenuBack) {
+        cImageLoader imgLoader;
+        if (imgLoader.LoadOsdElement("recmenu_background", pixmap->ViewPort().Width(), pixmap->ViewPort().Height())) {
+            cImage background = imgLoader.GetImage();
+            pixmap->DrawImage(cPoint(0, 0), background);
+        } else {
+            pixmap->Fill(clrTransparent);
+        }
+        return;
+    } else if (type == bgChannelJump) {
+        back = imgCache.GetOsdElement(oeChannelJump);
+    }
+    if (back) {
+        pixmap->DrawImage(cPoint(0,0), *back);
+    } else {
+        pixmap->Fill(clrTransparent);
+    }
+}
+
+void cStyledPixmap::drawBackgroundButton(bool active) {
+    std::string buttonName = "";
+    int buttonWidth = pixmap->ViewPort().Width();
+    int buttonHeight = pixmap->ViewPort().Height();
+    if (buttonWidth > geoManager.osdWidth * 50 / 100) {
+        if (active)
+            buttonName = "button_active_70percent";
+        else
+            buttonName = "button_70percent";
+    } else  {
+        if (active)
+            buttonName = "button_active_30percent";
+        else
+            buttonName = "button_30percent";            
+    }
+    cImageLoader imgLoader;
+    if (imgLoader.LoadOsdElement(buttonName.c_str(), buttonWidth, buttonHeight)) {
+        cImage button = imgLoader.GetImage();
+        pixmap->DrawImage(cPoint(0, 0), button);
+    } else {
+        pixmap->Fill(clrTransparent);
+    }
+}
+
+
 void cStyledPixmap::drawBlendedBackground() {
-	int width = pixmap->ViewPort().Width();
-	int height = pixmap->ViewPort().Height();
-	pixmap->Fill(color);
-	int numSteps = 64;
-	int alphaStep = 0x04;
-	if (height < 30)
-		return;
-	else if (height < 100) {
-		numSteps = 32;
-		alphaStep = 0x08;
-	}
-	int stepY = 0.5*height / numSteps;
-	if (stepY == 0) stepY = 1;
-	int alpha = 0x00;
-	tColor clr;
-	for (int i = 0; i<numSteps; i++) {
-		clr = AlphaBlend(color, colorBlending, alpha);
-		pixmap->DrawRectangle(cRect(0,i*stepY,width,stepY), clr);
-		alpha += alphaStep;
-	}
+    int width = pixmap->ViewPort().Width();
+    int height = pixmap->ViewPort().Height();
+    pixmap->Fill(color);
+    int numSteps = 64;
+    int alphaStep = 0x04;
+    if (height < 30)
+        return;
+    else if (height < 100) {
+        numSteps = 32;
+        alphaStep = 0x08;
+    }
+    int stepY = 0.5*height / numSteps;
+    if (stepY == 0) stepY = 1;
+    int alpha = 0x00;
+    tColor clr;
+    for (int i = 0; i<numSteps; i++) {
+        clr = AlphaBlend(color, colorBlending, alpha);
+        pixmap->DrawRectangle(cRect(0,i*stepY,width,stepY), clr);
+        alpha += alphaStep;
+    }
 }
 
 void cStyledPixmap::drawSparsedBackground() {
-	int width = pixmap->ViewPort().Width();
-	int height = pixmap->ViewPort().Height();
+    int width = pixmap->ViewPort().Width();
+    int height = pixmap->ViewPort().Height();
     cImageLoader imgLoader;
     if (imgLoader.DrawBackground(colorBlending, color, width, height))
         pixmap->DrawImage(cPoint(0,0), imgLoader.GetImage());
@@ -64,73 +125,81 @@ void cStyledPixmap::drawSparsedBackground() {
 }
 
 void cStyledPixmap::drawBorder() {
-	int width = pixmap->ViewPort().Width();
-	int height = pixmap->ViewPort().Height();
-	
-	drawDefaultBorder(width, height);
-	if (tvguideConfig.roundedCorners) {
-		int borderRadius = 12;
-		drawRoundedCorners(width, height, borderRadius);
-	}
+    int width = pixmap->ViewPort().Width();
+    int height = pixmap->ViewPort().Height();
+    
+    drawDefaultBorder(width, height);
+    if (tvguideConfig.roundedCorners) {
+        int borderRadius = 12;
+        drawRoundedCorners(width, height, borderRadius);
+    }
 }
 
 void cStyledPixmap::drawDefaultBorder(int width, int height) {
-	pixmap->DrawRectangle(cRect(0,0,width,2), theme.Color(clrBackground));			//top
-	pixmap->DrawRectangle(cRect(0,0,2,height), theme.Color(clrBackground));			//left
-	pixmap->DrawRectangle(cRect(0,height-2,width,2), theme.Color(clrBackground));	//bottom
-	pixmap->DrawRectangle(cRect(width-2,0,2,height), theme.Color(clrBackground));	//right
-	
-	pixmap->DrawRectangle(cRect(2,2,width-4,1), theme.Color(clrBorder));			//top
-	pixmap->DrawRectangle(cRect(2,2,1,height-4), theme.Color(clrBorder));			//left
-	pixmap->DrawRectangle(cRect(2,height-3,width-4,1), theme.Color(clrBorder));		//bottom
-	pixmap->DrawRectangle(cRect(width-3,2,1,height-4), theme.Color(clrBorder));		//right
+    pixmap->DrawRectangle(cRect(0,0,width,2), clrTransparent);          //top
+    pixmap->DrawRectangle(cRect(0,0,2,height), clrTransparent);         //left
+    pixmap->DrawRectangle(cRect(0,height-2,width,2), clrTransparent);   //bottom
+    pixmap->DrawRectangle(cRect(width-2,0,2,height), clrTransparent);   //right
+    
+    pixmap->DrawRectangle(cRect(2,2,width-4,1), theme.Color(clrBorder));            //top
+    pixmap->DrawRectangle(cRect(2,2,1,height-4), theme.Color(clrBorder));           //left
+    pixmap->DrawRectangle(cRect(2,height-3,width-4,1), theme.Color(clrBorder));     //bottom
+    pixmap->DrawRectangle(cRect(width-3,2,1,height-4), theme.Color(clrBorder));     //right
 }
 
 void cStyledPixmap::drawBoldBorder() {
-	int width = pixmap->ViewPort().Width();
-	int height = pixmap->ViewPort().Height();
-	pixmap->DrawRectangle(cRect(0,0,width,2), theme.Color(clrBorder));			//top
-	pixmap->DrawRectangle(cRect(0,0,2,height), theme.Color(clrBorder));			//left
-	pixmap->DrawRectangle(cRect(0,height-2,width,2), theme.Color(clrBorder));	//bottom
-	pixmap->DrawRectangle(cRect(width-2,0,2,height), theme.Color(clrBorder));	//right
+    int width = pixmap->ViewPort().Width();
+    int height = pixmap->ViewPort().Height();
+    pixmap->DrawRectangle(cRect(0,0,width,2), theme.Color(clrBorder));          //top
+    pixmap->DrawRectangle(cRect(0,0,2,height), theme.Color(clrBorder));         //left
+    pixmap->DrawRectangle(cRect(0,height-2,width,2), theme.Color(clrBorder));   //bottom
+    pixmap->DrawRectangle(cRect(width-2,0,2,height), theme.Color(clrBorder));   //right
 }
 
 void cStyledPixmap::drawRoundedCorners(int width, int height, int radius) {
-	pixmap->DrawEllipse(cRect(2,2,radius,radius), theme.Color(clrBorder), -2);
-	pixmap->DrawEllipse(cRect(1,1,radius,radius), theme.Color(clrBackground), -2);
-
-	pixmap->DrawEllipse(cRect(width-radius - 2,2,radius,radius), theme.Color(clrBorder), -1);
-	pixmap->DrawEllipse(cRect(width-radius - 1,1,radius,radius), theme.Color(clrBackground), -1);
-	
-	if( height > 2*radius) {
-		pixmap->DrawEllipse(cRect(2,height-radius - 2,radius,radius), theme.Color(clrBorder), -3);
-		pixmap->DrawEllipse(cRect(1,height-radius - 1,radius,radius), theme.Color(clrBackground), -3);
-		
-		pixmap->DrawEllipse(cRect(width-radius - 2,height-radius - 2,radius,radius), theme.Color(clrBorder), -4);
-		pixmap->DrawEllipse(cRect(width-radius - 1,height-radius - 1,radius,radius), theme.Color(clrBackground), -4);
-	}
+    pixmap->DrawEllipse(cRect(2,2,radius,radius), theme.Color(clrBorder), -2);
+    pixmap->DrawEllipse(cRect(1,1,radius,radius), clrTransparent, -2);
+
+    pixmap->DrawEllipse(cRect(width-radius - 2,2,radius,radius), theme.Color(clrBorder), -1);
+    pixmap->DrawEllipse(cRect(width-radius - 1,1,radius,radius), clrTransparent, -1);
+    
+    if( height > 2*radius) {
+        pixmap->DrawEllipse(cRect(2,height-radius - 2,radius,radius), theme.Color(clrBorder), -3);
+        pixmap->DrawEllipse(cRect(1,height-radius - 1,radius,radius), clrTransparent, -3);
+        
+        pixmap->DrawEllipse(cRect(width-radius - 2,height-radius - 2,radius,radius), theme.Color(clrBorder), -4);
+        pixmap->DrawEllipse(cRect(width-radius - 1,height-radius - 1,radius,radius), clrTransparent, -4);
+    }
 }
 
 void cStyledPixmap::drawVerticalLine(int x, int yStart, int yStop, tColor col) {
-	for (int y = yStart; y <= yStop; y++) {
-		pixmap->DrawPixel(cPoint(x,y), col);
-	}
+    for (int y = yStart; y <= yStop; y++) {
+        pixmap->DrawPixel(cPoint(x,y), col);
+    }
 }
 
 void cStyledPixmap::drawHorizontalLine(int y, int xStart, int xStop, tColor col) {
-	for (int x = xStart; x <= xStop; x++) {
-		pixmap->DrawPixel(cPoint(x,y), col);
-	}
+    for (int x = xStart; x <= xStop; x++) {
+        pixmap->DrawPixel(cPoint(x,y), col);
+    }
 }
 
 void cStyledPixmap::DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font) {
-	pixmap->DrawText(Point, s, ColorFg, ColorBg, Font);
+    pixmap->DrawText(Point, s, ColorFg, ColorBg, Font);
 }
 
 void cStyledPixmap::DrawImage(const cPoint &Point, const cImage &Image) {
-	pixmap->DrawImage(Point, Image);
+    pixmap->DrawImage(Point, Image);
 }
 
 void cStyledPixmap::DrawRectangle(const cRect &Rect, tColor Color) {
-	pixmap->DrawRectangle(Rect,Color);
+    pixmap->DrawRectangle(Rect,Color);
 }
+
+void cStyledPixmap::DrawEllipse(const cRect &Rect, tColor Color, int Quadrant) {
+    pixmap->DrawEllipse(Rect,Color,Quadrant);
+}
+
+void cStyledPixmap::SetViewPort(const cRect &Rect) {
+    pixmap->SetViewPort(Rect);
+}
\ No newline at end of file
diff --git a/styledpixmap.h b/styledpixmap.h
index 147d6a0..82af25c 100644
--- a/styledpixmap.h
+++ b/styledpixmap.h
@@ -1,36 +1,58 @@
 #ifndef __TVGUIDE_STYLEDPIXMAP_H
 #define __TVGUIDE_STYLEDPIXMAP_H
 
+#include <vdr/osd.h>
+#include <vdr/epg.h>
+#include "timer.h"
+#include "config.h"
+
+enum eBackgroundType {
+    bgGrid,
+    bgStatusHeaderFull,
+    bgStatusHeaderWindowed,
+    bgChannelHeader,
+    bgChannelGroup,
+    bgClock,
+    bgButton,
+    bgRecMenuBack,
+    bgChannelJump,
+};
+
 // --- cStyledPixmap -------------------------------------------------------------
 
 class cStyledPixmap {
 private:
-	void drawVerticalLine(int x, int yStart, int yStop, tColor col);
-	void drawHorizontalLine(int y, int xStart, int xStop, tColor col);
+    void drawVerticalLine(int x, int yStart, int yStop, tColor col);
+    void drawHorizontalLine(int y, int xStart, int xStop, tColor col);
+    void drawBackgroundButton(bool active);
 protected:
-	cPixmap *pixmap;
-	cString caller;
-	tColor color;
-	tColor colorBlending;
-	void setPixmap(cPixmap *pixmap);
+    cPixmap *pixmap;
+    tColor color;
+    tColor colorBlending;
+    void setPixmap(cPixmap *pixmap);
 public:
-  cStyledPixmap(void);
-  cStyledPixmap(cPixmap *pixmap, cString caller);
-  virtual ~cStyledPixmap(void);
-  void drawBackground();
-  void drawBlendedBackground();
-  void drawSparsedBackground();
-  void drawBorder();
-  void drawBoldBorder();
-  void drawDefaultBorder(int width, int height);
-  void drawRoundedCorners(int width, int height, int radius);
-  void setColor(tColor color, tColor colorBlending) {this->color = color; this->colorBlending = colorBlending;};
-  void SetAlpha(int alpha) {pixmap->SetAlpha(alpha);};
-  void DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font);
-  void DrawImage(const cPoint &Point, const cImage &Image);
-  void DrawRectangle(const cRect &Rect, tColor Color);
-  int Width() {return pixmap->ViewPort().Width();};
-  int Height() {return pixmap->ViewPort().Height();};
+    cStyledPixmap(void);
+    cStyledPixmap(cPixmap *pixmap);
+    virtual ~cStyledPixmap(void);
+    void drawBackground();
+    void drawBackgroundGraphical(eBackgroundType type, bool active = false);
+    void drawBlendedBackground();
+    void drawSparsedBackground();
+    void drawBorder();
+    void drawBoldBorder();
+    void drawDefaultBorder(int width, int height);
+    void drawRoundedCorners(int width, int height, int radius);
+    void setColor(tColor color, tColor colorBlending) {this->color = color; this->colorBlending = colorBlending;};
+    void SetAlpha(int alpha) {pixmap->SetAlpha(alpha);};
+    void SetLayer(int layer) {pixmap->SetLayer(layer);};
+    void Fill(tColor clr) {pixmap->Fill(clr);};
+    void DrawText(const cPoint &Point, const char *s, tColor ColorFg, tColor ColorBg, const cFont *Font);
+    void DrawImage(const cPoint &Point, const cImage &Image);
+    void DrawRectangle(const cRect &Rect, tColor Color);
+    void DrawEllipse(const cRect &Rect, tColor Color, int Quadrant);
+    void SetViewPort(const cRect &Rect);
+    int Width() {return pixmap->ViewPort().Width();};
+    int Height() {return pixmap->ViewPort().Height();};
 };
 
 #endif //__TVGUIDE_STYLEDPIXMAP_H
\ No newline at end of file
diff --git a/switchtimer.c b/switchtimer.c
new file mode 100644
index 0000000..f56c469
--- /dev/null
+++ b/switchtimer.c
@@ -0,0 +1,113 @@
+#include "switchtimer.h"
+
+cSwitchTimers SwitchTimers;
+
+// -- cSwitchTimer -----------------------------------------------------------------
+cSwitchTimer::cSwitchTimer(void) {
+    eventID = 0;
+    startTime = 0;
+    switchMinsBefore = 2;
+    announceOnly = 0;
+}
+
+cSwitchTimer::cSwitchTimer(const cEvent* Event) {
+    eventID = 0;
+    startTime = 0;
+    if (Event) {
+      eventID = Event->EventID();
+      channelID = Event->ChannelID();
+      startTime = Event->StartTime();
+    }
+}
+
+bool cSwitchTimer::Parse(const char *s) {
+    char *line;
+    char *pos;
+    char *pos_next;
+    int parameter = 1;
+    int valuelen;
+#define MAXVALUELEN (10 * MaxFileName)
+
+    char value[MAXVALUELEN];
+    startTime=0;
+
+    pos = line = strdup(s);
+    pos_next = pos + strlen(pos);
+    if (*pos_next == '\n') *pos_next = 0;
+        while (*pos) {
+            while (*pos == ' ') 
+                pos++;
+            if (*pos) {
+                if (*pos != ':') {
+                    pos_next = strchr(pos, ':');
+                    if (!pos_next)
+                        pos_next = pos + strlen(pos);
+                    valuelen = pos_next - pos + 1;
+                    if (valuelen > MAXVALUELEN)
+                        valuelen = MAXVALUELEN;
+                    strn0cpy(value, pos, valuelen);
+                    pos = pos_next;
+                    switch (parameter) {
+                        case 1:
+                            channelID = tChannelID::FromString(value);
+                            break;
+                        case 2:
+                            eventID = atoi(value);
+                            break;
+                        case 3:
+                            startTime = atol(value);
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                parameter++;
+            }
+            if (*pos) 
+                pos++;
+        }
+    free(line);
+    return (parameter >= 3) ? true : false;
+}
+
+bool cSwitchTimers::EventInSwitchList(const cEvent* event) {
+    if (!event) return false;
+    cMutexLock SwitchTimersLock(this);
+    cSwitchTimer* switchTimer = SwitchTimers.First();
+    while (switchTimer) {
+        if (switchTimer->eventID == event->EventID())
+            return true;
+        switchTimer = SwitchTimers.Next(switchTimer);
+    }
+    return false;
+}
+
+bool cSwitchTimers::ChannelInSwitchList(const cChannel* channel) {
+    if (!channel) return false;
+    cMutexLock SwitchTimersLock(this);
+    cSwitchTimer* switchTimer = SwitchTimers.First();
+    while (switchTimer) {
+        if (switchTimer->channelID == channel->GetChannelID())
+            return true;
+        switchTimer = SwitchTimers.Next(switchTimer);
+    }
+    return false;
+}
+
+void cSwitchTimers::DeleteSwitchTimer(const cEvent *event) {
+    if (!event) return;
+    cMutexLock SwitchTimersLock(this);
+    cSwitchTimer* switchTimer = SwitchTimers.First();
+    cSwitchTimer* delTimer = NULL;
+    
+    while (switchTimer) {
+        if (switchTimer->eventID == event->EventID()) {
+            delTimer = switchTimer;
+            break;
+        }
+        switchTimer = SwitchTimers.Next(switchTimer);
+    }
+    if (delTimer) {
+        SwitchTimers.Del(delTimer, true);
+    }
+}
diff --git a/switchtimer.h b/switchtimer.h
new file mode 100644
index 0000000..09ebe88
--- /dev/null
+++ b/switchtimer.h
@@ -0,0 +1,31 @@
+#ifndef __TVGUIDE_SWITCHTIMER_H
+#define __TVGUIDE_SWITCHTIMER_H
+
+#include <vdr/plugin.h>
+
+class cSwitchTimer : public cListObject {
+public:
+    tEventID eventID;
+    time_t startTime;
+    tChannelID channelID;
+    int switchMinsBefore;
+    int announceOnly;
+    cSwitchTimer(void);
+    cSwitchTimer(const cEvent* Event);
+    bool Parse(const char *s);
+    void SetEventID(tEventID eventID) { this->eventID = eventID; };
+    void SetStartTime(time_t startTime) { this->startTime = startTime; };
+};
+
+class cSwitchTimers : public cConfig<cSwitchTimer>, public cMutex {
+public:
+    cSwitchTimers(void) {}
+    ~cSwitchTimers(void) {}
+    bool EventInSwitchList(const cEvent* event);
+    bool ChannelInSwitchList(const cChannel* channel);
+    void DeleteSwitchTimer(const cEvent *event);
+};
+
+extern cSwitchTimers SwitchTimers;
+
+#endif //__TVGUIDE_SWITCHTIMER_H
diff --git a/themes/tvguide-blue.theme b/themes/tvguide-blue.theme
new file mode 100644
index 0000000..2aeda4c
--- /dev/null
+++ b/themes/tvguide-blue.theme
@@ -0,0 +1,53 @@
+Description = Blue 
+clrStyle = FFFFFFFF
+clrBackground = FF000000
+clrBackgroundOSD = FF000000
+clrGrid1 = EE555555
+clrGrid1Blending = 90000000
+clrGrid2 = EE888888
+clrGrid2Blending = 90000000
+clrHighlight = EE0033FF
+clrHighlightBlending = DD000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrFont = FFFFFFFF
+clrFontActive  = FFFFFFFF
+clrFontHeader = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrHeader = EE888888
+clrHeaderBlending = 90000000
+clrBorder = DD003DF5
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = BBFFFFFF
+clrTimeline1Blending = 90828282
+clrTimeline2 = BB000000
+clrTimeline2Blending = 903F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 44003DF5
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FF003DF5
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-darkblue.theme b/themes/tvguide-darkblue.theme
index 59db3ad..008aa80 100644
--- a/themes/tvguide-darkblue.theme
+++ b/themes/tvguide-darkblue.theme
@@ -1,5 +1,5 @@
-Description = DarkBlue
-
+Description = Dark Blue
+clrStyle = AAAAAAAA
 clrBackground = FF000000
 clrBackgroundOSD = FF000000
 clrGrid1 = FF0E53A7
@@ -8,16 +8,23 @@ clrGrid2 = FF071871
 clrGrid2Blending = FF000000
 clrHighlight = FF7A6D6D
 clrHighlightBlending = FF1C1919
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
 clrFont = FFFFFFFF
+clrFontActive = FFFFFFFF
 clrFontHeader = FF000000
 clrFontButtons = FFFFFFFF
 clrHeader = FF8B9194
 clrHeaderBlending = FF000000
 clrBorder = FFFFFFFF
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
 clrTimeline1 = FFFFFFFF
 clrTimeline1Blending = FF828282
 clrTimeline2 = FF000000
 clrTimeline2Blending = FF3F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 99242A38
 clrButtonRed = 99BB0000
 clrButtonRedBorder = FFBB0000
 clrButtonGreen = 9900BB00
@@ -27,3 +34,20 @@ clrButtonYellowBorder = FFBBBB00
 clrButtonBlue = 990000BB
 clrButtonBlueBorder = FF0000BB
 clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FFFFFFFF
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-darkred.theme b/themes/tvguide-darkred.theme
new file mode 100644
index 0000000..06f7c71
--- /dev/null
+++ b/themes/tvguide-darkred.theme
@@ -0,0 +1,53 @@
+Description = Dark Red
+clrStyle = FFFFFFFF
+clrBackground = FF000000
+clrBackgroundOSD = FF000000
+clrGrid1 = EE555555
+clrGrid1Blending = 90000000
+clrGrid2 = DD333333
+clrGrid2Blending = 90000000
+clrHighlight = DDBB0000
+clrHighlightBlending = DD000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrFont = FFFFFFFF
+clrFontActive  = FFFFFFFF
+clrFontHeader = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrHeader = EE888888
+clrHeaderBlending = 90000000
+clrBorder = AABB0000
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = BBFFFFFF
+clrTimeline1Blending = 90828282
+clrTimeline2 = BB000000
+clrTimeline2Blending = 903F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 66550000
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FF660000
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B0660000
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-darkredNG.theme b/themes/tvguide-darkredNG.theme
new file mode 100644
index 0000000..93ddc41
--- /dev/null
+++ b/themes/tvguide-darkredNG.theme
@@ -0,0 +1,53 @@
+Description = Dark Red NG
+clrStyle = 66666666
+clrBackground = FF000000
+clrBackgroundOSD = FF000000
+clrGrid1 = EE555555
+clrGrid1Blending = 90000000
+clrGrid2 = DD333333
+clrGrid2Blending = 90000000
+clrHighlight = DDBB0000
+clrHighlightBlending = DD000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrFont = FFFFFFFF
+clrFontActive  = FFFFFFFF
+clrFontHeader = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrHeader = EE888888
+clrHeaderBlending = 90000000
+clrBorder = 00000000
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = FFFFFFFF
+clrTimeline1Blending = 90828282
+clrTimeline2 = FF000000
+clrTimeline2Blending = 903F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 66660000
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = 90FF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FF660000
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B0660000
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-default.theme b/themes/tvguide-default.theme
index b9817b5..c8fc9b0 100644
--- a/themes/tvguide-default.theme
+++ b/themes/tvguide-default.theme
@@ -1,28 +1,53 @@
 Description = Default 
-clrBackground = FF000000
-clrBackgroundOSD = FF000000
-clrGrid1 = FF404749
-clrGrid1Blending = FF000000
-clrGrid2 = FF20293F
-clrGrid2Blending = FF000000
-clrHighlight = FFFF4D00
-clrHighlightBlending = FF000000
+clrStyle = 66666666
+clrBackground = FF12273f
+clrBackgroundOSD = B012273f
+clrGrid1 = 00000000
+clrGrid1Blending = 00000000
+clrGrid2 = 00000000
+clrGrid2Blending = 00000000
+clrHighlight = DD313548
+clrHighlightBlending = DD000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = FFAFD533
 clrFont = FFFFFFFF
-clrFontHeader = FFFFFFFF
+clrFontActive  = FF363636
+clrFontHeader = FF363636
 clrFontButtons = FFFFFFFF
-clrHeader = FF000000
-clrHeaderBlending = FFE0E0E0
-clrBorder = FFFFFFFF
+clrHeader = 00000000
+clrHeaderBlending = 00000000
+clrBorder = 00000000
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
 clrTimeline1 = FFFFFFFF
 clrTimeline1Blending = FF828282
 clrTimeline2 = FF000000
 clrTimeline2Blending = FF3F3F3F
-clrButtonRed = 99BB0000
-clrButtonRedBorder = FFBB0000
-clrButtonGreen = 9900BB00
-clrButtonGreenBorder = FF00BB00
-clrButtonYellow = 99BBBB00
-clrButtonYellowBorder = FFBBBB00
-clrButtonBlue = 990000BB
-clrButtonBlueBorder = FF0000BB
+clrTimeBase = A0FF0000
+clrTabInactive = A01F3D7A
+clrButtonRed = FFFF0000
+clrButtonRedBorder = 00000000
+clrButtonGreen = 00000000
+clrButtonGreenBorder = 00000000
+clrButtonYellow = 00000000
+clrButtonYellowBorder = 00000000
+clrButtonBlue = 00000000
+clrButtonBlueBorder = 00000000
 clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = A0FF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF939376
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = FFFFFFFF
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
diff --git a/themes/tvguide-green.theme b/themes/tvguide-green.theme
new file mode 100644
index 0000000..7fca3b0
--- /dev/null
+++ b/themes/tvguide-green.theme
@@ -0,0 +1,53 @@
+Description = Green
+clrStyle = FFFFFFFF
+clrBackground = FF000000
+clrBackgroundOSD = FF000000
+clrGrid1 = EE555555
+clrGrid1Blending = 90000000
+clrGrid2 = EE888888
+clrGrid2Blending = 90000000
+clrHighlight = EE006600
+clrHighlightBlending = 22000000
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrFont = FFFFFFFF
+clrFontActive  = FFFFFFFF
+clrFontHeader = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrHeader = EE888888
+clrHeaderBlending = 90000000
+clrBorder = EE006600
+clrStatusHeader = 00000000
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = BBFFFFFF
+clrTimeline1Blending = 90828282
+clrTimeline2 = BB000000
+clrTimeline2Blending = 903F3F3F
+clrTimeBase = A0FF0000
+clrTabInactive = 33006600
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = EE006600
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B0003D00
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-iceblue.theme b/themes/tvguide-iceblue.theme
new file mode 100644
index 0000000..310872a
--- /dev/null
+++ b/themes/tvguide-iceblue.theme
@@ -0,0 +1,51 @@
+Description = IceBlue
+clrStyle = 00000000
+clrBackground = DDFFFFFF
+clrBackgroundOSD = FFFFFFFF
+clrGrid1 = BB555555
+clrGrid2 = BB888888
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrHighlight = FF000044
+clrFont = FF000000
+clrFontActive  = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrFontHeader = FF000000
+clrHeader = FFFFFFFF
+clrBorder = FF000000
+clrStatusHeader = FFFFFFFF
+clrStatusHeaderBlending = FFFFFFFF
+clrTimeline1 = FFDDDDDD
+clrTimeline1Blending = 00000000
+clrTimeline2 = FF000000
+clrTimeline2Blending = 00000000
+clrTimeBase = A0FF0000
+clrTabInactive = 88B8B8E6
+clrButtonRed = FFBB0000
+clrButtonRedBorder = FF000000
+clrButtonGreen = FF00BB00
+clrButtonGreenBorder = FF000000
+clrButtonYellow = FFBBBB00
+clrButtonYellowBorder = FF000000
+clrButtonBlue = FF0000BB
+clrButtonBlueBorder = FF000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 77000000
+clrRecMenuTextBack = FF3C3C3C
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000044
+clrRecMenuKeyboardBorder = FF3C3C3C
+clrRecMenuKeyboardHigh = 55FFFFFF
+clrButtonRedKeyboard = FFBB0000
+clrButtonGreenKeyboard = FF00BB00
+clrButtonYellowKeyboard = FFBBBB00
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-keepitsimple.theme b/themes/tvguide-keepitsimple.theme
new file mode 100644
index 0000000..1f325c9
--- /dev/null
+++ b/themes/tvguide-keepitsimple.theme
@@ -0,0 +1,49 @@
+Description = Keep it simple
+clrStyle = 00000000
+clrBackground = FF111111
+clrBackgroundOSD = FF111111
+clrGrid1 = BB555555
+clrGrid2 = BB888888
+clrGridFontBack = 00000000
+clrGridActiveFontBack = 00000000
+clrHighlight = FF336699
+clrFont = FFFFFFFF
+clrFontActive  = FFFFFFFF
+clrFontButtons = FFFFFFFF
+clrFontHeader = FFDCDCDC
+clrHeader = FF2B3856
+clrBorder = FF000000
+clrStatusHeader = FF111111
+clrStatusHeaderBlending = 00000000
+clrTimeline1 = FF737CA1
+clrTimeline1Blending = 00000000
+clrTimeline2 = FF2B3856
+clrTimeline2Blending = 00000000
+clrTimeBase = A0FF0000
+clrTabInactive = 886fac10
+clrButtonRed = 99BB0000
+clrButtonRedBorder = FFBB0000
+clrButtonGreen = 9900BB00
+clrButtonGreenBorder = FF00BB00
+clrButtonYellow = 99BBBB00
+clrButtonYellowBorder = FFBBBB00
+clrButtonBlue = 990000BB
+clrButtonBlueBorder = FF0000BB
+clrButtonBlend = DD000000
+clrRecMenuBackground = AA000000
+clrRecMenuTimerConflictBackground = FFCCCCCC
+clrRecMenuTimerConflictBar = FF222222
+clrRecMenuTimerConflictOverlap = AAFF0000
+clrRecMenuDayActive = FF00FF00
+clrRecMenuDayInactive = FFFF0000
+clrRecMenuDayHighlight = 44FFFFFF
+clrRecMenuTextBack = FF000000
+clrRecMenuTextActiveBack = FF404749
+clrRecMenuKeyboardBack = FF000000
+clrRecMenuKeyboardBorder = BB555555
+clrRecMenuKeyboardHigh = 40BB0000
+clrRecMenuTimelineTimer = B012273f
+clrRecMenuTimelineBack = FF828282
+clrRecMenuTimelineActive = FF3F3F3F
+clrRecMenuTimelineConflict = 30FF0000
+clrRecMenuTimelineConflictOverlap = 90FF0000
\ No newline at end of file
diff --git a/themes/tvguide-nOpacity.theme b/themes/tvguide-nOpacity.theme
deleted file mode 100644
index f00d54b..0000000
--- a/themes/tvguide-nOpacity.theme
+++ /dev/null
@@ -1,28 +0,0 @@
-Description = nOpacity
-clrBackground = FF000000
-clrBackgroundOSD = FF000000
-clrGrid1 = EE555555
-clrGrid1Blending = 90000000
-clrGrid2 = EE888888
-clrGrid2Blending = 90000000
-clrHighlight = EE0033FF
-clrHighlightBlending = DD000000
-clrFont = FFFFFFFF
-clrFontHeader = FFFFFFFF
-clrFontButtons = FFFFFFFF
-clrHeader = EE888888
-clrHeaderBlending = 90000000
-clrBorder = DD003DF5 
-clrTimeline1 = BBFFFFFF
-clrTimeline1Blending = 90828282
-clrTimeline2 = BB000000
-clrTimeline2Blending = 903F3F3F
-clrButtonRed = 99BB0000
-clrButtonRedBorder = FFBB0000
-clrButtonGreen = 9900BB00
-clrButtonGreenBorder = FF00BB00
-clrButtonYellow = 99BBBB00
-clrButtonYellowBorder = FFBBBB00
-clrButtonBlue = 990000BB
-clrButtonBlueBorder = FF0000BB
-clrButtonBlend = DD000000
diff --git a/themes/tvguide-nOpacitygreen.theme b/themes/tvguide-nOpacitygreen.theme
deleted file mode 100644
index 46ca336..0000000
--- a/themes/tvguide-nOpacitygreen.theme
+++ /dev/null
@@ -1,28 +0,0 @@
-Description = nOpacity Green
-clrBackground = FF000000
-clrBackgroundOSD = FF000000
-clrGrid1 = EE555555
-clrGrid1Blending = 90000000
-clrGrid2 = EE888888
-clrGrid2Blending = 90000000
-clrHighlight = EE006600
-clrHighlightBlending = 22000000
-clrFont = FFFFFFFF
-clrFontHeader = FFFFFFFF
-clrFontButtons = FFFFFFFF
-clrHeader = EE888888
-clrHeaderBlending = 90000000
-clrBorder = EE006600 
-clrTimeline1 = BBFFFFFF
-clrTimeline1Blending = 90828282
-clrTimeline2 = BB000000
-clrTimeline2Blending = 903F3F3F
-clrButtonRed = 99BB0000
-clrButtonRedBorder = FFBB0000
-clrButtonGreen = 9900BB00
-clrButtonGreenBorder = FF00BB00
-clrButtonYellow = 99BBBB00
-clrButtonYellowBorder = FFBBBB00
-clrButtonBlue = 990000BB
-clrButtonBlueBorder = FF0000BB
-clrButtonBlend = DD000000
diff --git a/timeline.c b/timeline.c
index be3199a..168861c 100644
--- a/timeline.c
+++ b/timeline.c
@@ -1,102 +1,237 @@
+#include "imageloader.h"
 #include "timeline.h"
 
 cTimeLine::cTimeLine(cMyTime *myTime) {
-	this->myTime = myTime;
-	dateViewer = new cStyledPixmap(osdManager.requestPixmap(3, cRect(0, 0, tvguideConfig.timeColWidth, tvguideConfig.headerHeight), cRect::Null, "dateViewer"), "dateViewer");
-	timeline = osdManager.requestPixmap(2, cRect(0, tvguideConfig.headerHeight, tvguideConfig.timeColWidth, tvguideConfig.osdHeight - tvguideConfig.headerHeight - tvguideConfig.footerHeight), 
-									cRect(0,0, tvguideConfig.timeColWidth, 1440*tvguideConfig.minuteHeight), "timeline");
-	clock = new cStyledPixmap(osdManager.requestPixmap(3, cRect(0, tvguideConfig.osdHeight-tvguideConfig.footerHeight, tvguideConfig.timeColWidth, tvguideConfig.footerHeight-9), cRect::Null, "timeViewer"), "timeViewer");
+    this->myTime = myTime;
+    if (tvguideConfig.displayMode == eVertical) {
+        dateViewer = new cStyledPixmap(osdManager.requestPixmap(1, cRect(0, 
+                                                                         geoManager.statusHeaderHeight, 
+                                                                         geoManager.dateVieverWidth, 
+                                                                         geoManager.dateVieverHeight)));
+        timeline = osdManager.requestPixmap(2, cRect(0, 
+                                                     geoManager.statusHeaderHeight + geoManager.channelHeaderHeight + geoManager.channelGroupsHeight, 
+                                                     geoManager.timeLineWidth, 
+                                                     geoManager.osdHeight - geoManager.statusHeaderHeight - geoManager.channelHeaderHeight - geoManager.channelGroupsHeight - geoManager.footerHeight)
+                                             , cRect(0,
+                                                     0, 
+                                                     geoManager.timeLineWidth, 
+                                                     1440*geoManager.minutePixel));
+        timeBase = osdManager.requestPixmap(3, cRect(0, 
+                                                     geoManager.statusHeaderHeight + geoManager.channelGroupsHeight + geoManager.channelHeaderHeight, 
+                                                     geoManager.osdWidth, 
+                                                     geoManager.timeLineGridHeight));
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        dateViewer = new cStyledPixmap(osdManager.requestPixmap(1, cRect(0, 
+                                                                         geoManager.statusHeaderHeight, 
+                                                                         geoManager.dateVieverWidth,
+                                                                         geoManager.dateVieverHeight)));
+        timeline = osdManager.requestPixmap(2, cRect(geoManager.channelHeaderWidth + geoManager.channelGroupsWidth, 
+                                                     geoManager.statusHeaderHeight, 
+                                                     geoManager.osdWidth - geoManager.channelHeaderWidth - geoManager.channelGroupsWidth,
+                                                     geoManager.timeLineHeight)
+                                             , cRect(0,
+                                                     0, 
+                                                     1440*geoManager.minutePixel, 
+                                                     geoManager.timeLineHeight));
+        timeBase = osdManager.requestPixmap(3, cRect(geoManager.channelGroupsWidth + geoManager.channelHeaderWidth, 
+                                                     geoManager.statusHeaderHeight, 
+                                                     geoManager.timeLineGridWidth, 
+                                                     geoManager.timeLineHeight + tvguideConfig.channelRows * geoManager.rowHeight));
+    }
+    timeBase->Fill(clrTransparent);
+    int clockY = 10;
+    int clockX;
+    if (tvguideConfig.scaleVideo) {
+        clockX = geoManager.osdWidth - geoManager.tvFrameWidth - geoManager.clockWidth - 4;
+    } else {
+        clockX = geoManager.osdWidth - geoManager.clockWidth - 10;
+    }
+    clock = new cStyledPixmap(osdManager.requestPixmap(3, cRect(clockX, 
+                                                                clockY, 
+                                                                geoManager.clockWidth, 
+                                                                geoManager.clockHeight)));
 }
 
 cTimeLine::~cTimeLine(void) {
-	delete dateViewer;
-	osdManager.releasePixmap(timeline);
-	delete clock;
+    delete dateViewer;
+    osdManager.releasePixmap(timeline);
+    if (clock)
+        delete clock;
 }
 
 void cTimeLine::drawDateViewer() {
-	cString weekDay = myTime->GetWeekday();
-	cString date = myTime->GetDate();	
-
-	int textHeight = tvguideConfig.FontTimeLineWeekday->Height();
-	int weekdayWidth = tvguideConfig.FontTimeLineWeekday->Width(*weekDay);
-	int dateWidth = tvguideConfig.FontTimeLineDate->Width(*date);
+    cString weekDay = myTime->GetWeekday();
+    cString date = myTime->GetDate();   
+    if (tvguideConfig.style != eStyleGraphical) {
+        dateViewer->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
+        dateViewer->drawBackground();
+        dateViewer->drawBorder();
+        
+    } else {
+        cImage *imgBack = imgCache.GetOsdElement(oeDateViewer);
+        if (imgBack)
+            dateViewer->DrawImage(cPoint(0,0), *imgBack);
+        else
+            dateViewer->Fill(clrTransparent);
+    }
+    tColor colorFont = theme.Color(clrFont);
+    tColor colorFontBack = (tvguideConfig.style == eStyleFlat)?theme.Color(clrHeader):clrTransparent;
 
-	dateViewer->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
-	dateViewer->drawBackground();
-	dateViewer->drawBorder();
-	dateViewer->DrawText(cPoint((tvguideConfig.timeColWidth-weekdayWidth)/2, (tvguideConfig.headerHeight-2*textHeight)/2), *weekDay, theme.Color(clrFontHeader), clrTransparent, tvguideConfig.FontTimeLineWeekday);
-	dateViewer->DrawText(cPoint((tvguideConfig.timeColWidth-dateWidth)/2, (tvguideConfig.headerHeight-2*textHeight)/2 + textHeight + 5), *date, theme.Color(clrFontHeader), clrTransparent, tvguideConfig.FontTimeLineDate);
+    if (tvguideConfig.displayMode == eVertical) {
+        int textHeight = fontManager.FontTimeLineWeekday->Height();
+        int weekdayWidth = fontManager.FontTimeLineWeekday->Width(*weekDay);
+        int dateWidth = fontManager.FontTimeLineDate->Width(*date);
+        dateViewer->DrawText(cPoint((geoManager.timeLineWidth-weekdayWidth)/2, (geoManager.channelHeaderHeight + geoManager.channelGroupsHeight -2*textHeight)/2), *weekDay, colorFont, colorFontBack, fontManager.FontTimeLineWeekday);
+        dateViewer->DrawText(cPoint((geoManager.timeLineWidth-dateWidth)/2, (geoManager.channelHeaderHeight + geoManager.channelGroupsHeight -2*textHeight)/2 + textHeight + 5), *date, colorFont, colorFontBack, fontManager.FontTimeLineDate);
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        cString strDate = cString::sprintf("%s %s", *weekDay, *date);
+        int x = (dateViewer->Width() - fontManager.FontTimeLineDateHorizontal->Width(*strDate))/2;
+        int y = (dateViewer->Height() - fontManager.FontTimeLineDateHorizontal->Height())/2;
+        dateViewer->DrawText(cPoint(x, y), *strDate, colorFont, colorFontBack, fontManager.FontTimeLineDateHorizontal);
+    }
 }
 
 void cTimeLine::drawTimeline() {
-	timeline->SetTile(true);
-	timeline->Fill(theme.Color(clrBackground));
-	tColor colorFont;
-	
-	const cImage *img1 = createBackgroundImage(tvguideConfig.timeColWidth-4, tvguideConfig.minuteHeight*30, theme.Color(clrTimeline1), theme.Color(clrTimeline1Blending));
-	const cImage *img2 = createBackgroundImage(tvguideConfig.timeColWidth-4, tvguideConfig.minuteHeight*30, theme.Color(clrTimeline2), theme.Color(clrTimeline2Blending));
-	const cImage *img = NULL;
-	
-	int textWidth, posY;
-	char timetext[10];
-	
-	for (int i=0; i<48; i++) {
-		if (i%2==0) {
-			img = img1;
-			colorFont = theme.Color(clrTimeline2);
-			if (tvguideConfig.timeFormat == e12Hours) {
-				if (i == 0)
-					sprintf(timetext, "12:00 PM");
-				else if (i/2 < 13)
-					sprintf(timetext, "%d:00 AM", i/2);
-				else 
-					sprintf(timetext, "%d:00 PM", i/2-12);
-			} else {
-				sprintf(timetext, "%d:00", i/2);
-			}
-		} else {
-			img = img2;
-			colorFont = theme.Color(clrTimeline1);
-			if (tvguideConfig.timeFormat == e12Hours) {
-				if (i == 1)
-					sprintf(timetext, "12:30 PM");
-				else if (i/2 < 13)
-					sprintf(timetext, "%d:30 AM", i/2);
-				else 
-					sprintf(timetext, "%d:30 PM", i/2-12);
-			} else {
-				sprintf(timetext, "%d:30", i/2);
-			}
-		}
-		posY = i*tvguideConfig.minuteHeight*30;
-		timeline->DrawImage(cPoint(2, posY), *img);
-		textWidth = tvguideConfig.FontTimeLineTime->Width(timetext);
-		timeline->DrawText(cPoint((tvguideConfig.timeColWidth-textWidth)/2, posY + 5), timetext, colorFont, clrTransparent, tvguideConfig.FontTimeLineTime);
-	}
-	setTimeline();
-	delete img1;
-	delete img2;
+    timeline->SetTile(true);
+    timeline->Fill(clrTransparent);
+    tColor colorFont, colorBackground;
+    
+    int imgWidth = geoManager.timeLineGridWidth;
+    int imgHeight = geoManager.timeLineGridHeight;
+    const cImage *img1 = NULL;
+    const cImage *img2 = NULL;
+    if (tvguideConfig.style == eStyleGraphical) {
+        img1 = imgCache.GetOsdElement(oeTimeline1);
+        img2 = imgCache.GetOsdElement(oeTimeline2);
+    } else {
+        img1 = createBackgroundImage(imgWidth, imgHeight, theme.Color(clrTimeline1), theme.Color(clrTimeline1Blending));
+        img2 = createBackgroundImage(imgWidth, imgHeight, theme.Color(clrTimeline2), theme.Color(clrTimeline2Blending));
+    }
+    const cImage *img = NULL;
+    if (!img1 || !img2)
+        return;
+    int textWidth, posX, posY;
+    char timetext[10];
+    
+    for (int i=0; i<48; i++) {
+        if (i%2==0) {
+            img = img1;
+            colorFont = theme.Color(clrTimeline2);
+            colorBackground = (tvguideConfig.style == eStyleFlat)?theme.Color(clrTimeline1):clrTransparent;
+            if (tvguideConfig.timeFormat == e12Hours) {
+                if (i == 0)
+                    sprintf(timetext, "12:00 PM");
+                else if (i/2 < 13)
+                    sprintf(timetext, "%d:00 AM", i/2);
+                else 
+                    sprintf(timetext, "%d:00 PM", i/2-12);
+            } else {
+                sprintf(timetext, "%d:00", i/2);
+            }
+        } else {
+            img = img2;
+            colorFont = theme.Color(clrTimeline1);
+            colorBackground = (tvguideConfig.style == eStyleFlat)?theme.Color(clrTimeline2):clrTransparent;
+            if (tvguideConfig.timeFormat == e12Hours) {
+                if (i == 1)
+                    sprintf(timetext, "12:30 PM");
+                else if (i/2 < 13)
+                    sprintf(timetext, "%d:30 AM", i/2);
+                else 
+                    sprintf(timetext, "%d:30 PM", i/2-12);
+            } else {
+                sprintf(timetext, "%d:30", i/2);
+            }
+        }
+        if (tvguideConfig.displayMode == eVertical) {
+            posY = i*geoManager.minutePixel*30;
+            timeline->DrawImage(cPoint(0, posY), *img);
+            if (tvguideConfig.style != eStyleGraphical) {
+                decorateTile(0, posY, imgWidth+2, imgHeight);
+            }
+            textWidth = fontManager.FontTimeLineTime->Width(timetext);
+            timeline->DrawText(cPoint((geoManager.timeLineWidth-textWidth)/2, posY + 5), timetext, colorFont, colorBackground, fontManager.FontTimeLineTime);
+        } else if (tvguideConfig.displayMode == eHorizontal) {
+            posX = i*geoManager.minutePixel*30;
+            timeline->DrawImage(cPoint(posX, 0), *img);
+            if (tvguideConfig.style != eStyleGraphical) {
+                decorateTile(posX, 0, imgWidth, imgHeight+2);
+            }
+            timeline->DrawText(cPoint(posX + 15, (dateViewer->Height() - fontManager.FontTimeLineTimeHorizontal->Height())/2), timetext, colorFont, colorBackground, fontManager.FontTimeLineTimeHorizontal);
+       }
+    }
+    setTimeline();
+    if (tvguideConfig.style != eStyleGraphical) {
+        delete img1;
+        delete img2;
+    }
 }
 
+void cTimeLine::decorateTile(int posX, int posY, int tileWidth, int tileHeight) {
+    timeline->DrawRectangle(cRect(posX,posY,tileWidth,2), clrTransparent);          //top
+    timeline->DrawRectangle(cRect(posX,posY,2,tileHeight), clrTransparent);         //left
+    timeline->DrawRectangle(cRect(posX,posY + tileHeight-2,tileWidth,2), clrTransparent);   //bottom
+    timeline->DrawRectangle(cRect(posX + tileWidth-2,posY,2,tileHeight), clrTransparent);   //right
+
+    timeline->DrawRectangle(cRect(2+posX,posY+2,tileWidth-4,1), theme.Color(clrBorder));            //top
+    timeline->DrawRectangle(cRect(2+posX,posY+2,1,tileHeight-4), theme.Color(clrBorder));           //left
+    timeline->DrawRectangle(cRect(2+posX,posY+tileHeight-3,tileWidth-4,1), theme.Color(clrBorder));     //bottom
+    timeline->DrawRectangle(cRect(posX+tileWidth-3,posY+2,1,tileHeight-4), theme.Color(clrBorder));     //right
+    
+    if (tvguideConfig.roundedCorners) {
+        int borderRadius = 12;
+        drawRoundedCorners(posX, posY, tileWidth, tileHeight, borderRadius);
+    }
+}
+
+void cTimeLine::drawRoundedCorners(int posX, int posY, int width, int height, int radius) {
+    timeline->DrawEllipse(cRect(posX+2,posY+2,radius,radius), theme.Color(clrBorder), -2);
+    timeline->DrawEllipse(cRect(posX+1,posY+1,radius,radius), clrTransparent, -2);
+
+    timeline->DrawEllipse(cRect(posX+width-radius - 2,posY+2,radius,radius), theme.Color(clrBorder), -1);
+    timeline->DrawEllipse(cRect(posX+width-radius - 1,posY+1,radius,radius), clrTransparent, -1);
+    
+    if( height > 2*radius) {
+        timeline->DrawEllipse(cRect(posX+2,posY+height-radius - 2,radius,radius), theme.Color(clrBorder), -3);
+        timeline->DrawEllipse(cRect(posX+1,posY+height-radius - 1,radius,radius), clrTransparent, -3);
+        
+        timeline->DrawEllipse(cRect(posX+width-radius - 2,posY+height-radius - 2,radius,radius), theme.Color(clrBorder), -4);
+        timeline->DrawEllipse(cRect(posX+width-radius - 1,posY+height-radius - 1,radius,radius), clrTransparent, -4);
+    }
+}
+
+void cTimeLine::drawCurrentTimeBase(void) {
+    timeBase->Fill(clrTransparent);
+    bool nowVisible = myTime->NowVisible();
+    if (!nowVisible)
+        return;
+    int deltaTime = (myTime->GetNow() - myTime->GetStart()) / 60 * geoManager.minutePixel;
+    if (tvguideConfig.displayMode == eVertical) {
+        timeBase->DrawRectangle(cRect(0, deltaTime - 2, timeBase->ViewPort().Width(), 4), theme.Color(clrTimeBase));
+    } else {
+        timeBase->DrawRectangle(cRect(deltaTime-2, 0, 4, timeBase->ViewPort().Height()), theme.Color(clrTimeBase));
+    }
+}
+
+
 cImage *cTimeLine::createBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend) {
-	cImage *image = NULL;
-    if (tvguideConfig.useBlending == 1) {
+    cImage *image = NULL;
+    if (tvguideConfig.style == eStyleBlendingDefault) {
         image = new cImage(cSize(width, height));
         image->Fill(clrBgr);
-		int stepY = 0.5*height / 64;
-		int alpha = 0x00;
-		tColor clr;
-		for (int i = 0; i<64; i++) {
-			clr = AlphaBlend(clrBgr, clrBlend, alpha);
-			for (int y = i*stepY; y < (i+1)*stepY; y++) {
-				for (int x=0; x<width; x++) {
-					image->SetPixel(cPoint(x,y), clr);
-				}
-			}
-			alpha += 0x04;
-		}
-	} else  if (tvguideConfig.useBlending == 2) {
+        int stepY = 0.5*height / 64;
+        int alpha = 0x00;
+        tColor clr;
+        for (int i = 0; i<64; i++) {
+            clr = AlphaBlend(clrBgr, clrBlend, alpha);
+            for (int y = i*stepY; y < (i+1)*stepY; y++) {
+                for (int x=0; x<width; x++) {
+                    image->SetPixel(cPoint(x,y), clr);
+                }
+            }
+            alpha += 0x04;
+        }
+    } else  if (tvguideConfig.style == eStyleBlendingMagick) {
         cImageLoader imgLoader;
         if (imgLoader.DrawBackground(clrBgr, clrBlend, width, height)) {
             image = new cImage(imgLoader.GetImage());
@@ -105,20 +240,37 @@ cImage *cTimeLine::createBackgroundImage(int width, int height, tColor clrBgr, t
         image = new cImage(cSize(width, height));
         image->Fill(clrBgr);
     }
-	return image;
+    return image;
 }
 
 void cTimeLine::setTimeline() {
-	int offset = myTime->GetTimelineOffset();
-	timeline->SetDrawPortPoint(cPoint(0, -offset*tvguideConfig.minuteHeight));
+    int offset = myTime->GetTimelineOffset();
+    int xNew, yNew;
+    if (tvguideConfig.displayMode == eVertical) {
+        xNew = 0;
+        yNew = -offset*geoManager.minutePixel;
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        xNew = -offset*geoManager.minutePixel;
+        yNew = 0;
+    }
+    timeline->SetDrawPortPoint(cPoint(xNew, yNew));
+    if (tvguideConfig.displayTimeBase)
+        drawCurrentTimeBase();
 }
 
 void cTimeLine::drawClock() {
-	cString currentTime = myTime->GetCurrentTime();
-	int textHeight = tvguideConfig.FontTimeLineTime->Height();
-	int clockWidth = tvguideConfig.FontTimeLineTime->Width(*currentTime);
-	clock->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
-	clock->drawBackground();
-	clock->drawBorder();
-	clock->DrawText(cPoint((tvguideConfig.timeColWidth-clockWidth)/2, (tvguideConfig.footerHeight-textHeight)/2), *currentTime, theme.Color(clrFontHeader), clrTransparent, tvguideConfig.FontTimeLineTime);
+    clock->Fill(clrTransparent);
+    cString currentTime = myTime->GetCurrentTime();
+    const cFont *font = (tvguideConfig.displayMode == eVertical)?fontManager.FontTimeLineTime:fontManager.FontTimeLineTimeHorizontal;
+    int textHeight = font->Height();
+    int clockTextWidth = font->Width(*currentTime);
+    tColor colorFontBack = (tvguideConfig.style == eStyleFlat)?theme.Color(clrHeader):clrTransparent;
+    if (tvguideConfig.style == eStyleGraphical) {
+        clock->drawBackgroundGraphical(bgClock);
+    } else {
+        clock->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
+        clock->drawBackground();
+        clock->drawBorder();
+    }
+    clock->DrawText(cPoint((geoManager.clockWidth-clockTextWidth)/2, (geoManager.clockHeight-textHeight)/2), *currentTime, theme.Color(clrFont), colorFontBack, font);
 }
\ No newline at end of file
diff --git a/timeline.h b/timeline.h
index e534fa5..127b7be 100644
--- a/timeline.h
+++ b/timeline.h
@@ -1,22 +1,29 @@
 #ifndef __TVGUIDE_TIMELINE_H
 #define __TVGUIDE_TIMELINE_H
 
+#include "timer.h"
+#include "styledpixmap.h"
+
 // --- cTimeLine  -------------------------------------------------------------
 
 class cTimeLine  {
 private:
-	cMyTime *myTime;
-	cStyledPixmap *dateViewer;
-	cPixmap *timeline;
-	cStyledPixmap *clock;
-	cImage *createBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend);
+    cMyTime *myTime;
+    cStyledPixmap *dateViewer;
+    cPixmap *timeline;
+    cStyledPixmap *clock;
+    cPixmap *timeBase;
+    void decorateTile(int posX, int posY, int tileWidth, int tileHeight);
+    void drawRoundedCorners(int posX, int posY, int width, int height, int radius);
+    cImage *createBackgroundImage(int width, int height, tColor clrBgr, tColor clrBlend);
+    void drawCurrentTimeBase(void);
 public:
-	cTimeLine(cMyTime *myTime);
-	virtual ~cTimeLine(void);
-	void drawDateViewer();
-	void drawTimeline();
-	void setTimeline();
-	void drawClock();
+    cTimeLine(cMyTime *myTime);
+    virtual ~cTimeLine(void);
+    void setTimeline();
+    void drawDateViewer();
+    void drawTimeline();
+    void drawClock();
 };
 
 #endif //__TVGUIDE_TIMELINE_H
\ No newline at end of file
diff --git a/timer.c b/timer.c
index 9ec6681..59c21ec 100644
--- a/timer.c
+++ b/timer.c
@@ -1,106 +1,178 @@
+#include <time.h>
+#include <vdr/tools.h>
+#include "config.h"
 #include "timer.h"
 
 cMyTime::~cMyTime(void) {
 }
 
-void cMyTime::Now() {	
-	t = time(0);
-	tStart = t;
-	tStart = GetRounded();
-	tStop = tStart + (tvguideConfig.osdHeight - tvguideConfig.headerHeight - tvguideConfig.footerHeight)/tvguideConfig.minuteHeight*60;
+cString cMyTime::printTime(time_t displayTime) {
+    struct tm *ts;
+    ts = localtime(&displayTime);
+    cString strTime = cString::sprintf("%d.%d-%d:%d.%d", ts->tm_mday, ts->tm_mon+1, ts->tm_hour, ts->tm_min, ts->tm_sec);
+    return strTime;
+}
+
+
+void cMyTime::Now() {   
+    t = time(0);
+    tStart = t;
+    tStart = GetRounded();
+    if (tvguideConfig.displayMode == eVertical) {
+        tEnd = tStart + (geoManager.osdHeight - geoManager.statusHeaderHeight - geoManager.channelHeaderHeight - geoManager.channelGroupsHeight - geoManager.footerHeight)/geoManager.minutePixel*60;
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        tEnd = tStart + (geoManager.osdWidth - geoManager.channelHeaderWidth - geoManager.channelGroupsWidth)/geoManager.minutePixel*60;
+    }
 }
 
 void cMyTime::AddStep(int step) {
-	tStart += step*60;
-	tStop  += step*60;
+    tStart += step*60;
+    tEnd  += step*60;
 }
 
 bool cMyTime::DelStep(int step) {
-	if ((tStart - step*60)+30*60 < t) {
-		return true;
-	}
-	tStart -= step*60;
-	tStop -= step*60;
-	return false;
+    if ((tStart - step*60)+30*60 < t) {
+        return true;
+    }
+    tStart -= step*60;
+    tEnd -= step*60;
+    return false;
 }
 
 void cMyTime::SetTime(time_t newTime) {
-	tStart = newTime;
-	tStop = tStart + (tvguideConfig.osdHeight - tvguideConfig.headerHeight - tvguideConfig.footerHeight)/tvguideConfig.minuteHeight*60;
+    tStart = newTime;
+    if (tvguideConfig.displayMode == eVertical) {
+        tEnd = tStart + (geoManager.osdHeight - geoManager.statusHeaderHeight - geoManager.channelHeaderHeight - geoManager.channelGroupsHeight - geoManager.footerHeight)/geoManager.minutePixel*60;
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        tEnd = tStart + (geoManager.osdWidth - geoManager.channelHeaderWidth - geoManager.channelGroupsWidth)/geoManager.minutePixel*60;
+    }
 }
 
 time_t cMyTime::getPrevPrimetime(time_t current) {
-	tm *st = localtime(&current);
-	if (st->tm_hour < 21) {
-		current -= 24 * 60* 60;
-		st = localtime(&current);
-	}
-	st->tm_hour = 20;
-	st->tm_min = 0;
-	time_t primeTime = mktime(st);
-	return primeTime;
+    tm *st = localtime(&current);
+    if (st->tm_hour < 21) {
+        current -= 24 * 60* 60;
+        st = localtime(&current);
+    }
+    st->tm_hour = 20;
+    st->tm_min = 0;
+    time_t primeTime = mktime(st);
+    return primeTime;
 }
 
 time_t cMyTime::getNextPrimetime(time_t current){
-	tm *st = localtime(&current);
-	if (st->tm_hour > 19) {
-		current += 24 * 60* 60;
-		st = localtime(&current);
-	}
-	st->tm_hour = 20;
-	st->tm_min = 0;
-	time_t primeTime = mktime(st);
-	return primeTime;
+    tm *st = localtime(&current);
+    if (st->tm_hour > 19) {
+        current += 24 * 60* 60;
+        st = localtime(&current);
+    }
+    st->tm_hour = 20;
+    st->tm_min = 0;
+    time_t primeTime = mktime(st);
+    return primeTime;
 }
 
 bool cMyTime::tooFarInPast(time_t current) {
-	if (current < t) {
-		return true;
-	}
-	return false;
+    if (current < t) {
+        return true;
+    }
+    return false;
 }
 
 cString cMyTime::GetCurrentTime() {
-	char buf[25];
-	t = time(0);
-	tm *st = localtime(&t);
-	//snprintf(text, sizeof(text), "%d:%02d", st->tm_hour, st->tm_min);
-	if (tvguideConfig.timeFormat == e12Hours) {
-		strftime(buf, sizeof(buf), "%I:%M %p", st);
-	} else if (tvguideConfig.timeFormat == e24Hours)
-		strftime(buf, sizeof(buf), "%H:%M", st);
-	return buf;
-	
+    char buf[25];
+    t = time(0);
+    tm *st = localtime(&t);
+    //snprintf(text, sizeof(text), "%d:%02d", st->tm_hour, st->tm_min);
+    if (tvguideConfig.timeFormat == e12Hours) {
+        strftime(buf, sizeof(buf), "%I:%M %p", st);
+    } else if (tvguideConfig.timeFormat == e24Hours)
+        strftime(buf, sizeof(buf), "%H:%M", st);
+    return buf;
+    
 }
 
 cString cMyTime::GetDate() {
-	char text[6];
-	tm *st = localtime(&tStart);
-	snprintf(text, sizeof(text), "%d.%d", st->tm_mday, st->tm_mon+1);
-	return text;
+    char text[6];
+    tm *st = localtime(&tStart);
+    snprintf(text, sizeof(text), "%d.%d", st->tm_mday, st->tm_mon+1);
+    return text;
 }
 
 cString cMyTime::GetWeekday() {
-	return WeekDayName(tStart);
+    return WeekDayName(tStart);
 }
 
 int cMyTime::GetTimelineOffset() {
-	tm *st = localtime(&tStart);
-	int offset = st->tm_hour*60;
-	offset += st->tm_min;
-	return offset;
+    tm *st = localtime(&tStart);
+    int offset = st->tm_hour*60;
+    offset += st->tm_min;
+    return offset;
 }
 
 time_t cMyTime::GetRounded() {
-	tm *rounded = localtime ( &tStart );
-	rounded->tm_sec = 0;
-	if (rounded->tm_min > 29)
-		rounded->tm_min = 30;
-	else
-		rounded->tm_min = 0;
-	return mktime(rounded);
+    tm *rounded = localtime ( &tStart );
+    rounded->tm_sec = 0;
+    if (rounded->tm_min > 29)
+        rounded->tm_min = 30;
+    else
+        rounded->tm_min = 0;
+    return mktime(rounded);
 }
 
+bool cMyTime::NowVisible(void) {
+    if (t > tStart)
+        return true;
+    return false;
+}
+
+
 void cMyTime::debug() {
-	esyslog("t: %s, tStart: %s, tStop: %s", *TimeString(t), *TimeString(tStart), *TimeString(tStop));
+    esyslog("t: %s, tStart: %s, tEnd: %s", *TimeString(t), *TimeString(tStart), *TimeString(tEnd));
+}
+
+// --- cTimeInterval ------------------------------------------------------------- 
+
+cTimeInterval::cTimeInterval(time_t start, time_t stop) {
+    this->start = start;
+    this->stop = stop;
+}
+
+cTimeInterval::~cTimeInterval(void) {
 }
+
+cTimeInterval *cTimeInterval::Intersect(cTimeInterval *interval) {
+    time_t startIntersect, stopIntersect;
+    
+    if ((stop <= interval->Start()) || (interval->Stop() <= start)) {
+        return NULL;
+    }
+    
+    if (start <= interval->Start()) {
+        startIntersect = interval->Start();
+    } else {
+        startIntersect = start;
+    }
+    if (stop <= interval->Stop()) {
+        stopIntersect = stop;
+    } else {
+        stopIntersect = interval->Stop();
+    }
+    return new cTimeInterval(startIntersect, stopIntersect);
+}
+
+cTimeInterval *cTimeInterval::Union(cTimeInterval *interval) {
+    time_t startUnion, stopUnion;
+    
+    if (start <= interval->Start()) {
+        startUnion = start;
+    } else {
+        startUnion = interval->Start();
+    }
+    if (stop <= interval->Stop()) {
+        stopUnion = interval->Stop();
+    } else {
+        stopUnion = stop;
+    }
+    return new cTimeInterval(startUnion, stopUnion);
+}
\ No newline at end of file
diff --git a/timer.h b/timer.h
index b2d9aa5..6491458 100644
--- a/timer.h
+++ b/timer.h
@@ -1,32 +1,52 @@
 #ifndef __TVGUIDE_TIMER_H
 #define __TVGUIDE_TIMER_H
 
+#include <vdr/tools.h>
+
 // --- cMyTime ------------------------------------------------------------- 
 
 class cMyTime {
-	private:
-		time_t t;
-		time_t tStart;
-		time_t tStop;
-	public:
-		cMyTime(){};
-		virtual ~cMyTime(void);
-		void Now();
-		void AddStep(int step);
-		bool DelStep(int step);
-		void SetTime(time_t newTime);
-		time_t Get() {return t;};
-		time_t GetStart() {return tStart;};
-		time_t GetStop() {return tStop;};
-		cString GetCurrentTime();
-		cString GetDate();
-		cString GetWeekday();
-		time_t getPrevPrimetime(time_t current);
-		time_t getNextPrimetime(time_t current);
-		bool tooFarInPast(time_t current);
-		int GetTimelineOffset();
-		time_t GetRounded();
-		void debug();
+    private:
+        time_t t;
+        time_t tStart;
+        time_t tEnd;
+    public:
+        cMyTime(){};
+        virtual ~cMyTime(void);
+        static cString printTime(time_t displayTime);
+        void Now();
+        time_t GetNow() { return t; };
+        void AddStep(int step);
+        bool DelStep(int step);
+        void SetTime(time_t newTime);
+        time_t Get() {return t;};
+        time_t GetStart() {return tStart;};
+        time_t GetEnd() {return tEnd;};
+        cString GetCurrentTime();
+        cString GetDate();
+        cString GetWeekday();
+        time_t getPrevPrimetime(time_t current);
+        time_t getNextPrimetime(time_t current);
+        bool tooFarInPast(time_t current);
+        int GetTimelineOffset();
+        time_t GetRounded();
+        bool NowVisible(void);
+        void debug();
+};
+
+// --- cTimeInterval ------------------------------------------------------------- 
+
+class cTimeInterval {
+    private:
+        time_t start;
+        time_t stop;
+    public:
+        cTimeInterval(time_t start, time_t stop);
+        virtual ~cTimeInterval(void);
+        time_t Start(void) { return start; };
+        time_t Stop(void) { return stop; };
+        cTimeInterval *Intersect(cTimeInterval *interval);
+        cTimeInterval *Union(cTimeInterval *interval);
 };
 
 #endif //__TVGUIDE_TIMER_H
\ No newline at end of file
diff --git a/timerconflict.c b/timerconflict.c
new file mode 100644
index 0000000..e2a1fee
--- /dev/null
+++ b/timerconflict.c
@@ -0,0 +1,177 @@
+#include <string>
+#include <vector>
+#include <vdr/timers.h>
+#include "tools.h"
+#include "timer.h"
+#include "timerconflict.h"
+
+cTVGuideTimerConflict::cTVGuideTimerConflict(void) {
+    time = 0;
+    timeStart = 0;
+    timeStop = 0;
+    overlapStart = 0;
+    overlapStop = 0;
+    percentPossible = 0;
+    timerID = 0;
+}
+
+cTVGuideTimerConflict::~cTVGuideTimerConflict(void) {
+
+}
+
+bool cTVGuideTimerConflict::timerInvolved(int involvedID) {
+    int numConflicts = timerIDs.size();
+    for (int i=0; i<numConflicts; i++) {
+        if (timerIDs[i] == involvedID)
+            return true;
+    }
+    return false;
+}
+
+// --- cTVGuideTimerConflicts------------------------------------
+
+cTVGuideTimerConflicts::cTVGuideTimerConflicts(void) {
+	numConflicts = 0;
+	currentConflict = -1;
+}
+
+cTVGuideTimerConflicts::~cTVGuideTimerConflicts(void) {
+	for(std::vector<cTVGuideTimerConflict*>::const_iterator it = conflicts.begin(); it != conflicts.end(); it++) {
+        cTVGuideTimerConflict *conf = *it;
+        delete conf;
+    }
+    conflicts.clear();
+}
+
+void cTVGuideTimerConflicts::AddConflict(std::string epgSearchConflictLine) {
+	/* TIMERCONFLICT FORMAT:
+    The result list looks like this for example when we have 2 timer conflicts at one time:
+    1190232780:152|30|50#152#45:45|10|50#152#45
+    '1190232780' is the time of the conflict in seconds since 1970-01-01. 
+    It's followed by list of timers that have a conflict at this time:
+    '152|30|50#1    int editTimer(cTimer *timer, bool active, int prio, int start, int stop);
+    52#45' is the description of the first conflicting timer. Here:
+    '152' is VDR's timer id of this timer as returned from VDR's LSTT command
+    '30' is the percentage of recording that would be done (0...100)
+    '50#152#45' is the list of concurrent timers at this conflict
+    '45|10|50#152#45' describes the next conflict
+    */
+    cTVGuideTimerConflict *conflict = new cTVGuideTimerConflict();
+    splitstring s(epgSearchConflictLine.c_str());
+    std::vector<std::string> flds = s.split(':');
+    if (flds.size() < 2)
+        return;
+    conflict->time = atoi(flds[0].c_str());
+    splitstring s2(flds[1].c_str());
+    std::vector<std::string> flds2 = s2.split('|');
+    if (flds2.size() < 3)
+        return;
+    conflict->timerID = atoi(flds2[0].c_str());
+    conflict->percentPossible = atoi(flds2[1].c_str());
+    splitstring s3(flds2[2].c_str());
+    std::vector<std::string> flds3 = s3.split('#');
+    std::vector<int> timerIDs;
+    for (int k = 0; k < flds3.size(); k++) {
+        timerIDs.push_back(atoi(flds3[k].c_str()) - 1);
+    }
+    conflict->timerIDs = timerIDs;
+    conflicts.push_back(conflict);
+}
+
+void cTVGuideTimerConflicts::CalculateConflicts(void) {
+	numConflicts = conflicts.size();
+    time_t startTime = 0;
+    time_t endTime = 0;
+    for (int i=0; i < numConflicts; i++) {
+        cTimeInterval *unionSet = NULL;
+        int numTimers = conflicts[i]->timerIDs.size();
+        for (int j=0; j < numTimers; j++) {
+            const cTimer *timer = Timers.Get(conflicts[i]->timerIDs[j]);
+            if (timer) {
+                if (!unionSet) {
+                    unionSet = new cTimeInterval(timer->StartTime(), timer->StopTime());
+                } else {
+                    cTimeInterval *timerInterval = new cTimeInterval(timer->StartTime(), timer->StopTime());
+                    cTimeInterval *newUnion = unionSet->Union(timerInterval);
+                    delete unionSet;
+                    delete timerInterval;
+                    unionSet = newUnion;
+                }
+            }
+        }
+        conflicts[i]->timeStart = unionSet->Start();
+        conflicts[i]->timeStop = unionSet->Stop();
+        delete unionSet;
+        
+        cTimeInterval *intersect = NULL;
+        for (int j=0; j < numTimers; j++) {
+            const cTimer *timer = Timers.Get(conflicts[i]->timerIDs[j]);
+            if (timer) {
+                if (!intersect) {
+                    intersect = new cTimeInterval(timer->StartTime(), timer->StopTime());
+                } else {
+                    cTimeInterval *timerInterval = new cTimeInterval(timer->StartTime(), timer->StopTime());
+                    cTimeInterval *newIntersect = intersect->Intersect(timerInterval);
+                    if (newIntersect) {
+                        delete intersect;
+                        intersect = newIntersect;
+                    }
+                    delete timerInterval;
+                }
+            }
+        }
+        conflicts[i]->overlapStart = intersect->Start();
+        conflicts[i]->overlapStop = intersect->Stop();
+        delete intersect;
+    }
+}
+
+cTVGuideTimerConflict *cTVGuideTimerConflicts::GetCurrentConflict(void) {
+	if (currentConflict < 0)
+		return NULL;
+	if (currentConflict > (numConflicts-1))
+		return NULL;
+	return conflicts[currentConflict];
+}
+
+int cTVGuideTimerConflicts::GetCurrentConflictTimerID(int timerIndex) {
+	if (currentConflict < 0)
+		return -1;
+	if (currentConflict > (numConflicts-1))
+		return -1;
+	int numTimersInConflict = conflicts[currentConflict]->timerIDs.size();
+	if (timerIndex > (numTimersInConflict - 1))
+		return -1;
+	return conflicts[currentConflict]->timerIDs[timerIndex];
+}
+
+int cTVGuideTimerConflicts::GetCorrespondingConflict(int timerID) {
+    int conflictIndex = -1;
+    if (numConflicts > 0) {
+        for (int i=0; i<numConflicts; i++) {
+            if (conflicts[i]->timerInvolved(timerID)) {
+                conflictIndex = i;
+                break;
+            }
+        }
+    }
+    return conflictIndex;
+}
+
+cTVGuideTimerConflict *cTVGuideTimerConflicts::GetConflict(int conflictIndex) {
+    if (conflictIndex < 0)
+        return NULL;
+    if (conflictIndex > (numConflicts-1))
+        return NULL;
+    return conflicts[conflictIndex];
+}
+
+std::vector<cTVGuideTimerConflict*> cTVGuideTimerConflicts::GetConflictsBetween(time_t start, time_t stop) {
+    std::vector<cTVGuideTimerConflict*> conflictsFound;
+    for (int i=0; i < numConflicts; i++) {
+        if ((conflicts[i]->timeStart > start) && (conflicts[i]->timeStart < stop)||
+            (conflicts[i]->timeStop  > start) && (conflicts[i]->timeStop < stop))
+            conflictsFound.push_back(conflicts[i]);
+    }
+    return conflictsFound;
+}
\ No newline at end of file
diff --git a/timerconflict.h b/timerconflict.h
new file mode 100644
index 0000000..d3def89
--- /dev/null
+++ b/timerconflict.h
@@ -0,0 +1,38 @@
+#ifndef __TVGUIDE_TIMERCONFLICT_H
+#define __TVGUIDE_TIMERCONFLICT_H
+
+class cTVGuideTimerConflict {
+public:
+    cTVGuideTimerConflict(void);
+    virtual ~cTVGuideTimerConflict(void);
+    time_t time;
+    time_t timeStart;
+    time_t timeStop;
+    time_t overlapStart;
+    time_t overlapStop;
+    int percentPossible;
+    int timerID;
+    std::vector<int> timerIDs;
+    bool timerInvolved(int involvedID);
+};
+
+class cTVGuideTimerConflicts {
+private:
+    std::vector<cTVGuideTimerConflict*> conflicts;
+    int numConflicts;
+    int currentConflict;
+public:
+    cTVGuideTimerConflicts(void);
+    virtual ~cTVGuideTimerConflicts(void);
+    void AddConflict(std::string epgSearchConflictLine);
+    void CalculateConflicts(void);
+    int NumConflicts(void) {return numConflicts; };
+    void SetCurrentConflict(int current) { currentConflict = current; };
+    cTVGuideTimerConflict *GetCurrentConflict(void);
+    int GetCurrentConflictTimerID(int timerIndex);
+    int GetCorrespondingConflict(int timerID);
+    cTVGuideTimerConflict *GetConflict(int conflictIndex);
+    std::vector<cTVGuideTimerConflict*> GetConflictsBetween(time_t start, time_t stop);
+};
+
+#endif //__TVGUIDE_RECMMANAGER_H
\ No newline at end of file
diff --git a/tools.c b/tools.c
new file mode 100644
index 0000000..2607332
--- /dev/null
+++ b/tools.c
@@ -0,0 +1,474 @@
+#include <string>
+#include <vector>
+#include <sstream>
+#include <algorithm>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <vdr/osd.h>
+#include <vdr/plugin.h>
+#include "services/epgsearch.h"
+
+#include "tools.h"
+
+/****************************************************************************************
+*            CUTTEXT
+****************************************************************************************/
+std::string CutText(std::string text, int width, const cFont *font) {
+    if (width <= font->Size())
+        return text.c_str();
+    if (font->Width(text.c_str()) < width)
+        return text.c_str();
+    cTextWrapper twText;
+    twText.Set(text.c_str(), font, width);
+    std::string cuttedTextNative = twText.GetLine(0);
+    std::stringstream sstrText;
+    sstrText << cuttedTextNative << "...";
+    std::string cuttedText = sstrText.str();
+    int actWidth = font->Width(cuttedText.c_str());
+    if (actWidth > width) {
+        int overlap = actWidth - width;
+        int charWidth = font->Width(".");
+        if (charWidth == 0)
+            charWidth = 1;
+        int cutChars = overlap / charWidth;
+        if (cutChars > 0) {
+            cuttedTextNative = cuttedTextNative.substr(0, cuttedTextNative.length() - cutChars);
+            std::stringstream sstrText2;
+            sstrText2 << cuttedTextNative << "...";
+            cuttedText = sstrText2.str();
+        }
+    }
+    return cuttedText;
+}
+
+/****************************************************************************************
+*            StrToLowerCase
+****************************************************************************************/
+std::string StrToLowerCase(std::string str) {
+    std::string lowerCase = str;
+    const int length = lowerCase.length();
+    for(int i=0; i < length; ++i) {
+        lowerCase[i] = std::tolower(lowerCase[i]);
+    }
+    return lowerCase;
+}
+
+/****************************************************************************************
+*            GetDirectoryFromTimer
+****************************************************************************************/
+std::string GetDirectoryFromTimer(std::string file) {
+    std::string dir = "";
+    size_t found = file.find_last_of('~');
+    if (found != std::string::npos) {
+        dir = file.substr(0, found);
+    }
+    return dir;
+}
+
+/****************************************************************************************
+*            GetDirectoryFromTimer
+****************************************************************************************/
+void ReadRecordingDirectories(std::vector<std::string> *folders, cList<cNestedItem> *rootFolders, cString path) {
+    cPlugin *epgSearchPlugin = NULL;
+    epgSearchPlugin = cPluginManager::GetPlugin("epgsearch");
+    if (epgSearchPlugin) {
+        Epgsearch_services_v1_0 *epgSearch = new Epgsearch_services_v1_0;
+        if (epgSearchPlugin->Service("Epgsearch-services-v1.0", epgSearch)) {
+            std::set<std::string> epgSearchDirs = epgSearch->handler->DirectoryList();
+            std::set<std::string>::iterator it;
+            for (it = epgSearchDirs.begin(); it != epgSearchDirs.end(); it++) {
+                std::string newFolder = *it;
+                std::replace(newFolder.begin(), newFolder.end(), '/', '~');
+                folders->push_back(newFolder);
+            }
+        }
+    } else {
+        cList<cNestedItem> *foldersLevel = NULL;
+        if (rootFolders) {
+            foldersLevel = rootFolders;
+        } else {
+            foldersLevel = &Folders;
+        }
+        for (cNestedItem *folder = foldersLevel->First(); folder; folder = foldersLevel->Next(folder)) {
+            std::string strFolder = *cString::sprintf("%s%s", *path, folder->Text());
+            std::replace(strFolder.begin(), strFolder.end(), '/', '~');
+            folders->push_back(strFolder);
+            cList<cNestedItem> *subItems = folder->SubItems();
+            if (subItems) {
+                std::string strFolder2 = *cString::sprintf("%s%s", *path, folder->Text());
+                std::replace(strFolder2.begin(), strFolder2.end(), '/', '~');
+                ReadRecordingDirectories(folders, subItems, strFolder2.c_str());
+            }
+        }
+    }
+}
+
+
+/****************************************************************************************
+*            DrawRoundedCorners
+****************************************************************************************/
+void DrawRoundedCorners(cPixmap *p, int posX, int posY, int width, int height, int radius, int borderWidth, tColor borderColor) {
+    if( height > 2*radius) {
+        p->DrawEllipse(cRect(posX, posY, radius, radius), borderColor, -2);
+        p->DrawEllipse(cRect(posX - borderWidth, posY - borderWidth, radius, radius), clrTransparent, -2);
+
+        p->DrawEllipse(cRect(posX+width - radius, posY, radius, radius), borderColor, -1);
+        p->DrawEllipse(cRect(posX+width - radius + borderWidth, posY - borderWidth, radius, radius), clrTransparent, -1);
+        
+        p->DrawEllipse(cRect(posX, posY + height - radius, radius, radius), borderColor, -3);
+        p->DrawEllipse(cRect(posX - borderWidth, posY + height - radius + borderWidth, radius, radius), clrTransparent, -3);
+        
+        p->DrawEllipse(cRect(posX + width - radius, posY + height - radius, radius, radius), borderColor, -4);
+        p->DrawEllipse(cRect(posX + width - radius + borderWidth, posY + height - radius + borderWidth, radius, radius), clrTransparent, -4);
+    }
+}
+
+
+/****************************************************************************************
+*            SPLTSTRING
+****************************************************************************************/
+// split: receives a char delimiter; returns a vector of strings
+// By default ignores repeated delimiters, unless argument rep == 1.
+std::vector<std::string>& splitstring::split(char delim, int rep) {
+    if (!flds.empty()) flds.clear();  // empty vector if necessary
+    std::string work = data();
+    std::string buf = "";
+    int i = 0;
+    while (i < work.length()) {
+        if (work[i] != delim)
+            buf += work[i];
+        else if (rep == 1) {
+            flds.push_back(buf);
+            buf = "";
+        } else if (buf.length() > 0) {
+            flds.push_back(buf);
+            buf = "";
+        }
+        i++;
+    }
+    if (!buf.empty())
+        flds.push_back(buf);
+    return flds;
+}
+
+/****************************************************************************************
+*            FINDIGNORECASE
+****************************************************************************************/
+int FindIgnoreCase(const std::string& expr, const std::string& query)
+{
+  const char *p = expr.c_str();
+  const char *r = strcasestr(p, query.c_str());
+
+  if (!r)
+     return -1;
+  return r - p;
+}
+
+
+/****************************************************************************************
+*            GetAuxValue
+****************************************************************************************/
+char* GetAuxValue(const char* aux, const char* name) {
+	if (isempty(aux))
+    	return NULL;
+    
+	char* descr = strdup(aux);
+   	char* beginaux = strstr(descr, "<epgsearch>");
+   	char* endaux = strstr(descr, "</epgsearch>");
+   	if (!beginaux || !endaux) {
+        free(descr);
+    	return NULL;
+	}
+
+	beginaux +=  11;  // strlen("<epgsearch>");
+   	endaux[0] = 0;
+   	memmove(descr, beginaux, endaux - beginaux + 1);
+
+	if (strcmp(name, "epgsearch") == 0) 
+		return descr; // full aux
+
+   	int namelen = strlen(name);
+   	char catname[100] = "";
+   	catname[0] = '<';
+   	memcpy(catname + 1, name, namelen);
+   	catname[1 + namelen] = '>';
+   	catname[2 + namelen] = 0;
+
+   	char* cat = strcasestr(descr, catname);
+   	if (!cat) {
+    	free(descr);
+    	return NULL;
+    }
+      
+	cat += namelen + 2;
+   	char* end = strstr(cat, "</");
+   	if (!end) {
+    	free(descr);	
+    	return NULL;
+    }
+	end[0] = 0;
+
+   	int catlen = end - cat + 1;
+   	char* value = (char *) malloc(catlen);
+   	memcpy(value, cat, catlen);
+
+   	free(descr);
+   	return value;
+}
+
+char* GetAuxValue(const cRecording *recording, const char* name) {
+   	if (!recording || !recording->Info()) 
+        return NULL;
+    return GetAuxValue(recording->Info()->Aux(), name);
+}
+
+char* GetAuxValue(const cTimer *timer, const char* name) {
+	if (!timer || !timer->Aux()) 
+        return NULL;
+    return GetAuxValue(timer->Aux(), name);
+}
+
+/****************************************************************************************
+*            FUZZYSEARCH
+****************************************************************************************/
+
+/******************************************************************************
+FUNCTION afuzzy_init() 
+	Initialization of the fuzzy search routine. This applies to the consequent
+	calls of the afuzzy_CheckRTR (whole string matching) and afuzzy_CheckSUB
+	(substring match) routines. afuzzy_init() should be called for each
+	new pattern or error length. The search is case sensitive
+
+ARGUMENTS: 
+	p			Pattern
+	kerr		Number of possible errors. Shouldn't exceed pattern length
+	UseFilter	Use agrep filter algorithm that speeds up search.
+	fuzzy		pointer to the structure that will be later passes to Check*
+					(the first 6 elements should be NULLs for the first call)
+	
+RETURN VALUE:
+	none	
+
+ALGORITHM
+	see. the article on agrep algorithms.
+	The only change is accounting transpositions as one edit operation .
+******************************************************************************/
+void afuzzy_init(const char *p, int kerr, int UseFilter, AFUZZY *fuzzy)
+{
+	int cnt, p_len, i, j, l, d, m, dd;
+	char PatFilter[sizeof(Uint)*8 + 1];
+
+	fuzzy->k = kerr;
+	m = strlen(p);
+	fuzzy->FilterSet = 0;
+	memset(fuzzy->Map, 0 , sizeof(fuzzy->Map) );
+
+	if (fuzzy->S)
+		free(fuzzy->S);
+	if (fuzzy->R)
+		free(fuzzy->R);
+	if (fuzzy->R1)
+		free(fuzzy->R1);
+	if (fuzzy->RP)
+		free(fuzzy->RP);
+	if (fuzzy->RI)
+		free(fuzzy->RI);
+	if (fuzzy->FilterS)
+		free(fuzzy->FilterS);
+
+	fuzzy->FilterS = NULL;
+	fuzzy->S = (Uint *)calloc(m + 1, sizeof(Uint));
+	fuzzy->R = (Uint *)calloc(fuzzy->k + 1, sizeof(Uint));
+	fuzzy->R1 = (Uint *)calloc(fuzzy->k + 1, sizeof(Uint));
+	fuzzy->RI = (Uint *)calloc(fuzzy->k + 1, sizeof(Uint));
+	fuzzy->RP = (Uint *)calloc(fuzzy->k + 1, sizeof(Uint));
+
+	for (i = 0, cnt = 0; i < m; i++)
+	{
+		l = fuzzy->Map[(unsigned char)p[i]];
+		if (!l)
+		{
+			l = fuzzy->Map[(unsigned char)p[i]] = ++cnt;
+			fuzzy->S[l] = 0;
+		}
+		fuzzy->S[l] |= 1 << i;
+	}
+
+
+	for (d = 0; d <= fuzzy->k; d++)
+		fuzzy->RI[d] = (1 << d) - 1;
+
+	fuzzy->mask_ok = (1 << (m - 1));
+	fuzzy->r_size  = sizeof(Uint) * (fuzzy->k + 1);
+	p_len = m;
+
+	if (p_len > (int) sizeof(Uint)*8)
+		p_len = (int) sizeof(Uint)*8;
+
+	/* If k is zero then no filter is needed! */
+	if (fuzzy->k && (p_len >= 2*(fuzzy->k + 1)) )
+	{
+		if (UseFilter)
+		{
+			fuzzy->FilterSet = 1;
+			memset(fuzzy->FilterMap, 0 , sizeof(fuzzy->FilterMap) );
+			fuzzy->FilterS = (Uint *)calloc(m + 1, sizeof(Uint));
+
+			/* Not let's fill the interleaved pattern */
+			dd = p_len / (fuzzy->k + 1);
+			p_len  = dd * (fuzzy->k + 1);
+
+			for (i = 0, cnt = 0; i < dd; i++)
+				for (j = 0; j < fuzzy->k + 1; j++, cnt++)
+					PatFilter[cnt] = (unsigned char)p[j*dd + i];
+			PatFilter[p_len] = 0;
+
+			for (i = 0, cnt = 0; i < p_len; i++)
+			{
+				l = fuzzy->FilterMap[(unsigned char)PatFilter[i]];
+				if (!l)
+				{
+					l = fuzzy->FilterMap[(unsigned char)PatFilter[i]] = ++cnt;
+					fuzzy->FilterS[l] = 0;
+				}
+				fuzzy->FilterS[l] |= 1 << i;
+			}
+			fuzzy->filter_ok = 0;
+			for (i = p_len - fuzzy->k - 1; i <= p_len - 1; i++) /* k+1 times */
+				fuzzy->filter_ok |= 1 << i;
+
+			 /* k+1 first bits set to 1 */
+			fuzzy->filter_shift = (1 << (fuzzy->k + 2)) - 1;
+		}
+	}
+}
+
+/******************************************************************************
+FUNCTION afuzzy_free() 
+	Cleaning up after previous afuzzy_init() call.
+
+ARGUMENTS: 
+	fuzzy		pointer to the afuzzy parameters structure
+	
+RETURN VALUE:
+	none	
+******************************************************************************/
+void afuzzy_free(AFUZZY *fuzzy)
+{
+	if (fuzzy->S)
+	{
+		free(fuzzy->S);
+		fuzzy->S = NULL;
+	}
+	if (fuzzy->R)
+	{
+		free(fuzzy->R);
+		fuzzy->R = NULL;
+	}
+	if (fuzzy->R1)
+	{
+		free(fuzzy->R1);
+		fuzzy->R1 = NULL;
+	}
+	if (fuzzy->RP)
+	{
+		free(fuzzy->RP);
+		fuzzy->RP = NULL;
+	}
+	if (fuzzy->RI)
+	{
+		free(fuzzy->RI);
+		fuzzy->RI = NULL;
+	}
+	if (fuzzy->FilterS)
+	{
+		free(fuzzy->FilterS);
+		fuzzy->FilterS = NULL;
+	}
+}
+
+
+/******************************************************************************
+FUNCTION afuzzy_CheckSUB() 
+	Perform a fuzzy pattern substring matching. afuzzy_init() should be 
+	called previously to initialize the pattern and error length. 
+	Positive result means that some part of the string given matches the 
+	pattern with no more than afuzzy->k errors (1 error = 1 letter 
+	replacement or transposition)
+
+ARGUMENTS: 
+	t			the string to test
+	fuzzy		pointer to the afuzzy parameters structure
+
+RETURN VALUE:
+	0	- no match
+	> 0	- strings match
+
+ALGORITHM
+	????????????????
+******************************************************************************/
+int afuzzy_checkSUB(const char *t, AFUZZY *fuzzy)
+{
+	register char c;
+	register int j, d;
+
+	/* For eficciency this case should be little bit optimized */
+	if (!fuzzy->k)
+	{
+		Uint R = 0, R1;
+
+		for (j = 0; (c = t[j]) != '\0'; j++)
+		{
+			R1 = ( ((R<<1) | 1) & fuzzy->S[fuzzy->Map[(unsigned char)c]]);
+			R = R1;
+
+			if (R1 & fuzzy->mask_ok)
+				return 1;
+		} /* end for (register int j = 0 ... */
+		return 0;
+	}
+
+	if (fuzzy->FilterSet && !afuzzy_checkFLT(t, fuzzy))
+		return 0;
+
+	memcpy(fuzzy->R, fuzzy->RI, fuzzy->r_size); /* R = RI */
+
+	for (j = 0; (c = t[j]); j++)
+	{
+		for (d = 0; d <= fuzzy->k; d++)
+		{
+			fuzzy->R1[d] = (((fuzzy->R[d]<<1) | 1) & 
+										fuzzy->S[fuzzy->Map[(unsigned char)c]]);
+			if (d > 0)
+				fuzzy->R1[d] |= ((fuzzy->R[d-1] | fuzzy->R1[d-1])<<1) | 1 | 
+															fuzzy->R[d-1];
+		}
+		if (fuzzy->R1[fuzzy->k] & fuzzy->mask_ok)
+			return j;
+
+		memcpy(fuzzy->R, fuzzy->R1, fuzzy->r_size);
+
+	} /* end for (register int j = 0 ... */
+
+	return 0;
+}
+
+static int afuzzy_checkFLT(const char *t, AFUZZY *fuzzy)
+{
+	register Uint FilterR = 0;
+	register Uint FilterR1;
+	register int j;
+
+	for (j = 0; t[j] != '\0'; j++)
+	{
+		FilterR1 = ( ((FilterR<<(fuzzy->k+1)) | fuzzy->filter_shift) & 
+						fuzzy->FilterS[fuzzy->FilterMap[(unsigned char)t[j]]]);
+		if (FilterR1 & fuzzy->filter_ok)
+			return 1;
+		FilterR = FilterR1;
+	} /* end for (register int j = 0 ... */
+
+	return 0;
+}
diff --git a/tools.h b/tools.h
new file mode 100644
index 0000000..f401ea4
--- /dev/null
+++ b/tools.h
@@ -0,0 +1,68 @@
+#ifndef __TVGUIDETOOLS_H
+#define __TVGUIDETOOLS_H
+
+#include <string>
+#include <vector>
+#include <vdr/font.h>
+#include <vdr/recording.h>
+
+std::string CutText(std::string text, int width, const cFont *font);
+std::string StrToLowerCase(std::string str);
+std::string GetDirectoryFromTimer(std::string file);
+void ReadRecordingDirectories(std::vector<std::string> *folders, cList<cNestedItem> *rootFolders, cString path);
+void DrawRoundedCorners(cPixmap *p, int posX, int posY, int width, int height, int radius, int borderWidth, tColor borderColor);
+
+class splitstring : public std::string {
+    std::vector<std::string> flds;
+public:
+    splitstring(const char *s) : std::string(s) { };
+    std::vector<std::string>& split(char delim, int rep=0);
+};
+
+int FindIgnoreCase(const std::string& expr, const std::string& query);
+
+char* GetAuxValue(const char* aux, const char* name);
+char* GetAuxValue(const cRecording *recording, const char* name);
+char* GetAuxValue(const cTimer* timer, const char* name);
+
+#ifndef _AFUZZY_H
+#define _AFUZZY_H
+
+// source from:
+/*
+  Leonid Boitsov 2002. (itman at narod.ru)
+  C version of Stas Namin.
+  This code is a GPL software and is distributed under GNU
+  public licence without any warranty.
+*/
+
+typedef unsigned int Uint;
+
+#define MaxPatSize (sizeof(Uint) * 8)
+
+typedef struct
+{
+	Uint 		*R,
+				*R1,
+				*RP,
+				*S,
+				*RI;
+	Uint 		*FilterS;
+
+	int 		Map[256];
+	int 		FilterMap[256];
+	int			k;
+	Uint		mask_ok;
+	Uint		filter_ok;
+	Uint		filter_shift;
+	int			r_size;
+	int			FilterSet;
+} AFUZZY;
+
+void afuzzy_init(const char *p, int kerr, int UseFilter, AFUZZY *fuzzy);
+void afuzzy_free(AFUZZY *fuzzy);
+int afuzzy_checkSUB(const char *t, AFUZZY *fuzzy);
+static int afuzzy_checkFLT(const char *t, AFUZZY *fuzzy);
+#endif
+
+#endif // __TVGUIDETOOLS_H
\ No newline at end of file
diff --git a/tvguide.c b/tvguide.c
index 3a27d41..029166d 100644
--- a/tvguide.c
+++ b/tvguide.c
@@ -11,23 +11,26 @@
 #include <vdr/osd.h>
 #include <vdr/plugin.h>
 #include <vdr/device.h>
+#include <vdr/menu.h>
 
-#include "tvguideosd.c"
-
-#if defined(APIVERSNUM) && APIVERSNUM < 10717
-#error "VDR-1.7.17 API version or greater is required!"
-#endif
+#define DEFINE_CONFIG 1
+#include "geometrymanager.h"
+#include "fontmanager.h"
+#include "imagecache.h"
+#include "config.h"
+#include "setup.h"
+#include "tvguideosd.h"
 
 
+#if defined(APIVERSNUM) && APIVERSNUM < 20000
+#error "VDR-2.0.0 API version or greater is required!"
+#endif
 
-static const char *VERSION        = "0.0.2";
+static const char *VERSION        = "1.2.2";
 static const char *DESCRIPTION    = "A fancy 2d EPG Viewer";
 static const char *MAINMENUENTRY  = "Tvguide";
 
 class cPluginTvguide : public cPlugin {
-private:
-  bool logoPathSet;
-  bool imagesPathSet;
 public:
   cPluginTvguide(void);
   virtual ~cPluginTvguide();
@@ -42,7 +45,7 @@ public:
   virtual void MainThreadHook(void);
   virtual cString Active(void);
   virtual time_t WakeupTime(void);
-  virtual const char *MainMenuEntry(void) { return MAINMENUENTRY; }
+  virtual const char *MainMenuEntry(void) { return (tvguideConfig.showMainMenuEntry)?MAINMENUENTRY:NULL; }
   virtual cOsdObject *MainMenuAction(void);
   virtual cMenuSetupPage *SetupMenu(void);
   virtual bool SetupParse(const char *Name, const char *Value);
@@ -51,144 +54,107 @@ public:
   virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode);
   };
 
-cPluginTvguide::cPluginTvguide(void)
-{
-  // Initialize any member variables here.
-  // DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL
-  // VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT!
-  logoPathSet = false;
-  imagesPathSet = false;
+cPluginTvguide::cPluginTvguide(void) {
 }
 
-cPluginTvguide::~cPluginTvguide()
-{
-  // Clean up after yourself!
+cPluginTvguide::~cPluginTvguide() {
 }
 
-const char *cPluginTvguide::CommandLineHelp(void)
-{
-  // Return a string that describes all known command line options.
+const char *cPluginTvguide::CommandLineHelp(void) {
     return 
-         "  -i <IMAGESDIR>, --epgimages=<IMAGESDIR> Set directory where epgimages are stored\n"
+         "  -e <IMAGESDIR>, --epgimages=<IMAGESDIR> Set directory where epgimages are stored.\n"
+	       "  -i <ICONDIR>, --icons=<ICONDIR>         Set directory where icons are stored.\n"
          "  -l <LOGODIR>, --logodir=<LOGODIR>       Set directory where logos are stored.\n";
 }
 
-bool cPluginTvguide::ProcessArgs(int argc, char *argv[])
-{
-  // Implement command line argument processing here if applicable.
+bool cPluginTvguide::ProcessArgs(int argc, char *argv[]) {
   static const struct option long_options[] = {
-    { "epgimages", required_argument, NULL, 'i' },
+    { "epgimages", required_argument, NULL, 'e' },
+    { "iconpath", required_argument, NULL, 'i' },
     { "logopath", required_argument, NULL, 'l' },
     { 0, 0, 0, 0 }
   };
-
   int c;
-  cString *path = NULL;
-  while ((c = getopt_long(argc, argv, "i:f:l:", long_options, NULL)) != -1) {
-	switch (c) {
-      case 'i':
-		path = new cString(optarg);
-        tvguideConfig.SetImagesPath(*path);
-        imagesPathSet = true;
+  while ((c = getopt_long(argc, argv, "e:i:l:", long_options, NULL)) != -1) {
+    switch (c) {
+      case 'e':
+        tvguideConfig.SetImagesPath(cString(optarg));
         break;
+      case 'i':
+      	tvguideConfig.SetIconsPath(cString(optarg));
+	      break;
       case 'l':
-		path = new cString(optarg);
-        tvguideConfig.SetLogoPath(*path);
-        logoPathSet = true;
+        tvguideConfig.SetLogoPath(cString(optarg));
         break;
       default:
         return false;
     }
-	if (path) 
-		delete path;
   }
   return true;
 }
 
-bool cPluginTvguide::Initialize(void)
-{
-  // Initialize any background activities the plugin shall perform.
-  return true;
+bool cPluginTvguide::Initialize(void) {
+    tvguideConfig.SetDefaultPathes();
+    tvguideConfig.LoadTheme();
+    tvguideConfig.SetStyle();
+    tvguideConfig.setDynamicValues();
+    geoManager.SetGeometry(cOsd::OsdWidth(), cOsd::OsdHeight());
+    fontManager.SetFonts();
+    imgCache.CreateCache();
+    return true;
 }
 
-bool cPluginTvguide::Start(void)
-{
-	if (!logoPathSet) {
-		cString path = cString::sprintf("%s/channellogos/", cPlugin::ConfigDirectory(PLUGIN_NAME_I18N));
-		tvguideConfig.SetLogoPath(path);
-		logoPathSet = true;
-	}
-	
-	if (!imagesPathSet) {
-		cString path = cString::sprintf("%s/epgimages/", cPlugin::ConfigDirectory(PLUGIN_NAME_I18N));
-		tvguideConfig.SetImagesPath(path);
-		logoPathSet = true;
-	}
-	return true;
+bool cPluginTvguide::Start(void) {
+    return true;
 }
 
-void cPluginTvguide::Stop(void)
-{
-  // Stop any background activities the plugin is performing.
+void cPluginTvguide::Stop(void) {
 }
 
-void cPluginTvguide::Housekeeping(void)
-{
-  // Perform any cleanup or other regular tasks.
+void cPluginTvguide::Housekeeping(void) {
 }
 
-void cPluginTvguide::MainThreadHook(void)
-{
-  // Perform actions in the context of the main program thread.
-  // WARNING: Use with great care - see PLUGINS.html!
+void cPluginTvguide::MainThreadHook(void) {
 }
 
-cString cPluginTvguide::Active(void)
-{
-  // Return a message string if shutdown should be postponed
+cString cPluginTvguide::Active(void) {
   return NULL;
 }
 
-time_t cPluginTvguide::WakeupTime(void)
-{
-  // Return custom wakeup time for shutdown script
+time_t cPluginTvguide::WakeupTime(void) {
   return 0;
 }
 
-cOsdObject *cPluginTvguide::MainMenuAction(void)
-{
-  // Perform the action when selected from the main VDR menu.
-  return new cTvGuideOsd;
+cOsdObject *cPluginTvguide::MainMenuAction(void) {
+    return new cTvGuideOsd;
 }
 
-cMenuSetupPage *cPluginTvguide::SetupMenu(void)
-{
-  // Return a setup menu in case the plugin supports one.
+cMenuSetupPage *cPluginTvguide::SetupMenu(void) {
   return new cTvguideSetup();
 }
 
-bool cPluginTvguide::SetupParse(const char *Name, const char *Value)
-{
-  // Parse your own setup parameters and store their values.
+bool cPluginTvguide::SetupParse(const char *Name, const char *Value) {
   return tvguideConfig.SetupParse(Name, Value);
 }
 
-bool cPluginTvguide::Service(const char *Id, void *Data)
-{
-  // Handle custom service requests from other plugins
+bool cPluginTvguide::Service(const char *Id, void *Data) {
+  if (strcmp(Id, "MainMenuHooksPatch-v1.0::osSchedule") == 0 && tvguideConfig.replaceOriginalSchedule != 0) {
+      if (Data == NULL)
+         return true;
+      cOsdObject **guide = (cOsdObject**) Data;
+      if (guide)
+         *guide = MainMenuAction();
+      return true;
+  }
   return false;
 }
 
-const char **cPluginTvguide::SVDRPHelpPages(void)
-{
-  // Return help text for SVDRP commands this plugin implements
+const char **cPluginTvguide::SVDRPHelpPages(void) {
   return NULL;
 }
 
-cString cPluginTvguide::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode)
-{
-  // Process SVDRP commands this plugin implements
+cString cPluginTvguide::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) {
   return NULL;
 }
 
-VDRPLUGINCREATOR(cPluginTvguide); // Don't touch this!
+VDRPLUGINCREATOR(cPluginTvguide);
diff --git a/tvguideosd.c b/tvguideosd.c
index b127fdd..9770d82 100644
--- a/tvguideosd.c
+++ b/tvguideosd.c
@@ -1,542 +1,717 @@
-// --- Theme -------------------------------------------------------------
-static cTheme theme;
-
-THEME_CLR(theme, clrBackgroundOSD, clrBlack);
-THEME_CLR(theme, clrBackground, clrBlack);
-THEME_CLR(theme, clrGrid1, 0xFF404749);
-THEME_CLR(theme, clrGrid1Blending, 0xFF000000);
-THEME_CLR(theme, clrGrid2, 0xFF20293F);
-THEME_CLR(theme, clrGrid2Blending, 0xFF000000);
-THEME_CLR(theme, clrHighlight, 0xFFFF4D00);
-THEME_CLR(theme, clrHighlightBlending, 0xFF000000);
-THEME_CLR(theme, clrFont, clrWhite);
-THEME_CLR(theme, clrFontHeader, clrWhite);
-THEME_CLR(theme, clrFontButtons, clrWhite);
-THEME_CLR(theme, clrHeader, clrBlack);
-THEME_CLR(theme, clrHeaderBlending, 0xFFE0E0E0);
-THEME_CLR(theme, clrBorder, clrWhite);
-THEME_CLR(theme, clrTimeline1, clrWhite);
-THEME_CLR(theme, clrTimeline1Blending, 0xFF828282);
-THEME_CLR(theme, clrTimeline2, clrBlack);
-THEME_CLR(theme, clrTimeline2Blending, 0xFF3F3F3F);
-THEME_CLR(theme, clrButtonRed, 0x99BB0000);
-THEME_CLR(theme, clrButtonRedBorder, 0xFFBB0000);
-THEME_CLR(theme, clrButtonGreen, 0x9900BB00);
-THEME_CLR(theme, clrButtonGreenBorder, 0xFF00BB00);
-THEME_CLR(theme, clrButtonYellow, 0x99BBBB00);
-THEME_CLR(theme, clrButtonYellowBorder, 0xFFBBBB00);
-THEME_CLR(theme, clrButtonBlue, 0x990000BB);
-THEME_CLR(theme, clrButtonBlueBorder, 0xFF0000BB);
-THEME_CLR(theme, clrButtonBlend, 0xDD000000);
-
-#include "config.c"
-cTvguideConfig tvguideConfig;
-
-#include "osdmanager.c"
-cOsdManager osdManager;
-
-#include "setup.c"
-#include "imageloader.c"
-#include "styledpixmap.c"
-#include "timer.c"
-#include "messagebox.c"
-#include "timeline.c"
-#include "epggrid.c"
-#include "detailview.c"
-#include "channelcolumn.c"
-#include "footer.c"
+#include <stdlib.h>
+#include <vector>
+
+#include "config.h"
+#include "services/epgsearch.h"
+#include "services/remotetimers.h"
+
+#include "tools.h"
+#include "setup.h"
 
 #include "tvguideosd.h"
-#include <stdlib.h>
 
 cTvGuideOsd::cTvGuideOsd(void) {
-	detailView = NULL;
-	detailViewActive = false;
-	timeLine = NULL;
+    detailView = NULL;
+    detailViewActive = false;
+    activeGrid = NULL;
+    timeLine = NULL;
+    recMenuManager = NULL;
+    channelJumper = NULL;
 }
 
 cTvGuideOsd::~cTvGuideOsd() {
-	delete myTime;
-	columns.Clear();
-	if (detailView)
-		delete detailView;
-	delete timeLine;
-	delete footer;
-	cMessageBox::Destroy();
-	osdManager.deleteOsd();
+    delete myTime;
+    columns.Clear();
+    if (tvguideConfig.displayStatusHeader) {
+        delete statusHeader;
+    }
+    if (detailView)
+        delete detailView;
+    delete timeLine;
+    delete channelGroups;
+    delete footer;
+    delete recMenuManager;
+    if (channelJumper)
+        delete channelJumper;
+    osdManager.deleteOsd();
 }
 
 void cTvGuideOsd::Show(void) {
-	int start = cTimeMs::Now();
-	bool ok = false;
-	ok = osdManager.setOsd();
-	if (ok) {
-		tvguideConfig.setDynamicValues(osdManager.Width(), osdManager.Height());
-		tvguideConfig.loadTheme();
-		osdManager.setBackground();
-		myTime = new cMyTime();
-		myTime->Now();
-		drawOsd();
-	}
-	esyslog("tvguide: Rendering took %d ms", int(cTimeMs::Now()-start));
+    int start = cTimeMs::Now();
+    bool ok = false;
+    ok = osdManager.setOsd();
+    if (ok) {
+        bool themeChanged = tvguideConfig.LoadTheme();
+        tvguideConfig.SetStyle();
+        tvguideConfig.setDynamicValues();
+        bool geoChanged = geoManager.SetGeometry(cOsd::OsdWidth(), cOsd::OsdHeight());
+        if (themeChanged || geoChanged) {
+            fontManager.DeleteFonts();
+            fontManager.SetFonts();
+            imgCache.Clear();
+            imgCache.CreateCache();
+        }
+        osdManager.setBackground();
+        myTime = new cMyTime();
+        myTime->Now();
+        SwitchTimers.Load(AddDirectory(cPlugin::ConfigDirectory("epgsearch"), "epgsearchswitchtimers.conf"));
+        recMenuManager = new cRecMenuManager();
+        pRemoteTimers = cPluginManager::CallFirstService("RemoteTimers::RefreshTimers-v1.0", NULL);
+        if (pRemoteTimers) {
+            isyslog("tvguide: remotetimers-plugin is available");
+        }
+        if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+            cString errorMsg;
+            if (!pRemoteTimers->Service("RemoteTimers::RefreshTimers-v1.0", &errorMsg)) {
+                esyslog("tvguide: %s", *errorMsg);
+            }
+        }
+        drawOsd();
+    }
+    esyslog("tvguide: Rendering took %d ms", int(cTimeMs::Now()-start));
 }
 
 void cTvGuideOsd::drawOsd() {
-	cPixmap::Lock();
-	cChannel *startChannel = Channels.GetByNumber(cDevice::CurrentChannel());
-	timeLine = new cTimeLine(myTime);
-	timeLine->drawDateViewer();
-	timeLine->drawTimeline();
-	timeLine->drawClock();
-	footer = new cFooter();
-	footer->drawRedButton();
-	footer->drawGreenButton();
-	footer->drawYellowButton();
-	footer->drawBlueButton();
-	osdManager.flush();
-	readChannels(startChannel);
-	drawGridsChannelJump();
-	osdManager.flush();
-	cPixmap::Unlock();
-}
-
-void cTvGuideOsd::readChannels(cChannel *channelStart) {
-	int i=0;
-	columns.Clear();
-	if (!channelStart)
-		return;
-	for (cChannel *channel = channelStart; channel; channel = Channels.Next(channel)) {
-      if (!channel->GroupSep()) {
-		cChannelColumn *column = new cChannelColumn(i, channel, myTime);
-		if (column->readGrids()) {
-			columns.Add(column);
-			i++;
-		} else {
-			delete column;
-		}
-	  }
-	  if (i == tvguideConfig.channelCols)
-	    break;
-    }
-}
-
-bool cTvGuideOsd::readChannelsReverse(cChannel *channelStart) {
-	bool doUpdate = false;
-	int i = tvguideConfig.channelCols;
-	if (!channelStart)
-		return false;
-	for (cChannel *channel = Channels.Prev(channelStart); channel; channel = Channels.Prev(channel)) {
-      if (!channel->GroupSep()) {
-		cChannelColumn *column = new cChannelColumn(i-1, channel, myTime);
-		if (column->readGrids()) {
-			if (i == tvguideConfig.channelCols) {
-				columns.Clear();
-				doUpdate = true;
-			}
-			columns.Ins(column, columns.First());
-			i--;
-		} else {
-			delete column;
-		}
-	  }
-	  if (i == 0)
-	    break;
-    }
-	return doUpdate;
-}
-
-void cTvGuideOsd::drawGridsChannelJump() {
-	if (columns.Count() == 0)
-		return;
-	activeGrid = columns.First()->getActive();
-	if (activeGrid)
-		activeGrid->SetActive();
-	for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
-		column->createHeader();
-		column->drawGrids();
-	}
+    cPixmap::Lock();
+    cChannel *startChannel = Channels.GetByNumber(cDevice::CurrentChannel());
+    int numBack = tvguideConfig.numGrids / 2;
+    int offset = 0;
+    const cChannel *newStartChannel = startChannel;
+    for (; newStartChannel ; newStartChannel = Channels.Prev(newStartChannel)) {
+        if (newStartChannel && !newStartChannel->GroupSep()) {
+            offset++;
+        }
+        if (offset == numBack)
+            break;
+    }
+    if (!newStartChannel)
+        newStartChannel = Channels.First();
+    offset--;
+    if (offset < 0)
+        offset = 0;
+    
+    if (tvguideConfig.displayStatusHeader) {
+        statusHeader = new cStatusHeader();
+        statusHeader->Draw();
+        statusHeader->ScaleVideo();
+    }
+    timeLine = new cTimeLine(myTime);
+    timeLine->drawDateViewer();
+    timeLine->drawTimeline();
+    timeLine->drawClock();
+    channelGroups = new cChannelGroups();
+    channelGroups->ReadChannelGroups();
+    footer = new cFooter(channelGroups);
+    recMenuManager->SetFooter(footer);
+    footer->drawRedButton();
+    if (tvguideConfig.channelJumpMode == eNumJump) {
+        footer->drawGreenButton();
+        footer->drawYellowButton();
+    }
+    footer->drawBlueButton(false);
+    osdManager.flush();
+    readChannels(newStartChannel);
+    drawGridsChannelJump(offset);
+    osdManager.flush();
+    cPixmap::Unlock();
+}
+
+void cTvGuideOsd::readChannels(const cChannel *channelStart) {
+    int i=0;
+    bool foundEnough = false;
+    columns.Clear();
+    if (!channelStart)
+        return;
+    for (const cChannel *channel = channelStart; channel; channel = Channels.Next(channel)) {
+        if (!channel->GroupSep()) {
+            if (channelGroups->IsInLastGroup(channel)) {
+                break;
+            }
+            cChannelColumn *column = new cChannelColumn(i, channel, myTime);
+            if (column->readGrids()) {
+                columns.Add(column);
+                i++;
+            } else {
+                delete column;
+            }
+        }
+        if (i == tvguideConfig.numGrids) {
+            foundEnough = true;
+            break;
+        }
+    }
+    if (!foundEnough) {
+        int numCurrent = columns.Count();
+        int numBack = tvguideConfig.numGrids - numCurrent;
+        int newChannelNumber = columns.First()->getChannel()->Number() - numBack;
+        const cChannel *newStart = Channels.GetByNumber(newChannelNumber);
+        readChannels(newStart);
+    }
+}
+
+void cTvGuideOsd::drawGridsChannelJump(int offset) {
+    if (columns.Count() == 0)
+        return;
+    activeGrid = columns.Get(offset)->getActive();
+    if (activeGrid)
+        activeGrid->SetActive();
+    if (tvguideConfig.displayStatusHeader) {
+        statusHeader->DrawInfoText(activeGrid);
+    }
+    if (activeGrid && (tvguideConfig.channelJumpMode == eGroupJump)) {
+        footer->UpdateGroupButtons(activeGrid->column->getChannel());
+    }
+    if (tvguideConfig.displayChannelGroups) {
+        channelGroups->DrawChannelGroups(columns.First()->getChannel(), columns.Last()->getChannel());
+    }
+    for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
+        column->createHeader();
+        column->drawGrids();
+    }
 }
 
 void cTvGuideOsd::drawGridsTimeJump() {
-	if (columns.Count() == 0)
-		return;
-	cChannelColumn *colActive = NULL;
-	if (activeGrid) {
-		colActive = activeGrid->column;
-	} else {
-		colActive = columns.First();
-	}
-	for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
-		column->clearGrids();
-		column->readGrids();
-		column->drawGrids();
-	}
-	activeGrid = colActive->getActive();
-	if (activeGrid) {
-		activeGrid->SetActive();
-		activeGrid->Draw();
-	}
-}
-
-void cTvGuideOsd::setNextActiveGrid(cEpgGrid *next) {
-	if (!next || !activeGrid) {
-		return;
-	}
-	activeGrid->SetInActive();
-	activeGrid->Draw();	
-	activeGrid = next;
-	activeGrid->SetActive();
-	activeGrid->Draw();
+    if (columns.Count() == 0)
+        return;
+    cChannelColumn *colActive = NULL;
+    if (activeGrid) {
+        colActive = activeGrid->column;
+    } else {
+        colActive = columns.First();
+    }
+    for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
+        column->clearGrids();
+        column->readGrids();
+        column->drawGrids();
+    }
+    activeGrid = colActive->getActive();
+    if (activeGrid) {
+        activeGrid->SetActive();
+        activeGrid->Draw();
+        if (tvguideConfig.displayStatusHeader) {
+            statusHeader->DrawInfoText(activeGrid);
+        }
+    }
 }
 
-void cTvGuideOsd::processKeyUp() {
-	if (detailViewActive) {
-		detailView->scrollUp();
-	} else {
-		if (activeGrid == NULL) {
-			ScrollBack();
-			//Search for new active Grid
-			cEpgGrid *actGrid = NULL;
-			for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
-				actGrid = column->getActive();
-				if (actGrid) {
-					activeGrid = actGrid;
-					activeGrid->SetActive();
-					activeGrid->Draw();
-					break;
-				}
-			}
-		} else if (activeGrid->StartTime() <= myTime->GetStart()) {
-			activeGrid->debug();
-			ScrollBack();
-		} else {
-			cEpgGrid *prev = NULL;
-			prev = activeGrid->column->getPrev(activeGrid);
-			if (prev) {
-				setNextActiveGrid(prev);
-			} else {
-				ScrollBack();
-				prev = activeGrid->column->getPrev(activeGrid);
-				if (prev) {
-					setNextActiveGrid(prev);
-				}
-			}
-		}
-	}
-	osdManager.flush();
+void cTvGuideOsd::setNextActiveGrid(cGrid *next) {
+    if (!next || !activeGrid) {
+        return;
+    }
+    activeGrid->SetInActive();
+    activeGrid->Draw(); 
+    activeGrid = next;
+    activeGrid->SetActive();
+    activeGrid->Draw();
+    if (tvguideConfig.displayStatusHeader) {
+        statusHeader->DrawInfoText(activeGrid);
+    }
 }
 
-void cTvGuideOsd::processKeyDown() {
-	if (detailViewActive) {
-		detailView->scrollDown();
-	} else {
-		if (activeGrid == NULL) {
-			ScrollForward();
-		} else if (activeGrid->EndTime() > myTime->GetStop()) {
-			ScrollForward();
-		} else {
-			cEpgGrid *next = NULL;
-			next = activeGrid->column->getNext(activeGrid);
-			if (next) {
-				setNextActiveGrid(next);
-			} else {
-				ScrollForward();
-				next = activeGrid->column->getNext(activeGrid);
-				if (next) {
-					setNextActiveGrid(next);
-				}
-			}
-		}
-	}
-	osdManager.flush();
+void cTvGuideOsd::channelForward() {
+    cChannelColumn *colRight = columns.Next(activeGrid->column);
+    bool colAdded = false;
+    if (!colRight) {
+        const cChannel *channelRight = activeGrid->column->getChannel();
+        while (channelRight = Channels.Next(channelRight)) {
+            if (!channelRight->GroupSep()) {
+                if (channelGroups->IsInLastGroup(channelRight)) {
+                    break;
+                }
+                colRight = new cChannelColumn(tvguideConfig.numGrids - 1, channelRight, myTime);
+                if (colRight->readGrids()) {
+                    break;
+                } else {
+                    delete colRight;
+                    colRight = NULL;
+                }
+            }
+        }
+        if (colRight) {
+            colAdded = true;
+            if (columns.Count() == tvguideConfig.numGrids) {
+                cChannelColumn *cFirst = columns.First();
+                columns.Del(cFirst);
+            }
+            for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
+                column->SetNum(column->GetNum() - 1);
+                column->drawHeader();
+                column->drawGrids();
+            }
+            columns.Add(colRight);
+            colRight->createHeader();
+            colRight->drawGrids();
+        }
+    }
+    if (colRight) {
+        cGrid *right = colRight->getNeighbor(activeGrid);
+        if (right) {
+            setNextActiveGrid(right);
+        }
+    }
+    if (tvguideConfig.displayChannelGroups && colAdded) {
+        channelGroups->DrawChannelGroups(columns.First()->getChannel(), columns.Last()->getChannel());
+    }
+    if (activeGrid && (tvguideConfig.channelJumpMode == eGroupJump)) {
+        footer->UpdateGroupButtons(activeGrid->column->getChannel());
+    }
+    osdManager.flush();
+}
+
+void cTvGuideOsd::channelBack() {
+    cChannelColumn *colLeft = columns.Prev(activeGrid->column);
+    bool colAdded = false;
+    if (!colLeft) {
+        const cChannel *channelLeft = activeGrid->column->getChannel();
+        while (channelLeft = Channels.Prev(channelLeft)) {
+            if (!channelLeft->GroupSep()) {
+                colLeft = new cChannelColumn(0, channelLeft, myTime);
+                if (colLeft->readGrids()) {
+                    break;
+                } else {
+                    delete colLeft;
+                    colLeft = NULL;
+                }
+            }
+        }
+        if (colLeft) {
+            colAdded = true;
+            if (columns.Count() == tvguideConfig.numGrids) {
+                cChannelColumn *cLast = columns.Last();
+                columns.Del(cLast);
+            }
+            for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
+                column->SetNum(column->GetNum() + 1);
+                column->drawHeader();
+                column->drawGrids();
+            }
+            columns.Ins(colLeft, columns.First());
+            colLeft->createHeader();
+            colLeft->drawGrids();
+        }
+    }
+
+    if (colLeft) {
+        cGrid *left = colLeft->getNeighbor(activeGrid);
+        if (left) {
+            setNextActiveGrid(left);
+        }
+    }
+    if (tvguideConfig.displayChannelGroups && colAdded) {
+        channelGroups->DrawChannelGroups(columns.First()->getChannel(), columns.Last()->getChannel());
+    }
+
+    if (activeGrid && (tvguideConfig.channelJumpMode == eGroupJump)) {
+        footer->UpdateGroupButtons(activeGrid->column->getChannel());
+    }
+    osdManager.flush();
+}
+
+void cTvGuideOsd::timeForward() {
+    bool actionDone = false;
+    if ( (myTime->GetEnd() - activeGrid->EndTime())/60 < 30 ) {
+        ScrollForward();
+        actionDone = true;
+    }
+    cGrid *next = activeGrid->column->getNext(activeGrid);
+    if (next) {
+        if (   (next->EndTime() < myTime->GetEnd())
+            || ( (myTime->GetEnd() - next->StartTime())/60 > 30 ) ) {
+            setNextActiveGrid(next);
+            actionDone = true;
+        }
+    }
+    if (!actionDone) {
+        ScrollForward();
+    }
+    osdManager.flush();
 }
 
 void cTvGuideOsd::ScrollForward() {
-	myTime->AddStep(tvguideConfig.stepMinutes);
-	timeLine->drawDateViewer();
-	timeLine->drawClock();
-	timeLine->setTimeline();
-	for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
-		column->AddNewGridsAtEnd();
-		column->ClearOutdatedStart();
-		column->drawGrids();
-	}
+    myTime->AddStep(tvguideConfig.stepMinutes);
+    timeLine->drawDateViewer();
+    timeLine->drawClock();
+    timeLine->setTimeline();
+    for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
+        column->AddNewGridsAtEnd();
+        column->ClearOutdatedStart();
+        column->drawGrids();
+    }
+}
+
+void cTvGuideOsd::timeBack() {
+    bool actionDone = false;
+    if ( (activeGrid->StartTime() - myTime->GetStart())/60 < 30 ) {
+        ScrollBack();
+        actionDone = true;
+    }
+    cGrid *prev = activeGrid->column->getPrev(activeGrid);
+    if (prev) {
+        if (   (prev->StartTime() > myTime->GetStart())
+            || ( (prev->EndTime() - myTime->GetStart())/60 > 30 )
+            || ( prev->isFirst()) ) {
+            setNextActiveGrid(prev);
+            actionDone = true;
+        }
+    }
+    if (!actionDone) {
+        ScrollBack();
+    }
+    osdManager.flush();
 }
 
 void cTvGuideOsd::ScrollBack() {
-	bool tooFarInPast = myTime->DelStep(tvguideConfig.stepMinutes);
-	if (tooFarInPast)
-		return;
-	timeLine->drawDateViewer();
-	timeLine->drawClock();
-	timeLine->setTimeline();
-	for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
-		column->AddNewGridsAtStart();
-		column->ClearOutdatedEnd();
-		column->drawGrids();
-	}	
+    bool tooFarInPast = myTime->DelStep(tvguideConfig.stepMinutes);
+    if (tooFarInPast)
+        return;
+    timeLine->drawDateViewer();
+    timeLine->drawClock();
+    timeLine->setTimeline();
+    for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
+        column->AddNewGridsAtStart();
+        column->ClearOutdatedEnd();
+        column->drawGrids();
+    }   
+}
+
+void cTvGuideOsd::processKeyUp() {
+    if (!activeGrid) {
+        return;
+    }
+    if (tvguideConfig.displayMode == eVertical) {
+        timeBack();
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        channelBack();
+    }
+}
+
+void cTvGuideOsd::processKeyDown() {
+    if (!activeGrid) {
+            return;
+    }
+    if (tvguideConfig.displayMode == eVertical) {
+        timeForward();
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        channelForward();
+    }
 }
 
 void cTvGuideOsd::processKeyLeft() {
-	if (detailViewActive)
-		return;
-	if (activeGrid == NULL)
-		return;
-	cChannelColumn *colLeft = columns.Prev(activeGrid->column);
-	if (!colLeft) {
-		cChannel *channelLeft = activeGrid->column->getChannel();
-		while (channelLeft = Channels.Prev(channelLeft)) {
-			if (!channelLeft->GroupSep()) {
-				colLeft = new cChannelColumn(0, channelLeft, myTime);
-				if (colLeft->readGrids()) {
-					break;
-				} else {
-					delete colLeft;
-					colLeft = NULL;
-				}
-			}
-		}
-		if (colLeft) {
-			if (columns.Count() == tvguideConfig.channelCols) {
-				cChannelColumn *cLast = columns.Last();
-				columns.Del(cLast);
-			}
-			for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
-				column->SetNum(column->GetNum() + 1);
-				column->drawHeader();
-				column->drawGrids();
-			}
-			columns.Ins(colLeft, columns.First());
-			colLeft->createHeader();
-			colLeft->drawGrids();
-		}
-	}
-
-	if (colLeft) {
-		cEpgGrid *left = colLeft->getNeighbor(activeGrid);
-		if (left) {
-			setNextActiveGrid(left);
-		}
-	}
-	osdManager.flush();
+    if (activeGrid == NULL)
+        return;
+    if (tvguideConfig.displayMode == eVertical) {
+        channelBack();
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        timeBack();
+    }
 }
 
 void cTvGuideOsd::processKeyRight() {
-	if (detailViewActive)
-		return;
-	if (activeGrid == NULL)
-		return;
-	cChannelColumn *colRight = columns.Next(activeGrid->column);
-	if (!colRight) {
-		cChannel *channelRight = activeGrid->column->getChannel();
-		while (channelRight = Channels.Next(channelRight)) {
-			if (!channelRight->GroupSep()) {
-				colRight = new cChannelColumn(tvguideConfig.channelCols - 1, channelRight, myTime);
-				if (colRight->readGrids()) {
-					break;
-				} else {
-					delete colRight;
-					colRight = NULL;
-				}
-			}
-		}
-		if (colRight) {
-			if (columns.Count() == tvguideConfig.channelCols) {
-				cChannelColumn *cFirst = columns.First();
-				columns.Del(cFirst);
-			}
-			for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
-				column->SetNum(column->GetNum() - 1);
-				column->drawHeader();
-				column->drawGrids();
-			}
-			columns.Add(colRight);
-			colRight->createHeader();
-			colRight->drawGrids();
-		}
-	}
-	if (colRight) {
-		cEpgGrid *right = colRight->getNeighbor(activeGrid);
-		if (right) {
-			setNextActiveGrid(right);
-		}
-	}
-	osdManager.flush();
-}
-
-void cTvGuideOsd::processKeyOk() {
-	if (detailViewActive) {
-		delete detailView;
-		detailView = NULL;
-		detailViewActive = false;
-		osdManager.flush();
-	} else {
-		detailViewActive = true;
-		detailView = new cDetailView(activeGrid);
-		detailView->Start();
-	}
+    if (activeGrid == NULL)
+        return;
+    if (tvguideConfig.displayMode == eVertical) {
+        channelForward();
+    } else if (tvguideConfig.displayMode == eHorizontal) {
+        timeForward();
+    }
 }
 
 void cTvGuideOsd::processKeyRed() {
-	if (activeGrid == NULL)
-		return;
-    cTimer *timer = new cTimer(activeGrid->GetEvent());
-    cTimer *t = Timers.GetTimer(timer);
-	cString msg;
-	if (t) {
-        isyslog("timer %s already exists", *timer->ToDescr());
-		delete timer;
-		msg = cString::sprintf(tr("Timer not set! There is already a timer for this item."));
-    } else {
-        Timers.Add(timer);
-        Timers.SetModified();
-		msg = cString::sprintf("%s:\n%s (%s) %s - %s", tr("Timer set"), activeGrid->GetEvent()->Title(), timer->Channel()->Name(), *DayDateTime(timer->StartTime()), *TimeString(timer->StopTime()));
-		timer->SetEvent(activeGrid->GetEvent());
-		activeGrid->setTimer();
-		activeGrid->column->setTimer();
-		activeGrid->SetDirty();
-		activeGrid->Draw();
-		osdManager.flush();
-        isyslog("timer %s added (active)", *timer->ToDescr());
-    }
-	cMessageBox::Start(4000, msg);
+    if  ((activeGrid == NULL) || activeGrid->isDummy())
+        return;
+    recMenuManager->Start(activeGrid->GetEvent());
 }
 
 void cTvGuideOsd::processKeyGreen() {
-	if (activeGrid == NULL)
-		return;
-	cChannel *currentChannel = activeGrid->column->getChannel();
-	bool doUpdate = readChannelsReverse(currentChannel);
-	if (doUpdate && (columns.Count() > 0)) {
-		drawGridsChannelJump();
-	}
-	osdManager.flush();
+    if (activeGrid == NULL)
+        return;
+    
+    const cChannel *currentChannel = activeGrid->column->getChannel();
+    const cChannel *firstChannel = columns.First()->getChannel();
+    int currentCol = activeGrid->column->GetNum();
+    const cChannel *prev = NULL;
+    
+    if (tvguideConfig.channelJumpMode == eGroupJump) {
+        int prevNum = channelGroups->GetPrevGroupChannelNumber(currentChannel);
+        if (prevNum) {
+            prev = Channels.GetByNumber(prevNum);
+        }    
+    } else if (tvguideConfig.channelJumpMode == eNumJump) {
+        int i = tvguideConfig.jumpChannels + 1;
+        for (const cChannel *channel = firstChannel; channel; channel = Channels.Prev(channel)) {
+            if (!channel->GroupSep()) {
+                prev = channel;
+                i--;
+            }
+            if (i == 0)
+                break;
+        }
+    }
+    if (prev) {
+        readChannels(prev);
+        if (columns.Count() > 0) {
+            if (tvguideConfig.channelJumpMode == eGroupJump)
+                drawGridsChannelJump();
+            else
+                drawGridsChannelJump(currentCol);
+        }
+        osdManager.flush();
+    }
 }
 
 void cTvGuideOsd::processKeyYellow() {
-	if (activeGrid == NULL)
-		return;
-	cChannel *currentChannel = activeGrid->column->getChannel();
-	cChannel *next = NULL;
-	int i=0;
-	for (cChannel *channel = currentChannel; channel; channel = Channels.Next(channel)) {
-		if (!channel->GroupSep()) {
-			next = channel;
-			i++;
-		}
-		if (i == (tvguideConfig.jumpChannels+1))
-			break;
-    }
-	if (next) {
-		readChannels(next);
-		if (columns.Count() > 0) {
-			drawGridsChannelJump();
-		}
-		osdManager.flush();
-	}
-}
-
-eOSState cTvGuideOsd::processKeyBlue() {
-	if (activeGrid == NULL)
-		return osContinue;
-	cChannel *currentChannel = activeGrid->column->getChannel();
-	if (currentChannel) {
-		cDevice::PrimaryDevice()->SwitchChannel(currentChannel, true);
-		return osEnd;
-	}
-	return osContinue;
-}
-
-void cTvGuideOsd::processKey1() {
-	bool tooFarInPast = myTime->DelStep(tvguideConfig.bigStepHours*60);
-	if (tooFarInPast)
-		return;
-	drawGridsTimeJump();
-	timeLine->drawDateViewer();
-	timeLine->drawClock();
-	timeLine->setTimeline();
-	osdManager.flush();
-}
-
-void cTvGuideOsd::processKey3() {
-	myTime->AddStep(tvguideConfig.bigStepHours*60);
-	drawGridsTimeJump();
-	timeLine->drawDateViewer();
-	timeLine->drawClock();
-	timeLine->setTimeline();
-	osdManager.flush();
-}
-
-void cTvGuideOsd::processKey4() {
-	bool tooFarInPast = myTime->DelStep(tvguideConfig.hugeStepHours*60);
-	if (tooFarInPast)
-		return;
-	drawGridsTimeJump();
-	timeLine->drawDateViewer();
-	timeLine->drawClock();
-	timeLine->setTimeline();
-	osdManager.flush();
-}
-
-void cTvGuideOsd::processKey6() {
-	myTime->AddStep(tvguideConfig.hugeStepHours*60);
-	drawGridsTimeJump();
-	timeLine->drawDateViewer();
-	timeLine->drawClock();
-	timeLine->setTimeline();
-	osdManager.flush();
-}
-
-void cTvGuideOsd::processKey7() {
-	cMyTime *primeChecker = new cMyTime();
-	primeChecker->Now();
-	time_t prevPrime = primeChecker->getPrevPrimetime(myTime->GetStart());
-	if (primeChecker->tooFarInPast(prevPrime))
-		return;
-	myTime->SetTime(prevPrime);
-	drawGridsTimeJump();
-	timeLine->drawDateViewer();
-	timeLine->drawClock();
-	timeLine->setTimeline();
-	osdManager.flush();
-}
-
-void cTvGuideOsd::processKey9() {
-	cMyTime *primeChecker = new cMyTime();
-	time_t nextPrime = primeChecker->getNextPrimetime(myTime->GetStart());
-	myTime->SetTime(nextPrime);
-	drawGridsTimeJump();
-	timeLine->drawDateViewer();
-	timeLine->drawClock();
-	timeLine->setTimeline();
-	osdManager.flush();
+    if (activeGrid == NULL)
+        return;
+    const cChannel *currentChannel = activeGrid->column->getChannel();
+    int currentCol = activeGrid->column->GetNum();
+    const cChannel *firstChannel = columns.First()->getChannel();
+    const cChannel *next = NULL;
+    
+    if (tvguideConfig.channelJumpMode == eGroupJump) {
+        int nextNum = channelGroups->GetNextGroupChannelNumber(currentChannel);
+        if (nextNum) {
+            next = Channels.GetByNumber(nextNum);
+        }    
+    } else if (tvguideConfig.channelJumpMode == eNumJump) {
+        int i=0;
+        for (const cChannel *channel = firstChannel; channel; channel = Channels.Next(channel)) {
+            if (channelGroups->IsInLastGroup(channel)) {
+                break;
+            }
+            if (!channel->GroupSep()) {
+                next = channel;
+                i++;
+            }
+            if (i == (tvguideConfig.jumpChannels+1)) {
+                break;
+            }
+        }
+    }
+    if (next) {
+        readChannels(next);
+        if (columns.Count() > 0) {
+            if (tvguideConfig.channelJumpMode == eGroupJump)
+                drawGridsChannelJump();
+            else
+                drawGridsChannelJump(currentCol);
+        }
+        osdManager.flush();
+    }
+}
+
+eOSState cTvGuideOsd::processKeyBlue(bool *alreadyUnlocked) {
+    if (tvguideConfig.blueKeyMode == eBlueKeySwitch) {
+        return ChannelSwitch(alreadyUnlocked);
+    } else if (tvguideConfig.blueKeyMode == eBlueKeyEPG) {
+        DetailedEPG();
+    } else if (tvguideConfig.blueKeyMode == eBlueKeyFavorites) {
+        recMenuManager->StartFavorites();
+    }
+    return osContinue;
+}
+
+eOSState cTvGuideOsd::processKeyOk(bool *alreadyUnlocked) {
+    if (tvguideConfig.blueKeyMode == eBlueKeySwitch) {
+        DetailedEPG();
+    } else if (tvguideConfig.blueKeyMode == eBlueKeyEPG) {
+        return ChannelSwitch(alreadyUnlocked);
+    } else if (tvguideConfig.blueKeyMode == eBlueKeyFavorites) {
+        DetailedEPG();
+    }
+    return osContinue;
+}
+
+eOSState cTvGuideOsd::ChannelSwitch(bool *alreadyUnlocked) {
+    if (activeGrid == NULL)
+        return osContinue;
+    const cChannel *currentChannel = activeGrid->column->getChannel();
+    if (currentChannel) {
+        cPixmap::Unlock();
+        *alreadyUnlocked = true;
+        cDevice::PrimaryDevice()->SwitchChannel(currentChannel, true);
+        if (tvguideConfig.closeOnSwitch) {
+            if (detailView) {
+                delete detailView;
+                detailView = NULL;
+                detailViewActive = false;
+            }
+            return osEnd;
+        }
+    }
+    return osContinue;
+}
+
+void cTvGuideOsd::DetailedEPG() {
+    if (!activeGrid->isDummy()) {
+        detailViewActive = true;
+        detailView = new cDetailView(activeGrid->GetEvent(), footer);
+        footer->SetDetailedViewMode();
+        osdManager.flush();
+        detailView->Start();
+        osdManager.flush();
+    }
+}
+
+void cTvGuideOsd::processNumKey(int numKey) {
+    if (tvguideConfig.numkeyMode == 0) {
+        //timely jumps with 1,3,4,6,7,9
+        TimeJump(numKey);
+    } else {
+        //jump to specific channel
+        ChannelJump(numKey);
+    }
+}
+
+void cTvGuideOsd::TimeJump(int mode) {
+    switch (mode) {
+        case 1: {
+            bool tooFarInPast = myTime->DelStep(tvguideConfig.bigStepHours*60);
+            if (tooFarInPast)
+                return;
+        }
+            break;
+        case 3: {
+            myTime->AddStep(tvguideConfig.bigStepHours*60);
+        }
+            break;
+        case 4: {
+            bool tooFarInPast = myTime->DelStep(tvguideConfig.hugeStepHours*60);
+            if (tooFarInPast)
+                return;
+        }
+            break;
+        case 6: {
+            myTime->AddStep(tvguideConfig.hugeStepHours*60);
+        }
+            break;
+        case 7: {
+            cMyTime primeChecker;
+            primeChecker.Now();
+            time_t prevPrime = primeChecker.getPrevPrimetime(myTime->GetStart());
+            if (primeChecker.tooFarInPast(prevPrime))
+                return;
+            myTime->SetTime(prevPrime);
+        }
+            break;
+        case 9: {
+            cMyTime primeChecker;
+            time_t nextPrime = primeChecker.getNextPrimetime(myTime->GetStart());
+            myTime->SetTime(nextPrime);
+        }
+            break;
+        default:
+            return;
+    }
+    drawGridsTimeJump();
+    timeLine->drawDateViewer();
+    timeLine->drawClock();
+    timeLine->setTimeline();
+    osdManager.flush();
+}
+
+void cTvGuideOsd::ChannelJump(int num) {
+    if (!channelJumper) {
+        channelJumper = new cChannelJump(channelGroups);
+    }
+    channelJumper->Set(num);
+    channelJumper->DrawText();
+    osdManager.flush();
+}
+
+void cTvGuideOsd::CheckTimeout(void) {
+    if (!channelJumper)
+        return;
+    if (channelJumper->TimeOut()) {
+        int newChannelNum = channelJumper->GetChannel(); 
+        delete channelJumper;
+        channelJumper = NULL;
+        const cChannel *newChannel = Channels.GetByNumber(newChannelNum);
+        if (newChannel) {
+            readChannels(newChannel);
+            if (columns.Count() > 0) {
+                drawGridsChannelJump();
+            }
+        }
+        osdManager.flush();
+    }
+}
+
+void cTvGuideOsd::SetTimers() {
+    for (cChannelColumn *column = columns.First(); column; column = columns.Next(column)) {
+        column->SetTimers();
+    }
 }
 
 eOSState cTvGuideOsd::ProcessKey(eKeys Key) {
-	eOSState state = cOsdObject::ProcessKey(Key);
-	if (state == osUnknown) {
-		cPixmap::Lock();
-		state = osContinue;
-		switch (Key & ~k_Repeat) {
-			case kUp:     	processKeyUp(); break;
-			case kDown:   	processKeyDown(); break;
-			case kLeft:   	processKeyLeft(); break;
-			case kRight:  	processKeyRight(); break;
-			case kRed:    	processKeyRed(); break;
-			case kGreen:  	processKeyGreen(); break;
-			case kYellow: 	processKeyYellow(); break;
-			case kBlue:   	state = processKeyBlue(); break;
-			case kOk:     	processKeyOk(); break;
-			case kBack:	 	state=osEnd; break;
-			case k1:		processKey1(); break;
-			case k3:		processKey3(); break;
-			case k4:		processKey4(); break;
-			case k6:		processKey6(); break;
-			case k7:		processKey7(); break;
-			case k9:		processKey9(); break;
-			default: 	 	break;
-		}
-		cPixmap::Unlock();
-	}
-	return state;
-}
\ No newline at end of file
+    eOSState state = osContinue;
+    cPixmap::Lock();
+    bool alreadyUnlocked = false;
+    if (recMenuManager->isActive()) {
+        state = recMenuManager->ProcessKey(Key);
+        if (state == osEnd) {
+            SetTimers();                
+            osdManager.flush();
+        }
+        state = osContinue;
+    } else if (detailViewActive) {
+        if ((Key & ~k_Repeat) == kRed) {
+            delete detailView;
+            detailView = NULL;
+            detailViewActive = false;
+            processKeyRed();
+        } else if ((Key & ~k_Repeat) == kBlue) {
+            delete detailView;
+            detailView = NULL;
+            detailViewActive = false;
+            if ((tvguideConfig.blueKeyMode == eBlueKeySwitch) || (tvguideConfig.blueKeyMode == eBlueKeyFavorites)) {
+                state = ChannelSwitch(&alreadyUnlocked);
+            } else {
+                osdManager.flush();
+                state = osContinue;
+            }
+        } else if ((Key & ~k_Repeat) == kOk && (tvguideConfig.blueKeyMode == eBlueKeyEPG)) {
+            delete detailView;
+            detailView = NULL;
+            detailViewActive = false;
+            state = ChannelSwitch(&alreadyUnlocked);
+        } else {
+            state = detailView->ProcessKey(Key);
+            if (state == osEnd) {
+                delete detailView;
+                detailView = NULL;
+                detailViewActive = false;
+                osdManager.flush();
+                state = osContinue;
+            }
+        }
+    } else {
+        switch (Key & ~k_Repeat) {
+            case kUp:       processKeyUp(); break;
+            case kDown:     processKeyDown(); break;
+            case kLeft:     processKeyLeft(); break;
+            case kRight:    processKeyRight(); break;
+            case kRed:      processKeyRed(); break;
+            case kGreen:    processKeyGreen(); break;
+            case kYellow:   processKeyYellow(); break;
+            case kBlue:     state = processKeyBlue(&alreadyUnlocked); break;
+            case kOk:       state = processKeyOk(&alreadyUnlocked); break;
+            case kBack:     state=osEnd; break;    
+            case k0 ... k9: processNumKey(Key - k0); break;
+            case kNone:     if (channelJumper) CheckTimeout(); break;
+            default:        break;
+        }
+    }
+    if (!alreadyUnlocked) {
+        cPixmap::Unlock();
+    }
+    return state;
+}
+
+void cTvGuideOsd::dump() {
+    esyslog("tvguide: ------Dumping Content---------");
+    activeGrid->debug();
+    int i=1;
+    for (cChannelColumn *col = columns.First(); col; col = columns.Next(col)) {
+        col->dumpGrids();
+    }
+}
diff --git a/tvguideosd.h b/tvguideosd.h
index c619ec4..1e6a990 100644
--- a/tvguideosd.h
+++ b/tvguideosd.h
@@ -1,21 +1,35 @@
 #ifndef __TVGUIDE_TVGUIDEOSD_H
 #define __TVGUIDE_TVGUIDEOSD_H
 
+#include "timer.h"
+#include "grid.h"
+#include "channelcolumn.h"
+#include "statusheader.h"
+#include "detailview.h"
+#include "timeline.h"
+#include "channelgroups.h"
+#include "footer.h"
+#include "recmenumanager.h"
+#include "channeljump.h"
+
 // --- cTvGuideOsd -------------------------------------------------------------
 
 class cTvGuideOsd : public cOsdObject {
 private:
   cMyTime *myTime;
   cList<cChannelColumn> columns;
-  cEpgGrid *activeGrid;
+  cGrid *activeGrid;
+  cStatusHeader *statusHeader;
   cDetailView *detailView;
   cTimeLine *timeLine;
+  cChannelGroups *channelGroups;
   cFooter *footer;
+  cRecMenuManager *recMenuManager;
+  cChannelJump *channelJumper;
   bool detailViewActive;
   void drawOsd();
-  void readChannels(cChannel *channelStart);
-  bool readChannelsReverse(cChannel *channelStart);
-  void drawGridsChannelJump();
+  void readChannels(const cChannel *channelStart);
+  void drawGridsChannelJump(int offset = 0);
   void drawGridsTimeJump();
   void processKeyUp();
   void processKeyDown();
@@ -24,17 +38,23 @@ private:
   void processKeyRed();
   void processKeyGreen();
   void processKeyYellow();
-  eOSState processKeyBlue();
-  void processKeyOk();
-  void processKey1();
-  void processKey3();
-  void processKey4();
-  void processKey6();
-  void processKey7();
-  void processKey9();
-  void setNextActiveGrid(cEpgGrid *next);
+  eOSState processKeyBlue(bool *alreadyUnlocked);
+  eOSState processKeyOk(bool *alreadyUnlocked);
+  void processNumKey(int numKey);
+  void TimeJump(int mode);
+  void ChannelJump(int num);
+  void CheckTimeout(void);
+  void setNextActiveGrid(cGrid *next);
+  void channelForward();
+  void channelBack();
+  void timeForward();
+  void timeBack();
   void ScrollForward();
   void ScrollBack();
+  eOSState ChannelSwitch(bool *alreadyUnlocked);
+  void DetailedEPG();
+  void SetTimers();
+  void dump();
 public:
   cTvGuideOsd(void);
   virtual ~cTvGuideOsd(void);
@@ -42,4 +62,4 @@ public:
   virtual eOSState ProcessKey(eKeys Key);
 };
 
-#endif //__TVGUIDE_TVGUIDEOSD_H
\ No newline at end of file
+#endif //__TVGUIDE_TVGUIDEOSD_H
diff --git a/view.c b/view.c
new file mode 100644
index 0000000..7608c03
--- /dev/null
+++ b/view.c
@@ -0,0 +1,1046 @@
+#include "detailview.h"
+
+/********************************************************************************************
+* cView
+********************************************************************************************/
+
+cView::cView(void) {
+    activeView = 0;
+    scrollable = false;
+    tabbed = false;
+    font = NULL;
+    fontSmall = NULL;
+    fontHeader = NULL;
+    fontHeaderLarge = NULL;
+    pixmapBackground = NULL;
+    pixmapHeader = NULL;
+    pixmapHeaderLogo = NULL;
+    pixmapContent = NULL;
+    pixmapTabs = NULL;
+    pixmapScrollbar = NULL;
+    pixmapScrollbarBack = NULL;
+    imgScrollBar = NULL;
+    title = "";
+    subTitle = "";
+    dateTime = "";
+    infoText = "";
+    channel = NULL;
+    eventID = 0;
+    event = NULL;
+    x = 0;
+    y = 0;
+    width = 0;
+    height = 0;
+    border = 0;
+    headerHeight = 0;
+    contentHeight = 0;
+    tabHeight = 0;
+    headerDrawn = false;
+}
+
+cView::~cView(void) {
+    if (pixmapBackground)
+        osdManager.releasePixmap(pixmapBackground);
+    if (pixmapHeader)
+        delete pixmapHeader;
+    if (pixmapHeaderLogo)
+        osdManager.releasePixmap(pixmapHeaderLogo);   
+    if (pixmapContent)
+        osdManager.releasePixmap(pixmapContent);
+    if (pixmapTabs)
+        osdManager.releasePixmap(pixmapTabs);
+    if (pixmapScrollbar)
+        osdManager.releasePixmap(pixmapScrollbar);
+    if (pixmapScrollbarBack)
+        osdManager.releasePixmap(pixmapScrollbarBack);
+    if (imgScrollBar)
+        delete imgScrollBar;
+}
+
+void cView::SetFonts(void) {
+    font = fontManager.FontDetailView;
+    fontSmall = fontManager.FontDetailViewSmall;
+    fontHeaderLarge = fontManager.FontDetailHeaderLarge;
+    fontHeader = fontManager.FontDetailHeader;
+}
+
+void cView::SetGeometry(void) { 
+    x = 0;
+    y = 0;
+    scrollbarWidth = 40;
+    width = geoManager.osdWidth - scrollbarWidth;
+    height = geoManager.osdHeight;
+    border = tvguideConfig.epgViewBorder;
+    headerWidth = geoManager.headerContentWidth;
+    headerHeight = geoManager.epgViewHeaderHeight;
+    if (tabbed)
+        tabHeight = font->Height() * 3 / 2;
+    contentHeight = height - headerHeight - tabHeight - geoManager.footerHeight;
+}
+
+void cView::DrawHeader(void) {
+    if (!pixmapHeader) {
+        pixmapHeader = new cStyledPixmap(osdManager.requestPixmap(5, cRect(0, 0, headerWidth, headerHeight)));
+        pixmapHeader->setColor(theme.Color(clrHeader), theme.Color(clrHeaderBlending));
+    }
+    if (!pixmapHeaderLogo) {
+        pixmapHeaderLogo = osdManager.requestPixmap(6, cRect(0, 0, width, headerHeight));
+    }
+    pixmapHeader->Fill(clrTransparent);
+    pixmapHeaderLogo->Fill(clrTransparent);
+    if (tvguideConfig.style == eStyleGraphical) {
+        if (tvguideConfig.scaleVideo) {
+            pixmapHeader->drawBackgroundGraphical(bgStatusHeaderWindowed);
+        } else {
+            pixmapHeader->drawBackgroundGraphical(bgStatusHeaderFull);
+        }
+    } else {
+        pixmapHeader->drawBackground();
+        pixmapHeader->drawBoldBorder();
+    }
+    //Channel Logo
+    int logoHeight = 2 * headerHeight / 3;
+    int logoWidth = logoHeight * tvguideConfig.logoWidthRatio / tvguideConfig.logoHeightRatio;
+    int xText = border / 2;
+    if (channel && !tvguideConfig.hideChannelLogos) {
+        cImageLoader imgLoader;
+        if (imgLoader.LoadLogo(channel, logoWidth, logoHeight)) {
+            cImage logo = imgLoader.GetImage();
+            pixmapHeaderLogo->DrawImage(cPoint(border/2, (headerHeight - logoHeight)/2), logo);
+            xText += logoWidth + border / 2;
+        }
+    }
+    //Date and Time, Title, Subtitle
+    int yDateTime = border / 2;
+    int yTitle = (headerHeight - fontHeaderLarge->Height()) / 2;
+    int ySubtitle = headerHeight - fontHeader->Height() - border / 3;
+    int textWidthMax = headerWidth - xText;
+    pixmapHeader->DrawText(cPoint(xText, yDateTime), CutText(dateTime, textWidthMax, fontHeader).c_str(), theme.Color(clrFont), theme.Color(clrStatusHeader), fontHeader);
+    pixmapHeader->DrawText(cPoint(xText, yTitle), CutText(title, textWidthMax, fontHeaderLarge).c_str(), theme.Color(clrFont), theme.Color(clrStatusHeader), fontHeaderLarge);
+    pixmapHeader->DrawText(cPoint(xText, ySubtitle), CutText(subTitle, textWidthMax, fontHeader).c_str(), theme.Color(clrFont), theme.Color(clrStatusHeader), fontHeader);
+    //REC Icon
+    eTimerMatch timerMatch=tmNone; 
+    cTimer *ti;
+    if (!event)
+        return;
+    if (tvguideConfig.useRemoteTimers && pRemoteTimers) {
+        RemoteTimers_GetMatch_v1_0 rtMatch;
+        rtMatch.event = event;
+        pRemoteTimers->Service("RemoteTimers::GetMatch-v1.0", &rtMatch);
+        timerMatch = (eTimerMatch)rtMatch.timerMatch;
+        ti = rtMatch.timer;
+    } else {
+        ti=Timers.GetMatch(event, &timerMatch);
+    }
+    if (timerMatch == tmFull) {
+        cString recIconText(" REC ");
+        int widthIcon = fontManager.FontDetailHeader->Width(*recIconText);
+        int height = fontManager.FontDetailHeader->Height()+10;
+        int posX = headerWidth - widthIcon - 20;
+        int posY = 20;
+        pixmapHeader->DrawRectangle( cRect(posX, posY, widthIcon, height), theme.Color(clrButtonRed));
+        pixmapHeader->DrawText(cPoint(posX, posY+5), *recIconText, theme.Color(clrFont), theme.Color(clrButtonRed), fontManager.FontDetailHeader);
+    }
+}
+
+void cView::DrawTabs(void) {
+    if (!pixmapTabs) {
+        pixmapTabs = osdManager.requestPixmap(4, cRect(0, y + headerHeight + contentHeight, width + scrollbarWidth, tabHeight));
+    }
+    tColor bgColor = theme.Color(clrTabInactive);
+    pixmapTabs->Fill(clrTransparent);
+    pixmapTabs->DrawRectangle(cRect(0, 0, width, 2), bgColor);
+    int numTabs = tabs.size();
+    int xCurrent = 0;
+    for (int tab = 0; tab < numTabs; tab++) {
+        std::string tabText = tabs[tab];
+        int textWidth = font->Width(tabText.c_str());
+        int tabWidth = textWidth + border;
+        pixmapTabs->DrawRectangle(cRect(xCurrent, (tab == activeView) ? 0 : 2, tabWidth - 2, tabHeight), bgColor);
+        pixmapTabs->DrawEllipse(cRect(xCurrent, tabHeight - border/2, border/2, border/2), clrTransparent, -3);
+        pixmapTabs->DrawEllipse(cRect(xCurrent + tabWidth - border / 2 - 2, tabHeight - border/2, border/2, border/2), clrTransparent, -4);
+        if (tab == activeView) {
+            pixmapTabs->DrawRectangle(cRect(xCurrent + 2, 0, tabWidth - 6, tabHeight - border/2 - 1), clrTransparent);
+            pixmapTabs->DrawRectangle(cRect(xCurrent + border / 2, tabHeight - border/2 - 1, tabWidth - border, border/2 - 1), clrTransparent);
+            pixmapTabs->DrawEllipse(cRect(xCurrent + 2, tabHeight - border/2 - 2, border/2, border/2), clrTransparent, 3);
+            pixmapTabs->DrawEllipse(cRect(xCurrent + tabWidth - border / 2 - 4, tabHeight - border/2 - 2, border/2, border/2), clrTransparent, 4);
+        }
+        pixmapTabs->DrawText(cPoint(xCurrent + (tabWidth - textWidth) / 2, 2 + (tabHeight - font->Height())/2), tabText.c_str(), theme.Color(clrFont), (tab == activeView) ? clrTransparent : bgColor, font);
+        xCurrent += tabWidth;
+    }
+}
+
+void cView::ClearContent(void) {
+    if (pixmapContent && Running()) {
+        osdManager.releasePixmap(pixmapContent);
+        pixmapContent = NULL;
+    }
+    if (pixmapBackground && Running()) {
+        osdManager.releasePixmap(pixmapBackground);
+        pixmapBackground = NULL;
+    }
+}
+
+void cView::CreateContent(int fullHeight) {
+    scrollable = false;
+    pixmapBackground = osdManager.requestPixmap(3, cRect(x, y + headerHeight, width + scrollbarWidth, contentHeight + tabHeight));
+    pixmapBackground->Fill(theme.Color(clrBackground));
+
+    int drawPortHeight = contentHeight; 
+    if (fullHeight > contentHeight) {
+        drawPortHeight = fullHeight;
+        scrollable = true;
+    }
+    pixmapContent = osdManager.requestPixmap(4, cRect(x, y + headerHeight, width, contentHeight), cRect(0, 0, width, drawPortHeight));
+    pixmapContent->Fill(clrTransparent);
+}
+
+void cView::DrawContent(std::string *text) {
+    cTextWrapper wText;
+    wText.Set(text->c_str(), font, width - 2 * border);
+    int lineHeight = font->Height();
+    int textLines = wText.Lines();
+    int textHeight = lineHeight * textLines + 2*border;
+    int yText = border;
+    CreateContent(textHeight);
+    for (int i=0; i < textLines; i++) {
+        pixmapContent->DrawText(cPoint(border, yText), wText.GetLine(i), theme.Color(clrFont), clrTransparent, font);
+        yText += lineHeight;
+    }
+}
+
+void cView::DrawFloatingContent(std::string *infoText, cTvMedia *img, cTvMedia *img2) {
+    cTextWrapper wTextTall;
+    cTextWrapper wTextFull;
+    int imgWidth = img->width;
+    int imgHeight = img->height;
+    int imgWidth2 = 0;
+    int imgHeight2 = 0;
+    if (imgHeight > (contentHeight - 2 * border)) {
+        imgHeight = contentHeight - 2 * border;
+        imgWidth = imgWidth * ((double)imgHeight / (double)img->height);
+    }
+    int imgHeightTotal = imgHeight;
+    if (img2) {
+        imgWidth2 = imgWidth;
+        imgHeight2 = img2->height * ((double)img2->width / (double)imgWidth2);
+        imgHeightTotal += img2->height + border;
+    }
+    CreateFloatingTextWrapper(&wTextTall, &wTextFull, infoText, imgWidth, imgHeightTotal);
+    int lineHeight = font->Height();
+    int textLinesTall = wTextTall.Lines();
+    int textLinesFull = wTextFull.Lines();
+    int textHeight = lineHeight * (textLinesTall + textLinesFull) + 2*border;
+    int yText = border;
+    CreateContent(max(textHeight, imgHeight + 2*border));
+    for (int i=0; i < textLinesTall; i++) {
+        pixmapContent->DrawText(cPoint(border, yText), wTextTall.GetLine(i), theme.Color(clrFont), clrTransparent, font);
+        yText += lineHeight;
+    }
+    for (int i=0; i < textLinesFull; i++) {
+        pixmapContent->DrawText(cPoint(border, yText), wTextFull.GetLine(i), theme.Color(clrFont), clrTransparent, font);
+        yText += lineHeight;
+    }
+    osdManager.flush();
+    cImageLoader imgLoader;
+    if (imgLoader.LoadPoster(img->path.c_str(), imgWidth, imgHeight)) {
+        if (Running() && pixmapContent)
+            pixmapContent->DrawImage(cPoint(width - imgWidth - border, border), imgLoader.GetImage());
+    }
+    if (!img2)
+        return;
+    osdManager.flush();
+    if (imgLoader.LoadPoster(img2->path.c_str(), imgWidth2, imgHeight2)) {
+        if (Running() && pixmapContent)
+            pixmapContent->DrawImage(cPoint(width - imgWidth2 - border, imgHeight + 2*border), imgLoader.GetImage());
+    }
+}
+
+void cView::CreateFloatingTextWrapper(cTextWrapper *twNarrow, cTextWrapper *twFull, std::string *text, int widthImg, int heightImg) {
+    int lineHeight = font->Height();
+    int linesNarrow = (heightImg + 2*border)/ lineHeight;
+    int linesDrawn = 0;
+    int y = 0;
+    int widthNarrow = width - 3 * border - widthImg;
+    bool drawNarrow = true;
+    
+    splitstring s(text->c_str());
+    std::vector<std::string> flds = s.split('\n', 1);
+
+    if (flds.size() < 1)
+        return;
+
+    std::stringstream sstrTextTall;
+    std::stringstream sstrTextFull;
+      
+    for (int i=0; i<flds.size(); i++) {
+        if (!flds[i].size()) {
+            //empty line
+            linesDrawn++;
+            y += lineHeight;
+            if (drawNarrow)
+                sstrTextTall << "\n";
+            else
+                sstrTextFull << "\n";
+        } else {
+            cTextWrapper wrapper;
+            if (drawNarrow) {
+                wrapper.Set((flds[i].c_str()), font, widthNarrow);
+                int newLines = wrapper.Lines();
+                //check if wrapper fits completely into narrow area
+                if (linesDrawn + newLines < linesNarrow) {
+                    for (int line = 0; line < wrapper.Lines(); line++) {
+                        sstrTextTall << wrapper.GetLine(line) << " ";
+                    }
+                    sstrTextTall << "\n";
+                    linesDrawn += newLines;
+                } else {
+                    //this wrapper has to be splitted
+                    for (int line = 0; line < wrapper.Lines(); line++) {
+                        if (line + linesDrawn < linesNarrow) {
+                            sstrTextTall << wrapper.GetLine(line) << " ";
+                        } else {
+                            sstrTextFull << wrapper.GetLine(line) << " ";
+                        }
+                    }
+                    sstrTextFull << "\n";
+                    drawNarrow = false;
+                }
+            } else {
+                wrapper.Set((flds[i].c_str()), font, width - 2*border);
+                for (int line = 0; line < wrapper.Lines(); line++) {
+                    sstrTextFull << wrapper.GetLine(line) << " ";        
+                }
+                sstrTextFull << "\n";
+            }
+        }
+    }
+    twNarrow->Set(sstrTextTall.str().c_str(), font, widthNarrow);
+    twFull->Set(sstrTextFull.str().c_str(), font, width - 2 * border);
+}
+
+void cView::DrawActors(std::vector<cActor> *actors) {
+    int numActors = actors->size();
+    if (numActors < 1) {
+        CreateContent(100);
+        pixmapContent->DrawText(cPoint(border, border), tr("No Cast available"), theme.Color(clrFont), clrTransparent, fontHeaderLarge);
+        return;
+    }
+    int thumbWidth = actors->at(0).actorThumb.width;
+    int thumbHeight = actors->at(0).actorThumb.height;
+    
+    int picsPerLine = width / (thumbWidth + 2 * border);
+    if (picsPerLine < 1)
+        return;
+
+    int picLines = numActors / picsPerLine;
+    if (numActors%picsPerLine != 0)
+        picLines++;
+    
+    int totalHeight = picLines * (thumbHeight + 2*fontSmall->Height() + border + border/2) + 2*border + fontHeaderLarge->Height();
+
+    CreateContent(totalHeight);
+    cString header = cString::sprintf("%s:", tr("Cast"));
+    pixmapContent->DrawText(cPoint(border, border), *header, theme.Color(clrFont), clrTransparent, fontHeaderLarge);
+
+    int x = 0;
+    int y = 2 * border + fontHeaderLarge->Height();
+    if (!Running())
+        return;
+        cImageLoader imgLoader;
+    int actor = 0;
+    for (int row = 0; row < picLines; row++) {
+        for (int col = 0; col < picsPerLine; col++) {
+            if (!Running())
+                return;
+            if (actor == numActors)
+                break;
+            std::string path = actors->at(actor).actorThumb.path;
+            std::string name = actors->at(actor).name;
+            std::stringstream sstrRole;
+            sstrRole << "\"" << actors->at(actor).role << "\"";
+            std::string role = sstrRole.str();
+            if (imgLoader.LoadPoster(path.c_str(), thumbWidth, thumbHeight)) {
+                if (Running() && pixmapContent)
+                    pixmapContent->DrawImage(cPoint(x + border, y), imgLoader.GetImage());
+            }
+
+            if (fontSmall->Width(name.c_str()) > thumbWidth + 2*border)
+                name = CutText(name, thumbWidth + 2*border, fontSmall);
+            if (fontSmall->Width(role.c_str()) > thumbWidth + 2*border)
+                role = CutText(role, thumbWidth + 2*border, fontSmall);
+            int xName = x + ((thumbWidth+2*border) - fontSmall->Width(name.c_str()))/2;
+            int xRole = x + ((thumbWidth+2*border) - fontSmall->Width(role.c_str()))/2;
+            if (Running() && pixmapContent) {
+                pixmapContent->DrawText(cPoint(xName, y + thumbHeight + border/2), name.c_str(), theme.Color(clrFont), clrTransparent, fontSmall);
+                pixmapContent->DrawText(cPoint(xRole, y + thumbHeight + border/2 + fontSmall->Height()), role.c_str(), theme.Color(clrFont), clrTransparent, fontSmall);
+                x += thumbWidth + 2*border;
+            }
+            actor++;
+        }
+        osdManager.flush();
+        x = 0;
+        y += thumbHeight + 2 * fontSmall->Height() + border + border/2;
+    }
+}
+
+void cView::ClearScrollbar(void) {
+    if (pixmapScrollbar)
+        pixmapScrollbar->Fill(clrTransparent);
+    if (pixmapScrollbarBack)
+        pixmapScrollbarBack->Fill(clrTransparent);
+}
+
+void cView::ClearScrollbarImage(void) {
+    if (imgScrollBar) {
+        delete imgScrollBar;
+        imgScrollBar = NULL;
+    }
+}
+
+void cView::DrawScrollbar(void) {
+    ClearScrollbar();
+    if (!scrollable || !pixmapContent)
+        return;
+
+    if (!pixmapScrollbar) {
+        pixmapScrollbar = osdManager.requestPixmap(6, cRect(width, y + headerHeight, scrollbarWidth, contentHeight));
+        pixmapScrollbar->Fill(clrTransparent);
+    }
+    if (!pixmapScrollbarBack) {
+        pixmapScrollbarBack = osdManager.requestPixmap(5, cRect(width, y + headerHeight, scrollbarWidth, contentHeight));
+        pixmapScrollbarBack->Fill(clrTransparent);
+    }
+
+    int totalBarHeight = pixmapScrollbar->ViewPort().Height() - 6;
+    
+    int aktHeight = (-1)*pixmapContent->DrawPort().Point().Y();
+    int totalHeight = pixmapContent->DrawPort().Height();
+    int screenHeight = pixmapContent->ViewPort().Height();
+
+    int barHeight = (double)(screenHeight * totalBarHeight) / (double)totalHeight ;
+    int barTop = (double)(aktHeight * totalBarHeight) / (double)totalHeight ;
+
+    if (!imgScrollBar) {
+        imgScrollBar = CreateScrollbarImage(pixmapScrollbar->ViewPort().Width()-10, barHeight, theme.Color(clrHighlight), theme.Color(clrHighlightBlending));
+    }
+    
+    pixmapScrollbarBack->Fill(theme.Color(clrHighlightBlending));
+    pixmapScrollbarBack->DrawRectangle(cRect(2, 2, pixmapScrollbar->ViewPort().Width() - 4, pixmapScrollbar->ViewPort().Height() - 4), theme.Color(clrHighlightBlending));
+
+    pixmapScrollbar->DrawImage(cPoint(3, 3 + barTop), *imgScrollBar);
+}
+
+cImage *cView::CreateScrollbarImage(int width, int height, tColor clrBgr, tColor clrBlend) {
+    cImage *image = new cImage(cSize(width, height));
+    image->Fill(clrBgr);
+    if (tvguideConfig.style != eStyleFlat) {
+        int numSteps = 64;
+        int alphaStep = 0x03;
+        if (height < 30)
+            return image;
+        else if (height < 100) {
+            numSteps = 32;
+            alphaStep = 0x06;
+        }
+        int stepY = 0.5*height / numSteps;
+        if (stepY == 0)
+            stepY = 1;
+        int alpha = 0x40;
+        tColor clr;
+        for (int i = 0; i<numSteps; i++) {
+            clr = AlphaBlend(clrBgr, clrBlend, alpha);
+            for (int y = i*stepY; y < (i+1)*stepY; y++) {
+                for (int x=0; x<width; x++) {
+                    image->SetPixel(cPoint(x,y), clr);
+                }
+            }
+            alpha += alphaStep;
+        }
+    }
+    return image;
+}
+
+bool cView::KeyUp(void) { 
+    if (!scrollable)
+        return false;
+    int aktHeight = pixmapContent->DrawPort().Point().Y();
+    int lineHeight = font->Height();
+    if (aktHeight >= 0) {
+        return false;
+    }
+    int step = tvguideConfig.detailedViewScrollStep * font->Height();
+    int newY = aktHeight + step;
+    if (newY > 0)
+        newY = 0;
+    pixmapContent->SetDrawPortPoint(cPoint(0, newY));
+    return true;
+}
+
+bool cView::KeyDown(void) { 
+    if (!scrollable)
+        return false;
+    int aktHeight = pixmapContent->DrawPort().Point().Y();
+    int totalHeight = pixmapContent->DrawPort().Height();
+    int screenHeight = pixmapContent->ViewPort().Height();
+    
+    if (totalHeight - ((-1)*aktHeight) == screenHeight) {
+        return false;
+    } 
+    int step = tvguideConfig.detailedViewScrollStep * font->Height();
+    int newY = aktHeight - step;
+    if ((-1)*newY > totalHeight - screenHeight)
+        newY = (-1)*(totalHeight - screenHeight);
+    pixmapContent->SetDrawPortPoint(cPoint(0, newY));
+    return true;
+}
+
+/********************************************************************************************
+* cEPGView : cView
+********************************************************************************************/
+
+cEPGView::cEPGView(void) : cView() {
+    tabbed = true;
+    numEPGPics = -1;
+    numTabs = 0;
+}
+
+cEPGView::~cEPGView(void) {
+    Cancel(-1);
+    while (Active())
+        cCondWait::SleepMs(10);
+}
+
+void cEPGView::SetTabs(void) {
+    tabs.push_back(tr("EPG Info"));
+    if (eventID > 0)
+        tabs.push_back(tr("Reruns"));
+    else
+        tabs.push_back(tr("Recording Information"));
+    if (numEPGPics > 0)
+        tabs.push_back(tr("Image Galery"));
+    numTabs = tabs.size();
+}
+
+void cEPGView::CheckEPGImages(void) {
+    if (eventID > 0) {
+        for (int i=1; i <= tvguideConfig.numAdditionalEPGPictures; i++) {
+            cString epgimage;
+            epgimage = cString::sprintf("%s%d_%d.jpg", *tvguideConfig.epgImagePath, eventID, i);
+            FILE *fp = fopen(*epgimage, "r");
+            if (fp) {
+                std::stringstream ss;
+                ss << i;
+                epgPics.push_back(ss.str());
+                fclose(fp);
+            } else {
+                break;
+            }
+        }
+    } else {
+        return;
+    }
+    numEPGPics = epgPics.size();
+}
+
+void cEPGView::DrawImages(void) {
+    int imgWidth = tvguideConfig.epgImageWidthLarge;
+    int imgHeight = tvguideConfig.epgImageHeightLarge;
+
+    int totalHeight = numEPGPics * (imgHeight + border);
+
+    CreateContent(totalHeight);
+    
+    cImageLoader imgLoader;
+    int yPic = border;
+    for (int pic = 0; pic < numEPGPics; pic++) {
+        bool drawPic = false;
+        if (eventID > 0) {
+            cString epgimage = cString::sprintf("%d_%d", eventID, atoi(epgPics[pic].c_str()));
+            if (imgLoader.LoadAdditionalEPGImage(epgimage)) {
+                drawPic = true;
+            }
+
+        }
+        if (drawPic) {
+            pixmapContent->DrawImage(cPoint((width - imgWidth) / 2, yPic), imgLoader.GetImage());
+            yPic += imgHeight + border;
+            osdManager.flush();
+        }
+    } 
+}
+
+void cEPGView::KeyLeft(void) { 
+    if (Running())
+        return;
+    ClearScrollbarImage();
+    activeView--;
+    if (activeView < 0)
+        activeView = numTabs - 1; 
+}
+
+void cEPGView::KeyRight(void) { 
+    if (Running())
+        return;
+    ClearScrollbarImage();
+    activeView = (activeView + 1) % numTabs;
+}
+
+void cEPGView::Action(void) {
+    ClearContent();
+    if (!headerDrawn) {
+        DrawHeader();
+        osdManager.flush();
+        headerDrawn = true;
+    }
+    if (tabs.size() == 0) {
+        CheckEPGImages();
+        SetTabs();
+    }
+    DrawTabs();
+    switch (activeView) {
+        case evtInfo:
+            DrawContent(&infoText);
+            break;
+        case evtAddInfo:
+            DrawContent(&addInfoText);
+            break;
+        case evtImages:
+            DrawImages();
+            break;
+    }
+    DrawScrollbar();
+    osdManager.flush();
+}
+
+/********************************************************************************************
+* cSeriesView : cView
+********************************************************************************************/
+
+cSeriesView::cSeriesView(int seriesId, int episodeId) : cView() {
+    this->seriesId = seriesId;
+    this->episodeId = episodeId;
+    tvdbInfo = "";
+    tabbed = true;
+}
+
+cSeriesView::~cSeriesView(void) {
+    Cancel(-1);
+    while (Active())
+        cCondWait::SleepMs(10);
+}
+
+void cSeriesView::LoadMedia(void) {
+    static cPlugin *pScraper2Vdr = cPluginManager::GetPlugin("scraper2vdr");
+    if (!pScraper2Vdr || seriesId < 1)
+        return;
+    series.seriesId = seriesId;
+    series.episodeId = episodeId;
+    pScraper2Vdr->Service("GetSeries", &series);
+}
+
+void cSeriesView::SetTabs(void) {
+    tabs.push_back(tr("EPG Info"));
+    if (eventID > 0)
+        tabs.push_back(tr("Reruns"));
+    else
+        tabs.push_back(tr("Recording Information"));
+    tabs.push_back(tr("Cast"));
+    tabs.push_back(tr("TheTVDB Info"));
+    tabs.push_back(tr("Image Galery"));
+}
+
+void cSeriesView::CreateTVDBInfo(void) {
+    if (tvdbInfo.size() > 0)
+        return;
+    std::stringstream info;
+    info << tr("TheTVDB Information") << ":\n\n";
+
+    if (series.episode.name.size() > 0) {
+        info << tr("Episode") << ": " << series.episode.name << " (" << tr("Season") << " " << series.episode.season << ", " << tr("Episode") << " " << series.episode.number << ")\n\n";
+    }
+    if (series.episode.overview.size() > 0) {
+        info << tr("Episode Overview") << ": " << series.episode.overview << "\n\n";
+    }
+    if (series.episode.firstAired.size() > 0) {
+        info << tr("First aired") << ": " << series.episode.firstAired << "\n\n";
+    }
+    if (series.episode.guestStars.size() > 0) {
+        info << tr("Guest Stars") << ": " << series.episode.guestStars << "\n\n";
+    }
+    if (series.episode.rating > 0) {
+        info << tr("TheMovieDB Rating") << ": " << series.episode.rating << "\n\n";
+    }
+    if (series.overview.size() > 0) {
+        info << tr("Series Overview") << ": " << series.overview << "\n\n";
+    }
+    if (series.firstAired.size() > 0) {
+        info << tr("First aired") << ": " << series.firstAired << "\n\n";
+    }
+    if (series.genre.size() > 0) {
+        info << tr("Genre") << ": " << series.genre << "\n\n";
+    }
+    if (series.network.size() > 0) {
+        info << tr("Network") << ": " << series.network << "\n\n";
+    }
+    if (series.rating > 0) {
+        info << tr("TheMovieDB Rating") << ": " << series.rating << "\n\n";
+    }
+    if (series.status.size() > 0) {
+        info << tr("Status") << ": " << series.status << "\n\n";
+    }
+    tvdbInfo = info.str();
+}
+
+void cSeriesView::DrawImages(void) {
+    int numPosters = series.posters.size();
+    int numFanarts = series.fanarts.size();
+    int numBanners = series.banners.size();
+    
+    int totalHeight = border;
+    //Fanart Height
+    int fanartWidth = width - 2 * border;
+    int fanartHeight = 0;
+    if (numFanarts > 0 && series.fanarts[0].width > 0) {
+        fanartHeight = series.fanarts[0].height * ((double)fanartWidth / (double)series.fanarts[0].width);
+        if (fanartHeight > contentHeight - 2 * border) {
+            int fanartHeightOrig = fanartHeight;
+            fanartHeight = contentHeight - 2 * border;
+            fanartWidth = fanartWidth * ((double)fanartHeight / (double)fanartHeightOrig);
+        }
+        totalHeight += series.fanarts.size() * (fanartHeight + border);
+    }
+    //Poster Height
+    int posterWidth = (width - 4 * border) / 2;
+    int posterHeight = 0;
+    if (numPosters > 0 && series.posters[0].width > 0) {
+        posterHeight = series.posters[0].height * ((double)posterWidth / (double)series.posters[0].width);
+    }
+    if (numPosters > 0)
+        totalHeight += posterHeight + border;
+    if (numPosters == 3)
+        totalHeight += posterHeight + border;
+    //Banners Height
+    if (numBanners > 0)
+        totalHeight += (series.banners[0].height + border) * numBanners;
+       
+    CreateContent(totalHeight);
+    
+    cImageLoader imgLoader;
+    int yPic = border;
+    for (int i=0; i < numFanarts; i++) {
+        if (numBanners > i) {
+            if (imgLoader.LoadPoster(series.banners[i].path.c_str(), series.banners[i].width, series.banners[i].height) && Running()) {
+                pixmapContent->DrawImage(cPoint((width - series.banners[i].width) / 2, yPic), imgLoader.GetImage());
+                yPic += series.banners[i].height + border;
+                osdManager.flush();
+            }
+        }
+        if (imgLoader.LoadPoster(series.fanarts[i].path.c_str(), fanartWidth, fanartHeight) && Running()) {
+            pixmapContent->DrawImage(cPoint((width - fanartWidth)/2, yPic), imgLoader.GetImage());
+            yPic += fanartHeight + border;
+            osdManager.flush();
+        }
+    }
+    if (numPosters >= 1) {
+        if (imgLoader.LoadPoster(series.posters[0].path.c_str(), posterWidth, posterHeight) && Running()) {
+            pixmapContent->DrawImage(cPoint(border, yPic), imgLoader.GetImage());
+            osdManager.flush();
+            yPic += posterHeight + border;
+        }
+    }
+    if (numPosters >= 2) {
+        if (imgLoader.LoadPoster(series.posters[1].path.c_str(), posterWidth, posterHeight) && Running()) {
+            pixmapContent->DrawImage(cPoint(2 * border + posterWidth, yPic - posterHeight - border), imgLoader.GetImage());
+            osdManager.flush();
+        }
+    }
+    if (numPosters == 3) {
+        if (imgLoader.LoadPoster(series.posters[2].path.c_str(), posterWidth, posterHeight) && Running()) {
+            pixmapContent->DrawImage(cPoint((width - posterWidth) / 2, yPic), imgLoader.GetImage());
+            osdManager.flush();
+        }
+    }
+}
+
+int cSeriesView::GetRandomPoster(void) {
+    int numPosters = series.posters.size();
+    if (numPosters == 0)
+        return -1;
+    srand((unsigned)time(NULL));
+    int randPoster = rand()%numPosters;
+    return randPoster;
+}
+
+void cSeriesView::KeyLeft(void) { 
+    if (Running())
+        return;
+    ClearScrollbarImage();
+    activeView--;
+    if (activeView < 0)
+        activeView = mvtCount - 1; 
+}
+
+void cSeriesView::KeyRight(void) { 
+    if (Running())
+        return;
+    ClearScrollbarImage();
+    activeView = (activeView + 1) % mvtCount;
+}
+
+void cSeriesView::Action(void) {
+    ClearContent();
+    if (!headerDrawn) {
+        DrawHeader();
+        osdManager.flush();
+        headerDrawn = true;
+    }
+    if (tabs.size() == 0) {
+        SetTabs();
+    }
+    DrawTabs();
+    int randomPoster = GetRandomPoster();
+    switch (activeView) {
+        case mvtInfo:
+            if (randomPoster >= 0) {
+                DrawFloatingContent(&infoText, &series.posters[randomPoster]);
+            } else
+                DrawContent(&infoText);
+            break;
+        case mvtAddInfo:
+            if (randomPoster >= 0)
+                DrawFloatingContent(&addInfoText, &series.posters[randomPoster]);
+            else
+                DrawContent(&addInfoText);
+            break;
+        case mvtCast:
+            DrawActors(&series.actors);
+            break;
+        case mvtOnlineInfo:
+            CreateTVDBInfo();
+            if ((series.seasonPoster.path.size() > 0) && series.episode.episodeImage.path.size() > 0)
+                DrawFloatingContent(&tvdbInfo, &series.episode.episodeImage, &series.seasonPoster);
+            else if (series.seasonPoster.path.size() > 0)
+                DrawFloatingContent(&tvdbInfo, &series.seasonPoster);
+            else if (series.episode.episodeImage.path.size() > 0)
+                DrawFloatingContent(&tvdbInfo, &series.episode.episodeImage);
+            else if (randomPoster >= 0)
+                DrawFloatingContent(&tvdbInfo, &series.posters[randomPoster]);
+            else
+                DrawContent(&tvdbInfo);
+            break;
+        case mvtImages:
+            DrawImages();
+            break;
+    }
+    DrawScrollbar();
+    osdManager.flush();
+}
+
+/********************************************************************************************
+* cMovieView : cView
+********************************************************************************************/
+
+cMovieView::cMovieView(int movieId) : cView() {
+    this->movieId = movieId;
+    tabbed = true;
+}
+
+cMovieView::~cMovieView(void) {
+    Cancel(-1);
+    while (Active())
+        cCondWait::SleepMs(10);
+}
+
+void cMovieView::LoadMedia(void) {
+    static cPlugin *pScraper2Vdr = cPluginManager::GetPlugin("scraper2vdr");
+    if (!pScraper2Vdr || movieId < 1)
+        return;
+    movie.movieId = movieId;
+    pScraper2Vdr->Service("GetMovie", &movie);    
+}
+
+void cMovieView::SetTabs(void) {
+    tabs.push_back(tr("EPG Info"));
+    if (eventID > 0)
+        tabs.push_back(tr("Reruns"));
+    else
+        tabs.push_back(tr("Recording Information"));
+    tabs.push_back(tr("Cast"));
+    tabs.push_back(tr("TheTVDB Info"));
+    tabs.push_back(tr("Image Galery"));
+}
+
+void cMovieView::CreateMovieDBInfo(void) {
+    if (movieDBInfo.size() > 0)
+        return;
+    std::stringstream info;
+    info << tr("TheMovieDB Information") << ":\n\n";
+    if (movie.originalTitle.size() > 0) {
+        info << tr("Original Title") << ": " << movie.originalTitle << "\n\n";
+    }
+    if (movie.tagline.size() > 0) {
+        info << tr("Tagline") << ": " << movie.tagline << "\n\n";
+    }
+    if (movie.overview.size() > 0) {
+        info << tr("Overview") << ": " << movie.overview << "\n\n";
+    }
+    std::string strAdult = (movie.adult)?(tr("yes")):(tr("no"));
+    info << tr("Adult") << ": " << strAdult << "\n\n";
+    if (movie.collectionName.size() > 0) {
+        info << tr("Collection") << ": " << movie.collectionName << "\n\n";
+    }
+    if (movie.budget > 0) {
+        info << tr("Budget") << ": " << movie.budget << "$\n\n";
+    }
+    if (movie.revenue > 0) {
+        info << tr("Revenue") << ": " << movie.revenue << "$\n\n";
+    }
+    if (movie.genres.size() > 0) {
+        info << tr("Genre") << ": " << movie.genres << "\n\n";
+    }
+    if (movie.homepage.size() > 0) {
+        info << tr("Homepage") << ": " << movie.homepage << "\n\n";
+    }
+    if (movie.releaseDate.size() > 0) {
+        info << tr("Release Date") << ": " << movie.releaseDate << "\n\n";
+    }
+    if (movie.runtime > 0) {
+        info << tr("Runtime") << ": " << movie.runtime << " " << tr("minutes") << "\n\n";
+    }
+    if (movie.popularity > 0) {
+        info << tr("TheMovieDB Popularity") << ": " << movie.popularity << "\n\n";
+    }
+    if (movie.voteAverage > 0) {
+        info << tr("TheMovieDB Vote Average") << ": " << movie.voteAverage << "\n\n";
+    }
+    movieDBInfo = info.str();
+}
+
+void cMovieView::DrawImages(void) {
+    int totalHeight = border;
+    //Fanart Height
+    int fanartWidth = width - 2 * border;
+    int fanartHeight = 0;
+    if (movie.fanart.width > 0 && movie.fanart.height > 0 && movie.fanart.path.size() > 0) {
+        fanartHeight = movie.fanart.height * ((double)fanartWidth / (double)movie.fanart.width);
+        if (fanartHeight > contentHeight - 2 * border) {
+            int fanartHeightOrig = fanartHeight;
+            fanartHeight = contentHeight - 2 * border;
+            fanartWidth = fanartWidth * ((double)fanartHeight / (double)fanartHeightOrig);
+        }
+        totalHeight += fanartHeight + border;
+    }
+    //Collection Fanart Height
+    int collectionFanartWidth = width - 2 * border;
+    int collectionFanartHeight = 0;
+    if (movie.collectionFanart.width > 0 && movie.collectionFanart.height > 0 && movie.collectionFanart.path.size() > 0) {
+        collectionFanartHeight = movie.collectionFanart.height * ((double)collectionFanartWidth / (double)movie.collectionFanart.width);
+        if (collectionFanartHeight > contentHeight - 2 * border) {
+            int fanartHeightOrig = collectionFanartHeight;
+            collectionFanartHeight = contentHeight - 2 * border;
+            collectionFanartWidth = collectionFanartWidth * ((double)collectionFanartHeight / (double)fanartHeightOrig);
+        }
+        totalHeight += collectionFanartHeight + border;
+    }
+    //Poster Height
+    if (movie.poster.width > 0 && movie.poster.height > 0 && movie.poster.path.size() > 0) {
+        totalHeight += movie.poster.height + border;
+    }
+    //Collection Popster Height
+    if (movie.collectionPoster.width > 0 && movie.collectionPoster.height > 0 && movie.collectionPoster.path.size() > 0) {
+        totalHeight += movie.collectionPoster.height + border;
+    }
+
+    CreateContent(totalHeight);
+    
+    cImageLoader imgLoader;
+    int yPic = border;
+    if (movie.fanart.width > 0 && movie.fanart.height > 0 && movie.fanart.path.size() > 0) {
+        if (imgLoader.LoadPoster(movie.fanart.path.c_str(), fanartWidth, fanartHeight) && Running()) {
+            pixmapContent->DrawImage(cPoint((width - fanartWidth)/2, yPic), imgLoader.GetImage());
+            yPic += fanartHeight + border;
+            osdManager.flush();
+        }
+    }
+    if (movie.collectionFanart.width > 0 && movie.collectionFanart.height > 0 && movie.collectionFanart.path.size() > 0) {
+        if (imgLoader.LoadPoster(movie.collectionFanart.path.c_str(), collectionFanartWidth, collectionFanartHeight) && Running()) {
+            pixmapContent->DrawImage(cPoint((width - collectionFanartWidth)/2, yPic), imgLoader.GetImage());
+            yPic += collectionFanartHeight + border;
+            osdManager.flush();
+        }
+    }
+    if (movie.poster.width > 0 && movie.poster.height > 0 && movie.poster.path.size() > 0) {
+        if (imgLoader.LoadPoster(movie.poster.path.c_str(), movie.poster.width, movie.poster.height) && Running()) {
+            pixmapContent->DrawImage(cPoint((width - movie.poster.width) / 2, yPic), imgLoader.GetImage());
+            yPic += movie.poster.height + border;
+            osdManager.flush();
+        }
+    }
+    if (movie.collectionPoster.width > 0 && movie.collectionPoster.height > 0 && movie.collectionPoster.path.size() > 0) {
+        if (imgLoader.LoadPoster(movie.collectionPoster.path.c_str(), movie.collectionPoster.width, movie.collectionPoster.height) && Running()) {
+            pixmapContent->DrawImage(cPoint((width - movie.collectionPoster.width) / 2, yPic), imgLoader.GetImage());
+            yPic += movie.collectionPoster.height + border;
+            osdManager.flush();
+        }
+    }
+}
+
+void cMovieView::KeyLeft(void) { 
+    if (Running())
+        return;
+    ClearScrollbarImage();
+    activeView--;
+    if (activeView < 0)
+        activeView = mvtCount - 1; 
+}
+
+void cMovieView::KeyRight(void) { 
+    if (Running())
+        return;
+    ClearScrollbarImage();
+    activeView = (activeView + 1) % mvtCount;
+}
+
+void cMovieView::Action(void) {
+    ClearContent();
+    if (!headerDrawn) {
+        DrawHeader();
+        osdManager.flush();
+        headerDrawn = true;
+    }
+    if (tabs.size() == 0) {
+        SetTabs();
+    }
+    DrawTabs();
+    bool posterAvailable = (movie.poster.path.size() > 0 && movie.poster.width > 0 && movie.poster.height > 0) ? true : false;
+    switch (activeView) {
+        case mvtInfo:
+            if (posterAvailable)
+                DrawFloatingContent(&infoText, &movie.poster);
+            else
+                DrawContent(&infoText);
+            break;
+        case mvtAddInfo:
+            if (posterAvailable)
+                DrawFloatingContent(&addInfoText, &movie.poster);
+            else
+                DrawContent(&addInfoText);
+            break;
+        case mvtCast:
+            DrawActors(&movie.actors);
+            break;
+        case mvtOnlineInfo:
+            CreateMovieDBInfo();
+            if (posterAvailable)
+                DrawFloatingContent(&movieDBInfo, &movie.poster);
+            else
+                DrawContent(&movieDBInfo);
+            break;
+        case mvtImages:
+            DrawImages();
+            break;
+    }
+    DrawScrollbar();
+    osdManager.flush();
+}
\ No newline at end of file
diff --git a/view.h b/view.h
new file mode 100644
index 0000000..5581390
--- /dev/null
+++ b/view.h
@@ -0,0 +1,149 @@
+#ifndef __TVGUIDE_VIEW_H
+#define __TVGUIDE_VIEW_H
+
+#include <vector>
+#include <string>
+#include <sstream>
+#include <vdr/skins.h>
+#include "services/scraper2vdr.h"
+#include "services/epgsearch.h"
+#include "services/remotetimers.h"
+#include "config.h"
+#include "imagecache.h"
+#include "imageloader.h"
+#include "tools.h"
+
+enum eEPGViewTabs {
+    evtInfo = 0,
+    evtAddInfo,
+    evtImages,
+    evtCount
+};
+
+enum eMediaViewTabs {
+    mvtInfo = 0,
+    mvtAddInfo,
+    mvtCast,
+    mvtOnlineInfo,
+    mvtImages,
+    mvtCount
+};
+
+class cView : public cThread {
+protected:
+    const cEvent *event;
+    cPixmap *pixmapBackground;
+    cStyledPixmap *pixmapHeader;
+    cPixmap *pixmapHeaderLogo;
+    cPixmap *pixmapContent;
+    cPixmap *pixmapScrollbar;
+    cPixmap *pixmapScrollbarBack;
+    cPixmap *pixmapTabs;
+    cFont *font, *fontSmall, *fontHeader, *fontHeaderLarge;
+    cImage *imgScrollBar;
+    int activeView;
+    bool scrollable;
+    bool tabbed;
+    int x, y;
+    int width, height;
+    int border;
+    int headerWidth, headerHeight;
+    int contentHeight;
+    int tabHeight;
+    int scrollbarWidth;
+    std::vector<std::string> tabs;
+    std::string title;
+    std::string subTitle;
+    std::string dateTime;
+    std::string infoText;
+    std::string addInfoText;
+    const cChannel *channel;
+    int eventID;
+    bool headerDrawn;
+    void DrawHeader(void);
+    void ClearContent(void);
+    void CreateContent(int fullHeight);
+    void DrawContent(std::string *text);
+    void DrawFloatingContent(std::string *infoText, cTvMedia *img, cTvMedia *img2 = NULL);
+    void CreateFloatingTextWrapper(cTextWrapper *twNarrow, cTextWrapper *twFull, std::string *text, int widthImg, int heightImg);
+    void DrawActors(std::vector<cActor> *actors);
+    void ClearScrollbar(void);
+    void ClearScrollbarImage(void);
+    cImage *CreateScrollbarImage(int width, int height, tColor clrBgr, tColor clrBlend);
+    virtual void SetTabs(void) {};
+    void DrawTabs(void);
+public:    
+    cView(void);
+    virtual ~cView(void);
+    void SetTitle(const char *t) { title = t ? t : ""; };
+    void SetSubTitle(const char *s) { subTitle = s ? s : ""; };
+    void SetDateTime(const char *dt) { dateTime = dt; };
+    void SetInfoText(const char *i) { infoText = i ? i : ""; };
+    void SetAdditionalInfoText(std::string addInfo) { addInfoText = addInfo; };
+    void SetChannel(const cChannel *c) { channel = c; };
+    void SetEventID(int id) { eventID = id; };
+    void SetEvent(const cEvent *event) { this->event = event; };
+    virtual void LoadMedia(void) {};
+    void SetGeometry(void);
+    void SetFonts(void);
+    virtual bool KeyUp(void);
+    virtual bool KeyDown(void);
+    virtual void KeyLeft(void) {};
+    virtual void KeyRight(void) {};
+    void DrawScrollbar(void);
+    virtual void Action(void) {};
+};
+
+class cEPGView : public cView {
+protected:
+    std::vector<std::string> epgPics;
+    int numEPGPics;
+    int numTabs;
+    void SetTabs(void);
+    void CheckEPGImages(void);
+    void DrawImages(void);
+public:    
+    cEPGView(void);
+    virtual ~cEPGView(void);
+    void KeyLeft(void);
+    void KeyRight(void);
+    void Action(void);
+};
+
+class cSeriesView : public cView {
+protected:
+    int seriesId;
+    int episodeId;
+    cSeries series;
+    std::string tvdbInfo;
+    void SetTabs(void);
+    void CreateTVDBInfo(void);
+    void DrawImages(void);
+    int GetRandomPoster(void);
+public:    
+    cSeriesView(int seriesId, int episodeId);
+    virtual ~cSeriesView(void);
+    void LoadMedia(void);
+    void KeyLeft(void);
+    void KeyRight(void);
+    void Action(void);
+};
+
+class cMovieView : public cView {
+protected:
+    int movieId;
+    cMovie movie;
+    std::string movieDBInfo;
+    void SetTabs(void);
+    void CreateMovieDBInfo(void);
+    void DrawImages(void);
+public:    
+    cMovieView(int movieId);
+    virtual ~cMovieView(void);
+    void LoadMedia(void);
+    void KeyLeft(void);
+    void KeyRight(void);
+    void Action(void);
+};
+
+#endif //__TVGUIDE_VIEW_H
\ No newline at end of file

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-vdr-dvb/vdr-plugin-tvguide.git



More information about the pkg-vdr-dvb-changes mailing list