[vdr-plugin-eepg] 01/05: Imported Upstream version 0.0.5.git20121123

Tobias Grimm tiber-guest at moszumanska.debian.org
Sun Feb 15 19:14:06 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-eepg.

commit 403dc09b2ea2911423f16c3a559d3ce8306bafaa
Author: etobi <git at e-tobi.net>
Date:   Sun Feb 15 19:39:51 2015 +0100

    Imported Upstream version 0.0.5.git20121123
---
 .pc/.dpkg-source-unapply        |    0
 .pc/.quilt_patches              |    1 +
 .pc/.quilt_series               |    1 +
 .pc/.version                    |    1 +
 COPYING                         |  340 ++
 HISTORY                         |   64 +
 Makefile                        |  136 +
 README                          |  135 +
 TODO                            |   14 +
 dish.c                          |  619 ++++
 dish.h                          |  300 ++
 eepg.c                          | 3628 ++++++++++++++++++++
 eepg.equiv.IT                   |   17 +
 eepg.h                          | 7182 +++++++++++++++++++++++++++++++++++++++
 eit2.c                          |  587 ++++
 eit2.h                          |   50 +
 epghandler.c                    |  198 ++
 epghandler.h                    |   48 +
 equivhandler.c                  |  233 ++
 equivhandler.h                  |   40 +
 log.h                           |   78 +
 scripts/README                  |   28 +
 scripts/extract_vdr_chan_ids.pl |   38 +
 scripts/makeequiv.sh            |   56 +
 setupeepg.c                     |   37 +
 setupeepg.h                     |   52 +
 util.c                          |  392 +++
 util.h                          |   93 +
 28 files changed, 14368 insertions(+)

diff --git a/.pc/.dpkg-source-unapply b/.pc/.dpkg-source-unapply
new file mode 100644
index 0000000..e69de29
diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches
new file mode 100644
index 0000000..6857a8d
--- /dev/null
+++ b/.pc/.quilt_patches
@@ -0,0 +1 @@
+debian/patches
diff --git a/.pc/.quilt_series b/.pc/.quilt_series
new file mode 100644
index 0000000..c206706
--- /dev/null
+++ b/.pc/.quilt_series
@@ -0,0 +1 @@
+series
diff --git a/.pc/.version b/.pc/.version
new file mode 100644
index 0000000..0cfbf08
--- /dev/null
+++ b/.pc/.version
@@ -0,0 +1 @@
+2
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+

+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+

+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+

+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/HISTORY b/HISTORY
new file mode 100644
index 0000000..f3ccd4d
--- /dev/null
+++ b/HISTORY
@@ -0,0 +1,64 @@
+Release 0.0.6pre:
+- Fix for vdr-1.7.x
+- Fix for OTV formats
+- Fix MHW2 format
+- Fix crash when Themes are less than the size needed for the MHW2. This has also to be completely modified since the current implementation is not best.
+- Added parental rating for SKY since it is provided and handled by vdr-1.7.15
+- Fixed charset 
+- Added viasat support
+- Removed include si.c
+- Changed docodeText2 to use code from vdr which also handles charset override
+- Removed some gotos
+- Removed some code duplication
+- Removed some todos
+- moved Premiere code in separate method
+- Added setup option to display message after finish of writing epg
+- Added Dish Network and Bell ExpressVU support, thanks to the VDR patch, Mrgandalf and VDR User
+- Applied patch to Load Huffman dictionaries only on first use, thanks to Torsten Lang
+- Fixed update of equivalents for Freesat
+- Add category and genere to the description usable with epgsearch
+- Added EpgHandler for manipulation of the EPG for VDR > 1.7.26
+- Try to discard very long events that override more than one existing event
+- Equivalents stored in map for all equivalents for better handling
+- Move equivalence to separate file/class
+- Move utilities to separate files
+- Added cAddEventThread from VDR EPGFixer Plug-in to update equivalent channels in separate thread
+- Try to discard very long events that override more than one existing event
+- Use map instead of list in cAddEventThread to reduce sorting
+- Move cEIT2 in a separate file and try to use it in epghandler also
+- Drop unmanaged NOEPG support, there is a separate plugin for that
+- Drop unmanaged Disable Double EPG entry. EEPG tries to handle this anyway
+- Aditional fixes logged at http://projects.vdr-developer.org/git/vdr-plugin-eepg.git/
+
+Release 0.0.5:
+-changed TableId's so that Now/Next overwrites Nagra which overwrites MHW
+
+
+Release 0.0.4:
+-fixed changed format MHW1 that CDNL temporarily broadcasted, but has reversed after a lot of complaints
+-now first loading NagraGuide, not loading MHW if present on same stream (CDNL)
+
+Release 0.0.3:
+-fixed undefined symbol error when not using NO_EPG patch
+-declare Nagra-events that have day-of-the month in the period between today-7days and yesterday as "old events"; some providers keep sending old eepg data that otherways are presented as next months'
+-stopped processing the second title-field that is sent with Nagra, since it is not clear when it is valid 
+-make eepg-plugin actually obey the rules defined by the NO_EPG patch, if used
+-fixed all compiler warnings
+
+Release 0.0.2a:
+-fixed problem in NagraGuide, where month of title could get random value
+
+Release 0.0.2:
+-decoded and added NagraGuide
+-tested daylight savings functionality for SKY_UK
+-added daylight savings fucntionality for MHW1 and NAGRA
+-added possiblity to scan more eepg-streams on same transponder (like CanaalDigitaalNL, both MHW1 and Nagra)
+-disabled scan after 1 hour idle time; this was unused functionality, since a) most updates are once/24 hour, and b) most of the time zapping is done within 1 hour
+-added lookup for eventid, so existing events will be updated instead of added. This means less use for the DD_EPG patch, because double EPG entries will be minimized.
+-fixed compile problem when using NO_EPG patch
+-added hexdump routine for debugging
+-improved use of TableId's, so now the plugin can decide whether to overwrite or to preserve the existing EPG data
+-improved several routines, less memory use, less cpu use.
+
+Release 0.0.1:
+First release.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..49e8770
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,136 @@
+#
+# EEPG plugin to VDR
+#
+# (C) 2008-2009 Dingo35
+#
+# This code 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 code 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+
+# 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.
+#
+PLUGIN = eepg
+
+### 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 ?= -O2 -fPIC -Wall -Woverloaded-virtual
+
+### The directory environment:
+
+VDRDIR = ../../..
+LIBDIR = ../../lib
+TMPDIR = /tmp
+
+### Allow user defined options to overwrite defaults:
+
+-include $(VDRDIR)/Make.config
+-include Make.config
+
+### The version number of VDR (taken from VDR's "config.h"):
+
+VDRVERSION = $(shell sed -ne '/define VDRVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
+APIVERSION = $(shell sed -ne '/define APIVERSION/ s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h)
+ifeq ($(strip $(APIVERSION)),)
+   APIVERSION = $(VDRVERSION)
+endif
+
+### The name of the distribution archive:
+
+ARCHIVE = $(PLUGIN)-$(VERSION)
+PACKAGE = vdr-$(ARCHIVE)
+
+### Includes and Defines (add further entries here):
+
+INCLUDES += -I$(VDRDIR)/include
+
+DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
+
+### The object files (add further files here):
+
+OBJS = $(PLUGIN).o dish.o epghandler.o setupeepg.o equivhandler.o util.o eit2.o
+
+ifdef DBG
+CXXFLAGS += -g
+endif
+
+### Internationalization (I18N):
+
+PODIR     = po
+I18Npot   = $(PODIR)/$(PLUGIN).pot
+I18Nmsgs  = $(addprefix $(LOCALEDIR)/,$(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo,$(notdir $(foreach file, $(wildcard $(PODIR)/*.po), $(basename $(file))))))
+LOCALEDIR = $(VDRDIR)/locale
+
+### Default Target
+default: $(OBJS)
+
+### Dependencies:
+
+MAKEDEP = $(CXX) -MM -MG
+DEPFILE = .dependencies
+$(DEPFILE): Makefile
+	@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(OBJS:%.o=%.c) > $@
+
+-include $(DEPFILE)
+
+### Targets:
+
+TARGETS = libvdr-$(PLUGIN).so
+ifneq ($(shell grep -l 'Phrases' $(VDRDIR)/i18n.c),$(VDRDIR)/i18n.c)
+TARGETS += i18n
+endif
+
+all: $(TARGETS)
+.PHONY: i18n
+
+%.o: %.c
+	$(CXX) $(CXXFLAGS) -c $(DEFINES) $(INCLUDES) $<
+
+libvdr-$(PLUGIN).so: $(OBJS)
+	$(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@
+	@cp $@ $(LIBDIR)/$@.$(APIVERSION)
+
+$(I18Npot): $(shell grep -rl '\(tr\|trNOOP\)(\".*\")' *.c $(SYSDIR))
+	xgettext -C -cTRANSLATORS --no-wrap -F -k -ktr -ktrNOOP  -o $@ $^
+
+%.po: $(I18Npot)
+	msgmerge -U --no-wrap -F --backup=none -q $@ $<
+	@touch $@
+
+%.mo: %.po
+	msgfmt -c -o $@ $<
+
+$(I18Nmsgs): $(LOCALEDIR)/%/LC_MESSAGES/vdr-$(PLUGIN).mo: $(PODIR)/%.mo
+	@mkdir -p $(dir $@)
+	cp $< $@
+
+i18n: $(I18Nmsgs)
+
+dist: clean
+	@-rm -rf $(TMPDIR)/$(ARCHIVE)
+	@mkdir $(TMPDIR)/$(ARCHIVE)
+	@cp -a * $(TMPDIR)/$(ARCHIVE)
+	@tar czf $(PACKAGE).tar.gz -C $(TMPDIR) $(ARCHIVE)
+	@-rm -rf $(TMPDIR)/$(ARCHIVE)
+	@echo Distribution package created as $(PACKAGE).tar.gz
+
+clean:
+	@-rm -f $(OBJS) $(DEPFILE) *.so *.tar.gz core* *~
+#	@-rm -f $(PODIR)/*.mo $(PODIR)/*.pot
diff --git a/README b/README
new file mode 100644
index 0000000..edde5b7
--- /dev/null
+++ b/README
@@ -0,0 +1,135 @@
+
+This is the Extended EPG (EEPG) "plugin" for the Video Disk Recorder (VDR).
+
+Written by:                  Dingo35
+
+Mainnained by:               Dimitar Petrovski <dimeptr at gmail.com>
+
+Project's homepage:          http://projects.vdr-developer.org/projects/plg-eepg
+
+Latest stable version available at:       
+    http://projects.vdr-developer.org/git/vdr-plugin-eepg.git/snapshot/vdr-plugin-eepg-master.tar.bz2
+Latest experimental version available at: 
+    http://projects.vdr-developer.org/git/vdr-plugin-eepg.git/snapshot/vdr-plugin-eepg-experimental.tar.bz2
+
+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.
+See the file COPYING for more information.
+
+----------------------------------------------------------------------
+
+Description:
+
+This plugin parses the extended (2 to 10 day) EPG data which is send by 
+providers on their portal channels. This EEPG data is transmitted in a 
+non-standard format on a non-standard PID.
+
+Currently the following EEPG formats are supported:
+* Mediahighway 1 (CanaalDigitaalNL, CSat, Cyfra+)
+* Mediahighway 2 (Digital+)
+* Sky Italy
+* Sky UK
+* Freesat
+* Premiere
+* NagraGuide (CanaalDigitaalNL, only in test)
+* NA Dish and BEV
+
+INSTALL
+Unpack, make and make plugins like any other plugin. Call like any other
+On the first run, in the vdr-plugins directory a subdirectory eepg is created
+where all necessary files are created.
+One can define equivalent channels in the eepg.equiv file to "copy" 
+EEPG data to other channels. 
+E.g., CanaalDigitaalNL still sends Dorcel EEPG data on S19.2E, which can be used
+for Dorcel on S13.0E.
+Some sample eepg.equiv files are included.
+
+Scripts
+The provided scripts in the package can also help generate the eepg.equiv file.
+For more information see README in scripts/
+
+USE
+The plugin has no mainmenu entry, and only a few settings for Premiere. 
+When one of VDR's devices is tuned to a transponder (by tuning, a recording or 
+an EPG scan triggered by VDR), the plugin scans all channels on the transponder
+for the supported EEPG formats. When all of the supported formats are detected, 
+all available EEPG data is loaded into the schedule of VDR.
+Additionally, the EEPG data is loaded into additional channels if they are specified 
+in the eepg.equiv file (not for Premiere).
+Everything is done automatically and transparently, all is done concurrently
+with recordings and live viewings.
+Freesat and Premiere are loading their EEPG info continuously.
+
+The plugin is designed to use as less recources as possible: it only uses 1 Pid
+(especially important to users of FF cards, which have a max. of 32 Pids), 
+and allocates and frees memory according to its needs.
+
+If one needs to reload EEPG data periodically, it is sufficient to create
+a cron job which tunes to the proper channel through the SVDRP interface.
+In practice, viewing and tuning to your favourite channels reloads the EEPG data daily,
+which is often enough since EEPG data is valid for 2 - 10 days.
+
+New, unknown EEPG transponders will be detected automatically (MHW1, MHW2, Freesat) or 
+have to be added (Sky uses different huffman decoding tables for every country).
+
+Currently known transponders that send EEPG data:
+* Sky Italia       S13.0E:11881V (OpenTV)
+* Sky UK           S28.2E:11778V (OpenTV)
+* Cyfra+           S13.0E:10719V (Mediahighway 1)
+* CSat             S19.2E:12363V (Mediahighway 1)
+* Canal DigitaalNL S19.2E:12515H (Mediahighway 1, NagraGuide)
+* Digital+         S19.2E:10847V (Mediahighway 2)
+* Premiere         Sport Portal, Premiere Direkt Portal
+* Freesat          all freesat channels
+* Dish and BEV     S119.0W:12472H S91.0W12224R
+
+Please note that the NagraGuide broadcasts of Canal DigitaalNL are stil in betatest; 
+therefore its information is not always reliable. It seems that sometimes, when no summaries 
+are available for certain titles, random summaries are chosen by the broadcaster.
+This could, of course, also be a bug, since the protocol of NagraGuide is not published.
+It can be further investigated only when NagraGuide is taken into production, and 
+certified receivers will be able to decode Nagra... in the mean time YOU can already
+enjoy the 7-day EEPG schedule!
+The unreliability of Nagra is compensated by having Mediahighway 1 overwrite Nagra-events it 
+detects.
+
+For Premiere, the plugin can tag option events i.e. the same event with the same time on
+different channels e.g. F1 sub channels. The tagging format (e.g. before or
+after event name) can be selected in the plugin setup menu.
+In addition there are two switches in the plugin setup menu to control inclusion
+of order and parental rating information into the event description.
+The plugin setup menu is only for Premiere protocol!
+
+
+THANKS
+This code is based on:
+* Premiere plugin (C) 2005-2007 Stefan Huelswitt <s.huelswitt at gmx.de>
+* mhwepg program  (C) 2002, 2003 Jean-Claude Repetto <mhwepg at repetto.org>
+* LoadEpg plugin written by Luca De Pieri <dpluca at libero.it>
+* Freesat patch written by dom /at/ suborbital.org.uk
+* Dish/BEV patch written by 
+* cAddEventThread from EPGFixer plugin by Matti Lehtimaki matti.lehtimaki /at/ gmail.com
+Thanks to mrgandalf, and the others who helped map NA eit.
+Thanks to VDR User for testing and providing makequiv.sh script for S72.7W channels.
+
+We wish to thank all authors for the great work they have been doing, decoding
+this EEPG data; this plugin tries to combine the best of all worlds.
+Specific improvement has been done on Mediahigway 1 protocol: all software known
+tries to combine titles and summaries on the basis of the event-id, but several 
+channels can use the same event-id at the same time. This leads in practice to
+20-25% erroneous summaries. The plugin uses the same technique as more simple
+satellite receivers, which take into account the order in which titles
+and summaries are sent. This leads to 99-100% accuracy.
+Also, the "number of replays" technique for CSAT is implemented correctly; not all
+software supported this information, which leads to loss of 80-90% of the EEPG 
+information.
+
+
+KNOWN BUGS
+-Equivalents file is not used for Premiere.
+-On Sky Italy and Sky UK, a lot of "summaries not found" are reported. This is 
+ because it is not (yet) known where the "summary available" flag is coded in the
+ OpenTV protocol used, so all titles are assumed to have a summary available.
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..50c9f51
--- /dev/null
+++ b/TODO
@@ -0,0 +1,14 @@
+TODO/WISH:
+-Missing support for Freesat DVB-T
+-extend equivalents file with transponder SKIP (do not retrieve EEPG info) or 
+ transponder ONCE (retrieve once a day, first possiblity after midnight). 
+ TUNE (retrieve every time transponder gets tuned to) transponder CONT (retrieve continuously)
+-look at collisions and language problems (eg Cyfra at MTV) 
+-check broadcasting frequencys + windows of all providers; report first event seen and last event seen
+-use event-> as database instead of title[] and summary[] , except for MHW1
+-try to minimize resync problems by using sliding window after "lock" on 50 succesfull sequential syncs or so
+-stop premiere after having read all titles (from CONT to ONCE)
+-check version info for all providers
+-decode summary-available bit for OpenTV
+-parallellize when not on FF card
+-NAGRA 2nd textstring is not used right now, find out when it is relevant...
diff --git a/dish.c b/dish.c
new file mode 100644
index 0000000..d257d91
--- /dev/null
+++ b/dish.c
@@ -0,0 +1,619 @@
+/***************************************************************************
+ *                                                                         *
+ *   These routines decompress Huffman coded Dish Network EIT data.        *
+ *   The implementation is based on the algorithm presentend in            *
+ *                                                                         *
+ *     "A memory-efficient Huffman decoding algorithm"                     *
+ *     Pi-Chung Wang, Yuan-Rung Yang, Chun-Liang Lee, Hung-Yi Chang        *
+ *     Proceedings of the 19th International Conference on Advanced        *
+ *     Information Networking and Applications (AINA'05)                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "dish.h"
+#include <libsi/si.h>
+//#include <libsi/descriptor.h>
+#include <string.h>
+#include <string>
+#include <stdlib.h>
+#include <vdr/tools.h>
+
+namespace SI
+{
+
+  // returns the value of a sequence of bits in the byte array
+  static unsigned int getBits(int bitIndex, int bitCount, const unsigned char *byteptr,
+      int length) {
+    union
+    {
+      unsigned char b[4];
+      unsigned long val;
+    } chunk;
+
+    int offset = bitIndex >> 3;
+    int bitnum = bitIndex - (offset << 3);
+    int rightend = 32 - bitnum - bitCount;
+
+    chunk.b[3] = byteptr[offset];
+    chunk.b[2] = (offset + 1 < length) ? byteptr[offset + 1] : 0;
+    chunk.b[1] = (offset + 2 < length) ? byteptr[offset + 2] : 0;
+    chunk.b[0] = 0;  // Never need to look this far ahead.
+
+    return (unsigned int) ((((((chunk.val & (0xFFFFFFFF >> bitnum)) >> rightend)))));
+    }
+
+    DishDescriptor::DishDescriptor()
+    {
+        name = NULL;
+        shortText = NULL;
+        description = NULL;
+        decompressedShort = NULL;
+        decompressedExtended = NULL;
+        DishTheme = 0;
+        DishCategory = 0;
+        mpaaRating = 0;
+        starRating = 0;
+        originalAirDate = 0;
+        programId = NULL;
+        seriesId = NULL;
+        ratingStr = NULL;
+    }
+
+    DishDescriptor::~DishDescriptor()
+    {
+        delete [] decompressedShort;
+        decompressedShort = NULL;
+        delete [] decompressedExtended;
+        decompressedExtended = NULL;
+        delete [] programId;
+        programId = NULL;
+        delete [] seriesId;
+        seriesId = NULL;
+    }
+
+    const char *DishDescriptor::getTheme()
+    {
+      const char* theme;
+      using namespace DISH_THEMES;
+
+        switch (DishTheme){
+        case Movie:
+          theme = "Movie";
+          break;
+        case Sports:
+          theme = "Sports";
+            break;
+        case News_Business:
+          theme = "News/Business";
+            break;
+        case Family_Children:
+          theme = "Family/Children";
+            break;
+        case Education:
+          theme = "Education";
+            break;
+        case Series_Special:
+          theme = "Series/Special";
+            break;
+        case Music_Art:
+          theme = "Music/Art";
+            break;
+        case Religious:
+          theme = "Religious";
+            break;
+        default:
+          theme = "";
+          break;
+      }
+      return theme;
+    }
+
+    const char *DishDescriptor::getCategory()
+    {
+        using namespace DISH_CATEGORIES;
+
+      switch (DishCategory) {
+      case Action: return "Action";
+      case ActionSports:              return "Action Sports";
+      case Adults_only:               return "Adults only";
+      case Adventure:                 return "Adventure";
+      case Agriculture:               return "Agriculture";
+      case AirRacing:                 return "Air racing";
+      case Animals:                   return "Animals";
+      case Animated:                  return "Animated";
+      case Anime:                     return "Anime";
+      case Anthology:                 return "Anthology";
+      case ArmWrestling:              return "Arm wrestling";
+      case Art:                       return "Art";
+      case Arts_crafts:               return "Arts/crafts";
+      case Auction:                   return "Auction";
+      case Auto:                      return "Auto";
+      case AutoRacing:                return "Auto racing";
+      case Awards:                    return "Awards";
+      case Badminton:                 return "Badminton";
+      case Ballet:                    return "Ballet";
+      case Baseball:                  return "Baseball";
+      case Basketball:                return "Basketball";
+      case BicycleRacing:             return "Bicycle racing";
+      case Biography:                 return "Biography";
+      case Boat:                      return "Boat";
+      case BoatRacing:                return "Boat racing";
+      case Bowling:                   return "Bowling";
+      case Boxing:                    return "Boxing";
+      case Bus_financial:             return "Bus./financial";
+      case CardGames:                 return "Card games";
+      case Children:                  return "Children";
+      case ChildrenMusic:             return "Children music";
+      case ChildrenNews:              return "Children news";
+      case ChildrenSpecial:           return "Children special";
+      case Collectibles:              return "Collectibles";
+      case Comedy:                    return "Comedy";
+      case ComedyDrama:               return "Comedy-drama";
+      case Community:                 return "Community";
+      case Computers:                 return "Computers";
+      case Consumer:                  return "Consumer";
+      case Cooking:                   return "Cooking";
+      case Crime:                     return "Crime";
+      case CrimeDrama:                return "Crime drama";
+      case Dance:                     return "Dance";
+      case Debate:                    return "Debate";
+      case DishNetwork:               return "Dish Network";
+      case Docudrama:                 return "Docudrama";
+      case Documentary:               return "Documentary";
+      case DogShow:                   return "DogShow";
+      case DragRacing:                return "DragRacing";
+      case Drama:                     return "Drama";
+      case Educational:               return "Educational";
+      case Entertainment:             return "Entertainment";
+      case Environment:               return "Environment";
+      case Equestrian:                return "Equestrian";
+      case Excercise:                 return "Excercise";
+      case Fantasy:                   return "Fantasy";
+      case Fashion:                   return "Fashion";
+      case FieldHockey:               return "Field hockey";
+      case Fishing:                   return "Fishing";
+      case Football:
+      case Football2:                 return "Football";
+      case French:                    return "French";
+      case Fundraiser:                return "Fundraiser";
+      case GameShow:                  return "GameShow";
+      case Gay_lesbian:               return "Gay/lesbian";
+      case Golf:                      return "Golf";
+      case Gymnastics:                return "Gymnastics";
+      case Handball:                  return "Handball";
+      case Health:                    return "Health";
+      case HistoricalDrama:           return "Historical drama";
+      case History:                   return "History";
+      case Hockey:                    return "Hockey";
+      case Holiday:                   return "Holiday";
+      case HolidayChildren:           return "Holiday children";
+      case HolidayChildrenSpecial:    return "Holiday children special";
+      case HolidaySpecial:            return "Holiday special";
+      case HomeImprovement:           return "Home improvement";
+      case Horror:                    return "Horror";
+      case HorseRacing:               return "Horse racing";
+      case House_garden:              return "House/garden";
+      case HowTo:                     return "HowTo";
+      case Hunting:                   return "Hunting";
+      case HydroplaneRacing:          return "Hydroplane racing";
+      case Interview:                 return "Interview";
+      case Lacrosse:                  return "Lacrosse";
+      case Law:                       return "Law";
+      case MartialArts:               return "Martial arts";
+      case Medical:                   return "Medical";
+      case Military:                  return "Military";
+      case Miniseries:                return "Miniseries";
+      case MixedMartialArts:          return "Mixed martial arts";
+      case Motorcycle:                return "Motorcycle";
+      case MotorcycleRacing:          return "Motorcycle racing";
+      case Motorsports:               return "Motorsports";
+      case Music:                     return "Music";
+      case MusicSpecial:              return "Music special";
+      case MusicTalk:                 return "Music talk";
+      case Musical:                   return "Musical";
+      case MusicalComedy:             return "Musical comedy";
+      case Mystery:                   return "Mystery";
+      case Nature:                    return "Nature";
+      case News:                      return "News";
+      case Newsmagazine:              return "Newsmagazine";
+      case Opera:                     return "Opera";
+      case Outdoors:                  return "Outdoors";
+      case Paranormal:                return "Paranormal";
+      case Parenting:                 return "Parenting";
+      case PerformingArts:            return "Performing arts";
+      case Poker:                     return "Poker";
+      case Politics:                  return "Politics";
+      case ProWrestling:              return "Pro wrestling";
+      case PublicAffairs:             return "Public affairs";
+      case Reality:                   return "Reality";
+      case Religious:                 return "Religious";
+      case Rodeo:                     return "Rodeo";
+      case Romance:                   return "Romance";
+      case RomanceComedy:             return "Romance comedy";
+      case Rugby:                     return "Rugby";
+      case Running:                   return "Running";
+      case Sailing:                   return "Sailing";
+      case Science:                   return "Science";
+      case ScienceFiction:            return "Science fiction";
+      case SelfImprovement:           return "Self improvement";
+      case Shooting:                  return "Shooting";
+      case Shopping:                  return "Shopping";
+      case Sitcom:                    return "Sitcom";
+      case Skateboarding:             return "Skateboarding";
+      case Skiing:                    return "Skiing";
+      case Snowboarding:              return "Snowboarding";
+      case Soap:                      return "Soap";
+      case Soccor:                    return "Soccor";
+      case Softball:                  return "Softball";
+      case Spanish:                   return "Spanish";
+      case Special:                   return "Special";
+      case SportsNonEvent:            return "SportsNonEvent";
+      case SportsTalk:                return "SportsTalk";
+      case Standup:                   return "Standup";
+      case Surfing:                   return "Surfing";
+      case Suspense:                  return "Suspense";
+      case Swimming:                  return "Swimming";
+      case Talk:                      return "Talk";
+      case Technology:                return "Technology";
+      case Tennis:
+      case Tennis2:                   return "Tennis";
+      case Track_field:               return "Track/field";
+      case Travel:                    return "Travel";
+      case Triathlon:                 return "Triathlon";
+      case Variety:                   return "Variety";
+      case Volleyball:                return "Volleyball";
+      case War:                       return "War";
+      case Watersports:               return "Watersports";
+      case Weather:                   return "Weather";
+      case Western:                   return "Western";
+      case Wrestling:                 return "Wrestling";
+      case Yoga:                      return "Yoga";
+      default: return "";
+      }
+    }
+
+    void DishDescriptor::setShortData(unsigned char Tid, CharArray data)
+    {
+      decompressedShort = Decompress(Tid, data);
+      if (decompressedShort) {
+        name = (char*)decompressedShort;
+      }
+    }
+
+    void DishDescriptor::setExtendedtData(unsigned char Tid, CharArray data)
+    {
+      decompressedExtended = Decompress(Tid, data);
+        if (decompressedExtended) {
+        char *split = strchr((char*)((decompressedExtended)), 0x0D); // Look for carriage return
+        //LogD(2, prep("dLength:%d, length:%d, count:%d, decompressed: %s"), dLength, length, count, decompressed);
+        if(split){
+            *split = 0;
+            shortText = (char*)decompressedExtended;
+            description = (split[1] == 0x20) ? split + 2 : split + 1;
+        }else{
+          description = (char*)decompressedExtended;
+        }
+      }
+    }
+
+    const char *DishDescriptor::getShortText(void)
+    {
+//        string tmp = "";
+////        if (shortText != NULL) tmp += *shortText;
+//        tmp += shortText;
+//        if(DishTheme > 0){
+//            if(tmp != "") tmp += " - ";
+//
+//            tmp += getTheme();
+//        }
+//        if(DishCategory > 0){
+//            if(tmp != "") tmp += " - ";
+//
+//            tmp += getCategory();
+//        }
+//        return tmp.c_str();
+      return shortText?shortText:"";
+    }
+
+    const char *DishDescriptor::getDescription(void) {
+//      string tmp = "";
+////      if (description != NULL) tmp += *description;
+//      tmp += description;
+//      const char* rating = getRating();
+//      if (rating && strcmp(rating,"") != 0) {
+//        if(tmp != "") tmp += " ~ ";
+//        tmp += rating;
+//      }
+//      if (starRating > 0) {
+//        if(tmp != "") tmp += " ~ ";
+//        tmp += getStarRating();
+//      }
+//      return tmp.c_str();
+      return description?description:"";
+    }
+
+    const char *DishDescriptor::getProgramId(void) {
+      return programId?programId:"";
+    }
+
+    const char *DishDescriptor::getSeriesId(void) {
+      return seriesId?seriesId:"";
+    }
+
+    void DishDescriptor::setEpisodeInfo(CharArray data)
+    {
+      data.addOffset(2);
+      int series = (data[1] << 0x12) | (data[2] << 0x0a) | (data[3] << 0x02) | ((data[4] & 0xc0) >> 0x06);
+      int episode = ((data[4] & 0x3f) << 0x08) | data[5];
+      const char* prefix;
+
+      if (data[0] == 0x7c)
+           prefix = "MV";
+      else if (data[0] == 0x7d)
+           prefix = "SP";
+      else if (data[0] == 0x7e)
+           prefix = "EP";
+      else
+           prefix ="";
+
+      programId = new char[17];
+
+      sprintf(programId, "%s%08d%04d", (data[0] == 0x7e && episode == 0 ? "SH" : prefix), series, episode);
+
+      if (data[0] == 0x7e) {
+        seriesId = new char[11];
+        sprintf(seriesId, "%s%08d", prefix, series);
+      }
+
+      if (data.TwoBytes(6) != 0 && data.TwoBytes(6) != 0x9e8b ) {
+          originalAirDate = ((data[6] << 0x08 | data[7]) - 40587) * 86400;
+      }
+    }
+
+    void DishDescriptor::setContent(ContentDescriptor::Nibble Nibble)
+    {
+      DishTheme = Nibble.getContentNibbleLevel2() & 0xF;
+      DishCategory = ((Nibble.getUserNibble1() & 0xF) << 4) | (Nibble.getUserNibble2() & 0xF);
+    }
+
+    void DishDescriptor::setRating(uint16_t rating)
+    {
+      uint16_t newRating = (rating >> 10) & 0x07;
+      if (newRating == 0) newRating = 5;
+      if (newRating == 6) newRating = 0;
+      mpaaRating = (newRating << 10) | (rating & 0x3FF);
+      starRating = (rating >> 13) & 0x07;
+    }
+
+    const char* DishDescriptor::getRating(){
+      static const char *const ratings[8] =  { "", "G", "PG", "PG-13", "R", "NR/AO", "", "NC-17" };
+
+      if (mpaaRating == 0) {
+        return ratings[mpaaRating];
+      }
+
+      std::string str = ratings[(mpaaRating >> 10) & 0x07];
+//      char buffer[19];
+//      buffer[0] = 0;
+//      strcpy(buffer, ratings[(mpaaRating >> 10) & 0x07]);
+      if (mpaaRating & 0x3A7F) {
+          str += " [";
+//         strcat(buffer, " [");
+         if (mpaaRating & 0x0230)
+           str += "V,";
+//            strcat(buffer, "V,");
+         if (mpaaRating & 0x000A)
+           str += "L,";
+//            strcat(buffer, "L,");
+         if (mpaaRating & 0x0044)
+           str += "N,";
+//            strcat(buffer, "N,");
+         if (mpaaRating & 0x0101)
+           str += "SC,";
+//            strcat(buffer, "SC,");
+//         if (char *s = strrchr(buffer, ','))
+//            s[0] = ']';
+         if (str.find(',') != std::string::npos) {
+           str.erase(str.find_last_of(','));
+         }
+         str += "]";
+       }
+
+      if (!ratingStr) ratingStr = new char[19];
+      if (ratingStr) strcpy(ratingStr,str.c_str());
+      return ratingStr;
+
+//      return isempty(buffer) ? "" : buffer;
+    }
+
+    const char* DishDescriptor::getStarRating(){
+      static const char *const critiques[8] = { "", "*", "*+", "**", "**+", "***", "***+", "****" };
+      return critiques[starRating & 0x07];
+    }
+
+    unsigned char* DishDescriptor::Decompress(unsigned char Tid, CharArray data)
+    {
+        const unsigned char *str = data.getData();
+        const unsigned char *cmp = NULL;
+        int length = 0; // Length of compressed data
+        unsigned int dLength = 0; // Length of decompressed data
+        if((str[3] & 0xFC) == 0x80){
+            length = str[1] - 2;
+            dLength = (str[2] & 0x40) ? ((str[3] << 6) & 0xFF) | (str[2] & 0x3F) : str[2] & 0x3F;
+            cmp = str + 4;
+        }else{
+            length = str[1] - 1;
+            dLength = str[2] & 0x7F;
+            cmp = str + 3;
+        }
+        if(length <= 0 || !dLength)
+            return NULL;
+
+        unsigned char* decompressed = new unsigned char[dLength + 1];
+        HuffmanTable *table;
+        unsigned int tableSize, numBits;
+        if (Tid > 0x80) {
+        table = Table255;
+        tableSize = SIZE_TABLE_255;
+        numBits = 13;
+    } else {
+        table = Table128;
+        tableSize = SIZE_TABLE_128;
+        numBits = 11;
+     }
+        unsigned int bLength = length << 3; // number of bits
+        unsigned int currentBit = 0, count = 0;
+        while(currentBit < bLength - 1 && count < dLength){
+            // Find the interval containing the sequence of length numBits starting
+            // at currentBit. The corresponding character will  be the one encoded
+            // at the begin of the sequence.
+            unsigned int code = getBits(currentBit, numBits, cmp, length);
+            // We could use a binary search, but in practice this linear search is faster.
+            unsigned int index = 0;
+            while(table[index].startingAddress <= code && index < tableSize){
+                index++;
+            }
+            index--;
+            decompressed[count++] = table[index].character;
+            currentBit += table[index].numberOfBits;
+        }
+
+        decompressed[count] = 0;
+        return decompressed;
+    }
+
+struct DishDescriptor::HuffmanTable DishDescriptor::Table128[SIZE_TABLE_128] = {
+   { 0x0000, 0x20, 0x03 }, { 0x0100, 0x65, 0x04 }, { 0x0180, 0x74, 0x04 }, 
+   { 0x0200, 0x61, 0x04 }, { 0x0280, 0x6F, 0x04 }, { 0x0300, 0x73, 0x04 }, 
+   { 0x0380, 0x6E, 0x04 }, { 0x0400, 0x72, 0x06 }, { 0x0420, 0x69, 0x06 }, 
+   { 0x0440, 0x6C, 0x06 }, { 0x0460, 0x63, 0x06 }, { 0x0480, 0x68, 0x06 }, 
+   { 0x04A0, 0x75, 0x06 }, { 0x04C0, 0x64, 0x06 }, { 0x04E0, 0x70, 0x06 }, 
+   { 0x0500, 0x6D, 0x06 }, { 0x0520, 0x67, 0x06 }, { 0x0540, 0x79, 0x06 }, 
+   { 0x0560, 0x76, 0x06 }, { 0x0580, 0x0A, 0x06 }, { 0x05A0, 0x2E, 0x06 }, 
+   { 0x05C0, 0x77, 0x06 }, { 0x05E0, 0x66, 0x06 }, { 0x0600, 0x53, 0x07 }, 
+   { 0x0610, 0x62, 0x07 }, { 0x0620, 0x54, 0x07 }, { 0x0630, 0x22, 0x07 }, 
+   { 0x0640, 0x6B, 0x07 }, { 0x0650, 0x50, 0x07 }, { 0x0660, 0x41, 0x07 }, 
+   { 0x0670, 0x43, 0x07 }, { 0x0680, 0x44, 0x07 }, { 0x0690, 0x4C, 0x07 }, 
+   { 0x06A0, 0x4D, 0x07 }, { 0x06B0, 0x49, 0x07 }, { 0x06C0, 0x4E, 0x07 }, 
+   { 0x06D0, 0x3A, 0x07 }, { 0x06E0, 0x52, 0x07 }, { 0x06F0, 0x2C, 0x07 }, 
+   { 0x0700, 0x45, 0x08 }, { 0x0708, 0x55, 0x08 }, { 0x0710, 0x46, 0x08 }, 
+   { 0x0718, 0x48, 0x08 }, { 0x0720, 0x59, 0x08 }, { 0x0728, 0x56, 0x08 }, 
+   { 0x0730, 0x2D, 0x08 }, { 0x0738, 0x7A, 0x08 }, { 0x0740, 0x78, 0x08 }, 
+   { 0x0748, 0x2F, 0x08 }, { 0x0750, 0x4F, 0x08 }, { 0x0758, 0x3F, 0x08 }, 
+   { 0x0760, 0x57, 0x08 }, { 0x0768, 0x47, 0x08 }, { 0x0770, 0x42, 0x08 }, 
+   { 0x0778, 0x33, 0x08 }, { 0x0780, 0x31, 0x09 }, { 0x0784, 0x71, 0x09 }, 
+   { 0x0788, 0x30, 0x09 }, { 0x078C, 0x21, 0x09 }, { 0x0790, 0x6A, 0x09 }, 
+   { 0x0794, 0x5A, 0x09 }, { 0x0798, 0x39, 0x09 }, { 0x079C, 0x34, 0x09 }, 
+   { 0x07A0, 0x4B, 0x09 }, { 0x07A4, 0x2A, 0x09 }, { 0x07A8, 0x37, 0x09 }, 
+   { 0x07AC, 0x36, 0x09 }, { 0x07B0, 0x35, 0x09 }, { 0x07B4, 0x4A, 0x09 }, 
+   { 0x07B8, 0x38, 0x09 }, { 0x07BC, 0x29, 0x09 }, { 0x07C0, 0x28, 0x0A }, 
+   { 0x07C2, 0x58, 0x0A }, { 0x07C4, 0x51, 0x0A }, { 0x07C6, 0x3C, 0x0A }, 
+   { 0x07C8, 0x32, 0x0A }, { 0x07CA, 0x27, 0x0A }, { 0x07CC, 0x26, 0x0A }, 
+   { 0x07CE, 0x7F, 0x0B }, { 0x07CF, 0x7E, 0x0B }, { 0x07D0, 0x7D, 0x0B }, 
+   { 0x07D1, 0x7C, 0x0B }, { 0x07D2, 0x7B, 0x0B }, { 0x07D3, 0x60, 0x0B }, 
+   { 0x07D4, 0x5F, 0x0B }, { 0x07D5, 0x5E, 0x0B }, { 0x07D6, 0x5D, 0x0B }, 
+   { 0x07D7, 0x5C, 0x0B }, { 0x07D8, 0x5B, 0x0B }, { 0x07D9, 0x40, 0x0B }, 
+   { 0x07DA, 0x3E, 0x0B }, { 0x07DB, 0x3D, 0x0B }, { 0x07DC, 0x3B, 0x0B }, 
+   { 0x07DD, 0x2B, 0x0B }, { 0x07DE, 0x25, 0x0B }, { 0x07DF, 0x24, 0x0B }, 
+   { 0x07E0, 0x23, 0x0B }, { 0x07E1, 0x1F, 0x0B }, { 0x07E2, 0x1E, 0x0B }, 
+   { 0x07E3, 0x1D, 0x0B }, { 0x07E4, 0x1C, 0x0B }, { 0x07E5, 0x1B, 0x0B }, 
+   { 0x07E6, 0x1A, 0x0B }, { 0x07E7, 0x19, 0x0B }, { 0x07E8, 0x18, 0x0B }, 
+   { 0x07E9, 0x17, 0x0B }, { 0x07EA, 0x16, 0x0B }, { 0x07EB, 0x15, 0x0B }, 
+   { 0x07EC, 0x14, 0x0B }, { 0x07ED, 0x13, 0x0B }, { 0x07EE, 0x12, 0x0B }, 
+   { 0x07EF, 0x11, 0x0B }, { 0x07F0, 0x10, 0x0B }, { 0x07F1, 0x0F, 0x0B }, 
+   { 0x07F2, 0x0E, 0x0B }, { 0x07F3, 0x0D, 0x0B }, { 0x07F4, 0x0C, 0x0B }, 
+   { 0x07F5, 0x0B, 0x0B }, { 0x07F6, 0x09, 0x0B }, { 0x07F7, 0x08, 0x0B }, 
+   { 0x07F8, 0x07, 0x0B }, { 0x07F9, 0x06, 0x0B }, { 0x07FA, 0x05, 0x0B }, 
+   { 0x07FB, 0x04, 0x0B }, { 0x07FC, 0x03, 0x0B }, { 0x07FD, 0x02, 0x0B }, 
+   { 0x07FE, 0x01, 0x0B }, { 0x07FF, 0x00, 0x0B }
+};
+
+struct DishDescriptor::HuffmanTable DishDescriptor::Table255[SIZE_TABLE_255] = {
+   { 0x0000, 0x20, 0x02 }, { 0x0800, 0x65, 0x04 }, { 0x0A00, 0x72, 0x04 }, 
+   { 0x0C00, 0x6E, 0x04 }, { 0x0E00, 0x61, 0x04 }, { 0x1000, 0x74, 0x05 }, 
+   { 0x1100, 0x6F, 0x05 }, { 0x1200, 0x73, 0x05 }, { 0x1300, 0x69, 0x05 }, 
+   { 0x1400, 0x6C, 0x05 }, { 0x1500, 0x75, 0x05 }, { 0x1600, 0x63, 0x05 }, 
+   { 0x1700, 0x64, 0x05 }, { 0x1800, 0x70, 0x07 }, { 0x1840, 0x6D, 0x07 }, 
+   { 0x1880, 0x76, 0x07 }, { 0x18C0, 0x67, 0x07 }, { 0x1900, 0x68, 0x07 }, 
+   { 0x1940, 0x2E, 0x07 }, { 0x1980, 0x66, 0x07 }, { 0x19C0, 0x0A, 0x07 }, 
+   { 0x1A00, 0x53, 0x07 }, { 0x1A40, 0x41, 0x07 }, { 0x1A80, 0x45, 0x07 }, 
+   { 0x1AC0, 0x43, 0x07 }, { 0x1B00, 0x27, 0x07 }, { 0x1B40, 0x7A, 0x07 }, 
+   { 0x1B80, 0x52, 0x07 }, { 0x1BC0, 0x22, 0x07 }, { 0x1C00, 0x4C, 0x08 }, 
+   { 0x1C20, 0x49, 0x08 }, { 0x1C40, 0x4F, 0x08 }, { 0x1C60, 0x62, 0x08 }, 
+   { 0x1C80, 0x54, 0x08 }, { 0x1CA0, 0x4E, 0x08 }, { 0x1CC0, 0x55, 0x08 }, 
+   { 0x1CE0, 0x79, 0x08 }, { 0x1D00, 0x44, 0x08 }, { 0x1D20, 0x50, 0x08 }, 
+   { 0x1D40, 0x71, 0x08 }, { 0x1D60, 0x56, 0x08 }, { 0x1D80, 0x2D, 0x08 }, 
+   { 0x1DA0, 0x3A, 0x08 }, { 0x1DC0, 0x2C, 0x08 }, { 0x1DE0, 0x48, 0x08 }, 
+   { 0x1E00, 0x4D, 0x09 }, { 0x1E10, 0x78, 0x09 }, { 0x1E20, 0x77, 0x09 }, 
+   { 0x1E30, 0x42, 0x09 }, { 0x1E40, 0x47, 0x09 }, { 0x1E50, 0x46, 0x09 }, 
+   { 0x1E60, 0x30, 0x09 }, { 0x1E70, 0x3F, 0x09 }, { 0x1E80, 0x33, 0x09 }, 
+   { 0x1E90, 0x2F, 0x09 }, { 0x1EA0, 0x39, 0x09 }, { 0x1EB0, 0x31, 0x09 }, 
+   { 0x1EC0, 0x38, 0x09 }, { 0x1ED0, 0x6B, 0x09 }, { 0x1EE0, 0x6A, 0x09 }, 
+   { 0x1EF0, 0x21, 0x09 }, { 0x1F00, 0x36, 0x0A }, { 0x1F08, 0x35, 0x0A }, 
+   { 0x1F10, 0x59, 0x0A }, { 0x1F18, 0x51, 0x0A }, { 0x1F20, 0x34, 0x0B }, 
+   { 0x1F24, 0x58, 0x0B }, { 0x1F28, 0x32, 0x0B }, { 0x1F2C, 0x2B, 0x0B }, 
+   { 0x1F30, 0x2A, 0x0B }, { 0x1F34, 0x5A, 0x0B }, { 0x1F38, 0x4A, 0x0B }, 
+   { 0x1F3C, 0x29, 0x0B }, { 0x1F40, 0x28, 0x0C }, { 0x1F42, 0x23, 0x0C }, 
+   { 0x1F44, 0x57, 0x0C }, { 0x1F46, 0x4B, 0x0C }, { 0x1F48, 0x3C, 0x0C }, 
+   { 0x1F4A, 0x37, 0x0C }, { 0x1F4C, 0x7D, 0x0C }, { 0x1F4E, 0x7B, 0x0C }, 
+   { 0x1F50, 0x60, 0x0C }, { 0x1F52, 0x26, 0x0C }, { 0x1F54, 0xFE, 0x0D }, 
+   { 0x1F55, 0xFD, 0x0D }, { 0x1F56, 0xFC, 0x0D }, { 0x1F57, 0xFB, 0x0D }, 
+   { 0x1F58, 0xFA, 0x0D }, { 0x1F59, 0xF9, 0x0D }, { 0x1F5A, 0xF8, 0x0D }, 
+   { 0x1F5B, 0xF7, 0x0D }, { 0x1F5C, 0xF6, 0x0D }, { 0x1F5D, 0xF5, 0x0D }, 
+   { 0x1F5E, 0xF4, 0x0D }, { 0x1F5F, 0xF3, 0x0D }, { 0x1F60, 0xF2, 0x0D }, 
+   { 0x1F61, 0xF1, 0x0D }, { 0x1F62, 0xF0, 0x0D }, { 0x1F63, 0xEF, 0x0D }, 
+   { 0x1F64, 0xEE, 0x0D }, { 0x1F65, 0xED, 0x0D }, { 0x1F66, 0xEC, 0x0D }, 
+   { 0x1F67, 0xEB, 0x0D }, { 0x1F68, 0xEA, 0x0D }, { 0x1F69, 0xE9, 0x0D }, 
+   { 0x1F6A, 0xE8, 0x0D }, { 0x1F6B, 0xE7, 0x0D }, { 0x1F6C, 0xE6, 0x0D }, 
+   { 0x1F6D, 0xE5, 0x0D }, { 0x1F6E, 0xE4, 0x0D }, { 0x1F6F, 0xE3, 0x0D }, 
+   { 0x1F70, 0xE2, 0x0D }, { 0x1F71, 0xE1, 0x0D }, { 0x1F72, 0xE0, 0x0D }, 
+   { 0x1F73, 0xDF, 0x0D }, { 0x1F74, 0xDE, 0x0D }, { 0x1F75, 0xDD, 0x0D }, 
+   { 0x1F76, 0xDC, 0x0D }, { 0x1F77, 0xDB, 0x0D }, { 0x1F78, 0xDA, 0x0D }, 
+   { 0x1F79, 0xD9, 0x0D }, { 0x1F7A, 0xD8, 0x0D }, { 0x1F7B, 0xD7, 0x0D }, 
+   { 0x1F7C, 0xD6, 0x0D }, { 0x1F7D, 0xD5, 0x0D }, { 0x1F7E, 0xD4, 0x0D }, 
+   { 0x1F7F, 0xD3, 0x0D }, { 0x1F80, 0xD2, 0x0D }, { 0x1F81, 0xD1, 0x0D }, 
+   { 0x1F82, 0xD0, 0x0D }, { 0x1F83, 0xCF, 0x0D }, { 0x1F84, 0xCE, 0x0D }, 
+   { 0x1F85, 0xCD, 0x0D }, { 0x1F86, 0xCC, 0x0D }, { 0x1F87, 0xCB, 0x0D }, 
+   { 0x1F88, 0xCA, 0x0D }, { 0x1F89, 0xC9, 0x0D }, { 0x1F8A, 0xC8, 0x0D }, 
+   { 0x1F8B, 0xC7, 0x0D }, { 0x1F8C, 0xC6, 0x0D }, { 0x1F8D, 0xC5, 0x0D }, 
+   { 0x1F8E, 0xC4, 0x0D }, { 0x1F8F, 0xC3, 0x0D }, { 0x1F90, 0xC2, 0x0D }, 
+   { 0x1F91, 0xC1, 0x0D }, { 0x1F92, 0xC0, 0x0D }, { 0x1F93, 0xBF, 0x0D }, 
+   { 0x1F94, 0xBE, 0x0D }, { 0x1F95, 0xBD, 0x0D }, { 0x1F96, 0xBC, 0x0D }, 
+   { 0x1F97, 0xBB, 0x0D }, { 0x1F98, 0xBA, 0x0D }, { 0x1F99, 0xB9, 0x0D }, 
+   { 0x1F9A, 0xB8, 0x0D }, { 0x1F9B, 0xB7, 0x0D }, { 0x1F9C, 0xB6, 0x0D }, 
+   { 0x1F9D, 0xB5, 0x0D }, { 0x1F9E, 0xB4, 0x0D }, { 0x1F9F, 0xB3, 0x0D }, 
+   { 0x1FA0, 0xB2, 0x0D }, { 0x1FA1, 0xB1, 0x0D }, { 0x1FA2, 0xB0, 0x0D }, 
+   { 0x1FA3, 0xAF, 0x0D }, { 0x1FA4, 0xAE, 0x0D }, { 0x1FA5, 0xAD, 0x0D }, 
+   { 0x1FA6, 0xAC, 0x0D }, { 0x1FA7, 0xAB, 0x0D }, { 0x1FA8, 0xAA, 0x0D }, 
+   { 0x1FA9, 0xA9, 0x0D }, { 0x1FAA, 0xA8, 0x0D }, { 0x1FAB, 0xA7, 0x0D }, 
+   { 0x1FAC, 0xA6, 0x0D }, { 0x1FAD, 0xA5, 0x0D }, { 0x1FAE, 0xA4, 0x0D }, 
+   { 0x1FAF, 0xA3, 0x0D }, { 0x1FB0, 0xA2, 0x0D }, { 0x1FB1, 0xA1, 0x0D }, 
+   { 0x1FB2, 0xA0, 0x0D }, { 0x1FB3, 0x9F, 0x0D }, { 0x1FB4, 0x9E, 0x0D }, 
+   { 0x1FB5, 0x9D, 0x0D }, { 0x1FB6, 0x9C, 0x0D }, { 0x1FB7, 0x9B, 0x0D }, 
+   { 0x1FB8, 0x9A, 0x0D }, { 0x1FB9, 0x99, 0x0D }, { 0x1FBA, 0x98, 0x0D }, 
+   { 0x1FBB, 0x97, 0x0D }, { 0x1FBC, 0x96, 0x0D }, { 0x1FBD, 0x95, 0x0D }, 
+   { 0x1FBE, 0x94, 0x0D }, { 0x1FBF, 0x93, 0x0D }, { 0x1FC0, 0x92, 0x0D }, 
+   { 0x1FC1, 0x91, 0x0D }, { 0x1FC2, 0x90, 0x0D }, { 0x1FC3, 0x8F, 0x0D }, 
+   { 0x1FC4, 0x8E, 0x0D }, { 0x1FC5, 0x8D, 0x0D }, { 0x1FC6, 0x8C, 0x0D }, 
+   { 0x1FC7, 0x8B, 0x0D }, { 0x1FC8, 0x8A, 0x0D }, { 0x1FC9, 0x89, 0x0D }, 
+   { 0x1FCA, 0x88, 0x0D }, { 0x1FCB, 0x87, 0x0D }, { 0x1FCC, 0x86, 0x0D }, 
+   { 0x1FCD, 0x85, 0x0D }, { 0x1FCE, 0x84, 0x0D }, { 0x1FCF, 0x83, 0x0D }, 
+   { 0x1FD0, 0x82, 0x0D }, { 0x1FD1, 0x81, 0x0D }, { 0x1FD2, 0x80, 0x0D }, 
+   { 0x1FD3, 0x7F, 0x0D }, { 0x1FD4, 0x7E, 0x0D }, { 0x1FD5, 0x7C, 0x0D }, 
+   { 0x1FD6, 0x5F, 0x0D }, { 0x1FD7, 0x5E, 0x0D }, { 0x1FD8, 0x5D, 0x0D }, 
+   { 0x1FD9, 0x5C, 0x0D }, { 0x1FDA, 0x5B, 0x0D }, { 0x1FDB, 0x40, 0x0D }, 
+   { 0x1FDC, 0x3E, 0x0D }, { 0x1FDD, 0x3D, 0x0D }, { 0x1FDE, 0x3B, 0x0D }, 
+   { 0x1FDF, 0x25, 0x0D }, { 0x1FE0, 0x24, 0x0D }, { 0x1FE1, 0x1F, 0x0D }, 
+   { 0x1FE2, 0x1E, 0x0D }, { 0x1FE3, 0x1D, 0x0D }, { 0x1FE4, 0x1C, 0x0D }, 
+   { 0x1FE5, 0x1B, 0x0D }, { 0x1FE6, 0x1A, 0x0D }, { 0x1FE7, 0x19, 0x0D }, 
+   { 0x1FE8, 0x18, 0x0D }, { 0x1FE9, 0x17, 0x0D }, { 0x1FEA, 0x16, 0x0D }, 
+   { 0x1FEB, 0x15, 0x0D }, { 0x1FEC, 0x14, 0x0D }, { 0x1FED, 0x13, 0x0D }, 
+   { 0x1FEE, 0x12, 0x0D }, { 0x1FEF, 0x11, 0x0D }, { 0x1FF0, 0x10, 0x0D }, 
+   { 0x1FF1, 0x0F, 0x0D }, { 0x1FF2, 0x0E, 0x0D }, { 0x1FF3, 0x0D, 0x0D }, 
+   { 0x1FF4, 0x0C, 0x0D }, { 0x1FF5, 0x0B, 0x0D }, { 0x1FF6, 0x09, 0x0D }, 
+   { 0x1FF7, 0x08, 0x0D }, { 0x1FF8, 0x07, 0x0D }, { 0x1FF9, 0x06, 0x0D }, 
+   { 0x1FFA, 0x05, 0x0D }, { 0x1FFB, 0x04, 0x0D }, { 0x1FFC, 0x03, 0x0D }, 
+   { 0x1FFD, 0x02, 0x0D }, { 0x1FFE, 0x01, 0x0D }, { 0x1FFF, 0x00, 0x0D }
+};
+
+}  //end of namespace
diff --git a/dish.h b/dish.h
new file mode 100644
index 0000000..f891d7b
--- /dev/null
+++ b/dish.h
@@ -0,0 +1,300 @@
+/***************************************************************************
+ *                                                                         *
+ *   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.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef LIBSI_DISH_H
+#define LIBSI_DISH_H
+
+#include <libsi/util.h>
+#include <libsi/descriptor.h>
+#include <time.h>
+
+namespace SI
+{
+
+   namespace DISH_THEMES {
+     enum eDishThemes {
+      Movie           = 0x01,
+      Sports          = 0x02,
+      News_Business   = 0x03,
+      Family_Children = 0x04,
+      Education       = 0x05,
+      Series_Special  = 0x06,
+      Music_Art       = 0x07,
+      Religious       = 0x08
+     };
+   };
+
+   namespace DISH_CATEGORIES {
+     enum eDishCategories {
+        Action                   = 0x01,
+        Adults_only              = 0x02,
+        Adventure                = 0x03,
+        Animals                  = 0x04,
+        Animated                 = 0x05,
+     //  Anime
+        Anthology                = 0x07,
+        Art                      = 0x08,
+        Auto                     = 0x09,
+        Awards                   = 0x0a,
+        Ballet                   = 0x0b,
+        Baseball                 = 0x0c,
+        Basketball               = 0x0d,
+     //  Beach soccer
+     //  Beach volleyball
+     //  Biathlon
+        Biography                = 0x11,
+        Boat                     = 0x12,
+     //  Boat racing
+        Bowling                  = 0x14,
+        Boxing                   = 0x15,
+        Bus_financial            = 0x16,
+        Children                 = 0x1a,
+        ChildrenSpecial          = 0x1b,
+        ChildrenNews             = 0x1c,
+        ChildrenMusic            = 0x1d,
+        Collectibles             = 0x1f,
+        Comedy                   = 0x20,
+        ComedyDrama              = 0x21,
+        Computers                = 0x22,
+        Cooking                  = 0x23,
+        Crime                    = 0x24,
+        CrimeDrama               = 0x25,
+     //  Curling
+        Dance                    = 0x27,
+     //  Dark comedy
+        Docudrama                = 0x29,
+        Documentary              = 0x2a,
+        Drama                    = 0x2b,
+        Educational              = 0x2c,
+     //  Erotic
+        Excercise                = 0x2f,
+        Fantasy                  = 0x31,
+        Fashion                   = 0x32,
+     //  Fencing
+        Fishing                  = 0x34,
+        Football                 = 0x35,
+        French                   = 0x36,
+        Fundraiser               = 0x37,
+        GameShow                 = 0x38,
+        Golf                     = 0x39,
+        Gymnastics               = 0x3a,
+        Health                   = 0x3b,
+        History                  = 0x3c,
+        HistoricalDrama          = 0x3d,
+        Hockey                   = 0x3e,
+        Holiday                  = 0x3f,
+        HolidayChildren          = 0x40,
+        HolidayChildrenSpecial   = 0x41,
+     //  Holiday music
+     //  Holiday music special
+        HolidaySpecial           = 0x44,
+        Horror                   = 0x45,
+        HorseRacing              = 0x46,
+        House_garden             = 0x47,
+        HowTo                    = 0x49,
+        Interview                = 0x4b,
+        Lacrosse                 = 0x4d,
+        MartialArts              = 0x4f,
+        Medical                  = 0x50,
+        Miniseries               = 0x51,
+        Motorsports              = 0x52,
+        Motorcycle               = 0x53,
+        Music                    = 0x54,
+        MusicSpecial             = 0x55,
+        MusicTalk                = 0x56,
+        Musical                  = 0x57,
+        MusicalComedy            = 0x58,
+        Mystery                  = 0x5a,
+        Nature                   = 0x5b,
+        News                     = 0x5c,
+     //  Olympics
+        Opera                    = 0x5f,
+        Outdoors                 = 0x60,
+     //  Parade
+     //  Politics                =  0x62,
+        PublicAffairs            = 0x63,
+        Reality                  = 0x66,
+        Religious                = 0x67,
+        Rodeo                    = 0x68,
+        Romance                  = 0x69,
+        RomanceComedy            = 0x6a,
+        Rugby                    = 0x6b,
+        Running                  = 0x6c,
+        Science                  = 0x6e,
+        ScienceFiction           = 0x6f,
+        SelfImprovement          = 0x70,
+        Shopping                 = 0x71,
+        Skiing                   = 0x74,
+        Soap                     = 0x77,
+     //  Soap special
+     //  Soap talk
+        Soccor                   = 0x7b,
+        Softball                 = 0x7c,
+        Spanish                  = 0x7d,
+        Special                  = 0x7e,
+     //  Speedskating
+     //  Sports event
+        SportsNonEvent           = 0x81,
+        SportsTalk               = 0x82,
+        Suspense                 = 0x83,
+        Swimming                 = 0x85,
+        Talk                     = 0x86,
+        Tennis                   = 0x87,
+     //  Theater
+     //  Thriller
+        Track_field              = 0x89,
+        Travel                   = 0x8a,
+        Variety                  = 0x8b,
+        Volleyball               = 0x8c,
+        War                      = 0x8d,
+        Watersports              = 0x8e,
+        Weather                  = 0x8f,
+        Western                  = 0x90,
+        Wrestling                = 0x92,
+        Yoga                     = 0x93,
+        Agriculture              = 0x94,
+        Anime                    = 0x95,
+        ArmWrestling             = 0x97,
+        Arts_crafts              = 0x98,
+        Auction                  = 0x99,
+        AutoRacing               = 0x9a,
+        AirRacing                = 0x9b,
+        Badminton                = 0x9c,
+     //  Bicycle
+        BicycleRacing            = 0xa0,
+        BoatRacing               = 0xa1,
+     //  Bobsled
+     //  Bodybilding
+     //  Canoe
+     //  Cheerleading
+        Community                = 0xa6,
+        Consumer                 = 0xa7,
+     //  Darts
+        Debate                   = 0xaa,
+     //  Diving
+        DogShow                  = 0xac,
+        DragRacing               = 0xad,
+        Entertainment            = 0xae,
+        Environment              = 0xaf,
+        Equestrian               = 0xb0,
+     //  Event
+        FieldHockey              = 0xb3,
+     //  Figure skating
+        Football2                = 0xb5,
+        Gay_lesbian              = 0xb6,
+        Handball                 = 0xb7,
+        HomeImprovement          = 0xb8,
+        Hunting                  = 0xb9,
+     //  Hurling
+        HydroplaneRacing         = 0xbb,
+     //  Indoor soccer
+     //  Intl hockey
+     //  Intl soccer
+     //  Kayaking
+        Law                      = 0xc1,
+     //  Luge
+     //  Mountain biking
+        MotorcycleRacing         = 0xc3,
+        Newsmagazine             = 0xc5,
+        Paranormal               = 0xc7,
+        Parenting                = 0xc8,
+        PerformingArts           = 0xca,
+     //  Playoff sports
+        Politics                 = 0xcc,
+     //  Polo
+     //  Pool
+        ProWrestling             = 0xcf,
+     //  Ringuette
+     //  Roller derby
+     //  Rowing
+        Sailing                  = 0xd3,
+        Shooting                 = 0xd4,
+        Sitcom                   = 0xd5,
+        Skateboarding            = 0xd6,
+     //  Skating
+     //  Skeleton
+        Snowboarding             = 0xd9,
+     //  Snowmobile              =  0xda,
+        Standup                  = 0xdd,
+     //  Sumo wrestling
+        Surfing                  = 0xdf,
+        Tennis2                  = 0xe0,
+        Triathlon                = 0xe1,
+     //  Water polo
+     //  Water skiing
+     //  Weightlifting
+     //  Yacht racing
+        CardGames                = 0xe6 ,
+        Poker                    = 0xe7 ,
+     //  Musical                 =  0xe9,
+        Military                 = 0xea,
+        Technology               = 0xeb,
+        MixedMartialArts         = 0xec,
+        ActionSports             = 0xed,
+        DishNetwork              = 0xff
+     };
+   };
+#define SIZE_TABLE_128 128
+#define SIZE_TABLE_255 255
+
+using namespace std;
+
+class DishDescriptor {
+public:
+    DishDescriptor();
+    virtual ~DishDescriptor();
+    const char* getName(void) const { return name; }
+    const char* getShortText(void);
+    const char *getDescription(void);
+    //   const char* getShortText(void) const { return shortText?shortText->c_str():""; }
+    //   const char* getDescription(void) const { return description?description->c_str():""; }
+    const char *getTheme();
+    const char *getCategory();
+    const char *getRating();
+    const char *getStarRating();
+    const char *getSeriesId();
+    const char *getProgramId();
+    time_t getOriginalAirDate() { return originalAirDate; }
+    bool hasTheme() {return DishTheme > 0;}
+    bool hasCategory() {return DishCategory > 0;}
+    void setShortData(unsigned char Tid, CharArray data);
+    void setExtendedtData(unsigned char Tid, CharArray data);
+    void setRating(uint16_t value);
+    void setContent(ContentDescriptor::Nibble Nibble);
+    void setEpisodeInfo(CharArray data);
+
+protected:
+    // Decompress the byte array and stores the result to a text string
+    unsigned char* Decompress(unsigned char Tid, CharArray data);
+    const char* name; // name of the event
+    const char* shortText; // usually the episode name
+    const char* description; // description of the event
+    unsigned char* decompressedShort;
+    unsigned char* decompressedExtended;
+    unsigned char DishTheme;
+    unsigned char DishCategory;
+    uint16_t mpaaRating;
+    uint8_t starRating;
+    time_t originalAirDate;
+    char* seriesId;
+    char* programId;
+    char* ratingStr;
+
+    struct HuffmanTable
+    {
+        unsigned int startingAddress;
+        unsigned char character;
+        unsigned char numberOfBits;
+    };
+    static HuffmanTable Table128[SIZE_TABLE_128];
+    static HuffmanTable Table255[SIZE_TABLE_255];
+};
+
+} /* namespace SI */
+#endif /* LIBSI_DISH_H */
diff --git a/eepg.c b/eepg.c
new file mode 100644
index 0000000..fc7a5b0
--- /dev/null
+++ b/eepg.c
@@ -0,0 +1,3628 @@
+/*
+ * Extended Epg plugin to VDR (C++)
+ *
+ * (C) 2008-2009 Dingo35
+ *
+ * This code is based on:
+ * -Premiere plugin (C) 2005-2007 Stefan Huelswitt <s.huelswitt at gmx.de>
+ * -mhwepg program  (C) 2002, 2003 Jean-Claude Repetto <mhwepg at repetto.org>
+ * -LoadEpg plugin written by Luca De Pieri <dpluca at libero.it>
+ * -Freesat patch written by dom /at/ suborbital.org.uk
+ *
+ *
+ * This code 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 code 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <vdr/plugin.h>
+#include <vdr/filter.h>
+#include <vdr/epg.h>
+#include <vdr/channels.h>
+#include <vdr/dvbdevice.h>
+#include <vdr/i18n.h>
+#include <vdr/config.h>
+#include <libsi/section.h>
+#include <libsi/descriptor.h>
+#include <libsi/si.h>
+#include "eepg.h"
+#include "dish.h"
+#if APIVERSNUM > 10725
+#include "epghandler.h"
+#endif
+#include "log.h"
+#include "setupeepg.h"
+#include "equivhandler.h"
+#include "util.h"
+#include "eit2.h"
+
+#include <map>
+#include <string>
+#include <stdarg.h>
+
+
+#if APIVERSNUM < 10401
+#error You need at least VDR API version 1.4.1 for this plugin
+#endif
+#if APIVERSNUM < 10507
+#define trNOOP(s) (s)
+#endif
+
+#define PMT_SCAN_TIMEOUT  10 // seconds
+#define PMT_SCAN_IDLE     3600 // seconds
+
+static const char *VERSION = "0.0.6pre";
+static const char *DESCRIPTION = trNOOP ("Parses Extended EPG data");
+
+using namespace std;
+using namespace util;
+
+const char *optPats[] = {
+  "%s",
+  "%s (Option %d)",
+  "%s (O%d)",
+  "#%2$d %1$s",
+  "[%2$d] %1$s"
+};
+
+#define NUM_PATS (sizeof(optPats)/sizeof(char *))
+
+char *cs_hexdump (int m, const uchar * buf, int n)
+{
+  int i;
+  static char dump[1024];
+
+  dump[i = 0] = '\0';
+  m = (m) ? 3 : 2;
+  if (m * n >= (int) sizeof (dump))
+    n = (sizeof (dump) / m) - 1;
+  while (i < n)
+    sprintf (dump + (m * i++), "%02X%s", *buf++, (m > 2) ? " " : "");
+  return (dump);
+}
+
+cSetupEEPG* SetupPE = cSetupEEPG::getInstance();
+
+// --- cMenuSetupPremiereEpg ------------------------------------------------------------
+
+class cMenuSetupPremiereEpg:public cMenuSetupPage
+{
+private:
+  cSetupEEPG* data;
+  const char *optDisp[NUM_PATS];
+  char buff[NUM_PATS][32];
+protected:
+  virtual void Store (void);
+public:
+  cMenuSetupPremiereEpg (void);
+};
+
+cMenuSetupPremiereEpg::cMenuSetupPremiereEpg (void)
+{
+  data = cSetupEEPG::getInstance();
+  SetSection (tr ("PremiereEPG"));
+  optDisp[0] = tr ("off");
+  for (unsigned int i = 1; i < NUM_PATS; i++) {
+    snprintf (buff[i], sizeof (buff[i]), optPats[i], "Event", 1);
+    optDisp[i] = buff[i];
+  }
+  Add (new cMenuEditStraItem (tr ("Tag option events"), &data->OptPat, NUM_PATS, optDisp));
+  Add (new cMenuEditBoolItem (tr ("Show order information"), &data->OrderInfo));
+  Add (new cMenuEditBoolItem (tr ("Show rating information"), &data->RatingInfo));
+  Add (new cMenuEditBoolItem (tr ("Fix EPG data"), &data->FixEpg));
+  Add (new cMenuEditBoolItem (tr ("Display summary message"), &data->DisplayMessage));
+#ifdef DEBUG
+  Add (new cMenuEditIntItem (tr ("Level of logging verbosity"), &data->LogLevel, 0, 5));
+  Add (new cMenuEditBoolItem (tr ("Process EIT info with EEPG"), &data->ProcessEIT));
+#endif
+}
+
+void cMenuSetupPremiereEpg::Store (void)
+{
+  //SetupPE = data;
+  SetupStore ("OptionPattern", SetupPE->OptPat);
+  SetupStore ("OrderInfo", SetupPE->OrderInfo);
+  SetupStore ("RatingInfo", SetupPE->RatingInfo);
+  SetupStore ("FixEpg", SetupPE->FixEpg);
+  SetupStore ("DisplayMessage", SetupPE->DisplayMessage);
+#ifdef DEBUG
+  SetupStore ("LogLevel", SetupPE->LogLevel);
+  SetupStore ("ProcessEIT", SetupPE->ProcessEIT);
+#endif
+}
+
+//#define Asprintf(a, b, c...) void( asprintf(a, b, c) < 0 ? esyslog("memory allocation error - %s", b) : void() )
+
+// --- CRC16 -------------------------------------------------------------------
+
+#define POLY 0xA001  // CRC16
+
+unsigned int crc16 (unsigned int crc, unsigned char const *p, int len)
+{
+  while (len--) {
+    crc ^= *p++;
+    for (int i = 0; i < 8; i++)
+      crc = (crc & 1) ? (crc >> 1) ^ POLY : (crc >> 1);
+  }
+  return crc & 0xFFFF;
+}
+
+// --- cFilterEEPG ------------------------------------------------------
+
+#define STARTTIME_BIAS (20*60)
+
+static int LastVersionNagra = -1; //currently only used for Nagra, should be stored per transponder, per system
+
+
+class cFilterEEPG:public cFilter
+{
+private:
+  int pmtpid, pmtsid, pmtidx, pmtnext;
+  int UnprocessedFormat[HIGHEST_FORMAT + 1]; //stores the pid when a format is detected on this transponder, and that are not processed yet
+  int nChannels, nThemes, nTitles, nSummaries, NumberOfTables, Version;
+  int TitleCounter, SummaryCounter, NoSummaryCounter, RejectTableId;
+  bool EndChannels, EndThemes; //only used for ??
+  int MHWStartTime; //only used for MHW1
+  bool ChannelsOk;
+  //int Format; //the format that this filter currently is processing
+  std::map < int, int >ChannelSeq; // ChannelSeq[ChannelId] returns the recordnumber of the channel
+
+  Summary_t *Summaries[MAX_TITLES];
+  Title_t *Titles[MAX_TITLES];
+  sChannel sChannels[MAX_CHANNELS];
+  unsigned char Themes[MAX_THEMES][64];
+
+  std::map < unsigned short int, unsigned char *>buffer; //buffer[Table_Extension_Id] returns the pointer to the buffer for this TEI
+  std::map < unsigned short int, int >bufsize; //bufsize[Table_Extension_Id] returns the buffersize of the buffer for this TEI
+  unsigned short int NagraTIE[64]; //at this moment a max of 31 table_ids could be used, so 64 should be enough ....stores the Table_Extension_Id's of summaries received, so they can be processed. Processing while receiving somehow drops sections, the 0x0000 marker will be missed ...
+  unsigned short int NagraCounter;
+
+  unsigned char InitialChannel[8];
+  unsigned char InitialTitle[64];
+  unsigned char InitialSummary[64];
+
+  void NextPmt (void);
+  void ProccessContinuous(u_short Pid, u_char Tid, int Length, const u_char *Data);
+protected:
+  virtual void Process (u_short Pid, u_char Tid, const u_char * Data, int Length);
+  virtual void AddFilter (u_short Pid, u_char Tid);
+  virtual void AddFilter (u_short Pid, u_char Tid, unsigned char Mask);
+  virtual void ProcessNextFormat (bool FirstTime);
+  virtual int GetChannelsSKYBOX (const u_char * Data, int Length);
+  virtual bool GetThemesSKYBOX (void);
+  virtual int GetTitlesSKYBOX (const u_char * Data, int Length);
+  virtual int GetSummariesSKYBOX (const u_char * Data, int Length);
+  virtual int GetChannelsMHW (const u_char * Data, int Length, int MHW); //TODO replace MHW by Format?
+  virtual int GetThemesMHW1 (const u_char * Data, int Length);
+  virtual int GetNagra (const u_char * Data, int Length);
+  virtual void ProcessNagra (void);
+  virtual void GetTitlesNagra (const u_char * Data, int Length, unsigned short TableIdExtension);
+  virtual char *GetSummaryTextNagra (const u_char * DataStart, long int Offset, unsigned int EventId);
+  virtual int GetChannelsNagra (const u_char * Data, int Length);
+  virtual int GetThemesNagra (const u_char * Data, int Length, unsigned short TableIdExtension);
+  virtual int GetTitlesMHW1 (const u_char * Data, int Length);
+  virtual int GetSummariesMHW1 (const u_char * Data, int Length);
+  virtual int GetThemesMHW2 (const u_char * Data, int Length);
+  virtual int GetTitlesMHW2 (const u_char * Data, int Length);
+  virtual int GetSummariesMHW2 (const u_char * Data, int Length);
+  virtual void FreeSummaries (void);
+  virtual void FreeTitles (void);
+  //virtual void PrepareToWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps/*[MAX_EQUIVALENCES]*/); //gets a channel and returns an array of schedules that WriteToSchedule can write to. Call this routine before a batch of titles with the same ChannelId will be WriteToScheduled; batchsize can be 1
+  //virtual void FinishWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES]);
+  virtual void WriteToSchedule (tChannelID channelID, cSchedules* s, unsigned int EventId, unsigned int StartTime,
+                                unsigned int Duration, char *Text, char *SummText, unsigned short int ThemeId,
+                                unsigned short int TableId, unsigned short int Version, char Rating = 0x00);
+  virtual void LoadIntoSchedule (void);
+  //virtual void LoadEquivalentChannels (void);
+
+  void ProcessPremiere(const u_char *& Data);
+public:
+  cFilterEEPG (void);
+  virtual void SetStatus (bool On);
+  void Trigger (void);
+  bool InitDictionary (void); //Initialize the Huffman tables for SKY and Freesat
+
+  static const int EIT_PID = 0x12;
+};
+
+cFilterEEPG::cFilterEEPG (void)
+{
+  nSummaries = 0;
+  nTitles = 0;
+  Trigger ();
+  //Set (0x00, 0x00);
+}
+
+void cFilterEEPG::Trigger (void)
+{
+  LogI(3, prep("trigger\n"));
+  pmtpid = 0;
+  pmtidx = 0;
+  pmtnext = 0;
+}
+
+void cFilterEEPG::SetStatus (bool On)
+{
+  LogI(0, prep("setstatus %d\n"), On);
+  if (!On) {
+    FreeSummaries ();
+    FreeTitles ();
+    //Format = 0;
+    ChannelsOk = false;
+    NumberOfTables = 0;
+  } else {
+    //Set(0x00,0x00);
+    for (int i = 0; i <= HIGHEST_FORMAT; i++)
+      UnprocessedFormat[i] = 0; //pid 0 is assumed to be nonvalid for EEPG transfers
+    AddFilter (0, 0);
+  }
+  cFilter::SetStatus (On);
+  Trigger ();
+}
+
+void cFilterEEPG::NextPmt (void)
+{
+  Del (pmtpid, 0x02);
+  pmtpid = 0;
+  pmtidx++;
+  LogE(3, prep("PMT next\n"));
+}
+
+
+
+// -------------------  Freesat -------------------
+
+/* FreeSat Huffman decoder for VDR
+ *
+ * Insert GPL licence
+ */
+
+/* The following features can be controlled:
+ *
+ * FREEVIEW_NO_SYSLOG             - Disable use of isyslog
+ */
+
+#ifndef FREEVIEW_NO_SYSLOG
+#include <vdr/tools.h>
+/* Logging via vdr */
+#ifndef isyslog
+#define isyslog(a...) void( (SysLogLevel > 1) ? syslog_with_tid(LOG_INFO,  a) : void() )
+#endif
+void syslog_with_tid (int priority, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
+#else
+#define isyslog(a...)  fprintf(stderr,a)
+#endif
+
+
+
+//struct hufftab {
+//  unsigned int value;
+//  short bits;
+//  char next;
+//};
+//
+//#define START   '\0'
+//#define STOP    '\0'
+//#define ESCAPE  '\1'
+
+
+//int freesat_decode_error = 0; /* If set an error has occurred during decoding */
+
+//static struct hufftab *tables[2][128];
+//static int table_size[2][128];
+static sNodeH* sky_tables[2];
+
+/** \brief Convert a textual character description into a value
+ *
+ *  \param str - Encoded (in someway) string
+ *
+ *  \return Raw character
+ */
+static unsigned char resolve_char (char *str)
+{
+  int val;
+  if (strcmp (str, "ESCAPE") == 0) {
+    return ESCAPE;
+  } else if (strcmp (str, "STOP") == 0) {
+    return STOP;
+  } else if (strcmp (str, "START") == 0) {
+    return START;
+  } else if (sscanf (str, "0x%02x", &val) == 1) {
+    return val;
+  }
+  return str[0];
+
+
+}
+
+
+/** \brief Decode a binary string into a value
+ *
+ *  \param binary - Binary string to decode
+ *
+ *  \return Decoded value
+ */
+static unsigned long decode_binary (char *binary)
+{
+  unsigned long mask = 0x80000000;
+  unsigned long maskval = 0;
+  unsigned long val = 0;
+  size_t i;
+
+  for (i = 0; i < strlen (binary); i++) {
+    if (binary[i] == '1') {
+      val |= mask;
+    }
+    maskval |= mask;
+    mask >>= 1;
+  }
+  return val;
+}
+
+/** \brief Load an individual freesat data file
+ *
+ *  \param tableid   - Table id that should be loaded
+ *  \param filename  - Filename to load
+ *  \return Success of operation
+ */
+static bool load_freesat_file (int tableid, const char *filename)
+{
+  char buf[1024];
+  char *from, *to, *binary;
+  FILE *fp;
+
+  tableid--;
+  if ((fp = fopen (filename, "r")) != NULL) {
+    LogI(2, prep("Loading table %d Filename <%s>"), tableid + 1, filename);
+
+    while (fgets (buf, sizeof (buf), fp) != NULL) {
+      from = binary = to = NULL;
+      int elems = sscanf (buf, "%a[^:]:%a[^:]:%a[^:]:", &from, &binary, &to);
+      if (elems == 3) {
+        int bin_len = strlen (binary);
+        int from_char = resolve_char (from);
+        char to_char = resolve_char (to);
+        unsigned long bin = decode_binary (binary);
+        int i = table_size[tableid][from_char]++;
+
+        tables[tableid][from_char] =
+          (struct hufftab *) REALLOC (tables[tableid][from_char], (i + 1) * sizeof (tables[tableid][from_char][0]));
+        tables[tableid][from_char][i].value = bin;
+        tables[tableid][from_char][i].next = to_char;
+        tables[tableid][from_char][i].bits = bin_len;
+        /* char from; unsigned int value; short bits; char next; */
+        LogI(2, prep("%02x;%08x;%04x;%02x"), from_char, bin, bin_len, to_char);
+
+        free (from);
+        free (to);
+        free (binary);
+      }
+    }
+    fclose (fp);
+  } else {
+    LogE(0, prep("Cannot load <%s> for table %d"), filename, tableid + 1);
+    return false;
+  }
+  return true;
+}
+
+/** \brief Load an individual freesat data file
+ *
+ *  \param filename  - Filename to load
+ *  \return Success of operation
+ */
+static bool load_sky_file (const char *filename)
+{
+  FILE *FileDict;
+  char *Line;
+  char Buffer[256];
+  sNodeH *nH;
+  int tableId;
+
+  FileDict = fopen (filename, "r");
+  if (FileDict == NULL) {
+    LogE (0, prep("Error opening file '%s'. %s"), filename, strerror (errno));
+    return false;
+  } else {
+    int i;
+    int LenPrefix;
+    char string1[256];
+    char string2[256];
+
+    tableId = Format == SKY_IT ? 0 : 1;
+    if (!sky_tables[tableId]) {
+      sky_tables[tableId] = (sNodeH*) calloc(1,sizeof(sNodeH));
+      if (!sky_tables[tableId]) {
+        LogE (0, prep("Not enough memory to load file '%s'."), filename);
+        return false;
+      }
+    }
+
+    while ((Line = fgets (Buffer, sizeof (Buffer), FileDict)) != NULL) {
+      if (!isempty (Line)) {
+        memset (string1, 0, sizeof (string1));
+        memset (string2, 0, sizeof (string2));
+        if (sscanf (Line, "%c=%[^\n]\n", string1, string2) == 2
+          || (sscanf (Line, "%[^=]=%[^\n]\n", string1, string2) == 2)) {
+          nH = sky_tables[tableId];
+          LenPrefix = strlen (string2);
+          for (i = 0; i < LenPrefix; i++) {
+            switch (string2[i]) {
+            case '0':
+              if (nH->P0 == NULL) {
+                nH->P0 = new sNodeH ();
+                nH = nH->P0;
+                nH->Value = NULL;
+                nH->P0 = NULL;
+                nH->P1 = NULL;
+                if ((LenPrefix - 1) == i) {
+                  Asprintf (&nH->Value, "%s", string1);
+                }
+              } else {
+                nH = nH->P0;
+                if (nH->Value != NULL || (LenPrefix - 1) == i) {
+                  LogE (0 ,prep("Error, huffman prefix code already exists for \"%s\"=%s with '%s'"), string1,
+                    string2, nH->Value);
+                }
+              }
+              break;
+            case '1':
+              if (nH->P1 == NULL) {
+                nH->P1 = new sNodeH ();
+                nH = nH->P1;
+                nH->Value = NULL;
+                nH->P0 = NULL;
+                nH->P1 = NULL;
+                if ((LenPrefix - 1) == i) {
+                  Asprintf (&nH->Value, "%s", string1);
+                }
+              } else {
+                nH = nH->P1;
+                if (nH->Value != NULL || (LenPrefix - 1) == i) {
+                  LogE (0, prep("Error, huffman prefix code already exists for \"%s\"=%s with '%s'"), string1,
+                    string2, nH->Value);
+                }
+              }
+              break;
+            default:
+              break;
+            }
+          }
+        }
+      }
+    }
+    fclose (FileDict);
+  }
+
+  // check tree huffman nodes
+  FileDict = fopen (filename, "r");
+  if (FileDict) {
+    int i;
+    int LenPrefix;
+    char string1[256];
+    char string2[256];
+    while ((Line = fgets (Buffer, sizeof (Buffer), FileDict)) != NULL) {
+      if (!isempty (Line)) {
+        memset (string1, 0, sizeof (string1));
+        memset (string2, 0, sizeof (string2));
+        if (sscanf (Line, "%c=%[^\n]\n", string1, string2) == 2
+          || (sscanf (Line, "%[^=]=%[^\n]\n", string1, string2) == 2)) {
+          nH = sky_tables[tableId];
+          LenPrefix = strlen (string2);
+          for (i = 0; i < LenPrefix; i++) {
+            switch (string2[i]) {
+            case '0':
+              if (nH->P0 != NULL) {
+                nH = nH->P0;
+              }
+              break;
+            case '1':
+              if (nH->P1 != NULL) {
+                nH = nH->P1;
+              }
+              break;
+            default:
+              break;
+            }
+          }
+          if (nH->Value != NULL) {
+            if (memcmp (nH->Value, string1, strlen (nH->Value)) != 0) {
+              LogE (0, prep("Error, huffman prefix value '%s' not equal to '%s'"), nH->Value, string1);
+            }
+          } else {
+            LogE (0, prep("Error, huffman prefix value is not exists for \"%s\"=%s"), string1, string2);
+          }
+        }
+      }
+    }
+    fclose (FileDict);
+  }
+  return true;
+}
+
+/** \brief Decode an EPG string as necessary
+ *
+ *  \param src - Possibly encoded string
+ *  \param size - Size of the buffer
+ *
+ *  \retval NULL - Can't decode
+ *  \return A decoded string
+ */
+char *freesat_huffman_decode (const unsigned char *src, size_t size)
+{
+  int tableid;
+//  freesat_decode_error = 0;
+
+  if (src[0] == 0x1f && (src[1] == 1 || src[1] == 2)) {
+    int uncompressed_len = 30;
+    char *uncompressed = (char *) calloc (1, uncompressed_len + 1);
+    unsigned value = 0, byte = 2, bit = 0;
+    int p = 0;
+    unsigned char lastch = START;
+
+    tableid = src[1] - 1;
+    while (byte < 6 && byte < size) {
+      value |= src[byte] << ((5 - byte) * 8);
+      byte++;
+    }
+    //freesat_table_load ();    /**< Load the tables as necessary */
+
+    do {
+      bool found = false;
+      unsigned bitShift = 0;
+      if (lastch == ESCAPE) {
+        char nextCh = (value >> 24) & 0xff;
+        found = true;
+        // Encoded in the next 8 bits.
+        // Terminated by the first ASCII character.
+        bitShift = 8;
+        if ((nextCh & 0x80) == 0)
+          lastch = nextCh;
+        if (p >= uncompressed_len) {
+          uncompressed_len += 10;
+          uncompressed = (char *) REALLOC (uncompressed, uncompressed_len + 1);
+        }
+        uncompressed[p++] = nextCh;
+        uncompressed[p] = 0;
+      } else {
+        int j;
+        for (j = 0; j < table_size[tableid][lastch]; j++) {
+          unsigned mask = 0, maskbit = 0x80000000;
+          short kk;
+          for (kk = 0; kk < tables[tableid][lastch][j].bits; kk++) {
+            mask |= maskbit;
+            maskbit >>= 1;
+          }
+          if ((value & mask) == tables[tableid][lastch][j].value) {
+            char nextCh = tables[tableid][lastch][j].next;
+            bitShift = tables[tableid][lastch][j].bits;
+            if (nextCh != STOP && nextCh != ESCAPE) {
+              if (p >= uncompressed_len) {
+                uncompressed_len += 10;
+                uncompressed = (char *) REALLOC (uncompressed, uncompressed_len + 1);
+              }
+              uncompressed[p++] = nextCh;
+              uncompressed[p] = 0;
+            }
+            found = true;
+            lastch = nextCh;
+            break;
+          }
+        }
+      }
+      if (found) {
+        // Shift up by the number of bits.
+        unsigned b;
+        for (b = 0; b < bitShift; b++) {
+          value = (value << 1) & 0xfffffffe;
+          if (byte < size)
+            value |= (src[byte] >> (7 - bit)) & 1;
+          if (bit == 7) {
+            bit = 0;
+            byte++;
+          } else
+            bit++;
+        }
+      } else {
+        LogE (0, prep("Missing table %d entry: <%s>"), tableid + 1, uncompressed);
+        // Entry missing in table.
+        return uncompressed;
+      }
+    } while (lastch != STOP && value != 0);
+
+    return uncompressed;
+  }
+  return NULL;
+}
+
+int sky_huffman_decode (const u_char * Data, int Length, unsigned char *DecodeText)
+{
+  sNodeH *nH, H=(Format==SKY_IT)?*sky_tables[0]:*sky_tables[1];
+  int i;
+  int p;
+  int q;
+  bool CodeError;
+  bool IsFound;
+  unsigned char Byte;
+  unsigned char lastByte;
+  unsigned char Mask;
+  unsigned char lastMask;
+  nH = &H;
+  p = 0;
+  q = 0;
+  DecodeText[0] = '\0';
+  //DecodeErrorText[0] = '\0';
+  CodeError = false;
+  IsFound = false;
+  lastByte = 0;
+  lastMask = 0;
+  for (i = 0; i < Length; i++) {
+    Byte = Data[i];
+    Mask = 0x80;
+    if (i == 0) {
+      Mask = 0x20;
+      lastByte = i;
+      lastMask = Mask;
+    }
+loop1:
+    if (IsFound) {
+      lastByte = i;
+      lastMask = Mask;
+      IsFound = false;
+    }
+    if ((Byte & Mask) == 0) {
+      if (CodeError) {
+        //DecodeErrorText[q] = 0x30;
+        q++;
+        goto nextloop1;
+      }
+      if (nH->P0 != NULL) {
+        nH = nH->P0;
+        if (nH->Value != NULL) {
+          memcpy (&DecodeText[p], nH->Value, strlen (nH->Value));
+          p += strlen (nH->Value);
+          nH = &H;
+          IsFound = true;
+        }
+      } else {
+        memcpy (&DecodeText[p], "<...?...>", 9);
+        p += 9;
+        i = lastByte;
+        Byte = Data[lastByte];
+        Mask = lastMask;
+        CodeError = true;
+        goto loop1;
+      }
+    } else {
+      if (CodeError) {
+        //DecodeErrorText[q] = 0x31;
+        q++;
+        goto nextloop1;
+      }
+      if (nH->P1 != NULL) {
+        nH = nH->P1;
+        if (nH->Value != NULL) {
+          memcpy (&DecodeText[p], nH->Value, strlen (nH->Value));
+          p += strlen (nH->Value);
+          nH = &H;
+          IsFound = true;
+        }
+      } else {
+        memcpy (&DecodeText[p], "<...?...>", 9);
+        p += 9;
+        i = lastByte;
+        Byte = Data[lastByte];
+        Mask = lastMask;
+        CodeError = true;
+        goto loop1;
+      }
+    }
+nextloop1:
+    Mask = Mask >> 1;
+    if (Mask > 0) {
+      goto loop1;
+    }
+  }
+  DecodeText[p] = '\0';
+  //DecodeErrorText[q] = '\0';
+  return p;
+}
+
+//here all declarations for global variables over all devices
+
+//char *ConfDir;
+
+//unsigned char DecodeErrorText[4096];  //TODO only used for debugging?
+
+bool cFilterEEPG::GetThemesSKYBOX (void) //TODO can't we read this from the DVB stream?
+{
+  string FileName = cSetupEEPG::getInstance()->getConfDir();
+  FILE *FileThemes;
+  char *Line;
+  char Buffer[256];
+  if (Format == SKY_IT)
+    FileName += "/sky_it.themes";
+  else if (Format == SKY_UK)
+    FileName += "/sky_uk.themes";
+  else {
+    LogE (0, prep("Error, wrong format detected in GetThemesSKYBOX. Format = %i."), Format);
+    return false;
+  }
+  //asprintf( &FileName, "%s/%s", ConfDir, ( lProviders + CurrentProvider )->Parm3 );
+  FileThemes = fopen (FileName.c_str(), "r");
+  if (FileThemes == NULL) {
+    LogE (0, prep("Error opening file '%s'. %s"), FileName.c_str(), strerror (errno));
+    return false;
+  } else {
+    //int id = 0;
+    nThemes = 0;
+    char string1[256];
+    char string2[256];
+    //sTheme *T;
+    while ((Line = fgets (Buffer, sizeof (Buffer), FileThemes)) != NULL) {
+      memset (string1, 0, sizeof (string1));
+      memset (string2, 0, sizeof (string2));
+      if (!isempty (Line)) {
+        //T = &Themes[nThemes];
+        if (sscanf (Line, "%[^=] =%[^\n] ", string1, string2) == 2) {
+          snprintf ((char *) Themes[nThemes], 255, "%s", string2);
+        } else {
+          Themes[nThemes][0] = '\0';
+        }
+        //id ++;
+        nThemes++;
+      }
+    }
+    fclose (FileThemes);
+  }
+  return true;
+}
+
+/**
+ * \brief Initialize the Huffman dictionaries if they are not already initialized.
+ *
+ */
+bool cFilterEEPG::InitDictionary (void)
+{
+  string FileName = cSetupEEPG::getInstance()->getConfDir();
+  switch (Format) {
+  case SKY_IT:
+    if (sky_tables[0] == NULL) {
+      FileName += "/sky_it.dict";
+      LogD (4, prep("EEPGDebug: loading sky_it.dict"));
+      return load_sky_file(FileName.c_str());
+    } else
+        LogD (4, prep("EEPGDebug: sky_it.dict already loaded"));
+    break;
+  case SKY_UK:
+    if (sky_tables[1] == NULL) {
+      FileName += "/sky_uk.dict";
+      LogD (4, prep("EEPGDebug: loading sky_uk.dict"));
+      return load_sky_file(FileName.c_str());
+    } else
+        LogD (4, prep("EEPGDebug: sky_uk.dict already loaded"));
+    break;
+  case FREEVIEW:
+    if (tables[0][0] == NULL) {
+      LogD (4, prep("EEPGDebug: loading freesat.dict"));
+      FileName += "/freesat.t1";
+      if (!load_freesat_file (1, FileName.c_str()))
+        return false;
+      FileName = cSetupEEPG::getInstance()->getConfDir();
+      FileName += "/freesat.t2";
+      return load_freesat_file (2, FileName.c_str());
+    } else
+        LogD (4, prep("EEPGDebug: freesat.dict already loaded"));
+    break;
+  default:
+    LogE (0 ,prep("Error, wrong format detected in ReadFileDictionary. Format = %i."), Format);
+    return false;
+  }
+  return true;
+}
+
+//void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize)
+//{
+//  if (from[0] == 0x1f) {
+//    char *temp = freesat_huffman_decode (from, len);
+//    if (temp) {
+//      len = strlen (temp);
+//      len = len < buffsize - 1 ? len : buffsize - 1;
+//      strncpy (buffer, temp, len);
+//      buffer[len] = 0;
+//      free (temp);
+//      return;
+//    }
+//  }
+//
+//  SI::String convStr;
+//  SI::CharArray charArray;
+//  charArray.assign(from, len);
+//  convStr.setData(charArray, len);
+//  //LogE(5, prep("decodeText2 from %s - length %d"), from, len);
+//  convStr.getText(buffer,  buffsize);
+//  //LogE(5, prep("decodeText2 buffer %s - buffsize %d"), buffer, buffsize);
+//}
+
+/**
+ * \brief Get MHW channels
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetChannelsMHW (const u_char * Data, int Length, int MHW)
+{
+  if ((MHW == 1) || (nChannels == 0)) { //prevents MHW2 from reading channels twice while waiting for themes on same filter
+    sChannelMHW1 *Channel;
+    int Size, Off;
+    Size = sizeof (sChannelMHW1);
+    Off = 4;
+    if (MHW == 1) {
+      //Channel = (sChannelMHW1 *) (Data + 4);
+      nChannels = (Length - Off) / sizeof (sChannelMHW1);
+    }
+    if (MHW == 2) {
+      if (Length > 120)
+        nChannels = Data[120];
+      else {
+        LogE(0, prep("Error, channels packet too short for MHW2."));
+        return 0;
+      }
+      int pName = ((nChannels * 8) + 121);
+      if (Length > pName) {
+        //Channel = (sChannelMHW1 *) (Data + 120);
+        Size -= 14; //MHW2 is 14 bytes shorter
+        Off = 121;  //and offset differs
+      } else {
+        LogE(0, prep("Error, channels length does not match pname."));
+        return 0;
+      }
+    }
+
+    if (nChannels > MAX_CHANNELS) {
+      LogE(0, prep("EEPG: Error, %i channels found more than %i"), nChannels, MAX_CHANNELS);
+      return 0;
+    } else {
+      LogI(1, "|  ID  | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
+      LogI(1, "|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
+           "-----------------------------", "--------------------");
+      int pName = ((nChannels * 8) + 121); //TODO double ...
+      for (int i = 0; i < nChannels; i++) {
+        Channel = (sChannelMHW1 *) (Data + Off);
+        sChannel *C = &sChannels[i];
+        C->ChannelId = i;
+        ChannelSeq[C->ChannelId] = i; //fill lookup table to go from channel-id to sequence nr in table
+        C->SkyNumber = 0;
+        if (MHW == 1)
+          memcpy (C->Name, &Channel->Name, 16); //MHW1
+        else {   //MHW2
+          int lenName = Data[pName] & 0x0f;
+          //LogD (1, prep("EEPGDebug: MHW2 lenName:%d"), lenName);
+          decodeText2(&Data[pName+1],lenName,(char*)C->Name,256);
+          //memcpy (C->Name, &Data[pName + 1], lenName);
+          //else
+          //memcpy (C->Name, &Data[pName + 1], 256);
+          pName += (lenName + 1);
+        }
+        //C->NumberOfEquivalences = 1; //there is always an original channel. every equivalence adds 1
+        C->Src = Source (); //assume all EPG channels are on same satellite, if not, manage this via equivalents!!!
+        C->Nid = HILO16 (Channel->NetworkId);
+        C->Tid = HILO16 (Channel->TransportId);
+        C->Sid = HILO16 (Channel->ServiceId);
+        tChannelID channelID = tChannelID (C->Src, C->Nid, C->Tid, C->Sid);
+        cChannel *VC = GetChannelByID(channelID, true);
+        bool IsFound = (VC);
+        if(IsFound) {
+          C->Src = VC->Source();
+        }
+        CleanString (C->Name);
+
+        LogI(1, "|% 5d | %-26.26s | %-22.22s | %-3.3s |  % 6d  |\n", C->ChannelId
+             , *tChannelID (C->Src, C->Nid, C->Tid, C->Sid).ToString()
+             , C->Name, IsFound ? "YES" : "NO", C->SkyNumber);
+
+        Off += Size;
+      } //for loop
+    }   //else nChannels > MAX_CHANNELS
+    //LoadEquivalentChannels ();
+    EquivHandler->loadEquivalentChannelMap();
+    GetLocalTimeOffset (); //reread timing variables, only used for MHW
+    return 2; //obviously, when you get here, channels are read successfully, but since all channels are sent at once, you can stop now
+  } //if nChannels == 0
+  LogE (0, prep("Warning: Trying to read Channels more than once!"));
+  //you will only get here when GetChannelsMHW is called, and nChannels !=0, e.g. when multiple citpids cause channels to be read multiple times. Second time, do nothing, give error so that the rest of the chain is not restarted also.
+  return 0;
+}
+
+/**
+ * \brief Get MHW1 Themes
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetThemesMHW1 (const u_char * Data, int Length)
+{ //MHW1 Themes
+  if (Length > 19) {
+    sThemeMHW1 *Theme = (sThemeMHW1 *) (Data + 19);
+    nThemes = (Length - 19) / 15;
+    if (nThemes > MAX_THEMES) {
+      LogE(1, prep("Error, %i themes found more than %i"), nThemes, MAX_THEMES);
+      return 0;
+    } else {
+      LogI(1, "-------------THEMES FOUND--------------");
+      int ThemeId = 0;
+      int Offset = 0;
+      const u_char *ThemesIndex = (Data + 3);
+      for (int i = 0; i < nThemes; i++) {
+        if (ThemesIndex[ThemeId] == i) {
+          Offset = (Offset + 15) & 0xf0; //TODO do not understand this
+          ThemeId++;
+        }
+        memcpy (&Themes[Offset][0], &Theme->Name, 15);
+        Themes[Offset][15] = '\0'; //trailing null
+        CleanString (Themes[Offset]);
+        LogI(1, prep("%.15s"), Themes[Offset]);
+        Offset++;
+        Theme++;
+      }
+      if ((nThemes * 15) + 19 != Length) {
+        LogE(0, "Themes error: buffer is smaller or bigger than sum of entries.");
+        return 0;
+      } else
+        return 2;
+    }
+  }
+  return 1;
+}
+
+/**
+ * \brief Get MHW2 Themes
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetThemesMHW2 (const u_char * Data, int Length)
+{
+  if (!EndThemes) { //only process if not processed
+    int p1;
+    int p2;
+    int pThemeName = 0;
+    int pSubThemeName = 0;
+    int lenThemeName = 0;
+    int lenSubThemeName = 0;
+    int pThemeId = 0;
+    if (Length > 4) {
+      LogI(1, "-------------THEMES FOUND--------------");
+      for (int i = 0; i < Data[4]; i++) {
+        p1 = ((Data[5 + i * 2] << 8) | Data[6 + i * 2]) + 3;
+        if (Length > p1) {
+          for (int ii = 0; ii <= (Data[p1] & 0x3f); ii++) {
+            p2 = ((Data[p1 + 1 + ii * 2] << 8) | Data[p1 + 2 + ii * 2]) + 3;
+            if (Length > p2) {
+              if (ii == 0) {
+                pThemeName = p2 + 1;
+                lenThemeName = Data[p2] & 0x1f;
+                lenSubThemeName = 0;
+              } else {
+                pSubThemeName = p2 + 1;
+                lenSubThemeName = Data[p2] & 0x1f;
+              }
+              if (Length >= (pThemeName + lenThemeName)) {
+                pThemeId = ((i & 0x3f) << 6) | (ii & 0x3f);
+                if (pThemeId > MAX_THEMES) {
+                  LogE(1, prep("Error, something wrong with themes id calculation MaxThemes: %i pThemeID:%d"), MAX_THEMES, pThemeId);
+                  return 0; //fatal error
+                }
+                if ((lenThemeName + 2) < 256) {
+                  decodeText2(&Data[pThemeName],lenThemeName,(char*)Themes[pThemeId],256);
+                  //memcpy (Themes[pThemeId], &Data[pThemeName], lenThemeName);
+                  if (Length >= (pSubThemeName + lenSubThemeName))
+                    if (lenSubThemeName > 0)
+                      if ((lenThemeName + lenSubThemeName + 2) < 256) {
+                        Themes[pThemeId][lenThemeName] = '-';
+                        decodeText2(&Data[pSubThemeName],lenSubThemeName,(char*)&Themes[pThemeId][lenThemeName + 1],256);
+                        //memcpy (&Themes[pThemeId][lenThemeName + 1], &Data[pSubThemeName], lenSubThemeName);
+                      }
+                  CleanString (Themes[pThemeId]);
+                  LogI(1, prep("%.*s"), lenThemeName + 1 + lenSubThemeName, Themes[pThemeId]);
+                  //isyslog ("%.15s", (lThemes + pThemeId)->Name);
+                  nThemes++;
+                  if (nThemes > MAX_THEMES) {
+                    LogE(1, prep("Error, %i themes found more than %i"), nThemes, MAX_THEMES);
+                    return 0; //fatal error
+                  }
+                }
+              } else
+                return 1; //I assume non fatal error or success
+            } else
+              return 1;  //I assume non fatal error or success
+          }
+        } else
+          return 1;  //I assume non fatal error or success
+      }    //for loop
+      //Del (Pid, Tid);
+      EndThemes = true;
+      return 2; //all themes read
+    } //if length
+  } //if !EndThemes
+  return 1; //non fatal or success
+}
+
+/**
+ * \brief Get Nagra Summary text
+ *
+ * \param TitleEventId EventId passed from title, to check it against the eventId of the summary
+ * \return pointer to reserved part of memory with summary text in it, terminated by NULL
+ */
+char *cFilterEEPG::GetSummaryTextNagra (const u_char * DataStart, long int Offset, unsigned int TitleEventId)
+//EventId is passed from title, to check it against the eventid of the summary
+{
+  u_char *p = (u_char *) DataStart + Offset;
+  sSummaryDataNagraGuide *SD = (sSummaryDataNagraGuide *) p;
+
+  if (TitleEventId != HILO32 (SD->EventId)) {
+    LogI(0, prep("ERROR, Title has EventId %08x and points to Summary with EventId %08x."), TitleEventId,
+      HILO32 (SD->EventId));
+    return 0; //return empty string
+  }
+
+  if (CheckLevel(3)) {
+    if (SD->AlwaysZero1 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero1 is NOT ZERO:%x.", SD->AlwaysZero1);
+    if (SD->AlwaysZero2 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero2 is NOT ZERO:%x.", SD->AlwaysZero2);
+    if (SD->AlwaysZero3 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero3 is NOT ZERO:%x.", SD->AlwaysZero3);
+    if (SD->AlwaysZero4 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero4 is NOT ZERO:%x.", SD->AlwaysZero4);
+    if (SD->AlwaysZero5 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero5 is NOT ZERO:%x.", SD->AlwaysZero5);
+    if (SD->AlwaysZero6 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero6 is NOT ZERO:%x.", SD->AlwaysZero6);
+    if (SD->AlwaysZero7 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero7 is NOT ZERO:%x.", SD->AlwaysZero7);
+    if (SD->AlwaysZero8 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero8 is NOT ZERO:%x.", SD->AlwaysZero8);
+    if (SD->AlwaysZero9 != 0)
+      isyslog ("EEPGDEBUG: SummAlwaysZero9 is NOT ZERO:%x.", SD->AlwaysZero9);
+
+    if (SD->Always1 != 0x31) //1970
+      isyslog ("EEPGDEBUG: SummAlways1:%02x.", SD->Always1);
+    if (SD->Always9 != 0x39)
+      isyslog ("EEPGDEBUG: SummAlways9:%02x.", SD->Always9);
+    if (SD->Always7 != 0x37)
+      isyslog ("EEPGDEBUG: SummAlways7:%02x.", SD->Always7);
+    if (SD->Always0 != 0x30)
+      isyslog ("EEPGDEBUG: SummAlways0:%02x.", SD->Always0);
+
+    if (SD->Always0x01 != 0x01) // 0x01 byte
+      isyslog ("EEPGDEBUG: Summ0x01 byte:%02x.", SD->Always0x01);
+  }
+  u_char *p2 = (u_char *) DataStart + HILO32 (SD->SummTxtOffset);
+  /*    esyslog
+        ("EEPGDEBUG: EventId %08x NumberOfBlocks %02x BlockId %08x SummTxtOffset %08x *p2: %02x Unkn1:%02x, Unkn2:%02x.",
+         HILO32 (SD->EventId), SD->NumberOfBlocks, HILO32 (SD->BlockId), HILO32 (SD->SummTxtOffset), *p2, SD->Unknown1,
+         SD->Unknown2);
+   */
+  unsigned char *Text = NULL; //makes first realloc work like malloc
+  int TotLength = 0; //and also makes empty summaries if *p2 != 0x4e
+  if (SD->NumberOfBlocks > 1) {
+    switch (*p2) {
+    case 0x4e: //valid summary text follows
+    {
+      bool LastTextBlock = false;
+
+      do { //for all text parts
+        sSummaryTextNagraGuide *ST = (sSummaryTextNagraGuide *) p2;
+        p2 += 8;  //skip fixed block
+        if (ST->AlwaysZero1 != 0)
+          LogD(3, prep("DEBUG: ST AlwaysZero1 is NOT ZERO:%x."), ST->AlwaysZero1);
+        if (ST->Always0x4e != 0x4e) {
+          LogI(0, prep("DEBUG: ST Always0x4e is NOT 0x4e:%x."), ST->AlwaysZero1);
+          return 0; //fatal error, empty text
+        }
+        LogI(5, prep("DEBUG: Textnr %i, Lasttxt %i."), ST->TextNr, ST->LastTextNr);
+        int SummaryLength = ST->Textlength;
+
+        Text = (unsigned char *) REALLOC (Text, SummaryLength + TotLength);
+        if (Text == NULL) {
+          LogI(0, prep("Summaries memory allocation error."));
+          return 0; //empty text
+        }
+        memcpy (Text + TotLength, p2, SummaryLength); //append new textpart
+        TotLength += SummaryLength;
+        p2 += ST->Textlength; //skip text
+
+        LastTextBlock = ((ST->LastTextNr == 0) || (ST->TextNr >= ST->LastTextNr));
+      } while (!LastTextBlock);
+      Text = (unsigned char *) REALLOC (Text, 1 + TotLength); //allocate 1 extra byte
+      Text[TotLength] = '\0'; //terminate string by NULL char
+      LogD(5, prep("DEBUG: Full Text:%s."), Text);
+
+      break;
+    }
+    case 0x8c: //"Geen uitzending" "Geen informatie beschikbaar" e.d.
+    {
+      sSummaryGBRNagraGuide *GBR = (sSummaryGBRNagraGuide *) p2;
+
+      p2 += 16; //skip fixed part, point to byte after Nextlength
+      if (CheckLevel(3)) {
+        if (GBR->AlwaysZero1 != 0)
+          isyslog ("EEPGDEBUG: GBR AlwaysZero1 is NOT ZERO:%x.", GBR->AlwaysZero1);
+        if (GBR->AlwaysZero2 != 0)
+          isyslog ("EEPGDEBUG: GBR AlwaysZero2 is NOT ZERO:%x.", GBR->AlwaysZero2);
+        if (GBR->AlwaysZero3 != 0)
+          isyslog ("EEPGDEBUG: GBR AlwaysZero3 is NOT ZERO:%x.", GBR->AlwaysZero3);
+        if (GBR->AlwaysZero4 != 0)
+          isyslog ("EEPGDEBUG: GBR AlwaysZero4 is NOT ZERO:%x.", GBR->AlwaysZero4);
+
+        isyslog ("EEPGDEBUG: Blocklength: %02x Data %02x %02x %02x %02x %02x %02x %02x %02x %02x", GBR->Blocklength,
+                 GBR->Un1, GBR->Un2, GBR->Un3, GBR->Un4, GBR->Un5, GBR->Un6, GBR->Un7, GBR->Un8, GBR->Un9);
+        for (int i = 0; i < GBR->Nextlength; i += 2)
+          isyslog ("GBR Extradata %02x %02x.", *(p2 + i), *(p2 + i + 1));
+      }
+    }
+    break;
+    default:
+      LogE(0, prep("ERROR *p2 has strange value: EventId %08x NumberOfBlocks %02x BlockId %08x SummTxtOffset %08x *p2: %02x Unkn1:%02x, Unkn2:%02x."),
+        HILO32 (SD->EventId), SD->NumberOfBlocks, HILO32 (SD->BlockId), HILO32 (SD->SummTxtOffset), *p2,
+        SD->Unknown1, SD->Unknown2);
+      break;
+    } //end of switch
+  } //NrOfBlocks > 1
+
+  if (TotLength == 0)
+    Text = NULL;
+
+  p += 29; //skip fixed part of block
+  if (SD->NumberOfBlocks == 1)
+    p -= 4; //in this case there is NO summary text AND no GBR??!!
+  for (int i = 1; i < (SD->NumberOfBlocks - 1); i++) {
+    LogD(3, prep("DEBUG: Extra Block info: %02x %02x %02x %02x."), *p, *(p + 1), *(p + 2), *(p + 3));
+    p += 4; //skip this extra block info
+  }
+  return (char *) Text;
+}
+
+/**
+ * \brief Prepare to Write to Schedule
+ *
+ * gets a channel and returns an array of schedules that WriteToSchedule can write to.
+ * Call this routine before a batch of titles with the same ChannelId will be WriteToScheduled; batchsize can be 1
+ *
+ * \param C channel to prepare
+ * \param s VDR epg schedules
+ * \param ps pointer to the schedules that WriteToSchedule can write to
+ */
+//void cFilterEEPG::PrepareToWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps/*[MAX_EQUIVALENCES]*/)
+//{
+//  //for (int eq = 0; eq < C->NumberOfEquivalences; eq++) {
+//    tChannelID channelID = tChannelID (C->Src/*[eq]*/, C->Nid/*[eq]*/, C->Tid/*[eq]*/, C->Sid/*[eq]*/);
+//#ifdef USE_NOEPG
+//    if (allowedEPG (channelID) && (channelID.Valid ()))
+//#else
+//    if (channelID.Valid ()) //only add channels that are known to vdr
+//#endif /* NOEPG */
+//      ps/*[eq]*/ = s->AddSchedule (channelID); //open a a schedule for each equivalent channel
+//    else {
+//      ps/*[eq]*/ = NULL;
+////      LogE(5, prep("ERROR: Title block has invalid (equivalent) channel ID: Equivalence: %i, Source:%x, C->Nid:%x,C->Tid:%x,C->Sid:%x."),
+////           eq, C->Src[eq], C->Nid[eq], C->Tid[eq], C->Sid[eq]);
+//    }
+//  //}
+//}
+
+//void cFilterEEPG::FinishWriteToSchedule (sChannel * C, cSchedules * s, cSchedule * ps[MAX_EQUIVALENCES])
+//{
+//  for (int eq = 0; eq < C->NumberOfEquivalences; eq++)
+//    if (ps[eq]) {
+//      ps[eq]->Sort ();
+//      s->SetModified (ps[eq]);
+//    }
+//}
+
+/**
+ * \brief write event to schedule
+ *
+ * \param Duration the Duration of the event in minutes
+ * \param ps points to array of schedules ps[eq], where eq is equivalence number of the channel. If channelId is invalid then ps[eq]=NULL
+ */
+void cFilterEEPG::WriteToSchedule (tChannelID channelID, cSchedules* pSchedules, unsigned int EventId, unsigned int StartTime, unsigned int Duration, char *Text, char *SummText, unsigned short int ThemeId, unsigned short int TableId, unsigned short int Version, char Rating)
+{
+  bool WrittenTitle = false;
+  bool WrittenSummary = false;
+//  for (int eq = 0; eq < NumberOfEquivalences; eq++) {
+  cSchedule* ps;
+  if (channelID.Valid ()) //only add channels that are known to VDR
+    ps = pSchedules->AddSchedule (channelID); //open or create new schedule
+  else {
+    ps = NULL;
+  }
+
+  cEvent *Event = NULL;
+  if (ps/*[eq]*/) {
+
+      Event = (cEvent *) ps->GetEvent (EventId); //since Nagra uses consistent EventIds, try this first
+      bool TableIdMatches = false;
+      if (Event)
+        TableIdMatches = (Event->TableID() == TableId);
+      if (!Event || !TableIdMatches || abs(Event->StartTime() - (time_t) StartTime) > Duration * 60) //if EventId does not match, or it matched with wrong TableId, then try with StartTime
+        Event = (cEvent *) ps->GetEvent (EventId, StartTime);
+  }
+  cEvent *newEvent = NULL;
+  if (!Event) {  //event is new
+    Event = newEvent = new cEvent (EventId);
+    Event->SetSeen ();
+  } else if (Event->TableID() < TableId) { //existing table may not be overwritten
+    RejectTableId++;
+    //esyslog ("EEPGDEBUG: Rejecting Event, existing TableID:%x, new TableID:%x.", Event->TableID (),
+    //           TableId);
+    Event = NULL;
+  }
+
+  if (Event) {
+    Event->SetEventID (EventId); //otherwise the summary cannot be added later
+    Event->SetTableID (TableId); //TableID 0 is reserved for external epg, will not be overwritten; the lower the TableID, the more actual it is
+    Event->SetVersion (Version); //TODO use version and tableID to decide whether to update; TODO add language code
+    Event->SetStartTime (StartTime);
+    Event->SetDuration (Duration * 60);
+    if (Rating) {
+      Event->SetParentalRating(Rating);
+    }
+    char *tmp;
+    if (Text != 0x00) {
+      WrittenTitle = true;
+      CleanString ((uchar *) Text);
+      Event->SetTitle (Text);
+    }
+    Asprintf (&tmp, "%s - %d\'", Themes[ThemeId], Duration);
+    Event->SetShortText (tmp);
+    free(tmp);
+    //strreplace(t, '|', '\n');
+    if (SummText != 0x00) {
+      WrittenSummary = true;
+      CleanString ((uchar *) SummText);
+
+      //Add themes and categories epgsearch style
+      char *theme;
+      Asprintf (&theme, "%s", Themes[ThemeId]);
+      if (theme && 0 != strcmp(theme,"")) {
+        char *category, *genre;
+        category = NULL;
+        genre = NULL;
+        char *split = strchr(theme, '-'); // Look for '-' delim to separate category from genre
+        if (split){
+          *split = 0;
+          category = theme;
+          genre = (split[1] == 0x20) ? split + 2 : split + 1;
+        }else{
+          category = theme;
+        }
+        string fmt;
+        fmt = "%s";
+        if (stripspace(category)) {
+          fmt += "\nCategory: %s";
+        }
+        if (genre) {
+          fmt += "\nGenre: %s";
+        }
+        Asprintf (&tmp, fmt.c_str(), SummText, category, stripspace (genre));
+
+        Event->SetDescription (tmp);
+        free(tmp);
+        free(theme);
+    }
+    else
+      Event->SetDescription (SummText);
+    }
+    if (ps && newEvent)
+      ps->AddEvent (newEvent);
+
+    EquivHandler->updateEquivalent(pSchedules, channelID, Event);
+
+    if (!ps) {
+    //the event is not send to VDR so it has to be deleted.
+      delete Event;
+      Event = NULL;
+    }
+
+    //newEvent->FixEpgBugs (); causes segfault
+  }
+      /*      else
+            esyslog ("EEPG: ERROR, somehow not able to add/update event.");*///at this moment only reports RejectTableId events
+  if (CheckLevel(4)) {
+    isyslog ("EEPG: Title:%i, Summary:%i I would put into schedule:", TitleCounter, SummaryCounter);
+    //isyslog ("C %s-%i-%i-%i\n", *cSource::ToString (C->Src[eq]), C->Nid[eq], C->Tid[eq], C->Sid[eq]);
+    isyslog ("E %u %u %u 01 FF\n", EventId, StartTime, Duration * 60);
+    isyslog ("T %s\n", Text);
+    isyslog ("S %s - %d\'\n", Themes[ThemeId], Duration);
+    isyslog ("D %s\n", SummText);
+    isyslog ("e\nc\n.\n");
+  }
+//    } //if ps[eq]
+//  } //for eq
+  if (WrittenTitle)
+    TitleCounter++;
+  if (WrittenSummary)
+    SummaryCounter++;
+}
+
+/**
+ * \brief  Get Nagra titles
+ *
+ * \param TableIdExtension the TIE from the relevant summary sections!
+ */
+void cFilterEEPG::GetTitlesNagra (const u_char * Data, int Length, unsigned short TableIdExtension)
+{
+  u_char *p = (u_char *) Data;
+  u_char *DataEnd = (u_char *) Data + Length;
+  u_char *next_p;
+  unsigned short int MonthdayTitles = ((TableIdExtension & 0x1ff) >> 4); //Day is coded in day of the month
+  time_t timeLocal;
+  struct tm *tmCurrent;
+
+  timeLocal = time (NULL);
+  tmCurrent = gmtime (&timeLocal); //gmtime gives UTC; only used for getting current year and current day of the month...
+  unsigned short int CurrentMonthday = tmCurrent->tm_mday;
+  unsigned short int CurrentYear = tmCurrent->tm_year;
+  unsigned short int CurrentMonth = tmCurrent->tm_mon;
+  //esyslog("EEPGDEBUG: CurrentMonthday=%i, TableIdExtension:%04x, MonthdayTitles=%i.",CurrentMonthday,TableIdExtension, MonthdayTitles);
+  cSchedulesLock SchedulesLock (true);
+  cSchedules *s = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+  do { //process each block of titles
+    sTitleBlockNagraGuide *TB = (sTitleBlockNagraGuide *) p;
+    int ChannelId = HILO16 (TB->ChannelId);
+    int Blocklength = HILO16 (TB->Blocklength);
+    long int NumberOfTitles = HILO32 (TB->NumberOfTitles);
+
+    LogD(3, prep("DEBUG: ChannelId %04x, Blocklength %04x, NumberOfTitles %lu."), ChannelId, Blocklength,
+         NumberOfTitles);
+    p += 4; //skip ChannelId and Block length
+    next_p = p + Blocklength;
+    if (next_p > DataEnd) { //only process if block is complete
+      LogE(0, prep("ERROR, Block exceeds end of Data. p:%p, Blocklength:%x,DataEnd:%p."), p, Blocklength, DataEnd);
+      return; //fatal error, this should never happen
+    }
+    p += 4; //skip Title number
+
+    sChannel *C = &sChannels[ChannelSeq[ChannelId]]; //find channel
+    //cSchedule *ps = NULL;//[MAX_EQUIVALENCES];
+    //PrepareToWriteToSchedule (C, s, ps);
+
+    for (int i = 0; i < NumberOfTitles; i++) { //process each title within block
+      sTitleNagraGuide *Title = (sTitleNagraGuide *) p;
+      unsigned int EventId = HILO32 (Title->EventId);
+
+      unsigned int StartTime = Title->StartTimeHigh << 5 | Title->StartTimeLow;
+      int Hours = (StartTime / 60);
+      int Minutes = StartTime % 60;
+
+      /*StartTime */
+      tmCurrent->tm_year = CurrentYear;
+      tmCurrent->tm_mon = CurrentMonth;
+      tmCurrent->tm_mday = MonthdayTitles;
+      tmCurrent->tm_hour = 0;
+      tmCurrent->tm_min = StartTime; //if start time is bigger than 1 hour, mktime will correct this!
+      tmCurrent->tm_sec = 0;
+      tmCurrent->tm_isdst = -1; //now correct with daylight savings
+      if (MonthdayTitles < CurrentMonthday - 7) //the titles that are older than one week are not from the past, but from next month!
+        //at first this was set at -1 day (= yesterday), but sometimes providers send old data which then
+        //end up in next months schedule ...
+        tmCurrent->tm_mon++; //if a year border is passed, mktime will take care of this!
+      StartTime = UTC2LocalTime (mktime (tmCurrent)); //VDR stores its times in UTC, but wants its input in local time...
+
+      char *Text = NULL;
+      u_char *t = (u_char *) Data + HILO32 (Title->OffsetToText);
+      //u_char *t2 = (u_char *) Data + HILO32 (Title->OffsetToText2);
+      if (t >= DataEnd)
+        LogE(0, prep("ERROR, Title Text out of range: t:%p, DataEnd:%p, Data:%p, Length:%i."), t, DataEnd, Data,
+          Length);
+      else {
+        Asprintf (&Text, "%.*s", *t, t + 1);
+        //asprintf (&Text, "%.*s %.*s", *t, t + 1, *t2, t2 + 1); //FIXME second text string is not processed right now
+
+        //now get summary texts
+        u_char *DataStartSummaries = buffer[TableIdExtension] + 4;
+        unsigned int DataLengthSummaries = bufsize[TableIdExtension] - 4;
+        char *SummText = NULL;
+        if (HILO32 (Title->SumDataOffset) >= DataLengthSummaries)
+          LogE(0, prep("ERROR, SumDataOffset out of range: Title->SumDataOffset:%i, DataLengthSummaries:%i."), HILO32 (Title->SumDataOffset),DataLengthSummaries);
+        else
+          SummText = GetSummaryTextNagra (DataStartSummaries, HILO32 (Title->SumDataOffset), EventId);
+
+        LogD(3, prep("DEBUG: Eventid: %08x ChannelId:%x, Start time %02i:%02i, Duration %i, OffsetToText:%08x, OffsetToText2:%08x, SumDataOffset:%08x ThemeId:%x Title:%s \n SummaryText:%s"),
+             EventId, ChannelId, Hours, Minutes, Title->Duration,
+             HILO32 (Title->OffsetToText), HILO32 (Title->OffsetToText2),
+             HILO32 (Title->SumDataOffset), Title->ThemeId, Text, SummText);
+
+        if (Themes[Title->ThemeId][0] == 0x00) //if detailed themeid is not known, get global themeid
+          Title->ThemeId &= 0xf0;
+
+        WriteToSchedule (tChannelID (C->Src, C->Nid, C->Tid, C->Sid), s, EventId, StartTime, Title->Duration, Text, SummText,
+                         Title->ThemeId, NAGRA_TABLE_ID, Version);
+
+        if (Text != NULL)
+          free (Text);
+        Text = NULL;
+        if (SummText != NULL)
+          free (SummText);
+        SummText = NULL;
+      }
+
+      if (CheckLevel(3)) {
+        if (Title->AlwaysZero16 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero16 (3bits) is NOT ZERO:%x.", Title->AlwaysZero16);
+        if (Title->AlwaysZero17 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero17 is NOT ZERO:%x.", Title->AlwaysZero17);
+        if (Title->AlwaysZero1 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero1 is NOT ZERO:%x.", Title->AlwaysZero1);
+        if (Title->AlwaysZero2 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero2 is NOT ZERO:%x.", Title->AlwaysZero2);
+        if (Title->AlwaysZero3 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero3 is NOT ZERO:%x.", Title->AlwaysZero3);
+        if (Title->AlwaysZero4 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero4 is NOT ZERO:%x.", Title->AlwaysZero4);
+        if (Title->AlwaysZero5 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero5 is NOT ZERO:%x.", Title->AlwaysZero5);
+        if (Title->AlwaysZero8 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero8 is NOT ZERO:%x.", Title->AlwaysZero8);
+        if (Title->AlwaysZero9 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero9 is NOT ZERO:%x.", Title->AlwaysZero9);
+        if (Title->AlwaysZero10 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero10 is NOT ZERO:%x.", Title->AlwaysZero10);
+        if (Title->AlwaysZero11 != 0)
+          isyslog ("EEPGDEBUG: TitleAlwaysZero11 is NOT ZERO:%x.", Title->AlwaysZero11);
+      }
+      p += 30; //next title
+    } //end for titles
+
+    //FinishWriteToSchedule (C, s, ps);
+    sortSchedules(s, tChannelID (C->Src, C->Nid, C->Tid, C->Sid));
+    p = next_p;
+  } while (p < DataEnd); //end of TitleBlock
+}
+
+int cFilterEEPG::GetThemesNagra (const u_char * Data, int Length, unsigned short TableIdExtension) //return code 0 = fatal error, code 1 = success, code 2 = last item processed
+{
+  u_char *DataStart = (u_char *) Data;
+  u_char *p = DataStart; //TODO Language code terminated by 0 is ignored
+  u_char *DataEnd = DataStart + Length;
+  u_char *DataStartTitles = buffer[TableIdExtension] + 4;
+  u_char *DataEndTitles = DataStartTitles + bufsize[TableIdExtension] - 4;
+  if (Length == 0) {
+    LogI(1, prep("NO THEMES FOUND"));
+    return 2;
+  }
+
+  int NumberOfThemes = (*p << 24) | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3);
+  p += 4; //skip number of themes block
+  //isyslog ("EEPG: found %i themes.", NumberOfThemes);
+
+  if ((nThemes == 0))
+    LogI(1, "-------------THEMES FOUND--------------");
+
+  for (int i = 0; i < NumberOfThemes; i++) {
+    int Textlength = *p;
+    p++; //skip textlength byte
+    u_char *Text = p;
+    u_char ThemeId = 0;
+    p += Textlength; //skip text
+    int NrOfBlocks = (*p << 8) | *(p + 1);
+    p += 2; //skip nrofblocks
+    bool AnyDoubt = false;
+    u_char *p2 = p;
+    p += NrOfBlocks * 8;
+    for (int j = 0; j < NrOfBlocks; j++) {
+      sThemesTitlesNagraGuide *TT = (sThemesTitlesNagraGuide *) p2;
+      p2 += 8; //skip block
+      u_char *NewThemeId = DataStartTitles + HILO32 (TT->TitleOffset) + 28;
+      if (NewThemeId >= DataEndTitles)
+        LogE(0, prep("ERROR, ThemeId out of range: NewThemeId:%p, DataEndTitles:%p, DataStartTitles:%p."), NewThemeId,
+          DataEndTitles, DataStartTitles);
+      else {
+        //esyslog("EEPGDEBUG: NewThemeId:%02x, Text:%s.",*NewThemeId, Text);
+        if (Themes[*NewThemeId][0] != 0x00) { //theme is already filled, break off
+          AnyDoubt = true;
+          break;
+        }
+        if (j == 0) //first block
+          ThemeId = *NewThemeId;
+        else if (ThemeId != *NewThemeId) { //different theme ids in block
+          if ((ThemeId & 0xf0) != (*NewThemeId & 0xf0)) { //major nible of themeid does not correspond
+            LogE(3, prep("ERROR, Theme has multiple indices which differ in major nibble, old index = %x, new index = %x. Ignoring both indices."),
+              ThemeId, *NewThemeId);
+            AnyDoubt = true;
+            break;
+          } else if ((ThemeId & 0x0f) != 0) //ThemeId is like 1a, 2a, not like 10,20. So it is minor in tree-structure, and it should be labeled in major part of tree
+            ThemeId = *NewThemeId; //lets hope new themeid is major, if not, it has not worsened....
+        }
+      }    //else NewThemeId >= DataEndTitles
+      if (CheckLevel(3)) {
+        if (TT->Always1 != 1)
+          isyslog ("EEPGDEBUG: TT Always1 is NOT 1:%x.", TT->Always1);
+        if (TT->AlwaysZero1 != 0)
+          isyslog ("EEPGDEBUG: TT AlwaysZero1 is NOT ZERO:%x.", TT->AlwaysZero1);
+        if (TT->AlwaysZero2 != 0)
+          isyslog ("EEPGDEBUG: TT AlwaysZero2 is NOT ZERO:%x.", TT->AlwaysZero2);
+      }
+    } //for nrofblocks
+    // esyslog("EEPGDEBUG: AnyDoubt:%x.",AnyDoubt);
+    if (!AnyDoubt) {
+      if (Textlength > 63)
+        Textlength = 63; //leave room for trailing NULL
+      if (Themes[ThemeId][0] != 0) {
+        LogE(0, prep("Trying to add new theme, but Id already exists. ThemeId = %x, Old theme with this Id:%s, new theme: %s."),
+          ThemeId, Themes[ThemeId], Text);
+        continue;
+      }
+      memcpy (&Themes[ThemeId], Text, Textlength);
+      Themes[ThemeId][Textlength] = '\0'; //trailing NULL
+      CleanString (Themes[ThemeId]);
+      nThemes++;
+      LogI(1, prep("%02x %s"), ThemeId, Themes[ThemeId]);
+    }
+  } //for NumberOfThemes
+  if (p != DataEnd) {
+    LogE(0, prep("Themes error: buffer is smaller or bigger than sum of entries. p:%p,DataEnd:%p"), p, DataEnd);
+    return 0;
+  } else
+    return 2;
+}
+
+/**
+ * \brief Get Nagra channels
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetChannelsNagra (const u_char * Data, int Length)
+{
+  u_char *DataStart = (u_char *) Data;
+  u_char *p = DataStart;
+  u_char *DataEnd = DataStart + Length;
+
+  nChannels = (*p << 24) | *(p + 1) << 16 | *(p + 2) << 8 | *(p + 3);
+  p += 4; //skip numberofchannels
+  if (CheckLevel(1)) {
+    isyslog ("|  ID  | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
+    isyslog ("|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
+             "-----------------------------", "--------------------");
+  }
+
+  for (int j = 0; j < nChannels; j++) {
+    sChannelsNagraGuide *Channel = (sChannelsNagraGuide *) p;
+    sChannel *C = &sChannels[j];
+    C->ChannelId = j + 1; //Nagra starts numbering at 1
+    ChannelSeq[C->ChannelId] = j; //fill lookup table to go from channel-id to sequence nr in table; lookup table starts with 0
+    C->SkyNumber = 0;
+    //C->NumberOfEquivalences = 1; //there is always an original channel. every equivalence adds 1
+    C->Src = Source(); //assume all EPG channels are on same satellite, if not, manage this via equivalents!!!
+    C->Nid = HILO16 (Channel->NetworkId);
+    C->Tid = HILO16 (Channel->TransportId);
+    C->Sid = HILO16 (Channel->ServiceId);
+    tChannelID channelID = tChannelID(C->Src, C->Nid, C->Tid, C->Sid);
+    cChannel *VC = GetChannelByID(channelID, true);
+    bool IsFound = (VC);
+    if(IsFound) {
+      strncpy((char*)(C->Name), VC->Name (), 64);
+      C->Src = VC->Source();
+      CleanString (C->Name);
+    }
+    else
+      C->Name[0] = '\0'; //empty string
+
+    LogI(1, "|% 5d | %-26.26s | %-22.22s | %-3.3s |  % 6d  |\n", C->ChannelId
+         , *channelID.ToString(), C->Name, IsFound ? "YES" : "NO", C->SkyNumber);
+
+    LogD(4, prep("DEBUG: start    : %s"), cs_hexdump (0, p, 9));
+
+    p += 8; //skip to first 0x8c if non-FTA, or 0x00 if FTA
+    for (int i = 0; i < Channel->Nr8cBlocks; i++) {
+      if (*p != 0x8c) {
+        LogD(0, prep("DEBUG: ERROR in Channel Table, expected value of 0x8c is %02x"), *p);
+        return 0; //fatal error
+      }
+      p++; //skip 8c byte
+      LogD(4, prep("DEBUG: 8c string: %s"), cs_hexdump (0, p + 1, *p));
+      p += *p; //skip 8c block
+      p++; //forgot to skip length byte
+    }
+    //start last non 8c block here
+    if (*p != 0x00) {
+      LogE(0, prep("ERROR in Channel Table, expected value of 0x00 is %02x"), *p);
+      return 0; //fatal error
+    }
+    p++; //skip 0x00 byte
+    LogD(4, prep("DEBUG: endstring: %s"), cs_hexdump (0, p + 1, *p * 4));
+    p += (*p * 4); //p points to nrofblocks, each block is 4 bytes
+    p++; //forgot to skip nrofblocks byte
+
+    /*
+        if (Channel->AlwaysZero1 != 0)
+          isyslog ("EEPGDEBUG: AlwaysZero1 is NOT ZERO:%x.", Channel->AlwaysZero1);
+        if (Channel->AlwaysZero2 != 0)
+          isyslog ("EEPGDEBUG: AlwaysZero2 is NOT ZERO:%x.", Channel->AlwaysZero2);
+        if (Channel->Always0x8c != 0x8c)
+          isyslog ("EEPGDEBUG: Always0x8c is NOT 0x8c:%x.", Channel->Always0x8c);
+        if (Channel->Always0x08 != 0x08)
+          isyslog ("EEPGDEBUG: Always0x08 is NOT 0x08:%x.", Channel->Always0x08);
+        if (Channel->Always0x02 != 0x02)
+          isyslog ("EEPGDEBUG: Always0x02 is NOT 0x02:%x.", Channel->Always0x02);
+        if (Channel->Always0x01 != 0x01)
+          isyslog ("EEPGDEBUG: Always0x01 is NOT 0x01:%x.", Channel->Always0x01);
+        if (Channel->Always0x20 != 0x20)
+          isyslog ("EEPGDEBUG: Always0x20 is NOT 0x20:%x.", Channel->Always0x20);
+        if (Channel->Always0x0a != 0x0a)
+          isyslog ("EEPGDEBUG: Always0x0a is NOT 0x0a:%x.", Channel->Always0x0a);
+        if (Channel->Always0x81 != 0x81)
+          isyslog ("EEPGDEBUG: Always0x81 is NOT 0x81:%x.", Channel->Always0x81);
+        if (Channel->Always0x44 != 0x44)
+          isyslog ("EEPGDEBUG: Always0x44 is NOT 0x44:%x.", Channel->Always0x44);
+     */
+
+  }
+  if (p != DataEnd)
+    LogE(0, prep("Warning, possible problem at end of channel table; p = %p, DataEnd = %p"), p, DataEnd);
+  //LoadEquivalentChannels ();
+  EquivHandler->loadEquivalentChannelMap();
+  return 2; //obviously, when you get here, channels are read succesfully, but since all channels are sent at once, you can stop now
+}
+
+/**
+ * \brief Get Nagra extended EPG
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetNagra (const u_char * Data, int Length)
+{
+  sTitleBlockHeaderNagraGuide *TBH = (sTitleBlockHeaderNagraGuide *) Data;
+  if (InitialTitle[0] == 0x00) { //InitialTitle is empty, so we are waiting for the start marker
+    if (TBH->TableIdExtensionHigh == 0x00 && TBH->TableIdExtensionLow == 0x00) { //this is the start of the data
+      if (TBH->VersionNumber == LastVersionNagra) {
+        LogI(0, prep("Nagra EEPG already up-to-date with version %i"), LastVersionNagra);
+        return 2;
+      }
+      Version = TBH->VersionNumber;
+      LogI(0, prep("initialized Nagraguide, version %i"), Version);
+      //u_char *p = (u_char *) Data + 11;
+      u_char *p = (u_char *) Data + 8;
+      if (*p != 0x01) {
+        LogE(0, prep("Error, Nagra first byte in table_id_extension 0x00 is not 0x01 but %02x. Format unknown, exiting."),
+          *p);
+        return 0; //fatal error
+      }
+      p++; //skip 0x01 byte
+      unsigned short int l = ((*p << 8) | *(p + 1));
+      u_char *p_end = p + l - 3; //this ensures a full block of 4 bytes is there to process
+      p += 2; //skip length bytes
+      while (p < p_end) {
+        sSection0000BlockNagraGuide *S = (sSection0000BlockNagraGuide *) p;
+        int TTT = ((S->TableIdExtensionHigh << 10) | (S->TableIdExtensionLow << 3) | (S->TIE200 << 9));
+        LogD(4, prep("DEBUG: TableIdExtension %04x, Unknown1 %02x Version %02x Always 0xd6 %02x DayCounter %02x"),
+             TTT, S->Unknown1, S->VersionNumber, S->Always0xd6, S->DayCounter);
+        if ((TTT > 0x0400) && (TTT < 0x0600)) //take high byte and compare with summarie tables in 0x0400 and 0x0500 range;
+          NagraTIE[NagraCounter++] = TTT; //only store TIEs of titlessummaries, all others can be derived; they are stored in the order of the 0x0000 index table,
+        //lets hope first entry corresponds with today, next with tomorrow etc.
+        p += 4;
+      }
+      buffer.clear (); //clear buffer maps
+      bufsize.clear (); //clear buffer maps
+      InitialTitle[0] = 0xff; //copy data into initial title
+    }
+    return (1);
+  }
+  unsigned short SectionLength = ((TBH->SectionLengthHigh & 0x0f) << 8) | TBH->SectionLengthLow;
+  unsigned short TableIdExtension = HILO16 (TBH->TableIdExtension);
+  if (TableIdExtension == 0x0000) {
+    LastVersionNagra = Version;
+    return (2); //done
+  }
+  /*
+  Table_id_extensions:
+  (0x0000)
+  (0x0010) per channel, nr_of_channels entries, every entry is 8 bytes, first 4 bytes gives nr. of titles in corresponding title table
+  (0x0020) per channel info day 2 of the month
+  (0x01F0) per channel info day 31 of the month
+  (0x0200) leeg; letop op je leest gemakkelijk door naar 0x0210!
+  (0x0210) titles day 1 of the month
+  (0x0220) titles day 2 of the month
+  (0x03F0) titles day 31 of the month
+  (0x0400) channel info
+  (0x0410) summaries day 1 of the month
+  (0x0420) summaries day 2 of the month
+  (0x05F0) summaries day 31 of the month
+  (0x0610) themes/title reference sunday, correspond to titles 0x0400 lower...
+  (0x0620) themes/title reference monday
+  ... this goes on until 0x07f0
+  (0x0810) bouquet info; references to channels within a package, day 1 of the month
+  (0x0820) same day 2 of the month
+  (0x09f0) same day 31 of the month
+   */
+
+  if (!(TBH->TableIdExtensionHigh >= 0x02 && TBH->TableIdExtensionHigh <= 0x07)) //here we regulate which tables we are testing
+    return (1);
+  if (TableIdExtension == 0x0200) //table 0x0200 only contains language code, because it is for day 0 of the month, and 0x0400 is used for channels
+    return 1;
+  if (TBH->SectionNumber == 0) { //first section, create a table
+    buffer[TableIdExtension] = NULL;
+    bufsize[TableIdExtension] = 0;
+    NumberOfTables++;
+  }
+  //store all sections in core until last section is found; processing incomplete sections is very complex and doesnt save much memory,
+  //since the data has to be stored anyway; summaries do not seem to have channelid included, so storing titles and separately storing summaries will not work...
+  //GetEventId only works for a specific Schedule for a specific ChannelId....
+  buffer[TableIdExtension] =
+    (unsigned char *) REALLOC (buffer[TableIdExtension], SectionLength - 9 + bufsize[TableIdExtension]);
+  memcpy (buffer[TableIdExtension] + bufsize[TableIdExtension], Data + 8, SectionLength - 9); //append new section
+  bufsize[TableIdExtension] += SectionLength - 9;
+  if (TBH->SectionNumber >= TBH->LastSectionNumber) {
+    LogI(1, prep("found %04x lastsection nr:%i."), TableIdExtension, TBH->SectionNumber);
+    // if (TBH->TableIdExtensionHigh == 0x04 || TBH->TableIdExtensionHigh == 0x05) {
+    if (TableIdExtension == 0x0400) {
+      int Result = GetChannelsNagra (buffer[TableIdExtension] + 4, bufsize[TableIdExtension] - 4); //TODO language code terminated by 0 is ignored
+      free (buffer[TableIdExtension]);
+      buffer[TableIdExtension] = NULL;
+      NumberOfTables--;
+      if (Result == 0)
+        return 0; //fatal error; TODO this exit should also free all other, non-Channel sections that are stored!
+    }
+  } //if lastsection read
+  return (1); //return and continue, nonfatal
+}
+
+void cFilterEEPG::ProcessNagra ()
+{
+  for (int i = 0; i < MAX_THEMES; i++) //clear all themes
+    Themes[i][0] = '\0';
+
+  for (int i = 0; i < NagraCounter; i++) { //first prcoess all themes, since they all use the same codes
+    unsigned short int TableIdExtension = NagraTIE[i];
+    int TIE = TableIdExtension + 0x0200; //from 0x0400 to 0x0600 -> themes
+    LogI(3, prep("Processing Theme with TableIdExtension:%04x"), TIE);
+    GetThemesNagra (buffer[TIE] + 4, bufsize[TIE] - 4, TableIdExtension - 0x0200); //assume theme is completed  //TODO Language code terminatd by 0 is ignored
+    free (buffer[TIE]);
+    buffer[TIE] = NULL;
+    NumberOfTables--;
+  }
+
+  for (int i = 0; i < NagraCounter; i++) { //first process all themes, since they all use the same codes
+    unsigned short int TableIdExtension = NagraTIE[i];
+    int TIE = TableIdExtension - 0x0200; //from 0x0400 to 0x0200 -> titles
+    LogI(0, prep("Processing TableIdExtension:%04x"), TableIdExtension);
+    GetTitlesNagra (buffer[TIE] + 4, bufsize[TIE] - 4, TableIdExtension); //assume title-reading is completed  //TODO Language code terminated by 0 is ignored
+    free (buffer[TIE]);
+    buffer[TIE] = NULL;
+    NumberOfTables--;
+
+    free (buffer[TableIdExtension]); //summaries
+    buffer[TableIdExtension] = NULL;
+    NumberOfTables--;
+  }
+  if (NumberOfTables != 0)
+    LogE(0, prep("ERROR, Not all tables processed and stream is already repeating. NumberOfTables = %i."),
+      NumberOfTables);
+}
+
+/**
+ * \brief Get MHW1 Titles
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetTitlesMHW1 (const u_char * Data, int Length)
+{
+  if (Length >= 42) {
+    sTitleMHW1 *Title = (sTitleMHW1 *) Data;
+    if (Title->ChannelId == 0xff) { //FF is separator packet
+      if (memcmp (InitialTitle, Data, 46) == 0) { //data is the same as initial title //TODO use easier notation
+        LogD(2, prep("End processing titles"));
+        return 2;
+      }
+      if (nTitles == 0)
+        memcpy (InitialTitle, Data, 46); //copy data into initial title
+      int Day = Title->Day;
+      int Hours = Title->Hours;
+      if (Hours > 15)
+        Hours -= 4;
+      else if (Hours > 7)
+        Hours -= 2;
+      else
+        Day++;
+      if (Day > 6)
+        Day = Day - 7;
+      Day -= Yesterday;
+      if (Day < 1)
+        Day = 7 + Day;
+      //if (Day == 1 && Hours < 6)
+      if (Day == 0 && Hours < 6)
+        Day = 7;
+      //Day = 8;
+      MHWStartTime = (Day * 86400) + (Hours * 3600) + YesterdayEpochUTC;
+      LogI(3, prep("Titles: FF PACKET, seqnr:%02x."), Data[5]);
+    } else if (InitialTitle[0] != 0x00) { //if initialized this should always be 0x90 = tableid!
+      if (nTitles < MAX_TITLES) {
+        Title_t *T;
+        T = (Title_t *) malloc (sizeof (Title_t));
+        Titles[nTitles] = T;
+        int Minutes = Title->Minutes;
+        int StartTime = MHWStartTime + (Minutes * 60);
+        T->ChannelId = Title->ChannelId - 1;
+        T->ThemeId = Title->ThemeId;
+        T->TableId = Title->TableId;
+        T->MjdTime = 0;  //only used at MHW2 and SKY
+        T->EventId = HILO32 (Title->ProgramId);
+        T->StartTime = LocalTime2UTC (StartTime); //here also Daylight Savings correction is done
+        T->Duration = HILO16 (Title->Duration) * 60;
+        T->SummaryAvailable = Title->SummaryAvailable;
+        T->Text = (unsigned char *) malloc (47);
+        if (T->Text == NULL) {
+          LogE(0, prep("Titles memory allocation error."));
+          return 0;
+        }
+        //T->Text[46] = '\0'; //end string with NULL character
+        //memcpy (T->Text, &Title->Title, 23);
+        decodeText2((unsigned char *)&Title->Title, 23, (char*)T->Text, 47);
+        CleanString (T->Text);
+        LogI(3, prep("EvId:%08x,ChanId:%x, Titlenr:%d:, StartTime(epoch):%i, SummAv:%x,Name:%s."), T->EventId,
+             T->ChannelId, nTitles, T->StartTime, T->SummaryAvailable, T->Text);
+        nTitles++;
+      } //nTitles < MaxTitles
+      else {
+        LogE(0, prep("Error, %i titles found more than %i"), nTitles, MAX_TITLES);
+        return 0;
+      }
+    } //else if InitialTitle
+  } //Length==46
+  else {
+    LogE(0, prep("Error, length of title package < 42."));
+    return 1; //non fatal
+  }
+
+  return 1;
+}
+
+/**
+ * \brief Get MHW2 Titles
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetTitlesMHW2 (const u_char * Data, int Length)
+{
+  if (Length > 18) {
+    int Pos = 18;
+    int Len = 0;
+    /*bool Check = false;
+    while (Pos < Length) {
+      Check = false;
+      Pos += 7;
+      if (Pos < Length) {
+        Pos += 3;
+        if (Pos < Length)
+          if (Data[Pos] > 0xc0) {
+            Pos += (Data[Pos] - 0xc0);
+            Pos += 4;
+            if (Pos < Length) {
+              if (Data[Pos] == 0xff) {
+                Pos += 1;
+                Check = true;
+              }
+            }
+          }
+      }
+      if (Check == false){
+        isyslog ("EEPGDebug: Check==false");
+        return 1; // I assume nonfatal error or success
+        }
+    }*/
+    if (memcmp (InitialTitle, Data, 16) == 0) { //data is the same as initial title
+      return 2; //last item processed
+    } else {
+      if (nTitles == 0)
+        memcpy (InitialTitle, Data, 16); //copy data into initial title
+      //Pos = 18;
+      while (Pos < Length) {
+        Title_t *T;
+        T = (Title_t *) malloc (sizeof (Title_t));
+        Titles[nTitles] = T;
+        T->ChannelId = Data[Pos];
+        Pos+=11;//The date time starts here
+        //isyslog ("EEPGDebug: ChannelID:%d", T->ChannelId);
+        unsigned int MjdTime = (Data[Pos] << 8) | Data[Pos + 1];
+        T->MjdTime = 0; //not used for matching MHW2
+        T->StartTime = ((MjdTime - 40587) * 86400)
+                       + (((((Data[Pos + 2] & 0xf0) >> 4) * 10) + (Data[Pos + 2] & 0x0f)) * 3600)
+                       + (((((Data[Pos + 3] & 0xf0) >> 4) * 10) + (Data[Pos + 3] & 0x0f)) * 60);
+        T->Duration = (((Data[Pos + 5] << 8) | Data[Pos + 6]) >> 4) * 60;
+        Len = Data[Pos + 7] & 0x3f;
+        //isyslog ("EEPGDebug: Len:%d", Len);
+        T->Text = (unsigned char *) malloc (2 * Len + 1);
+        if (T->Text == NULL) {
+          LogE(0, prep("Titles memory allocation error."));
+          return 0; //fatal error
+        }
+        decodeText2(&Data[Pos + 8],Len,(char*)T->Text,2 * Len + 1);
+        //T->Text[Len] = '\0'; //end string with NULL character
+        //memcpy (T->Text, &Data[Pos + 8], Len);
+        CleanString (T->Text);
+        Pos += Len + 8; // Sub Theme starts here
+        T->ThemeId = ((Data[7] & 0x3f) << 6) | (Data[Pos] & 0x3f);
+        T->TableId = DEFAULT_TABLE_ID; //TODO locate the actual table id
+        T->EventId = (Data[Pos + 1] << 8) | Data[Pos + 2];
+        T->SummaryAvailable = (T->EventId != 0xFFFF);
+        LogI(3, prep("EventId %04x Titlenr %d:SummAv:%x,Name:%s."), T->EventId,
+             nTitles, T->SummaryAvailable, T->Text);
+        Pos += 3;
+        nTitles++;
+        if (nTitles > MAX_TITLES) {
+          LogE(0, prep("Error, %i titles found more than %i"), nTitles, MAX_TITLES);
+          return 0; //fatal error
+        }
+      }
+      return 1; //success
+    } //else memcmp
+  } //if length
+  return 1; //non fatal error
+}
+
+/**
+ * \brief Get MHW1 Summaries
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetSummariesMHW1 (const u_char * Data, int Length)
+{
+  sSummaryMHW1 *Summary = (sSummaryMHW1 *) Data;
+  if (Length >= 11) {
+    if (Summary->NumReplays < 10) { //Why limit this at 10?
+      if (Length >= (11 + (Summary->NumReplays * 7))) {
+        if (Summary->Byte7 == 0xff && Summary->Byte8 == 0xff && Summary->Byte9 == 0xff) {
+          if (memcmp (InitialSummary, Data, 20) == 0) { //data is equal to initial buffer
+            return 2;
+          } else if (nSummaries < MAX_TITLES) {
+            if (nSummaries == 0)
+              memcpy (InitialSummary, Data, 20); //copy this data in initial buffer
+            int SummaryOffset = 11 + (Summary->NumReplays * 7);
+            int SummaryLength = Length - SummaryOffset;
+            unsigned char *Text = (unsigned char *) malloc (2*SummaryLength + 1);
+            if (Text == NULL) {
+              LogE(0, prep("Summaries memory allocation error."));
+              return 0;
+            }
+            Text[SummaryLength+1] = '\0'; //end string with NULL character
+            //memcpy (Text, &Data[SummaryOffset], SummaryLength);
+            decodeText2(&Data[SummaryOffset], SummaryLength, (char*)Text, 2*SummaryLength + 1);
+//     CleanString (Text);
+//          if (Summary->NumReplays != 0)
+//          esyslog ("EEPG: Number of replays:%i.", Summary->NumReplays);
+            //int Replays = Summary->NumReplays;
+            int ReplayOffset = 11;
+            Summary_t *S;
+            S = (Summary_t *) malloc (sizeof (Summary_t));
+            Summaries[nSummaries] = S;
+            S->NumReplays = Summary->NumReplays;
+            S->EventId = HILO32 (Summary->ProgramId);
+            S->Text = Text;
+            int i = 0;
+            do {
+              S->Replays[i].MjdTime = 0; //only used for SKY
+              //if (Summary->NumReplays == 0) {
+              //S->ChannelId = 0xFFFF; //signal that ChannelId is not known; 0 is bad signal value because it is a valid ChannelId...
+              //S->StartTime = 0;
+              //}
+              //else {
+              S->Replays[i].ChannelId = Data[ReplayOffset++] - 1;
+              unsigned int Date_hi = Data[ReplayOffset++];
+              unsigned int Date_lo = Data[ReplayOffset++];
+              unsigned short int Hour = Data[ReplayOffset++];
+              unsigned short int Minute = Data[ReplayOffset++];
+              unsigned short int Sec = Data[ReplayOffset++];
+              ReplayOffset++; //makes total of 7 bytes
+
+              LogI(4, prep("EvId:%08x ChanId:%x, ChanName %s, Time: %02d:%02d:%02d."),
+                   S->EventId, S->Replays[i].ChannelId,
+                   sChannels[ChannelSeq[S->Replays[i].ChannelId]].Name, Hour, Minute, Sec);
+
+              S->Replays[i].StartTime = MjdToEpochTime (Date) + (((((Hour & 0xf0) >> 4) * 10) + (Hour & 0x0f)) * 3600)
+                                        + (((((Minute & 0xf0) >> 4) * 10) + (Minute & 0x0f)) * 60)
+                                        + ((((Sec & 0xf0) >> 4) * 10) + (Sec & 0x0f));
+//       summary -> time[i] = ProviderLocalTime2UTC (summary -> time[i]);
+              S->Replays[i].StartTime = LocalTime2UTC (S->Replays[i].StartTime);
+              //}
+              i++;
+            } while (i < Summary->NumReplays);
+            //} while (Replays-- >= 0);
+            LogI(3, prep("EvId:%08x ChanId:%x, Replays:%d, Summnr %d:%.35s."), S->EventId,
+                 S->Replays[0].ChannelId, S->NumReplays, nSummaries, S->Text);
+            nSummaries++;
+          } else {
+            LogE(0, prep("Error, %i summaries found more than %i"), nSummaries, MAX_TITLES);
+            return 0;
+          }
+        } //0xff
+        else {
+          LogE(0, prep("Warning, Summary bytes not as expected."));
+          return 1; //it is not a success, but error is not fatal
+        }
+      } //numreplays length
+      else {
+        LogE(0, prep("Warning, number of replays is not conforming to length."));
+        return 1; //nonfatal error
+      }
+    } //numreplays <10
+    else {
+      LogE(0, prep("Warning, number of replays %d > 10, cannot process."),
+        Summary->NumReplays);
+      return 1; //nonfatal error
+    }
+  } //length >11
+  else {
+    LogE(0, prep("Summary length too small:%s"), cs_hexdump (0, Data, Length));
+    return 1; //nonfatal error
+  }
+  return 1; //success
+}
+
+/**
+ * \brief Get MHW2 Summaries
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetSummariesMHW2 (const u_char * Data, int Length)
+{
+  if (Length > (Data[14] + 17)) {
+    if (memcmp (InitialSummary, Data, 16) == 0) //data is equal to initial buffer
+      return 2;
+    else {
+      if (nSummaries == 0)
+        memcpy (InitialSummary, Data, 16); //copy this data in initial buffer
+      if (nSummaries < MAX_TITLES) {
+        int lenText = Data[14];
+        int SummaryLength = lenText;
+        int Pos = 15;
+        int Loop = Data[Pos + SummaryLength] & 0x0f;
+        Summary_t *S;
+        S = (Summary_t *) malloc (sizeof (Summary_t));
+        Summaries[nSummaries] = S;
+
+        S->Replays[0].ChannelId = 0xFFFF; //signal that ChannelId is not known; 0 is bad signal value because it is a valid ChannelId...
+        S->Replays[0].StartTime = 0; //not used
+        S->Replays[0].MjdTime = 0;  //not used
+        S->NumReplays = 0; //not used
+        S->EventId = (Data[3] << 8) | Data[4];
+        unsigned char tmp[4096]; //TODO do this smarter
+        memcpy (tmp, &Data[Pos], lenText);
+        tmp[SummaryLength] = '\n';
+        SummaryLength += 1;
+        Pos += (lenText + 1);
+        if (Loop > 0) {
+          while (Loop > 0) {
+            lenText = Data[Pos];
+            Pos += 1;
+            if ((Pos + lenText) < Length) {
+              memcpy (&tmp[SummaryLength], &Data[Pos], lenText);
+              SummaryLength += lenText;
+              if (Loop > 1) {
+                tmp[SummaryLength] = ' ';// This is considered as an EPG bug in VDR '\n';
+                SummaryLength += 1;
+              }
+            } else
+              break;
+            Pos += lenText;
+            Loop--;
+          }
+        }
+        S->Text = (unsigned char *) malloc (2 * SummaryLength + 1);
+        if (S->Text == NULL) {
+          LogE(0, prep("Summaries memory allocation error."));
+          return 0; //fatal error
+        }
+        //memcpy (S->Text, tmp, SummaryLength);
+        //S->Text[SummaryLength] = '\0'; //end string with NULL character
+        decodeText2(tmp,SummaryLength,(char*)S->Text,2 * SummaryLength + 1);
+        CleanString (S->Text);
+        LogI(3, prep("EventId %08x Summnr %d:%.30s."), S->EventId, nSummaries, S->Text);
+        nSummaries++;
+      } else {
+        LogE(0, prep("Error, %i summaries found more than %i"), nSummaries, MAX_TITLES);
+        return 0; //fatal error
+      }
+    } //else
+  } //if length
+  return 1; //succes or nonfatal error
+}
+
+/**
+ * \brief Get SKYBOX Channels
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetChannelsSKYBOX (const u_char * Data, int Length)
+{
+
+  if (memcmp (InitialChannel, Data, 8) == 0) { //data is the same as initial title
+    //LoadEquivalentChannels ();
+      EquivHandler->loadEquivalentChannelMap();
+    return 2;
+  } else {
+    if (nChannels == 0)
+      memcpy (InitialChannel, Data, 8); //copy data into initial title
+    if (nChannels == 0) {
+      LogI(1, "|  ID  | %-26.26s | %-22.22s | FND | %-8.8s |\n", "Channel ID", "Channel Name", "Sky Num.");
+      LogI(1, "|------|-%-26.26s-|-%-22.22s-|-----|-%-8.8s-|\n", "------------------------------",
+           "-----------------------------", "--------------------");
+    }
+//    unsigned short int BouquetId = (Data[3] << 8) | Data[4];
+    int BouquetDescriptorsLength = ((Data[8] & 0x0f) << 8) | Data[9];
+    int TransportStreamLoopLength =
+      ((Data[BouquetDescriptorsLength + 10] & 0x0f) << 8) | Data[BouquetDescriptorsLength + 11];
+    int p1 = (BouquetDescriptorsLength + 12);
+    while (TransportStreamLoopLength > 0) {
+      unsigned short int Tid = (Data[p1] << 8) | Data[p1 + 1];
+      unsigned short int Nid = (Data[p1 + 2] << 8) | Data[p1 + 3];
+      int TransportDescriptorsLength = ((Data[p1 + 4] & 0x0f) << 8) | Data[p1 + 5];
+      int p2 = (p1 + 6);
+      p1 += (TransportDescriptorsLength + 6);
+      TransportStreamLoopLength -= (TransportDescriptorsLength + 6);
+      while (TransportDescriptorsLength > 0) {
+        unsigned char DescriptorTag = Data[p2];
+        int DescriptorLength = Data[p2 + 1];
+        int p3 = (p2 + 2);
+        p2 += (DescriptorLength + 2);
+        TransportDescriptorsLength -= (DescriptorLength + 2);
+        switch (DescriptorTag) { //TODO switch with only 1 case??? replace this by template
+        case 0xb1:
+          p3 += 2;
+          DescriptorLength -= 2;
+          while (DescriptorLength > 0) {
+            // 0x01 = Video Channel
+            // 0x02 = Audio Channel
+            // 0x05 = Other Channel
+            //if( Data[p3+2] == 0x01 || Data[p3+2] == 0x02 || Data[p3+2] == 0x05 )
+            //{
+            unsigned short int Sid = (Data[p3] << 8) | Data[p3 + 1];
+            unsigned short int ChannelId = (Data[p3 + 3] << 8) | Data[p3 + 4];
+            unsigned short int SkyNumber = (Data[p3 + 5] << 8) | Data[p3 + 6];
+            if (SkyNumber > 100 && SkyNumber < 1000) {
+              if (ChannelId > 0) {
+                sChannel *C;
+                if (ChannelSeq.count (ChannelId) == 0) { //not found
+                  C = &sChannels[nChannels];
+                  C->ChannelId = ChannelId;
+                  //C->NumberOfEquivalences = 1; //there is always an original channel. every equivalence adds 1
+                  C->Src = Source (); //assume all EPG channels are on same satellite, if not, manage this via equivalents!!!
+                  C->Nid = Nid;
+                  C->Tid = Tid;
+                  C->Sid = Sid;
+                  C->SkyNumber = SkyNumber;
+                  tChannelID channelID = tChannelID (C->Src, C->Nid, C->Tid, C->Sid);
+                  cChannel *VC = Channels.GetByChannelID (channelID, true);
+                  bool IsFound = (VC);
+                  if (IsFound)
+                    strncpy ((char *) C->Name, VC->Name (), 64);
+                  else
+                    C->Name[0] = '\0'; //empty string
+
+                  LogI(1, "|% 5d | %-26.26s | %-22.22s | %-3.3s |  % 6d  |\n", C->ChannelId
+                       , *channelID.ToString(), C->Name, IsFound ? "YES" : "NO", C->SkyNumber);
+
+                  ChannelSeq[C->ChannelId] = nChannels; //fill lookup table to go from channel-id to sequence nr in table
+                  nChannels++;
+                  if (nChannels >= MAX_CHANNELS) {
+                    LogE(0, prep("Error, %i channels found more than %i"), nChannels, MAX_CHANNELS);
+                    return 0;
+                  }
+                }
+              }
+            }
+            p3 += 9;
+            DescriptorLength -= 9;
+          }
+          break;
+        default:
+          break;
+        } //switch descriptortag
+      }
+    } //while
+    return 1;
+  } //else part of memcmp
+}
+
+/**
+ * \brief Get SKYBOX Titles
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetTitlesSKYBOX (const u_char * Data, int Length)
+{
+  int p;
+  unsigned short int ChannelId;
+  unsigned short int MjdTime;
+  int Len1;
+  int Len2;
+
+  if (Length < 20)
+    return 1; //nonfatal error
+  if (memcmp (InitialTitle, Data, 20) == 0) //data is the same as initial title
+    return 2;
+  else {
+    if (nTitles == 0)
+      memcpy (InitialTitle, Data, 20); //copy data into initial title
+    ChannelId = (Data[3] << 8) | Data[4];
+    MjdTime = ((Data[8] << 8) | Data[9]);
+    if (ChannelId > 0) {
+      if (MjdTime > 0) {
+        p = 10;
+        do {
+          Title_t *T;
+          T = (Title_t *) malloc (sizeof (Title_t));
+          Titles[nTitles] = T;
+          T->ChannelId = ChannelId;
+          T->MjdTime = MjdTime; //only date, no time. Is used to match titles and summaries, SKYBOX only
+          T->EventId = (Data[p] << 8) | Data[p + 1];
+          Len1 = ((Data[p + 2] & 0x0f) << 8) | Data[p + 3];
+          if (Data[p + 4] != 0xb5) {
+            LogD(5, prep("Data error signature for title - Data[p + 4] != 0xb5"));
+            break;
+          }
+          if (Len1 > Length) {
+            LogD(5, prep("Data error signature for title - Len1 > Length"));
+            break;
+          }
+          p += 4;
+          Len2 = Data[p + 1] - 7;
+          T->StartTime = ((MjdTime - 40587) * 86400) + ((Data[p + 2] << 9) | (Data[p + 3] << 1));
+          T->Duration = ((Data[p + 4] << 9) | (Data[p + 5] << 1));
+          T->ThemeId = Data[p + 6];
+          T->TableId = DEFAULT_TABLE_ID; //TODO locate the actual table id
+          //TODO Data[p + 7] is Quality value add it to description
+          //int quality = Data[p + 7];
+          switch (Data[p + 8] & 0x0F) {
+          case 0x01:
+            T->Rating = 0x00; //"U"
+            break;
+          case 0x02:
+            T->Rating = 0x08; //"PG"
+            break;
+          case 0x03:
+            T->Rating = 0x0C; //"12"
+            break;
+          case 0x04:
+            T->Rating = 0x0F; //"15"
+            break;
+          case 0x05:
+            T->Rating = 0x12; //"18"
+            break;
+          default:
+            T->Rating = 0x00; //"-"
+            break;
+          }
+          T->Unknown1 = Data[p + 4 - 13]; //FIXME
+          T->Unknown2 = Data[p + 4 - 12]; //FIXME
+          T->Unknown3 = Data[p + 4 - 11]; //FIXME
+          unsigned char tmp[4096]; //TODO smarter
+          Len2 = sky_huffman_decode (&Data[p + 9], Len2, tmp);
+          if (Len2 == 0) {
+            LogE(0, prep("Warning, could not huffman-decode title-text, skipping title."));
+            return 1; //non-fatal error
+          }
+          T->Text = (unsigned char *) malloc (Len2 + 1);
+          if (T->Text == NULL) {
+            LogE(0, prep("Titles memory allocation error."));
+            return 0;
+          }
+          T->Text[Len2] = '\0'; //end string with NULL character
+          memcpy (T->Text, tmp, Len2);
+          CleanString (T->Text);
+          T->SummaryAvailable = 1; //TODO I assume this is true?
+
+          LogI(3, prep("EventId %08x Titlenr %d,Unknown1:%x,Unknown2:%x,Un3:%x,Name:%s."),
+               T->EventId, nTitles, T->Unknown1, T->Unknown2, T->Unknown3, T->Text);
+
+          p += Len1;
+          nTitles++;
+          if (nTitles >= MAX_TITLES) {
+            LogE(0, prep("Error, %i titles found more than %i"), nTitles, MAX_TITLES);
+            return 0; //fatal error
+          }
+        } while (p < Length);
+      }
+    }
+  }
+  return 1; //success
+}
+
+/**
+ * \brief Get SKYBOX Summaries
+ *
+ * \return 0 = fatal error, code 1 = success, code 2 = last item processed
+ */
+int cFilterEEPG::GetSummariesSKYBOX (const u_char * Data, int Length)
+{
+  int p;
+  unsigned short int ChannelId;
+  unsigned short int MjdTime;
+  int Len1;
+  int Len2;
+
+  if (Length < 20) {
+    return 1; //non fatal error I assume
+  }
+  if (memcmp (InitialSummary, Data, 20) == 0) //data is equal to initial buffer
+    return 2;
+//        else if (nSummaries < MAX_SUMMARIES) {
+  else {
+    if (nSummaries == 0)
+      memcpy (InitialSummary, Data, 20); //copy this data in initial buffer
+    ChannelId = (Data[3] << 8) | Data[4];
+    MjdTime = ((Data[8] << 8) | Data[9]);
+    if (ChannelId > 0) {
+      if (MjdTime > 0) {
+        p = 10;
+        do {
+          Summary_t *S;
+          S = (Summary_t *) malloc (sizeof (Summary_t));
+          Summaries[nSummaries] = S;
+          S->Replays[0].ChannelId = ChannelId;
+          S->Replays[0].MjdTime = MjdTime;
+          S->NumReplays = 0; //not used
+          S->EventId = (Data[p] << 8) | Data[p + 1];
+          Len1 = ((Data[p + 2] & 0x0f) << 8) | Data[p + 3];
+          if (Data[p + 4] != 0xb9) {
+            LogD(5, prep("Data error signature for title - Data[p + 4] != 0xb5"));
+            break;
+          }
+          if (Len1 > Length) {
+            LogD(5, prep("Data error signature for title - Len1 > Length"));
+            break;
+          }
+          p += 4;
+          Len2 = Data[p + 1];
+          unsigned char tmp[4096]; //TODO can this be done better?
+          Len2 = sky_huffman_decode (&Data[p + 2], Len2, tmp);
+          if (Len2 == 0) {
+            LogE(0, prep("Warning, could not huffman-decode text, skipping summary."));
+            return 1; //non-fatal error
+          }
+          S->Text = (unsigned char *) malloc (Len2 + 1);
+          if (S->Text == NULL) {
+            LogE(0, prep("Summaries memory allocation error."));
+            return 0;
+          }
+          memcpy (S->Text, tmp, Len2);
+          S->Text[Len2] = '\0'; //end string with NULL character
+          CleanString (S->Text);
+          LogI(3, prep("EventId %08x Summnr %d:%.30s."), S->EventId, nSummaries, S->Text);
+          p += Len1;
+          nSummaries++;
+          if (nSummaries >= MAX_TITLES) {
+            LogI(0, prep("Error, %i summaries found more than %i"), nSummaries, MAX_TITLES);
+            return 0;
+          }
+        } while (p < Length);
+      }
+    }
+  }
+  return 1;
+}
+
+void cFilterEEPG::FreeSummaries (void)
+{
+  if (Format == MHW1 || Format == MHW2 || Format == SKY_IT || Format == SKY_UK) {
+    Summary_t *S; //TODO do I need this?
+    Summary_t *S2; //TODO do I need this?
+    for (int i = 0; i < nSummaries; i++) {
+      S = Summaries[i];
+      if (i < nSummaries - 1) {
+        S2 = Summaries[i + 1]; //look at next summary
+        if (S->Text != S2->Text && S->Text != 0x00) //this is the last summary that points to this text block; needed in case NumReplays > 1, multiple pointers to same textblock
+          free (S->Text);
+      } else if (S->Text != 0x00)
+        free (S->Text);
+      free (S);
+    }
+  }
+  nSummaries = 0;
+}
+
+void cFilterEEPG::FreeTitles (void)
+{
+  if (Format == MHW1 || Format == MHW2 || Format == SKY_IT || Format == SKY_UK) {
+    Title_t *T;
+    for (int i = 0; i < nTitles; i++) {
+      T = Titles[i];
+      free (T->Text);
+      free (T);
+    }
+  }
+  nTitles = 0;
+}
+
+void cFilterEEPG::LoadIntoSchedule (void)
+{
+  int i, j;
+  i = 0;
+  j = 0;
+  bool foundtitle;
+  foundtitle = false;
+  Title_t *T;
+  Summary_t *S;
+  int remembersummary;
+  //keep statistics
+  int SummariesNotFound = 0;
+  int NoSummary = 0;
+  int NotMatching = 0;
+  int LostSync = 0;
+  remembersummary = -1;
+
+  {
+  cSchedulesLock SchedulesLock (true);
+  cSchedules *s = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+  if (s) {
+
+    while (i < nTitles) {
+      T = Titles[i];
+      S = Summaries[j];
+      foundtitle = false;
+
+      while ((i < nTitles) && (!foundtitle)) { //find next title that has summary
+        T = Titles[i];
+        if (T->SummaryAvailable)
+          foundtitle = true;
+        else {
+          NoSummary++;
+          i++;
+        }
+      }
+//esyslog("foundtitle %x for next title that has a summary:%d",foundtitle,i);
+
+      if (!foundtitle)  //no more titles with summaries
+        break;
+      if ((T->EventId == S->EventId) && (T->MjdTime == S->Replays[0].MjdTime)
+        && ((T->ChannelId == S->Replays[0].ChannelId) || ((Format != SKY_IT) && (Format != SKY_UK)))) { //should always be true, titles and summaries are broadcasted in order...
+        LogD(3, prep("T->EventId == S->EventId"));
+        //MjdTime = 0 for all but SKY
+        //S->ChannelId must be equal to T->ChannelId only for SKY; in MHW1 S->ChannelId overrides T->ChannelId when NumReplays > 1
+        remembersummary = -1; //reset summary searcher
+        //int Replays = S->NumReplays;
+
+        int index = 0;
+        do {
+          unsigned short int ChannelId;
+          time_t StartTime;
+          if (S->NumReplays == 0) {
+            ChannelId = T->ChannelId;
+            StartTime = T->StartTime;
+          } else {
+            ChannelId = S->Replays[index].ChannelId;
+            StartTime = S->Replays[index].StartTime;
+          }
+
+          //channelids are sequentially numbered and sent in MHW1 and MHW2, but not in SKY, so we need to lookup the table index
+          sChannel *C = &sChannels[ChannelSeq[ChannelId]]; //find channel
+          //cSchedule *p;//[MAX_EQUIVALENCES];
+          //PrepareToWriteToSchedule (C, s, p);
+          tChannelID chanID = tChannelID (C->Src, C->Nid, C->Tid, C->Sid);
+
+          char rating = 0x00;
+          if ((Format == SKY_IT || Format == SKY_UK) &&  T->Rating) { //TODO only works on OTV for now
+            rating = T->Rating;
+          }
+          unsigned short int TableId = DEFAULT_TABLE_ID;
+          if (T->TableId) {
+            TableId = T->TableId;
+          }
+
+          WriteToSchedule (chanID, s, T->EventId, StartTime, T->Duration / 60, (char *) T->Text,
+                           (char *) S->Text, T->ThemeId, TableId, 0, rating);
+          sortSchedules(s, chanID);
+
+          //FinishWriteToSchedule (C, s, p);
+          //Replays--;
+          //if ((S->NumReplays != 0) && (Replays > 0)) { //when replays are used, all summaries of the replays are stored consecutively; currently only CSAT
+          //j++;  //move to next summary
+          //if (j >= nSummaries) //do not forget to look in beginning of (ring)buffer
+          //j = 0;
+          //S = Summaries[j]; //next summary within replay range
+          //}
+          index++;
+        }   //while
+        while (index < S->NumReplays);
+
+        //TODO: why load events that have already past, and then run Cleanup
+        //end of putting title and summary in schedule
+        i++; //move to next title
+      }    //if T->EventId == S->EventId
+      else {
+//      esyslog("EEPG ERROR: ProgramIds not matching, title:%d,summary%d, T->EventId:%u, S->Eventid:%u.",i,j,T->EventId,S->EventId);
+        NotMatching++;
+        if (remembersummary == -1) { //I am not in search loop yet
+          remembersummary = j;
+          if (remembersummary == 0)
+            remembersummary = nSummaries; //or next test will never be succesfull for remembersummary = 0
+          LostSync++;
+//      esyslog("EEPG Error: lost sync at title %d, summary %d.",i,j);
+        } else if (j == (remembersummary - 1)) { //the last summary to be checked has failed also
+          //esyslog ("EEPG Error: could not find summary for summary-available Title %d.", i);
+          esyslog
+          ("EEPG: Error, summary not found for EventId %08x Titlenr %d:SummAv:%x,Unknown1:%x,Unknown2:%x,Un3:%x,Name:%s.",
+            T->EventId, i, T->SummaryAvailable, T->Unknown1, T->Unknown2, T->Unknown3, T->Text);
+
+          /* write Title info to schedule */
+          sChannel *C = &sChannels[ChannelSeq[T->ChannelId]]; //find channel
+          //cSchedule *p;//[MAX_EQUIVALENCES];
+          tChannelID chanID = tChannelID (C->Src, C->Nid, C->Tid, C->Sid);
+          //PrepareToWriteToSchedule (C, s, p);
+          char rating = 0x00;
+          if ((Format == SKY_IT || Format == SKY_UK) &&  T->Rating) { //TODO only works on OTV for now
+            rating = T->Rating;
+          }
+          WriteToSchedule (chanID, s, T->EventId, T->StartTime, T->Duration / 60, (char *) T->Text,
+                           NULL, T->ThemeId, DEFAULT_TABLE_ID, 0, rating);
+          //FinishWriteToSchedule (C, s, p);
+          sortSchedules(s, chanID);
+
+          SummariesNotFound++;
+          i++; //move to next title, for this one no summary can be found
+        }
+
+//      esyslog("Trying again for this title %d, remember summary %d, but advancing one Summary to %d.",i,remembersummary,j);
+      }
+      j++; //move to next summary
+      if (j >= nSummaries) //do not forget to look in beginning of (ring)buffer
+        j = 0;
+    } //while title
+  } // if s
+  else
+    LogE (0, prep("Error: could not lock schedules."));
+
+  }//release ScheduleLock
+  cSchedules::Cleanup (true); //deletes all past events
+
+  //isyslog ("EEPG: found %i equivalents channels", nEquivChannels);
+  isyslog ("EEPG: found %i themes", nThemes);
+  isyslog ("EEPG: found %i channels", nChannels);
+  isyslog ("EEPG: found %i titles", nTitles);
+  if (NoSummary != 0)
+    isyslog ("EEPG: of which %i reported to have no summary available; skipping these BIENTOT titles", NoSummary);
+  isyslog ("EEPG: found %i summaries", nSummaries);
+  if (SummariesNotFound != 0)
+    esyslog ("EEPG: %i summaries not found", SummariesNotFound);
+  if (NotMatching > nSummaries)
+    LogI (0, prep("Warning: lost sync %i times, summary did not match %i times."),
+      LostSync, NotMatching);
+
+  FreeSummaries (); //do NOT free channels, themes and bouquets here because they will be reused in SKY!
+  FreeTitles ();
+  if (!((Format == SKY_IT) || (Format == SKY_UK))) { //everything but SKY; SKY is the only protocol where LoadIntoSchedule is called repeatedly
+    ChannelSeq.clear ();
+  }
+}
+
+void cFilterEEPG::AddFilter (u_short Pid, u_char Tid)
+{
+  if (!Matches (Pid, Tid)) {
+    Add (Pid, Tid);
+    esyslog (prep("Filter Pid:%x,Tid:%x added."), Pid, Tid);
+  }
+}
+
+void cFilterEEPG::AddFilter (u_short Pid, u_char Tid, unsigned char Mask)
+{
+  if (!Matches (Pid, Tid)) {
+    Add (Pid, Tid, Mask);
+    esyslog (prep("Filter Pid:%x,Tid:%x,Mask:%x added."), Pid, Tid, Mask);
+  }
+}
+
+void cFilterEEPG::ProcessNextFormat (bool FirstTime = false)
+{
+  /*  for (int i = 0; i <= HIGHEST_FORMAT; i++)
+      esyslog ("EEPGDEBUG: Format %i on pid %x", i, UnprocessedFormat[i]); */
+
+  if (!FirstTime) {
+    //isyslog ("EEPG: found %i equivalents channels", equiChanMap.size());
+    isyslog ("EEPG: found %i themes", nThemes);
+    isyslog ("EEPG: found %i channels", nChannels);
+    isyslog ("EEPG: found %i titles", nTitles);
+    isyslog ("EEPG: found %i summaries", nSummaries);
+    isyslog ("EEPG: written %i titles", TitleCounter);
+    isyslog ("EEPG: written %i summaries", SummaryCounter);
+    isyslog ("EEPG: rejected %i titles/summaries because of higher TableId", RejectTableId);
+    //Send message when finished
+    if (SetupPE->DisplayMessage) {
+      char *mesg;
+      Asprintf(&mesg, "EEPG: written %i summaries", SummaryCounter);
+      Skins.QueueMessage(mtInfo, mesg, 2);
+      free(mesg);
+    }
+
+    TitleCounter = 0;
+    SummaryCounter = 0;
+    /*if (SummariesNotFound != 0)
+       esyslog ("EEPG: %i summaries not found", SummariesNotFound);
+       else if (VERBOSE >= 1)
+       isyslog ("EEPG: %i summaries not found", SummariesNotFound); */
+    UnprocessedFormat[Format] = 0; //clear previously processed format
+
+    //Next few lines prevent eepg from reading multiple eepg-systems on one transponder e.g. CDNL
+    //isyslog ("EEPG: Ended all processing");
+    //return;
+    //If you remove these lines, multiple systems WILL be read
+
+  }
+  TitleCounter = 0;
+  SummaryCounter = 0;
+  RejectTableId = 0;
+  //cleanup mess of last processing
+  ChannelSeq.clear ();
+  FreeTitles ();
+  FreeSummaries ();
+
+  // Enable EIT scan for all except DISH_BEV since it is already enabled
+  if (SetupPE->ProcessEIT && !UnprocessedFormat[EIT]
+     && !UnprocessedFormat[FREEVIEW] && !UnprocessedFormat[DISH_BEV]) {
+    UnprocessedFormat[EIT] = EIT_PID;
+    EquivHandler->loadEquivalentChannelMap();
+  }
+
+  //now start looking for next format to process
+  int pid;
+  for (int i = 0; i <= HIGHEST_FORMAT; i++){ //find first format that is detected
+    if (UnprocessedFormat[i]) {
+      isyslog ("EEPG: %s Extended EPG detected on pid %x.", FormatName[i], UnprocessedFormat[i]);
+      Format = (EFormat)i;
+      // highest format is processed first this way
+      // make sure that CONT protocols like Premiere, Freesat are processed
+      // AFTER ONCE protocols like MHW, SKY and NAGRA
+      break;
+    }
+    if (i == HIGHEST_FORMAT) { //there are no formats left to process
+      isyslog ("EEPG: Ended all processing");
+      return;
+    }
+  }
+
+  pid = UnprocessedFormat[Format]; //and reinstall its pid
+
+  memset (&InitialChannel, 0, 8);
+  memset (&InitialTitle, 0, 64);
+  memset (&InitialSummary, 0, 64);
+  NagraCounter = 0;
+  Version = -1; //because 0 can be a valid version number...
+  nChannels = 0;
+  nThemes = 0;
+  EndChannels = false;
+  EndThemes = false;
+  switch (Format) {
+  case PREMIERE:
+    AddFilter (pid, 0xA0);
+    break;
+  case MHW1:
+    AddFilter (0xd3, 0x92); //ThemesMHW1//TODO: all filters are serialized, strictly speaking Themes is non-fatal...
+    break;
+  case MHW2:
+    AddFilter (0x231, 0xc8); //MHW2 Channels & Themes
+    break;
+  case SKY_IT:
+  case SKY_UK:
+    AddFilter (0x11, 0x4a); //Sky Channels
+    break;
+  case FREEVIEW: //Freeview, CONT mode //TODO streamline this for other modes
+    InitDictionary ();
+    AddFilter (pid, 0x4e, 0xfe); //event info, actual(0x4e)/other(0x4f) TS, present/following
+    AddFilter (pid, 0x50, 0xf0); //event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
+    AddFilter (pid, 0x60, 0xf0); //event info, other  TS, schedule(0x60)/schedule for future days(0x6X)
+    AddFilter (0x39, 0x50, 0xf0); //event info, actual TS, Viasat
+    AddFilter (0x39, 0x60, 0xf0); //event info, other  TS, Viasat
+    break;
+  case NAGRA:
+    AddFilter (pid, 0xb0); //perhaps TID is equal to first data byte?
+    break;
+  case DISH_BEV:
+#if APIVERSNUM < 10726
+    AddFilter (EIT_PID, 0, 0); // event info, actual(0x4e)/other(0x4f) TS, present/following
+#endif
+    AddFilter (0x0300, 0, 0); // Dish Network EEPG event info, actual(0x4e)/other(0x4f) TS, present/following
+    AddFilter (0x0441, 0, 0); // Dish Network EEPG event info, actual(0x4e)/other(0x4f) TS, present/following
+//    AddFilter (0x0441, 0x50, 0xf0); // Bell ExpressVU EEPG
+//    AddFilter (0x0441, 0x60, 0xf0); // Bell ExpressVU EEPG
+    break;
+  case EIT:
+    AddFilter (pid, 0x4e, 0xfe); //event info, actual(0x4e)/other(0x4f) TS, present/following
+    AddFilter (pid, 0x50, 0xf0); //event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
+    AddFilter (pid, 0x60, 0xf0); //event info, other  TS, schedule(0x60)/schedule for future days(0x6X)
+    break;
+  default:
+    break;
+  }
+}
+
+void cFilterEEPG::ProccessContinuous(u_short Pid, u_char Tid, int Length, const u_char *Data)
+{
+  //0x39 Viasat, 0x0300 Dish Network EEPG, 0x0441 Bell ExpressVU EEPG
+  LogD(4, prep("Pid: 0x%02x Tid: %d Length: %d"), Pid, Tid, Length);
+  cSchedulesLock SchedulesLock(true, 10);
+  cSchedules *Schedules = (cSchedules*)(cSchedules::Schedules(SchedulesLock));
+  //Look for other satelite positions only if Dish/Bell ExpressVU for the moment hardcoded pid check
+  if(Schedules)
+    SI::cEIT2 EIT(Schedules, Source(), Tid, Data, Pid == EIT_PID);
+
+  else//cEIT EIT (Schedules, Source (), Tid, Data);
+  {
+    // If we don't get a write lock, let's at least get a read lock, so
+    // that we can set the running status and 'seen' timestamp (well, actually
+    // with a read lock we shouldn't be doing that, but it's only integers that
+    // get changed, so it should be ok)
+    cSchedulesLock SchedulesLock;
+    cSchedules *Schedules = (cSchedules*)(cSchedules::Schedules(SchedulesLock));
+    if(Schedules)
+      SI::cEIT2 EIT(Schedules, Source(), Tid, Data, Pid == EIT_PID, true);
+
+    //cEIT EIT (Schedules, Source (), Tid, Data, true);
+  }
+}
+
+void cFilterEEPG::Process (u_short Pid, u_char Tid, const u_char * Data, int Length)
+{
+  int now = time (0);
+//  LogD(2, prep("Pid: 0x%02x Tid: %d Length: %d PMT pid: 0x%04x"), Pid, Tid, Length, pmtpid);
+//  LogD(2, prep("Source: %d Transponder: %d"), Source () , Transponder ());
+
+  if (Pid == 0 && Tid == SI::TableIdPAT) {
+    if (!pmtnext || now > pmtnext) {
+      if (pmtpid)
+        NextPmt ();
+      if (!pmtpid) {
+        SI::PAT pat (Data, false);
+        if (pat.CheckCRCAndParse ()) {
+          SI::PAT::Association assoc;
+          int idx = 0;
+          for (SI::Loop::Iterator it; pat.associationLoop.getNext (assoc, it);) {
+            if (!assoc.isNITPid ()) {
+              //if (!assoc.isNITPid () && Scanning) {
+              if (idx++ == pmtidx) {
+                pmtpid = assoc.getPid ();
+                pmtsid = assoc.getServiceId ();
+                Add (pmtpid, 0x02);
+                pmtnext = now + PMT_SCAN_TIMEOUT;
+                LogI(3, prep("PMT pid now 0x%04x (idx=%d)\n"), pmtpid, pmtidx);
+                break;
+              }
+            }
+          }
+          if (!pmtpid) {
+            pmtidx = 0;
+            pmtnext = now + PMT_SCAN_IDLE;
+            LogI(1, prep("PMT scan idle\n"));
+
+            Del (0, 0);  //this effectively kills the PMT_SCAN_IDLE functionality
+
+            //now after the scan is completed, start processing
+            ProcessNextFormat (true); //FirstTime flag is set
+          }
+        }
+      }
+    }
+  } else if (pmtpid > 0 && Pid == pmtpid && Tid == SI::TableIdPMT && Source () && Transponder ()) {
+    SI::PMT pmt (Data, false);
+    if (pmt.CheckCRCAndParse () && pmt.getServiceId () == pmtsid) {
+      SI::PMT::Stream stream;
+      for (SI::Loop::Iterator it; pmt.streamLoop.getNext (stream, it);) {
+        LogD(4, prep("StreamType: 0x%02x"), stream.getStreamType ());
+        if (stream.getStreamType () == 0x05 || stream.getStreamType () == 0xc1) { //0x05 = Premiere, SKY, Freeview, Nagra 0xc1 = MHW1,MHW2;
+          SI::CharArray data = stream.getData ();
+          if ((data[1] & 0xE0) == 0xE0 && (data[3] & 0xF0) == 0xF0) {
+            bool prvData = false, usrData = false;
+            bool prvOTV = false, prvFRV = false;
+            int usrOTV = 0, usrFRV = 0;
+            if (data[2]==0x39) {//TODO Test This
+              prvFRV = true;
+              usrFRV = 1;
+              LogD(4, prep("if (data[2]==0x39) {//TODO Test This"));
+            }
+            //Format = 0;               // 0 = premiere, 1 = MHW1, 2 = MHW2, 3 = Sky Italy (OpenTV), 4 = Sky UK (OpenTV), 5 = Freesat (Freeview), 6 = Nagraguide
+            SI::Descriptor * d;
+            unsigned char nDescriptorTag;
+            for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext (it));) {
+              LogD(4, prep("EEPGDEBUG:d->getDescriptorTAG():%x,SI::PrivateTag:%x\n"), d->getDescriptorTag (), SI::PrivateDataSpecifierDescriptorTag);
+              nDescriptorTag = d->getDescriptorTag ();
+              switch (nDescriptorTag) {
+              case SI::PrivateDataSpecifierDescriptorTag:
+                //esyslog ("prv: %d %08x\n", d->getLength (), d->getData ().FourBytes (2));
+                if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x000000be)
+                  prvData = true;
+                if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x4f545600) //OpenTV
+                  prvOTV = true;
+                if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x46534154) //Freeview
+                  prvFRV = true;
+                break;
+              case 0x52:
+                //if (d->getLength () == 3 && d->getData ().FourBytes (2) == 0xb07ea882) {
+                if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0xb000))
+                  UnprocessedFormat[NAGRA] = stream.getPid ();
+                break;
+              case 0x90:
+                //esyslog ("usr: %d %08x\n", d->getLength (), d->getData ().FourBytes (2));
+                if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x0000ffff)
+                  usrData = true;
+                if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0xb600)) //SKY IT //TODO ugly!
+                  //if (d->getLength () == 3 && (d->getData ().TwoBytes (2) == 0xb6a5))   //SKY IT //TODO ugly!
+                  usrOTV = SKY_IT;
+                //Format = SKY_IT;
+                if (d->getLength () == 3 && d->getData ().FourBytes (2) == 0xc004e288)       //SKY UK
+                  usrOTV = SKY_UK;
+                //Format = SKY_UK;
+                break;
+              case 0xc1: //MHW1, MHW2
+//      esyslog("EEPGDEBUG:d->getDescriptorTAG:%d %08x\n",d->getLength(),d->getData().FourBytes(2));
+                if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x50555348) //MHw1 Cyfra
+                  UnprocessedFormat[MHW1] = stream.getPid ();
+                break;
+              case 0xc2: //MHW1, MHW2
+                if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x45504700) //MHw1 CanDigNL and CSat
+                  UnprocessedFormat[MHW1] = stream.getPid ();
+                else if (d->getLength () == 10 && d->getData ().FourBytes (2) == 0x46494348) { //MHW2
+                  UnprocessedFormat[MHW2] = stream.getPid ();
+                }
+                break;
+              case 0xd1: //Freeview
+                LogD(4, prep("case 0xd1: //Freeview"));
+                if (d->getLength () == 3 && ((d->getData ().TwoBytes (2) & 0xff00) == 0x0100))
+                  usrFRV = 0x01;
+                //01 = EIT pid 3842
+                //03 04 = SDT Service Description Table pid 3841
+                //07 = still undocumented, definition of buch of transport streams pid 3840
+                //02 = ATSC reserved, find out what huffman encoded text is sent here! pid 3843
+                //05 06 = TOT Time Offset Table pid 3844
+                break;
+
+                /*       case 0xfe: //SKY_IT
+                  if (d->getLength () == 6 && d->getData ().FourBytes (2) == 0x534b5900) { //SKY_IT
+                    Format = SKY_IT;
+                  }
+                  break;*/
+              default:
+                break;
+              }
+              delete d;
+            }
+            if ((prvOTV) && ((usrOTV == SKY_IT) || (usrOTV == SKY_UK)))
+              UnprocessedFormat[usrOTV] = stream.getPid ();
+            else if (prvFRV)
+              if (usrFRV == 0x01)
+                UnprocessedFormat[FREEVIEW] = stream.getPid ();
+            if (prvData && usrData)
+              UnprocessedFormat[PREMIERE] = stream.getPid ();
+            //TODO DPE DISH/BEV filters are always ON on provided transponders,
+            // but there is no knowledge for the loop of the data at the moment.
+            //EEPG:12472:H:S119.0W:20000:0:0:0:0:36862:4100:18:36862
+            if (((Source() == cSource::FromString("S119.0W")
+                && Transponder() == cChannel::Transponder(12472,'H'))
+                || (Source() == cSource::FromString("S91.0W")
+                && Transponder() == cChannel::Transponder(12224,'V')))
+                && !UnprocessedFormat[DISH_BEV]) {
+              UnprocessedFormat[DISH_BEV] = stream.getPid ();
+            }
+
+          }   //if data[1] && data [3]
+        }   //if streamtype
+      } //for loop that walks through streams
+      NextPmt ();
+      pmtnext = 0;
+      /*      }
+            else {
+       Del (pmtpid, 0x02);
+       Del (0, 0);
+       pmtidx = 0;
+       pmtnext = now + PMT_SCAN_IDLE;
+       isyslog ("PMT scan forced idle\n");
+            }*/
+    } //checkCRC
+  } //if pmtpid
+  else if (Source ()) {
+
+    if ( Pid == EIT_PID || Pid == 0x0300 || Pid == 0x0441 ) {
+      if (Tid >= 0x4E)
+        ProccessContinuous(Pid, Tid, Length, Data);
+      return;
+    }
+    int Result;
+    switch (Tid) {
+    case 0xA0:
+      if ((Pid < 0x30) || (Pid > 0x37)) {
+
+        ProcessPremiere(Data);
+        break;
+      } //if citpid == 0xb11 Premiere
+      /* no break - used for sky also*/
+    case 0xa1:
+    case 0xa2:
+    case 0xa3:
+      Result = GetTitlesSKYBOX (Data, Length - 4);
+      if (Result != 1) //when fatal error or finished
+        Del (Pid, 0xa0, 0xfc); //kill filter
+      if (Result == 0) { //fatal error
+        esyslog ("EEPG: Fatal error reading titles.");
+        ProcessNextFormat (); //and go process other formats
+      }
+      if (Result == 2)
+        AddFilter (Pid + 0x10, 0xa8, 0xfc); //Set filter that processes summaries of this batch
+      break;
+    case 0xa8:
+    case 0xa9:
+    case 0xaa:
+    case 0xab:
+      Result = GetSummariesSKYBOX (Data, Length - 4);
+      if (Result != 1) //when fatal error or finished
+        Del (Pid, 0xa8, 0xfc); //kill filter
+      if (Result == 0) {
+        esyslog ("EEPG: Fatal error reading summaries.");
+        ProcessNextFormat ();
+      }
+      if (Result == 2) {
+        LoadIntoSchedule ();
+        if (Pid < 0x47) //this is not the last batch//FIXME chaining is easy on the PIDs and the CPU, but error when Pid,Tid is not used at the moment...
+          AddFilter (Pid - 0x0F, 0xa0, 0xfc); //next pid, first tid
+        else //last pid was processed
+          ProcessNextFormat ();
+      }
+      break;
+    case 0x90:
+      if (Pid == 0xd2) {
+        Result = GetTitlesMHW1 (Data, Length);
+        if (Result != 1) //fatal error or last processed
+          Del (Pid, Tid);
+        if (Result == 0) {
+          esyslog ("EEPG: Fatal error reading titles.");
+          ProcessNextFormat ();
+        }
+        if (Result == 2)
+          AddFilter (0xd3, 0x90); //SummariesMHW1
+      } else if (Pid == 0xd3) {
+        Result = GetSummariesMHW1 (Data, Length);
+        if (Result != 1) //fatal error or last processed
+          Del (Pid, Tid);
+        if (Result == 0) {
+          esyslog ("EEPG: Fatal error reading summaries.");
+        }
+        if (Result == 2) {
+          LoadIntoSchedule ();
+        }
+        if (Result != 1) {
+          ProcessNextFormat ();
+        }
+      }
+      break;
+    case 0xc8: //GetChannelsMHW2 or GetThemesMHW2
+      if (Pid == 0x231) {
+        if (Data[3] == 0x01) { //Themes it will be
+          Result = GetThemesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+          //break;
+          if (Result != 1)
+            EndThemes = true; //also set Endthemes on true on fatal error
+        } //if Data
+        else if (Data[3] == 0x00) { //Channels it will be
+          Result = GetChannelsMHW (Data, Length, 2); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+          if (Result != 1)
+            EndChannels = true; //always remove filter, code 1 should never be returned since MHW2 always reads all channels..
+          ChannelsOk = (Result == 2);
+        }
+        if (EndChannels && EndThemes) { //those are only set withing MHW2
+          Del (0x231, 0xc8); //stop reading MHW2 themes and channels
+          if (ChannelsOk) //No channels = fatal, no themes = nonfatal
+            AddFilter (0x234, 0xe6); //start reading MHW2 titles
+          else {
+            esyslog ("EEPG: Fatal error reading channels.");
+            ProcessNextFormat ();
+          }
+        }
+      }    //if Pid == 0x231
+      break;
+    case 0x91:
+      Result = GetChannelsMHW (Data, Length, 1); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+      Del (Pid, Tid); //always remove filter, code 1 should never be returned since MHW1 always reads all channels...
+      if (Result == 2)
+        AddFilter (0xd2, 0x90); //TitlesMHW1
+      else {
+        esyslog ("EEPG: Fatal error reading channels.");
+        ProcessNextFormat ();
+      }
+      break;
+    case 0x92:
+      Result = GetThemesMHW1 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+      if (Result != 1)
+        Del (Pid, Tid);
+      if (Result == 2)
+        AddFilter (0xd3, 0x91); //ChannelsMHW1
+      else {
+        esyslog ("EEPG: Fatal error reading themes."); //doesnt have to be fatal...
+        ProcessNextFormat ();
+      }
+      break;
+    case 0xe6: //TitlesMHW2
+      if (Pid == 0x234) {
+        Result = GetTitlesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+        if (Result != 1)
+          Del (Pid, Tid);
+        if (Result == 0) {
+          esyslog ("EEPG: Fatal error reading titles.");
+          ProcessNextFormat ();
+        }
+        if (Result == 2)
+          AddFilter (0x236, 0x96); //start reading MHW2 summaries....
+      }
+      break;
+    case 0x96: //Summaries MHW2
+      if (Pid == 0x236) {
+        Result = GetSummariesMHW2 (Data, Length); //return code 0 = fatal error, code 1 = sucess, code 2 = last item processed
+        if (Result != 1)
+          Del (Pid, Tid);
+        if (Result == 0) {
+          esyslog ("EEPG: Fatal error reading summaries.");
+        }
+        if (Result == 2)
+          LoadIntoSchedule ();
+        if (Result != 1) {
+          ProcessNextFormat ();
+        }
+      } //if pid
+      break;
+    case 0x4a: //Sky channels
+      if (Pid == 0x11) {
+        Result = GetChannelsSKYBOX (Data, Length - 4);
+        if (Result != 1) //only breakoff on completion or error; do NOT clean up after success, because then not all bouquets will be read
+          Del (Pid, Tid); //Read all channels, clean up filter
+        if (Result == 2) {
+          GetThemesSKYBOX (); //Sky Themes from file; must be called AFTER first channels to have lThemes initialized FIXME
+          if (InitDictionary ())
+            AddFilter (0x30, 0xa0, 0xfc); //SKY Titles batch 0 of 7
+          else {
+            esyslog ("EEPG: Fatal error reading huffman table.");
+            ProcessNextFormat ();
+          }
+        }
+
+      } //if Pid == 0x11
+      break;
+    case 0xb0: //NagraGuide
+      if (Pid == 0xc8) {
+        Result = GetNagra (Data, Length);
+        if (Result != 1)
+          Del (Pid, Tid);
+        if (Result == 0) {
+          esyslog ("EEPG: Fatal error processing NagraGuide. End of processing.");
+        }
+        if (Result == 2) {
+          ProcessNagra ();
+          cSchedules::Cleanup (true); //deletes all past events
+          isyslog ("EEPG: Ended processing Nagra");
+        }
+        if (Result != 1) {
+          ProcessNextFormat ();
+        }
+      }
+      break;
+
+    case 0x4E:
+    case 0x4F:
+    case 0x50:
+    case 0x51:
+    case 0x52:
+    case 0x53:
+    case 0x54:
+    case 0x55:
+    case 0x56:
+    case 0x57:
+    case 0x58:
+    case 0x59:
+    case 0x5A:
+    case 0x5B:
+    case 0x5C:
+    case 0x5D:
+    case 0x5E:
+    case 0x5F:
+    case 0x60:
+    case 0x61:
+    case 0x62:
+    case 0x63:
+    case 0x64:
+    case 0x65:
+    case 0x66:
+    case 0x67:
+    case 0x68:
+    case 0x69:
+    case 0x6A:
+    case 0x6B:
+    case 0x6C:
+    case 0x6D:
+    case 0x6E:
+    case 0x6F:
+      // Freesat:
+      // Set(3842, 0x4E, 0xFE);  // event info, actual(0x4E)/other(0x4F) TS, present/following
+      // Set(3842, 0x50, 0xF0);  // event info, actual TS, schedule(0x50)/schedule for future days(0x5X)
+      // Set(3842, 0x60, 0xF0);  // event info, other  TS, schedule(0x60)/schedule for future days(0x6X)
+      //
+      // PID found: 3841 (0x0f01)  [SECTION: Service Description Table (SDT) - other transport stream]
+      // PID found: 3842 (0x0f02)  [SECTION: Event Information Table (EIT) - other transport stream, schedule]
+      // PID found: 3843 (0x0f03)  [SECTION: ATSC reserved] TODO find out what compressed text info is here!
+      // PID found: 3844 (0x0f04)  [SECTION: Time Offset Table (TOT)]
+
+      if (Pid == 3842 || Pid == 0x39) {//0x39 Viasat, 0x0300 Dish Network EEPG, 0x0441 Bell ExpressVU EEPG
+        ProccessContinuous(Pid, Tid, Length, Data);
+      }
+      break;
+
+    default:
+      break;
+    } //end switch
+  } //closes SOURCE()
+} //end of closing
+
+void cFilterEEPG::ProcessPremiere(const u_char *& Data)
+
+{
+
+  SI::PremiereCIT cit(Data, false);
+
+  if (cit.CheckCRCAndParse ()) {
+    cSchedulesLock SchedulesLock (true, 10);
+    cSchedules *Schedules = (cSchedules *) cSchedules::Schedules (SchedulesLock);
+    if (Schedules) {
+      int now = time (0);
+      int nCount = 0;
+      int nRating = 0;
+      unsigned char Tid = 0xa0; // TODO maybe default TableID
+      SI::ExtendedEventDescriptors * ExtendedEventDescriptors = 0;
+      SI::ShortEventDescriptor * ShortEventDescriptor = 0;
+      char *order = 0, *rating = 0;
+      {
+        time_t firstTime = 0;
+        SI::Descriptor * d;
+        unsigned char nDescriptorTag;
+        bool UseExtendedEventDescriptor = false;
+        int LanguagePreferenceShort = -1;
+        int LanguagePreferenceExt = -1;
+        for (SI::Loop::Iterator it; (d = cit.eventDescriptors.getNext (it));) {
+          nDescriptorTag = d->getDescriptorTag ();
+          switch (nDescriptorTag) {
+          case 0xF0: // order information
+            if (SetupPE->OrderInfo) {
+              static const char *text[] = {
+                trNOOP ("Ordernumber"),
+                trNOOP ("Price"),
+                trNOOP ("Ordering"),
+                trNOOP ("SMS"),
+                trNOOP ("WWW")
+              };
+              char buff[512];
+              int p = 0;
+              const unsigned char *data = d->getData ().getData () + 2;
+              for (int i = 0; i < 5; i++) {
+                int l = data[0];
+                if (l > 0)
+                  p += snprintf (&buff[p], sizeof (buff) - p, "\n%s: %.*s", tr (text[i]), l, &data[1]);
+                data += l + 1;
+              }
+              if (p > 0)
+                order = strdup (buff);
+            }
+            break;
+          case 0xF1: // parental rating
+            if (SetupPE->RatingInfo) {
+              char buff[512];
+              int p = 0;
+              const unsigned char *data = d->getData ().getData () + 2;
+              nRating = data[0] + 3;
+              p += snprintf (&buff[p], sizeof (buff) - p, "\n%s: %d %s", tr ("Rating"), nRating, tr ("years"));
+              data += 7;
+              int l = data[0];
+              if (l > 0)
+                p += snprintf (&buff[p], sizeof (buff) - p, " (%.*s)", l, &data[1]);
+              if (p > 0)
+                rating = strdup (buff);
+            }
+            break;
+          case SI::PremiereContentTransmissionDescriptorTag:
+            if (nCount >= 0) {
+              SI::PremiereContentTransmissionDescriptor * pct = (SI::PremiereContentTransmissionDescriptor *) d;
+              nCount++;
+              SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
+              SI::Loop::Iterator it;
+              if (pct->startDayLoop.getNext (sd, it)) {
+                SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
+                SI::Loop::Iterator it2;
+                if (sd.startTimeLoop.getNext (st, it2)) {
+                  time_t StartTime = st.getStartTime (sd.getMJD ());
+                  if (nCount == 1)
+                    firstTime = StartTime;
+                  else if (firstTime < StartTime - 5 * 50 || firstTime > StartTime + 5 * 60)
+                    nCount = -1;
+                }
+              }
+            }
+            break;
+          case SI::ExtendedEventDescriptorTag: {
+            SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
+            if (I18nIsPreferredLanguage (Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
+              || !ExtendedEventDescriptors) {
+              delete ExtendedEventDescriptors;
+              ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+              UseExtendedEventDescriptor = true;
+            }
+            if (UseExtendedEventDescriptor) {
+              ExtendedEventDescriptors->Add (eed);
+              d = NULL; // so that it is not deleted
+            }
+            if (eed->getDescriptorNumber () == eed->getLastDescriptorNumber ())
+              UseExtendedEventDescriptor = false;
+          }
+          break;
+          case SI::ShortEventDescriptorTag: {
+            SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
+            if (I18nIsPreferredLanguage (Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
+              || !ShortEventDescriptor) {
+              delete ShortEventDescriptor;
+              ShortEventDescriptor = sed;
+              d = NULL; // so that it is not deleted
+            }
+          }
+          break;
+          default:
+            break;
+          }
+          delete d;
+        }
+      }
+
+      {
+        bool Modified = false;
+        int optCount = 0;
+        unsigned int crc[3];
+        crc[0] = cit.getContentId ();
+        SI::PremiereContentTransmissionDescriptor * pct;
+        for (SI::Loop::Iterator it;
+          (pct =
+            (SI::PremiereContentTransmissionDescriptor *) cit.eventDescriptors.getNext (it,
+              SI::
+              PremiereContentTransmissionDescriptorTag));) {
+          int nid = pct->getOriginalNetworkId ();
+          int tid = pct->getTransportStreamId ();
+          int sid = pct->getServiceId ();
+          if (SetupPE->FixEpg) {
+            if (nid == 133) {
+              if (tid == 0x03 && sid == 0xf0) {
+                tid = 0x02;
+                sid = 0xe0;
+              } else if (tid == 0x03 && sid == 0xf1) {
+                tid = 0x02;
+                sid = 0xe1;
+              } else if (tid == 0x03 && sid == 0xf5) {
+                tid = 0x03;
+                sid = 0xdc;
+              } else if (tid == 0x04 && sid == 0xd2) {
+                tid = 0x11;
+                sid = 0xe2;
+              } else if (tid == 0x11 && sid == 0xd3) {
+                tid = 0x11;
+                sid = 0xe3;
+              }
+            }
+          }
+          tChannelID channelID (Source (), nid, tid, sid);
+          cChannel *channel = Channels.GetByChannelID (channelID, true);
+
+          if (!channel)
+            continue;
+
+          cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channelID);
+          if (!pSchedule) {
+            pSchedule = new cSchedule (channelID);
+            Schedules->Add (pSchedule);
+          }
+
+          optCount++;
+          SI::PremiereContentTransmissionDescriptor::StartDayEntry sd;
+          int index = 0;
+          for (SI::Loop::Iterator it; pct->startDayLoop.getNext (sd, it);) {
+            int mjd = sd.getMJD ();
+            SI::PremiereContentTransmissionDescriptor::StartDayEntry::StartTimeEntry st;
+            for (SI::Loop::Iterator it2; sd.startTimeLoop.getNext (st, it2);) {
+              time_t StartTime = st.getStartTime (mjd);
+              time_t EndTime = StartTime + cit.getDuration ();
+              int runningStatus =
+                (StartTime < now && now < EndTime) ? SI::RunningStatusRunning :
+                  ((StartTime - 30 < now && now < StartTime) ?
+                    SI::RunningStatusStartsInAFewSeconds : SI::RunningStatusNotRunning);
+              bool isOpt = false;
+              if (index++ == 0 && nCount > 1)
+                isOpt = true;
+              crc[1] = isOpt ? optCount : 0;
+              crc[2] = StartTime / STARTTIME_BIAS;
+              tEventID EventId = ((('P' << 8) | 'W') << 16) | crc16 (0, (unsigned char *) crc, sizeof (crc));
+              LogI(2, "%s R%d %04x/%.4x %d %d/%d %s +%d ", *channelID.ToString (), runningStatus,
+                   EventId & 0xFFFF, cit.getContentId (), index, isOpt, optCount,
+                   stripspace (ctime (&StartTime)), (int) cit.getDuration () / 60);
+              if (EndTime + Setup.EPGLinger * 60 < now) {
+                LogI(2, "(old)\n");
+                continue;
+              }
+
+              bool newEvent = false;
+              cEvent *pEvent = (cEvent *) pSchedule->GetEvent (EventId, -1);
+              if (!pEvent) {
+                LogI(2, "(new)\n");
+                pEvent = new cEvent (EventId);
+                if (!pEvent)
+                  continue;
+                newEvent = true;
+              } else {
+                LogI(2, "(upd)\n");
+                pEvent->SetSeen ();
+                if (pEvent->TableID () == 0x00 || pEvent->Version () == cit.getVersionNumber ()) {
+                  if (pEvent->RunningStatus () != runningStatus)
+                    pSchedule->SetRunningStatus (pEvent, runningStatus, channel);
+                  continue;
+                }
+              }
+              pEvent->SetEventID (EventId);
+              pEvent->SetTableID (Tid);
+              pEvent->SetVersion (cit.getVersionNumber ());
+              pEvent->SetStartTime (StartTime);
+              pEvent->SetDuration (cit.getDuration ());
+
+              if (ShortEventDescriptor) {
+                char buffer[256];
+                ShortEventDescriptor->name.getText (buffer, sizeof (buffer));
+                if (isOpt) {
+                  char buffer2[sizeof (buffer) + 32];
+                  snprintf (buffer2, sizeof (buffer2), optPats[SetupPE->OptPat], buffer, optCount);
+                  pEvent->SetTitle (buffer2);
+                } else
+                  pEvent->SetTitle (buffer);
+                LogI(2, "title: %s\n", pEvent->Title ());
+                pEvent->SetShortText (ShortEventDescriptor->text.getText (buffer, sizeof (buffer)));
+              }
+              if (ExtendedEventDescriptors) {
+                char buffer[ExtendedEventDescriptors->getMaximumTextLength (": ") + 1];
+                pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
+              }
+              if (order || rating) {
+                int len = (pEvent->Description ()? strlen (pEvent->Description ()) : 0) +
+                  (order ? strlen (order) : 0) + (rating ? strlen (rating) : 0);
+                char buffer[len + 32];
+                buffer[0] = 0;
+                if (pEvent->Description ())
+                  strcat (buffer, pEvent->Description ());
+                if (rating) {
+                  strcat (buffer, rating);
+                  pEvent->SetParentalRating(nRating);
+                }
+                if (order)
+                  strcat (buffer, order);
+                pEvent->SetDescription (buffer);
+              }
+
+              if (newEvent)
+                pSchedule->AddEvent (pEvent);
+
+              pEvent->FixEpgBugs ();
+              if (pEvent->RunningStatus () != runningStatus)
+                pSchedule->SetRunningStatus (pEvent, runningStatus, channel);
+              pSchedule->DropOutdated (StartTime, EndTime, Tid, cit.getVersionNumber ());
+              Modified = true;
+            }
+          }
+          if (Modified) {
+            pSchedule->Sort ();
+            Schedules->SetModified (pSchedule);
+          }
+          delete pct;
+        }
+      }
+      delete ExtendedEventDescriptors;
+      delete ShortEventDescriptor;
+      free (order);
+      free (rating);
+    }
+  }
+
+}
+
+// --- cPluginEEPG ------------------------------------------------------
+
+class cPluginEEPG:public cPlugin
+{
+private:
+  struct {
+    cFilterEEPG *filter;
+    cDevice *device;
+  } epg[MAXDVBDEVICES];
+
+  void CheckCreateFile(const char* Name, const char *fileContent[]);
+
+public:
+  cPluginEEPG (void);
+  virtual const char *Version (void) {
+    return VERSION;
+  }
+  virtual const char *Description (void) {
+    return tr (DESCRIPTION);
+  }
+  virtual bool Start (void);
+  virtual void Stop (void);
+  virtual cMenuSetupPage *SetupMenu (void);
+  virtual bool SetupParse (const char *Name, const char *Value);
+};
+
+cPluginEEPG::cPluginEEPG (void)
+{
+  memset (epg, 0, sizeof (epg));
+}
+
+void cPluginEEPG::CheckCreateFile(const char* Name, const char *fileContent[])
+{
+  FILE *File;
+  string FileName = string(cSetupEEPG::getInstance()->getConfDir()) + "/" + Name;
+  File = fopen(FileName.c_str(), "r");
+  if (File == NULL) {
+    LogE (0, prep("Error opening file '%s', %s"), FileName.c_str(), strerror (errno));
+    File = fopen (FileName.c_str(), "w");
+    if (File == NULL) {
+      LogE (0, prep("Error creating file '%s', %s"), FileName.c_str(), strerror (errno));
+    } else {
+      int i = 0;
+      while (fileContent[i] != NULL) {
+        fprintf (File, "%s\n", fileContent[i]);
+        i++;
+      }
+      LogI (0, prep("Success creating file '%s'"), FileName.c_str());
+      fclose (File);
+    }
+  } else {
+    fclose (File);
+  }
+}
+
+bool cPluginEEPG::Start (void)
+{
+#if APIVERSNUM < 10507
+  RegisterI18n (Phrases);
+#endif
+  for (int i = 0; i < MAXDVBDEVICES; i++) {
+    cDevice *dev = cDevice::GetDevice (i);
+    if (dev) {
+      epg[i].device = dev;
+      dev->AttachFilter (epg[i].filter = new cFilterEEPG);
+      isyslog ("Attached EEPG filter to device %d", i);
+    }
+  }
+  char *ConfDir = NULL;
+  // Initialize any background activities the plugin shall perform.
+  DIR *ConfigDir;
+  //if (ConfDir == NULL) {
+  Asprintf (&ConfDir, "%s/eepg", cPlugin::ConfigDirectory ());
+  //}
+  ConfigDir = opendir (ConfDir);
+  if (ConfigDir == NULL) {
+    esyslog ("EEPG: Error opening directory '%s', %s", ConfDir, strerror (errno));
+    if (mkdir (ConfDir, 0777) < 0) {
+      esyslog ("EEPG: Error creating directory '%s', %s", ConfDir, strerror (errno));
+    } else {
+      isyslog ("EEPG: Success creating directory '%s'", ConfDir);
+    }
+  }
+  cSetupEEPG::getInstance()->setConfDir(ConfDir);
+
+  CheckCreateFile(EEPG_FILE_EQUIV, FileEquivalences);
+  CheckCreateFile("sky_it.dict", SkyItDictionary);
+  CheckCreateFile("sky_uk.dict", SkyUkDictionary);
+  CheckCreateFile("sky_it.themes", SkyItThemes);
+  CheckCreateFile("sky_uk.themes", SkyUkThemes);
+  CheckCreateFile("freesat.t1", FreesatT1);
+  CheckCreateFile("freesat.t2", FreesatT2);
+  CheckCreateFile("sky_uk.themes", SkyUkThemes);
+
+  sky_tables[0] = NULL;
+  sky_tables[1] = NULL;
+  tables[0][0] = NULL;
+  //store all available sources, so when a channel is not found on current satellite, we can look for alternate sat positions.
+  //perhaps this can be done smarter through existing VDR function???
+  for (cChannel * Channel = Channels.First (); Channel; Channel = Channels.Next (Channel)) {
+    if (!Channel->GroupSep ()) {
+      bool found = false;
+      for (int i = 0; (i < NumberOfAvailableSources) && (!found); i++)
+        found = (Channel->Source () == AvailableSources[i]);
+      if (!found)
+        AvailableSources[NumberOfAvailableSources++] = Channel->Source ();
+    }
+  }
+  if (CheckLevel(3))
+    for (int i = 0; i < NumberOfAvailableSources; i++)
+      isyslog ("EEPG: Available sources:%s.", *cSource::ToString (AvailableSources[i]));
+
+#if APIVERSNUM > 10725
+  new cEEpgHandler();
+#endif
+  EquivHandler =  new cEquivHandler();
+
+  if (ConfDir) {
+    free (ConfDir);
+  }
+  closedir(ConfigDir);
+  return true;
+}
+
+void cPluginEEPG::Stop (void)
+{
+  for (int i = 0; i < MAXDVBDEVICES; i++) {
+    cDevice *dev = epg[i].device;
+    if (dev)
+      dev->Detach (epg[i].filter);
+    delete epg[i].filter;
+    epg[i].device = 0;
+    epg[i].filter = 0;
+  }
+
+  // Clean up after yourself!
+//  if (ConfDir) {
+//    free (ConfDir);
+//  }
+  if (sky_tables[0]) {
+    free(sky_tables[0]);
+  }
+  if (sky_tables[1]) {
+    free(sky_tables[1]);
+  }
+  if (EquivHandler) {
+      delete EquivHandler;
+  }
+
+}
+
+cMenuSetupPage *cPluginEEPG::SetupMenu (void)
+{
+  return new cMenuSetupPremiereEpg;
+}
+
+bool cPluginEEPG::SetupParse (const char *Name, const char *Value)
+{
+//  LogF(0, "!!!! Dime test LogF");
+//  LogF(0, "!!!! Dime test LogF %d", 2);
+//  LogI(0, "!!!! Dime test LogI");
+//  LogI(0, "!!!! Dime test LogI %d", 2);
+//  LogI(0, prep2("!!!! Dime test prep"));
+//  LogI(0, prep2("!!!! Dime test prep %d"), 2);
+//  LogD(0, "!!!! Dime test LogD");
+//  LogD(0, "!!!! Dime test LogD %d", 2);
+//  LogE(0, "!!!! Dime test LogE");
+//  LogE(0, "!!!! Dime test LogE %d", 2);
+
+
+  if (!strcasecmp (Name, "OptionPattern"))
+    SetupPE->OptPat = atoi (Value);
+  else if (!strcasecmp (Name, "OrderInfo"))
+    SetupPE->OrderInfo = atoi (Value);
+  else if (!strcasecmp (Name, "RatingInfo"))
+    SetupPE->RatingInfo = atoi (Value);
+  else if (!strcasecmp (Name, "FixEpg"))
+    SetupPE->FixEpg = atoi (Value);
+  else if (!strcasecmp (Name, "DisplayMessage"))
+    SetupPE->DisplayMessage = atoi (Value);
+#ifdef DEBUG
+  else if (!strcasecmp (Name, "LogLevel"))
+    SetupPE->LogLevel = atoi (Value);
+  else if (!strcasecmp (Name, "ProcessEIT"))
+    SetupPE->ProcessEIT = atoi (Value);
+#endif
+  else
+    return false;
+  return true;
+}
+
+VDRPLUGINCREATOR (cPluginEEPG); // Don't touch this!
diff --git a/eepg.equiv.IT b/eepg.equiv.IT
new file mode 100644
index 0000000..6c21282
--- /dev/null
+++ b/eepg.equiv.IT
@@ -0,0 +1,17 @@
+#
+# Simply add a list of the channels in this file with the following format:
+#
+# <OriginalChannelId> <OtherChannelId> <ChannelName>
+#
+
+S13.0E-64511-6700-11517 S13.0E-318-13000-14601 BBC Prime
+S13.0E-318-5200-3401 S19.2E-1-1024-9015 Rai Uno
+S13.0E-318-5200-3401 S13.0E-318-12400-8511 Rai Uno
+S13.0E-318-5200-3402 S13.0E-318-12400-8512 Rai Due
+S13.0E-318-5200-3403 S13.0E-318-12400-8513 Rai Tre
+S13.0E-272-6000-3 T-272-905-143 Rete 4
+S13.0E-272-6000-2 T-272-905-141 Canale 5
+S13.0E-272-6000-1 T-272-905-142 Italia 1
+S13.0E-64511-8600-11733 T-29-514-1 La 7
+S13.0E-64511-6700-11504 S13.0E-318-200-13831 Eurosport
+
diff --git a/eepg.h b/eepg.h
new file mode 100644
index 0000000..7e1cc74
--- /dev/null
+++ b/eepg.h
@@ -0,0 +1,7182 @@
+//#define DEBUG false
+//#define DEBUG_STARTTIME false
+
+#define MAX_THEMES 2046 //this should always be >=256, or Nagra will go wrong!!
+#define MAX_CHANNELS 2048
+#define MAX_TITLES 262144
+
+//#define MAX_EQUIVALENCES 8 //the number of equivalences one channel can have
+
+//Formats (need to be consecutively numbered):
+//#define PREMIERE	0
+//#define FREEVIEW 	1
+//#define MHW1 		2
+//#define MHW2 		3
+//#define SKY_IT 		4
+//#define SKY_UK 		5
+//#define NAGRA 		6
+//#define HIGHEST_FORMAT 	6
+
+
+#define NAGRA_TABLE_ID  	0x55 //the lower the table Id, the more "current" it is; table_id 0x00 never gets overwritten, now/next are at 0x4e or 0x4f!
+#define DEFAULT_TABLE_ID 	0x30
+
+const char *FormatName[]= {"MediaHighWay 1","MediaHighWay 2","Sky Italy","Sky UK","NagraGuide","Premiere","FreeView","Dish/Bev","EIT"};
+
+struct sNode
+{
+  char *Value;
+  struct sNode *P0;
+  struct sNode *P1;
+};
+
+typedef struct sNode sNodeH;
+
+typedef struct
+{
+  unsigned short int ChannelId;
+  unsigned short int SkyNumber;
+  //unsigned short int NumberOfEquivalences;//original channel sets this value to 1, every equivalent channel adds 1
+  unsigned int Src;//[MAX_EQUIVALENCES];
+  unsigned short int Nid;//[MAX_EQUIVALENCES];
+  unsigned short int Tid;//[MAX_EQUIVALENCES];
+  unsigned short int Sid;//[MAX_EQUIVALENCES];
+  unsigned char Name[64];
+} sChannel;
+
+typedef struct {
+  unsigned short int ChannelId;
+  unsigned short int ThemeId;
+  unsigned short int MjdTime;
+  unsigned int EventId;//short is not sufficient for Nagra
+  unsigned int StartTime;
+  unsigned int Duration;
+  unsigned char SummaryAvailable;
+  unsigned char * Text;
+  unsigned char Unknown1;//FIXME
+  unsigned char Unknown2;//FIXME
+  unsigned char Unknown3;//FIXME
+  unsigned char Rating;
+  unsigned short int TableId;
+} Title_t;
+
+typedef struct {
+  unsigned short int ChannelId;
+  unsigned int StartTime;
+  unsigned short int MjdTime;
+} Replays_t;
+typedef struct {
+  Replays_t Replays[11]; //at the moment 10 is allowed, check why
+  unsigned int EventId;//short is not sufficient for Nagra
+  unsigned short int NumReplays;
+  unsigned char * Text;
+} Summary_t;
+
+
+// -- InheritEnum.h
+template <typename EnumT, typename BaseEnumT>
+class InheritEnum
+{
+public:
+  InheritEnum() {}
+  InheritEnum(EnumT e)
+    : enum_(e)
+  {}
+
+  InheritEnum(BaseEnumT e)
+    : baseEnum_(e)
+  {}
+
+  explicit InheritEnum( int val )
+    : enum_(static_cast<EnumT>(val))
+  {}
+
+  operator EnumT() const { return enum_; }
+private:
+  // Note - the value is declared as a union mainly for as a debugging aid. If
+  // the union is undesired and you have other methods of debugging, change it
+  // to either of EnumT and do a cast for the constructor that accepts BaseEnumT.
+  union
+  {
+    EnumT enum_;
+    BaseEnumT baseEnum_;
+  };
+};
+
+static const char *FileEquivalences[] = {
+  "#",
+  "# Simply add a list of the channels in this file with the following format:",
+  "#",
+  "# <OriginalChannelId> <OtherChannelId> <ChannelName>",
+  "#",
+  "",
+  "S13.0E-64511-6700-11517 S13.0E-318-13000-14601 BBC Prime",
+  "S13.0E-318-5200-3401 S19.2E-1-1024-9015 Rai Uno",
+  "S13.0E-318-5200-3401 S13.0E-318-12400-8511 Rai Uno",
+  "S13.0E-318-5200-3402 S13.0E-318-12400-8512 Rai Due",
+  "S13.0E-318-5200-3403 S13.0E-318-12400-8513 Rai Tre",
+  "S13.0E-272-6000-3 T-272-905-143 Rete 4",
+  "S13.0E-272-6000-2 T-272-905-141 Canale 5",
+  "S13.0E-272-6000-1 T-272-905-142 Italia 1",
+  "S13.0E-64511-8600-11733 T-29-514-1 La 7",
+  "S13.0E-64511-6700-11504 S13.0E-318-200-13831 Eurosport",
+  "",
+  NULL
+};
+
+static const char *SkyItDictionary[] = {
+  " =00001011010110001111010101010",
+  " =00001011010110001111010101011",
+  " =00001011010110001111010101100",
+  " =00001011010110001111010101101",
+  " =00001011010110001111010101110",
+  " =00001011010110001111010101111",
+  " =00001011010110001111010110000",
+  " =00001011010110001111010110001",
+  " =00001011010110001111010110010",
+  " =00001011010110001111010110011",
+  " =00001011010110001111010110100",
+  " =00001011010110001111010110101",
+  " =00001011010110001111010110110",
+  " =1001110",
+  " =00001011010110001111010110111",
+  " =00001011010110001111010111000",
+  " =00001011010110001111010111001",
+  " =00001011010110001111010111010",
+  " =00001011010110001111010111011",
+  " =00001011010110001111010111100",
+  " =00001011010110001111010111101",
+  " =00001011010110001111010111110",
+  " =00001011010110001111010111111",
+  " =00001011010110001111011000000",
+  " =00001011010110001111011000001",
+  " =00001011010110001111011000010",
+  " =00001011010110001111011000011",
+  " =00001011010110001111011000100",
+  " =00001011010110001111011000101",
+  " =00001011010110001111011000110",
+  " =00001011010110001111011000111",
+  " =00001011010110001111011001000",
+  " =01",
+  "!=1110000011101",
+  "\"=11100010000100011",
+  "#=00001011010110001111011001001",
+  "$=00001011010110001111011001010",
+  "%=00001011010110001111011001011",
+  "&=11100010000101",
+  "'=0000100",
+  "(=0000101101010",
+  ")=110100111111",
+  "*=00001011010110001111011001100",
+  "+=000010110101100011111",
+  ",=110000",
+  "-=10110011",
+  ".=100110",
+  "/=111000100001001",
+  "0=10010011",
+  "1=100100000",
+  "2=1111011001",
+  "3=1110001110",
+  "4=11000100101",
+  "5=111101110100",
+  "6=101100101111",
+  "7=110100011110",
+  "8=11010001110",
+  "9=1111010111",
+  ":=100100011",
+  ";=10000111101",
+  "<=00001011010110001111011001101",
+  "==00001011010110001111011001110",
+  ">=00001011010110001111011001111",
+  "?=1100110110110",
+  "@=1110001000010000",
+  "A=00001010",
+  "B=111101001",
+  "C=10010100",
+  "D=100001010",
+  "E=111000000",
+  "F=1110001100",
+  "G=100101100",
+  "H=1000011111",
+  "I=1111011111",
+  "J=1100010110",
+  "K=11110100011",
+  "L=001111101",
+  "M=100001101",
+  "N=100001011",
+  "O=1100101011",
+  "P=110100000",
+  "Q=00001011000",
+  "R=110010100",
+  "S=10110100",
+  "T=110101100",
+  "U=110100010011",
+  "V=1001000011",
+  "W=1101000110",
+  "X=1110001011001",
+  "Y=1100011110011",
+  "Z=1100010100110",
+  "[=00001011010110001111011010000",
+  "\\=00001011010110001111011010001",
+  "]=00001011010110001111011010010",
+  "^=0000101101011000100",
+  "_=00001011010110001111011010011",
+  "`=00001011010111",
+  "a=11111",
+  "b=11100001",
+  "c=111001",
+  "d=1011000",
+  "e=1010",
+  "f=0011011",
+  "g=000011",
+  "h=10110110",
+  "i=0001",
+  "j=110100010000",
+  "k=110001100",
+  "l=1111001",
+  "m=100010",
+  "n=10111",
+  "o=0010",
+  "p=100011",
+  "q=1110001001",
+  "r=11011",
+  "s=00000",
+  "t=11101",
+  "u=001110",
+  "v=1100111",
+  "w=001100110",
+  "x=11100011110",
+  "y=111101101",
+  "z=0011010",
+  "{=00001011010110001111011010100",
+  "|=00001011010110001111011010101",
+  "}=00001011010110001111011010110",
+  "~=00001011010110001111011010111",
+  " =00001011010110001111011011000",
+  " =000010110101100000",
+  " =00001011010110001111011011001",
+  " =00001011010110001111011011010",
+  " =00001011010110001111011011011",
+  " =00001011010110001111011011100",
+  " =00001011010110001111011011101",
+  " =00001011010110001111011011110",
+  " =00001011010110001111011011111",
+  " =11100010000100010",
+  " =000010110101100001",
+  " =00001011010110001111011100000",
+  " =00001011010110001111011100001",
+  " =00001011010110001111011100010",
+  " =00001011010110001111011100011",
+  " =00001011010110001111011100100",
+  " =00001011010110001111011100101",
+  " =00001011010110001111011100110",
+  " =00001011010110001111011100111",
+  " =00001011010110001110",
+  " =00001011010110001111011101000",
+  " =00001011010110001111011101001",
+  " =00001011010110001111011101010",
+  " =00001011010110001111011101011",
+  " =0000101101011000101",
+  " =00001011010110001111011101100",
+  " =00001011010110001111011101101",
+  " =00001011010110001111011101110",
+  " =00001011010110001111011101111",
+  " =00001011010110001111011110000",
+  " =00001011010110001111011110001",
+  " =00001011010110001111011110010",
+  " =00001011010110001111011110011",
+  " =00001011010110001111011110100",
+  "¡=00001011010110001111011110101",
+  "¢=00001011010110001111011110110",
+  "£=00001011010110001111011110111",
+  "¤=00001011010110001111011111000",
+  "¥=00001011010110001111011111001",
+  "¦=00001011010110001111011111010",
+  "§=00001011010110001111011111011",
+  "¨=00001011010110001111011111100",
+  "©=00001011010110001111011111101",
+  "ª=00001011010110001111011111110",
+  "«=00001011010110001111011111111",
+  "¬=0000101101011000111100000000",
+  "­=0000101101011000111100000001",
+  "®=0000101101011000111100000010",
+  "¯=0000101101011000111100000011",
+  "°=0000101101011000111100000100",
+  "±=0000101101011000111100000101",
+  "²=0000101101011000111100000110",
+  "³=0000101101011000111100000111",
+  "´=0000101101011000111100001000",
+  "µ=0000101101011000111100001001",
+  "¶=0000101101011000111100001010",
+  "·=0000101101011001",
+  "¸=0000101101011000111100001011",
+  "¹=0000101101011000111100001100",
+  "º=0000101101011000111100001101",
+  "»=0000101101011000111100001110",
+  "¼=0000101101011000111100001111",
+  "½=0000101101011000111100010000",
+  "¾=0000101101011000111100010001",
+  "¿=0000101101011000111100010010",
+  "À=0000101101011000111100010011",
+  "Á=0000101101011000111100010100",
+  "Â=0000101101011000111100010101",
+  "Ã=0000101101011000111100010110",
+  "Ä=0000101101011000111100010111",
+  "Å=0000101101011000111100011000",
+  "Æ=000010110101101",
+  "Ç=0000101101011000111100011001",
+  "È=0000101101011000111100011010",
+  "É=0000101101011000111100011011",
+  "Ê=0000101101011000111100011100",
+  "Ë=0000101101011000111100011101",
+  "Ì=0000101101011000111100011110",
+  "Í=0000101101011000111100011111",
+  "Î=0000101101011000111100100000",
+  "Ï=0000101101011000111100100001",
+  "Ð=0000101101011000111100100010",
+  "Ñ=0000101101011000111100100011",
+  "Ò=0000101101011000111100100100",
+  "Ó=0000101101011000111100100101",
+  "Ô=0000101101011000111100100110",
+  "Õ=0000101101011000111100100111",
+  "Ö=0000101101011000111100101000",
+  "×=0000101101011000111100101001",
+  "Ø=0000101101011000111100101010",
+  "Ù=0000101101011000111100101011",
+  "Ú=0000101101011000111100101100",
+  "Û=0000101101011000111100101101",
+  "Ü=0000101101011000111100101110",
+  "Ý=0000101101011000111100101111",
+  "Þ=0000101101011000111100110000",
+  "ß=0000101101011000111100110001",
+  "à=0000101101011000110",
+  "á=0000101101011000111100110010",
+  "â=0000101101011000111100110011",
+  "ã=0000101101011000111100110100",
+  "ä=0000101101011000111100110101",
+  "å=0000101101011000111100110110",
+  "æ=0000101101011000111100110111",
+  "ç=0000101101011000111100111000",
+  "è=0000101101011000111100111001",
+  "é=0000101101011000111100111010",
+  "ê=0000101101011000111100111011",
+  "ë=0000101101011000111100111100",
+  "ì=0000101101011000111100111101",
+  "í=0000101101011000111100111110",
+  "î=0000101101011000111100111111",
+  "ï=0000101101011000111101000000",
+  "ð=0000101101011000111101000001",
+  "ñ=0000101101011000111101000010",
+  "ò=0000101101011000111101000011",
+  "ó=0000101101011000111101000100",
+  "ô=0000101101011000111101000101",
+  "õ=0000101101011000111101000110",
+  "ö=0000101101011000111101000111",
+  "÷=0000101101011000111101001000",
+  "ø=0000101101011000111101001001",
+  "ù=0000101101011000111101001010",
+  "ú=0000101101011000111101001011",
+  "û=0000101101011000111101001100",
+  "ü=0000101101011000111101001101",
+  "ý=0000101101011000111101001110",
+  "þ=0000101101011000111101001111",
+  "ÿ=0000101101011000111101010000",
+  "(dur=100001111000",
+  "2001=001111100",
+  "2002=111000110101",
+  "Adulti=100001111001",
+  "Alle=1100110111",
+  "American=10110101100",
+  "Argentina=110010101011",
+  "Attualita'=110001000001",
+  "Bateman=10010111111",
+  "Bechis=1100010111011",
+  "Campionato=1101001111000",
+  "Carlos=1101000011101",
+  "Cartoon=11110111011",
+  "Club=10000110010",
+  "Commedia=100001100001",
+  "Con=10110101101",
+  "D'Alo'=1100100011111",
+  "Da=1001010111",
+  "Dal=1111010100011",
+  "Dalle=10010111110",
+  "Drammatico=111101111001",
+  "Durante=1101000111110",
+  "Echeverria=1100011100110",
+  "Emmanuelle=1100011100111",
+  "Enzo=1101000100010",
+  "Fares=00001011011",
+  "Figli=1100100011000",
+  "Film=1101011010",
+  "Fine=100001001100",
+  "Fiumi=00001011100",
+  "Francia=10000110001",
+  "Giallo=110001001000",
+  "Giovanni=1100011101000",
+  "Harron=10011110000",
+  "ITV=1101000100100",
+  "Il=0011001110",
+  "In=1001011011",
+  "Informazione=11110100001",
+  "Intrattenimento=1000010000",
+  "Italia=11100010001",
+  "Javier=1100011101001",
+  "Jean=10010101011",
+  "John=1111011100101",
+  "Kassovitz=00110000101",
+  "L'appassionante=00001011101",
+  "La=1001010110",
+  "Le=11000100111",
+  "Ma=1101001110",
+  "Magazine=100001110010",
+  "Mammuccari=1100011101010",
+  "Manhattan=10110010010",
+  "Marco=1110001011110",
+  "Mary=10011110110",
+  "Mathieu=00110000110",
+  "Michael=1101001111011",
+  "Momo=110010001011",
+  "Nadia=00001011110",
+  "News=110100111110",
+  "Notiziario=101100101110",
+  "Orario=1001000100",
+  "Patrick=10110010110",
+  "Paul=000010110011",
+  "Per=11000100110",
+  "Peter=1100101010101",
+  "Programmazione=1110001101001",
+  "Psycho=10011110111",
+  "Regia=110010000",
+  "Reno=00110000111",
+  "Rosa=1100011110101",
+  "Rubrica=1111011100100",
+  "Sandrelli=1100100010001",
+  "Seigner=1100011101011",
+  "Servizi=001100000110",
+  "Snow=100100001000",
+  "Sorvino=1100011110110",
+  "Stefania=1101011011010",
+  "Stream=111101000100",
+  "Street=10110101111",
+  "Streghe=1100011101100",
+  "TRAMA:=1100010111010",
+  "Teo=110001110010",
+  "USA=1101000101",
+  "Un=11110111101",
+  "Una=101100100010",
+  "Veronesi=1100011101101",
+  "Vincent=00110001001",
+  "Wall=11000100001",
+  "World=001100010110",
+  "XXX=10000110011",
+  "ad=1111010110",
+  "affidare=00110000100",
+  "ai=1001011110",
+  "al=0011110",
+  "alla=11010110111",
+  "alle=111101110101",
+  "amici=111000101110",
+  "ammazzare=10011110001",
+  "and=1111010101",
+  "anfiteatro=1100100011001",
+  "anni=10010101010",
+  "as=110011010",
+  "attraverso=1101011011001",
+  "aver=000010110100",
+  "bambina=1101000100011",
+  "banda=1110001011000",
+  "bello=10110101000",
+  "brani=1100100010010",
+  "broker=10011110010",
+  "business=000010110010",
+  "casa=101100100011",
+  "casi=10000111010",
+  "cassel=00001011111",
+  "cerca=11100010100",
+  "che=10010010",
+  "chilometri=00110001111",
+  "citta'=110001000101",
+  "come=110001011100",
+  "compagnia=1100110110001",
+  "con=11010010",
+  "conquista=1101000111111",
+  "contro=110001000100",
+  "crede=1110001111110",
+  "cui=001100111110",
+  "cultura=100001110001",
+  "curiosita'=001100010111",
+  "da=00110010",
+  "dai=1101000100101",
+  "dal=11110110000",
+  "dalla=100101101001",
+  "decidG266  :  dedicato=0000101101011000111101010001",
+  "degli=110001000000",
+  "dei=0011000110",
+  "del=111100010",
+  "della=1011001010",
+  "delle=11000111000",
+  "destra=1100101010001",
+  "deve=1111010001011",
+  "di=100000",
+  "diabolici=1100100011010",
+  "dice=1100110110000",
+  "diretta=100100001011",
+  "distanza=00110000000",
+  "divide=10110010011",
+  "divisi=1100011101110",
+  "dolce=1101001111001",
+  "domani=1111010100010",
+  "due=1100011111",
+  "e'=110001101",
+  "ed=101101111",
+  "essere=1110001000000",
+  "esseri=1110001111101",
+  "eventiG=0000101101011000111101010010",
+  "fatti=001100111111",
+  "feste=10110101001",
+  "film=10000100011",
+  "gemelli=1110001000011",
+  "giorno=11110100000",
+  "giovane=11100000110",
+  "giovani=1111011110001",
+  "gli=100101110",
+  "grande=1110001011111",
+  "grandi=1111010001010",
+  "grigi'=1100100011011",
+  "ha=1100010101",
+  "il=11001011",
+  "imbattere=1100100011100",
+  "in=1101010",
+  "incinta=1100101010000",
+  "informazione=110001001001",
+  "inizio=1001010100",
+  "internazionale=100001110111",
+  "interviste=100100001001",
+  "la=11001100",
+  "lavoro=11010000110",
+  "le=11010111",
+  "levatrice=1100011101111",
+  "libro=1100011110100",
+  "lo=111100011",
+  "loro=11000101000",
+  "ma=10011111",
+  "maggiori=100001110110",
+  "malcapitati=10110010000",
+  "maschietto=1100011110000",
+  "mondo=11100010101",
+  "musica=111000001111",
+  "nato=111101110011",
+  "nel=11110111000",
+  "nella=1111010100000",
+  "nello=10000100100",
+  "news=10010110101",
+  "non=00110011110",
+  "nord=1100100011101",
+  "nuovi=001100000111",
+  "of=1011010101",
+  "ogni=100001110011",
+  "ore=1101000010",
+  "parte=1101011011011",
+  "per=00111111",
+  "piccola=1101001111010",
+  "piu'=1001111010",
+  "poliziotti=00110001110",
+  "porpora=00110000001",
+  "prima=1110001111100",
+  "produttore=1100011110111",
+  "programmazione=1110001101000",
+  "proprio=1101011011000",
+  "prossimo=1001000101",
+  "quattro=1111011000110",
+  "regime=1100011110001",
+  "ricco=10110101110",
+  "ricordi=1100101010100",
+  "rovine=1110001000001",
+  "salvare=1110000011100",
+  "scrittore=1100110110111",
+  "scrive=1101000011110",
+  "serie=1111011000111",
+  "servizi=100001110000",
+  "settimanale=1100010100111",
+  "si=11110000",
+  "singolari=00110001000",
+  "solo=110010001010",
+  "sono=11000100011",
+  "stesso=10000100010",
+  "storia=11100011011",
+  "streghe=1100100010000",
+  "su=1110000010",
+  "sua=10000100101",
+  "successo=100101101000",
+  "sui=110011011001",
+  "sulle=100100001010",
+  "suo=10000100111",
+  "suoi=1101000011100",
+  "tale=110010101001",
+  "tempo=111101100010",
+  "the=11110101001",
+  "timida=1100100011110",
+  "torturare=10011110011",
+  "tra=110100110",
+  "trasformarlo=1100011110010",
+  "trecento=00110000010",
+  "trovato=1101000011111",
+  "tutto=110011011010",
+  "ultimi=1100100010011",
+  "un=11001001",
+  "una=101101110",
+  "uno=111000101101",
+  "uomini=1111011110000",
+  "vedono=00110001010",
+  "vengono=100001001101",
+  "verso=100001100000",
+  "viaggio=110001010010",
+  "viene=1111010100001",
+  "vita=11000101111",
+  "vuole=1110001111111",
+  NULL
+};
+
+static const char *SkyUkDictionary[] = {
+  " =101010111000110000101001100",
+  " =101010111000110000101001101",
+  " =101010111000110000101001110",
+  " =101010111000110000101001111",
+  " =101010111000110000101010000",
+  " =101010111000110000101010001",
+  " =101010111000110000101010010",
+  " =101010111000110000101010011",
+  " =101010111000110000101010100",
+  " =0001000",
+  " =1110111",
+  " =101010111000110000101010101",
+  " =101010111000110000101010110",
+  " =101010111000110000101010111",
+  " =101010111000110000101011000",
+  " =101010111000110000101011001",
+  " =101010111000110000101011010",
+  " =101010111000110000101011011",
+  " =101010111000110000101011100",
+  " =101010111000110000101011101",
+  " =101010111000110000101011110",
+  " =101010111000110000101011111",
+  " =101010111000110000101100000",
+  " =101010111000110000101100001",
+  " =101010111000110000101100010",
+  " =101010111000110000101100011",
+  " =101010111000110000101100100",
+  " =101010111000110000101100101",
+  " =101010111000110000101100110",
+  " =101010111000110000101100111",
+  " =101010111000110000101101000",
+  " =101010111000110000101101001",
+  " =110",
+  "!=01000011000",
+  "\"=101010111000110000101101010",
+  "#=101010111000110000101101011",
+  "$=1010101110001101",
+  "%=101010111000110000101101100",
+  "&=10000011101",
+  "'=10000010",
+  "(=11101000101",
+  ")=1010101100",
+  "*=100010101110",
+  "+=101010111000110000101101101",
+  ",=1011000",
+  "-=10001011",
+  ".=1110110",
+  "/=00010100011110",
+  "0=111010010",
+  "1=101100111",
+  "2=1000101000",
+  "3=1000001111",
+  "4=0001010000",
+  "5=1110101000",
+  "6=1000101001",
+  "7=1000100010",
+  "8=10001010110",
+  "9=0100001101",
+  ":=11101000110",
+  ";=00010100010",
+  "<=1110100011111",
+  "==101010111000110000101101110",
+  ">=1110101001100",
+  "?=111010100111",
+  "@=101010111000110001",
+  "A=11100010",
+  "B=01000000",
+  "C=01000010",
+  "D=111000111",
+  "E=1110100000",
+  "F=101010100",
+  "G=100010000",
+  "H=101010101",
+  "I=1110100001",
+  "J=000101001",
+  "K=1110100111",
+  "L=100000110",
+  "M=10001001",
+  "N=111010111",
+  "O=010000010",
+  "P=00010101",
+  "Q=1000101010111",
+  "R=111010110",
+  "S=0001001",
+  "T=0001011",
+  "U=10101011101",
+  "V=11101010101",
+  "W=10110010",
+  "X=1110001101101111",
+  "Y=10101011110",
+  "Z=1110101010000",
+  "[=10101011100011001",
+  "\\=101010111000110000101101111",
+  "]=11100011011011100",
+  "^=101010111000110000101110000",
+  "_=101010111000110000101110001",
+  "`=11101010010",
+  "a=1001",
+  "b=1110000",
+  "c=111001",
+  "d=01001",
+  "e=1111",
+  "f=100001",
+  "g=100011",
+  "h=10111",
+  "i=0101",
+  "j=11100011010",
+  "k=1000000",
+  "l=10100",
+  "m=101011",
+  "n=0111",
+  "o=0011",
+  "p=000111",
+  "q=10101011011",
+  "r=0010",
+  "s=0000",
+  "t=0110",
+  "u=101101",
+  "v=1010100",
+  "w=000110",
+  "x=1110101011",
+  "y=010001",
+  "z=1011001100",
+  "{=101010111000110000101110010",
+  "|=101010111000110000101110011",
+  "}=101010111000110000101110100",
+  "~=101010111000110000101110101",
+  " =101010111000110000101110110",
+  " =101010111000110000101110111",
+  " =101010111000110000101111000",
+  " =101010111000110000101111001",
+  " =101010111000110000101111010",
+  " =101010111000110000101111011",
+  " =101010111000110000101111100",
+  " =101010111000110000101111101",
+  " =101010111000110000101111110",
+  " =101010111000110000101111111",
+  " =101010111000110000110000000",
+  " =101010111000110000110000001",
+  " =101010111000110000110000010",
+  " =101010111000110000110000011",
+  " =101010111000110000110000100",
+  " =101010111000110000110000101",
+  " =101010111000110000110000110",
+  " =101010111000110000110000111",
+  " =101010111000110000110001000",
+  " =101010111000110000110001001",
+  " =101010111000110000110001010",
+  " =101010111000110000110001011",
+  " =101010111000110000110001100",
+  " =101010111000110000110001101",
+  " =101010111000110000110001110",
+  " =101010111000110000110001111",
+  " =101010111000110000110010000",
+  " =101010111000110000110010001",
+  " =101010111000110000110010010",
+  " =11100011011011101",
+  " =101010111000110000110010011",
+  " =101010111000110000110010100",
+  " =101010111000110000110010101",
+  " =101010111000110000110010110",
+  "¡=101010111000110000110010111",
+  "¢=101010111000110000110011000",
+  "£=101010111000110000110011001",
+  "¤=101010111000110000110011010",
+  "¥=101010111000110000110011011",
+  "¦=101010111000110000110011100",
+  "§=101010111000110000110011101",
+  "¨=101010111000110000110011110",
+  "©=101010111000110000110011111",
+  "ª=101010111000110000110100000",
+  "«=101010111000110000110100001",
+  "¬=101010111000110000110100010",
+  "­=101010111000110000110100011",
+  "®=101010111000110000110100100",
+  "¯=101010111000110000110100101",
+  "°=101010111000110000110100110",
+  "±=101010111000110000110100111",
+  "²=101010111000110000110101000",
+  "³=101010111000110000110101001",
+  "´=101010111000110000110101010",
+  "µ=101010111000110000110101011",
+  "¶=101010111000110000110101100",
+  "·=101010111000110000110101101",
+  "¸=101010111000110000110101110",
+  "¹=101010111000110000110101111",
+  "º=101010111000110000110110000",
+  "»=101010111000110000110110001",
+  "¼=101010111000110000110110010",
+  "½=101010111000110000110110011",
+  "¾=101010111000110000110110100",
+  "¿=101010111000110000110110101",
+  "À=101010111000110000110110110",
+  "Á=101010111000110000110110111",
+  "Â=101010111000110000110111000",
+  "Ã=101010111000110000110111001",
+  "Ä=101010111000110000110111010",
+  "Å=101010111000110000110111011",
+  "Æ=101010111000110000110111100",
+  "Ç=101010111000110000110111101",
+  "È=101010111000110000110111110",
+  "É=101010111000110000110111111",
+  "Ê=101010111000110000111000000",
+  "Ë=101010111000110000111000001",
+  "Ì=101010111000110000111000010",
+  "Í=101010111000110000111000011",
+  "Î=101010111000110000111000100",
+  "Ï=101010111000110000111000101",
+  "Ð=101010111000110000111000110",
+  "Ñ=101010111000110000111000111",
+  "Ò=101010111000110000111001000",
+  "Ó=101010111000110000111001001",
+  "Ô=101010111000110000111001010",
+  "Õ=101010111000110000111001011",
+  "Ö=101010111000110000111001100",
+  "×=101010111000110000111001101",
+  "Ø=101010111000110000111001110",
+  "Ù=101010111000110000111001111",
+  "Ú=101010111000110000111010000",
+  "Û=101010111000110000111010001",
+  "Ü=101010111000110000111010010",
+  "Ý=101010111000110000111010011",
+  "Þ=101010111000110000111010100",
+  "ß=101010111000110000111010101",
+  "à=101010111000110000111010110",
+  "á=101010111000110000111010111",
+  "â=101010111000110000111011000",
+  "ã=101010111000110000111011001",
+  "ä=101010111000110000111011010",
+  "å=101010111000110000111011011",
+  "æ=101010111000110000111011100",
+  "ç=101010111000110000111011101",
+  "è=101010111000110000111011110",
+  "é=101010111000110000111011111",
+  "ê=101010111000110000111100000",
+  "ë=101010111000110000111100001",
+  "ì=101010111000110000111100010",
+  "í=101010111000110000111100011",
+  "î=101010111000110000111100100",
+  "ï=101010111000110000111100101",
+  "ð=101010111000110000111100110",
+  "ñ=101010111000110000111100111",
+  "ò=101010111000110000111101000",
+  "ó=101010111000110000111101001",
+  "ô=101010111000110000111101010",
+  "õ=101010111000110000111101011",
+  "ö=101010111000110000111101100",
+  "÷=101010111000110000111101101",
+  "ø=101010111000110000111101110",
+  "ù=101010111000110000111101111",
+  "ú=101010111000110000111110000",
+  "û=101010111000110000111110001",
+  "ü=101010111000110000111110010",
+  "ý=101010111000110000111110011",
+  "þ=101010111000110000111110100",
+  "ÿ=101010111000110000111110101",
+  "(Including =10101011111110",
+  "(New Series)=11101000100010",
+  "(Part =1110100011101",
+  "(Repeat)=1110100110",
+  "(Stereo)=010000111",
+  "(Stereo) (Teletext)=010000011",
+  "(Teletext)=1110001100",
+  "(Widescreen)=100000111001110",
+  "Action=101010111000111",
+  "Adventures=10110011011111",
+  "America=0100001100100",
+  "Animated=111010100110111",
+  "Australia=0100001100101",
+  "Away=11101010100010",
+  "BBC=10101011111111",
+  "Baby=11100011011000",
+  "Best=11101010100011",
+  "Big=10110011011000",
+  "Bill=1000101011111",
+  "Black=1000101010000",
+  "Blue=1011001101110",
+  "Breakfast=000101000110",
+  "Britain=1010101111100",
+  "British=1110100011100",
+  "Business=0100001100110",
+  "Call=1010101111101",
+  "Cartoon=10101011100000",
+  "Channel=10101011100001",
+  "Children=11101010100111",
+  "Clock=11100011011001",
+  "Comedy=11101000100011",
+  "Cook=111010101001010",
+  "Country=111010100110110",
+  "Directed by =101010110100",
+  "Drama=0100001100111",
+  "East=1000101010001",
+  "Education=100000111001111",
+  "English=00010100011111",
+  "Europe=0001010001110",
+  "Extra=10110011011001",
+  "Final=10101011100010",
+  "Financial=111000110110100",
+  "For=111000110111",
+  "French=11101000111101",
+  "From=1000101010010",
+  "George=1010101111110",
+  "Get=1000100011010",
+  "Girls=10001000110110",
+  "Golden=10001000110111",
+  "Golf=111010101001011",
+  "Good=1010101101010",
+  "Great=11101000100100",
+  "Hampshire=111010101001100",
+  "Headlines=1000101010011",
+  "Hear=11101010011010",
+  "Hill=1000001110000",
+  "Hollywood=111000110110101",
+  "Home=1000101010100",
+  "Hour=11101000100101",
+  "House=1000001110010",
+  "How=1010101101011",
+  "ITN=11101010100100",
+  "Important=111010101001101",
+  "Including=1000101011110",
+  "International=11101000100110",
+  "John=10001000111",
+  "Last=11101000100111",
+  "Late=10000011100110",
+  "Learn=10001010101100",
+  "Little=10001010101101",
+  "Live=1110100010000",
+  "London=11101000111100",
+  "Look=10110011011110",
+  "Lunch=111000110110110",
+  "Man=1000101010101",
+  "Mark=1000001110001",
+  "Meridian=101010111001",
+  "Michael=1011001101101",
+  "Minutes=101010111000110000111110110",
+  "More=101010111000110000111110111",
+  "Morning=101010111000110000111111000",
+  "Murder=101010111000110000111111001",
+  "Nation=101010111000110000111111010",
+  "Neighbours=101010111000110000111111011",
+  "New=101010111000110000111111100",
+  "News & Weather=101010111000110000111111101",
+  "News And Weather=101010111000110000111111110",
+  "Paul=101010111000110000111111111",
+  "Plus=10101011100011000000000000",
+  "Prayer=10101011100011000000000001",
+  "Present=10101011100011000000000010",
+  "Presented by=10101011100011000000000011",
+  "Quiz=10101011100011000000000100",
+  "Regional=10101011100011000000000101",
+  "Represent=10101011100011000000000110",
+  "Resource=10101011100011000000000111",
+  "Review=10101011100011000000001000",
+  "Richard=10101011100011000000001001",
+  "School=10101011100011000000001010",
+  "Series=10101011100011000000001011",
+  "Service=10101011100011000000001100",
+  "Show=10101011100011000000001101",
+  "Smith=10101011100011000000001110",
+  "South=10101011100011000000001111",
+  "Sport=10101011100011000000010000",
+  "Star=10101011100011000000010001",
+  "Street=10101011100011000000010010",
+  "TV=10101011100011000000010011",
+  "Teaching=10101011100011000000010100",
+  "The=10101011100011000000010101",
+  "Today=10101011100011000000010110",
+  "Tonight=10101011100011000000010111",
+  "Weather=10101011100011000000011000",
+  "Western=10101011100011000000011001",
+  "Westminster=10101011100011000000011010",
+  "William=10101011100011000000011011",
+  "With=10101011100011000000011100",
+  "World=10101011100011000000011101",
+  "about=10101011100011000000011110",
+  "action-packed=10101011100011000000011111",
+  "adventure=10101011100011000000100000",
+  "afternoon=10101011100011000000100001",
+  "alert=10101011100011000000100010",
+  "all-star cast=10101011100011000000100011",
+  "and=10101011100011000000100100",
+  "anywhere=10101011100011000000100101",
+  "audience=10101011100011000000100110",
+  "based=10101011100011000000100111",
+  "book=10101011100011000000101000",
+  "business=10101011100011000000101001",
+  "but=10101011100011000000101010",
+  "celebrity=10101011100011000000101011",
+  "chance=10101011100011000000101100",
+  "chat=10101011100011000000101101",
+  "child=10101011100011000000101110",
+  "classic=10101011100011000000101111",
+  "consumer=10101011100011000000110000",
+  "contestants=10101011100011000000110001",
+  "continues=10101011100011000000110010",
+  "controversial=10101011100011000000110011",
+  "dealer=10101011100011000000110100",
+  "deliver=10101011100011000000110101",
+  "discuss=10101011100011000000110110",
+  "document=10101011100011000000110111",
+  "drama=10101011100011000000111000",
+  "edition=10101011100011000000111001",
+  "education=10101011100011000000111010",
+  "events=10101011100011000000111011",
+  "every=10101011100011000000111100",
+  "excellent=10101011100011000000111101",
+  "eyed=10101011100011000000111110",
+  "family=10101011100011000000111111",
+  "famous=10101011100011000001000000",
+  "featur=10101011100011000001000001",
+  "film=10101011100011000001000010",
+  "football=10101011100011000001000011",
+  "for=10101011100011000001000100",
+  "from=10101011100011000001000101",
+  "general knowledge=10101011100011000001000110",
+  "get=10101011100011000001000111",
+  "guest=10101011100011000001001000",
+  "guests=10101011100011000001001001",
+  "has=10101011100011000001001010",
+  "have=10101011100011000001001011",
+  "headline=10101011100011000001001100",
+  "her=10101011100011000001001101",
+  "his=10101011100011000001001110",
+  "home and abroad=10101011100011000001001111",
+  "host=10101011100011000001010000",
+  "how=10101011100011000001010001",
+  "in=10101011100011000001010010",
+  "including=10101011100011000001010011",
+  "international=10101011100011000001010100",
+  "interview=10101011100011000001010101",
+  "introduce=10101011100011000001010110",
+  "investigat=10101011100011000001010111",
+  "invites=10101011100011000001011000",
+  "issue=10101011100011000001011001",
+  "knowledge=10101011100011000001011010",
+  "life=10101011100011000001011011",
+  "live=10101011100011000001011100",
+  "look=10101011100011000001011101",
+  "magazine=10101011100011000001011110",
+  "meets =10101011100011000001011111",
+  "morning=10101011100011000001100000",
+  "morning magazine=10101011100011000001100001",
+  "music=10101011100011000001100010",
+  "near=10101011100011000001100011",
+  "network=10101011100011000001100100",
+  "new=10101011100011000001100101",
+  "new series=10101011100011000001100110",
+  "night=10101011100011000001100111",
+  "of=10101011100011000001101000",
+  "on=10101011100011000001101001",
+  "onight=10101011100011000001101010",
+  "out=10101011100011000001101011",
+  "over=10101011100011000001101100",
+  "part=10101011100011000001101101",
+  "people=10101011100011000001101110",
+  "phone=10101011100011000001101111",
+  "poli=10101011100011000001110000",
+  "police=10101011100011000001110001",
+  "political chat show=10101011100011000001110010",
+  "popular=10101011100011000001110011",
+  "presented by =10101011100011000001110100",
+  "programm=10101011100011000001110101",
+  "quiz=10101011100011000001110110",
+  "reconstruction=10101011100011000001110111",
+  "report=10101011100011000001111000",
+  "review=10101011100011000001111001",
+  "school=10101011100011000001111010",
+  "series=10101011100011000001111011",
+  "short =10101011100011000001111100",
+  "show=10101011100011000001111101",
+  "some=10101011100011000001111110",
+  "starring=10101011100011000001111111",
+  "stars=10101011100011000010000000",
+  "stories=10101011100011000010000001",
+  "story=10101011100011000010000010",
+  "studio=10101011100011000010000011",
+  "surprise=10101011100011000010000100",
+  "teller=10101011100011000010000101",
+  "that=10101011100011000010000110",
+  "the=10101011100011000010000111",
+  "their=10101011100011000010001000",
+  "them=10101011100011000010001001",
+  "they=10101011100011000010001010",
+  "this=10101011100011000010001011",
+  "through=10101011100011000010001100",
+  "to=10101011100011000010001101",
+  "top=10101011100011000010001110",
+  "trans=10101011100011000010001111",
+  "under=10101011100011000010010000",
+  "up=10101011100011000010010001",
+  "very=10101011100011000010010010",
+  "video=10101011100011000010010011",
+  "view=10101011100011000010010100",
+  "vintage=10101011100011000010010101",
+  "visit=10101011100011000010010110",
+  "was=10101011100011000010010111",
+  "way=10101011100011000010011000",
+  "week=10101011100011000010011001",
+  "well=10101011100011000010011010",
+  "what=10101011100011000010011011",
+  "when=10101011100011000010011100",
+  "which=10101011100011000010011101",
+  "while=10101011100011000010011110",
+  "who=10101011100011000010011111",
+  "will=10101011100011000010100000",
+  "win=10101011100011000010100001",
+  "with=10101011100011000010100010",
+  "words=10101011100011000010100011",
+  "world=10101011100011000010100100",
+  "written=10101011100011000010100101",
+  "year=100010001100",
+  "you=10110011010",
+  NULL
+};
+
+static const char *SkyItThemes[] = {
+  "Non Definito", // 000 00000
+  NULL, // 000 00001
+  NULL, // 000 00010
+  NULL, // 000 00011
+  NULL, // 000 00100
+  NULL, // 000 00101
+  NULL, // 000 00110
+  NULL, // 000 00111
+  NULL, // 000 01000
+  NULL, // 000 01001
+  NULL, // 000 01010
+  NULL, // 000 01011
+  NULL, // 000 01100
+  NULL, // 000 01101
+  NULL, // 000 01110
+  NULL, // 000 01111
+  NULL, // 000 10000
+  NULL, // 000 10001
+  NULL, // 000 10010
+  NULL, // 000 10011
+  NULL, // 000 10100
+  NULL, // 000 10101
+  NULL, // 000 10110
+  NULL, // 000 10111
+  NULL, // 000 11000
+  NULL, // 000 11001
+  NULL, // 000 11010
+  NULL, // 000 11011
+  NULL, // 000 11100
+  NULL, // 000 11101
+  NULL, // 000 11110
+  NULL, // 000 11111
+  "Intrattenimento", // 001 00000
+  "Intrattenimento - Fiction", // 001 00001
+  "Intrattenimento - Sit Com", // 001 00010
+  "Intrattenimento - Show", // 001 00011
+  "Intrattenimento - Telefilm", // 001 00100
+  "Intrattenimento - Soap Opera", // 001 00101
+  "Intrattenimento - Telenovela", // 001 00110
+  "Intrattenimento - Fantascienza", // 001 00111
+  "Intrattenimento - Animazione", // 001 01000
+  "Intrattenimento - Giallo", // 001 01001
+  "Intrattenimento - Drammatico", // 001 01010
+  "Intrattenimento - Romantico", // 001 01011
+  "Intrattenimento - Miniserie", // 001 01100
+  "Intrattenimento - Spettacolo", // 001 01101
+  "Intrattenimento - Quiz", // 001 01110
+  "Intrattenimento - Talk Show", // 001 01111
+  "Intrattenimento - Varietà", // 001 10000
+  "Intrattenimento - Festival", // 001 10001
+  "Intrattenimento - Teatro", // 001 10010
+  "Intrattenimento - Gioco", // 001 10011
+  NULL, // 001 10100
+  NULL, // 001 10101
+  NULL, // 001 10110
+  NULL, // 001 10111
+  NULL, // 001 11000
+  NULL, // 001 11001
+  NULL, // 001 11010
+  NULL, // 001 11011
+  NULL, // 001 11100
+  NULL, // 001 11101
+  NULL, // 001 11110
+  NULL, // 001 11111
+  "Sport", // 010 00000
+  "Sport - Calcio", // 010 00001
+  "Sport - Tennis", // 010 00010
+  "Sport - Motori", // 010 00011
+  "Sport - Altri", // 010 00100
+  "Sport - Baseball", // 010 00101
+  "Sport - Ciclismo", // 010 00110
+  "Sport - Rugby", // 010 00111
+  "Sport - Basket", // 010 01000
+  "Sport - Boxe", // 010 01001
+  "Sport - Atletica", // 010 01010
+  "Sport - Football USA", // 010 01011
+  "Sport - Hockey", // 010 01100
+  "Sport - Sci", // 010 01101
+  "Sport - Equestri", // 010 01110
+  "Sport - Golf", // 010 01111
+  "Sport - Nuoto", // 010 10000
+  "Sport - Wrestling", // 010 10001
+  NULL, // 010 10010
+  NULL, // 010 10011
+  NULL, // 010 10100
+  NULL, // 010 10101
+  NULL, // 010 10110
+  NULL, // 010 10111
+  NULL, // 010 11000
+  NULL, // 010 11001
+  NULL, // 010 11010
+  NULL, // 010 11011
+  NULL, // 010 11100
+  NULL, // 010 11101
+  NULL, // 010 11110
+  NULL, // 010 11111
+  "Film", // 011 00000
+  "Film - Drammatico", // 011 00001
+  "Film - Commedia", // 011 00010
+  "Film - Romantico", // 011 00011
+  "Film - Azione", // 011 00100
+  "Film - Fantascienza", // 011 00101
+  "Film - Western", // 011 00110
+  "Film - Comico", // 011 00111
+  "Film - Fantastico", // 011 01000
+  "Film - Avventura", // 011 01001
+  "Film - Poliziesco", // 011 01010
+  "Film - Guerra", // 011 01011
+  "Film - Horror", // 011 01100
+  "Film - Animazione", // 011 01101
+  "Film - Thriller", // 011 01110
+  "Film - Musicale", // 011 01111
+  "Film - Corto", // 011 10000
+  "Film - Cortometraggio", // 011 10001
+  NULL, // 011 10010
+  NULL, // 011 10011
+  NULL, // 011 10100
+  NULL, // 011 10101
+  NULL, // 011 10110
+  NULL, // 011 10111
+  NULL, // 011 11000
+  NULL, // 011 11001
+  NULL, // 011 11010
+  NULL, // 011 11011
+  NULL, // 011 11100
+  NULL, // 011 11101
+  NULL, // 011 11110
+  NULL, // 011 11111
+  "Mondo e Tendenze", // 100 00000
+  "Mondo e Tendenze - Natura", // 100 00001
+  "Mondo e Tendenze - Arte e Cultura", // 100 00010
+  "Mondo e Tendenze - Lifestyle", // 100 00011
+  "Mondo e Tendenze - Viaggi", // 100 00100
+  "Mondo e Tendenze - Documentario", // 100 00101
+  "Mondo e Tendenze - Società", // 100 00110
+  "Mondo e Tendenze - Scienza", // 100 00111
+  "Mondo e Tendenze - Storia", // 100 01000
+  "Mondo e Tendenze - Sport", // 100 01001
+  "Mondo e Tendenze - Pesca", // 100 01010
+  "Mondo e Tendenze - Popoli", // 100 01011
+  "Mondo e Tendenze - Cinema", // 100 01100
+  "Mondo e Tendenze - Musica", // 100 01101
+  "Mondo e Tendenze - Hobby", // 100 01110
+  "Mondo e Tendenze - Caccia", // 100 01111
+  "Mondo e Tendenze - Reportage", // 100 10000
+  "Mondo e Tendenze - Magazine", // 100 10001
+  "Mondo e Tendenze - Magazine Cultura", // 100 10010
+  "Mondo e Tendenze - Magazine Scienza", // 100 10011
+  "Mondo e Tendenze - Politica", // 100 10100
+  "Mondo e Tendenze - Magazine Cinema", // 100 10101
+  "Mondo e Tendenze - Magazine Sport", // 100 10110
+  "Mondo e Tendenze - Attualità", // 100 10111
+  "Mondo e Tendenze - Moda", // 100 11000
+  "Mondo e Tendenze - Economia", // 100 11001
+  "Mondo e Tendenze - Magazine Caccia e Pesca", // 100 11010
+  "Mondo e Tendenze - Magazine Viaggi", // 100 11011
+  "Mondo e Tendenze - Magazine Natura", // 100 11100
+  "Mondo e Tendenze - Magazine Musica", // 100 11101
+  "Mondo e Tendenze - Religione", // 100 11110
+  "Mondo e Tendenze - Televendita", // 100 11111
+  "Informazione", // 101 00000
+  "Informazione - Notiziario", // 101 00001
+  "Informazione - Sport", // 101 00010
+  "Informazione - Economia", // 101 00011
+  NULL, // 101 00100
+  NULL, // 101 00101
+  NULL, // 101 00110
+  NULL, // 101 00111
+  NULL, // 101 01000
+  NULL, // 101 01001
+  NULL, // 101 01010
+  NULL, // 101 01011
+  NULL, // 101 01100
+  NULL, // 101 01101
+  NULL, // 101 01110
+  NULL, // 101 01111
+  NULL, // 101 10000
+  NULL, // 101 10001
+  NULL, // 101 10010
+  NULL, // 101 10011
+  NULL, // 101 10100
+  NULL, // 101 10101
+  NULL, // 101 10110
+  NULL, // 101 10111
+  NULL, // 101 11000
+  NULL, // 101 11001
+  NULL, // 101 11010
+  NULL, // 101 11011
+  NULL, // 101 11100
+  NULL, // 101 11101
+  NULL, // 101 11110
+  NULL, // 101 11111
+  "Ragazzi e Musica", // 110 00000
+  "Ragazzi e Musica - Bambini", // 110 00001
+  "Ragazzi e Musica - Ragazzi", // 110 00010
+  "Ragazzi e Musica - Cartoni Animati", // 110 00011
+  "Ragazzi e Musica - Musica", // 110 00100
+  "Ragazzi e Musica - Film Animazione", // 110 00101
+  "Ragazzi e Musica - Film", // 110 00110
+  "Ragazzi e Musica - Telefilm", // 110 00111
+  "Ragazzi e Musica - Magazine", // 110 01000
+  NULL, // 110 01001
+  NULL, // 110 01010
+  NULL, // 110 01011
+  NULL, // 110 01100
+  NULL, // 110 01101
+  NULL, // 110 01110
+  NULL, // 110 01111
+  NULL, // 110 10000
+  NULL, // 110 10001
+  NULL, // 110 10010
+  NULL, // 110 10011
+  "Ragazzi e Musica - Danza", // 110 10100
+  NULL, // 110 10101
+  NULL, // 110 10110
+  NULL, // 110 10111
+  NULL, // 110 11000
+  NULL, // 110 11001
+  NULL, // 110 11010
+  NULL, // 110 11011
+  NULL, // 110 11100
+  NULL, // 110 11101
+  NULL, // 110 11110
+  NULL, // 110 11111
+  "Altri Programmi", // 111 00000
+  "Altri Programmi - Educational", // 111 00001
+  "Altri Programmi - Regionale", // 111 00010
+  "Altri Programmi - Shopping", // 111 00011
+  NULL, // 111 00100
+  "Altri Programmi - Inizio e Fine Trasmissioni", // 111 00101
+  "Altri Programmi - Eventi Speciali", // 111 00110
+  "Altri Programmi - Film per Adulti", // 111 00111
+  NULL, // 111 01000
+  NULL, // 111 01001
+  NULL, // 111 01010
+  NULL, // 111 01011
+  NULL, // 111 01100
+  NULL, // 111 01101
+  NULL, // 111 01110
+  NULL, // 111 01111
+  NULL, // 111 10000
+  NULL, // 111 10001
+  NULL, // 111 10010
+  NULL, // 111 10011
+  NULL, // 111 10100
+  NULL, // 111 10101
+  NULL, // 111 10110
+  NULL, // 111 10111
+  NULL, // 111 11000
+  NULL, // 111 11001
+  NULL, // 111 11010
+  NULL, // 111 11011
+  NULL, // 111 11100
+  NULL, // 111 11101
+  NULL, // 111 11110
+  NULL, // 111 11111
+};
+
+static const char *SkyUkThemes[] = {
+  "No Category", // 000 00000
+  NULL, // 000 00001
+  NULL, // 000 00010
+  NULL, // 000 00011
+  NULL, // 000 00100
+  NULL, // 000 00101
+  NULL, // 000 00110
+  NULL, // 000 00111
+  NULL, // 000 01000
+  NULL, // 000 01001
+  NULL, // 000 01010
+  NULL, // 000 01011
+  NULL, // 000 01100
+  NULL, // 000 01101
+  NULL, // 000 01110
+  NULL, // 000 01111
+  NULL, // 000 10000
+  NULL, // 000 10001
+  NULL, // 000 10010
+  NULL, // 000 10011
+  NULL, // 000 10100
+  NULL, // 000 10101
+  NULL, // 000 10110
+  NULL, // 000 10111
+  NULL, // 000 11000
+  NULL, // 000 11001
+  NULL, // 000 11010
+  NULL, // 000 11011
+  NULL, // 000 11100
+  NULL, // 000 11101
+  NULL, // 000 11110
+  NULL, // 000 11111
+  NULL, // 001 00000
+  NULL, // 001 00001
+  NULL, // 001 00010
+  "Shopping", // 001 00011
+  NULL, // 001 00100
+  NULL, // 001 00101
+  NULL, // 001 00110
+  NULL, // 001 00111
+  NULL, // 001 01000
+  NULL, // 001 01001
+  NULL, // 001 01010
+  NULL, // 001 01011
+  NULL, // 001 01100
+  NULL, // 001 01101
+  NULL, // 001 01110
+  NULL, // 001 01111
+  NULL, // 001 10000
+  NULL, // 001 10001
+  NULL, // 001 10010
+  NULL, // 001 10011
+  NULL, // 001 10100
+  NULL, // 001 10101
+  NULL, // 001 10110
+  NULL, // 001 10111
+  NULL, // 001 11000
+  NULL, // 001 11001
+  NULL, // 001 11010
+  NULL, // 001 11011
+  NULL, // 001 11100
+  NULL, // 001 11101
+  NULL, // 001 11110
+  NULL, // 001 11111
+  "Children", // 010 00000
+  "Children - Cartoons", // 010 00001
+  "Children - Comedy", // 010 00010
+  "Children - Drama", // 010 00011
+  "Children - Educational", // 010 00100
+  "Children - Under 5", // 010 00101
+  "Children - Factual", // 010 00110
+  "Children - Magazine", // 010 00111
+  NULL, // 010 01000
+  NULL, // 010 01001
+  NULL, // 010 01010
+  NULL, // 010 01011
+  NULL, // 010 01100
+  NULL, // 010 01101
+  NULL, // 010 01110
+  NULL, // 010 01111
+  NULL, // 010 10000
+  NULL, // 010 10001
+  NULL, // 010 10010
+  NULL, // 010 10011
+  NULL, // 010 10100
+  NULL, // 010 10101
+  NULL, // 010 10110
+  NULL, // 010 10111
+  NULL, // 010 11000
+  NULL, // 010 11001
+  NULL, // 010 11010
+  NULL, // 010 11011
+  NULL, // 010 11100
+  NULL, // 010 11101
+  NULL, // 010 11110
+  NULL, // 010 11111
+  "Entertainment", // 011 00000
+  "Entertainment - Action", // 011 00001
+  "Entertainment - Comedy", // 011 00010
+  "Entertainment - Detective", // 011 00011
+  "Entertainment - Drama", // 011 00100
+  "Entertainment - Game Show", // 011 00101
+  "Entertainment - Sci-FI", // 011 00110
+  "Entertainment - Soap", // 011 00111
+  "Entertainment - Animation", // 011 01000
+  "Entertainment - Chat Show", // 011 01001
+  "Entertainment - Cooking", // 011 01010
+  "Entertainment - Factual", // 011 01011
+  "Entertainment - Fashion", // 011 01100
+  "Entertainment - Gardening", // 011 01101
+  "Entertainment - Travel", // 011 01110
+  "Entertainment - Technology", // 011 01111
+  "Entertainment - Arts", // 011 10000
+  "Entertainment - Lifestyle", // 011 10001
+  "Entertainment - Home", // 011 10010
+  "Entertainment - Magazine", // 011 10011
+  "Entertainment - Medical", // 011 10100
+  "Entertainment - Review", // 011 10101
+  "Entertainment - Antiques", // 011 10110
+  "Entertainment - Motors", // 011 10111
+  "Entertainment - Art&Lit", // 011 11000
+  "Entertainment - Ballet", // 011 11001
+  "Entertainment - Opera", // 011 11010
+  NULL, // 011 11011
+  NULL, // 011 11100
+  NULL, // 011 11101
+  NULL, // 011 11110
+  NULL, // 011 11111
+  "Music", // 100 00000
+  "Music - Classical ", // 100 00001
+  "Music - Folk and Country", // 100 00010
+  "Music - National Music", // 100 00011
+  "Music - Jazz", // 100 00100
+  "Music - Opera", // 100 00101
+  "Music - Rock&Pop", // 100 00110
+  "Music - Alternative Music", // 100 00111
+  "Music - Events", // 100 01000
+  "Music - Club and Dance", // 100 01001
+  "Music - Hip Hop", // 100 01010
+  "Music - Soul/R&B", // 100 01011
+  "Music - Dance", // 100 01100
+  NULL, // 100 01101
+  NULL, // 100 01110
+  NULL, // 100 01111
+  "Music - Features", // 100 10000
+  NULL, // 100 10001
+  NULL, // 100 10010
+  NULL, // 100 10011
+  NULL, // 100 10100
+  "Music - Lifestyle", // 100 10101
+  "Music - News and Weather", // 100 10110
+  "Music - Easy Listening", // 100 10111
+  "Music - Discussion", // 100 11000
+  "Music - Entertainment", // 100 11001
+  "Music - Religious", // 100 11010
+  NULL, // 100 11011
+  NULL, // 100 11100
+  NULL, // 100 11101
+  NULL, // 100 11110
+  NULL, // 100 11111
+  "News & Documentaries", // 101 00000
+  "News & Documentaries - Business", // 101 00001
+  "News & Documentaries - World Cultures", // 101 00010
+  "News & Documentaries - Adventure", // 101 00011
+  "News & Documentaries - Biography", // 101 00100
+  "News & Documentaries - Educational", // 101 00101
+  "News & Documentaries - Feature", // 101 00110
+  "News & Documentaries - Politics", // 101 00111
+  "News & Documentaries - News", // 101 01000
+  "News & Documentaries - Nature", // 101 01001
+  "News & Documentaries - Religious", // 101 01010
+  "News & Documentaries - Science", // 101 01011
+  "News & Documentaries - Showbiz", // 101 01100
+  "News & Documentaries - War Documentary", // 101 01101
+  "News & Documentaries - Historical", // 101 01110
+  "News & Documentaries - Ancient", // 101 01111
+  "News & Documentaries - Transport", // 101 10000
+  "News & Documentaries - Docudrama", // 101 10001
+  "News & Documentaries - World Affairs", // 101 10010
+  NULL, // 101 10011
+  NULL, // 101 10100
+  NULL, // 101 10101
+  NULL, // 101 10110
+  NULL, // 101 10111
+  NULL, // 101 11000
+  NULL, // 101 11001
+  NULL, // 101 11010
+  NULL, // 101 11011
+  NULL, // 101 11100
+  NULL, // 101 11101
+  NULL, // 101 11110
+  NULL, // 101 11111
+  "Movie", // 110 00000
+  "Movie - Action", // 110 00001
+  "Movie - Animation", // 110 00010
+  NULL, // 110 00011
+  "Movie - Comedy", // 110 00100
+  "Movie - Family", // 110 00101
+  "Movie - Drama", // 110 00110
+  NULL, // 110 00111
+  "Movie - Sci-Fi", // 110 01000
+  "Movie - Thriller", // 110 01001
+  "Movie - Horror", // 110 01010
+  "Movie - Romance", // 110 01011
+  "Movie - Musical", // 110 01100
+  "Movie - Mystery", // 110 01101
+  "Movie - Western", // 110 01110
+  "Movie - Factual", // 110 01111
+  "Movie - Fantasy", // 110 10000
+  "Movie - Erotic", // 110 10001
+  "Movie - Adventure", // 110 10010
+  NULL, // 110 10011
+  NULL, // 110 10100
+  NULL, // 110 10101
+  NULL, // 110 10110
+  NULL, // 110 10111
+  NULL, // 110 11000
+  NULL, // 110 11001
+  NULL, // 110 11010
+  NULL, // 110 11011
+  NULL, // 110 11100
+  NULL, // 110 11101
+  NULL, // 110 11110
+  NULL, // 110 11111
+  "Sports - Other", // 111 00000
+  "Sports - American Football", // 111 00001
+  "Sports - Athletics", // 111 00010
+  "Sports - Baseball", // 111 00011
+  "Sports - Basketball", // 111 00100
+  "Sports - Boxing", // 111 00101
+  "Sports - Cricket", // 111 00110
+  "Sports - Fishing", // 111 00111
+  "Sports - Football", // 111 01000
+  "Sports - Golf", // 111 01001
+  "Sports - Ice Hockey", // 111 01010
+  "Sports - Motor Sport", // 111 01011
+  "Sports - Racing", // 111 01100
+  "Sports - Rugby", // 111 01101
+  "Sports - Equestrian", // 111 01110
+  "Sports - Winter Sports", // 111 01111
+  "Sports - Snooker / Pool", // 111 10000
+  "Sports - Tennis", // 111 10001
+  "Sports - Wrestling", // 111 10010
+  "Sports - Darts", // 111 10011
+  "Sports - Watersports", // 111 10100
+  "Sports - Extreme", // 111 10101
+  NULL, // 111 10110
+  NULL, // 111 10111
+  NULL, // 111 11000
+  NULL, // 111 11001
+  NULL, // 111 11010
+  NULL, // 111 11011
+  NULL, // 111 11100
+  NULL, // 111 11101
+  NULL, // 111 11110
+  NULL, // 111 11111
+};
+
+static const char *FreesatT1[] = {
+  "START:00:T:",
+  "START:010:B:",
+  "START:1000:C:",
+  "START:1001:I:",
+  "START:1101:S:",
+  "START:01100:L:",
+  "START:01110:D:",
+  "START:01111:H:",
+  "START:10100:R:",
+  "START:10101:N:",
+  "START:10110:E:",
+  "START:11000:F:",
+  "START:11001:A:",
+  "START:11100:M:",
+  "START:11101:P:",
+  "START:11110:W:",
+  "START:011011:Q:",
+  "START:101111:G:",
+  "START:111110:J:",
+  "START:0110100:K:",
+  "START:1011101:U:",
+  "START:1111110:O:",
+  "START:01101010:6:",
+  "START:01101011:.:",
+  "START:10111000:V:",
+  "START:11111110:Y:",
+  "START:101110011:2:",
+  "START:111111111:X:",
+  "START:1011100100:Z:",
+  "START:1111111100:8:",
+  "START:10111001010:1:",
+  "START:10111001011:3:",
+  "START:111111110100:4:",
+  "START:111111110101:':",
+  "START:111111110111: :",
+  "START:11111111011000:5:",
+  "START:11111111011011:0:",
+  "START:111111110110011:m:",
+  "START:1111111101100100:c:",
+  "START:1111111101101000:9:",
+  "START:1111111101101010:a:",
+  "START:1111111101101011:d:",
+  "START:11111111011001010:s:",
+  "START:11111111011001011:p:",
+  "START:11111111011010010:(:",
+  "START:111111110110100110:t:",
+  "START:1111111101101001110:7:",
+  "START:11111111011010011110:ESCAPE:",
+  "START:11111111011010011111:l:",
+  "ESCAPE:0:ESCAPE:",
+  "ESCAPE:1:ESCAPE:",
+  "STOP:0:ESCAPE:",
+  "STOP:1:ESCAPE:",
+  "0x03:0:ESCAPE:",
+  "0x03:1:ESCAPE:",
+  "0x04:0:ESCAPE:",
+  "0x04:1:ESCAPE:",
+  "0x05:0:ESCAPE:",
+  "0x05:1:ESCAPE:",
+  "0x06:0:ESCAPE:",
+  "0x06:1:ESCAPE:",
+  "0x07:0:ESCAPE:",
+  "0x07:1:ESCAPE:",
+  "0x08:0:ESCAPE:",
+  "0x08:1:ESCAPE:",
+  "0x09:0:ESCAPE:",
+  "0x09:1:ESCAPE:",
+  "0x0a:0:ESCAPE:",
+  "0x0a:1:ESCAPE:",
+  "0x0b:0:ESCAPE:",
+  "0x0b:1:ESCAPE:",
+  "0x0c:0:ESCAPE:",
+  "0x0c:1:ESCAPE:",
+  "0x0d:0:ESCAPE:",
+  "0x0d:1:ESCAPE:",
+  "0x0e:0:ESCAPE:",
+  "0x0e:1:ESCAPE:",
+  "0x0f:0:ESCAPE:",
+  "0x0f:1:ESCAPE:",
+  "0x10:0:ESCAPE:",
+  "0x10:1:ESCAPE:",
+  "0x11:0:ESCAPE:",
+  "0x11:1:ESCAPE:",
+  "0x12:0:ESCAPE:",
+  "0x12:1:ESCAPE:",
+  "0x13:0:ESCAPE:",
+  "0x13:1:ESCAPE:",
+  "0x14:0:ESCAPE:",
+  "0x14:1:ESCAPE:",
+  "0x15:0:ESCAPE:",
+  "0x15:1:ESCAPE:",
+  "0x16:0:ESCAPE:",
+  "0x16:1:ESCAPE:",
+  "0x17:0:ESCAPE:",
+  "0x17:1:ESCAPE:",
+  "0x18:0:ESCAPE:",
+  "0x18:1:ESCAPE:",
+  "0x19:0:ESCAPE:",
+  "0x19:1:ESCAPE:",
+  "0x1a:0:ESCAPE:",
+  "0x1a:1:ESCAPE:",
+  "0x1b:0:ESCAPE:",
+  "0x1b:1:ESCAPE:",
+  "0x1c:0:ESCAPE:",
+  "0x1c:1:ESCAPE:",
+  "0x1d:0:ESCAPE:",
+  "0x1d:1:ESCAPE:",
+  "0x1e:0:ESCAPE:",
+  "0x1e:1:ESCAPE:",
+  "0x1f:0:ESCAPE:",
+  "0x1f:1:ESCAPE:",
+  " :0000:W:",
+  " :0011:M:",
+  " :0100:C:",
+  " :0101:B:",
+  " :0111:P:",
+  " :1001:T:",
+  " :1100:N:",
+  " :1111:S:",
+  " :00011:I:",
+  " :00100:G:",
+  " :01100:H:",
+  " :01101:D:",
+  " :10000:o:",
+  " :10001:A:",
+  " :10100:t:",
+  " :10110:a:",
+  " :10111:F:",
+  " :11010:L:",
+  " :11011:R:",
+  " :001011:U:",
+  " :101011:O:",
+  " :111001:J:",
+  " :111010:E:",
+  " :0001000:f:",
+  " :0001001:Q:",
+  " :0001011:V:",
+  " :0010100:STOP:",
+  " :0010101:w:",
+  " :1110000:2:",
+  " :1110001:K:",
+  " :1110110:Y:",
+  " :1110111:i:",
+  " :00010100:-:",
+  " :10101001:1:",
+  " :101010000:&:",
+  " :101010101:X:",
+  " :0001010101:r:",
+  " :1010100010:5:",
+  " :1010100011:Z:",
+  " :1010101001:9:",
+  " :1010101101:s:",
+  " :1010101110:4:",
+  " :1010101111:3:",
+  " :00010101000:7:",
+  " :00010101100:b:",
+  " :00010101110:y:",
+  " :10101010000:':",
+  " :10101011000:6:",
+  " :000101011010:v:",
+  " :000101011011:d:",
+  " :000101011110:(:",
+  " :101010100010: :",
+  " :101010100011:0:",
+  " :101010110010:n:",
+  " :101010110011:8:",
+  " :0001010100110:g:",
+  " :0001010111110:u:",
+  " :00010101001000:+:",
+  " :00010101001001:.:",
+  " :00010101001010:ESCAPE:",
+  " :00010101001011:l:",
+  " :00010101001111:m:",
+  " :00010101111110:p:",
+  " :000101010011100:\\:",
+  " :000101010011101:/:",
+  " :000101011111111:e:",
+  " :0001010111111101:\":",
+  " :00010101111111001:c:",
+  " :000101011111110000:k:",
+  " :000101011111110001:h:",
+  "!:1:STOP:",
+  "!:01: :",
+  "!:001:.:",
+  "!:0001:!:",
+  "!:00001:\":",
+  "!:000000:ESCAPE:",
+  "!:000001:0x3a:",
+  "\":0: :",
+  "\":10:ESCAPE:",
+  "\":11:I:",
+  "#:0:ESCAPE:",
+  "#:1:ESCAPE:",
+  "$:0:ESCAPE:",
+  "$:1:ESCAPE:",
+  "%:1: :",
+  "%:00:ESCAPE:",
+  "%:01:STOP:",
+  "&:1: :",
+  "&:01:B:",
+  "&:000:ESCAPE:",
+  "&:001:.:",
+  "':1:s:",
+  "':000:m:",
+  "':010:C:",
+  "':0010:t:",
+  "':0011: :",
+  "':01100:d:",
+  "':01110:v:",
+  "':011011:r:",
+  "':011111:A:",
+  "':0110101:n:",
+  "':01101000:G:",
+  "':01111001:l:",
+  "':011010011:D:",
+  "':011110000:B:",
+  "':011110001:e:",
+  "':011110101:i:",
+  "':011110110:6:",
+  "':0110100100:L:",
+  "':0111101001:STOP:",
+  "':0111101111:w:",
+  "':01101001010:O:",
+  "':01111010000:S:",
+  "':01111010001:E:",
+  "':01111011101:N:",
+  "':011110111001:R:",
+  "':0110100101100:a:",
+  "':0110100101101:M:",
+  "':0110100101110:K:",
+  "':0110100101111:F:",
+  "':0111101110000:0:",
+  "':01111011100010:ESCAPE:",
+  "':01111011100011:c:",
+  "(:1:c:",
+  "(:000:1:",
+  "(:0010:M:",
+  "(:0011:U:",
+  "(:0100:R:",
+  "(:0101:D:",
+  "(:0110:H:",
+  "(:01110:S:",
+  "(:011110:F:",
+  "(:0111110:G:",
+  "(:01111110:ESCAPE:",
+  "(:01111111:Y:",
+  "):1:STOP:",
+  "):00:ESCAPE:",
+  "):01: :",
+  "*:0:*:",
+  "*:101: :",
+  "*:1000:d:",
+  "*:1100:m:",
+  "*:1101:t:",
+  "*:1111:s:",
+  "*:10010:e:",
+  "*:11100:g:",
+  "*:11101:k:",
+  "*:100110:ESCAPE:",
+  "*:100111:y:",
+  "+:0:ESCAPE:",
+  "+:1: :",
+  ",:1: :",
+  ",:01:0:",
+  ",:000:ESCAPE:",
+  ",:001:.:",
+  "-:11: :",
+  "-:011:S:",
+  "-:100:G:",
+  "-:101:O:",
+  "-:0011:T:",
+  "-:0100:U:",
+  "-:00000:E:",
+  "-:00010:D:",
+  "-:000010:m:",
+  "-:000110:0:",
+  "-:000111:I:",
+  "-:001010:6:",
+  "-:010100:F:",
+  "-:010101:o:",
+  "-:0000110:L:",
+  "-:0000111:C:",
+  "-:0010001:A:",
+  "-:0010010:t:",
+  "-:0010011:Y:",
+  "-:0010111:2:",
+  "-:0101100:B:",
+  "-:0101101:.:",
+  "-:00100000:P:",
+  "-:00100001:Z:",
+  "-:01011100:8:",
+  "-:01011101:i:",
+  "-:01011110:d:",
+  "-:01011111:H:",
+  "-:001011001:N:",
+  "-:001011011:R:",
+  "-:0010110000:1:",
+  "-:0010110001:W:",
+  "-:00101101001:c:",
+  "-:00101101010:a:",
+  "-:00101101011:M:",
+  "-:001011010000:ESCAPE:",
+  "-:001011010001:Q:",
+  ".:1:.:",
+  ".:01:STOP:",
+  ".:0010: :",
+  ".:00000:I:",
+  ".:00001:T:",
+  ".:00010:C:",
+  ".:00110:p:",
+  ".:00111:0:",
+  ".:000111:H:",
+  ".:00011010:W:",
+  ".:000110001:S:",
+  ".:000110110:3:",
+  ".:000110111:B:",
+  ".:0001100000:1:",
+  ".:0001100001:M:",
+  ".:0001100110:c:",
+  ".:00011001000:t:",
+  ".:00011001001:R:",
+  ".:00011001010:F:",
+  ".:00011001110:E:",
+  ".:00011001111:A:",
+  ".:0001100101100:ESCAPE:",
+  ".:0001100101101:l:",
+  ".:0001100101110:d:",
+  ".:0001100101111:U:",
+  "/:00:1:",
+  "/:10:7:",
+  "/:010:4:",
+  "/:011:2:",
+  "/:110:3:",
+  "/:1110:5:",
+  "/:111100:6:",
+  "/:111110:C:",
+  "/:1111010:9:",
+  "/:1111011: :",
+  "/:1111110:8:",
+  "/:11111111:U:",
+  "/:1111111000:G:",
+  "/:1111111010:0:",
+  "/:11111110010:ESCAPE:",
+  "/:11111110011:W:",
+  "/:11111110110:V:",
+  "/:11111110111:S:",
+  "0:00:6:",
+  "0:01: :",
+  "0:11:0:",
+  "0:1001:p:",
+  "0:1010:STOP:",
+  "0:10000:1:",
+  "0:10001:a:",
+  "0:10111:7:",
+  "0:1011000:-:",
+  "0:1011010:s:",
+  "0:10110011:4:",
+  "0:10110110:t:",
+  "0:101101111:%:",
+  "0:1011001000:8:",
+  "0:1011001001:0x3a:",
+  "0:1011001010:5:",
+  "0:1011001011:2:",
+  "0:1011011100:/:",
+  "0:10110111011:U:",
+  "0:101101110101:,:",
+  "0:1011011101000:.:",
+  "0:10110111010010:ESCAPE:",
+  "0:10110111010011:l:",
+  "1:01:STOP:",
+  "1:000:.:",
+  "1:101:0:",
+  "1:111:1:",
+  "1:0010:2:",
+  "1:0011: :",
+  "1:1101:/:",
+  "1:10010:8:",
+  "1:11000:3:",
+  "1:100000:5:",
+  "1:100001:s:",
+  "1:100010:6:",
+  "1:100011:0x3a:",
+  "1:100110:':",
+  "1:110010:X:",
+  "1:110011:9:",
+  "1:1001111:4:",
+  "1:10011101:-:",
+  "1:100111001:7:",
+  "1:1001110000:):",
+  "1:10011100010:ESCAPE:",
+  "1:10011100011:,:",
+  "2:0:0:",
+  "2:11:4:",
+  "2:101:STOP:",
+  "2:1001: :",
+  "2:10000:0x3a:",
+  "2:1000101:5:",
+  "2:1000111:/:",
+  "2:10001000:.:",
+  "2:10001001:1:",
+  "2:10001100:W:",
+  "2:100011011:7:",
+  "2:10001101001:3:",
+  "2:10001101011:Z:",
+  "2:100011010000:n:",
+  "2:100011010001:6:",
+  "2:100011010101:':",
+  "2:1000110101000:ESCAPE:",
+  "2:1000110101001:s:",
+  "3:0: :",
+  "3:10:STOP:",
+  "3:1100:r:",
+  "3:1101:/:",
+  "3:1111:B:",
+  "3:11100:0:",
+  "3:1110100:0x3a:",
+  "3:1110110:-:",
+  "3:11101010:1:",
+  "3:11101011:8:",
+  "3:11101111:4:",
+  "3:1110111000:6:",
+  "3:1110111011:9:",
+  "3:11101110011:t:",
+  "3:11101110100:3:",
+  "3:111011100100:ESCAPE:",
+  "3:111011100101:e:",
+  "3:111011101010:7:",
+  "3:111011101011:5:",
+  "4:0:STOP:",
+  "4:11: :",
+  "4:1001:0x3a:",
+  "4:1011:/:",
+  "4:10001:8:",
+  "4:10101:.:",
+  "4:100000:9:",
+  "4:101000:0:",
+  "4:1010010:M:",
+  "4:10000101:I:",
+  "4:10000110:):",
+  "4:10100110:R:",
+  "4:10100111:-:",
+  "4:100001000:W:",
+  "4:100001110:P:",
+  "4:100001111:5:",
+  "4:1000010011:2:",
+  "4:10000100100:ESCAPE:",
+  "4:10000100101:':",
+  "5:0:STOP:",
+  "5:11: :",
+  "5:101:0:",
+  "5:1001:/:",
+  "5:100001:-:",
+  "5:100011:0x3a:",
+  "5:1000001:t:",
+  "5:1000100:3:",
+  "5:1000101:1:",
+  "5:10000000:ESCAPE:",
+  "5:10000001:a:",
+  "6:00:STOP:",
+  "6:01: :",
+  "6:10:0:",
+  "6:111:0x3a:",
+  "6:11001:.:",
+  "6:11011:i:",
+  "6:110000:-:",
+  "6:110101:a:",
+  "6:1100011:4:",
+  "6:1101000:8:",
+  "6:1101001:/:",
+  "6:11000100:6:",
+  "6:110001011:9:",
+  "6:1100010100:3:",
+  "6:11000101010:ESCAPE:",
+  "6:11000101011:t:",
+  "7:1:STOP:",
+  "7:01: :",
+  "7:000:0:",
+  "7:0011:.:",
+  "7:00101:/:",
+  "7:0010000:1:",
+  "7:0010010:5:",
+  "7:00100010:ESCAPE:",
+  "7:00100011:4:",
+  "7:00100110:3:",
+  "7:00100111:2:",
+  "8:1: :",
+  "8:00:0:",
+  "8:010:0x3a:",
+  "8:01101:STOP:",
+  "8:011000:t:",
+  "8:011001:p:",
+  "8:011101:8:",
+  "8:011110:.:",
+  "8:011111:6:",
+  "8:0111000:5:",
+  "8:01110010:9:",
+  "8:011100110:M:",
+  "8:0111001110:F:",
+  "8:01110011110:ESCAPE:",
+  "8:01110011111:c:",
+  "9:0:1:",
+  "9:11:STOP:",
+  "9:1000:9:",
+  "9:1010:.:",
+  "9:10011:0:",
+  "9:100100: :",
+  "9:100101:8:",
+  "9:101100:7:",
+  "9:101101:/:",
+  "9:101110:6:",
+  "9:1011111:0x3a:",
+  "9:10111101:4:",
+  "9:101111000:ESCAPE:",
+  "9:101111001:3:",
+  "0x3a:1: :",
+  "0x3a:00:0:",
+  "0x3a:011:.:",
+  "0x3a:0100:2:",
+  "0x3a:01010:1:",
+  "0x3a:010111:3:",
+  "0x3a:0101101:C:",
+  "0x3a:01011000:ESCAPE:",
+  "0x3a:01011001:T:",
+  ";:1: :",
+  ";:00:ESCAPE:",
+  ";:01:.:",
+  "<:0:ESCAPE:",
+  "<:1:ESCAPE:",
+  "=:0:ESCAPE:",
+  "=:1:ESCAPE:",
+  ">:0:ESCAPE:",
+  ">:1:ESCAPE:",
+  "?:1:STOP:",
+  "?:01: :",
+  "?:001:0x3a:",
+  "?:0000:ESCAPE:",
+  "?:0001:.:",
+  "@:0:ESCAPE:",
+  "@:1:H:",
+  "A:001:r:",
+  "A:010: :",
+  "A:100:l:",
+  "A:110:n:",
+  "A:0000:m:",
+  "A:0111:g:",
+  "A:1111:d:",
+  "A:00010:w:",
+  "A:01100:T:",
+  "A:01101:c:",
+  "A:10101:t:",
+  "A:10110:f:",
+  "A:10111:i:",
+  "A:11100:s:",
+  "A:000110:u:",
+  "A:000111:STOP:",
+  "A:101001:R:",
+  "A:111010:b:",
+  "A:1010001:v:",
+  "A:1110110:p:",
+  "A:10100000:S:",
+  "A:11101110:M:",
+  "A:101000011:P:",
+  "A:111011111:.:",
+  "A:10100001000:e:",
+  "A:10100001001:B:",
+  "A:10100001010:1:",
+  "A:11101111011:-:",
+  "A:101000010110:k:",
+  "A:101000010111:h:",
+  "A:111011110000:a:",
+  "A:111011110100:y:",
+  "A:111011110101:*:",
+  "A:1110111100010:x:",
+  "A:1110111100011:':",
+  "A:1110111100100:N:",
+  "A:1110111100110:2:",
+  "A:11101111001010:0x3a:",
+  "A:11101111001111:z:",
+  "A:111011110010110:L:",
+  "A:111011110010111:F:",
+  "A:111011110011100:D:",
+  "A:1110111100111010:ESCAPE:",
+  "A:1110111100111011:q:",
+  "B:00:C:",
+  "B:01:B:",
+  "B:101:r:",
+  "B:1001:i:",
+  "B:1100:o:",
+  "B:1101:u:",
+  "B:1110:a:",
+  "B:1111:e:",
+  "B:10001:l:",
+  "B:1000000:STOP:",
+  "B:1000010:y:",
+  "B:10000010:O:",
+  "B:10000110:3:",
+  "B:100000111:A:",
+  "B:100001110:S:",
+  "B:1000001101:0x3a:",
+  "B:10000011000:.:",
+  "B:10000011001:w:",
+  "B:10000111101:h:",
+  "B:10000111110:*:",
+  "B:10000111111: :",
+  "B:100001111001:R:",
+  "B:1000011110000:':",
+  "B:10000111100011:T:",
+  "B:100001111000100:ESCAPE:",
+  "B:100001111000101:4:",
+  "C:00:o:",
+  "C:01: :",
+  "C:100:l:",
+  "C:110:h:",
+  "C:1010:r:",
+  "C:1110:a:",
+  "C:10110:i:",
+  "C:10111:e:",
+  "C:111100:u:",
+  "C:111101:B:",
+  "C:1111100:y:",
+  "C:1111110:!:",
+  "C:11111011:.:",
+  "C:111110100:w:",
+  "C:111111100:STOP:",
+  "C:111111110:S:",
+  "C:111111111:T:",
+  "C:1111101011:2:",
+  "C:1111111011:I:",
+  "C:11111010100:4:",
+  "C:11111010101:*:",
+  "C:11111110101:D:",
+  "C:111111101000:U:",
+  "C:1111111010010:':",
+  "C:11111110100110:n:",
+  "C:111111101001110:z:",
+  "C:11111110100111100:O:",
+  "C:11111110100111101:E:",
+  "C:11111110100111110:A:",
+  "C:111111101001111110:ESCAPE:",
+  "C:111111101001111111:s:",
+  "D:01:o:",
+  "D:10:a:",
+  "D:000:r:",
+  "D:110:e:",
+  "D:111:i:",
+  "D:00100:t:",
+  "D:00111:u:",
+  "D:001011: :",
+  "D:0010101:J:",
+  "D:0011000:y:",
+  "D:0011010:STOP:",
+  "D:0011011:I:",
+  "D:00110011:0x3a:",
+  "D:001010001:*:",
+  "D:001010010:-:",
+  "D:001010011:&:",
+  "D:001100100:':",
+  "D:0010100000:A:",
+  "D:0010100001:h:",
+  "D:00110010101:N:",
+  "D:00110010110:V:",
+  "D:001100101110:D:",
+  "D:001100101111:w:",
+  "D:0011001010000:O:",
+  "D:0011001010001:E:",
+  "D:0011001010011:d:",
+  "D:00110010100100:ESCAPE:",
+  "D:00110010100101:T:",
+  "E:00:m:",
+  "E:011:v:",
+  "E:101:n:",
+  "E:111:a:",
+  "E:0100:E:",
+  "E:1000:STOP:",
+  "E:1101:x:",
+  "E:10011:d:",
+  "E:11001:l:",
+  "E:010100:4:",
+  "E:010101:y:",
+  "E:010110:u:",
+  "E:100100:r:",
+  "E:110000:i:",
+  "E:0101111:s:",
+  "E:1001010:F:",
+  "E:1100010:X:",
+  "E:10010110:R:",
+  "E:11000111: :",
+  "E:010111010:g:",
+  "E:100101111:0x3a:",
+  "E:110001100:T:",
+  "E:110001101:':",
+  "E:0101110001:c:",
+  "E:0101110011:q:",
+  "E:0101110110:e:",
+  "E:0101110111:C:",
+  "E:1001011100:p:",
+  "E:01011100000:-:",
+  "E:01011100101:Z:",
+  "E:10010111011:t:",
+  "E:010111000010:S:",
+  "E:010111000011:.:",
+  "E:100101110101:W:",
+  "E:0101110010000:!:",
+  "E:1001011101000:o:",
+  "E:01011100100010:f:",
+  "E:01011100100011:U:",
+  "E:01011100100100:N:",
+  "E:01011100100101:M:",
+  "E:01011100100110:L:",
+  "E:01011100100111:A:",
+  "E:10010111010011:D:",
+  "E:100101110100100:ESCAPE:",
+  "E:100101110100101:w:",
+  "F:00:i:",
+  "F:10:a:",
+  "F:011:r:",
+  "F:110:u:",
+  "F:111:o:",
+  "F:0100:e:",
+  "F:01011:l:",
+  "F:0101000:A:",
+  "F:0101010:O:",
+  "F:01010010: :",
+  "F:010100110:h:",
+  "F:010100111:t:",
+  "F:010101101:f:",
+  "F:010101111:L:",
+  "F:0101011001:STOP:",
+  "F:01010111000:j:",
+  "F:01010111001:I:",
+  "F:01010111010:.:",
+  "F:01010111011:1:",
+  "F:010101100000:M:",
+  "F:010101100010:*:",
+  "F:010101100011:K:",
+  "F:0101011000010:y:",
+  "F:01010110000111:H:",
+  "F:010101100001100:ESCAPE:",
+  "F:010101100001101:!:",
+  "G:10:r:",
+  "G:001:M:",
+  "G:010:a:",
+  "G:011:o:",
+  "G:110:i:",
+  "G:111:e:",
+  "G:00001:u:",
+  "G:00010:X:",
+  "G:000001:h:",
+  "G:000111:l:",
+  "G:0000001:y:",
+  "G:0001100:w:",
+  "G:00000000:0x3a:",
+  "G:00011011:C:",
+  "G:000000011:STOP:",
+  "G:000110100:-:",
+  "G:0001101010:P:",
+  "G:0001101011: :",
+  "G:00000001000:':",
+  "G:00000001010:A:",
+  "G:000000010010:U:",
+  "G:000000010110:T:",
+  "G:000000010111:4:",
+  "G:0000000100110:ESCAPE:",
+  "G:0000000100111:Y:",
+  "H:0:o:",
+  "H:100:a:",
+  "H:101:i:",
+  "H:110:e:",
+  "H:1110:u:",
+  "H:11110:R:",
+  "H:111110:A:",
+  "H:1111110:.:",
+  "H:111111101:y:",
+  "H:111111110:S:",
+  "H:1111111110:E:",
+  "H:1111111111:r:",
+  "H:11111110000:STOP:",
+  "H:11111110010:L:",
+  "H:11111110011:M:",
+  "H:111111100011:w:",
+  "H:1111111000101:D:",
+  "H:11111110001000:ESCAPE:",
+  "H:11111110001001:I:",
+  "I:0:T:",
+  "I:100:s:",
+  "I:101:n:",
+  "I:1101:t:",
+  "I:11001: :",
+  "I:11101:':",
+  "I:11111:r:",
+  "I:110000:I:",
+  "I:110001:STOP:",
+  "I:111001:m:",
+  "I:1110000:d:",
+  "I:1110001:N:",
+  "I:1111001:z:",
+  "I:1111010:.:",
+  "I:11110000:a:",
+  "I:11110001:Y:",
+  "I:111101100:S:",
+  "I:111101110:c:",
+  "I:11110110101:D:",
+  "I:11110110110:f:",
+  "I:11110111100:l:",
+  "I:11110111111:y:",
+  "I:111101101000:V:",
+  "I:111101101110:o:",
+  "I:111101111011:F:",
+  "I:1111011010010:,:",
+  "I:1111011010011:A:",
+  "I:1111011011110:O:",
+  "I:1111011110101:g:",
+  "I:1111011111000:C:",
+  "I:1111011111001:0x3a:",
+  "I:1111011111011:v:",
+  "I:11110110111110:p:",
+  "I:11110110111111:E:",
+  "I:11110111101000:B:",
+  "I:11110111110100:k:",
+  "I:11110111110101:b:",
+  "I:1111011110100100:ESCAPE:",
+  "I:1111011110100101:R:",
+  "I:1111011110100110:L:",
+  "I:1111011110100111:G:",
+  "J:00:a:",
+  "J:01:u:",
+  "J:11:e:",
+  "J:101:o:",
+  "J:1001:i:",
+  "J:10000: :",
+  "J:100010:K:",
+  "J:1000111:STOP:",
+  "J:100011001:s:",
+  "J:100011010:F:",
+  "J:1000110000:V:",
+  "J:1000110001:':",
+  "J:1000110111:f:",
+  "J:10001101101:G:",
+  "J:100011011000:ESCAPE:",
+  "J:100011011001:D:",
+  "K:01:i:",
+  "K:11:y:",
+  "K:001:e:",
+  "K:101: :",
+  "K:0000:a:",
+  "K:1000:o:",
+  "K:00010:STOP:",
+  "K:00011:r:",
+  "K:100101:t:",
+  "K:100110:n:",
+  "K:100111:S:",
+  "K:10010011:G:",
+  "K:100100000:-:",
+  "K:100100011:O:",
+  "K:100100100:h:",
+  "K:100100101:w:",
+  "K:1001000010:1:",
+  "K:1001000011:':",
+  "K:10010001011:u:",
+  "K:100100010000:T:",
+  "K:100100010001:N:",
+  "K:100100010010:0x3a:",
+  "K:100100010011:.:",
+  "K:100100010100:,:",
+  "K:1001000101010:ESCAPE:",
+  "K:1001000101011:l:",
+  "L:00:a:",
+  "L:10:o:",
+  "L:11:i:",
+  "L:010:e:",
+  "L:0111:u:",
+  "L:01101:K:",
+  "L:0110000:l:",
+  "L:0110010:A:",
+  "L:0110011: :",
+  "L:01100011:y:",
+  "L:0110001000:L:",
+  "L:0110001001:I:",
+  "L:01100010100:C:",
+  "L:01100010101:.:",
+  "L:01100010111:STOP:",
+  "L:011000101101:':",
+  "L:0110001011000:E:",
+  "L:01100010110010:ESCAPE:",
+  "L:01100010110011:Y:",
+  "M:01:a:",
+  "M:10:o:",
+  "M:000:e:",
+  "M:111:i:",
+  "M:0010:T:",
+  "M:1100:y:",
+  "M:1101:u:",
+  "M:00110:STOP:",
+  "M:001111:c:",
+  "M:00111001:r:",
+  "M:00111010:E:",
+  "M:001110111:F:",
+  "M:0011100001:Z:",
+  "M:0011100011: :",
+  "M:0011101100:1:",
+  "M:0011101101:I:",
+  "M:00111000001:h:",
+  "M:00111000100:C:",
+  "M:001110000001:Q:",
+  "M:001110001010:K:",
+  "M:0011100010110:P:",
+  "M:00111000000000:0x3a:",
+  "M:00111000000001:.:",
+  "M:00111000000010:':",
+  "M:00111000101110:M:",
+  "M:001110000000110:ESCAPE:",
+  "M:001110000000111:w:",
+  "M:001110001011110:S:",
+  "M:001110001011111:R:",
+  "N:1:e:",
+  "N:00:o:",
+  "N:011:i:",
+  "N:0101:a:",
+  "N:01001:u:",
+  "N:010000:C:",
+  "N:01000100:E:",
+  "N:01000110:F:",
+  "N:010001110:B:",
+  "N:010001111:H:",
+  "N:0100010110:Y:",
+  "N:01000101000:G:",
+  "N:01000101001:':",
+  "N:01000101011:I:",
+  "N:01000101110:A:",
+  "N:010001010100:M:",
+  "N:010001011110: :",
+  "N:010001011111:STOP:",
+  "N:0100010101010:T:",
+  "N:01000101010110:.:",
+  "N:010001010101110:ESCAPE:",
+  "N:010001010101111:Z:",
+  "O:000:':",
+  "O:010:f:",
+  "O:110:u:",
+  "O:111:n:",
+  "O:0010:M:",
+  "O:0011:l:",
+  "O:1001:m:",
+  "O:01101:r:",
+  "O:01110:d:",
+  "O:10000:p:",
+  "O:10100:h:",
+  "O:10110:STOP:",
+  "O:011001:S:",
+  "O:011110:z:",
+  "O:011111:b:",
+  "O:100011:v:",
+  "O:101010:w:",
+  "O:101011:U:",
+  "O:1011100:T:",
+  "O:1011101:O:",
+  "O:1011110:K:",
+  "O:01100001:C:",
+  "O:01100010:x:",
+  "O:01100011:.:",
+  "O:10001001:t:",
+  "O:10001011: :",
+  "O:10111110:s:",
+  "O:10111111:N:",
+  "O:011000001:g:",
+  "O:100010000:-:",
+  "O:100010101:a:",
+  "O:1000100010:i:",
+  "O:1000100011:e:",
+  "O:1000101001:o:",
+  "O:01100000000:A:",
+  "O:01100000001:j:",
+  "O:01100000010:c:",
+  "O:10001010000:2:",
+  "O:011000000111:R:",
+  "O:100010100010:P:",
+  "O:100010100011:0x3a:",
+  "O:0110000001100:E:",
+  "O:01100000011010:ESCAPE:",
+  "O:01100000011011:L:",
+  "P:01:r:",
+  "P:10:l:",
+  "P:000:e:",
+  "P:001:a:",
+  "P:111:o:",
+  "P:1101:i:",
+  "P:110000:D:",
+  "P:110001:u:",
+  "P:110011:h:",
+  "P:11001000: :",
+  "P:11001010:2:",
+  "P:110010010:H:",
+  "P:110010011:M:",
+  "P:110010110:S:",
+  "P:11001011100:0x3a:",
+  "P:11001011101:*:",
+  "P:110010111101:s:",
+  "P:1100101111001:I:",
+  "P:1100101111100:STOP:",
+  "P:1100101111101:G:",
+  "P:1100101111110:':",
+  "P:11001011111110:y:",
+  "P:110010111100000:Y:",
+  "P:110010111100001:L:",
+  "P:110010111100010:C:",
+  "P:110010111100011:ESCAPE:",
+  "P:110010111111110:O:",
+  "P:110010111111111:.:",
+  "Q:1:u:",
+  "Q:000:I:",
+  "Q:001:STOP:",
+  "Q:010:V:",
+  "Q:0111: :",
+  "Q:01101:C:",
+  "Q:011000:ESCAPE:",
+  "Q:011001:':",
+  "R:00:a:",
+  "R:01:o:",
+  "R:11:e:",
+  "R:100:i:",
+  "R:1011:u:",
+  "R:10101:E:",
+  "R:101000:D:",
+  "R:1010011:STOP:",
+  "R:10100101:h:",
+  "R:1010010000:I:",
+  "R:1010010010:y:",
+  "R:1010010011:n:",
+  "R:101001000110: :",
+  "R:1010010001000:':",
+  "R:1010010001011:S:",
+  "R:1010010001110:N:",
+  "R:10100100010010:B:",
+  "R:10100100010011:.:",
+  "R:10100100010100:&:",
+  "R:10100100011110:T:",
+  "R:10100100011111:1:",
+  "R:101001000101010:ESCAPE:",
+  "R:101001000101011:C:",
+  "S:001:o:",
+  "S:010:p:",
+  "S:011:u:",
+  "S:110:h:",
+  "S:111:t:",
+  "S:0001:a:",
+  "S:1001:e:",
+  "S:1011:c:",
+  "S:00000:n:",
+  "S:10001:i:",
+  "S:10101:k:",
+  "S:000011:w:",
+  "S:101000:m:",
+  "S:0000101:A:",
+  "S:1000010:l:",
+  "S:1010010:q:",
+  "S:1010011:M:",
+  "S:00001000:2:",
+  "S:00001001:P:",
+  "S:10000000:O:",
+  "S:10000010:I:",
+  "S:10000011: :",
+  "S:10000111:STOP:",
+  "S:100000010:y:",
+  "S:100001100:E:",
+  "S:1000000111:?:",
+  "S:1000011011:H:",
+  "S:10000001100:B:",
+  "S:10000110100:g:",
+  "S:100000011011:r:",
+  "S:100001101010:*:",
+  "S:1000011010110:3:",
+  "S:1000011010111:.:",
+  "S:10000001101000:5:",
+  "S:10000001101010:0x3a:",
+  "S:10000001101011:1:",
+  "S:100000011010010:C:",
+  "S:1000000110100110:ESCAPE:",
+  "S:1000000110100111:Y:",
+  "T:0:h:",
+  "T:101:o:",
+  "T:111:V:",
+  "T:1000:e:",
+  "T:1001:r:",
+  "T:11000:a:",
+  "T:11010:w:",
+  "T:110011:i:",
+  "T:1101101:O:",
+  "T:1101111:H:",
+  "T:11001001:y:",
+  "T:11001010:M:",
+  "T:11011000:.:",
+  "T:11011100:u:",
+  "T:11011101:W:",
+  "T:110010001:P:",
+  "T:110010110:0x3a:",
+  "T:110010111:4:",
+  "T:110110011:I:",
+  "T:1101100100: :",
+  "T:1101100101:STOP:",
+  "T:11001000010:X:",
+  "T:11001000011:s:",
+  "T:110010000000:T:",
+  "T:110010000001:S:",
+  "T:110010000010:B:",
+  "T:1100100000110:U:",
+  "T:11001000001110:A:",
+  "T:1100100000111100:C:",
+  "T:1100100000111101:*:",
+  "T:1100100000111111:N:",
+  "T:11001000001111100:ESCAPE:",
+  "T:11001000001111101:Y:",
+  "U:0:n:",
+  "U:10:p:",
+  "U:1101:K:",
+  "U:1111:l:",
+  "U:11000:R:",
+  "U:11100:S:",
+  "U:110011:E:",
+  "U:111011:s:",
+  "U:1100101:g:",
+  "U:1110101:T:",
+  "U:11001001: :",
+  "U:110010000:-:",
+  "U:110010001:r:",
+  "U:111010000:2:",
+  "U:111010001:m:",
+  "U:111010011:STOP:",
+  "U:1110100100:.:",
+  "U:11101001010:c:",
+  "U:111010010110:k:",
+  "U:11101001011100:ESCAPE:",
+  "U:11101001011101:z:",
+  "U:11101001011110:t:",
+  "U:11101001011111:B:",
+  "V:1: :",
+  "V:000:0x3a:",
+  "V:011:i:",
+  "V:0010:e:",
+  "V:0011:a:",
+  "V:0100:3:",
+  "V:010101:C:",
+  "V:010111:STOP:",
+  "V:0101000:':",
+  "V:0101001:4:",
+  "V:0101101:o:",
+  "V:01011001:I:",
+  "V:0101100000:s:",
+  "V:0101100001:D:",
+  "V:0101100010:.:",
+  "V:01011000110:8:",
+  "V:0101100011101:u:",
+  "V:0101100011110:r:",
+  "V:0101100011111:B:",
+  "V:01011000111000:ESCAPE:",
+  "V:01011000111001:E:",
+  "W:01:o:",
+  "W:11:e:",
+  "W:001:h:",
+  "W:100:a:",
+  "W:101:i:",
+  "W:00000:.:",
+  "W:00010:O:",
+  "W:00011:r:",
+  "W:000011:y:",
+  "W:0000100:u:",
+  "W:00001010:STOP:",
+  "W:000010111:A:",
+  "W:00001011001:Y:",
+  "W:00001011010:T:",
+  "W:00001011011: :",
+  "W:000010110000:I:",
+  "W:0000101100010:ESCAPE:",
+  "W:0000101100011:l:",
+  "X:00:STOP:",
+  "X:10: :",
+  "X:11:t:",
+  "X:010:T:",
+  "X:0111:c:",
+  "X:01101:m:",
+  "X:011001:U:",
+  "X:01100000:a:",
+  "X:01100001:X:",
+  "X:01100010:-:",
+  "X:011000110:x:",
+  "X:0110001111:9:",
+  "X:01100011100:ESCAPE:",
+  "X:01100011101:i:",
+  "Y:1:o:",
+  "Y:01:e:",
+  "Y:000:u:",
+  "Y:0011: :",
+  "Y:00100:v:",
+  "Y:001010:a:",
+  "Y:00101110:P:",
+  "Y:00101111:':",
+  "Y:001011000:n:",
+  "Y:001011011:r:",
+  "Y:0010110010:D:",
+  "Y:00101100110:w:",
+  "Y:00101100111:s:",
+  "Y:00101101000:R:",
+  "Y:00101101001:L:",
+  "Y:00101101010:STOP:",
+  "Y:001011010110:C:",
+  "Y:0010110101110:ESCAPE:",
+  "Y:0010110101111:N:",
+  "Z:1:o:",
+  "Z:00:a:",
+  "Z:010:i:",
+  "Z:01100:O:",
+  "Z:01101:u:",
+  "Z:01110:e:",
+  "Z:011110: :",
+  "Z:0111111:STOP:",
+  "Z:01111101:0x3a:",
+  "Z:011111000:ESCAPE:",
+  "Z:011111001:-:",
+  "[:0:ESCAPE:",
+  "[:1:ESCAPE:",
+  "\\:0:ESCAPE:",
+  "\\:1:x:",
+  "]:0:ESCAPE:",
+  "]:1:ESCAPE:",
+  "^:0:ESCAPE:",
+  "^:1:ESCAPE:",
+  "_:0:ESCAPE:",
+  "_:1:ESCAPE:",
+  "`:0:ESCAPE:",
+  "`:1:ESCAPE:",
+  "a:001:r:",
+  "a:011:t:",
+  "a:100:l:",
+  "a:110:n:",
+  "a:0001:m:",
+  "a:0100:c:",
+  "a:1010:s:",
+  "a:1110:y:",
+  "a:10110: :",
+  "a:10111:d:",
+  "a:11110:i:",
+  "a:11111:k:",
+  "a:000010:b:",
+  "a:000011:STOP:",
+  "a:010110:p:",
+  "a:010111:g:",
+  "a:0000000:e:",
+  "a:0000001:':",
+  "a:0000011:w:",
+  "a:0101001:u:",
+  "a:0101010:z:",
+  "a:0101011:v:",
+  "a:00000101:f:",
+  "a:01010001:h:",
+  "a:000001001:0x3a:",
+  "a:0000010000:!:",
+  "a:0101000000:o:",
+  "a:0101000001:x:",
+  "a:00000100010:-:",
+  "a:00000100011:a:",
+  "a:01010000101:.:",
+  "a:01010000110:N:",
+  "a:01010000111:,:",
+  "a:010100001000:q:",
+  "a:0101000010010:j:",
+  "a:01010000100111:?:",
+  "a:010100001001101:J:",
+  "a:0101000010011000:ESCAPE:",
+  "a:0101000010011001:U:",
+  "b:000:r:",
+  "b:001:o:",
+  "b:010:e:",
+  "b:011:a:",
+  "b:100:i:",
+  "b:1011:u:",
+  "b:1100:y:",
+  "b:1101:l:",
+  "b:1111: :",
+  "b:10101:s:",
+  "b:11100:b:",
+  "b:11101:STOP:",
+  "b:101000:h:",
+  "b:1010010:3:",
+  "b:10100111:':",
+  "b:1010011001:t:",
+  "b:1010011010:j:",
+  "b:10100110000:n:",
+  "b:10100110001:d:",
+  "b:10100110111:w:",
+  "b:101001101101:m:",
+  "b:1010011011001:.:",
+  "b:10100110110000:ESCAPE:",
+  "b:10100110110001:0x3a:",
+  "c:00:k:",
+  "c:010:o:",
+  "c:100:h:",
+  "c:110:t:",
+  "c:111:e:",
+  "c:0111:r:",
+  "c:10100: :",
+  "c:10110:i:",
+  "c:10111:a:",
+  "c:011000:l:",
+  "c:011001:y:",
+  "c:011010:s:",
+  "c:011011:STOP:",
+  "c:1010100:c:",
+  "c:1010111:u:",
+  "c:10101010:0x3a:",
+  "c:10101011:P:",
+  "c:101011001:D:",
+  "c:1010110100:G:",
+  "c:1010110110:b:",
+  "c:10101100000:L:",
+  "c:10101100001:K:",
+  "c:10101100011:A:",
+  "c:10101101010:q:",
+  "c:10101101110:.:",
+  "c:10101101111:C:",
+  "c:101011000100:n:",
+  "c:101011000101:':",
+  "c:1010110101100:B:",
+  "c:1010110101101:I:",
+  "c:10101101011101:f:",
+  "c:10101101011110:8:",
+  "c:101011010111000:M:",
+  "c:101011010111001:ESCAPE:",
+  "c:101011010111111:F:",
+  "c:1010110101111100:w:",
+  "c:1010110101111101:Q:",
+  "d:11: :",
+  "d:001:e:",
+  "d:100:STOP:",
+  "d:101:a:",
+  "d:0001:y:",
+  "d:0100:i:",
+  "d:0110:s:",
+  "d:00000:o:",
+  "d:01010:d:",
+  "d:000011:u:",
+  "d:010110:r:",
+  "d:010111:l:",
+  "d:011101:v:",
+  "d:011110:g:",
+  "d:0000100:':",
+  "d:0111111:.:",
+  "d:00001010:0x3a:",
+  "d:00001011:h:",
+  "d:01110000:c:",
+  "d:01110010:n:",
+  "d:01110011:w:",
+  "d:011100010:?:",
+  "d:011111000:!:",
+  "d:011111001:-:",
+  "d:011111010:f:",
+  "d:0111000111:m:",
+  "d:0111110110:,:",
+  "d:01111101110:t:",
+  "d:01111101111:b:",
+  "d:011100011001:):",
+  "d:011100011010:/:",
+  "d:011100011011:k:",
+  "d:0111000110001:p:",
+  "d:01110001100001:z:",
+  "d:011100011000000:ESCAPE:",
+  "d:011100011000001:4:",
+  "e:01: :",
+  "e:000:s:",
+  "e:101:r:",
+  "e:0010:t:",
+  "e:1001:n:",
+  "e:1100:STOP:",
+  "e:1110:a:",
+  "e:1111:w:",
+  "e:10000:l:",
+  "e:11011:e:",
+  "e:001110:m:",
+  "e:100010:c:",
+  "e:100011:d:",
+  "e:0011010:i:",
+  "e:0011011:p:",
+  "e:0011110:b:",
+  "e:1101000:v:",
+  "e:1101011:y:",
+  "e:00110000:g:",
+  "e:00110001:f:",
+  "e:00110010:x:",
+  "e:00111110:k:",
+  "e:00111111:0x3a:",
+  "e:11010011:o:",
+  "e:11010100:':",
+  "e:001100111:h:",
+  "e:110100101:.:",
+  "e:0011001100:P:",
+  "e:0011001101:B:",
+  "e:1101001000:,:",
+  "e:1101010100:V:",
+  "e:1101010101:z:",
+  "e:1101010111:j:",
+  "e:11010010010:4:",
+  "e:11010010011:?:",
+  "e:11010101101:u:",
+  "e:110101011001:-:",
+  "e:1101010110001:!:",
+  "e:11010101100001:q:",
+  "e:110101011000001:G:",
+  "e:1101010110000000:ESCAPE:",
+  "e:1101010110000001:S:",
+  "f:0: :",
+  "f:101:o:",
+  "f:1001:t:",
+  "f:1100:a:",
+  "f:1101:i:",
+  "f:1111:e:",
+  "f:10000:.:",
+  "f:11100:r:",
+  "f:11101:f:",
+  "f:100010:STOP:",
+  "f:10001101:y:",
+  "f:10001111:u:",
+  "f:100011000:':",
+  "f:100011101:l:",
+  "f:1000110011:n:",
+  "f:1000111000:g:",
+  "f:10001100100:c:",
+  "f:10001110010:-:",
+  "f:100011001010:,:",
+  "f:100011001011:s:",
+  "f:100011100111:0x3a:",
+  "f:1000111001101:k:",
+  "f:10001110011000:ESCAPE:",
+  "f:10001110011001:b:",
+  "g:00:h:",
+  "g:10: :",
+  "g:010:STOP:",
+  "g:011:e:",
+  "g:1100:i:",
+  "g:11100:0x3a:",
+  "g:11101:r:",
+  "g:11111:a:",
+  "g:110100:s:",
+  "g:110111:l:",
+  "g:111101:u:",
+  "g:1101011:b:",
+  "g:1101100:g:",
+  "g:1101101:o:",
+  "g:1111001:n:",
+  "g:11010100:2:",
+  "g:11110000:!:",
+  "g:111100011:d:",
+  "g:1101010100:.:",
+  "g:1101010101:,:",
+  "g:1101010110:':",
+  "g:1101010111:t:",
+  "g:1111000101:y:",
+  "g:11110001000:w:",
+  "g:111100010011:m:",
+  "g:11110001001011:?:",
+  "g:111100010010000:p:",
+  "g:111100010010001:f:",
+  "g:111100010010010:@:",
+  "g:111100010010011:-:",
+  "g:111100010010101:;:",
+  "g:1111000100101000:ESCAPE:",
+  "g:1111000100101001:z:",
+  "h:0:e:",
+  "h:101:o:",
+  "h:1001:i:",
+  "h:1100:a:",
+  "h:1110: :",
+  "h:1111:t:",
+  "h:11010:r:",
+  "h:11011:STOP:",
+  "h:100000:b:",
+  "h:100001:u:",
+  "h:10001000:w:",
+  "h:10001001:d:",
+  "h:10001010:n:",
+  "h:10001011:y:",
+  "h:10001100:!:",
+  "h:10001101:l:",
+  "h:10001111:.:",
+  "h:100011100:':",
+  "h:1000111010:s:",
+  "h:10001110110:m:",
+  "h:100011101111:0x3a:",
+  "h:10001110111000:f:",
+  "h:10001110111001:?:",
+  "h:10001110111010:c:",
+  "h:1000111011101100:v:",
+  "h:1000111011101101:q:",
+  "h:1000111011101110:g:",
+  "h:100011101110111100:h:",
+  "h:100011101110111101:ESCAPE:",
+  "h:100011101110111110:,:",
+  "h:100011101110111111:*:",
+  "i:01:n:",
+  "i:000:c:",
+  "i:1001:o:",
+  "i:1010:l:",
+  "i:1100:g:",
+  "i:1101:s:",
+  "i:1110:t:",
+  "i:1111:e:",
+  "i:00101:a:",
+  "i:00110:v:",
+  "i:10000:r:",
+  "i:10001:d:",
+  "i:10110:m:",
+  "i:001000:p:",
+  "i:001110: :",
+  "i:101111:f:",
+  "i:0011110:z:",
+  "i:0011111:STOP:",
+  "i:1011100:b:",
+  "i:1011101:k:",
+  "i:00100101:-:",
+  "i:00100110:x:",
+  "i:001001001:':",
+  "i:001001111:q:",
+  "i:0010011100:u:",
+  "i:0010011101:i:",
+  "i:00100100001:h:",
+  "i:00100100010:0x3a:",
+  "i:00100100011:w:",
+  "i:0010010000001:,:",
+  "i:0010010000010:y:",
+  "i:0010010000011:/:",
+  "i:00100100000000:.:",
+  "i:001001000000010:ESCAPE:",
+  "i:001001000000011:j:",
+  "j:0:y:",
+  "j:11:o:",
+  "j:101:e:",
+  "j:1001:a:",
+  "j:10001:u:",
+  "j:100001:i:",
+  "j:1000000:STOP:",
+  "j:10000010:ESCAPE:",
+  "j:10000011: :",
+  "k:00: :",
+  "k:10:e:",
+  "k:010:i:",
+  "k:110:STOP:",
+  "k:0110:y:",
+  "k:0111:s:",
+  "k:1111:f:",
+  "k:111001:a:",
+  "k:111010:l:",
+  "k:1110001:0x3a:",
+  "k:1110110:k:",
+  "k:11100000:':",
+  "k:11101111:.:",
+  "k:111000011:w:",
+  "k:111011100:o:",
+  "k:1110000101:h:",
+  "k:11100001000:b:",
+  "k:11100001001:,:",
+  "k:11101110111:n:",
+  "k:111011101010:?:",
+  "k:111011101100:m:",
+  "k:111011101101:!:",
+  "k:1110111010010:u:",
+  "k:1110111010011:c:",
+  "k:1110111010110:d:",
+  "k:1110111010111:t:",
+  "k:11101110100001:j:",
+  "k:11101110100010:-:",
+  "k:111011101000000:p:",
+  "k:111011101000001:/:",
+  "k:111011101000111:S:",
+  "k:1110111010001100:ESCAPE:",
+  "k:1110111010001101:r:",
+  "l:01:e:",
+  "l:000:l:",
+  "l:101:a:",
+  "l:0011:y:",
+  "l:1000:STOP:",
+  "l:1001:d:",
+  "l:1100:o:",
+  "l:1110:i:",
+  "l:1111: :",
+  "l:00100:u:",
+  "l:11010:s:",
+  "l:001010:t:",
+  "l:001011:m:",
+  "l:1101101:k:",
+  "l:11011000:f:",
+  "l:11011100:b:",
+  "l:11011110:':",
+  "l:11011111:c:",
+  "l:110110011:v:",
+  "l:110111010:0x3a:",
+  "l:1101100101:.:",
+  "l:1101110110:w:",
+  "l:11011001000:z:",
+  "l:11011101111:p:",
+  "l:110110010010:h:",
+  "l:110110010011:*:",
+  "l:1101110111000:g:",
+  "l:1101110111001:,:",
+  "l:11011101110100:r:",
+  "l:11011101110101:n:",
+  "l:11011101110111:-:",
+  "l:110111011101100:!:",
+  "l:1101110111011011:?:",
+  "l:11011101110110101:C:",
+  "l:110111011101101000:ESCAPE:",
+  "l:110111011101101001:j:",
+  "m:10:e:",
+  "m:001:m:",
+  "m:011: :",
+  "m:111:a:",
+  "m:0000:i:",
+  "m:0001:STOP:",
+  "m:0100:y:",
+  "m:1101:p:",
+  "m:01010:b:",
+  "m:11000:o:",
+  "m:110010:n:",
+  "m:110011:s:",
+  "m:0101100:l:",
+  "m:0101110:f:",
+  "m:01011010:0x3a:",
+  "m:01011110:4:",
+  "m:010110110:h:",
+  "m:010111110:w:",
+  "m:0101101111:':",
+  "m:0101111110:r:",
+  "m:0101111111:u:",
+  "m:01011011101:.:",
+  "m:010110111001:k:",
+  "m:0101101110000:ESCAPE:",
+  "m:0101101110001:d:",
+  "n:000:i:",
+  "n:100:g:",
+  "n:101: :",
+  "n:110:d:",
+  "n:0011:a:",
+  "n:0100:s:",
+  "n:0110:e:",
+  "n:1110:STOP:",
+  "n:1111:t:",
+  "n:01110:c:",
+  "n:01111:n:",
+  "n:001010:y:",
+  "n:010100:':",
+  "n:010101:k:",
+  "n:010111:o:",
+  "n:0010000:r:",
+  "n:0010011:f:",
+  "n:0010110:u:",
+  "n:0010111:j:",
+  "n:00100010:v:",
+  "n:00100100:-:",
+  "n:00100101:.:",
+  "n:01011000:l:",
+  "n:01011010:x:",
+  "n:01011011:0x3a:",
+  "n:001000111:,:",
+  "n:010110011:m:",
+  "n:0010001100:!:",
+  "n:00100011010:z:",
+  "n:01011001001:?:",
+  "n:01011001010:h:",
+  "n:01011001011:b:",
+  "n:001000110110:B:",
+  "n:001000110111:*:",
+  "n:010110010000:w:",
+  "n:0101100100011:q:",
+  "n:01011001000101:p:",
+  "n:010110010001000:;:",
+  "n:0101100100010010:/:",
+  "n:0101100100010011:ESCAPE:",
+  "o:00:r:",
+  "o:110:n:",
+  "o:0100:f:",
+  "o:0101: :",
+  "o:0110:w:",
+  "o:1000:o:",
+  "o:1011:u:",
+  "o:01111:t:",
+  "o:10010:c:",
+  "o:10100:p:",
+  "o:10101:d:",
+  "o:11100:m:",
+  "o:11110:l:",
+  "o:011100:a:",
+  "o:011101:b:",
+  "o:100110:y:",
+  "o:100111:STOP:",
+  "o:111010:s:",
+  "o:111011:k:",
+  "o:1111101:v:",
+  "o:1111110:g:",
+  "o:11111111:i:",
+  "o:111110001:h:",
+  "o:111110010:!:",
+  "o:111111100:e:",
+  "o:111111101:j:",
+  "o:1111100110:':",
+  "o:11111000001:?:",
+  "o:11111000010:0x3a:",
+  "o:11111001110:z:",
+  "o:11111001111:x:",
+  "o:111110000000:J:",
+  "o:111110000110:.:",
+  "o:111110000111:-:",
+  "o:11111000000100:4:",
+  "o:11111000000110:,:",
+  "o:11111000000111:G:",
+  "o:111110000001011:):",
+  "o:1111100000010100:S:",
+  "o:11111000000101010:D:",
+  "o:111110000001010110:ESCAPE:",
+  "o:111110000001010111:q:",
+  "p:00:e:",
+  "p:010:STOP:",
+  "p:100:i:",
+  "p:110:o:",
+  "p:0110:s:",
+  "p:1010: :",
+  "p:1110:p:",
+  "p:01110:l:",
+  "p:01111:r:",
+  "p:10110:h:",
+  "p:11110:a:",
+  "p:101110:t:",
+  "p:101111:':",
+  "p:1111100:d:",
+  "p:1111101:m:",
+  "p:1111110:y:",
+  "p:111111101:0x3a:",
+  "p:111111111:!:",
+  "p:1111111100:w:",
+  "p:1111111101:u:",
+  "p:11111110000:b:",
+  "p:11111110010:-:",
+  "p:11111110011:.:",
+  "p:111111100011:n:",
+  "p:1111111000101:k:",
+  "p:11111110001001:,:",
+  "p:111111100010000:ESCAPE:",
+  "p:111111100010001:c:",
+  "q:1:u:",
+  "q:01:STOP:",
+  "q:001:0x3a:",
+  "q:0000:ESCAPE:",
+  "q:0001:':",
+  "r:000: :",
+  "r:011:i:",
+  "r:101:e:",
+  "r:0011:y:",
+  "r:0100:d:",
+  "r:1000:s:",
+  "r:1001:t:",
+  "r:1100:a:",
+  "r:1101:STOP:",
+  "r:1111:o:",
+  "r:01011:n:",
+  "r:11101:l:",
+  "r:001001:k:",
+  "r:001010:r:",
+  "r:001011:m:",
+  "r:010101:u:",
+  "r:111001:g:",
+  "r:0010000:':",
+  "r:0101001:c:",
+  "r:1110001:0x3a:",
+  "r:00100010:f:",
+  "r:00100011:.:",
+  "r:01010001:b:",
+  "r:11100000:v:",
+  "r:010100000:,:",
+  "r:010100001:p:",
+  "r:111000010:w:",
+  "r:1110000111:j:",
+  "r:11100001100:-:",
+  "r:111000011010:h:",
+  "r:1110000110110:G:",
+  "r:11100001101110:q:",
+  "r:111000011011111:S:",
+  "r:1110000110111100:!:",
+  "r:111000011011110100:*:",
+  "r:111000011011110110:T:",
+  "r:1110000110111101010:ESCAPE:",
+  "r:1110000110111101011:E:",
+  "r:1110000110111101110:1:",
+  "r:1110000110111101111:/:",
+  "s:10: :",
+  "s:11:STOP:",
+  "s:011:t:",
+  "s:0000:s:",
+  "s:0010:i:",
+  "s:0011:h:",
+  "s:00011:;:",
+  "s:01010:e:",
+  "s:010001:o:",
+  "s:010011:c:",
+  "s:010110:0x3a:",
+  "s:0001000:.:",
+  "s:0001001:!:",
+  "s:0001011:y:",
+  "s:0100000:p:",
+  "s:0100100:a:",
+  "s:0101111:u:",
+  "s:00010100:,:",
+  "s:00010101:f:",
+  "s:01000011:':",
+  "s:01001011:n:",
+  "s:01011100:l:",
+  "s:01011101:r:",
+  "s:010000101:k:",
+  "s:010010100:d:",
+  "s:0100001001:m:",
+  "s:0100101011:b:",
+  "s:01000010000:?:",
+  "s:01000010001:w:",
+  "s:01001010100:g:",
+  "s:010010101010:q:",
+  "s:01001010101101:E:",
+  "s:01001010101110:-:",
+  "s:010010101011000:ESCAPE:",
+  "s:010010101011001:):",
+  "s:010010101011110:W:",
+  "s:010010101011111:1:",
+  "t:000:i:",
+  "t:011:STOP:",
+  "t:100: :",
+  "t:111:h:",
+  "t:0010:a:",
+  "t:0100:r:",
+  "t:1010:s:",
+  "t:1011:o:",
+  "t:1101:e:",
+  "t:00111:t:",
+  "t:01010:y:",
+  "t:11000:u:",
+  "t:010110:m:",
+  "t:110010:c:",
+  "t:110011:l:",
+  "t:0011000:':",
+  "t:0011010:0x3a:",
+  "t:00110010:w:",
+  "t:00110110:!:",
+  "t:01011100:.:",
+  "t:01011101:b:",
+  "t:01011110:E:",
+  "t:01011111:f:",
+  "t:001100110:?:",
+  "t:001101110:n:",
+  "t:0011001110:z:",
+  "t:0011011110:d:",
+  "t:00110011111:,:",
+  "t:00110111110:P:",
+  "t:001100111100:v:",
+  "t:001100111101:-:",
+  "t:001101111110:):",
+  "t:0011011111110:g:",
+  "t:00110111111110:ESCAPE:",
+  "t:001101111111110:S:",
+  "t:0011011111111111:4:",
+  "t:00110111111111100:k:",
+  "t:001101111111111010:j:",
+  "t:001101111111111011:p:",
+  "u:00:r:",
+  "u:100:s:",
+  "u:111:n:",
+  "u:0100:e:",
+  "u:0101:m:",
+  "u:1100:t:",
+  "u:01100:c:",
+  "u:01101:g:",
+  "u:01110:b:",
+  "u:10100:p:",
+  "u:10101:i:",
+  "u:10110:l:",
+  "u:11010:d:",
+  "u:11011:a:",
+  "u:011110:STOP:",
+  "u:101110:y:",
+  "u:0111110:z:",
+  "u:1011110: :",
+  "u:01111111:':",
+  "u:10111110:-:",
+  "u:011111100:k:",
+  "u:101111111:0x3a:",
+  "u:0111111010:f:",
+  "u:0111111011:,:",
+  "u:1011111100:w:",
+  "u:101111110100:v:",
+  "u:101111110101:x:",
+  "u:101111110111:o:",
+  "u:1011111101100:j:",
+  "u:10111111011010:u:",
+  "u:101111110110110:.:",
+  "u:1011111101101111:h:",
+  "u:10111111011011100:?:",
+  "u:10111111011011101:ESCAPE:",
+  "v:1:e:",
+  "v:01:i:",
+  "v:001:a:",
+  "v:0001:o:",
+  "v:00000: :",
+  "v:000011:STOP:",
+  "v:0000100:y:",
+  "v:00001011:s:",
+  "v:000010101:r:",
+  "v:0000101000:ESCAPE:",
+  "v:0000101001:.:",
+  "w:0:s:",
+  "w:100: :",
+  "w:110:STOP:",
+  "w:1011:i:",
+  "w:1110:o:",
+  "w:10100:a:",
+  "w:11110:n:",
+  "w:11111:e:",
+  "w:1010111:y:",
+  "w:10101000:m:",
+  "w:10101011:d:",
+  "w:10101101:l:",
+  "w:101010011:b:",
+  "w:101010100:k:",
+  "w:101010101:r:",
+  "w:1010100100:j:",
+  "w:1010110001:,:",
+  "w:1010110011:h:",
+  "w:10101001011:-:",
+  "w:10101100000:c:",
+  "w:10101100001:f:",
+  "w:10101100101:p:",
+  "w:101010010100:g:",
+  "w:101011001000:t:",
+  "w:1010100101010:.:",
+  "w:1010100101011:0x3a:",
+  "w:1010110010011:q:",
+  "w:10101100100101:':",
+  "w:101011001001001:?:",
+  "w:1010110010010000:ESCAPE:",
+  "w:1010110010010001:B:",
+  "x:00:p:",
+  "x:10: :",
+  "x:11:t:",
+  "x:0110:STOP:",
+  "x:01000:o:",
+  "x:01010:c:",
+  "x:01110:i:",
+  "x:01111:m:",
+  "x:010010:e:",
+  "x:010110:y:",
+  "x:0100110:u:",
+  "x:0100111:f:",
+  "x:0101111:,:",
+  "x:010111000:g:",
+  "x:010111001:a:",
+  "x:010111011:9:",
+  "x:0101110101:':",
+  "x:01011101001:x:",
+  "x:010111010000:ESCAPE:",
+  "x:010111010001:s:",
+  "y:0: :",
+  "y:11:STOP:",
+  "y:10001:o:",
+  "y:10010:s:",
+  "y:10100:a:",
+  "y:10110:l:",
+  "y:10111:0x3a:",
+  "y:100110:d:",
+  "y:1000001:n:",
+  "y:1000010:t:",
+  "y:1010100:':",
+  "y:1010101:b:",
+  "y:1010111:.:",
+  "y:10000000:i:",
+  "y:10000110:,:",
+  "y:10000111:p:",
+  "y:10011100:m:",
+  "y:10011110:c:",
+  "y:10101100:w:",
+  "y:10101101:e:",
+  "y:100000010:?:",
+  "y:100000011:f:",
+  "y:100111010:r:",
+  "y:100111011:g:",
+  "y:1001111100:z:",
+  "y:1001111110:-:",
+  "y:1001111111:T:",
+  "y:100111110100:2:",
+  "y:100111110110:!:",
+  "y:100111110111:k:",
+  "y:1001111101010:v:",
+  "y:10011111010110:y:",
+  "y:100111110101110:h:",
+  "y:1001111101011111:j:",
+  "y:10011111010111100:ESCAPE:",
+  "y:10011111010111101:):",
+  "z:00:z:",
+  "z:01:STOP:",
+  "z:101:i:",
+  "z:1000:y:",
+  "z:1001:e:",
+  "z:1100:w:",
+  "z:1101: :",
+  "z:1110:l:",
+  "z:11110:a:",
+  "z:111110:o:",
+  "z:11111100:m:",
+  "z:11111101:0x3a:",
+  "z:11111111:c:",
+  "z:111111100:,:",
+  "z:1111111011:b:",
+  "z:11111110100:u:",
+  "z:111111101011:!:",
+  "z:11111110101000:ESCAPE:",
+  "z:11111110101001:t:",
+  "z:11111110101010:h:",
+  "z:11111110101011:?:",
+  "{:0:ESCAPE:",
+  "{:1:ESCAPE:",
+  "|:0:ESCAPE:",
+  "|:1:ESCAPE:",
+  "}:0:ESCAPE:",
+  "}:1:ESCAPE:",
+  "~:0:ESCAPE:",
+  "~:1:ESCAPE:",
+  "0x7f:0:ESCAPE:",
+  "0x7f:1:ESCAPE:",
+  NULL
+};
+
+static const char *FreesatT2[] = {
+  "START:010:A:",
+  "START:100:C:",
+  "START:111:T:",
+  "START:0001:J:",
+  "START:0011:D:",
+  "START:1010:S:",
+  "START:00000:H:",
+  "START:00100:I:",
+  "START:00101:R:",
+  "START:01101:F:",
+  "START:01110:.:",
+  "START:01111:W:",
+  "START:10111:M:",
+  "START:11000:B:",
+  "START:11001:P:",
+  "START:11011:N:",
+  "START:000010:O:",
+  "START:011001:[:",
+  "START:101101:L:",
+  "START:110101:E:",
+  "START:0000110:K:",
+  "START:1101000:Y:",
+  "START:1101001:G:",
+  "START:00001110:2:",
+  "START:01100000:p:",
+  "START:01100001:b:",
+  "START:01100010:U:",
+  "START:01100011:(:",
+  "START:10110000:1:",
+  "START:10110011:V:",
+  "START:000011110:Q:",
+  "START:101100010:3:",
+  "START:0000111110:9:",
+  "START:0000111111:8:",
+  "START:1011000110:6:",
+  "START:1011000111:5:",
+  "START:1011001000:Z:",
+  "START:1011001001:7:",
+  "START:1011001010:4:",
+  "START:101100101110:X:",
+  "START:101100101111: :",
+  "START:1011001011001:w:",
+  "START:1011001011010:':",
+  "START:1011001011011:\":",
+  "START:10110010110000:t:",
+  "START:101100101100010:a:",
+  "START:1011001011000110:`:",
+  "START:10110010110001110:ESCAPE:",
+  "START:10110010110001111:m:",
+  "ESCAPE:0:ESCAPE:",
+  "ESCAPE:1:ESCAPE:",
+  "STOP:0:ESCAPE:",
+  "STOP:1:ESCAPE:",
+  "0x03:0:ESCAPE:",
+  "0x03:1:ESCAPE:",
+  "0x04:0:ESCAPE:",
+  "0x04:1:ESCAPE:",
+  "0x05:0:ESCAPE:",
+  "0x05:1:ESCAPE:",
+  "0x06:0:ESCAPE:",
+  "0x06:1:ESCAPE:",
+  "0x07:0:ESCAPE:",
+  "0x07:1:ESCAPE:",
+  "0x08:0:ESCAPE:",
+  "0x08:1:ESCAPE:",
+  "0x09:0:ESCAPE:",
+  "0x09:1:ESCAPE:",
+  "0x0a:0:ESCAPE:",
+  "0x0a:1:ESCAPE:",
+  "0x0b:0:ESCAPE:",
+  "0x0b:1:ESCAPE:",
+  "0x0c:0:ESCAPE:",
+  "0x0c:1:ESCAPE:",
+  "0x0d:0:ESCAPE:",
+  "0x0d:1:ESCAPE:",
+  "0x0e:0:ESCAPE:",
+  "0x0e:1:ESCAPE:",
+  "0x0f:0:ESCAPE:",
+  "0x0f:1:ESCAPE:",
+  "0x10:0:ESCAPE:",
+  "0x10:1:ESCAPE:",
+  "0x11:0:ESCAPE:",
+  "0x11:1:ESCAPE:",
+  "0x12:0:ESCAPE:",
+  "0x12:1:ESCAPE:",
+  "0x13:0:ESCAPE:",
+  "0x13:1:ESCAPE:",
+  "0x14:0:ESCAPE:",
+  "0x14:1:ESCAPE:",
+  "0x15:0:ESCAPE:",
+  "0x15:1:ESCAPE:",
+  "0x16:0:ESCAPE:",
+  "0x16:1:ESCAPE:",
+  "0x17:0:ESCAPE:",
+  "0x17:1:ESCAPE:",
+  "0x18:0:ESCAPE:",
+  "0x18:1:ESCAPE:",
+  "0x19:0:ESCAPE:",
+  "0x19:1:ESCAPE:",
+  "0x1a:0:ESCAPE:",
+  "0x1a:1:ESCAPE:",
+  "0x1b:0:ESCAPE:",
+  "0x1b:1:ESCAPE:",
+  "0x1c:0:ESCAPE:",
+  "0x1c:1:ESCAPE:",
+  "0x1d:0:ESCAPE:",
+  "0x1d:1:ESCAPE:",
+  "0x1e:0:ESCAPE:",
+  "0x1e:1:ESCAPE:",
+  "0x1f:0:ESCAPE:",
+  "0x1f:1:ESCAPE:",
+  " :010:a:",
+  " :100:t:",
+  " :0001:o:",
+  " :0010:s:",
+  " :00110:d:",
+  " :01100:[:",
+  " :01111:p:",
+  " :10101:b:",
+  " :11001:c:",
+  " :11010:h:",
+  " :11100:w:",
+  " :11101:i:",
+  " :11111:f:",
+  " :000000:A:",
+  " :000011:M:",
+  " :001111:e:",
+  " :011100:B:",
+  " :011101:C:",
+  " :101000:T:",
+  " :101101:S:",
+  " :101110:g:",
+  " :110000:r:",
+  " :110110:n:",
+  " :110111:l:",
+  " :111101:m:",
+  " :0000011:v:",
+  " :0000100:G:",
+  " :0000101:N:",
+  " :0011101:y:",
+  " :0110101:H:",
+  " :0110111:L:",
+  " :1010010:J:",
+  " :1010011:F:",
+  " :1011001:R:",
+  " :1011110:u:",
+  " :1100010:D:",
+  " :1100011:W:",
+  " :1111001:P:",
+  " :00000100:k:",
+  " :00000101:O:",
+  " :01101000:-:",
+  " :01101101:1:",
+  " :10110001:K:",
+  " :10111110:j:",
+  " :11110000:I:",
+  " :11110001:E:",
+  " :001110010:q:",
+  " :001110011:U:",
+  " :011010010:V:",
+  " :011011000:Y:",
+  " :011011001: :",
+  " :101100001:2:",
+  " :101111110:STOP:",
+  " :0011100000:3:",
+  " :0011100001:8:",
+  " :0011100010:6:",
+  " :0110100111:5:",
+  " :1011000000:(:",
+  " :1011111110:7:",
+  " :00111000110:0:",
+  " :01101001100:':",
+  " :01101001101:9:",
+  " :10110000010:Z:",
+  " :10111111110:4:",
+  " :10111111111:Q:",
+  " :001110001111:X:",
+  " :1011000001100:ESCAPE:",
+  " :1011000001101:.:",
+  " :1011000001110:&:",
+  " :00111000111000:\\:",
+  " :00111000111010:@:",
+  " :00111000111011:`:",
+  " :10110000011110:\":",
+  " :10110000011111:z:",
+  " :001110001110011:$:",
+  " :0011100011100100:+:",
+  " :00111000111001011:x:",
+  " :001110001110010101:]:",
+  " :0011100011100101000:/:",
+  " :0011100011100101001:?:",
+  "!:1: :",
+  "!:01:STOP:",
+  "!:001:.:",
+  "!:0000:0x3a:",
+  "!:00011:[:",
+  "!:0001001:\":",
+  "!:0001010:/:",
+  "!:0001011:!:",
+  "!:00010000:):",
+  "!:000100010:':",
+  "!:0001000111:?:",
+  "!:00010001100:ESCAPE:",
+  "!:00010001101:]:",
+  "\":11: :",
+  "\":001:.:",
+  "\":0000:p:",
+  "\":0101:B:",
+  "\":0111:T:",
+  "\":1000:i:",
+  "\":00010:f:",
+  "\":00011:W:",
+  "\":01000:S:",
+  "\":01100:t:",
+  "\":01101:C:",
+  "\":10100:STOP:",
+  "\":10111:,:",
+  "\":010010:J:",
+  "\":100100:m:",
+  "\":101010:n:",
+  "\":101011:I:",
+  "\":0100110:E:",
+  "\":0100111:D:",
+  "\":1001010:w:",
+  "\":1001011:g:",
+  "\":1001100:b:",
+  "\":1001101:L:",
+  "\":1001110:-:",
+  "\":1011000:c:",
+  "\":1011001:H:",
+  "\":10011110:P:",
+  "\":10110100:r:",
+  "\":10110111:K:",
+  "\":100111111:l:",
+  "\":101101010:Y:",
+  "\":101101011:Q:",
+  "\":101101100:G:",
+  "\":101101101:A:",
+  "\":1001111100:ESCAPE:",
+  "\":1001111101:a:",
+  "#:0:ESCAPE:",
+  "#:1:ESCAPE:",
+  "$:0:1:",
+  "$:11:3:",
+  "$:100:4:",
+  "$:1011:2:",
+  "$:10101:7:",
+  "$:101001:5:",
+  "$:1010000:ESCAPE:",
+  "$:1010001:9:",
+  "%:1: :",
+  "%:00:ESCAPE:",
+  "%:01:,:",
+  "&:1: :",
+  "&:01:w:",
+  "&:001:B:",
+  "&:0000:E:",
+  "&:000100:2:",
+  "&:000110:A:",
+  "&:000111:R:",
+  "&:00010100:O:",
+  "&:00010101:4:",
+  "&:00010111:J:",
+  "&:000101100:ESCAPE:",
+  "&:000101101:P:",
+  "':1:s:",
+  "':001:t:",
+  "':010: :",
+  "':0000:l:",
+  "':01101:r:",
+  "':000100:n:",
+  "':000101:.:",
+  "':000110:C:",
+  "':011000:B:",
+  "':011101:A:",
+  "':0111000:d:",
+  "':0111100:v:",
+  "':00011100:S:",
+  "':00011111:p:",
+  "':01100101:D:",
+  "':01111011:i:",
+  "':01111100:c:",
+  "':01111101:m:",
+  "':01111111:,:",
+  "':000111010:f:",
+  "':000111011:g:",
+  "':011001000:F:",
+  "':011001001:h:",
+  "':011001101:H:",
+  "':011001110:N:",
+  "':011100101:R:",
+  "':011100110:STOP:",
+  "':011100111:T:",
+  "':011110101:G:",
+  "':011111101:L:",
+  "':0001111000:o:",
+  "':0001111001:K:",
+  "':0001111011:a:",
+  "':0110011001:u:",
+  "':0110011111:O:",
+  "':0111001001:I:",
+  "':0111101000:w:",
+  "':0111101001:b:",
+  "':0111111001:e:",
+  "':00011110101:?:",
+  "':01100110000:E:",
+  "':01100110001:7:",
+  "':01110010000:P:",
+  "':000111101001:W:",
+  "':011001111001:0x3a:",
+  "':011001111010:!:",
+  "':011100100011:J:",
+  "':011111100001:q:",
+  "':011111100011:M:",
+  "':0001111010001:V:",
+  "':0110011110001:9:",
+  "':0110011110111:y:",
+  "':0111001000100:8:",
+  "':0111001000101:5:",
+  "':0111111000000:6:",
+  "':0111111000101:k:",
+  "':00011110100000:2:",
+  "':00011110100001:0:",
+  "':01100111100001:Y:",
+  "':01100111101100:):",
+  "':01111110000010:j:",
+  "':01111110000011:Q:",
+  "':011001111000000:-:",
+  "':011001111000001:':",
+  "':011001111011011:z:",
+  "':011111100010000:X:",
+  "':011111100010001:U:",
+  "':011111100010010:4:",
+  "':011111100010011:3:",
+  "':0110011110110100:ESCAPE:",
+  "':0110011110110101:1:",
+  "(:01:1:",
+  "(:000:P:",
+  "(:101:t:",
+  "(:1000:2:",
+  "(:1101:5:",
+  "(:1110:N:",
+  "(:00111:T:",
+  "(:10010:p:",
+  "(:11111:c:",
+  "(:001001:a:",
+  "(:001010:S:",
+  "(:001100:R:",
+  "(:100111:e:",
+  "(:111100:J:",
+  "(:111101:A:",
+  "(:0010110:D:",
+  "(:0011011:K:",
+  "(:1001100:v:",
+  "(:1001101:s:",
+  "(:1100000:b:",
+  "(:1100010:G:",
+  "(:1100011:8:",
+  "(:1100100:M:",
+  "(:1100101:H:",
+  "(:1100110:C:",
+  "(:00100000:m:",
+  "(:00100010:o:",
+  "(:00100011:E:",
+  "(:00101110:W:",
+  "(:11000011:g:",
+  "(:11001110:L:",
+  "(:001000010:d:",
+  "(:001011111:U:",
+  "(:001101000:F:",
+  "(:001101010:f:",
+  "(:110000100:w:",
+  "(:110000101:B:",
+  "(:110011111:n:",
+  "(:0010000110:l:",
+  "(:0010000111:9:",
+  "(:0010111100:4:",
+  "(:0010111101:I:",
+  "(:0011010010:3:",
+  "(:0011010111:h:",
+  "(:1100111101:i:",
+  "(:00110100110:Z:",
+  "(:00110100111:V:",
+  "(:00110101100: :",
+  "(:11001111000:k:",
+  "(:001101011011:O:",
+  "(:110011110010:':",
+  "(:0011010110100:ESCAPE:",
+  "(:0011010110101:u:",
+  "(:1100111100110:X:",
+  "(:1100111100111:7:",
+  "):0: :",
+  "):11:.:",
+  "):101:STOP:",
+  "):1001:,:",
+  "):10000:0x3a:",
+  "):100011:;:",
+  "):1000101:!:",
+  "):10001001:(:",
+  "):1000100000:ESCAPE:",
+  "):1000100001:o:",
+  "):1000100010:?:",
+  "):1000100011:):",
+  "*:0:*:",
+  "*:100:s:",
+  "*:101: :",
+  "*:1100:m:",
+  "*:1110:t:",
+  "*:11010:g:",
+  "*:11011:k:",
+  "*:11111:d:",
+  "*:111101:y:",
+  "*:1111001:e:",
+  "*:11110000:i:",
+  "*:111100010:ESCAPE:",
+  "*:111100011:n:",
+  "+:1:n:",
+  "+:00:ESCAPE:",
+  "+:01: :",
+  ",:1: :",
+  ",:01:S:",
+  ",:001:0:",
+  ",:0001:A:",
+  ",:00000:5:",
+  ",:0000110:b:",
+  ",:0000111:3:",
+  ",:00001000:2:",
+  ",:00001001:\":",
+  ",:00001011:1:",
+  ",:0000101000:Q:",
+  ",:0000101010:':",
+  ",:00001010111:4:",
+  ",:000010100100:T:",
+  ",:000010100101:B:",
+  ",:000010100110:7:",
+  ",:000010100111:6:",
+  ",:000010101100:STOP:",
+  ",:0000101011010:ESCAPE:",
+  ",:0000101011011:i:",
+  "-:00: :",
+  "-:0100:t:",
+  "-:0101:b:",
+  "-:0110:w:",
+  "-:0111:u:",
+  "-:1001:o:",
+  "-:1010:s:",
+  "-:1011:f:",
+  "-:10000:c:",
+  "-:11011:l:",
+  "-:11101:d:",
+  "-:100010:9:",
+  "-:110000:h:",
+  "-:110010:1:",
+  "-:110011:y:",
+  "-:110101:r:",
+  "-:111000:a:",
+  "-:111100:m:",
+  "-:111110:p:",
+  "-:1000110:S:",
+  "-:1101000:e:",
+  "-:1101001:i:",
+  "-:1111011:n:",
+  "-:10001110:C:",
+  "-:11000101:W:",
+  "-:11000111:g:",
+  "-:11100101:J:",
+  "-:11100110:D:",
+  "-:11110101:2:",
+  "-:11111100:7:",
+  "-:11111110:G:",
+  "-:11111111:O:",
+  "-:100011111:H:",
+  "-:110001000:A:",
+  "-:110001100:6:",
+  "-:110001101:B:",
+  "-:111001111:M:",
+  "-:111101000:E:",
+  "-:111101001:L:",
+  "-:111111010:U:",
+  "-:111111011:k:",
+  "-:1000111100:F:",
+  "-:1100010010:j:",
+  "-:1100010011:P:",
+  "-:1110010001:q:",
+  "-:1110010010:5:",
+  "-:1110010011:T:",
+  "-:1110011101:I:",
+  "-:10001111011:K:",
+  "-:11100100000:v:",
+  "-:11100100001:Z:",
+  "-:11100111001:N:",
+  "-:100011110101:R:",
+  "-:111001110001:Y:",
+  "-:1000111101001:0:",
+  "-:10001111010000:4:",
+  "-:10001111010001:z:",
+  "-:11100111000001:V:",
+  "-:11100111000010:3:",
+  "-:11100111000011:8:",
+  "-:111001110000001:Q:",
+  "-:1110011100000000:':",
+  "-:11100111000000010:ESCAPE:",
+  "-:11100111000000011:x:",
+  ".:1: :",
+  ".:01:STOP:",
+  ".:0011:.:",
+  ".:00010:i:",
+  ".:00100:0:",
+  ".:00101:c:",
+  ".:000001:u:",
+  ".:0000000:a:",
+  ".:0000001:[:",
+  ".:0001101:3:",
+  ".:00001000:4:",
+  ".:00001110:H:",
+  ".:00011000:S:",
+  ".:00011001:W:",
+  ".:00011100:o:",
+  ".:00011110:1:",
+  ".:000010100:5:",
+  ".:000010101:L:",
+  ".:000010111:p:",
+  ".:000011000:T:",
+  ".:000011001:A:",
+  ".:000011010:M:",
+  ".:000011110:C:",
+  ".:000011111:2:",
+  ".:000111011:D:",
+  ".:000111110:B:",
+  ".:0000100100:N:",
+  ".:0000100110:t:",
+  ".:0000100111:J:",
+  ".:0000101101:R:",
+  ".:0000110111:P:",
+  ".:0001110101:s:",
+  ".:0001111111:I:",
+  ".:00001011000:r:",
+  ".:00001101100:V:",
+  ".:00011101000:w:",
+  ".:00011101001:F:",
+  ".:00011111101:G:",
+  ".:000010010100:E:",
+  ".:000010010101:0x3a:",
+  ".:000010110010:h:",
+  ".:000011011010:,:",
+  ".:000111111000:':",
+  ".:0000100101101:b:",
+  ".:0000100101110:K:",
+  ".:0000100101111:Y:",
+  ".:0000101100111:O:",
+  ".:0000110110110:-:",
+  ".:0001111110010:f:",
+  ".:0001111110011:(:",
+  ".:00001011001100:\":",
+  ".:00001101101110:y:",
+  ".:000010010110000:?:",
+  ".:000010010110001:m:",
+  ".:000010010110010:Q:",
+  ".:000011011011110:*:",
+  ".:000011011011111:&:",
+  ".:0000100101100110:U:",
+  ".:0000100101100111:;:",
+  ".:0000101100110100:8:",
+  ".:0000101100110101:6:",
+  ".:0000101100110111:k:",
+  ".:00001011001101100:d:",
+  ".:000010110011011010:ESCAPE:",
+  ".:000010110011011011:n:",
+  "/:01:c:",
+  "/:110:1:",
+  "/:111:e:",
+  "/:0000:5:",
+  "/:0010:8:",
+  "/:00010:T:",
+  "/:00011:f:",
+  "/:00110:B:",
+  "/:00111:2:",
+  "/:10001:3:",
+  "/:10010:7:",
+  "/:10100:6:",
+  "/:10110:a:",
+  "/:101111:4:",
+  "/:1000000:F:",
+  "/:1000010:s:",
+  "/:1000011:M:",
+  "/:1001100:H:",
+  "/:1001110:D:",
+  "/:1001111:A:",
+  "/:1010101:S:",
+  "/:10000011:m:",
+  "/:10011010:W:",
+  "/:10101000:G:",
+  "/:10101001:U:",
+  "/:10101100:d:",
+  "/:10101101:O:",
+  "/:10101110:N:",
+  "/:10111001:C:",
+  "/:10111011:P:",
+  "/:100110110:L:",
+  "/:101011110: :",
+  "/:101011111:I:",
+  "/:101110000:E:",
+  "/:101110001:R:",
+  "/:101110100:K:",
+  "/:101110101:t:",
+  "/:1000001001:J:",
+  "/:1000001011:9:",
+  "/:10000010000:v:",
+  "/:10000010001:p:",
+  "/:10000010100:h:",
+  "/:10011011101:o:",
+  "/:10011011110:Q:",
+  "/:10011011111:0:",
+  "/:100000101010:l:",
+  "/:100000101011:i:",
+  "/:100110111000:V:",
+  "/:1001101110011:y:",
+  "/:10011011100100:ESCAPE:",
+  "/:10011011100101:g:",
+  "0:0:0:",
+  "0:111: :",
+  "0:1001:a:",
+  "0:1011:p:",
+  "0:10001:s:",
+  "0:11000:.:",
+  "0:11001:8:",
+  "0:11011:,:",
+  "0:100000:4:",
+  "0:100001:t:",
+  "0:101001:5:",
+  "0:110100:6:",
+  "0:1010000:3:",
+  "0:1010001:7:",
+  "0:1010101:]:",
+  "0:1010110:-:",
+  "0:1010111:1:",
+  "0:10101000:):",
+  "0:10101001:/:",
+  "0:11010100:STOP:",
+  "0:11010101:9:",
+  "0:11010111:2:",
+  "0:110101100:%:",
+  "0:1101011010:0x3a:",
+  "0:110101101101:f:",
+  "0:110101101111:m:",
+  "0:1101011011100:y:",
+  "0:11010110110001:l:",
+  "0:11010110110010:;:",
+  "0:11010110110011:':",
+  "0:11010110111010:k:",
+  "0:11010110111011:!:",
+  "0:110101101100000:C:",
+  "0:1101011011000010:ESCAPE:",
+  "0:1101011011000011:J:",
+  "1:00:9:",
+  "1:100:1:",
+  "1:111:0:",
+  "1:0101: :",
+  "1:0111:2:",
+  "1:1011:.:",
+  "1:1100:5:",
+  "1:01000:6:",
+  "1:01001:8:",
+  "1:01101:/:",
+  "1:10100:]:",
+  "1:11010:3:",
+  "1:011001:7:",
+  "1:110110:4:",
+  "1:0110000:STOP:",
+  "1:0110001:-:",
+  "1:1010100:):",
+  "1:1010110:0x3a:",
+  "1:1010111:s:",
+  "1:1101110:,:",
+  "1:1101111:x:",
+  "1:10101010:':",
+  "1:101010110:X:",
+  "1:10101011110:t:",
+  "1:10101011111:R:",
+  "1:101010111011:;:",
+  "1:1010101110000:p:",
+  "1:1010101110001:m:",
+  "1:1010101110010:!:",
+  "1:1010101110101:&:",
+  "1:10101011100110:e:",
+  "1:101010111001110:b:",
+  "1:101010111001111:a:",
+  "1:101010111010000:D:",
+  "1:101010111010001:C:",
+  "1:101010111010010:%:",
+  "1:1010101110100110:ESCAPE:",
+  "1:1010101110100111:o:",
+  "2:11:0:",
+  "2:000: :",
+  "2:010:.:",
+  "2:100:5:",
+  "2:0011:/:",
+  "2:1011:,:",
+  "2:00100:]:",
+  "2:00101:p:",
+  "2:01101:1:",
+  "2:10101:4:",
+  "2:011000:6:",
+  "2:011001:2:",
+  "2:011100:0x3a:",
+  "2:011101:-:",
+  "2:011111:):",
+  "2:1010000:STOP:",
+  "2:1010010:8:",
+  "2:1010011:9:",
+  "2:01111000:D:",
+  "2:01111001:3:",
+  "2:01111010:t:",
+  "2:01111011:7:",
+  "2:10100010:n:",
+  "2:101000110:a:",
+  "2:1010001110:':",
+  "2:10100011111:;:",
+  "2:101000111100:s:",
+  "2:1010001111010:\":",
+  "2:101000111101100:ESCAPE:",
+  "2:101000111101101:i:",
+  "2:101000111101110:W:",
+  "2:101000111101111:L:",
+  "3:00: :",
+  "3:10:0:",
+  "3:110:.:",
+  "3:1110:/:",
+  "3:01000:2:",
+  "3:01001:1:",
+  "3:01010:):",
+  "3:01100:0x3a:",
+  "3:01110:-:",
+  "3:11111:]:",
+  "3:010110:D:",
+  "3:011010:4:",
+  "3:011011:STOP:",
+  "3:011111:5:",
+  "3:111100:,:",
+  "3:0101110:7:",
+  "3:0101111:3:",
+  "3:0111101:6:",
+  "3:1111011:t:",
+  "3:01111001:B:",
+  "3:11110100:8:",
+  "3:111101010:9:",
+  "3:0111100001:;:",
+  "3:1111010110:r:",
+  "3:1111010111:s:",
+  "3:01111000000:n:",
+  "3:01111000101:b:",
+  "3:01111000110:':",
+  "3:01111000111:A:",
+  "3:011110000010:p:",
+  "3:011110000011:e:",
+  "3:0111100010000:a:",
+  "3:0111100010001:&:",
+  "3:0111100010010:%:",
+  "3:01111000100110:ESCAPE:",
+  "3:01111000100111:k:",
+  "4:01: :",
+  "4:000:4:",
+  "4:100:.:",
+  "4:110:0:",
+  "4:0010:/:",
+  "4:1010:5:",
+  "4:1011:-:",
+  "4:00110:1:",
+  "4:11101:]:",
+  "4:11110:,:",
+  "4:001110:2:",
+  "4:111001:8:",
+  "4:111110:):",
+  "4:0011110:0x3a:",
+  "4:0011111:':",
+  "4:1110000:t:",
+  "4:1110001:3:",
+  "4:1111111:STOP:",
+  "4:11111101:6:",
+  "4:1111110000:9:",
+  "4:1111110010:7:",
+  "4:11111100011:C:",
+  "4:11111100110:;:",
+  "4:111111000101:x:",
+  "4:1111110011101:m:",
+  "4:1111110011110:I:",
+  "4:11111100010000:f:",
+  "4:11111100010001:e:",
+  "4:11111100010010:b:",
+  "4:11111100010011:L:",
+  "4:11111100111000:%:",
+  "4:11111100111110:p:",
+  "4:11111100111111:c:",
+  "4:111111001110010:ESCAPE:",
+  "4:111111001110011:i:",
+  "5:00:0:",
+  "5:10: :",
+  "5:010:.:",
+  "5:0111:p:",
+  "5:1100:5:",
+  "5:01100:/:",
+  "5:11010:a:",
+  "5:11011:-:",
+  "5:11101:6:",
+  "5:011010:3:",
+  "5:111100:2:",
+  "5:111110:8:",
+  "5:111111:]:",
+  "5:0110110:0x3a:",
+  "5:1110000:):",
+  "5:1110001:s:",
+  "5:1110011:,:",
+  "5:1111010:7:",
+  "5:1111011:9:",
+  "5:01101110:4:",
+  "5:11100100:STOP:",
+  "5:11100101:t:",
+  "5:0110111110:c:",
+  "5:0110111111:1:",
+  "5:01101111001:;:",
+  "5:01101111011:m:",
+  "5:011011110000:e:",
+  "5:011011110001:':",
+  "5:011011110101:k:",
+  "5:0110111101001:l:",
+  "5:01101111010000:ESCAPE:",
+  "5:01101111010001:f:",
+  "6:00: :",
+  "6:10:.:",
+  "6:111:0:",
+  "6:0101:]:",
+  "6:01001:1:",
+  "6:01100:7:",
+  "6:01110:):",
+  "6:11000:,:",
+  "6:11001:0x3a:",
+  "6:11010:/:",
+  "6:010001:-:",
+  "6:011010:5:",
+  "6:011011:4:",
+  "6:011111:8:",
+  "6:110111:t:",
+  "6:0100000:6:",
+  "6:0111100:3:",
+  "6:0111101:2:",
+  "6:1101101:9:",
+  "6:01000010:STOP:",
+  "6:01000011:+:",
+  "6:11011000:':",
+  "6:1101100101:a:",
+  "6:1101100110:?:",
+  "6:11011001000:m:",
+  "6:11011001001:e:",
+  "6:11011001110:;:",
+  "6:1101100111100:f:",
+  "6:1101100111101:b:",
+  "6:1101100111110:M:",
+  "6:11011001111110:\":",
+  "6:110110011111110:ESCAPE:",
+  "6:110110011111111:i:",
+  "7:11:.:",
+  "7:001: :",
+  "7:011:0:",
+  "7:101:-:",
+  "7:0000:8:",
+  "7:0100:7:",
+  "7:1001:]:",
+  "7:01010:/:",
+  "7:000101:6:",
+  "7:000110:2:",
+  "7:000111:1:",
+  "7:010111:t:",
+  "7:100000:9:",
+  "7:100010:):",
+  "7:100011:5:",
+  "7:0001001:3:",
+  "7:0101101:,:",
+  "7:1000010:a:",
+  "7:1000011:4:",
+  "7:00010000:STOP:",
+  "7:01011000:0x3a:",
+  "7:01011001:p:",
+  "7:0001000101:R:",
+  "7:0001000110:;:",
+  "7:00010001000:':",
+  "7:00010001111:m:",
+  "7:000100010011:f:",
+  "7:000100011100:A:",
+  "7:000100011101:?:",
+  "7:0001000100100:ESCAPE:",
+  "7:0001000100101:s:",
+  "8:01: :",
+  "8:000:4:",
+  "8:110:.:",
+  "8:0011:0:",
+  "8:1000:9:",
+  "8:1001:7:",
+  "8:1011:8:",
+  "8:1110:1:",
+  "8:00100:/:",
+  "8:10100:3:",
+  "8:11110:5:",
+  "8:101010:):",
+  "8:111110:6:",
+  "8:111111:]:",
+  "8:0010100:0x3a:",
+  "8:0010101:,:",
+  "8:1010111:t:",
+  "8:00101100:p:",
+  "8:00101101:-:",
+  "8:00101111:a:",
+  "8:10101100:c:",
+  "8:10101101:2:",
+  "8:001011101:STOP:",
+  "8:0010111001:;:",
+  "8:001011100000:l:",
+  "8:001011100001:':",
+  "8:0010111000100:f:",
+  "8:0010111000101:D:",
+  "8:0010111000110:A:",
+  "8:00101110001110:ESCAPE:",
+  "8:00101110001111:i:",
+  "9:000:5:",
+  "9:001:]:",
+  "9:111:9:",
+  "9:0101:0:",
+  "9:0110:.:",
+  "9:0111:-:",
+  "9:1000:4:",
+  "9:1001:8:",
+  "9:1011:6:",
+  "9:1100: :",
+  "9:1101:7:",
+  "9:01000:2:",
+  "9:10100:3:",
+  "9:010010:1:",
+  "9:010011:/:",
+  "9:101010:t:",
+  "9:1010111:):",
+  "9:10101100:0x3a:",
+  "9:101011010:,:",
+  "9:10101101100:p:",
+  "9:10101101101:;:",
+  "9:10101101111:STOP:",
+  "9:1010110111000:n:",
+  "9:1010110111001:m:",
+  "9:1010110111010:a:",
+  "9:10101101110111:e:",
+  "9:101011011101100:ESCAPE:",
+  "9:101011011101101:k:",
+  "0x3a:1: :",
+  "0x3a:01:0:",
+  "0x3a:001:3:",
+  "0x3a:00001:1:",
+  "0x3a:00010:T:",
+  "0x3a:00011:C:",
+  "0x3a:000001:4:",
+  "0x3a:0000000:ESCAPE:",
+  "0x3a:0000001:5:",
+  ";:0:ESCAPE:",
+  ";:1: :",
+  "<:0:ESCAPE:",
+  "<:1:ESCAPE:",
+  "=:0:ESCAPE:",
+  "=:1:ESCAPE:",
+  ">:0:ESCAPE:",
+  ">:1:ESCAPE:",
+  "?:1: :",
+  "?:01:STOP:",
+  "?:000:0x3a:",
+  "?:00100:!:",
+  "?:00110:[:",
+  "?:00111:.:",
+  "?:001010:;:",
+  "?:0010110:':",
+  "?:00101111:,:",
+  "?:001011101:/:",
+  "?:0010111000:ESCAPE:",
+  "?:0010111001:Q:",
+  "@:0:k:",
+  "@:10: :",
+  "@:111:T:",
+  "@:1101:b:",
+  "@:11000:ESCAPE:",
+  "@:11001:H:",
+  "A:01: :",
+  "A:110:D:",
+  "A:111:n:",
+  "A:0000:s:",
+  "A:0001:m:",
+  "A:0010:d:",
+  "A:1000:r:",
+  "A:1011:l:",
+  "A:00110:c:",
+  "A:10010:u:",
+  "A:10100:g:",
+  "A:001111:b:",
+  "A:100111:t:",
+  "A:101011:f:",
+  "A:1010100:w:",
+  "A:1010101:i:",
+  "A:10011001:v:",
+  "A:10011011:p:",
+  "A:001110010:h:",
+  "A:001110100:.:",
+  "A:001110111:B:",
+  "A:100110100:q:",
+  "A:0011100000:C:",
+  "A:0011100010:,:",
+  "A:0011100110:y:",
+  "A:0011101010:S:",
+  "A:0011101100:k:",
+  "A:0011101101:T:",
+  "A:1001100001:R:",
+  "A:1001100010:F:",
+  "A:1001100011:z:",
+  "A:1001101011:a:",
+  "A:00111000010:P:",
+  "A:00111000110:-:",
+  "A:00111010110:A:",
+  "A:00111010111:I:",
+  "A:10011000001:e:",
+  "A:10011010100:N:",
+  "A:10011010101:x:",
+  "A:001110000110:X:",
+  "A:001110000111:K:",
+  "A:001110001110:3:",
+  "A:001110001111:&:",
+  "A:001110011101:M:",
+  "A:001110011111:Y:",
+  "A:0011100111000:L:",
+  "A:0011100111001:W:",
+  "A:0011100111100:*:",
+  "A:1001100000000:o:",
+  "A:1001100000001:1:",
+  "A:1001100000010:':",
+  "A:1001100000011:0x3a:",
+  "A:00111001111010:j:",
+  "A:001110011110110:G:",
+  "A:0011100111101110:O:",
+  "A:00111001111011110:4:",
+  "A:001110011110111110:ESCAPE:",
+  "A:001110011110111111:E:",
+  "B:00:C:",
+  "B:010:a:",
+  "B:101:r:",
+  "B:110:e:",
+  "B:111:B:",
+  "B:0111:i:",
+  "B:1000:u:",
+  "B:1001:o:",
+  "B:01101:l:",
+  "B:01100000:T:",
+  "B:01100001:.:",
+  "B:01100011:y:",
+  "B:01100100:I:",
+  "B:01100110:h:",
+  "B:01100111: :",
+  "B:011000100:A:",
+  "B:0110001010:O:",
+  "B:01100010110:0x3a:",
+  "B:01100101000:&:",
+  "B:01100101001:3:",
+  "B:01100101010:j:",
+  "B:01100101011:M:",
+  "B:01100101110:D:",
+  "B:011000101111:W:",
+  "B:011001011000:*:",
+  "B:011001011010:,:",
+  "B:011001011011:1:",
+  "B:011001011110:ESCAPE:",
+  "B:011001011111:P:",
+  "B:0110001011100:E:",
+  "B:0110010110011:R:",
+  "B:01100010111011:w:",
+  "B:011000101110100:-:",
+  "B:011001011001001:U:",
+  "B:011001011001010:S:",
+  "B:011001011001011:F:",
+  "B:0110001011101010:X:",
+  "B:0110001011101011:V:",
+  "B:0110010110010000:Q:",
+  "B:0110010110010001:4:",
+  "C:00:h:",
+  "C:011:B:",
+  "C:100:a:",
+  "C:110:o:",
+  "C:0101:r:",
+  "C:1010:.:",
+  "C:1110: :",
+  "C:1111:l:",
+  "C:01000:':",
+  "C:10111:i:",
+  "C:010011:e:",
+  "C:101101:u:",
+  "C:0100101:y:",
+  "C:1011001:,:",
+  "C:01001001:I:",
+  "C:010010000:A:",
+  "C:1011000000:C:",
+  "C:1011000001:D:",
+  "C:1011000011:STOP:",
+  "C:1011000100:S:",
+  "C:1011000101:T:",
+  "C:1011000111:G:",
+  "C:01001000100:*:",
+  "C:01001000111:w:",
+  "C:10110001101:J:",
+  "C:010010001010:R:",
+  "C:010010001100:2:",
+  "C:010010001101:U:",
+  "C:101100001000:?:",
+  "C:101100001010:O:",
+  "C:101100001011:H:",
+  "C:101100011000:E:",
+  "C:0100100010110:z:",
+  "C:1011000010011:-:",
+  "C:1011000110011:s:",
+  "C:01001000101111:1:",
+  "C:10110000100101:!:",
+  "C:10110001100100:P:",
+  "C:010010001011101:n:",
+  "C:101100001001000:K:",
+  "C:101100001001001:7:",
+  "C:101100011001011:4:",
+  "C:0100100010111000:0x3a:",
+  "C:1011000110010100:F:",
+  "C:1011000110010101:):",
+  "C:01001000101110010:ESCAPE:",
+  "C:01001000101110011:b:",
+  "D:00:a:",
+  "D:01:,:",
+  "D:100:r:",
+  "D:101:o:",
+  "D:110:e:",
+  "D:1110:i:",
+  "D:111111:u:",
+  "D:1111001: :",
+  "D:1111011:':",
+  "D:11110000:.:",
+  "D:11110001:]:",
+  "D:11111010:y:",
+  "D:111101010:w:",
+  "D:111101011:W:",
+  "D:111110001:N:",
+  "D:111110010:C:",
+  "D:111110111:J:",
+  "D:1111010010:h:",
+  "D:1111100000:t:",
+  "D:1111100111:I:",
+  "D:1111101101:0x3a:",
+  "D:11110100001:M:",
+  "D:11110100010:&:",
+  "D:11110100011:V:",
+  "D:11111000010:-:",
+  "D:11111000011:G:",
+  "D:11111001100:O:",
+  "D:11111001101:A:",
+  "D:11111011001:S:",
+  "D:111101000000:F:",
+  "D:111101001100:*:",
+  "D:111101001101:s:",
+  "D:111101001111:d:",
+  "D:111110110000:v:",
+  "D:1111010011100:m:",
+  "D:1111010011101:j:",
+  "D:1111101100010:ESCAPE:",
+  "D:1111101100011:T:",
+  "D:11110100000110:9:",
+  "D:111101000001000:):",
+  "D:111101000001011:E:",
+  "D:111101000001110:8:",
+  "D:111101000001111:7:",
+  "D:1111010000010010:U:",
+  "D:1111010000010011:R:",
+  "D:1111010000010100:B:",
+  "D:1111010000010101:4:",
+  "E:000:p:",
+  "E:010:a:",
+  "E:011:n:",
+  "E:110:l:",
+  "E:1001:m:",
+  "E:1010:x:",
+  "E:1110:v:",
+  "E:1111:d:",
+  "E:00100:s:",
+  "E:00110:r:",
+  "E:00111:u:",
+  "E:10000:E:",
+  "E:10001: :",
+  "E:001010:.:",
+  "E:001011:i:",
+  "E:101101:0x3a:",
+  "E:1011000:y:",
+  "E:1011001:t:",
+  "E:1011100:g:",
+  "E:1011110:4:",
+  "E:101110110:w:",
+  "E:101111100:c:",
+  "E:101111110:b:",
+  "E:1011101010:R:",
+  "E:1011101011:F:",
+  "E:1011101111:C:",
+  "E:10111010001:k:",
+  "E:10111010010:f:",
+  "E:10111010011:o:",
+  "E:10111011100:U:",
+  "E:10111011101:L:",
+  "E:10111110101:e:",
+  "E:10111110110:N:",
+  "E:10111111100:h:",
+  "E:10111111101:I:",
+  "E:10111111111:D:",
+  "E:101111101000:M:",
+  "E:101111101111:':",
+  "E:101111111100:2:",
+  "E:101111111101:-:",
+  "E:1011101000011:q:",
+  "E:1011111010010:O:",
+  "E:1011111010011:A:",
+  "E:1011111011101:Z:",
+  "E:10111010000000:W:",
+  "E:10111010000001:S:",
+  "E:10111010000010:H:",
+  "E:10111010000011:9:",
+  "E:10111010000100:):",
+  "E:10111110111000:T:",
+  "E:10111110111001:,:",
+  "E:101110100001010:P:",
+  "E:1011101000010110:ESCAPE:",
+  "E:1011101000010111:z:",
+  "F:00:o:",
+  "F:10:r:",
+  "F:010:e:",
+  "F:110:i:",
+  "F:111:a:",
+  "F:0110:l:",
+  "F:01110:u:",
+  "F:0111100: :",
+  "F:0111101:O:",
+  "F:01111101:A:",
+  "F:01111111:B:",
+  "F:011111100:f:",
+  "F:0111110000:.:",
+  "F:0111110011:L:",
+  "F:01111100010:M:",
+  "F:01111100011:E:",
+  "F:01111100101:T:",
+  "F:01111110101:C:",
+  "F:01111110110:W:",
+  "F:011111001000:0x3a:",
+  "F:011111101000:U:",
+  "F:011111101001:':",
+  "F:011111101111:1:",
+  "F:0111110010010:y:",
+  "F:0111110010011:,:",
+  "F:01111110111000:-:",
+  "F:01111110111010:I:",
+  "F:011111101110011:h:",
+  "F:0111111011100100:*:",
+  "F:0111111011100101:K:",
+  "F:0111111011101100:F:",
+  "F:0111111011101101:ESCAPE:",
+  "F:01111110111011100:X:",
+  "F:01111110111011101:R:",
+  "F:01111110111011110:;:",
+  "F:01111110111011111:4:",
+  "G:00:r:",
+  "G:01:a:",
+  "G:101:o:",
+  "G:110:e:",
+  "G:1001:u:",
+  "G:1111:i:",
+  "G:10001:n:",
+  "G:11101:l:",
+  "G:100000:X:",
+  "G:1110000:y:",
+  "G:1110001: :",
+  "G:1110011:w:",
+  "G:10000101:4:",
+  "G:10000111:P:",
+  "G:11100101:h:",
+  "G:100001000:-:",
+  "G:100001100:C:",
+  "G:111001001:M:",
+  "G:1000011010:B:",
+  "G:1110010000:.:",
+  "G:1110010001:I:",
+  "G:10000100100:;:",
+  "G:10000100101:,:",
+  "G:10000100110:A:",
+  "G:10000100111:N:",
+  "G:10000110111:0x3a:",
+  "G:1000011011000:O:",
+  "G:1000011011001:L:",
+  "G:10000110110110:b:",
+  "G:100001101101000:K:",
+  "G:100001101101001:2:",
+  "G:100001101101010:1:",
+  "G:100001101101011:':",
+  "G:1000011011011100:ESCAPE:",
+  "G:1000011011011101:m:",
+  "G:1000011011011110:T:",
+  "G:1000011011011111:S:",
+  "H:00:e:",
+  "H:01:a:",
+  "H:10:o:",
+  "H:110:i:",
+  "H:1111:u:",
+  "H:11100:R:",
+  "H:1110100:P:",
+  "H:1110110:y:",
+  "H:11101011:I:",
+  "H:111011100:Q:",
+  "H:111011101:M:",
+  "H:111011110:A:",
+  "H:111011111: :",
+  "H:1110101000:S:",
+  "H:1110101001:.:",
+  "H:11101010101:G:",
+  "H:11101010110:):",
+  "H:111010101001:E:",
+  "H:1110101011100:O:",
+  "H:1110101011101:L:",
+  "H:11101010100000:1:",
+  "H:11101010100001:&:",
+  "H:11101010111100:H:",
+  "H:11101010111101:w:",
+  "H:11101010111110:v:",
+  "H:111010101000100:X:",
+  "H:111010101000101:W:",
+  "H:111010101000110:D:",
+  "H:111010101111110:s:",
+  "H:111010101111111:F:",
+  "H:1110101010001110:ESCAPE:",
+  "H:1110101010001111:r:",
+  "I:0:n:",
+  "I:110:t:",
+  "I:1001:s:",
+  "I:1111:r:",
+  "I:10000:T:",
+  "I:10101:a:",
+  "I:11100: :",
+  "I:100010:c:",
+  "I:101001:m:",
+  "I:101100:z:",
+  "I:101101:.:",
+  "I:101111:d:",
+  "I:111011:I:",
+  "I:1000111:':",
+  "I:1011101:l:",
+  "I:10100000:A:",
+  "I:10100001:v:",
+  "I:10111001:V:",
+  "I:11101001:f:",
+  "I:11101011:o:",
+  "I:100011001:C:",
+  "I:100011010:P:",
+  "I:101000100:w:",
+  "I:101000110:0x3a:",
+  "I:101110000:p:",
+  "I:111010000:R:",
+  "I:111010001:,:",
+  "I:111010101:Y:",
+  "I:1000110000:E:",
+  "I:1000110001:6:",
+  "I:1000110111:q:",
+  "I:1010001011:y:",
+  "I:1010001110:M:",
+  "I:1110101000:g:",
+  "I:1110101001:D:",
+  "I:10001101100:e:",
+  "I:10001101101:5:",
+  "I:10100010100:S:",
+  "I:10100010101:9:",
+  "I:10100011111:F:",
+  "I:10111000100:b:",
+  "I:10111000110:-:",
+  "I:10111000111:L:",
+  "I:101000111100:B:",
+  "I:101000111101:):",
+  "I:1011100010100:N:",
+  "I:1011100010101:Q:",
+  "I:1011100010110:k:",
+  "I:10111000101111:O:",
+  "I:101110001011101:?:",
+  "I:1011100010111000:ESCAPE:",
+  "I:1011100010111001:h:",
+  "J:00:e:",
+  "J:10:a:",
+  "J:11:o:",
+  "J:011:u:",
+  "J:0101:i:",
+  "J:01000: :",
+  "J:0100110:D:",
+  "J:0100111:.:",
+  "J:01001001:r:",
+  "J:010010110:s:",
+  "J:0100100000:M:",
+  "J:0100100010:J:",
+  "J:0100100011:,:",
+  "J:0100101000:B:",
+  "J:0100101001:-:",
+  "J:0100101010:V:",
+  "J:0100101110:K:",
+  "J:0100101111:T:",
+  "J:01001000010:C:",
+  "J:01001010110:n:",
+  "J:010010000110:!:",
+  "J:0100100001110:w:",
+  "J:0100100001111:R:",
+  "J:0100101011100:F:",
+  "J:0100101011110:7:",
+  "J:0100101011111:':",
+  "J:01001010111010:G:",
+  "J:010010101110110:ESCAPE:",
+  "J:010010101110111:L:",
+  "K:00:i:",
+  "K:01:a:",
+  "K:10:e:",
+  "K:1111:y:",
+  "K:11000:n:",
+  "K:11001:o:",
+  "K:11011:r:",
+  "K:11101: :",
+  "K:110100:':",
+  "K:111000:u:",
+  "K:1101011:.:",
+  "K:1110011:l:",
+  "K:11100101:h:",
+  "K:110101000:T:",
+  "K:110101011:G:",
+  "K:111001001:,:",
+  "K:1101010100:w:",
+  "K:11010100100:5:",
+  "K:11010100101:4:",
+  "K:11010100110:A:",
+  "K:11010101010:3:",
+  "K:11100100000:2:",
+  "K:11100100011:M:",
+  "K:110101001110:-:",
+  "K:110101010110:0x3a:",
+  "K:110101010111:!:",
+  "K:111001000010:):",
+  "K:111001000101:S:",
+  "K:1101010011110:V:",
+  "K:1110010000110:6:",
+  "K:1110010000111:1:",
+  "K:11010100111111:L:",
+  "K:11100100010000:I:",
+  "K:11100100010001:?:",
+  "K:110101001111100:ESCAPE:",
+  "K:110101001111101:v:",
+  "K:111001000100100:k:",
+  "K:111001000100101:Y:",
+  "K:111001000100110:N:",
+  "K:111001000100111:E:",
+  "L:00:i:",
+  "L:10:o:",
+  "L:011:]:",
+  "L:110:e:",
+  "L:111:a:",
+  "L:0100:u:",
+  "L:010100:l:",
+  "L:010101:A:",
+  "L:010111:y:",
+  "L:01011011: :",
+  "L:010110000:I:",
+  "L:010110001:R:",
+  "L:010110101:,:",
+  "L:0101100100:O:",
+  "L:0101100101:':",
+  "L:01011001101:.:",
+  "L:01011001110:C:",
+  "L:01011001111:Y:",
+  "L:01011010001:F:",
+  "L:01011010010:L:",
+  "L:010110011001:t:",
+  "L:010110100001:G:",
+  "L:010110100111:S:",
+  "L:0101100110001:h:",
+  "L:0101101000001:W:",
+  "L:0101101001100:J:",
+  "L:01011001100000:E:",
+  "L:01011010000001:\":",
+  "L:01011010011011:STOP:",
+  "L:010110011000010:T:",
+  "L:010110011000011:P:",
+  "L:010110100000000:D:",
+  "L:010110100000001:7:",
+  "L:010110100110101:j:",
+  "L:0101101001101000:ESCAPE:",
+  "L:0101101001101001:U:",
+  "M:00:o:",
+  "M:11:a:",
+  "M:011:e:",
+  "M:101:i:",
+  "M:0101:c:",
+  "M:1001:u:",
+  "M:01001:y:",
+  "M:10001:r:",
+  "M:100000:S:",
+  "M:100001:P:",
+  "M:0100001: :",
+  "M:01000001:C:",
+  "M:01000110:F:",
+  "M:010000000:1:",
+  "M:010001000:h:",
+  "M:010001010:I:",
+  "M:010001110:T:",
+  "M:010001111:X:",
+  "M:0100000010:A:",
+  "M:0100010010:z:",
+  "M:01000100110:f:",
+  "M:01000101110:.:",
+  "M:010000001100:Z:",
+  "M:010000001101:K:",
+  "M:010000001110:B:",
+  "M:010001001111:s:",
+  "M:010001011000:R:",
+  "M:010001011001:W:",
+  "M:010001011010:O:",
+  "M:0100000011110:,:",
+  "M:0100000011111:':",
+  "M:0100010110111:D:",
+  "M:0100010111100:4:",
+  "M:0100010111110:E:",
+  "M:01000100111000:m:",
+  "M:01000100111001:J:",
+  "M:01000100111010:ESCAPE:",
+  "M:01000101111010:l:",
+  "M:01000101111011:-:",
+  "M:01000101111110:):",
+  "M:01000101111111:w:",
+  "M:010001001110110:t:",
+  "M:010001001110111:V:",
+  "M:010001011011000:Q:",
+  "M:010001011011001:N:",
+  "M:010001011011010:6:",
+  "M:010001011011011:2:",
+  "N:00:a:",
+  "N:10:o:",
+  "N:11:e:",
+  "N:011:i:",
+  "N:01010:u:",
+  "N:01011:E:",
+  "N:010010:A:",
+  "N:0100010:y:",
+  "N:0100110:g:",
+  "N:01000001:B:",
+  "N:01000010:I:",
+  "N:01000110:F:",
+  "N:01000111: :",
+  "N:010000000:):",
+  "N:010000001:':",
+  "N:010000111:Y:",
+  "N:010011100:L:",
+  "N:010011101:H:",
+  "N:0100001100:C:",
+  "N:0100111100:W:",
+  "N:0100111110:N:",
+  "N:0100111111:T:",
+  "N:010000110101:M:",
+  "N:010000110111:O:",
+  "N:010011110100:,:",
+  "N:010011110101:J:",
+  "N:010011110111:h:",
+  "N:0100001101000:D:",
+  "N:0100001101001:.:",
+  "N:0100111101100:X:",
+  "N:0100111101101:ESCAPE:",
+  "N:01000011011000:k:",
+  "N:01000011011001:Z:",
+  "N:01000011011010:Q:",
+  "N:01000011011011:G:",
+  "O:111:n:",
+  "O:0000:s:",
+  "O:0001:N:",
+  "O:0011:z:",
+  "O:0100:r:",
+  "O:1000:u:",
+  "O:1010:p:",
+  "O:1011:l:",
+  "O:1101:':",
+  "O:00101:U:",
+  "O:01011:h:",
+  "O:01110:f:",
+  "O:01111:w:",
+  "O:10010:.:",
+  "O:11000: :",
+  "O:001000:o:",
+  "O:001001:J:",
+  "O:010100:b:",
+  "O:010101:m:",
+  "O:011001:H:",
+  "O:011010:O:",
+  "O:011011:v:",
+  "O:100111:c:",
+  "O:110011:x:",
+  "O:1001101:d:",
+  "O:1100100:a:",
+  "O:01100001:t:",
+  "O:01100010:k:",
+  "O:10011000:g:",
+  "O:11001010:R:",
+  "O:011000000:K:",
+  "O:100110010:i:",
+  "O:110010111:V:",
+  "O:0110000011:2:",
+  "O:0110001101:S:",
+  "O:0110001110:B:",
+  "O:1001100110:W:",
+  "O:1001100111:-:",
+  "O:01100000100:,:",
+  "O:01100011000:j:",
+  "O:01100011001:L:",
+  "O:01100011111:I:",
+  "O:11001011001:A:",
+  "O:11001011011:C:",
+  "O:011000001010:0x3a:",
+  "O:011000111100:e:",
+  "O:110010110000:y:",
+  "O:110010110001:/:",
+  "O:110010110100:M:",
+  "O:0110000010110:!:",
+  "O:0110001111011:P:",
+  "O:1100101101011:F:",
+  "O:01100000101110:E:",
+  "O:01100000101111:D:",
+  "O:01100011110100:8:",
+  "O:01100011110101:4:",
+  "O:11001011010101:T:",
+  "O:110010110101000:ESCAPE:",
+  "O:110010110101001:q:",
+  "P:11:a:",
+  "P:000:i:",
+  "P:010:e:",
+  "P:011:l:",
+  "P:100:o:",
+  "P:101:r:",
+  "P:0010:h:",
+  "P:001111:u:",
+  "P:0011010:C:",
+  "P:0011100:.:",
+  "P:0011101: :",
+  "P:00110000:B:",
+  "P:00110010:D:",
+  "P:00110111:s:",
+  "P:001100011:O:",
+  "P:001100111:,:",
+  "P:0011000101:y:",
+  "P:0011001100:M:",
+  "P:0011011000:E:",
+  "P:0011011001:':",
+  "P:0011011011:3:",
+  "P:00110001001:T:",
+  "P:001100010000:L:",
+  "P:001100010001:G:",
+  "P:001100110100:*:",
+  "P:001100110110:A:",
+  "P:001100110111:S:",
+  "P:001101101000:w:",
+  "P:001101101001:F:",
+  "P:0011001101011:J:",
+  "P:0011011010100:f:",
+  "P:0011011010101:R:",
+  "P:0011011010111:t:",
+  "P:00110011010100:V:",
+  "P:00110110101100:Y:",
+  "P:00110110101101:I:",
+  "P:001100110101011:&:",
+  "P:0011001101010100:ESCAPE:",
+  "P:0011001101010101:):",
+  "Q:1:u:",
+  "Q:00:V:",
+  "Q:011: :",
+  "Q:0101:.:",
+  "Q:01000:a:",
+  "Q:0100100:w:",
+  "Q:0100110:E:",
+  "Q:0100111:C:",
+  "Q:01001011:&:",
+  "Q:010010101:':",
+  "Q:0100101000:T:",
+  "Q:01001010010:ESCAPE:",
+  "Q:01001010011:s:",
+  "R:01:a:",
+  "R:11:o:",
+  "R:100:i:",
+  "R:101:e:",
+  "R:0000:p:",
+  "R:0011:u:",
+  "R:00011:E:",
+  "R:00100:h:",
+  "R:000100: :",
+  "R:001010:y:",
+  "R:00010100:D:",
+  "R:00010110:.:",
+  "R:00101100:T:",
+  "R:00101110:S:",
+  "R:000101010:F:",
+  "R:001011010:B:",
+  "R:001011011:n:",
+  "R:001011111:A:",
+  "R:0001010110:w:",
+  "R:0001011100:N:",
+  "R:0001011101:&:",
+  "R:0001011110:V:",
+  "R:0001011111:H:",
+  "R:0010111101:':",
+  "R:00010101110:t:",
+  "R:00010101111:I:",
+  "R:001011110000:C:",
+  "R:001011110010:O:",
+  "R:00101111000100:,:",
+  "R:00101111000101:s:",
+  "R:00101111000110:U:",
+  "R:00101111000111:M:",
+  "R:00101111001100:-:",
+  "R:00101111001101:ESCAPE:",
+  "R:00101111001111:0x3a:",
+  "R:001011110011100:2:",
+  "R:001011110011101:R:",
+  "S:1:]:",
+  "S:0000:a:",
+  "S:0010:h:",
+  "S:0111:t:",
+  "S:00010:p:",
+  "S:00011:,:",
+  "S:00110:L:",
+  "S:01000:i:",
+  "S:01001:u:",
+  "S:01010:o:",
+  "S:01011:c:",
+  "S:01100:e:",
+  "S:001111:k:",
+  "S:0011100:w:",
+  "S:0110101: :",
+  "S:0110111:m:",
+  "S:00111010:q:",
+  "S:01101000:M:",
+  "S:01101001:n:",
+  "S:01101100:l:",
+  "S:001110110:P:",
+  "S:011011011:y:",
+  "S:0011101110:A:",
+  "S:01101101001:.:",
+  "S:001110111101:r:",
+  "S:001110111110:S:",
+  "S:001110111111:W:",
+  "S:011011010000:C:",
+  "S:011011010101:E:",
+  "S:011011010110:v:",
+  "S:0110110100011:ESCAPE:",
+  "S:0110110101000:I:",
+  "S:0110110101111:g:",
+  "S:00111011110000:*:",
+  "S:00111011110010:4:",
+  "S:00111011110011:1:",
+  "S:01101101000100:O:",
+  "S:01101101010010:STOP:",
+  "S:01101101011100:z:",
+  "S:011011010001011:B:",
+  "S:011011010111010:H:",
+  "S:011011010111011:T:",
+  "S:0011101111000100:G:",
+  "S:0011101111000110:}:",
+  "S:0011101111000111:D:",
+  "S:0110110100010100:-:",
+  "S:0110110101001100:3:",
+  "S:0110110101001101:2:",
+  "S:00111011110001010:':",
+  "S:00111011110001011:?:",
+  "S:01101101010011101:s:",
+  "S:01101101010011110:j:",
+  "S:01101101010011111:b:",
+  "S:011011010001010100:R:",
+  "S:011011010001010101:K:",
+  "S:011011010001010110:J:",
+  "S:011011010001010111:F:",
+  "S:011011010100111000:0x3a:",
+  "S:011011010100111001:):",
+  "T:0:h:",
+  "T:100:o:",
+  "T:1010:V:",
+  "T:1011:w:",
+  "T:1100:r:",
+  "T:1111:e:",
+  "T:11010:a:",
+  "T:11011:i:",
+  "T:11100:u:",
+  "T:1110100:H:",
+  "T:1110110:W:",
+  "T:11101010: :",
+  "T:11101011:y:",
+  "T:111011101:M:",
+  "T:111011111:x:",
+  "T:1110111000:S:",
+  "T:11101110010:A:",
+  "T:11101111001:s:",
+  "T:11101111011:J:",
+  "T:111011100111:X:",
+  "T:111011110000:.:",
+  "T:1110111001101:-:",
+  "T:1110111100011:L:",
+  "T:1110111101000:C:",
+  "T:1110111101011:c:",
+  "T:11101110011000:T:",
+  "T:11101110011001:U:",
+  "T:11101111000101:4:",
+  "T:11101111010010:O:",
+  "T:111011110001001:G:",
+  "T:111011110100110:E:",
+  "T:111011110100111:,:",
+  "T:111011110101010:':",
+  "T:1110111100010001:;:",
+  "T:1110111101010000:P:",
+  "T:1110111101010001:1:",
+  "T:1110111101010010:ESCAPE:",
+  "T:1110111101010111:D:",
+  "T:11101111000100000:0x3a:",
+  "T:11101111000100001:*:",
+  "T:11101111010100110:R:",
+  "T:11101111010100111:N:",
+  "T:11101111010101100:I:",
+  "T:11101111010101101:B:",
+  "U:00:K:",
+  "U:10:n:",
+  "U:011:S:",
+  "U:110:p:",
+  "U:1111:l:",
+  "U:01010:s:",
+  "U:01011:r:",
+  "U:11101:R:",
+  "U:010000:g:",
+  "U:111000: :",
+  "U:0100111:.:",
+  "U:1110010:m:",
+  "U:01000100:k:",
+  "U:01000101:t:",
+  "U:01000110:E:",
+  "U:01000111:-:",
+  "U:01001000:F:",
+  "U:01001100:2:",
+  "U:11100110:c:",
+  "U:11100111:N:",
+  "U:010010010:f:",
+  "U:010010011:8:",
+  "U:010010100:,:",
+  "U:010010111:Z:",
+  "U:0100101010:h:",
+  "U:0100110100:i:",
+  "U:0100110101:w:",
+  "U:0100110110:a:",
+  "U:01001010110:b:",
+  "U:01001010111:D:",
+  "U:01001101110:!:",
+  "U:010010110000:e:",
+  "U:010010110001:V:",
+  "U:010010110010:P:",
+  "U:010010110011:I:",
+  "U:010010110100:B:",
+  "U:010010110101:A:",
+  "U:010011011111:d:",
+  "U:0100101101100:H:",
+  "U:0100101101101:C:",
+  "U:0100101101110:0x3a:",
+  "U:0100101101111:):",
+  "U:0100110111101:z:",
+  "U:01001101111000:ESCAPE:",
+  "U:01001101111001:T:",
+  "V:01: :",
+  "V:11:i:",
+  "V:000:.:",
+  "V:001:a:",
+  "V:101:e:",
+  "V:10001:C:",
+  "V:10011:o:",
+  "V:1000001:F:",
+  "V:1000011:I:",
+  "V:10000001:1:",
+  "V:10000101:4:",
+  "V:10010000:r:",
+  "V:10010010:E:",
+  "V:10010011:s:",
+  "V:10010101:':",
+  "V:10010110:0x3a:",
+  "V:10010111:l:",
+  "V:100000001:/:",
+  "V:100001001:-:",
+  "V:100100010:D:",
+  "V:100100011:u:",
+  "V:100101001:,:",
+  "V:1000000000:6:",
+  "V:1000000001:2:",
+  "V:1000010000:5:",
+  "V:1001010000:;:",
+  "V:10010100010:ESCAPE:",
+  "V:100001000100:7:",
+  "V:100101000110:3:",
+  "V:1000010001010:9:",
+  "V:1000010001011:y:",
+  "V:1000010001100:P:",
+  "V:1000010001101:H:",
+  "V:1000010001110:A:",
+  "V:1000010001111:8:",
+  "V:1001010001111:W:",
+  "V:10010100011100:f:",
+  "V:10010100011101:B:",
+  "W:00:h:",
+  "W:10:i:",
+  "W:011:a:",
+  "W:110:o:",
+  "W:111:e:",
+  "W:0100:r:",
+  "W:01011:O:",
+  "W:0101001: :",
+  "W:0101010:y:",
+  "W:010100000:B:",
+  "W:010100001:.:",
+  "W:010101100:I:",
+  "W:010101110:W:",
+  "W:010101111:A:",
+  "W:0101000100:':",
+  "W:0101000101:M:",
+  "W:0101000111:T:",
+  "W:01010001100:2:",
+  "W:01010001101:0x3a:",
+  "W:01010110100:H:",
+  "W:01010110110:V:",
+  "W:010101101010:l:",
+  "W:010101101110:s:",
+  "W:010101101111:,:",
+  "W:0101011010111:u:",
+  "W:010101101011000:5:",
+  "W:010101101011001:):",
+  "W:010101101011011:E:",
+  "W:0101011010110100:ESCAPE:",
+  "W:0101011010110101:m:",
+  "X:1: :",
+  "X:000:a:",
+  "X:0010:z:",
+  "X:0011:m:",
+  "X:0111:t:",
+  "X:01001:U:",
+  "X:01010:-:",
+  "X:01011:e:",
+  "X:011000:u:",
+  "X:011001:I:",
+  "X:011011:,:",
+  "X:0100010:V:",
+  "X:0110100:5:",
+  "X:0110101:.:",
+  "X:01000000:S:",
+  "X:01000010:0x3a:",
+  "X:01000110:c:",
+  "X:01000111:i:",
+  "X:010000010:9:",
+  "X:010000011:':",
+  "X:010000111:X:",
+  "X:0100001100:):",
+  "X:01000011010:ESCAPE:",
+  "X:01000011011:y:",
+  "Y:1:o:",
+  "Y:00:e:",
+  "Y:010:u:",
+  "Y:01100:a:",
+  "Y:01110:v:",
+  "Y:01111: :",
+  "Y:0110100:n:",
+  "Y:01101010:r:",
+  "Y:01101101:O:",
+  "Y:01101111:i:",
+  "Y:011010111:N:",
+  "Y:011011000:L:",
+  "Y:011011001:s:",
+  "Y:011011101:m:",
+  "Y:0110101100:.:",
+  "Y:0110101101:M:",
+  "Y:0110111001:P:",
+  "Y:011011100001:R:",
+  "Y:011011100010:2:",
+  "Y:0110111000000:-:",
+  "Y:0110111000110:C:",
+  "Y:0110111000111:,:",
+  "Y:01101110000010:ESCAPE:",
+  "Y:01101110000011:d:",
+  "Z:01:a:",
+  "Z:10:e:",
+  "Z:11:o:",
+  "Z:0010:z:",
+  "Z:0011:i:",
+  "Z:00001:Z:",
+  "Z:00010: :",
+  "Z:00011:u:",
+  "Z:0000010:O:",
+  "Z:0000011:.:",
+  "Z:00000000:y:",
+  "Z:00000001:4:",
+  "Z:00000010:,:",
+  "Z:0000001100:f:",
+  "Z:0000001101:-:",
+  "Z:0000001110:STOP:",
+  "Z:00000011110:ESCAPE:",
+  "Z:00000011111:l:",
+  "[:1:S:",
+  "[:01:A:",
+  "[:0000:2:",
+  "[:0010:R:",
+  "[:0011:1:",
+  "[:000101:n:",
+  "[:000110:m:",
+  "[:0001111:l:",
+  "[:00010011:r:",
+  "[:00011101:b:",
+  "[:000100001:C:",
+  "[:000100010:f:",
+  "[:000100101:M:",
+  "[:000111001:c:",
+  "[:0001000001:STOP:",
+  "[:0001000111:K:",
+  "[:0001001000:H:",
+  "[:0001110001:T:",
+  "[:00010000000:J:",
+  "[:00010000001:B:",
+  "[:00010001101:Z:",
+  "[:00010010011:P:",
+  "[:00011100000:L:",
+  "[:000100011000:F:",
+  "[:000100100101:I:",
+  "[:000111000011:N:",
+  "[:0001000110010:s:",
+  "[:0001000110011:V:",
+  "[:0001001001000:U:",
+  "[:0001001001001:G:",
+  "[:0001110000101:D:",
+  "[:00011100001000:O:",
+  "[:000111000010010:ESCAPE:",
+  "[:000111000010011:W:",
+  "\\:0:ESCAPE:",
+  "\\:1:x:",
+  "]:1:STOP:",
+  "]:01: :",
+  "]:001:.:",
+  "]:0001:[:",
+  "]:00001:0x3a:",
+  "]:000001:,:",
+  "]:0000001:;:",
+  "]:00000000:ESCAPE:",
+  "]:00000001:]:",
+  "^:0:ESCAPE:",
+  "^:1:ESCAPE:",
+  "_:0:ESCAPE:",
+  "_:1:ESCAPE:",
+  "`:001:w:",
+  "`:011:H:",
+  "`:110:P:",
+  "`:111:F:",
+  "`:0101:n:",
+  "`:1011:D:",
+  "`:00001:s:",
+  "`:00010:A:",
+  "`:01001:t:",
+  "`:10000:g:",
+  "`:10011:c:",
+  "`:000000:W:",
+  "`:000001:r:",
+  "`:000110:e:",
+  "`:000111:C:",
+  "`:100011:l:",
+  "`:100100:h:",
+  "`:100101:G:",
+  "`:101001:B:",
+  "`:101010:T:",
+  "`:101011:S:",
+  "`:0100000:o:",
+  "`:0100001:d:",
+  "`:0100010:b:",
+  "`:0100011:R:",
+  "`:1000100:O:",
+  "`:1000101:L:",
+  "`:1010001:f:",
+  "`:10100000:J:",
+  "`:101000010:ESCAPE:",
+  "`:101000011:M:",
+  "a:01:n:",
+  "a:001:r:",
+  "a:101:t:",
+  "a:0000:m:",
+  "a:1001:s:",
+  "a:1110: :",
+  "a:1111:l:",
+  "a:00011:d:",
+  "a:10000:i:",
+  "a:11000:y:",
+  "a:11010:c:",
+  "a:000100:p:",
+  "a:100010:u:",
+  "a:100011:v:",
+  "a:110011:g:",
+  "a:110110:b:",
+  "a:110111:k:",
+  "a:0001010:w:",
+  "a:00010111:z:",
+  "a:11001000:.:",
+  "a:11001011:f:",
+  "a:000101100:,:",
+  "a:000101101:':",
+  "a:110010011:e:",
+  "a:110010101:h:",
+  "a:1100101001:x:",
+  "a:11001001000:a:",
+  "a:11001001001:-:",
+  "a:11001001011:j:",
+  "a:11001010000:0x3a:",
+  "a:11001010001:o:",
+  "a:110010010100:q:",
+  "a:11001001010100:!:",
+  "a:11001001010111:?:",
+  "a:1100100101010100:ESCAPE:",
+  "a:1100100101010110:;:",
+  "a:1100100101010111:):",
+  "a:1100100101011001:/:",
+  "a:1100100101011011:@:",
+  "a:11001001010101010:J:",
+  "a:11001001010101011:]:",
+  "a:11001001010110100:N:",
+  "a:11001001010110101:L:",
+  "a:110010010101100000:R:",
+  "a:110010010101100001:S:",
+  "a:110010010101100010:V:",
+  "a:11001001010110001100:[:",
+  "a:11001001010110001110:P:",
+  "a:11001001010110001111:STOP:",
+  "a:110010010101100011010:W:",
+  "a:110010010101100011011:1:",
+  "b:00:e:",
+  "b:010:u:",
+  "b:011:a:",
+  "b:100:y:",
+  "b:101:o:",
+  "b:1100:l:",
+  "b:1110:r:",
+  "b:1111:i:",
+  "b:110100:s:",
+  "b:110110: :",
+  "b:110111:b:",
+  "b:11010101:c:",
+  "b:110101000:j:",
+  "b:110101100:,:",
+  "b:110101101:.:",
+  "b:1101010011:':",
+  "b:1101011111:t:",
+  "b:11010100101:0x3a:",
+  "b:11010111000:w:",
+  "b:11010111001:d:",
+  "b:11010111010:h:",
+  "b:11010111011:&:",
+  "b:11010111101:-:",
+  "b:110101111000:m:",
+  "b:110101111001:n:",
+  "b:1101010010000:?:",
+  "b:1101010010010:v:",
+  "b:11010100100010:f:",
+  "b:11010100100111:p:",
+  "b:110101001000111:;:",
+  "b:110101001001101:D:",
+  "b:1101010010001100:/:",
+  "b:1101010010011001:@:",
+  "b:11010100100011010:X:",
+  "b:11010100100011011:\":",
+  "b:11010100100110001:k:",
+  "b:110101001001100000:STOP:",
+  "b:1101010010011000010:ESCAPE:",
+  "b:1101010010011000011:!:",
+  "c:00:o:",
+  "c:011:a:",
+  "c:100:e:",
+  "c:110:h:",
+  "c:0100:i:",
+  "c:0101:l:",
+  "c:1011:k:",
+  "c:1111:t:",
+  "c:10100:u:",
+  "c:10101:r:",
+  "c:11100: :",
+  "c:1110100:y:",
+  "c:1110101:c:",
+  "c:11101101:s:",
+  "c:11101110:.:",
+  "c:111011111:,:",
+  "c:1110110001:G:",
+  "c:11101100001:n:",
+  "c:11101100110:D:",
+  "c:11101111000:K:",
+  "c:11101111011:C:",
+  "c:111011000000:0x3a:",
+  "c:111011001001:-:",
+  "c:111011001010:A:",
+  "c:111011001110:L:",
+  "c:111011001111:':",
+  "c:111011110010:d:",
+  "c:111011110100:q:",
+  "c:111011110101:I:",
+  "c:1110110010000:N:",
+  "c:1110110010001:z:",
+  "c:1110111100111:F:",
+  "c:11101100000101:w:",
+  "c:11101100000111:E:",
+  "c:11101100101100:?:",
+  "c:11101111001100:M:",
+  "c:11101111001101:S:",
+  "c:111011000001000:b:",
+  "c:111011000001001:ESCAPE:",
+  "c:111011000001100:!:",
+  "c:111011001011010:Q:",
+  "c:111011001011011:P:",
+  "c:111011001011100:;:",
+  "c:111011001011110:B:",
+  "c:1110110000011011:V:",
+  "c:1110110010111011:m:",
+  "c:1110110010111110:/:",
+  "c:11101100000110101:):",
+  "c:11101100101110100:U:",
+  "c:11101100101111110:W:",
+  "c:111011000001101000:p:",
+  "c:111011000001101001:H:",
+  "c:111011001011101010:STOP:",
+  "c:111011001011111110:R:",
+  "c:111011001011111111:T:",
+  "c:1110110010111010110:]:",
+  "c:1110110010111010111:[:",
+  "d:0: :",
+  "d:101:e:",
+  "d:1100:a:",
+  "d:1110:i:",
+  "d:10001:.:",
+  "d:10011:o:",
+  "d:11011:r:",
+  "d:11111:s:",
+  "d:100001:d:",
+  "d:100101:l:",
+  "d:110100:u:",
+  "d:111101:y:",
+  "d:1001001:-:",
+  "d:1101011:v:",
+  "d:1111000:g:",
+  "d:1111001:,:",
+  "d:10000000:h:",
+  "d:10000001:0x3a:",
+  "d:10000010:m:",
+  "d:10010000:w:",
+  "d:10010001:n:",
+  "d:11010101:':",
+  "d:100000111:f:",
+  "d:1101010001:?:",
+  "d:1101010010:b:",
+  "d:1101010011:c:",
+  "d:10000011000:!:",
+  "d:11010100000:p:",
+  "d:11010100001:t:",
+  "d:100000110010:STOP:",
+  "d:100000110011:):",
+  "d:100000110100:k:",
+  "d:100000110101:;:",
+  "d:100000110111:/:",
+  "d:10000011011010:\":",
+  "d:10000011011011:j:",
+  "d:100000110110000:z:",
+  "d:100000110110011:q:",
+  "d:1000001101100011:@:",
+  "d:1000001101100100:ESCAPE:",
+  "d:10000011011000101:C:",
+  "d:10000011011001010:]:",
+  "d:100000110110001000:Z:",
+  "d:100000110110001001:[:",
+  "d:100000110110010110:T:",
+  "d:100000110110010111:`:",
+  "e:10: :",
+  "e:010:s:",
+  "e:110:r:",
+  "e:0000:d:",
+  "e:0011:a:",
+  "e:1111:n:",
+  "e:00010:c:",
+  "e:01100:e:",
+  "e:01101:w:",
+  "e:01111:t:",
+  "e:11100:l:",
+  "e:000110:x:",
+  "e:001000:v:",
+  "e:001001:i:",
+  "e:001010:y:",
+  "e:011100:m:",
+  "e:111010:.:",
+  "e:0001110:f:",
+  "e:0010111:b:",
+  "e:0111010:,:",
+  "e:1110110:p:",
+  "e:00011110:-:",
+  "e:00011111:h:",
+  "e:00101100:k:",
+  "e:01110110:':",
+  "e:11101110:g:",
+  "e:11101111:o:",
+  "e:001011011:0x3a:",
+  "e:0010110100:):",
+  "e:0010110101:q:",
+  "e:0111011101:?:",
+  "e:0111011110:u:",
+  "e:01110111000:z:",
+  "e:01110111110:!:",
+  "e:011101111110:STOP:",
+  "e:011101111111:j:",
+  "e:0111011100110:/:",
+  "e:01110111001001:4:",
+  "e:01110111001010:B:",
+  "e:01110111001110:]:",
+  "e:01110111001111:;:",
+  "e:011101110010000:\":",
+  "e:0111011100100011:D:",
+  "e:0111011100101100:ESCAPE:",
+  "e:0111011100101110:@:",
+  "e:01110111001000100:T:",
+  "e:01110111001000101:C:",
+  "e:01110111001011011:[:",
+  "e:01110111001011111:L:",
+  "e:011101110010110100:V:",
+  "e:011101110010110101:G:",
+  "e:011101110010111100:1:",
+  "e:01110111001011110101:E:",
+  "e:011101110010111101000:2:",
+  "e:011101110010111101001:N:",
+  "e:011101110010111101100:F:",
+  "e:011101110010111101101:A:",
+  "e:0111011100101111011100:\\:",
+  "e:0111011100101111011101:P:",
+  "e:0111011100101111011110:M:",
+  "e:0111011100101111011111:H:",
+  "f:00:o:",
+  "f:10: :",
+  "f:010:i:",
+  "f:110:r:",
+  "f:0111:a:",
+  "f:1110:e:",
+  "f:01100:t:",
+  "f:11110:u:",
+  "f:11111:f:",
+  "f:011011:l:",
+  "f:01101000:s:",
+  "f:01101001:y:",
+  "f:011010110:.:",
+  "f:0110101000:?:",
+  "f:0110101011:,:",
+  "f:0110101111:-:",
+  "f:01101010011:0x3a:",
+  "f:01101010100:':",
+  "f:01101010101:g:",
+  "f:011010100100:m:",
+  "f:011010111000:ESCAPE:",
+  "f:011010111010:b:",
+  "f:011010111011:n:",
+  "f:0110101001011:c:",
+  "f:0110101110010:!:",
+  "f:01101011100110:):",
+  "f:01101011100111:w:",
+  "f:011010100101001:p:",
+  "f:011010100101010:/:",
+  "f:0110101001010000:h:",
+  "f:0110101001010110:;:",
+  "f:01101010010100010:STOP:",
+  "f:01101010010100011:d:",
+  "f:01101010010101110:k:",
+  "f:01101010010101111:v:",
+  "g:11: :",
+  "g:000:a:",
+  "g:010:h:",
+  "g:101:e:",
+  "g:0011:u:",
+  "g:0110:r:",
+  "g:1000:i:",
+  "g:01110:l:",
+  "g:10010:s:",
+  "g:10011:o:",
+  "g:001001:,:",
+  "g:001010:n:",
+  "g:011110:g:",
+  "g:011111:.:",
+  "g:0010110:y:",
+  "g:00100001:':",
+  "g:00100010:-:",
+  "g:00100011:0x3a:",
+  "g:001000000:d:",
+  "g:001011101:b:",
+  "g:001011110:t:",
+  "g:001011111:w:",
+  "g:0010000010:?:",
+  "g:0010000011:m:",
+  "g:00101110001:!:",
+  "g:00101110011:f:",
+  "g:001011100001:;:",
+  "g:001011100101:STOP:",
+  "g:0010111000000:k:",
+  "g:0010111001000:p:",
+  "g:00101110000010:):",
+  "g:00101110000011:\":",
+  "g:001011100100101:c:",
+  "g:001011100100111:/:",
+  "g:0010111001001000:ESCAPE:",
+  "g:0010111001001100:]:",
+  "g:0010111001001101:z:",
+  "g:00101110010010010:`:",
+  "g:001011100100100110:v:",
+  "g:001011100100100111:@:",
+  "h:0:e:",
+  "h:100:o:",
+  "h:101:i:",
+  "h:110: :",
+  "h:1111:a:",
+  "h:111001:r:",
+  "h:111011:t:",
+  "h:11100001:y:",
+  "h:11100011:l:",
+  "h:11101000:.:",
+  "h:11101001:n:",
+  "h:11101011:u:",
+  "h:111000000:d:",
+  "h:111000100:s:",
+  "h:111010100:,:",
+  "h:1110000011:w:",
+  "h:1110001010:':",
+  "h:1110001011:-:",
+  "h:11101010101:m:",
+  "h:11101010110:0x3a:",
+  "h:11101010111:b:",
+  "h:111000001001:c:",
+  "h:111000001011:?:",
+  "h:111010101000:!:",
+  "h:1110000010000:):",
+  "h:1110000010100:h:",
+  "h:1110000010101:k:",
+  "h:1110101010011:f:",
+  "h:11101010100101:g:",
+  "h:111000001000100:p:",
+  "h:111000001000101:;:",
+  "h:111000001000110:/:",
+  "h:111000001000111:STOP:",
+  "h:111010101001001:v:",
+  "h:1110101010010000:q:",
+  "h:11101010100100010:ESCAPE:",
+  "h:111010101001000110:\":",
+  "h:11101010100100011100:z:",
+  "h:11101010100100011101:j:",
+  "h:11101010100100011110:]:",
+  "h:11101010100100011111:*:",
+  "i:10:n:",
+  "i:000:t:",
+  "i:010:s:",
+  "i:0011:l:",
+  "i:1100:o:",
+  "i:1101:c:",
+  "i:1111:e:",
+  "i:00100:a:",
+  "i:01100:m:",
+  "i:01101:d:",
+  "i:01110:v:",
+  "i:11100:g:",
+  "i:11101:r:",
+  "i:001010:p:",
+  "i:011110:f:",
+  "i:0010110:z:",
+  "i:0111110: :",
+  "i:00101111:b:",
+  "i:01111110:k:",
+  "i:001011100:-:",
+  "i:001011101:x:",
+  "i:0111111100:u:",
+  "i:0111111110:q:",
+  "i:01111111010:.:",
+  "i:01111111110:,:",
+  "i:011111110111:w:",
+  "i:011111111111:':",
+  "i:0111111101101:i:",
+  "i:0111111111101:j:",
+  "i:01111111011001:0x3a:",
+  "i:01111111111000:h:",
+  "i:011111110110000:/:",
+  "i:011111111110011:y:",
+  "i:0111111101100011:?:",
+  "i:0111111111100100:P:",
+  "i:01111111011000101:R:",
+  "i:01111111111001011:!:",
+  "i:011111111110010100:):",
+  "i:011111111110010101:S:",
+  "i:0111111101100010000:STOP:",
+  "i:0111111101100010001:C:",
+  "i:0111111101100010010:ESCAPE:",
+  "i:01111111011000100110:D:",
+  "i:01111111011000100111:;:",
+  "j:0:o:",
+  "j:11:u:",
+  "j:101:a:",
+  "j:1001:e:",
+  "j:10000:i:",
+  "j:100011:y:",
+  "j:1000101: :",
+  "j:10001001:.:",
+  "j:100010000:':",
+  "j:1000100011:t:",
+  "j:10001000100:n:",
+  "j:100010001011:s:",
+  "j:1000100010100:ESCAPE:",
+  "j:1000100010101:h:",
+  "k:10: :",
+  "k:11:e:",
+  "k:000:s:",
+  "k:011:i:",
+  "k:0010:.:",
+  "k:01001:y:",
+  "k:001100:':",
+  "k:001101:a:",
+  "k:001110:p:",
+  "k:001111:,:",
+  "k:010100:l:",
+  "k:010101:f:",
+  "k:010110:n:",
+  "k:0100000:/:",
+  "k:0100010:-:",
+  "k:0100011:o:",
+  "k:01011101:0x3a:",
+  "k:010000111:b:",
+  "k:010111000:w:",
+  "k:010111001:m:",
+  "k:010111100:h:",
+  "k:010111110:u:",
+  "k:010111111:k:",
+  "k:0100001000:r:",
+  "k:0100001001:ESCAPE:",
+  "k:0100001010:?:",
+  "k:0100001100:t:",
+  "k:0100001101:g:",
+  "k:0101111011:d:",
+  "k:01000010110:j:",
+  "k:010000101110:):",
+  "k:010111101000:;:",
+  "k:010111101001:c:",
+  "k:010111101010:S:",
+  "k:0100001011110:v:",
+  "k:0100001011111:R:",
+  "k:0101111010110:!:",
+  "k:01011110101110:@:",
+  "k:010111101011110:\":",
+  "k:010111101011111:STOP:",
+  "l:010:a:",
+  "l:011:i:",
+  "l:100:l:",
+  "l:110:e:",
+  "l:111: :",
+  "l:0000:u:",
+  "l:0001:d:",
+  "l:0010:y:",
+  "l:1011:o:",
+  "l:10100:s:",
+  "l:001100:.:",
+  "l:001110:t:",
+  "l:0011010:v:",
+  "l:0011110:f:",
+  "l:1010100:m:",
+  "l:1010101:k:",
+  "l:1010110:p:",
+  "l:00110111:c:",
+  "l:00111110:-:",
+  "l:10101111:,:",
+  "l:001101101:0x3a:",
+  "l:001111111:b:",
+  "l:101011100:':",
+  "l:0011011000:r:",
+  "l:0011011001:h:",
+  "l:0011111100:n:",
+  "l:0011111101:g:",
+  "l:1010111011:w:",
+  "l:10101110100:?:",
+  "l:1010111010100:!:",
+  "l:1010111010110:z:",
+  "l:10101110101011:/:",
+  "l:101011101010100:;:",
+  "l:101011101011100:E:",
+  "l:101011101011101:*:",
+  "l:101011101011111:STOP:",
+  "l:1010111010101011:ESCAPE:",
+  "l:1010111010111100:):",
+  "l:10101110101010100:@:",
+  "l:10101110101010101:j:",
+  "l:10101110101111010:\":",
+  "l:101011101011110110:[:",
+  "l:101011101011110111:]:",
+  "m:00:a:",
+  "m:01:e:",
+  "m:111: :",
+  "m:1001:p:",
+  "m:1011:o:",
+  "m:1100:i:",
+  "m:10000:.:",
+  "m:10001:s:",
+  "m:11010:u:",
+  "m:11011:m:",
+  "m:101001:y:",
+  "m:101011:b:",
+  "m:1010000:,:",
+  "m:1010100:/:",
+  "m:10100010:]:",
+  "m:101000110:0x3a:",
+  "m:101010100:':",
+  "m:1010001111:r:",
+  "m:1010101011:f:",
+  "m:1010101100:l:",
+  "m:1010101110:n:",
+  "m:10100011100:?:",
+  "m:10100011101:!:",
+  "m:10101010100:STOP:",
+  "m:10101010101:w:",
+  "m:10101011011:h:",
+  "m:10101011110:-:",
+  "m:101010111110:4:",
+  "m:1010101101010:t:",
+  "m:1010101101011:@:",
+  "m:1010101111110:;:",
+  "m:1010101111111:c:",
+  "m:10101011010000:):",
+  "m:10101011010001:ESCAPE:",
+  "m:10101011010011:d:",
+  "m:101010110100101:g:",
+  "m:10101011010010000:[:",
+  "m:10101011010010001:v:",
+  "m:10101011010010010:k:",
+  "m:10101011010010011:z:",
+  "n:01: :",
+  "n:001:t:",
+  "n:100:g:",
+  "n:111:d:",
+  "n:0000:s:",
+  "n:1010:a:",
+  "n:1101:e:",
+  "n:10110:c:",
+  "n:11000:i:",
+  "n:000111:.:",
+  "n:101111:n:",
+  "n:110011:o:",
+  "n:0001001:u:",
+  "n:0001011:v:",
+  "n:0001100:f:",
+  "n:1011100:k:",
+  "n:1011101:':",
+  "n:1100100:y:",
+  "n:1100101:,:",
+  "n:00010000:m:",
+  "n:00010100:l:",
+  "n:00010101:-:",
+  "n:000100011:w:",
+  "n:000110101:0x3a:",
+  "n:0001000101:z:",
+  "n:0001101000:h:",
+  "n:0001101100:b:",
+  "n:0001101101:j:",
+  "n:0001101110:r:",
+  "n:00010001000:p:",
+  "n:00011010011:x:",
+  "n:00011011111:?:",
+  "n:000100010011:;:",
+  "n:000110100101:):",
+  "n:000110111100:!:",
+  "n:000110111101:q:",
+  "n:0001000100100:/:",
+  "n:0001000100101:STOP:",
+  "n:0001101001000:ESCAPE:",
+  "n:00011010010010:B:",
+  "n:0001101001001100:]:",
+  "n:0001101001001101:\":",
+  "n:0001101001001110:@:",
+  "n:0001101001001111:*:",
+  "o:001:u:",
+  "o:011: :",
+  "o:100:r:",
+  "o:111:n:",
+  "o:0000:l:",
+  "o:1100:m:",
+  "o:1101:f:",
+  "o:00010:v:",
+  "o:01000:s:",
+  "o:01001:p:",
+  "o:10100:t:",
+  "o:10101:o:",
+  "o:10111:w:",
+  "o:000110:k:",
+  "o:000111:i:",
+  "o:010100:g:",
+  "o:010111:c:",
+  "o:101101:d:",
+  "o:0101011:e:",
+  "o:0101100:y:",
+  "o:0101101:a:",
+  "o:1011001:b:",
+  "o:01010101:h:",
+  "o:10110000:.:",
+  "o:010101000:-:",
+  "o:010101001:,:",
+  "o:1011000101:':",
+  "o:1011000111:x:",
+  "o:10110001001:0x3a:",
+  "o:10110001101:z:",
+  "o:101100010001:?:",
+  "o:101100011001:j:",
+  "o:1011000100000:!:",
+  "o:1011000110001:q:",
+  "o:10110001000010:J:",
+  "o:10110001100000:/:",
+  "o:10110001100001:):",
+  "o:1011000100001101:;:",
+  "o:1011000100001110:G:",
+  "o:10110001000011000:\":",
+  "o:10110001000011110:ESCAPE:",
+  "o:101100010000110010:]:",
+  "o:101100010000110011:@:",
+  "o:1011000100001111100:4:",
+  "o:1011000100001111101:STOP:",
+  "o:1011000100001111110:B:",
+  "o:10110001000011111110:O:",
+  "o:10110001000011111111:C:",
+  "p:001:l:",
+  "p:010: :",
+  "p:011:o:",
+  "p:101:r:",
+  "p:111:e:",
+  "p:0000:p:",
+  "p:1100:a:",
+  "p:1101:i:",
+  "p:00011:t:",
+  "p:10000:u:",
+  "p:10001:h:",
+  "p:10010:s:",
+  "p:000101:m:",
+  "p:0001001:d:",
+  "p:1001101:y:",
+  "p:1001110:.:",
+  "p:1001111:,:",
+  "p:00010000:-:",
+  "p:000100011:?:",
+  "p:100110001:0x3a:",
+  "p:1001100100:':",
+  "p:1001100101:]:",
+  "p:1001100110:+:",
+  "p:1001100111:b:",
+  "p:00010001001:f:",
+  "p:00010001010:k:",
+  "p:00010001011:!:",
+  "p:10011000001:c:",
+  "p:10011000010:n:",
+  "p:10011000011:w:",
+  "p:000100010000:STOP:",
+  "p:000100010001:;:",
+  "p:100110000001:/:",
+  "p:1001100000001:g:",
+  "p:10011000000001:):",
+  "p:100110000000001:\":",
+  "p:1001100000000001:S:",
+  "p:10011000000000000:ESCAPE:",
+  "p:10011000000000001:B:",
+  "q:1:u:",
+  "q:000:,:",
+  "q:001:.:",
+  "q:011: :",
+  "q:01001:b:",
+  "q:01010:':",
+  "q:01011:i:",
+  "q:010001:a:",
+  "q:01000000:?:",
+  "q:01000001:0x3a:",
+  "q:01000011:):",
+  "q:010000100:ESCAPE:",
+  "q:010000101:w:",
+  "r:000:a:",
+  "r:001:o:",
+  "r:100:i:",
+  "r:110: :",
+  "r:111:e:",
+  "r:0100:s:",
+  "r:0101:t:",
+  "r:01110:d:",
+  "r:10100:n:",
+  "r:10101:y:",
+  "r:011010:u:",
+  "r:011011:m:",
+  "r:011111:k:",
+  "r:101101:l:",
+  "r:101110:.:",
+  "r:101111:r:",
+  "r:0110000:f:",
+  "r:0110010:,:",
+  "r:0110011:v:",
+  "r:1011000:c:",
+  "r:1011001:g:",
+  "r:01100011:':",
+  "r:01111000:-:",
+  "r:01111001:b:",
+  "r:01111011:p:",
+  "r:011000101:0x3a:",
+  "r:011110100:w:",
+  "r:0111101010:?:",
+  "r:0111101011:h:",
+  "r:01100010010:!:",
+  "r:011000100001:q:",
+  "r:011000100010:j:",
+  "r:011000100011:STOP:",
+  "r:011000100110:/:",
+  "r:0110001000001:;:",
+  "r:0110001001111:):",
+  "r:01100010011100:8:",
+  "r:01100010011101:z:",
+  "r:011000100000001:\":",
+  "r:011000100000011:]:",
+  "r:0110001000000000:T:",
+  "r:0110001000000100:x:",
+  "r:0110001000000101:ESCAPE:",
+  "r:01100010000000011:Z:",
+  "r:011000100000000100:*:",
+  "r:0110001000000001010:D:",
+  "r:0110001000000001011:B:",
+  "s:0: :",
+  "s:101:t:",
+  "s:1000:.:",
+  "s:1110:e:",
+  "s:10011:,:",
+  "s:11000:o:",
+  "s:11001:s:",
+  "s:11110:h:",
+  "s:11111:i:",
+  "s:100101:c:",
+  "s:110100:u:",
+  "s:110110:p:",
+  "s:1101111:a:",
+  "s:10010001:n:",
+  "s:10010011:m:",
+  "s:11010100:y:",
+  "s:11010110:0x3a:",
+  "s:11011100:l:",
+  "s:11011101:k:",
+  "s:100100001:b:",
+  "s:100100100:f:",
+  "s:110101010:w:",
+  "s:110101111:':",
+  "s:1001000000:!:",
+  "s:1001000001:g:",
+  "s:1001001010:r:",
+  "s:1101010110:?:",
+  "s:1101010111:-:",
+  "s:1101011101:q:",
+  "s:11010111001:d:",
+  "s:100100101100:/:",
+  "s:100100101101:):",
+  "s:100100101111:STOP:",
+  "s:110101110000:]:",
+  "s:110101110001:;:",
+  "s:1001001011101:v:",
+  "s:100100101110001:\":",
+  "s:100100101110011:z:",
+  "s:1001001011100000:j:",
+  "s:1001001011100001:ESCAPE:",
+  "s:1001001011100100:[:",
+  "s:10010010111001011:@:",
+  "s:100100101110010101:T:",
+  "s:1001001011100101000:x:",
+  "s:1001001011100101001:`:",
+  "t:10:h:",
+  "t:000:i:",
+  "t:010:o:",
+  "t:011:e:",
+  "t:111: :",
+  "t:0010:a:",
+  "t:00110:u:",
+  "t:11001:r:",
+  "t:11011:s:",
+  "t:001111:.:",
+  "t:110001:t:",
+  "t:110100:y:",
+  "t:0011101:c:",
+  "t:1100001:l:",
+  "t:00111001:-:",
+  "t:11000000:v:",
+  "t:11000001:m:",
+  "t:11010101:w:",
+  "t:11010110:,:",
+  "t:11010111:':",
+  "t:001110000:n:",
+  "t:0011100011:?:",
+  "t:1101010001:b:",
+  "t:1101010010:0x3a:",
+  "t:00111000100:!:",
+  "t:11010100000:z:",
+  "t:11010100110:d:",
+  "t:11010100111:f:",
+  "t:110101000010:x:",
+  "t:0011100010100:g:",
+  "t:0011100010101:;:",
+  "t:1101010000110:p:",
+  "t:00111000101100:P:",
+  "t:00111000101101:STOP:",
+  "t:00111000101111:):",
+  "t:11010100001110:/:",
+  "t:11010100001111:k:",
+  "t:0011100010111000:@:",
+  "t:0011100010111010:E:",
+  "t:00111000101110011:]:",
+  "t:00111000101110111:\":",
+  "t:001110001011100100:F:",
+  "t:001110001011101100:ESCAPE:",
+  "t:0011100010111001010:j:",
+  "t:0011100010111011010:1:",
+  "t:0011100010111011011:[:",
+  "t:00111000101110010110:\\:",
+  "t:001110001011100101110:K:",
+  "t:001110001011100101111:C:",
+  "u:011:t:",
+  "u:101:n:",
+  "u:110:s:",
+  "u:111:r:",
+  "u:0001:d:",
+  "u:0010:e:",
+  "u:0101:l:",
+  "u:1000:p:",
+  "u:00000:b:",
+  "u:00001: :",
+  "u:00110:i:",
+  "u:01000:a:",
+  "u:01001:g:",
+  "u:10010:c:",
+  "u:10011:m:",
+  "u:0011100:y:",
+  "u:00111010:z:",
+  "u:00111100:':",
+  "u:00111110:f:",
+  "u:00111111:k:",
+  "u:001111010:,:",
+  "u:0011101101:-:",
+  "u:0011101110:o:",
+  "u:0011110110:.:",
+  "u:0011110111:x:",
+  "u:00111011000:w:",
+  "u:00111011110:0x3a:",
+  "u:001110110010:q:",
+  "u:001110111110:h:",
+  "u:001110111111:v:",
+  "u:0011101100110:j:",
+  "u:001110110011100:u:",
+  "u:001110110011101:?:",
+  "u:0011101100111110:/:",
+  "u:0011101100111111:!:",
+  "u:00111011001111001:ESCAPE:",
+  "u:001110110011110000:\\:",
+  "u:001110110011110001:STOP:",
+  "u:001110110011110100:;:",
+  "u:001110110011110110:J:",
+  "u:001110110011110111:):",
+  "u:0011101100111101010:T:",
+  "u:0011101100111101011:]:",
+  "v:1:e:",
+  "v:01:i:",
+  "v:000:a:",
+  "v:0011:o:",
+  "v:00101:.:",
+  "v:001001: :",
+  "v:00100001:':",
+  "v:00100011:y:",
+  "v:001000000:u:",
+  "v:001000100:s:",
+  "v:0010001010:r:",
+  "v:00100000100:-:",
+  "v:00100000110:,:",
+  "v:00100010110:n:",
+  "v:001000001010:g:",
+  "v:001000001011:v:",
+  "v:001000001111:l:",
+  "v:001000101110:@:",
+  "v:001000101111:0x3a:",
+  "v:0010000011101:k:",
+  "v:00100000111000:b:",
+  "v:001000001110010:t:",
+  "v:0010000011100110:d:",
+  "v:00100000111001110:/:",
+  "v:001000001110011110:ESCAPE:",
+  "v:001000001110011111:1:",
+  "w:00:i:",
+  "w:011:e:",
+  "w:100: :",
+  "w:101:s:",
+  "w:110:h:",
+  "w:0101:a:",
+  "w:1111:o:",
+  "w:01000:.:",
+  "w:01001:w:",
+  "w:11100:n:",
+  "w:1110110:r:",
+  "w:11101010:,:",
+  "w:11101011:l:",
+  "w:11101111:y:",
+  "w:111010010:c:",
+  "w:111011101:b:",
+  "w:1110100010:0x3a:",
+  "w:1110100110:m:",
+  "w:1110100111:':",
+  "w:1110111000:d:",
+  "w:11101000000:f:",
+  "w:11101000001:]:",
+  "w:11101000010:!:",
+  "w:11101000111:k:",
+  "w:11101110010:-:",
+  "w:111010000111:g:",
+  "w:111010001100:?:",
+  "w:111010001101:t:",
+  "w:111011100111:p:",
+  "w:1110100001100:STOP:",
+  "w:1110100001101:u:",
+  "w:1110111001101:):",
+  "w:11101110011001:j:",
+  "w:111011100110001:q:",
+  "w:1110111001100000:/:",
+  "w:11101110011000010:;:",
+  "w:111011100110000111:[:",
+  "w:1110111001100001100:ESCAPE:",
+  "w:1110111001100001101:B:",
+  "x:01:p:",
+  "x:11:t:",
+  "x:101: :",
+  "x:0000:i:",
+  "x:0010:a:",
+  "x:1000:c:",
+  "x:00010:u:",
+  "x:00111:e:",
+  "x:10011:-:",
+  "x:000110:f:",
+  "x:001101:o:",
+  "x:100100:.:",
+  "x:0001110:,:",
+  "x:0001111:m:",
+  "x:0011001:y:",
+  "x:00110001:9:",
+  "x:10010101:':",
+  "x:10010110:q:",
+  "x:001100000:s:",
+  "x:100101000:0x3a:",
+  "x:100101110:h:",
+  "x:0011000011:?:",
+  "x:1001010010:l:",
+  "x:1001011110:w:",
+  "x:00110000100:A:",
+  "x:10010100110:x:",
+  "x:10010100111:b:",
+  "x:10010111111:):",
+  "x:001100001011:/:",
+  "x:0011000010100:4:",
+  "x:0011000010101:!:",
+  "x:1001011111000:g:",
+  "x:1001011111001:STOP:",
+  "x:1001011111011:;:",
+  "x:100101111101001:v:",
+  "x:100101111101010:F:",
+  "x:100101111101011:E:",
+  "x:1001011111010000:ESCAPE:",
+  "x:1001011111010001:C:",
+  "y:1: :",
+  "y:000:o:",
+  "y:0011:s:",
+  "y:0101:.:",
+  "y:01001:,:",
+  "y:01100:e:",
+  "y:01110:':",
+  "y:001001:a:",
+  "y:001010:i:",
+  "y:001011:d:",
+  "y:010001:n:",
+  "y:011011:0x3a:",
+  "y:011111:l:",
+  "y:0010000:w:",
+  "y:0110100:t:",
+  "y:0110101:m:",
+  "y:0111101:-:",
+  "y:00100011:b:",
+  "y:01000000:?:",
+  "y:01000001:r:",
+  "y:01000010:p:",
+  "y:01000011:f:",
+  "y:01111001:c:",
+  "y:0010001001:;:",
+  "y:0010001010:J:",
+  "y:0111100000:h:",
+  "y:0111100001:!:",
+  "y:0111100011:g:",
+  "y:00100010000:):",
+  "y:00100010111:/:",
+  "y:01111000101:]:",
+  "y:001000100011:k:",
+  "y:001000101100:ESCAPE:",
+  "y:001000101101:u:",
+  "y:011110001001:STOP:",
+  "y:0010001000100:z:",
+  "y:0111100010001:\":",
+  "y:00100010001011:j:",
+  "y:01111000100001:2:",
+  "y:001000100010100:y:",
+  "y:001000100010101:x:",
+  "y:0111100010000000:v:",
+  "y:0111100010000001:T:",
+  "y:0111100010000010:E:",
+  "y:0111100010000011:P:",
+  "z:10:e:",
+  "z:001:a:",
+  "z:011:z:",
+  "z:110: :",
+  "z:111:i:",
+  "z:0001:l:",
+  "z:0100:y:",
+  "z:01010:o:",
+  "z:000000:c:",
+  "z:000010:,:",
+  "z:000011:.:",
+  "z:010110:w:",
+  "z:0000010:':",
+  "z:00000110:0x3a:",
+  "z:00000111:t:",
+  "z:01011101:m:",
+  "z:010111000:k:",
+  "z:010111100:-:",
+  "z:010111101:u:",
+  "z:010111111:b:",
+  "z:01011100100:s:",
+  "z:01011100101:/:",
+  "z:01011100111:d:",
+  "z:01011111001:p:",
+  "z:01011111011:?:",
+  "z:010111001100:h:",
+  "z:010111110000:@:",
+  "z:010111110100:):",
+  "z:0101110011010:!:",
+  "z:0101111100011:v:",
+  "z:0101111101010:g:",
+  "z:01011100110110:f:",
+  "z:01011100110111:r:",
+  "z:01011111000100:q:",
+  "z:01011111000101:n:",
+  "z:01011111010110:ESCAPE:",
+  "z:01011111010111:]:",
+  "{:0:ESCAPE:",
+  "{:1:ESCAPE:",
+  "|:0:ESCAPE:",
+  "|:1:ESCAPE:",
+  "}:0:ESCAPE:",
+  "}:1:STOP:",
+  "~:0:ESCAPE:",
+  "~:1:ESCAPE:",
+  "0x7f:0:ESCAPE:",
+  "0x7f:1:ESCAPE:",
+  NULL,
+};
+
+// MediaHighWay Ver. 1
+
+typedef struct
+{
+  u_char Name                   [15];
+} sThemeMHW1;
+
+typedef struct
+{
+  u_char NetworkIdHigh            :8;
+  u_char NetworkIdLow             :8;
+  u_char TransportIdHigh          :8;
+  u_char TransportIdLow           :8;
+  u_char ServiceIdHigh            :8;
+  u_char ServiceIdLow             :8;
+  u_char Name                   [16];
+} sChannelMHW1;
+
+typedef struct
+{
+  u_char TableId                  :8;
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char SectionSyntaxIndicator   :1;
+  u_char                          :1;
+  u_char                          :2;
+  u_char SectionLengthHigh        :4;
+#else
+  u_char SectionLengthHigh        :4;
+  u_char                          :2;
+  u_char                          :1;
+  u_char SectionSyntaxIndicator   :1;
+#endif
+  u_char SectionLengthLow         :8;
+  u_char ChannelId                :8;
+  u_char ThemeId                  :8;
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char Day                      :3;
+  u_char Hours                    :5;
+#else
+  u_char Hours                    :5;
+  u_char Day                      :3;
+#endif
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char Minutes                  :6;
+  u_char                          :1;
+  u_char SummaryAvailable         :1;
+#else
+  u_char SummaryAvailable         :1;
+  u_char                          :1;
+  u_char Minutes                  :6;
+#endif
+  u_char                          :8;
+  u_char                          :8;
+  u_char DurationHigh             :8;
+  u_char DurationLow              :8;
+  u_char Title                  [23];
+  u_char PpvIdHigh                :8;
+  u_char PpvIdMediumHigh          :8;
+  u_char PpvIdMediumLow           :8;
+  u_char PpvIdLow                 :8;
+  u_char ProgramIdHigh            :8;
+  u_char ProgramIdMediumHigh      :8;
+  u_char ProgramIdMediumLow       :8;
+  u_char ProgramIdLow             :8;
+  u_char                          :8;
+  u_char                          :8;
+  u_char                          :8;
+  u_char                          :8;
+} sTitleMHW1;
+
+typedef struct {
+  u_char TableId                  :8;
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char SectionSyntaxIndicator   :1;
+  u_char                          :1;
+  u_char                          :2;
+  u_char SectionLengthHigh        :4;
+#else
+  u_char SectionLengthHigh        :4;
+  u_char                          :2;
+  u_char                          :1;
+  u_char SectionSyntaxIndicator   :1;
+#endif
+  u_char SectionLengthLow         :8;
+  u_char ProgramIdHigh            :8;
+  u_char ProgramIdMediumHigh      :8;
+  u_char ProgramIdMediumLow       :8;
+  u_char ProgramIdLow             :8;
+  u_char Byte7                    :8;
+  u_char Byte8                    :8;
+  u_char Byte9                    :8;
+  u_char NumReplays               :8;
+} sSummaryMHW1;
+
+typedef struct {
+  u_char TableId		  :8;
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char SectionSyntaxIndicator   :1;
+  u_char                          :1;
+  u_char                          :2;
+  u_char SectionLengthHigh        :4;
+#else
+  u_char SectionLengthHigh        :4;
+  u_char                          :2;
+  u_char                          :1;
+  u_char SectionSyntaxIndicator   :1;
+#endif
+  u_char SectionLengthLow         :8;
+  u_char TableIdExtensionHigh	  :8;
+  u_char TableIdExtensionLow	  :8;
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char Reserved  		  :2;
+  u_char VersionNumber 		  :5;
+  u_char CurrentNextIndicator	  :1;
+#else
+  u_char CurrentNextIndicator	  :1;
+  u_char VersionNumber 		  :5;
+  u_char Reserved  		  :2;
+#endif
+  u_char SectionNumber		  :8;
+  u_char LastSectionNumber	  :8;
+  u_char LanguageCodeHigh	  :8;
+  u_char LanguageCodeMedium	  :8;
+  u_char LanguageCodeLow	  :8;
+  u_char AlwaysZero0		  :8;
+} sTitleBlockHeaderNagraGuide;
+
+typedef struct {
+  u_char ChannelIdHigh	          :8;
+  u_char ChannelIdLow	          :8;
+  u_char BlocklengthHigh          :8;
+  u_char BlocklengthLow           :8;
+  u_char NumberOfTitlesHigh       :8;
+  u_char NumberOfTitlesMediumHigh :8;
+  u_char NumberOfTitlesMediumLow  :8;
+  u_char NumberOfTitlesLow        :8;
+} sTitleBlockNagraGuide;             //all titles in one block are on the same channel
+
+typedef struct {
+  u_char EventIdHigh		  :8;
+  u_char EventIdMediumHigh	  :8;
+  u_char EventIdMediumLow	  :8;
+  u_char EventIdLow		  :8;
+  u_char StartTimeHigh		  :8;
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char StartTimeLow		  :5;
+  u_char AlwaysZero16		  :3;
+#else
+  u_char AlwaysZero16		  :3;//can be 1,2,3 or 4 with night-programs etc.???
+  u_char StartTimeLow		  :5;
+#endif
+  u_char Duration		  :8;
+  u_char AlwaysZero1		  :8;
+  u_char AlwaysZero2		  :8;
+  u_char AlwaysZero3		  :8;
+  u_char AlwaysZero4		  :8;
+  u_char AlwaysZero5		  :8;
+  u_char SumDataOffsetHigh	  :8;//address of relevant Summary Data Record 
+  u_char SumDataOffsetMediumHigh  :8;
+  u_char SumDataOffsetMediumLow   :8;
+  u_char SumDataOffsetLow         :8;
+  u_char AlwaysZero8		  :8;
+  u_char AlwaysZero9		  :8;
+  u_char AlwaysZero10		  :8;
+  u_char AlwaysZero11		  :8;
+  u_char OffsetToTextHigh	  :8;//offset from 2nd byte after languagecode gives length byte of title-text
+  u_char OffsetToTextMediumHigh	  :8;
+  u_char OffsetToTextMediumLow	  :8;
+  u_char OffsetToTextLow	  :8;
+  u_char OffsetToText2High	  :8;//offset from 2nd byte after languagecode gives length byte of title-text2
+  u_char OffsetToText2MediumHigh  :8;
+  u_char OffsetToText2MediumLow	  :8;
+  u_char OffsetToText2Low	  :8;
+  u_char ThemeId		  :8;
+  u_char AlwaysZero17		  :8;
+} sTitleNagraGuide;
+
+//first 4 bytes with zeroterminated language code
+typedef struct {
+  u_char AlwaysZero1              :8;
+  u_char AlwaysZero2              :8;
+  u_char AlwaysZero3              :8;
+  u_char AlwaysZero4              :8;
+  u_char Always1                  :8;
+  u_char Always9                  :8;
+  u_char Always7                  :8;
+  u_char Always0                  :8;
+  u_char AlwaysZero5              :8;
+  u_char AlwaysZero6              :8;
+  u_char AlwaysZero7              :8;
+  u_char AlwaysZero8              :8;
+  u_char AlwaysZero9              :8;
+  u_char Always0x01               :8;
+  u_char EventIdHigh              :8;
+  u_char EventIdMediumHigh        :8;
+  u_char EventIdMediumLow         :8;
+  u_char EventIdLow               :8;
+  u_char NumberOfBlocks           :8;//every block > 2 adds 4 bytes, if block = 1 then no summtxtoffset so subtract 4 bytes!
+  u_char BlockIdHigh              :8;
+  u_char BlockIdMediumHigh        :8;
+  u_char BlockIdMediumLow         :8;
+  u_char BlockIdLow               :8;
+  u_char SummTxtOffsetHigh        :8;//address from start of section + 4 points to relevant Always0x4e
+  u_char SummTxtOffsetMediumHigh  :8;
+  u_char SummTxtOffsetMediumLow   :8;
+  u_char SummTxtOffsetLow         :8;
+  u_char Unknown1                 :8;
+  u_char Unknown2                 :8;
+} sSummaryDataNagraGuide;
+
+typedef struct {
+  u_char Always0x4e               :8;//if 0x4e summarytext follows if 0x8c no summarytext GBR record follows
+  u_char Blocklength              :8;
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char TextNr                   :4;
+  u_char LastTextNr               :4;
+#else
+  u_char LastTextNr               :4;//last nr of block of text
+  u_char TextNr                   :4;//nr of a block of text, starts with 0!!!
+#endif
+  u_char LanguageCodeHigh         :8;
+  u_char LanguageCodeMedium       :8;
+  u_char LanguageCodeLow          :8;
+  u_char AlwaysZero1              :8;
+  u_char Textlength               :8;
+  u_char Text                     :8;
+} sSummaryTextNagraGuide;
+
+typedef struct {
+  u_char Always0x8c               :8;
+  u_char Blocklength              :8;
+  u_char AlwaysZero1              :8;
+  u_char AlwaysZero2              :8;
+  u_char Un1		          :8;
+  u_char Un2		          :8;
+  u_char Un3		          :8;
+  u_char Un4		          :8;
+  u_char AlwaysZero3              :8;
+  u_char Un5		          :8;
+  u_char Un6		          :8;
+  u_char Un7		          :8;
+  u_char AlwaysZero4              :8;
+  u_char Un8		          :8;
+  u_char Un9		          :8;
+  u_char Nextlength               :8;
+  u_char Always0x81		  :8;
+  u_char EventIdHigh		  :8;
+  u_char EventIdMedium		  :8;
+  u_char EventIdLow		  :8;
+} sSummaryGBRNagraGuide;
+
+typedef struct {
+  u_char SatId                    :8;//is always 0x01
+  u_char NetworkIdHigh            :8;
+  u_char NetworkIdLow             :8;
+  u_char TransportIdHigh          :8;
+  u_char TransportIdLow	          :8;
+  u_char ServiceIdHigh	          :8;
+  u_char ServiceIdLow	          :8;
+  u_char Nr8cBlocks		  :8;
+  u_char Always0x8c               :8;//next three fields are 0x00 for FTA channels....
+  u_char Nr8cBytes                :8;
+  u_char AlwaysZero1              :8;//from here on optional fields, not used for FTA channels like BVN, regional S23.5 broadcasts
+  u_char ProviderIdHigh		  :8;
+  u_char ProviderIdLow		  :8;
+  u_char Always0x08		  :8;
+  u_char Always0x02		  :8;
+  u_char Always0x01		  :8;
+  u_char AlwaysZero2              :8;
+  u_char Always0x20               :8;
+  u_char Always0x0a               :8;
+  u_char Un4		          :8;
+  u_char Always0x81               :8;
+  u_char Un5		          :8;
+  u_char Always0x44               :8;
+  u_char Un6		          :8;
+  u_char Un7		          :8;
+  u_char Un8		          :8;
+  u_char Un9		          :8;
+} sChannelsNagraGuide;
+
+typedef struct {
+  u_char TitleOffsetHigh          :8;//address from start of section (in 0x02x0) + 4 points to eventid of title that has this theme
+  u_char TitleOffsetMediumHigh    :8;
+  u_char TitleOffsetMediumLow     :8;
+  u_char TitleOffsetLow           :8;
+  u_char AlwaysZero1              :8;
+  u_char Un1		          :8;
+  u_char AlwaysZero2              :8;
+  u_char Always1                  :8;
+} sThemesTitlesNagraGuide;
+
+typedef struct { //first three bytes form unknown header, then X blocks, where X = number of distinct table_id_extensio
+#if BYTE_ORDER == BIG_ENDIAN
+  u_char TableIdExtensionLow	  :6;//BIG_ENDIAN not tested!!
+  u_char TableIdExtensionHigh	  :2;
+  u_char TIE200     	  	  :1;
+  u_char Unknown1     	  	  :2;
+  u_char VersionNumber     	  :5;//contains current version of table_id_extension
+#else
+  u_char TableIdExtensionHigh	  :2;
+  u_char TableIdExtensionLow	  :6;
+  u_char VersionNumber     	  :5;//contains current version of table_id_extension
+  u_char Unknown1     	  	  :2;
+  u_char TIE200     	  	  :1;
+#endif
+  u_char Always0xd6               :8;
+  u_char DayCounter               :8;//for most sections this increments each day
+} sSection0000BlockNagraGuide;
+
+#define HILO16( x ) ( ( ( x##High << 8 ) | x##Low ) & 0xffff )
+#define HILO32( x ) ( ( ( ( ( x##High << 24 ) | ( x##MediumHigh << 16 ) ) | ( x##MediumLow << 8 ) ) | x##Low ) & 0xffffffff )
+#define MjdToEpochTime(x) (((x##_hi << 8 | x##_lo)-40587)*86400)
diff --git a/eit2.c b/eit2.c
new file mode 100644
index 0000000..3980dba
--- /dev/null
+++ b/eit2.c
@@ -0,0 +1,587 @@
+/*
+ * eit2.c
+ *
+ *  Created on: Oct 16, 2012
+ *      Author: d.petrovski
+ */
+#include "eit2.h"
+
+#include <string>
+#include <vdr/config.h>
+#include "log.h"
+#include "util.h"
+#include "dish.h"
+#include "equivhandler.h"
+
+using namespace std;
+using namespace util;
+
+namespace SI
+{
+
+cEvent* cEIT2::ProcessEitEvent(cSchedule* pSchedule,const SI::EIT::Event* EitEvent,
+                               uchar Tid, uchar versionNumber)
+{
+  bool ExternalData = false;
+  // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number.
+  if (EitEvent->getStartTime () == 0 || (EitEvent->getStartTime () > 0 && EitEvent->getDuration () == 0))
+    return NULL;
+  Empty = false;
+  if (!SegmentStart)
+    SegmentStart = EitEvent->getStartTime ();
+  SegmentEnd = EitEvent->getStartTime () + EitEvent->getDuration ();
+  //    int versionNumber = getVersionNumber();
+
+  cEvent *newEvent = NULL;
+  cEvent *pEvent = (cEvent *) pSchedule->GetEvent (EitEvent->getEventId (), EitEvent->getStartTime ());
+  if (!pEvent) {
+    if (OnlyRunningStatus)
+      return NULL;
+    // If we don't have that event yet, we create a new one.
+    // Otherwise we copy the information into the existing event anyway, because the data might have changed.
+    pEvent = newEvent = new cEvent (EitEvent->getEventId ());
+    if (!pEvent)
+      return NULL;
+  } else {
+    //LogD(3, prep("existing event channelID: %s Title: %s TableID 0x%02X new TID 0x%02X Version %i, new version %i"), *channel->GetChannelID().ToString(), pEvent->Title(), pEvent->TableID(), Tid, pEvent->Version(), versionNumber);
+    // We have found an existing event, either through its event ID or its start time.
+    pEvent->SetSeen ();
+
+    // If the existing event has a zero table ID it was defined externally and shall
+    // not be overwritten.
+    if (pEvent->TableID () == 0x00) {
+      if (pEvent->Version () == versionNumber)
+        return NULL;
+      /*HasExternalData = */ExternalData = true;
+    }
+    // If the new event has a higher table ID, let's skip it.
+    // The lower the table ID, the more "current" the information.
+    else if (Tid > pEvent->TableID())
+      return NULL;
+    // If the new event comes from the same table and has the same version number
+    // as the existing one, let's skip it to avoid unnecessary work.
+    // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like
+    // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on
+    // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned
+    // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers.
+    else if (Tid == pEvent->TableID() && pEvent->Version() == versionNumber)
+      return NULL;
+  }
+  if (!ExternalData) {
+    pEvent->SetEventID (EitEvent->getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-(
+    pEvent->SetTableID (Tid);
+    pEvent->SetStartTime (EitEvent->getStartTime ());
+    pEvent->SetDuration (EitEvent->getDuration ());
+  }
+  if (newEvent)
+    pSchedule->AddEvent (newEvent);
+  if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
+    if (EitEvent->getRunningStatus () >= SI::RunningStatusNotRunning)
+      pSchedule->SetRunningStatus (pEvent, EitEvent->getRunningStatus (), channel);
+  }
+  if (OnlyRunningStatus)
+    return NULL;  // do this before setting the version, so that the full update can be done later
+  pEvent->SetVersion (versionNumber);
+
+  ProcessEventDescriptors(ExternalData, channel->Source(), Tid, EitEvent,
+                          pEvent, Schedules, channel);
+
+  Modified = true;
+  return pEvent;
+}
+
+void cEIT2::ProcessEventDescriptors(bool ExternalData, int Source,
+                                    u_char Tid, const SI::EIT::Event* SiEitEvent, cEvent* pEvent,
+                                    cSchedules* Schedules, cChannel* channel)
+{
+
+  cEvent *rEvent = NULL;
+  int LanguagePreferenceShort = -1;
+  int LanguagePreferenceExt = -1;
+  unsigned char nDescriptorTag;
+  bool UseExtendedEventDescriptor = false;
+  SI::Descriptor * d;
+  SI::ExtendedEventDescriptors * ExtendedEventDescriptors = NULL;
+  SI::ShortEventDescriptor * ShortEventDescriptor = NULL;
+  //SI::DishDescriptor *DishExtendedEventDescriptor = NULL;
+  SI::DishDescriptor *DishEventDescriptor = NULL;
+  //uchar DishTheme = 0, DishCategory = 0;
+
+
+  cLinkChannels *LinkChannels = NULL;
+  cComponents *Components = NULL;
+
+
+  DescriptorLoop dl = SiEitEvent->eventDescriptors;
+  for (SI::Loop::Iterator it2; (d = dl.getNext(it2)); )
+  {
+    if (ExternalData && d->getDescriptorTag() != SI::ComponentDescriptorTag)
+    {
+      delete d;
+      LogD(2, prep("continue:d->getDescriptorTAG():%x)"), d->getDescriptorTag ());
+      continue;
+    }
+
+    //LogD(2, prep("EEPGDEBUG:d->getDescriptorTAG():%x)"), d->getDescriptorTag ());
+    nDescriptorTag = d->getDescriptorTag();
+    switch (nDescriptorTag) {
+    case SI::ExtendedEventDescriptorTag: {
+      SI::ExtendedEventDescriptor * eed = (SI::ExtendedEventDescriptor *) d;
+      if (I18nIsPreferredLanguage(Setup.EPGLanguages, eed->languageCode, LanguagePreferenceExt)
+        || !ExtendedEventDescriptors) {
+        delete ExtendedEventDescriptors;
+        ExtendedEventDescriptors = new SI::ExtendedEventDescriptors;
+        UseExtendedEventDescriptor = true;
+      }
+      if (UseExtendedEventDescriptor) {
+        ExtendedEventDescriptors->Add(eed);
+        d = NULL; // so that it is not deleted
+      }
+      if (eed->getDescriptorNumber() == eed->getLastDescriptorNumber())
+        UseExtendedEventDescriptor = false;
+    }
+    break;
+    case SI::ShortEventDescriptorTag: {
+      SI::ShortEventDescriptor * sed = (SI::ShortEventDescriptor *) d;
+      if (I18nIsPreferredLanguage(Setup.EPGLanguages, sed->languageCode, LanguagePreferenceShort)
+        || !ShortEventDescriptor) {
+        delete ShortEventDescriptor;
+        ShortEventDescriptor = sed;
+        d = NULL; // so that it is not deleted
+      }
+    }
+    break;
+#if APIVERSNUM > 10711
+    case SI::ContentDescriptorTag: {
+      SI::ContentDescriptor *cd = (SI::ContentDescriptor *) d;
+      SI::ContentDescriptor::Nibble Nibble;
+      int NumContents = 0;
+      uchar Contents[MaxEventContents] = { 0 };
+      for (SI::Loop::Iterator it3; cd->nibbleLoop.getNext(Nibble, it3);) {
+        if (NumContents < MaxEventContents) {
+          Contents[NumContents] = ((Nibble.getContentNibbleLevel1() & 0xF) << 4)
+            | (Nibble.getContentNibbleLevel2() & 0xF);
+          NumContents++;
+        }
+        if (DishEventDescriptor && NumContents == 1) {
+          DishEventDescriptor->setContent(Nibble);
+        }
+        //          LogD(2, prep("EEPGDEBUG:Nibble:%x-%x-%x-%x)"), Nibble.getContentNibbleLevel1(),Nibble.getContentNibbleLevel2()
+        //              , Nibble.getUserNibble1(), Nibble.getUserNibble2());
+
+      }
+      pEvent->SetContents(Contents);
+    }
+    break;
+#endif
+    case SI::ParentalRatingDescriptorTag: {
+      int LanguagePreferenceRating = -1;
+      SI::ParentalRatingDescriptor *prd = (SI::ParentalRatingDescriptor *) d;
+      SI::ParentalRatingDescriptor::Rating Rating;
+      for (SI::Loop::Iterator it3; prd->ratingLoop.getNext(Rating, it3);) {
+        if (I18nIsPreferredLanguage(Setup.EPGLanguages, Rating.languageCode,
+          LanguagePreferenceRating)) {
+          int ParentalRating = (Rating.getRating() & 0xFF);
+          switch (ParentalRating) {
+          // values defined by the DVB standard (minimum age = rating + 3 years):
+          case 0x01 ... 0x0F: ParentalRating += 3; break;
+          // values defined by broadcaster CSAT (now why didn't they just use 0x07, 0x09 and 0x0D?):
+          case 0x11: ParentalRating = 10; break;
+          case 0x12: ParentalRating = 12; break;
+          case 0x13: ParentalRating = 16; break;
+          default: ParentalRating = 0;
+          }
+          pEvent->SetParentalRating(ParentalRating);
+        }
+      }
+    }
+    break;
+    case SI::PDCDescriptorTag: {
+      SI::PDCDescriptor * pd = (SI::PDCDescriptor *) d;
+      time_t now = time(NULL);
+      struct tm tm_r;
+      struct tm t = *localtime_r(&now, &tm_r); // this initializes the time zone in 't'
+      t.tm_isdst = -1; // makes sure mktime() will determine the correct DST setting
+      int month = t.tm_mon;
+      t.tm_mon = pd->getMonth() - 1;
+      t.tm_mday = pd->getDay();
+      t.tm_hour = pd->getHour();
+      t.tm_min = pd->getMinute();
+      t.tm_sec = 0;
+      if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan
+        t.tm_year++;
+      else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec
+      t.tm_year--;
+      time_t vps = mktime(&t);
+      pEvent->SetVps(vps);
+    }
+    break;
+    case SI::TimeShiftedEventDescriptorTag: {
+      if (Schedules) {
+        SI::TimeShiftedEventDescriptor * tsed = (SI::TimeShiftedEventDescriptor *) d;
+        cSchedule *rSchedule = (cSchedule *) Schedules->GetSchedule(
+          tChannelID(Source, channel->Nid(), channel->Tid(), tsed->getReferenceServiceId()));
+        if (!rSchedule)
+          break;
+        rEvent = (cEvent *) rSchedule->GetEvent(tsed->getReferenceEventId());
+        if (!rEvent)
+          break;
+        pEvent->SetTitle(rEvent->Title());
+        pEvent->SetShortText(rEvent->ShortText());
+        pEvent->SetDescription(rEvent->Description());
+      }
+    }
+    break;
+    case SI::LinkageDescriptorTag: {
+      SI::LinkageDescriptor * ld = (SI::LinkageDescriptor *) d;
+      tChannelID linkID(Source, ld->getOriginalNetworkId(), ld->getTransportStreamId(),
+        ld->getServiceId());
+      if (ld->getLinkageType() == 0xB0) { // Premiere World
+        time_t now = time(NULL);
+        bool hit = SiEitEvent->getStartTime() <= now
+          && now < SiEitEvent->getStartTime() + SiEitEvent->getDuration();
+        if (hit) {
+          char linkName[ld->privateData.getLength() + 1];
+          strn0cpy(linkName, (const char *) ld->privateData.getData(), sizeof(linkName));
+          // TODO is there a standard way to determine the character set of this string?
+          cChannel *link = Channels.GetByChannelID(linkID);
+          if (link != channel) { // only link to other channels, not the same one
+            //fprintf(stderr, "Linkage %s %4d %4d %5d %5d %5d %5d  %02X  '%s'\n", hit ? "*" : "", channel->Number(), link ? link->Number() : -1, SiEitEvent.getEventId(), ld->getOriginalNetworkId(), ld->getTransportStreamId(), ld->getServiceId(), ld->getLinkageType(), linkName);//XXX
+            if (link) {
+              if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
+                link->SetName(linkName, "", "");
+            }
+            else if (Setup.UpdateChannels >= 4) {
+              cChannel *transponder = channel;
+              if (channel->Tid() != ld->getTransportStreamId())
+                transponder = Channels.GetByTransponderID(linkID);
+              link = Channels.NewChannel(transponder, linkName, "", "", ld->getOriginalNetworkId(),
+                ld->getTransportStreamId(), ld->getServiceId());
+            }
+            if (link) {
+              if (!LinkChannels) LinkChannels = new cLinkChannels;
+              LinkChannels->Add(new cLinkChannel(link));
+            }
+          }
+          else
+            channel->SetPortalName(linkName);
+        }
+      }
+    }
+    break;
+    case SI::ComponentDescriptorTag: {
+      SI::ComponentDescriptor * cd = (SI::ComponentDescriptor *) d;
+      uchar Stream = cd->getStreamContent();
+      uchar Type = cd->getComponentType();
+      //if (1 <= Stream && Stream <= 3 && Type != 0) { // 1=video, 2=audio, 3=subtitles
+      if (1 <= Stream && Stream <= 6 && Type != 0) { // 1=MPEG2-video, 2=MPEG1-audio, 3=subtitles, 4=AC3-audio, 5=H.264-video, 6=HEAAC-audio
+        if (!Components)
+          Components = new cComponents;
+        char buffer[Utf8BufSize (256)];
+        Components->SetComponent(Components->NumComponents(), Stream,
+          Type, I18nNormalizeLanguageCode(cd->languageCode),
+          cd->description.getText(buffer, sizeof(buffer)));
+      }
+    }
+    break;
+    case SI::DishExtendedEventDescriptorTag: {
+      SI::UnimplementedDescriptor *deed = (SI::UnimplementedDescriptor *) d;
+      if (!DishEventDescriptor) {
+        DishEventDescriptor = new SI::DishDescriptor();
+      }
+      DishEventDescriptor->setExtendedtData(Tid + 1, deed->getData());
+      //          HasExternalData = true;
+    }
+    break;
+    case SI::DishShortEventDescriptorTag: {
+      SI::UnimplementedDescriptor *dsed = (SI::UnimplementedDescriptor *) d;
+      if (!DishEventDescriptor) {
+        DishEventDescriptor = new SI::DishDescriptor();
+      }
+      DishEventDescriptor->setShortData(Tid + 1, dsed->getData());
+      //          HasExternalData = true;
+    }
+    break;
+    case SI::DishRatingDescriptorTag: {
+      if (d->getLength() == 4) {
+        if (!DishEventDescriptor) {
+          DishEventDescriptor = new SI::DishDescriptor();
+        }
+        uint16_t rating = d->getData().TwoBytes(2);
+        DishEventDescriptor->setRating(rating);
+      }
+    }
+    break;
+    case SI::DishSeriesDescriptorTag: {
+      if (d->getLength() == 10) {
+        //LogD(2, prep("DishSeriesDescriptorTag: %s)"), (const char*) d->getData().getData());
+        if (!DishEventDescriptor) {
+          DishEventDescriptor = new SI::DishDescriptor();
+        }
+        DishEventDescriptor->setEpisodeInfo(d->getData());
+      }
+      //        else {
+      //            LogD(2, prep("DishSeriesDescriptorTag length: %d)"), d->getLength());
+      //        }
+    }
+    break;
+    default:
+      break;
+    }
+    delete d;
+  }
+  if (!rEvent) {
+    if (ShortEventDescriptor) {
+      char buffer[Utf8BufSize (256)];
+      unsigned char *f;
+      int l = ShortEventDescriptor->name.getLength();
+      f = (unsigned char *) ShortEventDescriptor->name.getData().getData();
+      decodeText2 (f, l, buffer, sizeof (buffer));
+      //ShortEventDescriptor->name.getText(buffer, sizeof(buffer));
+      LogD(2, prep("Title: %s Decoded: %s"), f, buffer);
+      pEvent->SetTitle (buffer);
+      LogD(3, prep("channelID: %s Title: %s"), *channel->GetChannelID().ToString(), pEvent->Title());
+      l = ShortEventDescriptor->text.getLength();
+      if (l > 0) { //Set the Short Text only if there is data so that we do not overwrite valid data
+        f = (unsigned char *) ShortEventDescriptor->text.getData().getData();
+        decodeText2 (f, l, buffer, sizeof (buffer));
+        //ShortEventDescriptor->text.getText(buffer, sizeof(buffer));
+        pEvent->SetShortText (buffer);
+      }
+      LogD(3, prep("ShortText: %s"), pEvent->ShortText());
+      LogD(2, prep("ShortText: %s Decoded: %s"), f, buffer);
+    } else if (/*!HasExternalData*/!DishEventDescriptor) {
+      pEvent->SetTitle (NULL);
+      pEvent->SetShortText (NULL);
+      LogD(3, prep("SetTitle (NULL)"));
+    }
+    if (ExtendedEventDescriptors) {
+      char buffer[Utf8BufSize (ExtendedEventDescriptors->getMaximumTextLength (": ")) + 1];
+      pEvent->SetDescription (ExtendedEventDescriptors->getText (buffer, sizeof (buffer), ": "));
+      LogD(3, prep("Description: %s"), pEvent->Description());
+    } else if (!/*HasExternalData*/DishEventDescriptor)
+      pEvent->SetDescription (NULL);
+
+    if (DishEventDescriptor) {
+      if (DishEventDescriptor->getName())
+        pEvent->SetTitle(DishEventDescriptor->getName());
+      //LogD(2, prep("channelID: %s DishTitle: %s"), *channel->GetChannelID().ToString(), DishEventDescriptor->getName());
+      pEvent->SetShortText(DishEventDescriptor->getShortText());
+      char *tmp;
+      string fmt;
+
+      const char * description = DishEventDescriptor->getDescription();
+      //BEV sets the description previously with ExtendedEventDescriptor
+      if (0 == strcmp(DishEventDescriptor->getDescription(),"") && pEvent->Description())
+        description = pEvent->Description();
+
+
+      fmt = "%s";
+      if (DishEventDescriptor->hasTheme()) {
+        fmt += "\nTheme: ";
+      }
+      fmt += "%s";
+      if (DishEventDescriptor->hasCategory()) {
+        fmt += "\nCategory: ";
+      }
+      fmt += "%s";
+
+      if ((0 != strcmp(DishEventDescriptor->getRating(),"")
+        || 0 != strcmp(DishEventDescriptor->getStarRating(),""))) {
+        fmt += "\n\nRating: ";
+      }
+      fmt += "%s %s";
+      if (0 != strcmp(DishEventDescriptor->getProgramId(),"")) {
+        fmt += "\n\nProgram ID: ";
+      }
+      fmt += "%s %s%s";
+      time_t orgAirDate = DishEventDescriptor->getOriginalAirDate();
+      char datestr [80];
+      bool dateok = false;
+      if (orgAirDate != 0) {
+        dateok = strftime (datestr,80," \nOriginal Air Date: %a %b %d %Y",gmtime(&orgAirDate)) > 0;
+      }
+
+      Asprintf (&tmp, fmt.c_str(), description
+                , DishEventDescriptor->getTheme(), DishEventDescriptor->getCategory()
+                , DishEventDescriptor->getRating(), DishEventDescriptor->getStarRating()
+                , DishEventDescriptor->getProgramId(), DishEventDescriptor->getSeriesId()
+                , orgAirDate == 0 || !dateok ? "" : datestr);
+      pEvent->SetDescription(tmp);
+      free(tmp);
+
+      //LogD(2, prep("DishDescription: %s"), DishEventDescriptor->getDescription());
+      //LogD(2, prep("DishShortText: %s"), DishEventDescriptor->getShortText());
+    }
+
+  }
+  delete ExtendedEventDescriptors;
+  delete ShortEventDescriptor;
+  delete DishEventDescriptor;
+
+  pEvent->SetComponents (Components);
+
+  //    LogD(2, prep("channelID: %s Title: %s"), *channel->GetChannelID().ToString(), pEvent->Title());
+
+  //    if (pEvent->ChannelID() == tChannelID::FromString("S119.0W-4100-6-110-110")) {
+  //      LogD(2, prep("ID: %d Title: %s Time: %d Tid: 0x%x"), pEvent->EventID(), pEvent->Title(), pEvent->StartTime(), pEvent->TableID());
+  //    }
+
+  //FixEpgBugs removes newlines from description which is not wanted especially for DISH/BEV
+  if (Format != DISH_BEV)
+    pEvent->FixEpgBugs();
+
+  if (LinkChannels)
+    channel->SetLinkChannels (LinkChannels);
+}
+
+cEIT2::cEIT2 (cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool isEITPid, bool OnlyRunningStatus)
+:  SI::EIT (Data, false)
+, OnlyRunningStatus(OnlyRunningStatus)
+, Schedules(Schedules)
+{
+
+  //LogD(2, prep("cEIT2::cEIT2"));
+  if (Tid > 0 && (Format == DISH_BEV || (cSetupEEPG::getInstance()->ProcessEIT && isEITPid))) Tid--;
+
+  if (!CheckCRCAndParse ()) {
+    LogD(2, prep("!CheckCRCAndParse ()"));
+    return;
+  }
+
+  bool searchOtherSatPositions = Format == DISH_BEV;
+
+  tChannelID channelID (Source, getOriginalNetworkId (), getTransportStreamId (), getServiceId ());
+  channel = GetChannelByID (channelID, searchOtherSatPositions);
+  if (!channel) {
+    LogD(3, prep("!channel channelID: %s"), *channelID.ToString());
+    return; // only collect data for known channels
+  }
+
+  //LogD(5, prep("channelID: %s format:%d"), *channel->GetChannelID().ToString(), Format);
+
+  cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (channel, true);
+
+  Empty = true;
+  Modified = false;
+  //    bool HasExternalData = false;
+  SegmentStart = 0;
+  SegmentEnd = 0;
+
+  SI::EIT::Event SiEitEvent;
+  for (SI::Loop::Iterator it; eventLoop.getNext (SiEitEvent, it);) {
+    int versionNumber = getVersionNumber();
+    //      bool ExternalData = false;
+    //      // Drop bogus events - but keep NVOD reference events, where all bits of the start time field are set to 1, resulting in a negative number.
+    //      if (SiEitEvent.getStartTime () == 0 || (SiEitEvent.getStartTime () > 0 && SiEitEvent.getDuration () == 0))
+    //        continue;
+    //      Empty = false;
+    //      if (!SegmentStart)
+    //        SegmentStart = SiEitEvent.getStartTime ();
+    //      SegmentEnd = SiEitEvent.getStartTime () + SiEitEvent.getDuration ();
+    //      int versionNumber = getVersionNumber();
+    //
+    //      cEvent *newEvent = NULL;
+    //      cEvent *pEvent = (cEvent *) pSchedule->GetEvent (SiEitEvent.getEventId (), SiEitEvent.getStartTime ());
+    //      if (!pEvent) {
+    //        if (OnlyRunningStatus)
+    //          continue;
+    //        // If we don't have that event yet, we create a new one.
+    //        // Otherwise we copy the information into the existing event anyway, because the data might have changed.
+    //        pEvent = newEvent = new cEvent (SiEitEvent.getEventId ());
+    //        if (!pEvent)
+    //          continue;
+    //      } else {
+    //        //LogD(3, prep("existing event channelID: %s Title: %s TableID 0x%02X new TID 0x%02X Version %i, new version %i"), *channel->GetChannelID().ToString(), pEvent->Title(), pEvent->TableID(), Tid, pEvent->Version(), versionNumber);
+    //        // We have found an existing event, either through its event ID or its start time.
+    //        pEvent->SetSeen ();
+    //
+    //        // If the existing event has a zero table ID it was defined externally and shall
+    //        // not be overwritten.
+    //        if (pEvent->TableID () == 0x00) {
+    //          if (pEvent->Version () == versionNumber)
+    //            continue;
+    //          /*HasExternalData = */ExternalData = true;
+    //        }
+    //        // If the new event has a higher table ID, let's skip it.
+    //        // The lower the table ID, the more "current" the information.
+    //        else if (Tid > pEvent->TableID())
+    //          continue;
+    //        // If the new event comes from the same table and has the same version number
+    //        // as the existing one, let's skip it to avoid unnecessary work.
+    //        // Unfortunately some stations (like, e.g. "Premiere") broadcast their EPG data on several transponders (like
+    //        // the actual Premiere transponder and the Sat.1/Pro7 transponder), but use different version numbers on
+    //        // each of them :-( So if one DVB card is tuned to the Premiere transponder, while an other one is tuned
+    //        // to the Sat.1/Pro7 transponder, events will keep toggling because of the bogus version numbers.
+    //        else if (Tid == pEvent->TableID() && pEvent->Version() == versionNumber)
+    //          continue;
+    //      }
+    //      if (!ExternalData) {
+    //        pEvent->SetEventID (SiEitEvent.getEventId ()); // unfortunately some stations use different event ids for the same event in different tables :-(
+    //        pEvent->SetTableID (Tid);
+    //        pEvent->SetStartTime (SiEitEvent.getStartTime ());
+    //        pEvent->SetDuration (SiEitEvent.getDuration ());
+    //      }
+    //      if (newEvent)
+    //        pSchedule->AddEvent (newEvent);
+    //      if (Tid == 0x4E) { // we trust only the present/following info on the actual TS
+    //        if (SiEitEvent.getRunningStatus () >= SI::RunningStatusNotRunning)
+    //          pSchedule->SetRunningStatus (pEvent, SiEitEvent.getRunningStatus (), channel);
+    //      }
+    //      if (OnlyRunningStatus)
+    //        continue;  // do this before setting the version, so that the full update can be done later
+    //      pEvent->SetVersion (versionNumber);
+    //
+    //      ProcessEventDescriptors(ExternalData, Source, Tid, SiEitEvent,
+    //            pEvent, Schedules, channel);
+    //
+    //      Modified = true;
+    cEvent *pEvent = ProcessEitEvent(pSchedule, &SiEitEvent,
+      Tid, versionNumber);
+    if (pEvent)
+      EquivHandler->updateEquivalent(Schedules, channel->GetChannelID(), pEvent);
+  }
+
+  ////
+
+  if (Empty && Tid == 0x4E && getSectionNumber () == 0)
+    // ETR 211: an empty entry in section 0 of table 0x4E means there is currently no event running
+    pSchedule->ClrRunningStatus (channel);
+  if (Tid == 0x4E)
+    pSchedule->SetPresentSeen ();
+  if (OnlyRunningStatus) {
+    LogD(4, prep("OnlyRunningStatus"));
+    return;
+  }
+  if (Modified) {
+    //      if (!HasExternalData)
+    pSchedule->DropOutdated (SegmentStart, SegmentEnd, Tid, getVersionNumber ());
+    sortSchedules(Schedules, channel->GetChannelID());
+  }
+  LogD(4, prep("end of cEIT2"));
+
+}
+//end of cEIT2
+
+cEIT2::cEIT2 (cSchedule * Schedule)
+: Empty(true)
+, Modified(false)
+, OnlyRunningStatus(false)
+, SegmentStart(0)
+, SegmentEnd(0)
+, Schedules(NULL)
+{
+  //LogD(2, prep("cEIT2::cEIT2"));
+  //    if (Tid > 0 && (Format == DISH_BEV || (SetupPE->ProcessEIT && isEITPid))) Tid--;
+
+  bool searchOtherSatPositions = Format == DISH_BEV;
+
+  tChannelID channelID = Schedule->ChannelID();
+  channel = GetChannelByID (channelID, searchOtherSatPositions);
+  if (!channel) {
+    LogD(3, prep("!channel channelID: %s"), *channelID.ToString());
+    return; // only collect data for known channels
+  }
+}
+} //end namespace SI
+
diff --git a/eit2.h b/eit2.h
new file mode 100644
index 0000000..7686672
--- /dev/null
+++ b/eit2.h
@@ -0,0 +1,50 @@
+#ifndef CEIT2_H_
+#define CEIT2_H_
+#include <libsi/section.h>
+#include <libsi/descriptor.h>
+#include <libsi/si.h>
+#include <vdr/epg.h>
+
+namespace SI
+{
+enum DescriptorTagExt {
+  DishRatingDescriptorTag = 0x89,
+  DishShortEventDescriptorTag = 0x91,
+  DishExtendedEventDescriptorTag = 0x92,
+  DishSeriesDescriptorTag = 0x96,
+};
+
+// typedef InheritEnum< DescriptorTagExt, SI::DescriptorTag > ExtendedDescriptorTag;
+
+/*extern const char *getCharacterTable(const unsigned char *&buffer, int &length, bool *isSingleByte = NULL);
+extern bool convertCharacterTable(const char *from, size_t fromLength, char *to, size_t toLength, const char *fromCode);
+extern bool SystemCharacterTableIsSingleByte;*/
+class cEIT2:public SI::EIT
+{
+public:
+  cEIT2(cSchedules * Schedules, int Source, u_char Tid, const u_char * Data, bool isEITPid = false,
+        bool OnlyRunningStatus = false);
+  cEIT2 (cSchedule * Schedule);
+  //protected:
+  //  void updateEquivalent(cSchedules * Schedules, tChannelID channelID, cEvent *pEvent);
+  cEvent* ProcessEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version);
+
+private:
+  void ProcessEventDescriptors(bool ExternalData, int Source, u_char Tid,
+                               const SI::EIT::Event* SiEitEvent, cEvent* pEvent,
+                               cSchedules* Schedules, cChannel* channel);
+
+private:
+  bool Empty;
+  bool Modified;
+  //    bool HasExternalData = false;
+  bool OnlyRunningStatus;
+  time_t SegmentStart;
+  time_t SegmentEnd;
+  cSchedules* Schedules;
+  cChannel* channel;
+
+};
+} //end namespace SI
+
+#endif /* CEIT2_H_ */
diff --git a/epghandler.c b/epghandler.c
new file mode 100644
index 0000000..49c89e4
--- /dev/null
+++ b/epghandler.c
@@ -0,0 +1,198 @@
+/*
+ * cEEpgHandler.c
+ *
+ *  Created on: 11.3.2012
+ *      Author: d.petrovski
+ */
+
+#include "epghandler.h"
+#if APIVERSNUM > 10725
+#include "log.h"
+#include "equivhandler.h"
+#include "eit2.h"
+#include "util.h"
+#include <vdr/sources.h>
+#include <libsi/si.h>
+
+using namespace util;
+
+cEEpgHandler::cEEpgHandler() {
+  LogD(4, prep("cEEpgHandler()"));
+  equivHandler = new cEquivHandler();
+  modified = false;
+}
+
+cEEpgHandler::~cEEpgHandler() {
+  delete equivHandler;
+  equivHandler = NULL;
+}
+
+bool cEEpgHandler::HandleEitEvent(cSchedule* Schedule,
+                                  const SI::EIT::Event* EitEvent, uchar TableID, uchar Version) {
+  //LogD(1, prep("HandleEitEvent"));
+  //DISH NID 0x1001 to 0x100B BEV 0x100 and 0x101
+  int nid = Schedule->ChannelID().Nid();
+  if ((nid >= 0x1001 && nid <= 0x100B) || nid == 0x101 || nid == 0x100) {
+    //Set the Format for Eit events so that the new lines are not erased with FixEpgBugs
+    if (Format != DISH_BEV) Format = DISH_BEV;
+
+    SI::cEIT2 eit2(Schedule);
+    eit2.ProcessEitEvent(Schedule, EitEvent, TableID, Version);
+    return true;
+  }
+
+  //TODO Should it be added in setup?
+  if (EitEvent->getDurationHour() > _LONG_EVENT_HOURS) {
+    LogD(4, prep("Event longer than 10h Duration:%d DurationHour:%d StartTimeHour:%d"), EitEvent->getDuration(), EitEvent->getDurationHour(), EitEvent->getStartTimeHour());
+    const cEvent* exEvent = Schedule->GetEventAround(EitEvent->getStartTime()+EitEvent->getDuration()/3);
+    if (exEvent) {
+      const cEvent* exEvent2 = Schedule->GetEventAround(EitEvent->getStartTime()+EitEvent->getDuration()/3*2);
+      if (exEvent2 && exEvent != exEvent2) {
+        LogD(2, prep("EitEvent overrides existing events '%s', '%s' ... Skipping"), *exEvent->Title(), *exEvent2->Title());
+        return true;
+      }
+    }
+  }
+
+  modified = false;
+  //VDR creates new event if the EitEvent StartTime is different than EEPG time so 
+  //the EEPG event has to be deleted but the data should be kept
+  const cEvent* ev = Schedule->GetEvent(EitEvent->getEventId(),EitEvent->getStartTime());
+  if (!ev){
+      ev = Schedule->GetEvent(EitEvent->getEventId());
+      if (ev && ((ev->StartTime()>EitEvent->getStartTime() && ev->StartTime()<=EitEvent->getStartTime()+EitEvent->getDuration())
+          || (EitEvent->getStartTime() > ev->StartTime() && EitEvent->getStartTime() <= ev->EndTime()))) {
+        LogD(0, prep("!!!Deleting Event id:%d title:%s start_time:%d new_start_time:%d duration:%d new_duration:%d"), ev->EventID(), ev->Title(), ev->StartTime(), EitEvent->getStartTime(), ev->Duration(), EitEvent->getDuration());
+
+        if (ev->Description() && strcmp(ev->Description(),"") != 0)
+          origDescription = ev->Description();
+        if (ev->ShortText() && strcmp(ev->ShortText(),"") != 0)
+          origShortText = ev->ShortText();
+        Schedule->DelEvent((cEvent *) ev);
+//        Schedule->DropOutdated(ev->StartTime()-1,ev->EndTime()+1,ev->TableID()-1,ev->Version());
+        LogD(0, prep("!!!End Deleting Event"));
+        //TODO equivalent channels !!!
+      }
+  }
+
+
+
+  return false;
+  //	return true;
+}
+
+bool cEEpgHandler::SetEventID(cEvent* Event, tEventID EventID) {
+  Event->SetEventID(EventID);
+  return true;
+}
+
+bool cEEpgHandler::SetTitle(cEvent* Event, const char* Title) {
+  LogD(3, prep("Event id:%d title:%s new title:%s"), Event->EventID(), Event->Title(), Title);
+
+  if (!Event->Title() || (Title && (!strcmp(Event->Title(),"") || (strcmp(Title,"") && strcmp(Event->Title(),Title))))) {
+    //LogD(0, prep("Event id:%d title:%s new title:%s"), Event->EventID(), Event->Title(), Title);
+    modified = true;
+    Event->SetTitle(Title);
+  }
+  return true;
+}
+
+bool cEEpgHandler::SetShortText(cEvent* Event, const char* ShortText) {
+  LogD(3, prep("Event id:%d ShortText:%s new ShortText:%s"), Event->EventID(), Event->ShortText(), ShortText);
+
+  if (Event->ShortText() && strcmp(Event->ShortText(),"") != 0) {
+    origShortText = std::string(Event->ShortText());
+  }
+  else {
+    origShortText.clear();
+  }
+
+  //if (!Event->ShortText() || ShortText && (!strcmp(Event->ShortText(),"") || (strcmp(ShortText,"") && strcmp(Event->ShortText(),ShortText))))
+  Event->SetShortText(ShortText);
+  return true;
+}
+
+bool cEEpgHandler::SetDescription(cEvent* Event, const char* Description) {
+  LogD(3, prep("Event id:%d Description:%s new Description:%s"), Event->EventID(), Event->Description(), Description);
+
+  if (Event->Description() && strcmp(Event->Description(),"") != 0)
+    origDescription = Event->Description();
+  else
+    origDescription.clear();
+    
+  //Based on asumption that SetDescription is always called after SetTitle
+  if (!modified && Description && (!Event->Description() || strcmp(Event->Description(),Description) ))
+    modified = true;
+
+  //if (!Event->Description() || Description && (!strcmp(Event->Description(),"") || (strcmp(Description,"") && strcmp(Event->Description(),Description))))
+  Event->SetDescription(Description);
+  return true;
+}
+
+bool cEEpgHandler::SetContents(cEvent* Event, uchar* Contents) {
+  Event->SetContents(Contents);
+  return true;
+}
+
+bool cEEpgHandler::SetParentalRating(cEvent* Event, int ParentalRating) {
+  Event->SetParentalRating(ParentalRating);
+  return true;
+}
+
+bool cEEpgHandler::SetStartTime(cEvent* Event, time_t StartTime) {
+  Event->SetStartTime(StartTime);
+  return true;
+}
+
+bool cEEpgHandler::SetDuration(cEvent* Event, int Duration) {
+  Event->SetDuration(Duration);
+  return true;
+}
+
+bool cEEpgHandler::SetVps(cEvent* Event, time_t Vps) {
+  Event->SetVps(Vps);
+  return true;
+}
+
+bool cEEpgHandler::HandleEvent(cEvent* Event) {
+
+  LogD(3, prep("HandleEvent st:%s ost:%s desc:%s odesc:%s"),Event->ShortText(),origShortText.c_str(),Event->Description(),origDescription.c_str());
+
+  //After FixEpgBugs of cEvent set the original Short Text if empty
+  if (!Event->ShortText() || !strcmp(Event->ShortText(),""))
+    Event->SetShortText(origShortText.c_str());
+
+  if ((!Event->Description() && !origDescription.empty()) || (Event->Description() && !origDescription.empty() && origDescription.find(Event->Description()) != string::npos) ) {
+    Event->SetDescription(origDescription.c_str());
+  }
+
+  if (equivHandler->getEquiChanMap().count(*Event->ChannelID().ToString()) <= 0)
+    return true;
+
+  //if (modified)
+    equivHandler->updateEquivalent(Event->ChannelID(), Event);
+
+  //TODO just to see the difference
+  //else if (!origDescription.empty() && !origDescription.compare(Event->Description())) {
+  //	origDescription.append(" | EIT: ");
+  //	origDescription.append(Event->Description());
+  //	Event->SetDescription(origDescription.c_str());
+  //  }
+
+  return true;
+}
+
+
+bool cEEpgHandler::SortSchedule(cSchedule* Schedule) {
+
+  Schedule->Sort();
+
+  return true;
+}
+
+bool cEEpgHandler::DropOutdated(cSchedule* Schedule, time_t SegmentStart,
+                                time_t SegmentEnd, uchar TableID, uchar Version) {
+  return false;
+}
+
+#endif
diff --git a/epghandler.h b/epghandler.h
new file mode 100644
index 0000000..003fd32
--- /dev/null
+++ b/epghandler.h
@@ -0,0 +1,48 @@
+/*
+ * cEEpgHandler.h
+ *
+ *  Created on: 11.3.2012
+ *      Author: d.petrovski
+ */
+
+#ifndef CEEPGHANDLER_H_
+#define CEEPGHANDLER_H_
+#include <vdr/config.h>
+#if APIVERSNUM > 10725
+#include <vdr/epg.h>
+#include <string>
+
+class cEquivHandler;
+
+class cEEpgHandler : public cEpgHandler {
+public:
+    cEEpgHandler();
+    virtual ~cEEpgHandler();
+    virtual bool IgnoreChannel(const cChannel *Channel) { return false; }
+    virtual bool HandleEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version);
+    virtual bool SetEventID(cEvent *Event, tEventID EventID);
+    virtual bool SetTitle(cEvent *Event, const char *Title);
+    virtual bool SetShortText(cEvent *Event, const char *ShortText);
+    virtual bool SetDescription(cEvent *Event, const char *Description);
+    virtual bool SetContents(cEvent *Event, uchar *Contents);
+    virtual bool SetParentalRating(cEvent *Event, int ParentalRating);
+    virtual bool SetStartTime(cEvent *Event, time_t StartTime);
+    virtual bool SetDuration(cEvent *Event, int Duration);
+    virtual bool SetVps(cEvent *Event, time_t Vps);
+    virtual bool FixEpgBugs(cEvent *Event) { return false; }
+    virtual bool HandleEvent(cEvent *Event);
+    virtual bool SortSchedule(cSchedule *Schedule);
+    virtual bool DropOutdated(cSchedule *Schedule, time_t SegmentStart, time_t SegmentEnd, uchar TableID, uchar Version);
+
+//    bool ParseEitEvent(cSchedule *Schedule, const SI::EIT::Event *EitEvent, uchar TableID, uchar Version);
+
+private:
+    std::string origShortText;
+    std::string origDescription;
+    cEquivHandler* equivHandler;
+    static const int _LONG_EVENT_HOURS = 10;
+    bool modified;
+};
+
+#endif /*APIVERSNUM > 10725*/
+#endif /* CEEPGHANDLER_H_ */
diff --git a/equivhandler.c b/equivhandler.c
new file mode 100644
index 0000000..281d2f3
--- /dev/null
+++ b/equivhandler.c
@@ -0,0 +1,233 @@
+/*
+ * equivhandler.cpp
+ *
+ *  Created on: 19.5.2012
+ *      Author: d.petrovski
+ */
+
+#include "equivhandler.h"
+#include "setupeepg.h"
+#include "log.h"
+#include "util.h"
+
+#include <string>
+
+using namespace util;
+
+multimap<string, string> cEquivHandler::equiChanMap;
+long cEquivHandler::equiChanFileTime = 0;
+
+cEquivHandler::cEquivHandler()
+{
+  loadEquivalentChannelMap();
+}
+
+cEquivHandler::~cEquivHandler()
+{
+  // TODO Auto-generated destructor stub
+}
+
+void cEquivHandler::loadEquivalentChannelMap (void)
+{
+  char Buffer[1024];
+  char *Line;
+  FILE *File;
+  string FileName = string(cSetupEEPG::getInstance()->getConfDir()) + "/" + EEPG_FILE_EQUIV;
+  multimap<string,string>::iterator it,it2;
+  pair<multimap<string,string>::iterator,multimap<string,string>::iterator> ret;
+
+  //Test if file is changed and reload
+  struct stat st;
+  if (stat(FileName.c_str(), &st)) {
+      LogE(0, prep("Error obtaining stats for '%s' "), FileName.c_str());
+      return;
+  }
+
+  if (equiChanMap.size() > 0 &&  equiChanFileTime == st.st_mtim.tv_nsec)
+    return;
+  else
+    equiChanMap.clear();
+
+
+  File = fopen (FileName.c_str(), "r");
+  if (File) {
+    memset (Buffer, 0, sizeof (Buffer));
+    char origChanID[256];
+    char equiChanID[256];
+    char source[256];
+    int nid = 0;
+    int tid = 0;
+    int sid = 0;
+    int rid = 0;
+    while ((Line = fgets (Buffer, sizeof (Buffer), File)) != NULL) {
+      Line = compactspace (skipspace (stripspace (Line)));
+      if (!isempty (Line)) {
+        if (sscanf (Line, "%[^ ] %[^ ] %[^\n]\n", origChanID, equiChanID, source) == 3) {
+          if (origChanID[0] != '#' && origChanID[0] != ';') {
+            nid = 0;
+            tid = 0;
+            sid = 0;
+            rid = 0;
+            if (sscanf (origChanID, "%[^-]-%i -%i -%i ", source, &nid, &tid, &sid) == 4)
+              if (sscanf (equiChanID, "%[^-]-%i -%i -%i ", source, &nid, &tid, &sid) == 4) {
+                if (sscanf (origChanID, "%[^-]-%i -%i -%i -%i ", source, &nid, &tid, &sid, &rid) != 5) {
+                  rid = 0;
+                }
+                tChannelID OriginalChID = tChannelID (cSource::FromString (source), nid, tid, sid, rid);
+                bool found = false;
+                //int i = 0;
+                cChannel *OriginalChannel = Channels.GetByChannelID (OriginalChID, false);
+                if (!OriginalChannel) {
+                  LogI(2, prep("Warning, not found epg channel \'%s\' in channels.conf. Equivalency is assumed to be valid, but perhaps you should check the entry in the equivalents file"), origChanID); //TODO: skip this ing?
+                  continue;
+                }
+                if (sscanf (equiChanID, "%[^-]-%i -%i -%i ", source, &nid, &tid, &sid) == 4) {
+                  if (sscanf (equiChanID, "%[^-]-%i -%i -%i -%i ", source, &nid, &tid, &sid, &rid)
+                    != 5) {
+                    rid = 0;
+                  }
+                  tChannelID EquivChID = tChannelID (cSource::FromString (source), nid, tid, sid, rid);
+                  cChannel *EquivChannel = Channels.GetByChannelID (EquivChID, false); //TODO use valid function?
+                  if (EquivChannel) {
+                    ret = equiChanMap.equal_range(*OriginalChID.ToString());
+                    for (it=ret.first; it!=ret.second; ++it)
+                      if ((*it).second ==  *OriginalChID.ToString()) {
+                        found = true;
+                        break;
+                      }
+
+                    if (!found) {
+                      string origCh(*OriginalChID.ToString());
+                      string equiCh(*EquivChID.ToString());
+                      equiChanMap.insert(pair<string,string>(origCh.c_str(),equiCh.c_str()));
+                      LogD(4, prep("Found %s equivalent to %s. origCh %s"), *EquivChID.ToString(), *OriginalChID.ToString(), origCh.c_str());
+                      for ( it2=equiChanMap.begin() ; it2 != equiChanMap.end(); it2++ )
+                        LogD(3, prep("Original ID %s <-> Equivalent ID %s"), (*it2).first.c_str(), it2->second.c_str());
+                    }
+                  } else
+                    LogI(0, prep("Warning, not found equivalent channel \'%s\' in channels.conf"), equiChanID);
+                }
+              }   //if scanf string1
+          }   //if string1
+        }     //if scanf
+      }    //if isempty
+    }      //while
+    fclose (File);
+    equiChanFileTime = st.st_mtim.tv_nsec;
+    LogD(2, prep("Loaded %i equivalents."), equiChanMap.size());
+    for ( it2=equiChanMap.begin() ; it2 != equiChanMap.end(); it2++ )
+      LogD(2, prep("Original ID %s <-> Equivalent ID %s"), (*it2).first.c_str(), it2->second.c_str());
+  }  //if file
+}
+
+void cEquivHandler::updateEquivalent(cSchedules * Schedules, tChannelID channelID, cEvent *pEvent){
+  multimap<string,string>::iterator it;
+  pair<multimap<string,string>::iterator,multimap<string,string>::iterator> ret;
+
+  LogD(2, prep("Start updateEquivalent %s"), *channelID.ToString());
+
+  ret = equiChanMap.equal_range(*channelID.ToString());
+  for (it=ret.first; it!=ret.second; ++it) {
+    LogD(2, prep("equivalent channel exists"));
+    tChannelID equChannelID (tChannelID::FromString((*it).second.c_str()));
+    cChannel *equChannel = GetChannelByID (equChannelID, false);
+    if (equChannel) {
+      LogD(2, prep("found Equivalent channel %s"), *equChannelID.ToString());
+      cSchedule *pSchedule = (cSchedule *) Schedules->GetSchedule (equChannel, true);
+      cEvent *pEqvEvent = (cEvent *) pSchedule->GetEvent (pEvent->EventID(), pEvent->StartTime());
+      if (pEqvEvent) {
+        LogD(3, prep("equivalent event exists"));
+        if (pEqvEvent == pEvent) {
+          LogD(3, prep("equal event exists"));
+
+        } else {
+          LogD(2, prep("remove equivalent"));
+          pSchedule->DelEvent(pEqvEvent);
+          cEvent* newEvent = new cEvent (pEvent->EventID());
+          cloneEvent(pEvent, newEvent);
+
+          pSchedule->AddEvent(newEvent);
+
+        }
+
+      } else {
+        LogD(3, prep("equivalent event does not exist"));
+        cEvent* newEvent = new cEvent (pEvent->EventID());
+        cloneEvent(pEvent, newEvent);
+
+        pSchedule->AddEvent(newEvent);
+
+      }
+    }
+  }
+}
+
+void cEquivHandler::updateEquivalent(tChannelID channelID, cEvent *pEvent){
+  multimap<string,string>::iterator it;
+  pair<multimap<string,string>::iterator,multimap<string,string>::iterator> ret;
+
+  LogD(3, prep("Start updateEquivalent %s"), *channelID.ToString());
+
+  ret = equiChanMap.equal_range(*channelID.ToString());
+  for (it=ret.first; it!=ret.second; ++it) {
+    tChannelID equChannelID (tChannelID::FromString((*it).second.c_str()));
+    LogD(3, prep("equivalent channel '%s' exists"), *equChannelID.ToString());
+    cEvent* newEvent = new cEvent (pEvent->EventID());
+    cloneEvent(pEvent, newEvent);
+
+    AddEvent(newEvent, equChannelID);
+  }
+}
+
+
+void cEquivHandler::sortEquivalents(tChannelID channelID, cSchedules* Schedules)
+{
+  multimap<string, string>::iterator it;
+  pair < multimap < string, string > ::iterator, multimap < string, string
+      > ::iterator > ret;
+  LogD(2, prep("sortEquivalents for channel %s count: %d"), *channelID.ToString(), cEquivHandler::getEquiChanMap().count(*channelID.ToString()));
+  
+  ret = equiChanMap.equal_range(*channelID.ToString());
+  for (it = ret.first; it != ret.second; ++it)
+  {
+    LogD(3, prep("equivalent channel exists"));
+    tChannelID equChannelID(tChannelID::FromString((*it).second.c_str()));
+    cChannel* pChannel = GetChannelByID(equChannelID, false);
+    if (pChannel)
+    {
+      LogD(2, prep("found Equivalent channel %s"), *equChannelID.ToString());
+      cSchedule* pSchedule = (cSchedule *) Schedules->GetSchedule(pChannel, true);
+
+      pSchedule->Sort();
+      Schedules->SetModified(pSchedule);
+    }
+  }
+}
+
+void cEquivHandler::cloneEvent(cEvent *Source, cEvent *Dest) {
+
+  Dest->SetEventID(Source->EventID());
+  Dest->SetTableID(Source->TableID());
+  Dest->SetVersion(Source->Version());
+  Dest->SetRunningStatus(Source->RunningStatus());
+  Dest->SetTitle(Source->Title());
+  Dest->SetShortText(Source->ShortText());
+  Dest->SetDescription(Source->Description());
+  cComponents *components = new cComponents();
+  if (Source->Components()) {
+     for (int i = 0; i < Source->Components()->NumComponents(); ++i)
+         components->SetComponent(i, Source->Components()->Component(i)->ToString());
+     }
+  Dest->SetComponents(components);
+  uchar contents[MaxEventContents];
+  for (int i = 0; i < MaxEventContents; ++i)
+      contents[i] = Source->Contents(i);
+  Dest->SetContents(contents);
+  Dest->SetParentalRating(Source->ParentalRating());
+  Dest->SetStartTime(Source->StartTime());
+  Dest->SetDuration(Source->Duration());
+  Dest->SetVps(Source->Vps());
+  if (Source->Seen())
+     Dest->SetSeen();
+}
+
diff --git a/equivhandler.h b/equivhandler.h
new file mode 100644
index 0000000..f60dbfc
--- /dev/null
+++ b/equivhandler.h
@@ -0,0 +1,40 @@
+/*
+ * equivhandler.h
+ *
+ *  Created on: 19.5.2012
+ *      Author: d.petrovski
+ */
+
+#ifndef EQUIVHANDLER_H_
+#define EQUIVHANDLER_H_
+
+#include <vdr/epg.h>
+#include <vdr/channels.h>
+#include <map>
+#include <string>
+
+#define EEPG_FILE_EQUIV "eepg.equiv"
+
+using namespace std;
+
+class cEquivHandler
+{
+public:
+  cEquivHandler();
+  virtual ~cEquivHandler();
+
+  void loadEquivalentChannelMap (void);
+  void updateEquivalent(cSchedules * Schedules, tChannelID channelID, cEvent *pEvent);
+  void updateEquivalent(tChannelID channelID, cEvent *pEvent);
+  void sortEquivalents(tChannelID channelID, cSchedules* Schedules);
+  void cloneEvent(cEvent *Source, cEvent *Dest);
+
+  static multimap<string, string> getEquiChanMap() { return cEquivHandler::equiChanMap; };
+
+private:
+  static multimap<string, string> equiChanMap;
+  static long equiChanFileTime;
+
+};
+
+#endif /* EQUIVHANDLER_H_ */
diff --git a/log.h b/log.h
new file mode 100644
index 0000000..b743763
--- /dev/null
+++ b/log.h
@@ -0,0 +1,78 @@
+/*
+ * log.h
+ *
+ *  Created on: 08.5.2012
+ *      Author: d.petrovski
+ */
+
+#ifndef LOG_H_
+#define LOG_H_
+
+#include <string>
+#include <vdr/tools.h>
+#include <vdr/thread.h>
+#include "setupeepg.h"
+
+#define VERBOSE 1
+/* 0 = only print errors, 1 = print channels and themes, 2 = print channels, themes, titles, summaries 3 = debug mode */
+/* all is logged into /var/log/syslog */
+
+
+inline bool CheckLevel(int level)
+{
+#ifdef DEBUG
+  if (cSetupEEPG::getInstance()->LogLevel >= level)
+#else
+  if (VERBOSE >= level)
+#endif
+  {
+    return true;
+  }
+  return false;
+}
+
+inline const char* PrepareLog(std::string message)
+{
+  message = "EEPG: " + message;
+  return message.c_str();
+}
+
+#define MAXSYSLOGBUF 256
+
+//void LogVsyslog(int errLevel, const char * message, ...)
+inline void LogVsyslog(int errLevel, int const& lineNum, const char * function, const char * message, ...)
+{
+  va_list ap;
+  char fmt[MAXSYSLOGBUF];
+  if (errLevel == LOG_DEBUG) {
+    snprintf(fmt, sizeof(fmt), "[%d] %s:%d %s", cThread::ThreadId(), function, lineNum, message);
+  } else {
+    snprintf(fmt, sizeof(fmt), "[%d] %s", cThread::ThreadId(), message);
+  }
+  va_start(ap,message);
+  vsyslog ( errLevel, fmt, ap );
+  va_end(ap);
+}
+
+#define LogI(a, b...) void( CheckLevel(a) ? LogVsyslog ( LOG_INFO, __LINE__, __FUNCTION__, b ) : void() )
+#define LogE(a, b...) void( CheckLevel(a) ? LogVsyslog ( LOG_ERR, __LINE__, __FUNCTION__, b ) : void() )
+#define LogD(a, b...) void( CheckLevel(a) ? LogVsyslog ( LOG_DEBUG, __LINE__, __FUNCTION__, b ) : void() )
+//#define LogE(a, b...) void( CheckLevel(a) ? esyslog ( b ) : void() )
+//#define LogD(a, b...) void( CheckLevel(a) ? dsyslog ( b ) : void() )
+#define prep(s) PrepareLog(s)
+#define prep2(s) s
+
+
+//void LogF(int level, const char * message, ...)  __attribute__ ((format (printf,2,3)));
+
+//void LogF(int level, const char * message, ...)
+//{
+//  if (CheckLevel(level)) {
+//    va_list ap;
+//    va_start(ap,message);
+//    vsyslog (LOG_ERR, PrepareLog(message), ap );
+//    va_end(ap);
+//  }
+//}
+
+#endif /* LOG_H_ */
diff --git a/scripts/README b/scripts/README
new file mode 100644
index 0000000..22e2835
--- /dev/null
+++ b/scripts/README
@@ -0,0 +1,28 @@
+extract_vdr_chan_ids.pl
+The script extract_vdr_chan_ids.pl can be used along with grep to extract the IDs 
+of required channel i.e.:
+
+USAGE:
+    extract_vdr_chan_ids.pl [/path/to/channels.conf]
+
+EXAMPES:
+    extract_vdr_chan_ids.pl /path/to/channels.conf | grep -i Chanel Name
+
+makeequiv.sh thanks to VDR User
+The makeequiv.sh bash script can be used to generate an eepg.equiv
+file based on SID matching. You may optionally require channel name
+matching as well.
+
+USAGE:
+    makeequiv.sh [channels.conf] [listsources|source to map epg from] <matchname>
+
+EXAMPES:
+    makequiv.sh /video/channels.conf listsources
+    * shows a list of all available sources in channels.conf
+    
+     makeequiv.sh /video/channels.conf S72.7W
+     * map epg from S72.7W channels based on SID match
+      
+     makeequiv.sh /video/channels.conf S72.7W matchname
+     * map epg from S72.7W channels based on SID and channel name match
+
diff --git a/scripts/extract_vdr_chan_ids.pl b/scripts/extract_vdr_chan_ids.pl
new file mode 100755
index 0000000..e40bbb9
--- /dev/null
+++ b/scripts/extract_vdr_chan_ids.pl
@@ -0,0 +1,38 @@
+#!/usr/bin/perl -w
+#
+# extract VDR channel ID's from channels conf
+#
+
+use strict;
+use File::Path;
+
+my $channelsConf = "../channels.conf";
+my $Usage = qq{
+Usage: $0 (default: ../channels.conf)
+       $0 /path/to/channels.conf
+};
+
+$channelsConf  = "@ARGV" if @ARGV;
+
+#my $file;
+open(MYINPUTFILE, "<$channelsConf") or die("Could not open $channelsConf" . $Usage);
+
+foreach (<MYINPUTFILE>)
+{
+    chomp;
+    if ( /^:.*/ )
+    {
+        print $_ . "\n";
+        next;
+    }
+
+    my($line) = $_;
+
+    my(@tokens) = split(":");
+
+    my($chanID) = "$tokens[3]-$tokens[10]-$tokens[11]-$tokens[9] $tokens[0]";
+
+    print $chanID . "\n"
+
+}
+
diff --git a/scripts/makeequiv.sh b/scripts/makeequiv.sh
new file mode 100755
index 0000000..1be3e80
--- /dev/null
+++ b/scripts/makeequiv.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+equiv_file="eepg.equiv"
+
+usage() {
+	echo
+	[[ "$@" ]] && echo -e "ABORTED! $@\n"
+	echo -e "usage: ${0##*/} [channels.conf] [listsources|source to map epg from] <matchname>"
+	echo -e "       * the 3rd argument is optional. if its \"matchname\", channel name matching is required for a positive match.\n"
+	exit
+}
+
+getsources() { awk -F: '{print $4}' "$1" |sort -V |uniq; }
+listsources() { getsources "$1"; exit; }
+
+(($# < 2)) && usage
+[[ -e "$1" ]] || usage "$1 not found"
+[[ "$2" == "listsources" ]] && listsources "$1"
+[[ $(getsources "$1" |grep "$2$") ]] || usage "$2 is not a source in $1"
+[[ "$3" == "matchname" ]] && match_name=1 || match_name=0
+[[ -e "$equiv_file" ]] && rm "$equiv_file"
+echo
+tput sc
+OLDIFS=$IFS; IFS=$'\n'
+for i in $(awk -F: -v var="$2" '$4==var' "$1"); do
+	matched=0
+	mapto_name=" ${i%%:*}"
+	mapto_sid=$(awk -F: '{print $10}' <<<"$i")
+	mapto_line=$(awk -F: '{print $4"-"$11"-"$12"-"$10"-"$13}' <<<"$i")
+	mapto_source=$(awk -F: '{print $4}' <<<"$i")
+	for j in $(awk -F: -v var1="$2" -v var2="$mapto_sid" '$4!=var1 && $10==var2' "$1"); do
+		mapfrom_source=$(awk -F: '{print $4}' <<<"$j")
+		mapfrom_line=$(awk -F: '{print $4"-"$11"-"$12"-"$10"-"$13}' <<<"$j")
+		matched=1
+		(($match_name)) && {
+			[[ " ${j%%:*}" == "$mapto_name" ]] || matched=0
+		} || unset mapto_name
+	done
+	(($matched)) && {
+		((matchcount++))
+		outline="$mapfrom_line $mapto_line$mapto_name"
+		echo "$outline" >>"$equiv_file"
+	} || {
+		((unmatchcount++))
+		array+=( "$i" )
+		unset outline
+	}
+	tput rc
+	tput el
+	echo "$outline"
+	echo -n "matched: $matchcount  -  unmatched: $unmatchcount"
+done
+IFS=$OLDIFS
+echo -e "\n"
+((${#array[@]} > 0)) && for i in "${array[@]}"; do echo "NO MATCH: $i"; done
+echo "wrote $equiv_file ($matchcount entries)."
diff --git a/setupeepg.c b/setupeepg.c
new file mode 100644
index 0000000..c0dff6a
--- /dev/null
+++ b/setupeepg.c
@@ -0,0 +1,37 @@
+/*
+ * setupeepg.c
+ *
+ *  Created on: 08.5.2012
+ *      Author: d.petrovski
+ */
+
+#include <stddef.h>
+#include "setupeepg.h"
+
+// --- cSetupEEPG -------------------------------------------------------
+
+cSetupEEPG* cSetupEEPG::_setupEEPG = NULL;
+
+cSetupEEPG::cSetupEEPG (void)
+:ConfDir(NULL)
+{
+  ConfDir = NULL;
+  OptPat = 1;
+  OrderInfo = 1;
+  RatingInfo = 1;
+  FixEpg = 0;
+  DisplayMessage = 1;
+  ProcessEIT = 0;
+#ifdef DEBUG
+  LogLevel = 0;
+#endif
+}
+
+cSetupEEPG* cSetupEEPG::getInstance()
+{
+  if (!_setupEEPG)
+    _setupEEPG = new cSetupEEPG();
+
+  return _setupEEPG;
+}
+
diff --git a/setupeepg.h b/setupeepg.h
new file mode 100644
index 0000000..0db20d1
--- /dev/null
+++ b/setupeepg.h
@@ -0,0 +1,52 @@
+/*
+ * setupeepg.h
+ *
+ *  Created on: 08.5.2012
+ *      Author: d.petrovski
+ */
+
+#ifndef SETUPEEPG_H_
+#define SETUPEEPG_H_
+#include <string.h>
+
+class cSetupEEPG
+{
+public:
+  int OptPat;
+  int OrderInfo;
+  int RatingInfo;
+  int FixEpg;
+  int DisplayMessage;
+  int ProcessEIT;
+#ifdef DEBUG
+  int LogLevel;
+#endif
+
+public:
+  static cSetupEEPG* getInstance();
+
+  char*  getConfDir() const
+  {
+    return ConfDir;
+  }
+
+  void  setConfDir(char* confDir)
+  {
+    if (ConfDir)
+      delete [] ConfDir;
+    ConfDir = new char[strlen(confDir)+1];
+    strcpy(ConfDir, confDir);
+  }
+
+private:
+  cSetupEEPG (void);
+  cSetupEEPG(cSetupEEPG const&);             // copy constructor is private
+  cSetupEEPG& operator=(cSetupEEPG const&);  // assignment operator is private
+  static cSetupEEPG* _setupEEPG;
+
+private:
+  char *ConfDir;
+
+};
+
+#endif /* SETUPEEPG_H_ */
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..415f213
--- /dev/null
+++ b/util.c
@@ -0,0 +1,392 @@
+/*
+ * util.c
+ *
+ *  Created on: 23.5.2012
+ *      Author: d.petrovski
+ */
+#include "util.h"
+#include "log.h"
+#include "equivhandler.h"
+#include <vdr/channels.h>
+#include <vdr/thread.h>
+#include <vdr/epg.h>
+
+#include <map>
+
+namespace util
+{
+
+int AvailableSources[32];
+int NumberOfAvailableSources = 0;
+
+int Yesterday;
+int YesterdayEpoch;
+int YesterdayEpochUTC;
+
+struct hufftab *tables[2][128];
+int table_size[2][128];
+
+EFormat Format;
+cEquivHandler* EquivHandler;
+
+cChannel *GetChannelByID(tChannelID & channelID, bool searchOtherPos)
+{
+  cChannel *VC = Channels.GetByChannelID(channelID, true);
+  if(!VC && searchOtherPos){
+    //look on other satpositions
+    for(int i = 0;i < NumberOfAvailableSources;i++){
+      channelID = tChannelID(AvailableSources[i], channelID.Nid(), channelID.Tid(), channelID.Sid());
+      VC = Channels.GetByChannelID(channelID, true);
+      if(VC){
+        //found this actually on satellite nextdoor...
+        break;
+      }
+    }
+  }
+
+  return VC;
+}
+
+/*
+ * Convert local time to UTC
+ */
+time_t LocalTime2UTC (time_t t)
+{
+  struct tm *temp;
+
+  temp = gmtime (&t);
+  temp->tm_isdst = -1;
+  return mktime (temp);
+}
+
+/*
+ * Convert UTC to local time
+ */
+time_t UTC2LocalTime (time_t t)
+{
+  return 2 * t - LocalTime2UTC (t);
+}
+
+void GetLocalTimeOffset (void)
+{
+  time_t timeLocal;
+  struct tm *tmCurrent;
+
+  timeLocal = time (NULL);
+  timeLocal -= 86400;
+  tmCurrent = gmtime (&timeLocal);
+  Yesterday = tmCurrent->tm_wday;
+  tmCurrent->tm_hour = 0;
+  tmCurrent->tm_min = 0;
+  tmCurrent->tm_sec = 0;
+  tmCurrent->tm_isdst = -1;
+  YesterdayEpoch = mktime (tmCurrent);
+  YesterdayEpochUTC = UTC2LocalTime (mktime (tmCurrent));
+}
+
+void CleanString (unsigned char *String)
+{
+
+//  LogD (1, prep("Unclean: %s"), String);
+  unsigned char *Src;
+  unsigned char *Dst;
+  int Spaces;
+  int pC;
+  Src = String;
+  Dst = String;
+  Spaces = 0;
+  pC = 0;
+  while (*Src) {
+    // corrections
+    if (*Src == 0x8c) { // iso-8859-2 LATIN CAPITAL LETTER S WITH ACUTE
+      *Src = 0xa6;
+    }
+    if (*Src == 0x8f) { // iso-8859-2 LATIN CAPITAL LETTER Z WITH ACUTE
+      *Src = 0xac;
+    }
+
+    if (*Src!=0x0A &&  *Src < 0x20) { //don't remove newline
+      *Src = 0x20;
+    }
+    if (*Src == 0x20) {
+      Spaces++;
+      if (pC == 0) {
+        Spaces++;
+      }
+    } else {
+      Spaces = 0;
+    }
+    if (Spaces < 2) {
+      *Dst = *Src;
+      Dst++;
+      pC++;
+    }
+    Src++;
+  }
+  if (Spaces > 0 && String && String < Dst) {
+    Dst--;
+    *Dst = 0;
+  } else {
+    *Dst = 0;
+  }
+//  LogD (1, prep("Clean: %s"), String);
+}
+
+struct tChannelIDCompare
+{
+   bool operator() (const tChannelID& lhs, const tChannelID& rhs) const
+   {
+     if (lhs.Source() < rhs.Source()) return true;
+     bool eq = lhs.Source() == rhs.Source();
+     if (eq && lhs.Nid() < rhs.Nid()) return true;
+     eq &= lhs.Nid() == rhs.Nid();
+     if (eq && lhs.Tid() < rhs.Tid()) return true;
+     eq &= lhs.Tid() == rhs.Tid();
+     if (eq && lhs.Sid() < rhs.Sid()) return true;
+     eq &= lhs.Sid() == rhs.Sid();
+     if (eq && lhs.Rid() < rhs.Rid()) return true;
+     return false;
+   }
+};
+
+cTimeMs LastAddEventThread;
+enum { INSERT_TIMEOUT_IN_MS = 10000 };
+
+class cAddEventThread : public cThread
+{
+private:
+  cTimeMs LastHandleEvent;
+  std::map<tChannelID,cList<cEvent>*,tChannelIDCompare> *map_list;
+//  enum { INSERT_TIMEOUT_IN_MS = 10000 };
+protected:
+  virtual void Action(void);
+public:
+  cAddEventThread(void);
+  ~cAddEventThread(void);
+  void AddEvent(cEvent *Event, tChannelID ChannelID);
+};
+
+cAddEventThread::cAddEventThread(void)
+:cThread("cAddEEPGEventThread"), LastHandleEvent()
+{
+  map_list = new std::map<tChannelID,cList<cEvent>*,tChannelIDCompare>;
+}
+
+cAddEventThread::~cAddEventThread(void)
+{
+//  LOCK_THREAD;
+  Cancel(3);
+  std::map<tChannelID,cList<cEvent>*,tChannelIDCompare>::iterator it;
+  for ( it=map_list->begin() ; it != map_list->end(); it++ )
+    (*it).second->Clear();
+}
+
+void cAddEventThread::Action(void)
+{
+  //LogD (0, prep("Action"));
+  SetPriority(19);
+  while (Running() && !LastHandleEvent.TimedOut()) {
+    std::map<tChannelID, cList<cEvent>*, tChannelIDCompare>::iterator it;
+
+    cSchedulesLock SchedulesLock(true, 10);
+    cSchedules *schedules = (cSchedules *) cSchedules::Schedules(SchedulesLock);
+    Lock();
+
+    it = map_list->begin();
+    while (schedules && it != map_list->end()) {
+      cSchedule *schedule = (cSchedule *) schedules->GetSchedule(
+        Channels.GetByChannelID((*it).first), true);
+      while (((*it).second->First()) != NULL) {
+        cEvent* event = (*it).second->First();
+
+         cEvent *pEqvEvent = (cEvent *) schedule->GetEvent (event->EventID(), event->StartTime());
+         if (pEqvEvent){
+//	   LogD (0, prep("schedule->DelEvent(event) size:%d"), (*it).second->Count());
+    	   (*it).second->Del(event);
+//           schedule->DelEvent(pEqvEvent);
+         } else {
+
+          (*it).second->Del(event, false);
+          EpgHandlers.DropOutdated(schedule, event->StartTime(), event->EndTime(), event->TableID(),
+            event->Version());
+          schedule->AddEvent(event);
+        }
+      }
+      EpgHandlers.SortSchedule(schedule);
+       //sortSchedules(schedules, (*it).first);
+       //schedule->Sort();
+      delete (*it).second;
+      map_list->erase(it);
+      it = map_list->begin();
+
+    }
+    Unlock();
+    cCondWait::SleepMs(10);
+  }
+}
+
+void cAddEventThread::AddEvent(cEvent *Event, tChannelID ChannelID)
+{
+  LOCK_THREAD;
+  if (map_list->count(ChannelID) == 0) {
+      cList<cEvent>* list = new cList<cEvent>;
+      list->Add(Event);
+      map_list->insert(std::make_pair(ChannelID, list));
+  } else {
+      map_list->find(ChannelID)->second->Add(Event);
+  }
+//  LogD (0, prep("AddEventT %s channel: <%s> map size:%d"), Event->Title(), *ChannelID.ToString(), map_list->size());
+  LastHandleEvent.Set(INSERT_TIMEOUT_IN_MS);
+}
+
+static cAddEventThread AddEventThread;
+
+// ---
+
+void AddEvent(cEvent *Event, tChannelID ChannelID)
+{
+//  LogD (0, prep("AddEvent %s channel: <%s>"), Event->Title(), *ChannelID.ToString());
+  AddEventThread.AddEvent(Event, ChannelID);
+//  if (!AddEventThread.Active())
+//     AddEventThread.Start();
+  if (!AddEventThread.Active() && LastAddEventThread.TimedOut()){
+    LastAddEventThread.Set(INSERT_TIMEOUT_IN_MS * 2);
+    AddEventThread.Start();
+  }
+
+}
+
+/** \brief Decode an EPG string as necessary
+ *
+ *  \param src - Possibly encoded string
+ *  \param size - Size of the buffer
+ *
+ *  \retval NULL - Can't decode
+ *  \return A decoded string
+ */
+char *freesat_huffman_decode (const unsigned char *src, size_t size)
+{
+  int tableid;
+
+  if (src[0] == 0x1f && (src[1] == 1 || src[1] == 2)) {
+    int uncompressed_len = 30;
+    char *uncompressed = (char *) calloc (1, uncompressed_len + 1);
+    unsigned value = 0, byte = 2, bit = 0;
+    int p = 0;
+    unsigned char lastch = START;
+
+    tableid = src[1] - 1;
+    while (byte < 6 && byte < size) {
+      value |= src[byte] << ((5 - byte) * 8);
+      byte++;
+    }
+    //freesat_table_load ();    /**< Load the tables as necessary */
+
+    do {
+      bool found = false;
+      unsigned bitShift = 0;
+      if (lastch == ESCAPE) {
+        char nextCh = (value >> 24) & 0xff;
+        found = true;
+        // Encoded in the next 8 bits.
+        // Terminated by the first ASCII character.
+        bitShift = 8;
+        if ((nextCh & 0x80) == 0)
+          lastch = nextCh;
+        if (p >= uncompressed_len) {
+          uncompressed_len += 10;
+          uncompressed = (char *) REALLOC (uncompressed, uncompressed_len + 1);
+        }
+        uncompressed[p++] = nextCh;
+        uncompressed[p] = 0;
+      } else {
+        int j;
+        for (j = 0; j < table_size[tableid][lastch]; j++) {
+          unsigned mask = 0, maskbit = 0x80000000;
+          short kk;
+          for (kk = 0; kk < tables[tableid][lastch][j].bits; kk++) {
+            mask |= maskbit;
+            maskbit >>= 1;
+          }
+          if ((value & mask) == tables[tableid][lastch][j].value) {
+            char nextCh = tables[tableid][lastch][j].next;
+            bitShift = tables[tableid][lastch][j].bits;
+            if (nextCh != STOP && nextCh != ESCAPE) {
+              if (p >= uncompressed_len) {
+                uncompressed_len += 10;
+                uncompressed = (char *) REALLOC (uncompressed, uncompressed_len + 1);
+              }
+              uncompressed[p++] = nextCh;
+              uncompressed[p] = 0;
+            }
+            found = true;
+            lastch = nextCh;
+            break;
+          }
+        }
+      }
+      if (found) {
+        // Shift up by the number of bits.
+        unsigned b;
+        for (b = 0; b < bitShift; b++) {
+          value = (value << 1) & 0xfffffffe;
+          if (byte < size)
+            value |= (src[byte] >> (7 - bit)) & 1;
+          if (bit == 7) {
+            bit = 0;
+            byte++;
+          } else
+            bit++;
+        }
+      } else {
+        LogE (0, prep("Missing table %d entry: <%s>"), tableid + 1, uncompressed);
+        // Entry missing in table.
+        return uncompressed;
+      }
+    } while (lastch != STOP && value != 0);
+
+    return uncompressed;
+  }
+  return NULL;
+}
+
+void decodeText2 (const unsigned char *from, int len, char *buffer, int buffsize)
+{
+  if (from[0] == 0x1f) {
+    char *temp = freesat_huffman_decode (from, len);
+    if (temp) {
+      len = strlen (temp);
+      len = len < buffsize - 1 ? len : buffsize - 1;
+      strncpy (buffer, temp, len);
+      buffer[len] = 0;
+      free (temp);
+      return;
+    }
+  }
+
+  SI::String convStr;
+  SI::CharArray charArray;
+  charArray.assign(from, len);
+  convStr.setData(charArray, len);
+  //LogE(5, prep("decodeText2 from %s - length %d"), from, len);
+  convStr.getText(buffer,  buffsize);
+  //LogE(5, prep("decodeText2 buffer %s - buffsize %d"), buffer, buffsize);
+}
+
+void sortSchedules(cSchedules * Schedules, tChannelID channelID){
+
+  LogD(3, prep("Start sortEquivalent %s"), *channelID.ToString());
+
+  cChannel *pChannel = GetChannelByID (channelID, false);
+  cSchedule *pSchedule;
+  if (pChannel) {
+    pSchedule = (cSchedule *) (Schedules->GetSchedule(pChannel, true));
+      pSchedule->Sort();
+      Schedules->SetModified(pSchedule);
+    }
+  if (EquivHandler->getEquiChanMap().count(*channelID.ToString()) > 0)
+    EquivHandler->sortEquivalents(channelID, Schedules);
+}
+
+}
+
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..dec5b70
--- /dev/null
+++ b/util.h
@@ -0,0 +1,93 @@
+/*
+ * util.h
+ *
+ *  Created on: 23.5.2012
+ *      Author: d.petrovski
+ */
+
+#ifndef UTIL_H_
+#define UTIL_H_
+#include <time.h>
+#include <stdlib.h>
+
+class cChannel;
+struct tChannelID;
+class cEvent;
+class cEquivHandler;
+class cSchedules;
+
+#define START   '\0'
+#define STOP    '\0'
+#define ESCAPE  '\1'
+
+#define Asprintf(a, b, c...) void( asprintf(a, b, c) < 0 ? esyslog("memory allocation error - %s", b) : void() )
+
+namespace util
+{
+
+extern int AvailableSources[32];
+extern int NumberOfAvailableSources;
+
+extern int Yesterday;
+extern int YesterdayEpoch;
+extern int YesterdayEpochUTC;
+
+extern enum EFormat
+{
+//First all batchmode, load ONCE protocols:
+  MHW1 = 0,
+  MHW2,
+  SKY_IT,
+  SKY_UK,
+  NAGRA,
+//Than all CONTinuous protocols, so they will be processed LAST:
+  PREMIERE,
+  FREEVIEW,
+  DISH_BEV,
+  EIT,
+//the highest number of EPG-formats that is supported by this plugin
+  HIGHEST_FORMAT = EIT
+} Format;
+
+extern cEquivHandler* EquivHandler;
+
+void AddEvent(cEvent *event, tChannelID ChannelID);
+
+cChannel *GetChannelByID(tChannelID & channelID, bool searchOtherPos);
+time_t LocalTime2UTC(time_t t);
+time_t UTC2LocalTime(time_t t);
+void GetLocalTimeOffset(void);
+void CleanString(unsigned char *String);
+void decodeText2(const unsigned char *from, int len, char *buffer, int buffsize);
+char *freesat_huffman_decode(const unsigned char *src, size_t size);
+void sortSchedules(cSchedules * Schedules, tChannelID channelID);
+
+//struct sNode
+//{
+//  char *Value;
+//  struct sNode *P0;
+//  struct sNode *P1;
+//};
+//
+//typedef struct sNode sNodeH;
+
+template<class T> T REALLOC(T Var, size_t Size)
+{
+  T p = (T) realloc(Var, Size);
+  if (!p) free(Var);
+  return p;
+}
+
+struct hufftab
+{
+  unsigned int value;
+  short bits;
+  char next;
+};
+
+extern struct hufftab *tables[2][128];
+extern int table_size[2][128];
+//static sNodeH* sky_tables[2];
+
+}
+#endif /* UTIL_H_ */

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



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