summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-15 18:23:18 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-15 18:23:18 +0000
commit3133bbc63a2d32dac638db58fa13e966488e88b5 (patch)
tree326595b5fefc87fd7cf5ab3905bc00883fe3c919 /src
downloadkchmviewer-3133bbc63a2d32dac638db58fa13e966488e88b5.tar.gz
kchmviewer-3133bbc63a2d32dac638db58fa13e966488e88b5.zip
Added abandoned KDE3 version of kchmviewer
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kchmviewer@1090662 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am39
-rw-r--r--src/config.h.in255
-rw-r--r--src/forwarddeclarations.h48
-rw-r--r--src/iconstorage.cpp1295
-rw-r--r--src/iconstorage.h71
-rw-r--r--src/kchmbookmarkwindow.cpp239
-rw-r--r--src/kchmbookmarkwindow.h63
-rw-r--r--src/kchmconfig.cpp215
-rw-r--r--src/kchmconfig.h84
-rw-r--r--src/kchmcontentswindow.cpp95
-rw-r--r--src/kchmcontentswindow.h52
-rw-r--r--src/kchmdialogchooseurlfromlist.cpp70
-rw-r--r--src/kchmdialogchooseurlfromlist.h47
-rw-r--r--src/kchmindexwindow.cpp179
-rw-r--r--src/kchmindexwindow.h62
-rw-r--r--src/kchmkeyeventfilter.cpp53
-rw-r--r--src/kchmkeyeventfilter.h49
-rw-r--r--src/kchmlistitemtooltip.h72
-rw-r--r--src/kchmmainwindow.cpp1298
-rw-r--r--src/kchmmainwindow.h191
-rw-r--r--src/kchmnavtoolbar.cpp75
-rw-r--r--src/kchmnavtoolbar.h42
-rw-r--r--src/kchmsearchengine.cpp257
-rw-r--r--src/kchmsearchengine.h61
-rw-r--r--src/kchmsearchengine_impl.cpp572
-rw-r--r--src/kchmsearchengine_impl.h151
-rw-r--r--src/kchmsearchtoolbar.cpp438
-rw-r--r--src/kchmsearchtoolbar.h87
-rw-r--r--src/kchmsearchwindow.cpp246
-rw-r--r--src/kchmsearchwindow.h85
-rw-r--r--src/kchmsettings.cpp298
-rw-r--r--src/kchmsettings.h94
-rw-r--r--src/kchmsetupdialog.cpp395
-rw-r--r--src/kchmsetupdialog.ui710
-rw-r--r--src/kchmsourcefactory.cpp94
-rw-r--r--src/kchmsourcefactory.h43
-rw-r--r--src/kchmtreeviewitem.cpp286
-rw-r--r--src/kchmtreeviewitem.h100
-rw-r--r--src/kchmviewwindow.cpp314
-rw-r--r--src/kchmviewwindow.h156
-rw-r--r--src/kchmviewwindow_qtextbrowser.cpp270
-rw-r--r--src/kchmviewwindow_qtextbrowser.h107
-rw-r--r--src/kchmviewwindowmgr.cpp344
-rw-r--r--src/kchmviewwindowmgr.h90
-rw-r--r--src/kde-qt.cpp52
-rw-r--r--src/kde-qt.h148
-rw-r--r--src/kde/Makefile.am8
-rw-r--r--src/kde/kchmdcopiface.cpp86
-rw-r--r--src/kde/kchmdcopiface.h58
-rw-r--r--src/kde/kchmdcopiface_skel.cpp98
-rw-r--r--src/kde/kchmviewwindow_khtmlpart.cpp163
-rw-r--r--src/kde/kchmviewwindow_khtmlpart.h114
-rw-r--r--src/kqrunprocess.h52
-rw-r--r--src/kqtempfile.cpp72
-rw-r--r--src/kqtempfile.h53
-rw-r--r--src/main.cpp96
-rw-r--r--src/pics/Makefile.am2
-rw-r--r--src/pics/cr128-app-kchmviewer.pngbin0 -> 15308 bytes
-rw-r--r--src/pics/cr48-app-kchmviewer.pngbin0 -> 3458 bytes
-rw-r--r--src/pics/cr64-app-kchmviewer.pngbin0 -> 5390 bytes
60 files changed, 10794 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..6540292
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,39 @@
+if AMC_USE_KDE
+LIB_KDEEXTRADIR = kde
+LIB_KDEEXTRA = kde/libkdeextra.a
+endif
+
+bin_PROGRAMS = kchmviewer
+kchmviewer_SOURCES = iconstorage.cpp kchmbookmarkwindow.cpp kchmconfig.cpp \
+ kchmindexwindow.cpp kchmmainwindow.cpp kchmsearchtoolbar.cpp kchmsearchwindow.cpp \
+ kchmsettings.cpp kchmsourcefactory.cpp kchmtreeviewitem.cpp kchmviewwindow.cpp main.cpp \
+ kchmdialogchooseurlfromlist.cpp kde-qt.cpp kchmviewwindow_qtextbrowser.cpp \
+ kchmsetupdialog.ui kqtempfile.cpp kchmnavtoolbar.cpp kchmviewwindowmgr.cpp \
+ kchmkeyeventfilter.cpp kchmcontentswindow.cpp kchmsearchengine_impl.cpp \
+ kchmsearchengine.cpp
+
+# set the include path found by configure
+INCLUDES = $(QT_INCLUDES) $(CHM_INCLUDES) $(KDE_INCLUDES) $(LIBCHMFILE_INCLUDES)
+
+SUBDIRS = $(LIB_KDEEXTRADIR) . pics
+
+# the library search path.
+kchmviewer_LDADD = $(top_builddir)/lib/libchmfile/libchmfile.a $(LIB_KDEEXTRA) \
+ $(CHM_LIBS) $(LIB_QT) $(LIB_KDEUI) $(LIB_KHTML)
+kchmviewer_LDFLAGS = $(QT_LDFLAGS) $(KDE_LDFLAGS) -L../lib/chmlib/
+
+METASOURCES = AUTO
+KDE_OPTIONS = qtonly
+KDE_ICON = AUTO
+noinst_HEADERS = kchmsettings.h forwarddeclarations.h kchmsourcefactory.h \
+ iconstorage.h kchmbookmarkwindow.h kchmconfig.h kchmtreeviewitem.h \
+ kchmdialogchooseurlfromlist.h kchmviewwindow.h kchmindexwindow.h \
+ kchmmainwindow.h kchmviewwindow_qtextbrowser.h kchmsearchtoolbar.h kde-qt.h \
+ kchmsearchwindow.h kqtempfile.h kqrunprocess.h kchmnavtoolbar.h kchmviewwindowmgr.h \
+ kchmkeyeventfilter.h kchmcontentswindow.h kchmlistitemtooltip.h kchmsearchengine_impl.h \
+ kchmsearchengine.h
+
+messages: rc.cpp
+ $(EXTRACTRC) *.rc > rc.cpp
+ $(EXTRACTRC) *.ui >> rc.cpp
+ $(XGETTEXT) rc.cpp *.h *.cpp -o $(podir)/kchmviewer.pot
diff --git a/src/config.h.in b/src/config.h.in
new file mode 100644
index 0000000..f0c2ac9
--- /dev/null
+++ b/src/config.h.in
@@ -0,0 +1,255 @@
+/* src/config.h.in. Generated from configure.in by autoheader. */
+
+/* Application version as integer */
+#undef APP_INT_VERSION
+
+/* Application name */
+#undef APP_NAME
+
+/* Application version as text */
+#undef APP_VERSION
+
+/* Define to 1 if you have the <Carbon/Carbon.h> header file. */
+#undef HAVE_CARBON_CARBON_H
+
+/* Define if you have the CoreAudio API */
+#undef HAVE_COREAUDIO
+
+/* Define to 1 if you have the <crt_externs.h> header file. */
+#undef HAVE_CRT_EXTERNS_H
+
+/* Defines if your system has the crypt function */
+#undef HAVE_CRYPT
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define if you have libjpeg */
+#undef HAVE_LIBJPEG
+
+/* Define if you have libpng */
+#undef HAVE_LIBPNG
+
+/* Define if you have a working libpthread (will enable threaded code) */
+#undef HAVE_LIBPTHREAD
+
+/* Define if you have libz */
+#undef HAVE_LIBZ
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if your system needs _NSGetEnviron to set up the environment */
+#undef HAVE_NSGETENVIRON
+
+/* Define if you have res_init */
+#undef HAVE_RES_INIT
+
+/* Define if you have the res_init prototype */
+#undef HAVE_RES_INIT_PROTO
+
+/* Define if you have a STL implementation by SGI */
+#undef HAVE_SGI_STL
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have strlcat */
+#undef HAVE_STRLCAT
+
+/* Define if you have the strlcat prototype */
+#undef HAVE_STRLCAT_PROTO
+
+/* Define if you have strlcpy */
+#undef HAVE_STRLCPY
+
+/* Define if you have the strlcpy prototype */
+#undef HAVE_STRLCPY_PROTO
+
+/* Define to 1 if you have the <sys/bitypes.h> header file. */
+#undef HAVE_SYS_BITYPES_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Suffix for lib directories */
+#undef KDELIBSUFF
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* The size of `char *', as computed by sizeof. */
+#undef SIZEOF_CHAR_P
+
+/* The size of `int', as computed by sizeof. */
+#undef SIZEOF_INT
+
+/* The size of `long', as computed by sizeof. */
+#undef SIZEOF_LONG
+
+/* The size of `short', as computed by sizeof. */
+#undef SIZEOF_SHORT
+
+/* The size of `size_t', as computed by sizeof. */
+#undef SIZEOF_SIZE_T
+
+/* The size of `unsigned long', as computed by sizeof. */
+#undef SIZEOF_UNSIGNED_LONG
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* use builtin chmlib */
+#undef USE_BUILTIN_CHMLIB
+
+/* use KDE support */
+#undef USE_KDE
+
+/* Version number of package */
+#undef VERSION
+
+/* Defined if compiling without arts */
+#undef WITHOUT_ARTS
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/*
+ * jpeg.h needs HAVE_BOOLEAN, when the system uses boolean in system
+ * headers and I'm too lazy to write a configure test as long as only
+ * unixware is related
+ */
+#ifdef _UNIXWARE
+#define HAVE_BOOLEAN
+#endif
+
+
+
+/*
+ * AIX defines FD_SET in terms of bzero, but fails to include <strings.h>
+ * that defines bzero.
+ */
+
+#if defined(_AIX)
+#include <strings.h>
+#endif
+
+
+
+#if defined(HAVE_NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H)
+# include <sys/time.h>
+# include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#endif
+
+
+
+#if !defined(HAVE_RES_INIT_PROTO)
+#ifdef __cplusplus
+extern "C" {
+#endif
+int res_init(void);
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+#if !defined(HAVE_STRLCAT_PROTO)
+#ifdef __cplusplus
+extern "C" {
+#endif
+unsigned long strlcat(char*, const char*, unsigned long);
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+#if !defined(HAVE_STRLCPY_PROTO)
+#ifdef __cplusplus
+extern "C" {
+#endif
+unsigned long strlcpy(char*, const char*, unsigned long);
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+/*
+ * On HP-UX, the declaration of vsnprintf() is needed every time !
+ */
+
+#if !defined(HAVE_VSNPRINTF) || defined(hpux)
+#if __STDC__
+#include <stdarg.h>
+#include <stdlib.h>
+#else
+#include <varargs.h>
+#endif
+#ifdef __cplusplus
+extern "C"
+#endif
+int vsnprintf(char *str, size_t n, char const *fmt, va_list ap);
+#ifdef __cplusplus
+extern "C"
+#endif
+int snprintf(char *str, size_t n, char const *fmt, ...);
+#endif
+
+
+
+#if defined(__SVR4) && !defined(__svr4__)
+#define __svr4__ 1
+#endif
+
+
+/* type to use in place of socklen_t if not defined */
+#undef kde_socklen_t
+
+/* type to use in place of socklen_t if not defined (deprecated, use
+ kde_socklen_t) */
+#undef ksize_t
diff --git a/src/forwarddeclarations.h b/src/forwarddeclarations.h
new file mode 100644
index 0000000..ea8d8ee
--- /dev/null
+++ b/src/forwarddeclarations.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef FORWARD_DECLARATIONS_H
+#define FORWARD_DECLARATIONS_H
+
+class QComboBox;
+class QListView;
+class QListBox;
+class QListViewItem;
+class QListViewItemIterator;
+class QLineEdit;
+class QTabWidget;
+class QToolButton;
+
+class KCHMMainWindow;
+class KCHMViewWindow;
+class KCHMIndexWindow;
+class KCHMSearchWindow;
+class KCHMBookmarkWindow;
+class KCHMSettings;
+class KCHMSearchAndViewToolbar;
+class KCHMNavToolbar;
+class KCHMViewWindow;
+class KCHMViewWindowMgr;
+class KCHMContentsWindow;
+
+#include "config.h"
+
+#endif /* FORWARD_DECLARATIONS_H */
diff --git a/src/iconstorage.cpp b/src/iconstorage.cpp
new file mode 100644
index 0000000..c4bbb25
--- /dev/null
+++ b/src/iconstorage.cpp
@@ -0,0 +1,1295 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+
+#include "iconstorage.h"
+
+
+static const KCHMIconStorage::png_memory_image_t png_image_toolbakicons[] =
+{
+{
+ 1625,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x0D\x00\x00\x0B\x0D\x01\xED\x07\xC0\x2C\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD3\x09\x09\x13\x12\x2A\x95\x49\x4D\xF6\x00\x00\x05\xE6\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x97\x5D\x8C\x5B\x47\x15\xC7\x7F\x77\xEE\xBD\xFE\xDA\xAC\xF7\x23\x2E\x49\x76\x13\x36\x81\x50"
+ "\x25\xA4\x91\x36\x7B\xA1\x0F\x44\x09\x09\x10\x22\xA2\x88\x96\x0A\x29\x2F\x2D\x6D\x0A\x2B\xC8\x43\xDF"
+ "\xAA\xBE\x54\x42\x4A\x05\x02\x89\x87\x22\xF5\xA5\xC8\x22\x25\xB4\x12\x2A\x0F\x14\x10\x0A\x12\x55\x1A"
+ "\xD4\x88\x0D\x91\xBA\xDE\xEE\x2E\x5D\xAA\xB6\x86\x6C\x83\xE3\x4D\xF6\xC3\x5E\xC7\xF6\xBD\xBE\x1F\x33"
+ "\x3C\xF8\xEE\xDA\x8E\xED\x6C\x8A\x0A\x8C\xF4\x7F\xF0\x9D\x33\xF3\xFF\x9F\xE3\x99\x33\xE7\xC0\xFF\x79"
+ "\x68\x1F\xC5\x78\xEC\xCC\xF4\x2E\x50\x47\x41\x8E\x02\xA3\x28\xD9\xB4\x87\x9A\x41\xC9\x19\xA4\x77\xC9"
+ "\xE2\x7C\x16\x90\xE9\x74\x5A\x7D\x2C\x02\xC6\xCE\x4C\x9F\x06\x9E\x00\x0E\x83\x02\x24\x88\x08\x88\x58"
+ "\xDD\x40\x3A\x10\x38\xCD\x4B\x26\x90\xFE\x2B\x96\xFA\xF9\x39\xC0\x4B\xA7\xD3\xF2\x3F\x12\x30\x76\x66"
+ "\xFA\x00\x9A\x78\x1E\x25\xBF\x88\xD0\x21\xD2\x0F\x91\x41\x22\xD1\x38\x3B\x92\x25\x3E\xBF\xBD\x00\x40"
+ "\xD9\x81\x8B\xD7\x46\xB0\x1D\x17\x6A\x8B\xE0\x2C\x83\xF2\x00\x65\x13\x38\x4F\x5B\xFC\xF2\x17\x80\xD3"
+ "\x49\x88\xB6\x81\xD7\xE7\x00\x88\x6F\x25\xB2\xE9\x13\x7C\xFB\xC1\x1C\xFB\x3F\xB5\x89\xFB\xB7\x27\x88"
+ "\x45\x44\xDB\x9A\xDC\x52\x8D\xBF\xFE\x7D\x95\xCB\xEF\xC2\x5B\xD7\x4C\xA8\xCC\xD7\x27\x02\xF7\x35\x8B"
+ "\x97\xBE\x03\x94\xD2\xE9\xB4\xBF\xA1\x80\x75\x72\x3D\x0A\xC9\xFB\x79\xF4\xC0\xBF\x78\xE8\x60\x8A\x81"
+ "\x4D\x46\xD7\x68\xA9\x3B\xB6\xBA\x3C\x5B\xE4\x67\x97\x4C\x6E\x2E\x2C\x80\x5F\x06\xE9\xCD\x58\xEA\xDC"
+ "\x57\x81\xC5\xE6\x48\xE8\x5D\xC9\x8D\x04\x3B\x76\x6C\xE3\xE9\xE3\x65\x8E\x7D\x6E\x10\xD3\x10\xF8\x92"
+ "\x16\xBC\xF1\x76\x89\x6C\xBE\xC6\xF0\x7D\x51\x02\xA9\x5A\x30\x9C\x8A\x72\x68\x0F\x14\xCA\x3E\xD7\x16"
+ "\x35\x50\xC1\x96\xBC\xDA\xF7\xD9\x21\xA6\x7F\x67\x59\x96\x9F\xC9\x64\x54\x9B\x80\xB1\x33\x6F\x1F\x00"
+ "\xED\x02\xBA\xC9\xF0\xF0\x30\xCF\x9C\x54\xEC\xDC\x12\xC3\xF3\x55\x1B\xAE\xCC\x95\x39\x75\x24\xC5\x03"
+ "\x3B\x13\x5C\xB8\x5A\xE0\xBE\x3E\xA3\xCD\xC6\xD0\x35\xF6\xEF\x8C\x73\xAB\x24\xB9\xBE\x0C\xA0\x3E\x93"
+ "\xF7\x76\x5D\x19\x12\x73\xD7\x43\x11\xDC\x19\xD3\x97\x20\x80\xE4\x7E\x9E\x3C\xB4\x4C\x32\x91\xA0\x5A"
+ "\x6B\xBF\x49\x73\xF3\x55\x4E\x1D\x49\xAD\xFF\x3E\x75\x24\xC5\xEC\x3F\xAB\x5D\xFF\x9E\x6F\x1D\x4D\x72"
+ "\xF3\xB6\xC9\x07\xFF\x28\x43\xA4\xFF\x2C\x92\x29\xC0\x03\x3C\xBD\xE1\x7D\xE6\x34\xA8\xEF\x12\x1F\xE2"
+ "\xB1\x07\x0B\xEC\x1D\xD9\x84\x17\xA8\x36\xBC\x9F\x73\x5A\xC8\xD7\xC6\xB5\x9B\x4E\x47\x7B\x2F\x50\x28"
+ "\x60\x67\x4A\xF2\x66\xB6\x1F\xBC\xD2\xB6\xBC\xDC\x5B\x1C\xD2\x66\xA6\x2C\xCB\x72\x1B\x11\x50\xF2\x09"
+ "\x34\x93\x2D\xA9\x5E\xF6\x8C\x38\x54\x9C\xF6\xAB\xBB\x58\xF4\x3A\x92\x03\x1D\xED\x9B\x47\xB2\xC7\xE4"
+ "\x1B\xA3\x4B\xBC\x36\x61\x82\x1E\x7B\x04\xC9\xCB\x80\x6D\x00\x8C\x7D\xEF\xAD\x5D\xC0\x61\x62\x9B\xF9"
+ "\xD2\xEE\x65\xFC\xA0\x07\x3F\x08\x5A\x09\x6C\xD9\x95\xFC\x0F\x57\x57\xEE\x4A\xEE\xF9\x8A\xE5\x92\x8B"
+ "\x42\x87\xD8\x66\xB0\x17\x46\x27\x6B\x27\xF6\x5A\xD1\x0B\x85\xB5\x08\x1C\x05\x20\x32\x48\x2A\x59\xA2"
+ "\x62\xB7\x7B\xD3\x8D\xFC\xD5\x3F\x2F\x75\x25\x5E\x58\x71\xF8\x70\x45\xE3\x6A\x6E\xB8\xF1\x31\x62\x83"
+ "\xBD\x00\x66\xDF\x41\x60\x6A\x4D\xC0\x28\xC0\xD6\x3E\x89\x02\xAA\xB5\x56\xEF\x4F\x1F\xDF\x72\xCF\xE4"
+ "\xCD\x6B\x57\xCA\x01\x57\x73\x23\x2D\xF3\x91\x68\x1C\x17\x40\x44\xF6\x00\xF1\x86\x00\x3D\xC6\x40\xDC"
+ "\xA5\x7C\x87\xF7\x4F\x3D\xBC\xAD\xAB\x87\xDD\xA2\xD2\x3C\xCE\x02\x87\x9E\x03\x15\x5E\x26\x5D\x00\x9A"
+ "\x09\x22\xD8\x8D\x24\xD6\xC8\xA7\x22\x46\x32\xEA\x52\xA9\xC9\x75\xDC\x8D\xFC\xA3\x8C\xCB\xDF\x07\xAD"
+ "\x39\x51\x1A\x3D\xA0\x94\x06\x98\x46\x73\x4A\xAE\x78\x11\x6E\xDB\xFE\xFF\xB2\x1C\x10\x8D\x6B\x28\x1D"
+ "\x0A\x76\x0C\x43\xA8\xFF\x1A\xDB\x7A\x14\xFC\x4A\x43\xC1\x7A\x31\x11\x38\x14\x6B\x51\xF2\xE5\xDE\x75"
+ "\x9C\xF8\xB1\xF7\xB1\x10\x1F\x7A\x2E\x8C\xBC\x08\xCF\x82\xF2\x40\x79\x59\x40\x1A\x61\x12\x9A\x41\xD3"
+ "\xA9\xD8\x3E\xA6\xDE\x9A\x9D\xBF\xFC\x43\xC9\xC5\x67\xC5\x5D\x37\xDE\x68\x98\x4D\x2F\x8E\xED\xB8\xE1"
+ "\x13\x5D\xCB\xA2\xE3\xD5\x77\x96\xDE\x25\x00\xDC\x65\x84\x10\x6D\x38\xF6\xA3\xEE\x87\xEB\x5E\x86\x2E"
+ "\x1A\xC0\x5D\xAE\x7F\x74\x0B\x19\xC0\x11\x00\x61\x0D\x37\x81\xBD\x88\xA9\x79\xC4\x8D\x76\x7C\xFD\x27"
+ "\xDE\x3D\x8B\x18\x88\x7B\x2D\x58\xDB\xC3\xD4\x3C\xB0\x17\x41\xFA\xB3\x56\xFC\x4F\xF3\xEB\xA9\x18\x90"
+ "\x48\xFF\x15\x04\x5F\x28\x15\x97\xF8\xF4\x70\x4F\x47\xB2\xC7\x5F\xB0\x39\xFF\x54\xB2\xA3\x88\xC7\x5F"
+ "\x28\x6D\x18\x89\x6C\xAE\x52\xFF\xFF\xFD\xF2\xEB\xE8\x54\x00\x5B\x07\xC8\x64\x32\x9C\x1C\xD3\x66\xF3"
+ "\xC2\xFA\x8A\x5F\x2B\x6F\x4F\x0D\x24\xE9\x8F\x07\xC4\x8C\x76\xFC\x71\xB2\xCA\xD7\xAC\x44\xDB\xE6\x97"
+ "\xA6\x6F\x77\xB4\x5F\x83\x5D\x93\xE4\x6F\x5C\xAF\x7B\xAF\xBD\xFC\x53\xE0\x26\x50\x6C\x3E\x5D\x1E\x81"
+ "\xF3\x0C\x40\x76\x3E\x47\xCC\xF0\xE8\x8D\xBA\x1D\xF1\xEC\xF9\x1B\x6D\x02\xBA\xD9\xF6\x46\x5D\x62\x86"
+ "\x47\x76\x3E\x57\x37\x74\xF2\x2F\x02\xC5\x10\x8D\x7A\x20\x93\xC9\xA8\x93\x96\x91\xCF\xAB\x07\x0A\x81"
+ "\x14\xC7\x97\x8A\x35\x76\x0F\x45\x88\x98\x3A\xA6\xAE\xB5\xE1\xCD\xBF\x95\x39\xBC\xBF\x17\x80\x1F\xFC"
+ "\x2A\xDF\xD1\xC6\xD4\x35\x04\x3E\x7F\x99\x29\x50\x75\x3C\x70\x0B\xCF\x5B\xE6\x6F\x2F\x02\x79\xA0\x98"
+ "\x4E\xA7\x83\x96\x92\xCC\xB2\x2C\x35\xC4\xF4\x74\x5E\xED\x5B\x75\x03\x71\xEC\xFA\xA2\xCB\x48\x4A\x90"
+ "\x88\x47\x31\x74\xAD\x0D\x13\x73\x15\x26\xE6\x2A\x1D\xE7\x0C\x5D\xC3\xB1\xAB\x5C\x9C\x5A\xA5\x62\x87"
+ "\xE4\xFA\xAF\x7F\x03\x2C\x00\x4B\x80\x9B\xC9\x64\x5A\x6B\xC2\x4C\x26\x83\x65\x59\xC1\x9A\x08\x4F\xEA"
+ "\xC7\xDE\xCB\x39\x78\x52\xB0\x63\xB3\xC0\x34\x04\x86\x60\x43\x68\xCA\x67\xF2\x83\x2A\x57\xDE\x29\xE2"
+ "\xF9\xB2\x99\x3C\x0F\xDC\x02\xEC\xB5\xAE\xA9\x63\x59\x3E\x3E\x3E\x2E\x80\xC4\xA4\xFF\xCD\x23\x44\xFA"
+ "\xCF\xA2\xE9\x63\x51\x53\xF0\xC9\xAD\x09\xF6\x0D\x49\x06\x07\xFB\xD0\x75\xB3\x65\x4D\x10\x78\xAC\xAC"
+ "\xAC\xF2\xCE\x0D\xC1\x87\x0B\x55\x6A\x9E\x04\xE9\xCF\xE2\xE4\x5F\xB4\xA2\x17\xA6\xC2\x43\x77\x0B\xA8"
+ "\x36\x97\xE5\x5D\x1B\x93\x50\x44\x0C\x18\x98\x54\x8F\x3E\x89\x1E\x7B\x04\x4D\x1F\x5D\x9B\x8F\x47\x20"
+ "\xD5\x57\xBF\xC5\x4B\xAB\x3E\xB6\xDB\xB4\x58\xFA\xB3\xF8\xE5\xD7\x2D\xFD\xD5\xDF\x87\x87\x6D\x09\x28"
+ "\x74\xEA\x8E\xEE\xDA\x9A\x8D\x8F\x8F\x6B\x80\x01\xF4\x00\xFD\x93\xB5\x13\x7B\x31\xFB\x0E\x22\x22\x7B"
+ "\x10\xE6\xEE\xF0\x49\x0D\x9F\x13\x2F\x4B\x50\xCB\xE2\x16\x32\x61\x92\xA9\x00\xAB\xA1\x80\x0A\xE0\x77"
+ "\x6A\x56\xEF\xA9\x39\x0D\xA3\x61\x86\x11\x89\x87\x88\x85\xDF\xC4\x7A\x32\xAB\x97\xDA\x0E\x60\x87\x70"
+ "\x36\x6A\x4E\xFF\x0D\xCD\x4A\x06\xF6\x87\x57\xDE\x02\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1793,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xAF\xC8\x37\x05\x8A\xE9\x00"
+ "\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61"
+ "\x67\x65\x52\x65\x61\x64\x79\x71\xC9\x65\x3C\x00\x00\x06\x93\x49\x44\x41\x54\x78\xDA\x62\x60\x20\x13"
+ "\xFC\xE8\x66\x38\xF0\xAD\x83\xE1\x22\x90\xC9\x0D\xC4\x2C\xE4\x9A\x03\x10\x40\x4C\xFF\xFF\xFF\x67\x20"
+ "\x15\x7F\xEC\x60\x50\x64\xFC\xCF\x60\x0F\xC4\x7A\xAB\x63\x18\x02\xA1\x8E\x60\x24\xC7\x2C\x80\x00\x62"
+ "\x22\xC7\xD5\xAC\x0C\x0C\x0D\x0C\x3C\x0C\x0C\x4C\xD2\xA2\x0C\x06\x52\x0C\x69\x40\x21\x7E\x72\x43\x01"
+ "\x20\x80\x48\x76\xC0\xCF\x2E\x46\x01\x26\x46\x86\x38\x36\xBB\x74\x06\x56\xC3\x20\x06\x71\x6E\x06\xDB"
+ "\x5C\x4B\x06\x4D\xA0\x14\x27\x23\x10\x90\x6A\x1E\x40\x00\x91\xEC\x80\x7F\xFF\x19\x0A\x41\x41\xC0\xA0"
+ "\x1D\xC0\xC0\xA8\x03\xC4\xBC\x0C\x0C\x69\x26\x0C\x79\x40\x11\x60\x98\x30\x30\x93\x6A\x1E\x40\x00\x91"
+ "\xE4\x80\x9F\x9D\x8C\x02\x0C\xFF\x18\xF2\x59\x4D\xBD\x81\xBC\xDD\x60\xCC\x69\x19\xC9\x20\xC6\xCD\x60"
+ "\xE7\xA2\xCC\x20\x0B\x14\x60\x27\xD5\x01\x00\x01\x44\x92\x03\xFE\xFC\x65\x08\x04\x26\x3C\x7E\x26\xAB"
+ "\x54\x20\x0F\x94\x01\x6E\x32\x30\x9B\x86\x33\xB0\x70\x32\xF0\xD4\xDA\x31\x80\x04\x79\x80\xB1\x40\x52"
+ "\x28\x00\x04\x10\x13\x69\x59\x86\xA1\x9E\x45\x57\x0F\xC8\xB8\x0C\xCB\x8C\xC0\x40\xBF\xCC\xC0\x6D\xED"
+ "\xCD\xA0\xC0\xC7\x00\x0A\x16\x3E\x20\x66\x23\xC5\x4C\x80\x00\x22\xDA\x01\x5F\x5B\x18\x41\xD9\x4D\x9E"
+ "\xC5\xB1\x10\x48\x9D\x40\x92\xB9\xC0\xC0\x6E\x16\xCB\xC0\xC6\xC4\x20\xB1\x26\x84\x21\x1A\x28\xC0\x05"
+ "\x0C\x05\xA2\xCD\x05\x08\x20\x94\xAC\xF3\x63\x12\xA3\x22\x0B\x13\x83\xC2\x8F\x9F\x0C\x4C\x40\x09\x07"
+ "\x60\x90\x33\x02\xE3\x5C\x1E\x18\xEC\xF2\x20\xCB\x99\x64\x45\x81\x81\xFC\x15\xE2\x73\x38\xF8\xC0\xC0"
+ "\xC0\xFB\x86\x81\xCB\x54\x8F\xC1\xE4\xD7\xA5\xE2\x6B\xA9\x0C\x9E\xCC\xFF\x19\xDE\x5C\x4B\x64\xBC\xF8"
+ "\xF7\x1F\xC3\xFF\x9F\xBF\x19\x2E\xFE\xFB\xCB\xF0\xFE\xDB\x6F\x86\xFB\x8E\xEB\x19\xEE\x01\x35\xFC\x07"
+ "\x01\x98\x6E\x80\x00\x62\xFC\x37\x9B\x61\x03\x30\xF3\xF8\x33\xFC\x05\xF2\x40\xF8\x1F\x10\xFD\x01\xD2"
+ "\x42\x9C\xC0\xC0\xE4\x61\xF8\xCF\xCE\xCB\xC0\x28\x0A\xCC\x65\x40\x2D\x4C\x06\xB1\x40\x07\xAC\x86\x58"
+ "\x8A\x02\x04\x80\x7A\x53\x19\xBE\xEC\x9A\x0C\x56\xF7\xE3\xC1\x75\x86\x3F\x5F\x3E\x33\xFC\xFE\xF2\x85"
+ "\xE1\xFB\xC3\xEF\x0C\xFF\x81\xE6\x02\x1D\xC3\xF0\x1F\x64\x36\x10\xFF\xF8\xCD\x70\xD4\x6C\x03\x83\x07"
+ "\x50\xE3\x77\x80\x00\x62\xF9\xF3\x8F\xE1\x13\x2B\x28\xF7\xAA\x01\xE3\xD6\x30\x0B\x58\xA4\x18\x31\x40"
+ "\xC2\xEF\x36\xD4\xF0\xB7\x40\xFC\x1E\xCA\xDE\x00\xC4\xEF\xB0\x04\x24\x50\x8C\x79\x05\x03\x8F\xA7\x2E"
+ "\xA8\x38\x00\xE6\x47\x33\x20\xCD\x01\xC4\x32\x70\x15\x7F\xAF\x9C\x61\x78\xB9\x75\x2D\xC3\xEB\xD3\x8F"
+ "\x18\xDE\x7E\x07\x1B\x28\x0E\xC4\xCF\x01\x02\x08\x64\x35\xE7\xD3\x4E\x86\x69\x52\x3C\x0C\x09\x0C\x7A"
+ "\xB6\x0C\x0C\x36\x16\xC0\xE4\x7E\x84\x81\x6A\xE0\x37\xD0\x3B\xEF\x98\x18\xDE\xEF\xBE\xCE\xF0\x64\xEB"
+ "\x1B\x86\xBB\x9F\x18\xF6\x04\xEE\x62\x68\x05\xCA\x3C\x05\xE2\x27\x00\x01\xC4\x08\x2D\x3C\x78\x4F\x96"
+ "\x30\x64\x9A\xC8\x30\xB4\x31\x69\x00\x43\xC2\x41\x9D\x81\xE1\xD7\x5D\xCA\x2D\xFF\x02\x34\xFA\x33\x0B"
+ "\xC3\xB3\xD5\x67\x18\xDE\x5E\xF8\xCD\x70\xFC\x05\xC3\xAC\xF4\x23\x0C\xCB\x80\x32\xAF\x80\xF8\x05\x10"
+ "\x7F\x02\x08\x20\x70\x05\x02\x4D\xB5\x3C\x87\x72\x19\xA2\x4C\x65\x19\xBA\x59\x65\xF8\x78\x98\x1D\xB5"
+ "\x80\x85\xFE\x67\xF2\x7D\xFD\x09\x98\x1B\xBF\xFC\x66\x78\xBE\xFD\x1A\xC3\x9B\x8B\x7F\x18\x76\x3D\x66"
+ "\xE8\x2F\x39\xC1\xB0\x1E\x6A\x31\xC8\x01\x5F\x80\x76\xFF\x05\x08\x20\x46\x58\x82\x84\x3A\x82\x73\x41"
+ "\x24\x83\x7D\xB0\x0E\xC3\x4A\x56\x11\x66\x1E\x76\x0F\x7D\x60\xF8\x7C\x22\xCD\xF2\x6F\x6C\x10\x0C\x4C"
+ "\x69\xF7\x97\x5E\x65\xF8\xF8\x9C\xE1\xEB\x84\x4B\x0C\x65\x0B\x6F\x01\xF3\x2B\xC2\xF2\x6F\x40\x7B\xFF"
+ "\x81\x94\x03\x04\x10\x23\x52\x8E\x80\x39\x82\x7D\x49\x04\x83\xBD\x8B\x0A\xC3\x44\x2E\x4E\x06\x35\x5E"
+ "\x57\x61\x06\x06\x41\x2E\x22\x2B\x0A\xA0\xF6\xF7\x5C\x0C\x7F\x5F\x7F\x66\x78\xB4\xEB\x09\xB2\xE5\x67"
+ "\x41\x09\x0E\x88\xDF\x40\xF3\x30\xD8\x72\x90\xDD\x00\x01\x84\xE2\x00\xA8\x23\x40\xE9\x82\x3D\xD1\x84"
+ "\x41\xA1\xD5\x85\x61\x03\x37\x2F\x83\x3A\x9F\xBF\x38\xD1\x01\x70\xED\x25\x33\x43\xF1\xB7\x37\x38\xE5"
+ "\xAF\x33\xFC\x0A\x7C\xE8\x0B\xCE\x4E\x60\x00\x10\x40\x18\x0E\x40\x72\x04\xEB\xDD\x22\x86\x29\xA2\x32"
+ "\x0C\xA9\xBC\xF6\x82\x44\x3B\xC0\xF3\xE1\x57\x86\x08\xA3\xC9\x0C\x4A\xDC\x2A\xC0\x52\x0C\x51\x3B\x03"
+ "\x9B\x1F\x0C\x6F\x7F\xBD\x61\x88\x3E\x14\xFE\xE1\x5B\x24\x03\xDC\x40\x80\x00\xC2\xDA\x88\x80\x96\x54"
+ "\xBF\x5E\x55\x32\x5A\xB0\x0B\x80\xAA\xC1\x9F\xC4\x37\xD5\xBE\xFF\x63\x30\x96\xB7\x62\x10\x03\x42\x74"
+ "\xF0\x0A\x08\xBF\x7D\x07\x95\x5A\x08\x00\x10\x40\x78\x5B\x31\xC0\x4C\xA4\x0B\xAC\xE9\xC0\x09\x0A\xB5"
+ "\x62\x60\x82\xB4\x7F\xD8\xFF\x61\x6A\xFA\xF5\x8F\xE1\x30\x10\xE2\xAE\xD3\x51\xB9\x00\x01\x84\xD3\x01"
+ "\x2F\xCB\x19\x1D\x41\x05\x04\x13\x37\x92\x03\xFE\x03\x83\xF4\x03\x50\xF4\x27\xD4\x62\x0E\x20\xCD\x0B"
+ "\xC4\xCC\x48\xD1\xF8\x8B\x01\xEC\x80\xC7\x40\x88\x0E\x64\x41\x4D\x86\x1F\xA8\x62\x00\x01\x84\xD3\x01"
+ "\xC0\x4C\xE2\xC8\xC4\x01\x4D\xAF\xBF\xA0\xF8\x3D\xD0\xA2\xBF\x7F\x18\x3E\x01\xD3\xF3\x3B\x60\x86\x02"
+ "\x95\xF1\x02\x12\xC0\x4C\xA2\x0A\xAD\x88\x99\x21\x3E\x3C\x05\x84\xF7\xFE\xDF\x43\x31\x4F\x88\x51\x88"
+ "\xE1\x33\x10\xA2\x87\x00\x40\x00\xB1\xE0\x69\x7A\x19\xB0\xB0\x43\x33\x0D\xA8\x02\xFC\x08\x74\x03\x90"
+ "\x7E\x0D\xB4\xFC\x3B\x50\xEC\xDC\x4B\x86\x65\xC0\x5A\xF2\x9F\xE6\x0F\x86\x80\xA2\x1F\x0C\x3C\x77\x81"
+ "\x4D\x33\x66\x60\x74\x01\x0B\x3C\x86\xCF\x7F\x1E\x00\xAB\x41\x68\xA8\x00\x03\x8D\x91\x8D\x91\xE1\x23"
+ "\xD3\x47\x06\x10\x04\x3B\xA0\x81\x61\x3F\xAC\x2E\x07\x08\x20\xAC\xB9\x00\x04\x9E\x15\x31\x3E\x14\x96"
+ "\x60\x90\x63\x07\x35\x2F\xBE\x00\x13\x10\xB0\x4E\xFA\x06\x74\xC0\x93\x4F\x0C\x27\x3A\x4F\x33\x4C\xDB"
+ "\x72\x8F\xE1\x0E\x50\xE6\x73\x92\x26\x83\xD4\xBC\x40\x86\x9D\x0C\x41\x48\x0D\x32\x39\x68\xCD\x8A\xCD"
+ "\x8B\x0F\x91\xD8\xEB\x18\x18\x00\x02\x08\xAB\x03\x1E\xE6\x33\x2A\xB2\x31\x33\xDC\x13\x03\x96\x3F\xDF"
+ "\x80\x41\xFF\x1E\x18\x72\x1F\x7F\x30\xDC\x5B\x7E\x9D\x61\x66\xFB\x49\x86\xE3\xD0\xEA\x11\x54\x2D\x42"
+ "\xCA\xEA\x3C\x86\xD9\x0C\xD2\x0C\xE1\x0C\xA1\xD0\x4A\x90\x18\xB0\x03\x54\x68\x30\x2C\x00\x08\x20\xAC"
+ "\x51\x00\x0C\x35\x43\x50\x41\xF9\x12\x14\x65\xBF\x18\xBE\xEE\xBA\xCB\x30\x2B\x63\x37\xC3\x26\x48\x44"
+ "\x80\xEB\x67\x50\x83\xE0\x1B\xDC\x9F\x93\x18\x62\x18\x32\x19\xFE\x30\x2C\x02\xB6\x88\x82\x89\x68\x9A"
+ "\xEE\x06\x97\x48\x0B\x18\xA6\x30\x24\x02\x04\x10\xF6\x34\xF0\x0F\xE8\x00\x60\x4E\xBB\xFC\x8A\x61\x7E"
+ "\xF9\x3E\x86\x8D\x97\x5E\x31\x3C\x83\xFA\xF8\x1D\x34\x45\xFC\x86\xB5\x6A\xA0\x5D\x81\x3F\x0C\xD3\x19"
+ "\x62\x19\x52\x80\x0E\x5A\xCA\x10\x07\x6C\xDE\xE0\x76\xC4\x3E\x70\x5B\xF6\x02\xB0\xD1\x01\x6A\xDB\x31"
+ "\x00\x04\x10\xAE\x92\x10\x14\xF3\xA2\xA0\xC4\x0B\x4D\xFF\xB0\xE0\xFE\x05\xAB\x44\x90\xD4\xA2\x6A\x8E"
+ "\x05\xFA\x4C\x98\x21\x1E\xDC\x44\x45\x77\xC4\x41\x70\x3B\x07\x64\xB9\x23\x50\x15\xB8\x59\x05\x10\x40"
+ "\xB8\x1C\xC0\x04\xD5\xCE\x0A\xF6\x1D\x30\x26\x40\x55\x27\xD6\xE8\xC2\xD6\x19\x8A\x66\x98\x0F\x74\x7A"
+ "\x02\x83\x33\x52\x1B\x19\xD4\x8E\xBD\x0B\xAE\x11\x1D\x81\xA1\x04\x6F\xD3\x01\x04\x10\xCE\x5C\x40\x2C"
+ "\xC0\xD9\x1B\x03\x39\x82\x1F\xE8\x08\x6B\x20\xFB\x0A\x10\x3F\xC2\xB4\x1C\x04\x00\x02\x88\x62\x07\xE0"
+ "\x75\x5C\x0C\xE3\x7C\x20\x95\x00\x6E\xBB\x03\x2D\xFF\xBF\xE4\x3F\x7A\x6B\x96\x01\x20\xC0\x00\xA5\xBB"
+ "\x6A\x3A\x4A\x3F\xC0\x7E\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 2232,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xAF\xC8\x37\x05\x8A\xE9\x00"
+ "\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61"
+ "\x67\x65\x52\x65\x61\x64\x79\x71\xC9\x65\x3C\x00\x00\x08\x4A\x49\x44\x41\x54\x78\xDA\x62\xFC\xFF\xFF"
+ "\x3F\xC3\x40\x02\x80\x00\x62\x62\x18\x60\x00\x10\x40\x2C\x20\x82\x91\x91\x91\x2A\x86\xD5\xB4\x6E\x56"
+ "\x64\x66\x60\x9D\xFF\xFD\xD7\xCF\xA3\x5D\x8D\xFE\xCD\x40\xA1\x5F\x40\xFC\x0F\x9F\x1E\x80\x00\xA2\x5A"
+ "\x08\x34\x76\xEE\x6C\xE4\xE6\xE2\xBE\xE7\xE3\xA5\x67\xCF\xC3\xC3\x5D\xE5\x1B\x5C\xE6\x04\x14\xE6\x04"
+ "\xF9\x0F\x9F\x3E\x80\x00\x62\xA1\xD8\xE2\xAE\x1D\x86\x40\x3B\xE6\x2B\xCA\x8B\xE8\xFB\x79\xE8\x32\xB0"
+ "\xB3\xB1\x00\x31\x33\xC3\xEB\x37\x1F\x26\x00\xA5\x9D\xA0\xA1\xF0\x1B\x97\x7E\x80\x00\x62\x20\x37\x11"
+ "\xB6\xF7\xEF\x15\x68\xED\xDD\xDD\xD8\x33\xE5\xC0\xFF\xBB\xF7\xDF\xFF\xFF\xFD\xFB\xFF\xFF\xB7\x6F\x7F"
+ "\xFE\x7F\xF5\xEA\xDB\x7F\x10\x98\x3E\xFF\xE4\xFF\xC8\xC4\x09\xDD\x40\xA5\x42\xF8\x42\x1A\x20\x80\x18"
+ "\x41\x0E\xE0\x0E\x3F\x7C\xE0\xFF\xDF\xBF\x4C\xFF\xFF\xFD\x67\x04\xBA\x08\xE2\x28\x10\x82\x3A\x0E\x28"
+ "\xCE\xF0\xEF\xE7\x9B\xB6\xBF\x7B\xA2\xF6\x82\x7C\xD3\xDE\xB7\xCB\xE1\x3F\x03\xD3\x7C\x0D\x35\x09\x79"
+ "\x5F\x0F\x6D\x86\x5F\x3F\xFF\x31\xFC\xFE\xFD\x97\xE1\xEF\xDF\xFF\x40\xFC\x97\x81\x89\x89\x91\x81\x9D"
+ "\x83\x95\xA1\xA9\x6B\xE7\x97\x43\xFB\x96\xF9\x9C\x3C\xB2\xF4\x34\x50\xDF\x77\x06\xB0\xA9\xA8\x00\x20"
+ "\x80\xC0\x51\x60\xAF\x23\x64\xBF\xA9\x56\x9B\xE1\x03\x90\xFD\xE7\x2F\x03\xC3\x0F\x20\xFE\xF9\x07\x18"
+ "\x76\x50\xF6\xCE\x93\x9F\x18\x7A\xE6\x5C\xD8\xC6\xE2\xB9\xA4\xB1\xD8\x49\x58\x54\x50\x90\x37\xCB\xDD"
+ "\x49\x93\x41\x4E\x86\x9F\xE1\xC7\x8F\x7F\x0C\xFF\xFE\xA1\x9A\xFB\xE7\xCF\x3F\x06\x2E\x26\x26\x06\x17"
+ "\x07\x0D\x9E\xD7\x6F\x3C\xFB\x80\x0E\xF0\x81\x46\x03\x46\x54\x00\x04\x10\x0B\x24\x1A\x18\x18\x3E\x01"
+ "\xE9\x27\xDF\x80\x9A\xFF\x41\xF0\xEF\x3F\x10\x1A\xE4\x08\x43\x3D\x3E\x86\xD2\x28\x45\x86\x6F\x77\xFE"
+ "\xD6\x5B\x5B\x2B\x30\xD8\x98\x2B\x82\xF5\xFC\xF9\x83\x3B\x8A\xDE\xBF\xFF\xCA\xE0\xE6\xA8\xC4\x70\xEA"
+ "\xDC\x63\x23\x1D\x9F\x19\xDD\x57\x6E\xDE\xED\x61\xB8\xDD\x7D\x05\x28\xF5\x17\x39\x24\x00\x02\x88\x85"
+ "\x01\xE6\x02\x1C\xE0\x1F\xD0\xCD\xCF\xCE\x5C\x67\x90\xF8\xF2\x89\xC1\x27\xC1\x9C\x41\x5C\x94\x0B\xAC"
+ "\xFC\xDF\x3F\xC2\xE9\xE4\xCD\x9B\x1F\x0C\x31\xA1\x46\x0C\x37\xEF\xBF\x8B\xBE\xF9\xF2\xDF\x47\xA0\x51"
+ "\x35\x40\xE1\xCF\xA0\x40\x82\xA9\x01\x08\x20\xB0\x03\x40\x21\xF8\x17\x8B\x1B\x3E\x3D\xFF\xCC\xF0\xE8"
+ "\xD4\x25\x06\x4B\x23\x79\x06\x13\x43\x4D\x92\x13\xEA\xAF\x5F\x7F\x18\xA4\x24\x78\x19\xFC\xDD\xD5\x19"
+ "\x3E\x7E\x78\xA5\xB8\xF9\x34\x83\x20\x34\x2D\xC0\x1D\x00\x10\x40\x2C\xB0\x44\x86\xEC\x80\x3F\xC0\x8C"
+ "\x73\xF7\xC8\x15\x06\xCE\x7F\xBF\x18\x12\xC2\xCD\x19\x78\x79\x48\xCB\xAD\x57\x1F\x7E\x61\xD8\x72\xFA"
+ "\x0D\xD8\x67\x8C\xCC\x8C\x0C\x6C\x2C\xCC\x0C\x8F\x7E\x4B\x78\xB2\x5A\xCC\x6E\xFA\xFD\x8F\xF3\x19\x03"
+ "\x03\xCB\x6F\x88\xAF\x7F\x5F\x04\x08\x20\x48\x08\x40\xE3\x1D\xEE\xF2\xAF\x7F\x18\x7E\x7D\xFC\xC8\x90"
+ "\x10\x6F\x4D\xB2\xAF\xAF\x3C\xFC\xCA\x10\xD0\x72\x91\xC1\x40\x43\x84\x41\x45\x9A\x1F\x92\x4E\x7E\xFE"
+ "\x67\xD0\xB7\xD0\x61\x50\xD6\xF9\x19\x0D\xF4\xE8\x07\x50\x36\xDD\x7B\xFC\x11\xEF\xD7\x17\xCF\x17\x03"
+ "\x04\x10\xD8\x01\x7F\xFF\xA3\x86\x00\x97\x20\x0B\x03\x9B\x90\x10\xC3\xE9\xF3\x4F\x18\x4C\x0D\x65\x88"
+ "\xB6\xFC\xE3\xD7\xDF\x0C\xB9\xD3\x6F\x30\xD8\x1A\x49\x31\x64\x45\x6A\x33\xDC\x7C\x09\x49\xC4\x20\xC0"
+ "\xC6\xCA\xC0\xF0\xF2\xD5\x2F\x86\x97\xEF\xBF\xFD\xFC\xFE\xF9\xC7\x8B\xAF\xDF\xEE\xEA\x32\x7C\xB9\x71"
+ "\x03\x20\x80\x70\xA6\x81\x9D\x0F\xD8\x19\xBA\x36\xDD\x63\x90\x97\xFD\x00\x4E\x74\xFF\xFF\x42\xCA\x87"
+ "\xFF\xC0\xE0\x82\x44\xD9\x7F\x30\x0D\x13\x07\x65\xC5\x47\x2F\xBF\x31\xE8\x6B\x88\x32\x64\x47\x6B\x33"
+ "\xAC\x3D\xCF\xC0\xF0\xEE\x2B\xC4\x6C\x70\x99\x0F\x2C\x8A\x58\x98\xD9\x18\x8E\x9D\x7A\x26\xFE\xE4\xE0"
+ "\xA5\x7F\x0C\xDC\xBF\x99\x18\xEE\x76\x1F\x05\x08\x20\x68\x14\xFC\x03\xE7\x7F\x18\x78\x0E\x8C\xBE\x8D"
+ "\x87\x9E\x32\x2C\x2D\xD5\x67\xE0\x61\xFD\xCF\xC0\xCB\xCB\x0E\x96\xFF\x03\xCC\x3D\xBF\x41\xD1\x05\xB4"
+ "\x14\x14\xB4\xBF\x41\x05\x0F\x28\xCB\x82\xE4\xFE\xFC\x67\xE0\x64\x67\x65\x10\x10\xE6\x60\xD8\x78\x11"
+ "\x98\xD4\x7F\x20\x2C\x07\xD5\x75\xA0\x10\xB8\x75\xE2\x21\xC3\xF3\x63\x37\xFE\x31\xB0\xFC\x13\x60\xF8"
+ "\xF5\xE6\x18\x28\xB6\x01\x02\x08\x9E\x06\x90\x43\xE0\xE8\xF9\x57\x0C\xBA\x8A\xBC\x0C\x3E\x66\xFC\x0C"
+ "\xF7\x1E\x7C\x62\x10\x10\x62\x65\xE0\xE6\x63\x01\xE7\x9F\x4F\xC0\xBC\xF4\x19\x58\x5E\x7C\xFA\x0E\xC1"
+ "\x5F\x81\xEC\xCF\x40\x1A\x94\xC7\x3E\xBF\x07\xE2\xA7\x10\xCB\x7F\x43\x3D\xF4\xF7\xC7\x6F\x86\x0F\x4F"
+ "\xDF\x33\x5C\x3D\x72\x8B\xE1\xDD\x2B\xA0\x8E\x2F\xBF\x5E\x32\x08\xFC\x91\x64\xF8\x72\xFF\x28\x28\x47"
+ "\x00\x04\x10\xD4\x01\x10\x9F\xC0\x4A\xEC\xB5\xBB\x1F\x31\x34\x46\x29\x31\xFC\x00\x55\x67\xA2\x7C\x0C"
+ "\xF7\x1E\xBE\x66\x50\xD1\x12\x05\xA5\x25\x86\x5F\x40\x8B\x80\x66\x32\x7C\x00\x96\x5C\x4F\x5F\xFF\x67"
+ "\x78\xFF\xF9\x1F\xC3\xE3\xE7\x3F\x81\xFC\x7F\x0C\x1F\x3F\xFF\x65\xF8\xFC\xE5\x0F\xC3\x8F\x6F\xBF\x18"
+ "\x7E\xFF\xF8\xC9\xF0\xE7\xF3\x57\x86\x77\x4F\xDF\x31\xBC\x7B\xFF\x8D\xE1\xEF\xF7\xDF\x1F\x81\x1A\x5F"
+ "\x33\x30\xFF\x67\x61\x60\xFA\xCF\xCE\xF0\xF1\x24\xA8\x78\xFE\x06\x10\x40\xD0\x44\x08\x0C\x42\x68\x08"
+ "\xDC\x7E\xF4\x87\xE1\xF9\xEB\x6F\x0C\x3E\x16\x42\x0C\xC0\x22\x9E\xE1\x1F\x1B\x50\x90\x8F\x9F\xE1\xEA"
+ "\xBD\xCF\x0C\x42\xE2\xBC\x0C\x77\x80\x3E\x7C\xFC\xF2\x1F\xD0\xC2\xBF\x60\x0C\xB2\xF4\x03\x10\x7F\xFC"
+ "\xF8\x87\xE1\x1D\x90\xFF\xF5\x0B\xD0\xE2\xEF\xBF\x18\xFE\x00\x83\xE6\xCD\xF3\xB7\x0C\x7F\x81\xD9\xEB"
+ "\x2F\x13\x07\x30\x48\x7E\x41\x4A\x40\x76\x06\x6E\x86\x3F\xDF\xEE\x30\xBC\x3B\xF0\x08\xE4\x00\x80\x00"
+ "\x42\x84\x00\xD0\x01\xCC\x40\xF6\xF6\xC3\x4F\x19\x7C\xCC\x45\x19\xB8\x80\x16\xBF\x07\xD5\x09\xA0\x02"
+ "\x1C\xC8\xB9\xF5\xE4\x27\x03\xF3\x7B\x60\x1A\xF8\xC3\xC8\xF0\xF3\xF7\x7F\x70\x48\x80\xD2\x02\x28\x1D"
+ "\xFC\x06\xB2\x7F\xFD\x81\xB0\xC1\xC5\x3A\x30\xA4\x3F\xBD\xFB\xC2\xC0\xC4\xC6\xC9\xC0\xC8\xCE\x08\x89"
+ "\x2B\x18\x60\xFE\xCB\xC9\xF0\xEB\xED\x21\x06\x88\xD1\x3F\x00\x02\x88\x09\x96\x0B\x60\xE5\xC0\xA1\xB3"
+ "\x2F\x19\x7C\xCD\xC5\xC0\xB2\x9F\x81\x05\xD2\xA3\x77\xC0\xA0\xFE\x00\x0A\x09\x5E\x86\x97\xAF\xBF\x02"
+ "\x2D\x86\x58\x08\x4A\x94\xBF\x40\x09\xF1\x37\x24\x31\xFE\xF9\xC7\xC8\xF0\xED\xFB\x5F\x86\xA7\x4F\x3F"
+ "\x31\x7C\x01\xC6\x15\x0B\x0F\x2F\x03\x23\x0B\x96\x02\x8C\xE5\x1F\x0F\xC3\x87\xA3\xDB\x40\xBE\x07\x25"
+ "\x42\x80\x00\x82\x87\x00\xC8\x01\x8F\x1E\xFE\x61\xF8\xF6\xF5\x17\x83\xB7\xA5\x30\xC3\x93\x2F\x0C\x60"
+ "\x0C\xE4\x82\x53\xFC\x7F\xA0\x53\xFF\x30\x32\x33\xBC\xFB\xF8\x83\x81\x91\x89\x0D\xEC\xE3\x3F\x60\x5F"
+ "\x43\x1C\xF3\x1C\xE8\xB8\x97\xAF\x7F\x32\x30\x72\x72\x31\x30\xFF\xFB\xCB\xF0\xFF\xC7\x0F\xCC\x3A\x86"
+ "\xFD\x3F\x37\xB0\xF4\xFB\xC2\xF0\x7A\xDD\x75\x20\xEF\x2B\xC8\x01\x00\x01\x04\x4F\x03\x20\xBC\x7C\xFB"
+ "\x03\x86\x00\x0B\x31\x06\xA0\x39\x40\x5F\x00\x13\x20\x23\x24\x0B\x81\xF2\x30\x33\x30\x7E\xFE\xF3\xB1"
+ "\x33\x3C\x7D\xF2\x99\x81\x93\x8B\x99\x81\x0D\x98\x29\xD9\x18\xFF\x32\xB0\xFD\xFF\xCD\xF0\xF5\x1D\x50"
+ "\x0C\x28\x2F\x21\xC2\xC1\xF0\xFF\xE7\x4F\x20\xFE\x01\x2C\x23\xBE\x03\x43\xF6\x27\xB8\xAC\xF8\xC6\xF9"
+ "\x1B\x98\xFE\xFE\xB3\xFE\xF8\xF7\x87\x0D\x96\xFD\xA0\x75\xC2\x5F\x80\x00\x82\x84\x00\x34\x3F\x1F\x38"
+ "\xFD\x9C\x61\x19\x30\xEF\x6B\xF2\x02\x05\x79\x11\x0E\x07\xB6\x31\xC0\x0D\x8E\x3F\x40\xAF\xFE\xD1\x64"
+ "\x05\xB2\x7F\x42\xD8\xC0\xA0\x01\xD5\xFD\xBF\x7F\xB3\x41\xD9\x7F\x20\xD1\xF3\x87\x05\x88\xB9\x80\x98"
+ "\x1D\x2A\xC6\x09\xA4\x79\x79\x43\xDB\x1F\x32\xFC\x78\xF4\xF4\x02\x28\xEE\xA1\x8E\xF8\x0F\x10\x40\xF0"
+ "\x92\x70\xCF\xA9\x4F\xC0\x44\xF8\x9F\xC1\xC3\x88\x0F\xB3\xE5\x0A\x0E\x01\x46\x60\x54\x31\x82\x5B\x3B"
+ "\x4C\x40\x01\x26\x26\x60\x45\xC3\x08\xA1\x51\xE5\x40\x98\x19\x2A\xFF\x1F\xCE\xBE\xFB\xFC\x17\xC3\x8F"
+ "\xB7\x40\xD7\xBD\x59\x7F\x18\x1A\xFF\xE0\xC6\x09\x40\x00\x41\x13\xE1\x7F\x86\xC3\x67\x9E\x33\x24\xB9"
+ "\x61\x2F\xF7\x21\xD1\x00\xB3\x98\x19\x6C\x21\x88\xCF\xCC\xCC\x04\x6E\xD2\x23\x2C\x65\x02\x8B\x21\x1C"
+ "\xC2\x08\x96\x07\xA9\x3F\x7C\x15\x18\xE5\x7F\xBF\xDE\x63\xF8\x71\xF7\x1D\xB2\x03\x00\x02\x88\x09\x56"
+ "\x12\x9E\xBF\xF4\x82\x21\xD1\x5D\x16\x67\x45\x03\x33\x08\xD9\x70\x88\x83\x98\xC0\x21\x81\x29\x07\x53"
+ "\x0F\x92\x67\x66\x38\x78\x19\x98\xA2\xBF\xDF\xDB\x0D\x8D\xFB\x1F\xB0\xFE\x02\x40\x00\x81\xA3\xE0\xCE"
+ "\xBD\xB7\x0C\xCA\x72\xBC\x0C\x1A\x52\xAC\xB8\x3B\x10\x4C\xD0\x22\x1B\xD8\x44\xFA\xF9\x0B\x18\x9C\xC0"
+ "\x92\xEE\x27\x30\xB1\x81\xE8\x1F\x3F\x7E\x31\x7C\x07\xA6\xFA\x1F\xC0\x04\xF8\xF3\x07\x48\xEE\x07\xB0"
+ "\xAC\xF8\xC5\xF0\x0F\x54\x08\x01\x35\x7D\xFA\xF6\x8F\xE1\xCD\x63\x60\xAA\xFE\x76\xF5\x1C\xD0\xA8\x2F"
+ "\xD0\xF8\x07\x03\x80\x00\x62\x81\x85\xF1\x7B\x60\x21\xEF\x5C\x7E\x16\xDC\x5A\x03\x37\x32\xFF\x43\x0A"
+ "\x15\x10\xF1\x0F\x5A\xF3\xFD\x03\x66\x2F\x90\xA1\x7F\x80\xA9\xF2\x1F\x30\xD5\xFE\x03\xD2\x7F\xA0\xF4"
+ "\x63\x60\xD6\xF9\xFC\xFA\x37\x24\x41\x81\x5C\xFA\x1F\x9A\xB8\xFE\x43\xF1\xBF\x9F\xAF\x18\xDE\x6F\xBE"
+ "\x06\xCD\x7E\xF0\xC6\x29\x40\x00\x81\x9B\xE5\xC0\xE0\x05\xA5\x3C\x50\xF8\xF3\xD3\xB0\x1B\x08\x0A\x72"
+ "\x50\xDB\xF7\x29\x94\x06\x17\x12\x00\x01\x04\x73\x00\x2B\xB4\x1B\xC5\x4A\x43\x07\xFC\x87\xFA\x1C\xA5"
+ "\x4D\x08\x10\x40\x8C\x03\xDD\x3D\x07\x08\x30\x00\xBB\x4C\x41\x1B\x78\xB7\x50\xC8\x00\x00\x00\x00\x49"
+ "\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1331,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xAF\xC8\x37\x05\x8A\xE9\x00"
+ "\x00\x04\xEA\x49\x44\x41\x54\x78\x9C\xB5\x57\x5F\x68\x53\x57\x18\xFF\x9D\x73\x4F\x4D\xD6\xA4\xB1\x74"
+ "\x6D\xAC\x26\xD0\x12\x42\x92\x75\xA1\x98\x40\x67\x0B\xBA\xD9\x22\x8C\xE9\x50\x86\xB6\x0A\x85\xF9\x3C"
+ "\xB6\x37\xDF\xA4\x3E\x0E\x87\x43\xFA\xB0\x27\x1D\x7B\x90\xBD\xA9\x43\x19\x9B\x58\x11\x19\xB4\xF4\xA1"
+ "\x4E\x47\x1B\xD6\x4E\xB0\xC6\x06\x63\xDB\xD0\x76\x9A\xDE\x24\x4D\x72\xFE\xEC\xA1\xBD\x77\x69\xCC\x6D"
+ "\x52\xAA\x1F\x7C\xDC\x7B\xCE\x3D\xF7\xFB\x7E\xDF\x39\xDF\xBF\x43\x50\x85\x06\x06\x06\x2E\x9E\x3A\x75"
+ "\xEA\x2B\x21\x84\xE5\x1A\xA5\x14\xA4\x94\x90\x52\x42\x29\x05\xC6\x18\x26\x27\x27\x67\x2F\x5D\xBA\x74"
+ "\x04\xC0\xBF\x5B\xC9\x67\xD5\x00\xEC\xDD\xBB\xD7\xD5\xDF\xDF\xBF\xBB\xDA\x3A\x00\xE0\x9C\x83\x73\x0E"
+ "\xBB\xDD\x8E\x4C\x26\xD3\x0E\xC0\xBD\x63\x00\x00\x64\x2D\x4A\x4B\xB9\x58\x2C\x82\x73\x2E\x00\x90\x6A"
+ "\xC2\xAB\x02\x20\xC4\x5A\x46\x25\xE5\x9C\x73\x68\x9A\x56\x4D\x6C\xED\x00\x28\xA5\xDB\x52\xCE\x39\x07"
+ "\xA5\x74\x4B\xE0\xDB\x02\x50\xC9\x9A\xAD\x94\x73\xCE\x6B\x56\x5E\x13\x80\xF2\x1D\xA8\xA6\xFC\xAD\x03"
+ "\x60\xEC\xFF\x25\xB5\x28\x37\x00\xBC\xB5\x23\x10\x42\x14\x37\x9E\x35\x03\x00\x00\xA5\x94\x02\x90\xAB"
+ "\x26\x7F\x4B\x77\x3D\x7F\xFE\xFC\x47\x5E\xAF\xF7\x44\x57\x57\x57\x90\x52\x0A\x4D\xD3\x40\x29\x35\x9D"
+ "\xAC\x12\x03\xEB\xBB\xB6\xB8\xB8\xC8\x57\x57\x57\x67\xFB\xFA\xFA\xF4\xC7\x8F\x1F\x2F\x5B\xE9\xB0\xDC"
+ "\xA7\xBE\xBE\xBE\xDE\xA1\xA1\xA1\x3B\xD7\xAF\x5F\xB7\x77\x76\x76\x42\x08\x01\x21\x84\x99\xF1\x0C\x36"
+ "\xE6\x4A\x9F\x00\x30\x37\x37\x87\x68\x34\x8A\x8E\x8E\x8E\x17\x03\x03\x03\x87\xD3\xE9\xF4\x6C\x25\x3D"
+ "\x96\x47\x70\xF0\xE0\xC1\x2F\x0F\x1D\x3A\x64\xF7\x78\x3C\x28\x16\x8B\xEB\x68\x4B\xCE\xD5\x00\xB4\x91"
+ "\x74\xDE\xE0\x03\x07\x0E\xA0\xA9\xA9\x09\x4E\xA7\xD3\x1B\x0E\x87\xCF\x8C\x8F\x8F\x7F\x5B\x33\x80\x48"
+ "\x24\xE2\xF7\xFB\xFD\x3D\x8C\x31\x04\x02\x81\x8A\x00\xA5\x94\x28\x14\x0A\x66\xE6\x33\xB8\x74\x9C\xCF"
+ "\xE7\xC1\x39\x87\xDF\xEF\x3F\x32\x3E\x3E\xFE\x13\x80\x85\x72\x39\xA6\x49\xFD\xFD\xFD\xAD\xAD\xEE\xD6"
+ "\x93\xFB\x23\xFB\x4F\x84\xC3\xE1\x9E\xD0\x07\x21\xA7\xCB\xE5\xB2\x54\x6E\x14\x20\xA5\x94\xC9\xA5\xE3"
+ "\xD2\x77\x5D\xD7\x31\x33\x33\x93\x1A\x1D\x1D\xFD\xE3\xEE\xDD\xBB\xBF\x3C\x7C\xF8\xF0\x77\x00\x19\x53"
+ "\xE0\xBE\x7D\xFB\x02\x37\x6E\xDC\x98\x7B\xB5\xF2\x4A\x15\x8A\x05\xF5\x2E\x29\x95\x4A\xA9\xA1\xA1\xA1"
+ "\x51\x00\x8D\x26\x80\xC1\xC1\xC1\x1F\x94\x52\xEA\x66\xFC\xA6\x3A\xFB\xE7\x59\x75\x6D\xE6\xDA\x3B\x05"
+ "\xB1\xB0\xB0\xA0\x42\xA1\xD0\x37\x00\x40\x01\x34\x1E\x3F\x7E\xFC\x24\x00\xE4\x8A\x39\xC4\xD2\x31\x80"
+ "\xAE\xD7\x78\xC3\xD1\xDE\x26\x2B\xA5\xB0\x67\xCF\x1E\x1C\x3D\x7A\xF4\x0C\x00\x3B\x09\x04\x02\x9F\xDD"
+ "\xBE\x7D\xFB\x4E\x30\x18\x84\x2C\x4A\xAC\x15\xD7\x60\xAF\xB3\x43\xC0\xBA\x01\xD9\x29\xD9\x6C\x36\xDC"
+ "\xBA\x75\x2B\x77\xFA\xF4\xE9\x6E\xE6\xF3\xF9\xA2\x4D\x4D\x4D\xD0\x75\x1D\x1A\xD5\xA0\x51\x0D\x79\x9E"
+ "\x87\x52\xEA\x9D\x01\x10\x42\xC0\xEB\xF5\xBE\xD7\xDA\xDA\x1A\x61\xED\xED\xED\x6D\x85\x42\x01\x6B\x6B"
+ "\x6B\xA0\x94\x82\x31\x66\x66\x3C\x23\xEE\x4B\xE3\xBF\x1A\xB0\x4A\x6B\xD5\x46\x54\x18\xE9\x9C\x10\x02"
+ "\xA7\xD3\x09\xB7\xDB\xED\x63\x76\xBB\xDD\x61\xC4\x6F\xA9\x70\x42\xC8\x1B\x69\xD7\xA8\x8C\x56\x85\xC6"
+ "\xF8\xBF\x3C\x1C\x8D\xB1\x41\x86\x81\x75\x75\x75\x0E\x06\x40\xE6\xF3\x79\xD3\x41\xAA\x59\x5A\xAD\xCA"
+ "\xD5\xF2\x1F\xA5\xD4\xD8\x09\xC2\x96\x97\x97\x5F\x1B\x19\x4D\x29\x05\x4A\x29\x1C\x0E\xC7\xB6\x6A\x7A"
+ "\x2D\x24\x84\x40\x26\xB3\x9E\x7B\x34\x4D\x83\xAE\xEB\xC8\x66\xB3\x19\x96\x48\x24\x66\xB3\xD9\xAC\x89"
+ "\x32\x9D\x4E\xE3\xEA\xD5\xAB\x66\x59\x2D\xDF\x99\xED\x10\x21\xC4\xEC\xA8\x5A\x5A\x5A\x70\xEC\xD8\x31"
+ "\xD3\xCF\x96\x96\x96\x90\x4A\xA5\xE6\x58\x3C\x1E\x9F\x78\xF9\xF2\xA5\x72\xBB\xDD\x84\x10\x82\x95\x95"
+ "\x15\x5C\xB9\x72\x65\xC7\x16\x13\x42\x36\x01\xF7\x78\x3C\xE8\xED\xED\x85\xCD\x66\x03\x00\x3C\x7F\xFE"
+ "\x7C\x75\x7E\x7E\x7E\x86\x25\x12\x89\xBF\x9E\x3C\x79\x32\xDD\xDC\xDC\xFC\x21\xE7\x1C\xF9\x7C\x7E\x93"
+ "\xA0\xE1\xE1\x61\x04\x83\xC1\x37\xE6\x4B\xA9\xBC\x1C\x0B\x21\x40\x29\x45\x22\x91\xC0\x85\x0B\x17\x4C"
+ "\xEF\xD7\x75\xDD\x74\xE4\x89\x89\x89\x49\x00\xFF\x30\x00\xD9\x91\x91\x91\x9F\xC3\xE1\xF0\x77\x0D\x0D"
+ "\x0D\x68\x6C\x6C\xC4\xB9\x73\xE7\xCC\xF6\x7A\x70\x70\x10\x2E\x97\xCB\xAC\xF3\xE5\x64\xD5\x15\x49\x29"
+ "\x11\x0C\x06\xB1\xB8\xB8\x08\x4A\x29\x6C\x36\x1B\x08\x21\x60\x8C\x21\x1E\x8F\x63\x6C\x6C\xEC\x57\x00"
+ "\x2B\x86\xA7\x35\x74\x74\x74\x7C\xDD\xDD\xDD\xFD\x45\x57\x57\x57\x38\x14\x0A\xD5\x03\x80\xCB\xE5\x42"
+ "\x34\x1A\xB5\xB4\x5C\x29\xB5\xA9\x1F\x28\x7D\x37\x7A\x85\xA7\x4F\x9F\xA2\xBE\xBE\x1E\xBA\xAE\x63\x6A"
+ "\x6A\x6A\xF5\xD1\xA3\x47\x7F\x8F\x8D\x8D\x8D\xCC\xCF\xCF\xFF\x08\x20\x59\xEE\xEA\x6E\x4D\xD3\x3A\xDB"
+ "\xDA\xDA\x22\x3D\x3D\x3D\x9F\x0F\x0F\x0F\x7F\xDC\xD2\xD2\x52\x93\xE5\xE5\x8D\x89\xD1\xC4\x24\x12\x09"
+ "\x5C\xBE\x7C\xF9\x41\x2C\x16\xBB\x9F\x4C\x26\x63\x00\xA6\x00\xBC\xC0\xC6\x8D\xAB\xFC\xD6\x91\x12\x42"
+ "\xDC\x7F\xF6\xEC\xD9\xF7\x3E\x9F\x2F\x6E\xA5\x1C\x58\x0F\x25\x83\x8D\x84\x55\x9E\xB8\xA4\x94\xF0\x78"
+ "\x3C\x90\x52\xC6\x92\xC9\xE4\x45\x00\xBF\x01\x48\xA0\xE4\xBA\x57\xB1\x23\x72\x38\x1C\xEE\x68\x34\xFA"
+ "\xE9\xF4\xF4\x34\x84\x10\x9B\x62\xB0\xD4\xD1\xA4\x94\xE6\x79\x5B\xCD\xED\xDA\xB5\x8B\x44\x22\x91\x4F"
+ "\xEE\xDD\xBB\xB7\x1B\xC0\xEB\x72\x5D\x56\xD9\xC6\x6E\xB3\xD9\x0E\x4B\x29\xDF\x07\x76\x5C\x16\x29\x63"
+ "\x6C\x2D\x97\xCB\x3D\x00\xF0\xAA\xFC\xE3\x7F\xC0\x42\x83\x1B\x33\x49\xBA\x6F\x00\x00\x00\x00\x49\x45"
+ "\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1647,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x0D\x00\x00\x0B\x0D\x01\xED\x07\xC0\x2C\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD3\x09\x09\x14\x14\x16\xE9\x33\x80\x72\x00\x00\x05\xFC\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x97\x5D\x6C\x1C\x57\x15\xC7\x7F\xF3\xB5\xBB\x63\xC7\x6B\xEF\x66\x69\x12\x3B\xA9\x93\xE2\x56"
+ "\x0E\x21\x91\xE3\x81\x08\x11\x12\x1A\x20\x54\x8D\x22\x22\xAA\x4A\x7D\x69\xA1\x1F\x58\x60\xC9\xAD\xFA"
+ "\x50\x55\x08\x24\xA4\x20\x40\x48\x3C\x14\x09\x1E\x4A\x57\x4E\x09\xA4\x42\xED\x43\x0B\x08\xF5\x21\x25"
+ "\x4A\x95\xB6\x29\x95\xEA\x49\x6D\xB7\x29\x5F\x8B\x92\xA6\xCE\xBA\xF1\xC7\xEE\xBA\xBB\x3B\xB3\x3B\x33"
+ "\xF7\xF2\xB0\xB3\xF6\x6E\xBD\x6B\xA7\x10\xC4\x95\xFE\x5A\xCD\x9E\x73\xE7\xFC\xCF\xB9\x67\xCE\x39\x17"
+ "\xFE\xCF\x4B\xF9\x38\xCA\xC3\xA3\x93\x3B\x40\x1E\x02\x31\x04\x0C\x21\x45\xC3\x3B\xE4\x14\x52\x4C\x21"
+ "\xBC\xB3\x16\x27\x33\x80\x48\xA7\xD3\xF2\x86\x10\x18\x1E\x9D\x7C\x00\xB8\x1F\x38\x08\x12\x10\xA0\x46"
+ "\x40\x8D\xD5\x14\x84\x0B\x81\xDB\xB8\xE5\x3C\xC2\x3F\x65\xC9\xF1\x13\x80\x97\x4E\xA7\xC5\x7F\x44\x60"
+ "\x78\x74\x72\x2F\x8A\xFA\x04\x52\x7C\x11\x55\x83\x48\x0F\x44\x92\x44\xA2\x26\xDB\xE2\x4B\x7C\x76\x6B"
+ "\x0E\x80\xA2\x0B\x67\x2E\xF5\xE3\xB8\x55\xA8\xCC\x81\xBB\x00\xD2\x03\xA4\x43\xE0\x3E\x66\xF1\x9B\x5F"
+ "\x03\x6E\x2B\x22\xCA\x3A\x5E\x9F\x00\xC0\xDC\x4C\x64\xC3\x4D\x3C\xB4\x6F\x86\xDD\xB7\x6C\xE0\xB6\xAD"
+ "\x1D\xC4\x22\xEA\xAA\x3D\x33\xF3\x15\xFE\xF2\x6E\x81\x57\xFE\x0A\x6F\x5E\x32\xA0\x74\xB9\x26\x08\xAA"
+ "\x2F\x58\x3C\xFD\x2D\x60\x29\x9D\x4E\xFB\xEB\x12\x58\x36\xAE\x45\x21\x7E\x1B\xF7\xEE\x7D\x9F\x63\xFB"
+ "\x53\x24\x36\xE8\x6D\xA3\x25\x3F\xF2\xAA\x57\xA6\xF3\xFC\xEA\xAC\xC1\x07\xB3\xB3\xE0\x17\x41\x78\x53"
+ "\x96\x3C\xF1\x55\x60\xAE\x31\x12\x5A\x5B\xE3\x7A\x07\xDB\xB6\x6D\xE1\xB1\x3B\x8A\x1C\xFE\x4C\x12\x43"
+ "\x57\xF1\x05\x4D\xF8\xEE\xA9\x22\xA7\x27\xAB\x1C\xDC\x15\x21\x10\xB2\x09\x7D\xA9\x28\x07\x06\x21\x57"
+ "\xF4\xB9\x34\xA7\x80\x0C\x36\x65\xE5\xAE\x4F\xF5\x32\xF9\x07\xCB\xB2\x7C\xDB\xB6\xE5\x2A\x02\xC3\xA3"
+ "\x6F\xED\x05\xE5\x45\x34\x83\xBE\xBE\x3E\x1E\x3F\x2A\xD9\xBE\x29\x86\xE7\xCB\x55\x38\xFE\x5C\x99\xF1"
+ "\xB1\x24\xC7\xF6\x99\x3C\x3A\x5E\xE0\x73\xB7\x6A\xAB\x74\x74\x4D\x61\xF7\x76\x93\x6B\x4B\x82\x2B\x0B"
+ "\x00\xF2\xD6\xAC\xB7\xE3\xF5\x5E\xF5\xE2\x95\x90\x04\x1F\x3D\xC8\xA7\x21\x80\xF8\x20\x0F\x1E\x70\x89"
+ "\x77\xE8\x94\x2B\xB2\x25\xC6\xC7\x92\xCB\x9B\xC6\xC7\x92\xFC\xE4\x79\xA7\xA5\x9E\x90\xF0\x8D\x43\x71"
+ "\x06\x6E\x4E\xD4\x94\x23\x3D\xC7\x81\x04\xA0\x37\x45\x60\x78\xD4\x7E\x00\xE4\xB7\x31\x7B\xB9\x6F\x5F"
+ "\x8E\x9D\xFD\x1B\xF0\x02\xD9\x16\x5B\x53\xD1\x26\xE6\xC7\xF6\x99\x7C\xEF\x99\x0F\xD9\xD3\xAF\xAC\xD2"
+ "\x95\xC0\xF6\x94\xE0\x5C\xA6\x07\xBC\xA5\x2D\x59\xB1\x33\xDF\xAB\x4C\x5D\xB0\x2C\xAB\xBA\x12\x01\x29"
+ "\xEE\x07\x8D\x4D\xA9\x2E\x06\xFB\x3B\x29\xB9\x62\x4D\xB4\x5A\xE3\x63\x49\x9E\xFA\xB3\xD7\x52\x3F\xDE"
+ "\x69\xF0\xF5\xA1\x02\x28\x06\x68\xB1\xBB\x80\x1E\xC0\x50\x01\x86\xBF\xF3\xE6\x0E\xE0\x20\xB1\x8D\x7C"
+ "\x69\x60\x01\x3F\x80\x72\x25\x58\x13\x7F\x7A\x63\xB1\x2D\x89\x67\x5E\x6D\xD6\x2D\x94\x7C\xFE\x95\x2D"
+ "\x23\xD1\x20\xB6\x11\x14\x6D\x68\xA2\x72\x64\x27\x10\xAB\x7F\x57\x87\x6A\xE7\x93\x24\x15\x5F\xA2\xE4"
+ "\x88\xEB\x2A\xCD\xCF\xBE\x3C\xCF\x3D\xB7\xA7\x5A\x92\x78\xE8\x97\x8B\xEC\xE9\x2D\xF3\xDE\xA2\xC2\x1B"
+ "\x33\x7D\x2B\xC2\x88\x03\xCE\x2C\x18\xDD\xFB\x81\x0B\x75\x02\x43\x00\x9B\xBB\x05\x92\x9A\xF7\x00\xAF"
+ "\xFE\xC3\x58\x97\xC4\xE9\xB7\x17\x9B\x12\xB2\x99\x04\xFC\x6D\xA1\x59\x16\x89\x9A\x54\x01\xD4\xC8\x20"
+ "\x60\xAE\x10\xD0\x62\x24\xCC\x2A\xC5\xD0\xFB\xB7\xDE\x8F\xB6\x7C\xF1\xC7\x59\xE3\x63\x49\x0E\xFC\x30"
+ "\x4C\xB1\xB0\x2D\x69\x2A\xB5\x3C\x50\x83\x01\x04\xB1\x95\x24\x54\x63\xC4\xA3\x55\x4A\x15\x41\xA9\x22"
+ "\xFE\x6B\xE3\xCB\x15\xF1\x07\x35\xE3\x4A\x63\xA1\xD4\x3B\x41\x4A\x05\x30\xF4\xC6\x92\x5C\xF2\x22\x7C"
+ "\xE8\xF8\x37\xBE\xE7\xB7\x6F\x79\xEA\x4A\x71\x17\x2E\x39\x27\x86\xAE\xCA\xFF\xDD\xF0\x51\x27\xE2\x97"
+ "\x56\x18\x2C\x0F\x13\x81\x4B\xBE\x12\x25\x5B\xEC\x22\x5B\xEC\xE2\xC8\x4F\xBD\x1B\x62\xB4\x9E\x03\x00"
+ "\xBA\x1A\xE6\x82\xF4\x40\x7A\x19\x40\xE8\x61\x11\x9A\x42\xD1\x28\x39\x3E\x86\xB6\x12\x94\x2F\xFF\x58"
+ "\x34\x74\xBB\xE6\xAA\xED\x05\xCD\xE7\xBC\x96\x71\xA3\xA1\xE3\x38\x6E\x35\x6C\xD1\x95\x0C\x1A\x5E\xCD"
+ "\x9A\xF0\xCE\xA2\x69\x50\x5D\x40\x55\xB7\x5C\x97\x67\x75\x02\xEB\x19\x5F\xCE\xFC\xFA\xAA\x2E\x84\xBF"
+ "\x39\x1B\x13\x57\x05\x08\x67\xB8\xF3\x38\x73\x18\x8A\x87\xA9\xB7\x87\xEB\x81\xEB\xAD\x6D\xFC\x6B\x3F"
+ "\xF3\x48\x98\x2B\xA8\xEF\x35\x14\x0F\x9C\x39\x10\xFE\xB4\x65\x9E\xBE\x0C\x38\xF5\x78\x0B\x84\x7F\x0A"
+ "\x95\xCF\x2F\xE5\xE7\xF9\x64\x5F\x67\x5B\xCF\x13\x31\x07\x80\x93\x0F\xC7\x5B\xCA\xBF\xF9\x8B\x25\x12"
+ "\xB1\xD6\x7B\x33\x33\xA5\xDA\xF9\xFB\xC5\x97\xD0\x28\x01\x8E\x06\x60\xDB\x36\x47\x87\x95\xE9\xAC\x6A"
+ "\x7D\xC5\xAF\x14\xB7\xA6\x12\x71\x7A\xCC\x80\x98\xDE\x1E\x77\x5A\x1D\xAB\x0C\x3C\xF2\xD4\x7C\x5B\x7D"
+ "\xA7\x22\xC8\x5E\xBD\x52\xF3\x5E\xF9\xED\xCF\x81\x0F\x80\x7C\xE3\x8C\xE5\x11\xB8\x8F\xA3\x99\xE7\x32"
+ "\x97\x67\xF8\xC2\x9E\x4F\x60\x68\xD7\xFF\x49\x7E\xFF\xE4\x55\xBA\xA2\xED\xF2\x45\x21\x73\x79\xAE\xF6"
+ "\xE0\x66\x9F\x24\x4A\x1E\xC8\x03\xDE\x72\x7E\xDA\xB6\x2D\x8F\x5A\x7A\x36\x2B\x3F\x9D\x0B\x84\x7A\xC7"
+ "\x7C\xBE\xC2\x40\x6F\x84\x88\xA1\x61\x68\xCA\x2A\x9C\x7B\xBB\xC8\xC1\xDD\x5D\x00\xFC\xE8\x77\xD9\x96"
+ "\x3A\x86\xA6\xA0\xE2\xF3\xDA\x54\x8E\xB2\xEB\x41\x35\xF7\x84\x65\xFC\xFE\x0C\x90\x05\xF2\xE9\x74\x3A"
+ "\x68\x1A\xC9\x2C\xCB\x92\xBD\x4C\x4E\x66\xE5\xAE\x42\x35\x50\x0F\x5F\x99\xAB\xD2\x9F\x52\xE9\x30\xA3"
+ "\xE8\x9A\xB2\x0A\xE7\x2F\x96\x38\x7F\xB1\xD4\x52\xA6\x6B\x0A\xAE\x53\xE6\xCC\x85\x02\x25\x27\x34\xAE"
+ "\x3D\xF7\x3C\x30\x0B\xCC\x03\x55\xDB\xB6\x9B\x67\x42\xDB\xB6\xB1\x2C\x2B\xA8\x93\xF0\x84\x76\xF8\xEF"
+ "\x33\x2E\x9E\x50\xD9\xB6\x51\xC5\xD0\x55\x74\x95\x75\xA1\x48\x9F\x89\x7F\x96\x79\xFD\x9D\x3C\x9E\x2F"
+ "\x1A\x8D\x67\x81\x6B\x80\x53\xBF\x35\xB5\xAC\xD2\x23\x23\x23\x2A\xD0\x31\xE1\xDF\x7D\x3B\x91\x9E\xE3"
+ "\x28\xDA\x70\xD4\x50\xB9\x79\x73\x07\xBB\x7A\x05\xC9\x64\x37\x9A\xD6\xDC\xAA\x83\xC0\x63\x71\xB1\xC0"
+ "\x3B\x57\x55\xDE\x9B\x2D\x53\xF1\x04\x08\x7F\x1A\x37\xFB\xA4\x15\x7D\xF1\x42\x98\x74\xD7\x80\x72\xE3"
+ "\x58\xDE\xB6\x4D\x84\x24\x62\x40\x62\x42\xDE\xFB\x20\x5A\xEC\x2E\x14\x6D\xA8\x2E\x37\x23\x90\xEA\xAE"
+ "\xE5\xF0\x7C\xC1\xC7\xA9\x36\x6C\x16\xFE\x34\x7E\xF1\x25\x4B\x7B\xF6\x8F\x61\xB2\xCD\x03\xB9\x56\xB7"
+ "\xA3\x35\xAF\x66\x23\x23\x23\x4A\x38\xBD\x76\x02\x3D\x13\x95\x23\x3B\x31\xBA\xF7\xA3\x46\x06\x51\x8D"
+ "\x81\xB0\xA5\x86\xB5\xDA\xCB\x10\x54\x32\x54\x73\x76\x58\x64\x4A\x40\x21\x24\x50\x02\xFC\x56\x97\xD5"
+ "\xEB\xBA\x9C\x86\xD1\x30\xC2\x88\x98\x21\x62\xE1\x7F\xEA\x72\x31\x03\x0F\x70\x01\x27\x84\xBB\xDE\xE5"
+ "\xF4\xDF\xBB\x32\x46\xA9\x19\x56\x7E\x4C\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1625,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x0D\x00\x00\x0B\x0D\x01\xED\x07\xC0\x2C\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD3\x09\x09\x13\x12\x2A\x95\x49\x4D\xF6\x00\x00\x05\xE6\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x97\x5D\x8C\x5B\x47\x15\xC7\x7F\x77\xEE\xBD\xFE\xDA\xAC\xF7\x23\x2E\x49\x76\x13\x36\x81\x50"
+ "\x25\xA4\x91\x36\x7B\xA1\x0F\x44\x09\x09\x10\x22\xA2\x88\x96\x0A\x29\x2F\x2D\x6D\x0A\x2B\xC8\x43\xDF"
+ "\xAA\xBE\x54\x42\x4A\x05\x02\x89\x87\x22\xF5\xA5\xC8\x22\x25\xB4\x12\x2A\x0F\x14\x10\x0A\x12\x55\x1A"
+ "\xD4\x88\x0D\x91\xBA\xDE\xEE\x2E\x5D\xAA\xB6\x86\x6C\x83\xE3\x4D\xF6\xC3\x5E\xC7\xF6\xBD\xBE\x1F\x33"
+ "\x3C\xF8\xEE\xDA\x8E\xED\x6C\x8A\x0A\x8C\xF4\x7F\xF0\x9D\x33\xF3\xFF\x9F\xE3\x99\x33\xE7\xC0\xFF\x79"
+ "\x68\x1F\xC5\x78\xEC\xCC\xF4\x2E\x50\x47\x41\x8E\x02\xA3\x28\xD9\xB4\x87\x9A\x41\xC9\x19\xA4\x77\xC9"
+ "\xE2\x7C\x16\x90\xE9\x74\x5A\x7D\x2C\x02\xC6\xCE\x4C\x9F\x06\x9E\x00\x0E\x83\x02\x24\x88\x08\x88\x58"
+ "\xDD\x40\x3A\x10\x38\xCD\x4B\x26\x90\xFE\x2B\x96\xFA\xF9\x39\xC0\x4B\xA7\xD3\xF2\x3F\x12\x30\x76\x66"
+ "\xFA\x00\x9A\x78\x1E\x25\xBF\x88\xD0\x21\xD2\x0F\x91\x41\x22\xD1\x38\x3B\x92\x25\x3E\xBF\xBD\x00\x40"
+ "\xD9\x81\x8B\xD7\x46\xB0\x1D\x17\x6A\x8B\xE0\x2C\x83\xF2\x00\x65\x13\x38\x4F\x5B\xFC\xF2\x17\x80\xD3"
+ "\x49\x88\xB6\x81\xD7\xE7\x00\x88\x6F\x25\xB2\xE9\x13\x7C\xFB\xC1\x1C\xFB\x3F\xB5\x89\xFB\xB7\x27\x88"
+ "\x45\x44\xDB\x9A\xDC\x52\x8D\xBF\xFE\x7D\x95\xCB\xEF\xC2\x5B\xD7\x4C\xA8\xCC\xD7\x27\x02\xF7\x35\x8B"
+ "\x97\xBE\x03\x94\xD2\xE9\xB4\xBF\xA1\x80\x75\x72\x3D\x0A\xC9\xFB\x79\xF4\xC0\xBF\x78\xE8\x60\x8A\x81"
+ "\x4D\x46\xD7\x68\xA9\x3B\xB6\xBA\x3C\x5B\xE4\x67\x97\x4C\x6E\x2E\x2C\x80\x5F\x06\xE9\xCD\x58\xEA\xDC"
+ "\x57\x81\xC5\xE6\x48\xE8\x5D\xC9\x8D\x04\x3B\x76\x6C\xE3\xE9\xE3\x65\x8E\x7D\x6E\x10\xD3\x10\xF8\x92"
+ "\x16\xBC\xF1\x76\x89\x6C\xBE\xC6\xF0\x7D\x51\x02\xA9\x5A\x30\x9C\x8A\x72\x68\x0F\x14\xCA\x3E\xD7\x16"
+ "\x35\x50\xC1\x96\xBC\xDA\xF7\xD9\x21\xA6\x7F\x67\x59\x96\x9F\xC9\x64\x54\x9B\x80\xB1\x33\x6F\x1F\x00"
+ "\xED\x02\xBA\xC9\xF0\xF0\x30\xCF\x9C\x54\xEC\xDC\x12\xC3\xF3\x55\x1B\xAE\xCC\x95\x39\x75\x24\xC5\x03"
+ "\x3B\x13\x5C\xB8\x5A\xE0\xBE\x3E\xA3\xCD\xC6\xD0\x35\xF6\xEF\x8C\x73\xAB\x24\xB9\xBE\x0C\xA0\x3E\x93"
+ "\xF7\x76\x5D\x19\x12\x73\xD7\x43\x11\xDC\x19\xD3\x97\x20\x80\xE4\x7E\x9E\x3C\xB4\x4C\x32\x91\xA0\x5A"
+ "\x6B\xBF\x49\x73\xF3\x55\x4E\x1D\x49\xAD\xFF\x3E\x75\x24\xC5\xEC\x3F\xAB\x5D\xFF\x9E\x6F\x1D\x4D\x72"
+ "\xF3\xB6\xC9\x07\xFF\x28\x43\xA4\xFF\x2C\x92\x29\xC0\x03\x3C\xBD\xE1\x7D\xE6\x34\xA8\xEF\x12\x1F\xE2"
+ "\xB1\x07\x0B\xEC\x1D\xD9\x84\x17\xA8\x36\xBC\x9F\x73\x5A\xC8\xD7\xC6\xB5\x9B\x4E\x47\x7B\x2F\x50\x28"
+ "\x60\x67\x4A\xF2\x66\xB6\x1F\xBC\xD2\xB6\xBC\xDC\x5B\x1C\xD2\x66\xA6\x2C\xCB\x72\x1B\x11\x50\xF2\x09"
+ "\x34\x93\x2D\xA9\x5E\xF6\x8C\x38\x54\x9C\xF6\xAB\xBB\x58\xF4\x3A\x92\x03\x1D\xED\x9B\x47\xB2\xC7\xE4"
+ "\x1B\xA3\x4B\xBC\x36\x61\x82\x1E\x7B\x04\xC9\xCB\x80\x6D\x00\x8C\x7D\xEF\xAD\x5D\xC0\x61\x62\x9B\xF9"
+ "\xD2\xEE\x65\xFC\xA0\x07\x3F\x08\x5A\x09\x6C\xD9\x95\xFC\x0F\x57\x57\xEE\x4A\xEE\xF9\x8A\xE5\x92\x8B"
+ "\x42\x87\xD8\x66\xB0\x17\x46\x27\x6B\x27\xF6\x5A\xD1\x0B\x85\xB5\x08\x1C\x05\x20\x32\x48\x2A\x59\xA2"
+ "\x62\xB7\x7B\xD3\x8D\xFC\xD5\x3F\x2F\x75\x25\x5E\x58\x71\xF8\x70\x45\xE3\x6A\x6E\xB8\xF1\x31\x62\x83"
+ "\xBD\x00\x66\xDF\x41\x60\x6A\x4D\xC0\x28\xC0\xD6\x3E\x89\x02\xAA\xB5\x56\xEF\x4F\x1F\xDF\x72\xCF\xE4"
+ "\xCD\x6B\x57\xCA\x01\x57\x73\x23\x2D\xF3\x91\x68\x1C\x17\x40\x44\xF6\x00\xF1\x86\x00\x3D\xC6\x40\xDC"
+ "\xA5\x7C\x87\xF7\x4F\x3D\xBC\xAD\xAB\x87\xDD\xA2\xD2\x3C\xCE\x02\x87\x9E\x03\x15\x5E\x26\x5D\x00\x9A"
+ "\x09\x22\xD8\x8D\x24\xD6\xC8\xA7\x22\x46\x32\xEA\x52\xA9\xC9\x75\xDC\x8D\xFC\xA3\x8C\xCB\xDF\x07\xAD"
+ "\x39\x51\x1A\x3D\xA0\x94\x06\x98\x46\x73\x4A\xAE\x78\x11\x6E\xDB\xFE\xFF\xB2\x1C\x10\x8D\x6B\x28\x1D"
+ "\x0A\x76\x0C\x43\xA8\xFF\x1A\xDB\x7A\x14\xFC\x4A\x43\xC1\x7A\x31\x11\x38\x14\x6B\x51\xF2\xE5\xDE\x75"
+ "\x9C\xF8\xB1\xF7\xB1\x10\x1F\x7A\x2E\x8C\xBC\x08\xCF\x82\xF2\x40\x79\x59\x40\x1A\x61\x12\x9A\x41\xD3"
+ "\xA9\xD8\x3E\xA6\xDE\x9A\x9D\xBF\xFC\x43\xC9\xC5\x67\xC5\x5D\x37\xDE\x68\x98\x4D\x2F\x8E\xED\xB8\xE1"
+ "\x13\x5D\xCB\xA2\xE3\xD5\x77\x96\xDE\x25\x00\xDC\x65\x84\x10\x6D\x38\xF6\xA3\xEE\x87\xEB\x5E\x86\x2E"
+ "\x1A\xC0\x5D\xAE\x7F\x74\x0B\x19\xC0\x11\x00\x61\x0D\x37\x81\xBD\x88\xA9\x79\xC4\x8D\x76\x7C\xFD\x27"
+ "\xDE\x3D\x8B\x18\x88\x7B\x2D\x58\xDB\xC3\xD4\x3C\xB0\x17\x41\xFA\xB3\x56\xFC\x4F\xF3\xEB\xA9\x18\x90"
+ "\x48\xFF\x15\x04\x5F\x28\x15\x97\xF8\xF4\x70\x4F\x47\xB2\xC7\x5F\xB0\x39\xFF\x54\xB2\xA3\x88\xC7\x5F"
+ "\x28\x6D\x18\x89\x6C\xAE\x52\xFF\xFF\xFD\xF2\xEB\xE8\x54\x00\x5B\x07\xC8\x64\x32\x9C\x1C\xD3\x66\xF3"
+ "\xC2\xFA\x8A\x5F\x2B\x6F\x4F\x0D\x24\xE9\x8F\x07\xC4\x8C\x76\xFC\x71\xB2\xCA\xD7\xAC\x44\xDB\xE6\x97"
+ "\xA6\x6F\x77\xB4\x5F\x83\x5D\x93\xE4\x6F\x5C\xAF\x7B\xAF\xBD\xFC\x53\xE0\x26\x50\x6C\x3E\x5D\x1E\x81"
+ "\xF3\x0C\x40\x76\x3E\x47\xCC\xF0\xE8\x8D\xBA\x1D\xF1\xEC\xF9\x1B\x6D\x02\xBA\xD9\xF6\x46\x5D\x62\x86"
+ "\x47\x76\x3E\x57\x37\x74\xF2\x2F\x02\xC5\x10\x8D\x7A\x20\x93\xC9\xA8\x93\x96\x91\xCF\xAB\x07\x0A\x81"
+ "\x14\xC7\x97\x8A\x35\x76\x0F\x45\x88\x98\x3A\xA6\xAE\xB5\xE1\xCD\xBF\x95\x39\xBC\xBF\x17\x80\x1F\xFC"
+ "\x2A\xDF\xD1\xC6\xD4\x35\x04\x3E\x7F\x99\x29\x50\x75\x3C\x70\x0B\xCF\x5B\xE6\x6F\x2F\x02\x79\xA0\x98"
+ "\x4E\xA7\x83\x96\x92\xCC\xB2\x2C\x35\xC4\xF4\x74\x5E\xED\x5B\x75\x03\x71\xEC\xFA\xA2\xCB\x48\x4A\x90"
+ "\x88\x47\x31\x74\xAD\x0D\x13\x73\x15\x26\xE6\x2A\x1D\xE7\x0C\x5D\xC3\xB1\xAB\x5C\x9C\x5A\xA5\x62\x87"
+ "\xE4\xFA\xAF\x7F\x03\x2C\x00\x4B\x80\x9B\xC9\x64\x5A\x6B\xC2\x4C\x26\x83\x65\x59\xC1\x9A\x08\x4F\xEA"
+ "\xC7\xDE\xCB\x39\x78\x52\xB0\x63\xB3\xC0\x34\x04\x86\x60\x43\x68\xCA\x67\xF2\x83\x2A\x57\xDE\x29\xE2"
+ "\xF9\xB2\x99\x3C\x0F\xDC\x02\xEC\xB5\xAE\xA9\x63\x59\x3E\x3E\x3E\x2E\x80\xC4\xA4\xFF\xCD\x23\x44\xFA"
+ "\xCF\xA2\xE9\x63\x51\x53\xF0\xC9\xAD\x09\xF6\x0D\x49\x06\x07\xFB\xD0\x75\xB3\x65\x4D\x10\x78\xAC\xAC"
+ "\xAC\xF2\xCE\x0D\xC1\x87\x0B\x55\x6A\x9E\x04\xE9\xCF\xE2\xE4\x5F\xB4\xA2\x17\xA6\xC2\x43\x77\x0B\xA8"
+ "\x36\x97\xE5\x5D\x1B\x93\x50\x44\x0C\x18\x98\x54\x8F\x3E\x89\x1E\x7B\x04\x4D\x1F\x5D\x9B\x8F\x47\x20"
+ "\xD5\x57\xBF\xC5\x4B\xAB\x3E\xB6\xDB\xB4\x58\xFA\xB3\xF8\xE5\xD7\x2D\xFD\xD5\xDF\x87\x87\x6D\x09\x28"
+ "\x74\xEA\x8E\xEE\xDA\x9A\x8D\x8F\x8F\x6B\x80\x01\xF4\x00\xFD\x93\xB5\x13\x7B\x31\xFB\x0E\x22\x22\x7B"
+ "\x10\xE6\xEE\xF0\x49\x0D\x9F\x13\x2F\x4B\x50\xCB\xE2\x16\x32\x61\x92\xA9\x00\xAB\xA1\x80\x0A\xE0\x77"
+ "\x6A\x56\xEF\xA9\x39\x0D\xA3\x61\x86\x11\x89\x87\x88\x85\xDF\xC4\x7A\x32\xAB\x97\xDA\x0E\x60\x87\x70"
+ "\x36\x6A\x4E\xFF\x0D\xCD\x4A\x06\xF6\x87\x57\xDE\x02\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1647,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x0D\x00\x00\x0B\x0D\x01\xED\x07\xC0\x2C\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD3\x09\x09\x14\x14\x16\xE9\x33\x80\x72\x00\x00\x05\xFC\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x97\x5D\x6C\x1C\x57\x15\xC7\x7F\xF3\xB5\xBB\x63\xC7\x6B\xEF\x66\x69\x12\x3B\xA9\x93\xE2\x56"
+ "\x0E\x21\x91\xE3\x81\x08\x11\x12\x1A\x20\x54\x8D\x22\x22\xAA\x4A\x7D\x69\xA1\x1F\x58\x60\xC9\xAD\xFA"
+ "\x50\x55\x08\x24\xA4\x20\x40\x48\x3C\x14\x09\x1E\x4A\x57\x4E\x09\xA4\x42\xED\x43\x0B\x08\xF5\x21\x25"
+ "\x4A\x95\xB6\x29\x95\xEA\x49\x6D\xB7\x29\x5F\x8B\x92\xA6\xCE\xBA\xF1\xC7\xEE\xBA\xBB\x3B\xB3\x3B\x33"
+ "\xF7\xF2\xB0\xB3\xF6\x6E\xBD\x6B\xA7\x10\xC4\x95\xFE\x5A\xCD\x9E\x73\xE7\xFC\xCF\xB9\x67\xCE\x39\x17"
+ "\xFE\xCF\x4B\xF9\x38\xCA\xC3\xA3\x93\x3B\x40\x1E\x02\x31\x04\x0C\x21\x45\xC3\x3B\xE4\x14\x52\x4C\x21"
+ "\xBC\xB3\x16\x27\x33\x80\x48\xA7\xD3\xF2\x86\x10\x18\x1E\x9D\x7C\x00\xB8\x1F\x38\x08\x12\x10\xA0\x46"
+ "\x40\x8D\xD5\x14\x84\x0B\x81\xDB\xB8\xE5\x3C\xC2\x3F\x65\xC9\xF1\x13\x80\x97\x4E\xA7\xC5\x7F\x44\x60"
+ "\x78\x74\x72\x2F\x8A\xFA\x04\x52\x7C\x11\x55\x83\x48\x0F\x44\x92\x44\xA2\x26\xDB\xE2\x4B\x7C\x76\x6B"
+ "\x0E\x80\xA2\x0B\x67\x2E\xF5\xE3\xB8\x55\xA8\xCC\x81\xBB\x00\xD2\x03\xA4\x43\xE0\x3E\x66\xF1\x9B\x5F"
+ "\x03\x6E\x2B\x22\xCA\x3A\x5E\x9F\x00\xC0\xDC\x4C\x64\xC3\x4D\x3C\xB4\x6F\x86\xDD\xB7\x6C\xE0\xB6\xAD"
+ "\x1D\xC4\x22\xEA\xAA\x3D\x33\xF3\x15\xFE\xF2\x6E\x81\x57\xFE\x0A\x6F\x5E\x32\xA0\x74\xB9\x26\x08\xAA"
+ "\x2F\x58\x3C\xFD\x2D\x60\x29\x9D\x4E\xFB\xEB\x12\x58\x36\xAE\x45\x21\x7E\x1B\xF7\xEE\x7D\x9F\x63\xFB"
+ "\x53\x24\x36\xE8\x6D\xA3\x25\x3F\xF2\xAA\x57\xA6\xF3\xFC\xEA\xAC\xC1\x07\xB3\xB3\xE0\x17\x41\x78\x53"
+ "\x96\x3C\xF1\x55\x60\xAE\x31\x12\x5A\x5B\xE3\x7A\x07\xDB\xB6\x6D\xE1\xB1\x3B\x8A\x1C\xFE\x4C\x12\x43"
+ "\x57\xF1\x05\x4D\xF8\xEE\xA9\x22\xA7\x27\xAB\x1C\xDC\x15\x21\x10\xB2\x09\x7D\xA9\x28\x07\x06\x21\x57"
+ "\xF4\xB9\x34\xA7\x80\x0C\x36\x65\xE5\xAE\x4F\xF5\x32\xF9\x07\xCB\xB2\x7C\xDB\xB6\xE5\x2A\x02\xC3\xA3"
+ "\x6F\xED\x05\xE5\x45\x34\x83\xBE\xBE\x3E\x1E\x3F\x2A\xD9\xBE\x29\x86\xE7\xCB\x55\x38\xFE\x5C\x99\xF1"
+ "\xB1\x24\xC7\xF6\x99\x3C\x3A\x5E\xE0\x73\xB7\x6A\xAB\x74\x74\x4D\x61\xF7\x76\x93\x6B\x4B\x82\x2B\x0B"
+ "\x00\xF2\xD6\xAC\xB7\xE3\xF5\x5E\xF5\xE2\x95\x90\x04\x1F\x3D\xC8\xA7\x21\x80\xF8\x20\x0F\x1E\x70\x89"
+ "\x77\xE8\x94\x2B\xB2\x25\xC6\xC7\x92\xCB\x9B\xC6\xC7\x92\xFC\xE4\x79\xA7\xA5\x9E\x90\xF0\x8D\x43\x71"
+ "\x06\x6E\x4E\xD4\x94\x23\x3D\xC7\x81\x04\xA0\x37\x45\x60\x78\xD4\x7E\x00\xE4\xB7\x31\x7B\xB9\x6F\x5F"
+ "\x8E\x9D\xFD\x1B\xF0\x02\xD9\x16\x5B\x53\xD1\x26\xE6\xC7\xF6\x99\x7C\xEF\x99\x0F\xD9\xD3\xAF\xAC\xD2"
+ "\x95\xC0\xF6\x94\xE0\x5C\xA6\x07\xBC\xA5\x2D\x59\xB1\x33\xDF\xAB\x4C\x5D\xB0\x2C\xAB\xBA\x12\x01\x29"
+ "\xEE\x07\x8D\x4D\xA9\x2E\x06\xFB\x3B\x29\xB9\x62\x4D\xB4\x5A\xE3\x63\x49\x9E\xFA\xB3\xD7\x52\x3F\xDE"
+ "\x69\xF0\xF5\xA1\x02\x28\x06\x68\xB1\xBB\x80\x1E\xC0\x50\x01\x86\xBF\xF3\xE6\x0E\xE0\x20\xB1\x8D\x7C"
+ "\x69\x60\x01\x3F\x80\x72\x25\x58\x13\x7F\x7A\x63\xB1\x2D\x89\x67\x5E\x6D\xD6\x2D\x94\x7C\xFE\x95\x2D"
+ "\x23\xD1\x20\xB6\x11\x14\x6D\x68\xA2\x72\x64\x27\x10\xAB\x7F\x57\x87\x6A\xE7\x93\x24\x15\x5F\xA2\xE4"
+ "\x88\xEB\x2A\xCD\xCF\xBE\x3C\xCF\x3D\xB7\xA7\x5A\x92\x78\xE8\x97\x8B\xEC\xE9\x2D\xF3\xDE\xA2\xC2\x1B"
+ "\x33\x7D\x2B\xC2\x88\x03\xCE\x2C\x18\xDD\xFB\x81\x0B\x75\x02\x43\x00\x9B\xBB\x05\x92\x9A\xF7\x00\xAF"
+ "\xFE\xC3\x58\x97\xC4\xE9\xB7\x17\x9B\x12\xB2\x99\x04\xFC\x6D\xA1\x59\x16\x89\x9A\x54\x01\xD4\xC8\x20"
+ "\x60\xAE\x10\xD0\x62\x24\xCC\x2A\xC5\xD0\xFB\xB7\xDE\x8F\xB6\x7C\xF1\xC7\x59\xE3\x63\x49\x0E\xFC\x30"
+ "\x4C\xB1\xB0\x2D\x69\x2A\xB5\x3C\x50\x83\x01\x04\xB1\x95\x24\x54\x63\xC4\xA3\x55\x4A\x15\x41\xA9\x22"
+ "\xFE\x6B\xE3\xCB\x15\xF1\x07\x35\xE3\x4A\x63\xA1\xD4\x3B\x41\x4A\x05\x30\xF4\xC6\x92\x5C\xF2\x22\x7C"
+ "\xE8\xF8\x37\xBE\xE7\xB7\x6F\x79\xEA\x4A\x71\x17\x2E\x39\x27\x86\xAE\xCA\xFF\xDD\xF0\x51\x27\xE2\x97"
+ "\x56\x18\x2C\x0F\x13\x81\x4B\xBE\x12\x25\x5B\xEC\x22\x5B\xEC\xE2\xC8\x4F\xBD\x1B\x62\xB4\x9E\x03\x00"
+ "\xBA\x1A\xE6\x82\xF4\x40\x7A\x19\x40\xE8\x61\x11\x9A\x42\xD1\x28\x39\x3E\x86\xB6\x12\x94\x2F\xFF\x58"
+ "\x34\x74\xBB\xE6\xAA\xED\x05\xCD\xE7\xBC\x96\x71\xA3\xA1\xE3\x38\x6E\x35\x6C\xD1\x95\x0C\x1A\x5E\xCD"
+ "\x9A\xF0\xCE\xA2\x69\x50\x5D\x40\x55\xB7\x5C\x97\x67\x75\x02\xEB\x19\x5F\xCE\xFC\xFA\xAA\x2E\x84\xBF"
+ "\x39\x1B\x13\x57\x05\x08\x67\xB8\xF3\x38\x73\x18\x8A\x87\xA9\xB7\x87\xEB\x81\xEB\xAD\x6D\xFC\x6B\x3F"
+ "\xF3\x48\x98\x2B\xA8\xEF\x35\x14\x0F\x9C\x39\x10\xFE\xB4\x65\x9E\xBE\x0C\x38\xF5\x78\x0B\x84\x7F\x0A"
+ "\x95\xCF\x2F\xE5\xE7\xF9\x64\x5F\x67\x5B\xCF\x13\x31\x07\x80\x93\x0F\xC7\x5B\xCA\xBF\xF9\x8B\x25\x12"
+ "\xB1\xD6\x7B\x33\x33\xA5\xDA\xF9\xFB\xC5\x97\xD0\x28\x01\x8E\x06\x60\xDB\x36\x47\x87\x95\xE9\xAC\x6A"
+ "\x7D\xC5\xAF\x14\xB7\xA6\x12\x71\x7A\xCC\x80\x98\xDE\x1E\x77\x5A\x1D\xAB\x0C\x3C\xF2\xD4\x7C\x5B\x7D"
+ "\xA7\x22\xC8\x5E\xBD\x52\xF3\x5E\xF9\xED\xCF\x81\x0F\x80\x7C\xE3\x8C\xE5\x11\xB8\x8F\xA3\x99\xE7\x32"
+ "\x97\x67\xF8\xC2\x9E\x4F\x60\x68\xD7\xFF\x49\x7E\xFF\xE4\x55\xBA\xA2\xED\xF2\x45\x21\x73\x79\xAE\xF6"
+ "\xE0\x66\x9F\x24\x4A\x1E\xC8\x03\xDE\x72\x7E\xDA\xB6\x2D\x8F\x5A\x7A\x36\x2B\x3F\x9D\x0B\x84\x7A\xC7"
+ "\x7C\xBE\xC2\x40\x6F\x84\x88\xA1\x61\x68\xCA\x2A\x9C\x7B\xBB\xC8\xC1\xDD\x5D\x00\xFC\xE8\x77\xD9\x96"
+ "\x3A\x86\xA6\xA0\xE2\xF3\xDA\x54\x8E\xB2\xEB\x41\x35\xF7\x84\x65\xFC\xFE\x0C\x90\x05\xF2\xE9\x74\x3A"
+ "\x68\x1A\xC9\x2C\xCB\x92\xBD\x4C\x4E\x66\xE5\xAE\x42\x35\x50\x0F\x5F\x99\xAB\xD2\x9F\x52\xE9\x30\xA3"
+ "\xE8\x9A\xB2\x0A\xE7\x2F\x96\x38\x7F\xB1\xD4\x52\xA6\x6B\x0A\xAE\x53\xE6\xCC\x85\x02\x25\x27\x34\xAE"
+ "\x3D\xF7\x3C\x30\x0B\xCC\x03\x55\xDB\xB6\x9B\x67\x42\xDB\xB6\xB1\x2C\x2B\xA8\x93\xF0\x84\x76\xF8\xEF"
+ "\x33\x2E\x9E\x50\xD9\xB6\x51\xC5\xD0\x55\x74\x95\x75\xA1\x48\x9F\x89\x7F\x96\x79\xFD\x9D\x3C\x9E\x2F"
+ "\x1A\x8D\x67\x81\x6B\x80\x53\xBF\x35\xB5\xAC\xD2\x23\x23\x23\x2A\xD0\x31\xE1\xDF\x7D\x3B\x91\x9E\xE3"
+ "\x28\xDA\x70\xD4\x50\xB9\x79\x73\x07\xBB\x7A\x05\xC9\x64\x37\x9A\xD6\xDC\xAA\x83\xC0\x63\x71\xB1\xC0"
+ "\x3B\x57\x55\xDE\x9B\x2D\x53\xF1\x04\x08\x7F\x1A\x37\xFB\xA4\x15\x7D\xF1\x42\x98\x74\xD7\x80\x72\xE3"
+ "\x58\xDE\xB6\x4D\x84\x24\x62\x40\x62\x42\xDE\xFB\x20\x5A\xEC\x2E\x14\x6D\xA8\x2E\x37\x23\x90\xEA\xAE"
+ "\xE5\xF0\x7C\xC1\xC7\xA9\x36\x6C\x16\xFE\x34\x7E\xF1\x25\x4B\x7B\xF6\x8F\x61\xB2\xCD\x03\xB9\x56\xB7"
+ "\xA3\x35\xAF\x66\x23\x23\x23\x4A\x38\xBD\x76\x02\x3D\x13\x95\x23\x3B\x31\xBA\xF7\xA3\x46\x06\x51\x8D"
+ "\x81\xB0\xA5\x86\xB5\xDA\xCB\x10\x54\x32\x54\x73\x76\x58\x64\x4A\x40\x21\x24\x50\x02\xFC\x56\x97\xD5"
+ "\xEB\xBA\x9C\x86\xD1\x30\xC2\x88\x98\x21\x62\xE1\x7F\xEA\x72\x31\x03\x0F\x70\x01\x27\x84\xBB\xDE\xE5"
+ "\xF4\xDF\xBB\x32\x46\xA9\x19\x56\x7E\x4C\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1736,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x0D\x00\x00\x0B\x0D\x01\xED\x07\xC0\x2C\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD3\x09\x09\x13\x0E\x0C\xA1\x33\x95\x56\x00\x00\x06\x55\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x97\xDB\x6F\x1C\xD5\x1D\xC7\x3F\x73\x66\xE7\xB2\xBB\xB6\x77\xD7\x71\x62\xC7\xC6\x89\x13\x62"
+ "\x14\x27\x4D\xB0\x3D\x2D\x52\x9B\x84\x92\x16\x8A\x8A\x90\xDA\xA2\xBE\x20\xD1\x0A\x68\xAD\x36\x0F\x7D"
+ "\xA8\x84\xF2\x58\x89\xFE\x03\xBC\x82\x96\x86\x06\xF1\xD2\x3E\xF4\xC2\x03\x42\x05\x14\x95\xA8\x84\x4A"
+ "\x78\x8D\x6D\x51\x10\xCA\xA6\x36\xA9\xB3\x49\x7C\xD9\x5D\xDB\xBB\x33\xBB\x33\x73\x4E\x1F\x76\xBD\x17"
+ "\xAF\x43\x48\x52\xA9\x23\x7D\xA5\x33\xE7\xFC\xCE\xF9\x5D\xCE\xEF\xFC\x2E\xF0\x7F\xFE\xB4\x3B\x21\x9E"
+ "\x3C\x33\x7B\x00\xD4\x69\x90\xE3\xC0\x38\x4A\xB6\x9C\xA1\xE6\x50\x72\x0E\xE9\x5F\x70\x38\x9F\x05\x64"
+ "\x3A\x9D\x56\xFF\x13\x01\x26\xCF\xCC\x3E\x07\x3C\x0B\x3C\x0C\x0A\x90\x20\x4C\x10\x76\x8D\x40\x7A\x10"
+ "\x7A\xAD\x5B\x3E\x40\x06\x6F\x38\xEA\x77\xE7\x00\x3F\x9D\x4E\xCB\xBB\x12\x60\xF2\xCC\xEC\x04\x9A\x78"
+ "\x09\x25\xBF\x8D\xD0\xC1\x4C\x82\xD9\x8B\x69\x45\x19\xEE\x59\xE7\x1B\xF7\xE5\x01\xD8\xF4\xE0\xBD\x85"
+ "\xFD\xB8\x5E\x15\x2A\xCB\xE0\xAD\x82\xF2\x01\xE5\x12\x7A\x2F\x38\xBC\xFE\x7B\xC0\xDB\x49\x10\xED\x36"
+ "\x5A\x9F\x03\x20\x3A\x80\xD9\xB5\x87\x9F\x3D\xB4\xC4\xB1\x83\x5D\x3C\x70\x5F\x0C\xDB\x14\x1D\x7B\x96"
+ "\x56\x2A\x7C\xF8\x69\x91\x8B\x9F\xC1\x47\x0B\x06\x94\x16\x6B\x0B\x61\xF5\xCF\x0E\xAF\xFD\x1C\x58\x4F"
+ "\xA7\xD3\xC1\x6D\x05\x68\x30\xD7\x2D\xE8\x79\x80\x67\x26\xFE\xC3\x0F\x4E\xF4\x91\xEA\x8A\xB4\xD1\xCD"
+ "\x64\xCB\x00\x4C\xDC\x1F\x43\x6D\x3B\xEA\xE2\x7C\x81\x57\x2E\x18\xDC\xB8\x7E\x1D\x82\x4D\x90\xFE\x9C"
+ "\xA3\xCE\x7D\x0F\x58\x6E\xB5\x84\x7E\x4B\xE6\x91\x18\xC3\xC3\x7B\x79\xE1\xF1\x4D\x1E\xFB\x7A\x2F\x46"
+ "\x44\x10\x48\x1A\x98\x5F\x70\x79\xF0\x60\x8C\x3D\x49\x83\xD9\x2B\x65\x52\xDD\x11\x42\xA9\x1A\x18\xEA"
+ "\xB3\x38\x75\x18\xF2\x9B\x01\x0B\xCB\x1A\xA8\xB0\x3F\xA7\x8E\x1E\x19\x64\xF6\xAF\x8E\xE3\x04\x99\x4C"
+ "\x46\x75\x08\x30\x79\xE6\xE3\x09\xD0\xDE\x42\x37\x18\x1A\x1A\xE2\xEC\x93\x8A\x91\x7E\x1B\x3F\x50\x6D"
+ "\xB8\x7C\xAD\xC2\x91\x7D\x36\x7B\x92\x26\x86\xAE\x11\xB5\x04\x9F\x5D\xF5\x88\x5B\xA2\x8D\x2E\xA2\x6B"
+ "\x1C\x1B\x89\x72\x73\x5D\x72\x75\x15\x40\x8D\xE6\xFC\x03\x97\x06\xC5\xBF\xAE\xD6\x85\x20\xB2\xCD\x00"
+ "\xAF\x41\x08\x3D\xC7\x78\xFE\xD4\x2A\x3D\xB1\x18\xE5\x4A\xFB\x4B\x5A\x2E\xFA\x8C\x0E\xD9\xEC\x4E\x98"
+ "\x00\x98\x86\xA0\xB7\xDB\x60\xA4\x5F\xB1\x70\xA3\xC2\xEE\x84\xD1\x71\xA5\x3F\x3D\xDD\xC3\x8D\x0D\x83"
+ "\xCB\x57\x36\xC1\x4C\xBE\x88\x64\x06\xF0\x01\x5F\x6F\x6A\x9F\x79\x0E\xD4\x2F\x88\x0E\xF2\x93\x87\xF2"
+ "\x8C\xED\xEF\xC2\x0F\x55\x1B\x0A\xA5\x90\x91\x7E\x8B\xC1\x5D\x26\x46\xA4\xE9\x84\x46\x44\xC3\x34\x34"
+ "\x82\x50\x71\xB3\xE0\xA3\x69\xB4\xED\x53\xC0\x48\x9F\xE4\xFD\x6C\x12\xFC\xF5\xBD\x39\x39\x56\x18\xD4"
+ "\xE6\x66\x1C\xC7\xA9\x36\x4F\x51\xF2\x59\xD0\xE9\xEF\xEB\xE6\xF0\xFE\x38\x25\x4F\x76\x60\xA0\xD7\x60"
+ "\xA8\xCF\xC4\x8C\x74\xBE\x80\xB8\xAD\x33\xD2\x6F\xD1\x15\x15\x3B\xEE\xED\x89\x1B\xFC\x68\xBC\x08\x9A"
+ "\x01\xBA\xFD\x14\x90\x04\x0C\x01\x30\xF9\xCB\x8F\x0E\x00\x0F\x63\xEF\xE2\x3B\x87\x56\x09\x42\x28\x57"
+ "\xC2\x36\x24\xE2\x82\xD1\x41\x1B\xCB\x10\xB7\x8C\x1B\x71\x5B\xE7\xF8\x81\x38\x52\xC9\xB6\xBD\xC5\x52"
+ "\xC0\x95\x5C\x19\x85\x0E\xF6\x2E\xD0\xF4\xF1\xE9\xCA\x13\x63\x80\xBD\xE5\x03\xA7\x6B\x17\xDA\x4B\x5F"
+ "\xCF\x3A\x25\xB7\x19\x2F\x34\x0D\x86\x77\x9B\x38\xA3\xDD\x5F\x29\x5C\xDB\xA6\xE0\xD1\x89\x14\x6F\x5E"
+ "\x5A\xE3\xDF\xB9\x32\x5F\xAC\x69\xFC\x73\x69\xA8\x49\x60\xBA\xE0\x5E\x07\x23\x71\x02\x98\xD9\x52\x67"
+ "\x1C\x60\x20\x21\x51\xB4\x6B\xBF\x27\x19\xE1\x9B\x47\x7A\xEE\x38\xC9\x3C\x3A\x99\xC0\x34\x44\x3B\x73"
+ "\xC0\xB4\xA2\xB5\x81\x30\x0F\x03\xD1\xA6\x00\xBA\x4D\x2A\x5A\x65\xD3\x95\x0D\xF4\xA7\x4C\x1E\x79\x30"
+ "\x79\x57\x59\x2E\x66\xE9\xFC\xF0\x64\x3F\xC7\xF7\xD5\xAC\xD8\x08\x3C\x82\x9A\x1F\x08\xE3\x10\x60\x37"
+ "\x2F\x54\xD8\xF4\x58\x55\x4A\x15\x49\xA9\x22\x39\xB8\xD7\xE6\xBB\xE3\x89\x7B\x4A\xB5\x7B\x53\x3A\xBF"
+ "\xFE\x3E\x8C\x6F\x13\x82\x48\x1C\x94\xD2\x1A\x4E\xB8\x15\x92\x4B\xBE\xC9\x86\x0B\x1B\x2E\x8C\xED\x8B"
+ "\x61\x99\xE2\x9E\xF3\xFD\xE8\x00\x4C\x8C\xDC\x72\x59\x34\x03\x91\xF4\xC8\xBB\x36\x11\x51\x0B\x3C\xAF"
+ "\xFF\xDD\x23\x66\x55\x00\x18\xEE\xD3\x79\xFA\x54\xFC\x8E\x18\xFF\xEA\x7C\x73\x7C\xBD\xD0\x74\x68\x00"
+ "\x82\x52\xD3\x18\x8D\x62\x22\xF4\x4E\x16\x2A\x16\x81\xAA\x4D\xE5\x36\x9B\x07\x1C\x73\x35\x9E\xDE\x81"
+ "\xC9\xA9\xDF\xB6\xFF\x5F\xFC\x4D\x73\xFC\xF1\x62\x27\x7D\x44\x80\x1F\x52\x4B\xD5\xCA\xCF\x02\x32\x52"
+ "\x0F\x42\x73\x68\x3A\x25\x37\xC0\xD0\x23\x1D\x1B\xFD\xF0\xDE\xAE\xC1\x68\xC9\x38\xAE\x57\xAD\xA7\xE8"
+ "\x4A\x16\x1D\xBF\x76\xC9\xD2\xBF\x00\x40\x75\x15\x21\x44\x07\x34\x71\x6F\xBE\xA0\x8B\x26\xA8\xAE\xD6"
+ "\x26\xAB\xF9\x0C\xE0\x09\x80\x7A\x0D\xF7\x01\xEE\x32\x86\xE6\x13\x8D\xB4\xC3\xD2\x83\x3B\x66\x9A\x8A"
+ "\xFA\x0D\x6C\x9D\x63\x68\x3E\xB8\xCB\x20\x83\x79\x27\xFA\xB7\x45\xC0\xDD\xB2\xB7\x44\x06\x6F\x20\xF8"
+ "\xD6\x7A\x61\x85\xFB\x87\xDA\x1D\xAE\xDB\xD4\x9B\xEE\xD2\xF2\x1D\x4C\xAD\x6F\x9B\x69\x06\xAC\x94\xED"
+ "\x76\xD0\x67\x97\x4A\xB5\xFB\x0F\x36\xDF\x41\xA7\x04\xB8\x02\x20\x9D\x4E\xAB\x5A\x01\xA9\x3E\x74\x8B"
+ "\xD7\x90\x81\x4F\xC2\xAA\x36\x10\x37\x76\xB6\x40\x2B\x4D\xC2\xAA\x7E\xE9\x9A\x0C\x7C\xDC\xE2\xB5\x9A"
+ "\xF6\xFA\x1F\xDE\x04\x8A\x80\xD7\xAA\x96\x4F\xE8\x9D\x45\x8F\xBE\x9F\x5D\x5C\xE2\xE4\xF1\xDD\x18\x7A"
+ "\xED\x49\x16\x37\x7C\x5E\x7D\xDB\x6F\x10\xE6\xD6\x7C\x3C\x5F\xD1\x6D\xB5\x0B\xF4\xEA\xDB\x2B\x4D\xAB"
+ "\xB5\x08\xE4\x87\x1A\xD9\xC5\xE5\xDA\x8F\x97\x7B\x19\x8B\x02\x50\x68\xAB\x07\x32\x99\x8C\x7A\xD2\x89"
+ "\xE4\x72\xEA\x6B\xF9\x50\x8A\xC7\x57\x0A\x15\x0E\x0D\x9A\x98\x86\x8E\xA6\xC1\xA6\x27\x1B\xD0\x34\x30"
+ "\x74\xAD\x03\xAD\x34\x5B\x73\x82\x80\x7F\xCC\xE5\x29\x7B\x3E\x54\xF3\x2F\x39\xC6\x5F\xDE\x03\x72\x40"
+ "\x21\x9D\x4E\x87\xDB\xDD\x3B\x70\x38\xFF\x0A\xA1\x7B\x76\xA3\x5C\xE5\xDD\xE9\x3C\x7E\xC5\xC5\x32\xC4"
+ "\x5D\xC1\xAF\xB8\xBC\x3B\x9D\x67\xA3\x5C\xAD\x31\xD7\xFF\xF8\x27\xE0\x06\x90\x07\x82\x8E\x9A\x30\x93"
+ "\xC9\xE0\x38\x4E\x38\xC8\xEC\x6C\x4E\x1D\x2D\xFA\x52\x7F\xEC\xF3\x25\x0F\x5F\x0A\x86\x77\x09\x8C\x88"
+ "\x20\x22\xB8\x2D\x34\x15\x30\x7D\xB9\xCC\xA5\x4F\x0A\xF8\x81\x6C\x65\x9E\x03\x6E\x02\xEE\x56\xD7\xB4"
+ "\x63\x59\x3E\x35\x35\x25\x80\xD8\x74\xF0\xE3\x47\x30\x93\x2F\xA2\xE9\x93\x96\x21\xD8\x37\x10\xE3\xE8"
+ "\xA0\xA4\xB7\x37\x81\xAE\xB7\xD7\x7E\x61\xE8\xB3\xB6\x56\xE4\x93\x6B\x82\x2F\xAE\x97\xA9\xF8\x12\x64"
+ "\x30\x8F\x97\x7B\xD9\xB1\xDE\x9A\xA9\x6B\x7E\x13\x28\xB7\x96\xE5\xB7\x6C\x4C\xEA\x42\xD8\x40\x6A\x5A"
+ "\x3D\xF3\x3C\xBA\xFD\x14\x9A\x3E\xBE\xB5\x1E\x35\xA1\x2F\x51\xF3\xE1\x95\x62\x80\xDB\xFA\x08\x64\x30"
+ "\x4F\xB0\xF9\x4E\xDD\xDB\x0B\xC0\x4A\xDD\xEC\x1D\xDD\xD1\x97\xB6\x66\x53\x53\x53\x5A\x3D\x00\xC4\x81"
+ "\xE4\x74\xE5\x89\x31\x8C\xC4\x09\x84\x79\x18\x61\x1C\xAA\xA7\xD4\x7A\x3A\xF1\xB3\x84\x95\x2C\xD5\x7C"
+ "\xA6\x1E\x64\x4A\xF5\xA7\x56\xA8\x8F\x83\x9D\x9A\xD5\xAF\xD4\x9C\xD6\xAD\x61\xD4\x2D\x12\xAD\xC3\xAE"
+ "\xCF\x89\x46\x30\xAB\x95\xDA\x1E\xE0\xD6\xE1\xDD\xAE\x39\xFD\x2F\xD0\x42\x12\x9F\x36\x7A\xBA\x3A\x00"
+ "\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 952,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xAF\xC8\x37\x05\x8A\xE9\x00"
+ "\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61"
+ "\x67\x65\x52\x65\x61\x64\x79\x71\xC9\x65\x3C\x00\x00\x03\x4A\x49\x44\x41\x54\x78\xDA\x62\xFC\xFF\xFF"
+ "\x3F\xC3\x40\x02\x80\x00\x62\x04\x11\x16\x93\x1E\x1A\xFE\xFF\xF7\x57\xF0\xEF\xCF\x1F\x4C\xFF\xFE\xFE"
+ "\x65\xF8\xF7\xF7\x1F\xC3\xBF\x3F\x20\x0C\x65\x23\xF3\x41\xF4\x3F\x08\xFD\x17\x2C\xFF\x9F\xE1\x3F\x48"
+ "\xEC\xEF\x5F\x14\x3D\x7F\xC1\xFC\xFF\x60\x71\xB0\x3C\x5C\xCD\xEF\x0F\xFF\xCE\xA7\x9F\x07\x5A\xFB\x0F"
+ "\x88\xFF\x03\x04\x10\xA3\xC5\xE4\x47\x89\x8C\x4C\xCC\xF3\x44\xF9\xD9\x80\x06\x02\x35\xFE\xFE\x0F\xA1"
+ "\xA1\xF8\xCF\x6F\x18\x1B\x28\x0E\x64\xFF\x01\xAB\x81\x8A\x81\xF9\xFF\xE1\x6C\x14\xF5\x40\x73\xFE\xC0"
+ "\x2D\xFE\xC7\xF0\xFF\x1F\x90\xFE\xFD\x87\xE1\xDF\xCF\x57\x0C\xFF\x7F\xBE\xCA\x67\xB8\x52\x38\x07\xE8"
+ "\x80\x1F\x00\x01\xC4\x02\xB2\xDC\x54\x4D\x80\x41\x46\x98\x8B\xE1\xF7\x6F\x06\x30\xFE\xF5\x0B\x15\xFF"
+ "\x44\x66\xFF\x44\xA3\x41\xE2\x3F\x21\x7C\x38\x1B\x48\xFF\x06\x86\x2D\xD0\x0D\x0C\xFF\x40\x61\xCC\x0A"
+ "\x0D\x6F\xA0\x23\x18\xBF\x9F\x60\xF8\xCF\xF6\x7F\x22\x90\xB7\x09\x88\x5F\x00\x04\x10\x13\x48\x1C\x6E"
+ "\xF9\x1F\x88\x03\xFE\x00\x69\x60\x48\xC2\xF1\x5F\x24\x0C\x34\x83\x01\xE8\x21\x30\x0D\xC6\x50\xB1\x7F"
+ "\xFF\x51\xE9\xFF\x20\x8C\x9E\xBC\x98\x98\x18\x18\xFF\x8B\xC0\x78\x20\x06\x07\x40\x00\xB1\x80\x58\x20"
+ "\x9F\x80\x2C\x05\x39\x00\x99\xFE\xFB\x07\xD5\x72\xB8\x23\xFE\x42\x1C\x81\xE2\xA0\xBF\x98\x0E\x22\x90"
+ "\xBE\xD9\x80\x98\x19\x20\x80\xC0\x0E\xB0\x96\x44\xF2\x01\xCC\xD0\xBF\x08\x83\xFF\xE2\xC1\xE8\x21\xF4"
+ "\x07\xE6\x78\x60\xE2\x04\xF1\x61\xB9\x0C\x42\xFD\x67\xF8\xF9\x86\x8B\xA1\x6B\x19\xC2\x15\x00\x01\xC4"
+ "\x02\x14\x63\x70\x90\xA3\x5E\xB6\x02\x59\xF8\x1F\xEC\x99\xFF\x50\xF6\x7F\x28\x1B\x22\xF7\xE9\x23\x27"
+ "\x8A\x03\x00\x02\x88\x89\x9A\xE5\x00\x36\xCB\xFF\x43\xA3\x02\xD9\x31\xC8\x00\x20\x80\xA8\xE6\x00\x5C"
+ "\x96\xA3\xF2\x41\x0E\xF8\x87\xA2\x0F\x20\x80\x58\xFE\x23\xB9\xA8\xA9\xA9\x09\xA7\x05\x75\x75\x75\x44"
+ "\xA9\xC3\x05\x8A\x8A\xCA\xA0\x39\x07\xD5\x01\x00\x01\xC4\x82\x9C\x54\x91\x2D\xC1\x07\x90\xD5\xE1\x0E"
+ "\xF6\xFF\x68\xE9\x80\x01\x6B\x14\x00\x04\x10\x45\x51\x40\xAA\xE5\xD8\xA2\x00\x20\x80\x98\xFE\xFF\xFB"
+ "\x4F\x91\xE5\xC8\xF1\x8B\x69\x39\x03\x86\x1A\x50\xF6\x44\x06\x00\x01\xC4\x82\x1C\x02\xB4\x4C\x03\xB9"
+ "\xB9\xC5\xD0\xD0\x42\x0D\x01\x80\x00\x42\x49\x84\xC4\xA4\x01\x90\x21\x35\x35\xB5\x58\x7C\x4A\x1C\x1F"
+ "\xDD\x01\x00\x01\x44\x52\x1A\xC0\x0C\x72\xD2\x2C\xC7\x96\x08\x01\x02\x88\x89\x81\xC8\x34\x80\x6E\x39"
+ "\x72\xE9\x46\x4A\x48\xA0\x87\x00\x40\x00\x11\x9D\x06\x60\xC1\x0E\xC2\x6D\x6D\xAD\x24\xA7\x81\x8C\x8C"
+ "\x42\x88\x63\xFE\xA2\x3A\x00\x20\x80\x58\xFE\xFF\x63\xC0\x9B\x06\x30\x7D\xCE\xC0\x50\x5E\x5E\x85\x35"
+ "\x24\x88\x0D\x19\x64\x00\x10\x40\x78\xD3\x00\x36\xCB\x31\xF9\x0C\x38\x1D\x83\x35\x1A\xD0\xEC\x00\x08"
+ "\x20\x02\x0E\x20\x64\xF9\x7F\x92\x43\x02\x1D\x00\x04\x10\xD1\x75\x01\x72\xB0\x77\x77\x77\x90\x9C\x06"
+ "\x92\x93\xF3\x20\xC1\x8F\xE6\x08\x80\x00\xC2\x5A\x17\xE0\xAB\xD1\x40\x3E\x2F\x2A\x2A\x27\x2B\x24\xB0"
+ "\x45\x01\x40\x00\x61\x14\xC5\xF8\xAB\x53\xF2\xA3\x01\x5B\x19\x00\x02\x00\x01\x84\x92\x06\x08\x59\x8E"
+ "\xDF\x31\xB8\x13\x20\xB2\x3C\x7A\x42\x00\x08\x20\x70\x1A\xF8\xFC\xF9\x1B\xB8\x80\x80\x15\x95\xFF\xA1"
+ "\x34\x84\xFF\x1F\x45\x0E\xAB\x9A\xFF\x48\xE2\x50\x4B\xE0\xD6\x20\x47\x3B\x50\xFC\x37\xA8\xC1\x88\x04"
+ "\x00\x02\x08\x5C\x10\x99\x34\xDD\x82\x77\x20\x40\x3D\x9B\xBF\xE8\x3D\x1D\xE4\x1E\x0F\x72\x8F\x09\x4D"
+ "\x0E\xBD\x90\x21\x06\x00\x04\x10\xA8\xDB\xC0\x07\xC4\xB2\x40\xCC\x4F\xE7\x6E\xE1\x47\x20\x7E\x0C\x10"
+ "\x40\xB0\x7E\x0B\x27\x52\xFF\x85\x5E\x00\xD8\x05\x62\xF8\x0E\x10\x40\x8C\x03\xDD\x3B\x06\x08\x20\x26"
+ "\x86\x01\x06\x00\x01\x06\x00\x37\xA7\x3B\x50\x1D\xE2\x87\x14\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42"
+ "\x60\x82"
+},
+
+{
+ 1749,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x13\x00\x00\x0B\x13\x01\x00\x9A\x9C\x18\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD4\x07\x18\x0F\x35\x0D\xB5\x2A\xAE\xCF\x00\x00\x06\x62\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x96\x5D\x6C\x54\xC7\x15\xC7\x7F\x33\x73\x3F\xF6\xDE\xDD\x35\x6B\xEC\x80\xA1\x44\x36\x90\x18"
+ "\x9A\x36\x68\x4B\x93\x2A\xA0\x56\x71\xAA\x50\xA1\x24\x04\xA7\x6A\x78\xA8\x44\x20\x12\x51\x9B\xBC\x04"
+ "\xD4\xAA\x7D\x08\x2A\x28\xCA\x03\x3C\x54\xA9\x91\x0A\xAA\x62\x09\x9B\x46\x45\x48\x21\x60\xDA\x26\x21"
+ "\xA9\x6A\x4B\x4D\x52\x15\x37\x60\xA9\x0D\xE0\x84\x80\xF9\x30\x8E\xC1\x1F\x8B\x31\xFB\x71\xF7\xDE\x99"
+ "\x3E\xAC\xBD\x98\x04\xD4\x35\x25\xEA\x91\x46\xF7\xEA\x6A\xEE\x9C\xDF\xF9\x9F\x33\x67\x46\x70\x0B\x3B"
+ "\x7C\xF8\x83\xF5\x4A\x99\xD5\x4A\x99\x26\xCF\x73\x53\xAE\xEB\x12\x86\x21\xE3\xE3\x59\xA2\x48\x74\x45"
+ "\x91\xE8\x30\x46\xB4\xAD\x5C\xB9\x3C\xC3\xFF\x60\xE2\x8B\x1F\x0E\x1D\xEA\x6A\x72\x1C\xBD\x3B\x32\x51"
+ "\x43\x88\xC4\xF5\xE3\x18\x63\x90\x52\x22\xA5\x44\x6B\x8D\x25\x20\x2A\x16\xD0\x41\x98\x29\x16\x55\xCB"
+ "\xAA\x55\x0F\x6F\xBD\x23\x00\xFB\xF7\xBF\xB7\xD5\x76\xA2\x2D\x45\xA1\xF0\x13\x09\x12\x09\xBF\xEC\x58"
+ "\x0A\x90\x52\x22\xA4\x40\x20\x08\x8A\x21\xB9\x6C\x8E\xFC\xF8\x18\xF9\xF1\xA8\x2B\x0C\xC5\x53\x6B\xD6"
+ "\x3C\x9A\xB9\x6D\x80\xBD\x7B\xDF\xDA\x6A\xBB\xE1\x16\x11\x4B\x52\x5B\x9B\xC2\xB2\x2C\x6C\x4B\xA1\x94"
+ "\x42\x08\x81\x10\x82\x7C\x21\xC0\xB1\x2D\xA4\x92\x58\x4A\x62\x8C\x21\x9F\x0F\x18\x19\xFC\x9C\xD1\xA1"
+ "\x7C\x4F\x18\xF2\xC8\xDA\xB5\x8F\x4D\x0B\x42\x02\xEC\xDE\xDD\xD1\x64\xC8\x6E\xC1\x4D\x50\x5B\x9B\x22"
+ "\xE6\x3A\xF8\x7E\xAC\x3C\x62\x31\x87\x58\xCC\x21\x99\xF0\x28\x04\x45\x82\x42\x40\x10\x84\x48\x29\x49"
+ "\x26\xE3\xCC\xBE\xFB\x6E\xFC\x19\x76\x3A\x0C\x8B\x5B\xA6\xAB\x80\x04\x30\x26\xB7\x5B\x7A\xD7\x9D\x7B"
+ "\x9E\x8B\xEF\xC5\x88\xC7\x3D\xE2\xBE\x47\x22\xEE\x93\xCB\x15\xF0\xFD\x18\xA9\x19\x09\x6C\xC7\x46\x59"
+ "\x0A\xAD\x35\x00\xC9\xB8\x47\xFD\xFC\x7A\x84\x15\x6E\xDC\xB5\x6B\x7F\xD3\xB4\x00\x76\xEC\xD8\xBB\xDE"
+ "\xC8\xA8\x21\x55\x3D\x21\xBB\x63\xE3\x38\xA5\x88\x3D\xD7\xC5\x77\x1D\x7C\xD7\xC1\xB1\x2D\x0A\x85\x22"
+ "\x89\xB8\x8F\xEB\xD8\xB8\x13\xF3\xA4\x94\x48\x55\x52\x62\xE1\x3D\xF3\x08\xC3\xE0\xC5\x69\x01\x68\x9D"
+ "\x5B\xED\xF8\x09\x3C\xCF\x45\x29\x85\x6D\x95\x86\x63\x59\x38\x96\x45\xCC\x71\x88\x39\x0E\xB6\x63\xA3"
+ "\xB5\x2E\x3B\x77\xDD\xEB\x43\x4A\x89\xED\xD8\xCC\x9A\x53\x47\x14\xE5\x9A\xB7\x6D\x6B\x4B\x55\x0C\x10"
+ "\x86\xF9\xA6\x99\xB5\xB5\x48\x29\x51\xB2\x54\x6C\x93\x95\xAF\x94\x2A\x47\xA9\xB5\xC6\xB6\x6D\x04\x02"
+ "\xDB\xB1\xB1\x2D\x1B\xC7\xB2\xB0\x95\xC2\x56\x0A\x25\x04\xBE\xEF\x93\xAA\xAD\x22\x0C\xA3\x74\xC5\x00"
+ "\xB1\x98\x95\x52\x4A\xDD\xB0\xCF\x0D\xA6\xF4\x34\x86\x7C\x21\x60\x60\x68\x18\xDB\x52\x25\xD9\xED\x92"
+ "\x53\x4B\x95\x00\xA7\x0E\x4B\x49\x66\xCF\xAA\xA6\x50\x08\x2A\x06\xB0\x5C\xD7\xC6\xB2\x2C\x84\x10\x20"
+ "\x20\xD2\x86\xC1\x4B\xA3\xF8\x9E\x83\x6D\xD9\x18\x0C\xB6\x6D\xE3\x38\x16\x55\x71\x9F\x28\x8A\xAE\xF7"
+ "\x06\x28\xFD\x07\x18\x63\xD0\x80\xD6\x9A\x20\x08\x2B\x4F\xC1\xC8\xC8\x08\x51\x14\x95\xF6\x3A\x02\x4B"
+ "\x49\x92\x09\x8F\x30\xD4\x84\x51\x58\x8A\xCC\x92\x24\x62\x31\x94\x52\x84\x5A\x63\x49\x89\x25\x6F\xA2"
+ "\x80\x94\xE8\x28\xA4\x50\x28\x56\xDC\x0B\xAC\xE1\xE1\x51\x82\x20\x40\x4E\xB4\xA4\x2B\x63\xD7\x98\x51"
+ "\x15\x67\xE6\xCC\x2A\xA4\x90\x65\xC9\x35\x90\xCD\xE7\xCB\x8E\xA5\x94\xA5\x7A\x99\x58\x68\x32\xFA\xB3"
+ "\x7D\xE7\x09\x82\xA0\xA7\x62\x05\x72\xB9\xE8\xE0\xC8\xE5\x4B\xE5\x6E\x67\x5B\x8A\x6C\x36\x4F\xE6\xCA"
+ "\x38\xD7\xB2\x39\xB2\xB9\x3C\xD9\x20\x20\x0C\xC3\xEB\xD2\x4B\x89\x12\xA2\xA4\x84\x65\x95\xA3\x0F\x0A"
+ "\x01\xBD\x27\xCF\x50\x2C\x46\xD3\x01\x30\x1D\x9F\x9E\x38\x41\x50\x0C\x41\x80\xE3\x3A\x65\x18\x21\x44"
+ "\xB9\xF7\x4F\xE6\x7A\xF2\xFB\xE4\x2E\x99\xAA\xC8\xF1\x8F\x8F\x93\xCD\xEA\x83\xAF\xBD\xF6\x52\xC5\x29"
+ "\x90\xAD\xAD\xDB\xDA\x2E\x7D\x7E\xB1\xAF\xEF\x74\x1F\x46\x9B\x72\x75\x4B\x71\x8B\xB6\x39\x79\x88\x4C"
+ "\x05\x11\x82\x7C\x2E\xCF\xDB\x7F\x7E\x9B\x6C\x96\x96\x69\xB7\xE2\x7C\xDE\xDE\xD4\xFD\xC1\xDF\xC8\x64"
+ "\xC6\x00\xF0\x3C\xB7\x1C\xF1\x54\xD3\x53\xDE\x8D\x31\x18\x63\x08\xB5\x26\x32\x86\x37\xDE\x78\x13\x29"
+ "\x13\x34\x36\x2E\x58\x3D\x6D\x80\x3D\x7B\x5A\x0E\x8E\x5F\xCD\xFE\xE6\xF0\xA1\x0E\x46\x47\xAF\x60\x8C"
+ "\xC1\x71\x4A\xA9\x30\xDA\x60\x30\x65\x87\xC6\x94\x7A\x84\xD6\x9A\x28\x8A\x88\xA2\x88\x3D\xED\xAF\x73"
+ "\xFA\xB3\xB3\x2C\x59\xB2\x94\xAB\x57\xB3\xA9\xDB\xBE\x0F\x3C\xF7\xDC\xF3\xAF\xC6\x13\xC9\x8D\x0F\xAF"
+ "\x58\xC1\xBD\x8D\x0B\xF1\x62\x6E\x49\x62\xAB\xD4\xE9\x26\x73\x3E\x99\xFF\xD1\x91\x51\x3A\x0E\x74\x30"
+ "\x32\x3C\xC2\xF2\xE5\x8F\x70\xF6\xEC\x65\x92\x49\x3F\x33\x6B\x56\x75\x8B\x77\x74\x63\xBD\x08\x32\x99"
+ "\x65\x2F\x1D\xDF\x34\xAD\x1B\xD1\x86\x0D\x2F\x34\x0B\x61\x5E\x9D\x3B\x6F\x5E\xC3\xD2\x07\x1F\x60\xF1"
+ "\x7D\x8B\x71\x9C\xD2\x61\x34\xB9\x03\x06\x2E\xF4\x73\xF4\x9F\x47\x39\x76\xF4\x18\x96\xE5\xB4\x3D\xF4"
+ "\x50\xD3\xFA\x53\xA7\x06\xFA\x96\x2D\xBB\xBF\x21\x97\x2B\x90\x38\xFF\x3A\xA9\xF1\xBF\x62\x8A\x59\x46"
+ "\x72\xC9\xB6\xEF\xBF\x7C\xE2\xD9\x8A\x01\xA6\xA8\xB1\x1E\x58\x07\x34\xD5\xD4\xD4\x10\x4F\x26\x89\x8A"
+ "\x45\x06\x07\x2F\x13\x86\x41\x0F\xD0\x15\x04\x76\x4B\x7B\xFB\x8E\xBE\xCD\x9B\x77\xA5\x5F\x79\xE5\xF9"
+ "\x9E\xED\xDB\xDB\x0F\xDC\xEF\xBE\xDF\x3C\x27\x31\xC8\x82\xFA\x18\x41\xFF\x11\xCE\x9C\x2B\x72\xF9\x5A"
+ "\x55\xDB\xE3\xDB\x6F\x0E\x21\x2A\xC9\xD3\x86\x0D\x2F\x34\x08\x61\x1A\x8C\x11\xB4\xB6\xEE\xEC\xBA\xD5"
+ "\xBC\x3F\xBC\xB8\xF4\x40\x63\xFA\xDE\xE6\xF4\x0F\x7F\x4A\xF1\xE2\x47\x04\xFD\x47\x08\xFA\xBB\xE9\xFD"
+ "\xAC\xC8\xC0\x95\x64\xDB\xD3\x2D\x5F\x86\xB0\x2A\x01\x68\x6D\xDD\xD9\x07\xF4\xFD\xB7\x79\x51\x90\x6D"
+ "\x48\x79\x43\xA8\xE0\x1C\xCC\xFD\xF6\x44\x7C\x82\x45\x74\x13\x9C\x1C\x5B\xDF\xFE\x93\xC5\xAC\xFB\xDD"
+ "\xC9\x1B\x20\x14\x77\xD0\x9E\x48\xD7\xEE\x3B\x7D\xEA\xEA\xCA\x84\x39\x53\x77\x57\x7D\x3D\xA2\xFA\xEB"
+ "\x08\x51\x72\x71\x97\x3B\xC8\x58\x26\x9B\xFE\x6E\xE3\xD7\x1A\xFE\xD4\x33\xD4\xF1\x95\x00\x1C\x3A\x3A"
+ "\x94\xFF\xC1\x37\x6A\xF6\x7D\xFA\xC9\xD8\xCA\x24\xA7\xEB\x66\xCF\xAF\x47\x54\xDF\x87\x90\x12\x04\xD4"
+ "\xF9\x97\xC8\x8C\x64\xD3\x0F\xCE\x9F\xDB\x70\xF8\xDF\xC3\x1D\x37\xD4\x80\xF7\x21\xE6\xA6\xAB\xFE\x1D"
+ "\x72\x3F\xAB\xAC\x56\x26\x6D\xFB\xD3\x8B\x52\x91\xA6\xF3\xF1\x27\xE6\xA4\x97\x3C\xF6\x0C\x3A\xB6\x80"
+ "\x60\xE0\x18\x41\xFF\x11\x8A\xFD\xDD\x74\xFE\x23\x47\xEF\xC5\x44\xDB\xE6\x03\xBD\xCF\xDE\x00\xF0\xC7"
+ "\x7B\x7E\xF5\xA5\xC5\x56\xFD\xFE\xE5\x69\x03\x00\x6C\x5D\xB5\x28\x15\x69\xD3\xD9\xFC\xD4\x9C\xF4\xD2"
+ "\x55\xCF\xA0\xBD\x85\x04\x17\x7B\x26\x20\x8E\xF0\xEE\xFB\x39\x3E\x3E\x1F\x6F\xBB\x0E\xF0\xEB\x5B\x28"
+ "\x00\xB7\x05\x00\xF0\x8B\x15\x8D\x29\x63\xE8\x5C\xB3\xA6\x2E\xFD\xC0\xEA\xB5\x68\xAF\xB1\xAC\xC4\x85"
+ "\x7F\x75\xD3\xFE\x8E\x77\x7B\x0B\x4F\xC7\x7E\xFE\x68\x63\x0A\xE8\x7C\xF2\xC9\xD9\xE9\xEF\xAD\x59\x8B"
+ "\xF6\x17\x71\xAE\xFB\x2F\xB4\xEF\x7C\x8B\xD8\x37\x7F\x7C\x67\x8B\xF0\x66\xF6\xE1\xE9\xE1\xFC\xF2\x05"
+ "\x35\xFB\x7A\x7B\xAF\xAD\x1C\xBD\xF0\x49\x5D\x4D\x8D\x43\xFB\x6F\xDF\xE3\x5B\x3F\xFA\x25\x1F\x1D\x1F"
+ "\xCA\x7C\xE5\x0A\x7C\x51\x09\x2D\xEC\xF4\xCC\xEF\xAC\xE3\xEC\xA5\x62\x26\x93\xB9\xBA\x49\x18\x63\xF8"
+ "\x7F\xDA\x7F\x00\x35\xAE\x9C\x9A\x49\xED\xBD\xC2\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1783,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x13\x00\x00\x0B\x13\x01\x00\x9A\x9C\x18\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD4\x07\x18\x0F\x35\x31\x9A\x45\xD2\x48\x00\x00\x06\x84\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x96\x6D\x8C\x15\x57\x19\xC7\x7F\xE7\xCC\xCC\x99\x99\xFB\xB2\x5C\x70\x0B\x05\x8A\x2C\xD2\x02"
+ "\x9A\xB6\xAE\x14\xD7\x20\x6D\xB2\xDB\x6A\x1B\x5B\x09\x60\x0A\xB5\x69\x94\x6D\xFC\xA0\x7E\x30\x85\xD0"
+ "\x54\x13\x9B\x42\x10\x93\x42\x82\x48\xF8\xA0\x46\xEB\xEE\x52\x52\xB2\xD2\x16\xB6\x0D\x16\x68\x52\xA8"
+ "\x52\x8D\xA0\xB0\xD1\xF0\x26\x95\x2E\x94\xE5\x75\x61\x2F\xCB\x72\xEF\x9D\xB9\x33\xE7\xF8\x61\xD8\xCB"
+ "\x5A\x40\xEF\xA5\x4D\x7C\x92\x93\x99\x9C\x9C\x39\xCF\xEF\xF9\x3F\xE7\x79\xE6\x08\x6E\x62\xDB\xB7\xBF"
+ "\xD7\x6A\x59\x66\x8E\x94\x34\xFB\xBE\x9B\xF3\x3C\x45\x14\x45\x0C\x0E\x16\xD0\x9A\x5D\x5A\xD3\xA5\xB5"
+ "\x6C\x7F\xE4\x91\x59\x79\x3E\x86\x89\x8F\x4E\x74\x75\xBD\xDB\xAC\x94\x6E\xD3\x44\x0D\x11\x12\x37\x95"
+ "\xC6\x18\x83\x94\x12\x29\x25\x5A\x6B\x6C\x01\x71\x39\x80\x28\xCC\x47\x91\x5C\xFB\xE8\xA3\x0F\x2E\xFB"
+ "\x44\x00\x5E\x7B\xED\xED\x65\x8E\x8A\x97\x96\x85\x45\x2A\x93\x21\x93\x49\x55\x1C\x4B\x01\x52\x4A\x84"
+ "\x14\x08\x04\x61\x39\xA2\x58\x28\x12\x0C\x5E\x22\x0A\xC2\x5D\x41\x60\xCD\x7B\xFC\xF1\x87\xF3\xB7\x0C"
+ "\xB0\x71\xE3\xEF\x97\x39\x6E\xB4\x54\x78\x59\xEA\xEB\x73\xD8\xB6\x8D\x63\x5B\x58\x96\x85\x10\x02\x21"
+ "\x04\xA5\x20\x44\x39\x36\xD2\x92\xD8\x96\xC4\x18\x43\xA9\x14\x72\xF1\xEC\x19\x0A\x97\x07\xBA\x8B\x45"
+ "\xBB\xE5\xA9\xA7\xBE\x5E\x13\x84\x04\x68\x6B\xEB\x6A\x36\x14\x96\xE2\x66\xA8\xAF\xCF\xE1\xB9\x8A\x54"
+ "\xCA\xAB\x0C\xCF\x53\x78\x9E\x22\x9B\xF1\x09\xC2\x32\x61\x10\x12\x86\x11\x52\x4A\xB2\xD9\x34\x63\x26"
+ "\x4C\xC0\xF1\xFC\x46\x21\x0A\x4B\x6B\x55\x40\x02\x18\x53\x68\x93\xFE\x35\xE7\xBE\xEF\x92\xF2\x3D\xD2"
+ "\x69\x9F\x74\xCA\x27\x93\x4E\x51\x2C\x06\xA4\x52\x1E\xB9\x11\x19\x1C\xE5\x60\xD9\x16\x5A\x6B\x00\xB2"
+ "\x69\x9F\x09\x93\x26\x61\x30\x8B\x5E\x7A\x69\x63\x73\x4D\x00\xEB\xD6\xBD\xD2\x6A\xA4\x6E\xC8\x8D\xBC"
+ "\x2A\xBB\x72\x50\x2A\x89\xD8\x77\x5D\x52\xAE\x22\xE5\x2A\x94\x63\x13\x04\x65\x32\xE9\x14\xAE\x72\x70"
+ "\xAF\xAE\x93\x52\x22\xAD\x44\x89\x4F\x4F\x6A\x40\xEB\xD2\x33\x35\x01\xC4\x71\x69\x8E\x4A\x65\xF0\x7D"
+ "\x17\xCB\xB2\x70\xEC\x64\x28\xDB\x46\xD9\x36\x9E\x52\x78\x4A\xE1\x28\x07\xAD\x75\xC5\xB9\xEB\x5E\x1B"
+ "\x52\x4A\x1C\xE5\x30\x7A\xEC\xED\x84\x61\x38\x77\xF5\xEA\x5F\xE7\x6A\x00\x28\x36\x8F\xAA\xAF\x47\x4A"
+ "\x89\x25\x93\xC3\x36\x74\xF2\x2D\xCB\xAA\x44\xA9\xB5\xC6\x71\x1C\x04\x02\x47\x39\x38\xB6\x83\xB2\x6D"
+ "\x1C\xCB\xC2\xB1\x2C\x2C\x21\x48\xA5\x52\x8C\xC8\x8D\x00\xC2\xC6\xAA\x01\x5C\xD7\xCE\x59\x96\xF5\x1F"
+ "\x75\x6E\x30\xC9\xD3\x18\x4A\x41\xC8\xE9\xBE\x0B\x38\xB6\x95\xC8\xEE\x24\x4E\x6D\x2B\x01\x1C\x3E\x6C"
+ "\x4B\x52\x7F\x5B\x3D\x61\x58\xAA\x1A\xC0\x76\x5D\x85\x6D\xDB\x08\x21\x40\x40\xAC\x0D\x67\xCF\xF5\x93"
+ "\xF2\x15\x8E\xED\x60\x30\x38\x8E\x83\x52\x36\x75\xE9\x14\x71\x1C\x5F\xEB\x0D\x90\x7C\x07\x18\x63\xD0"
+ "\x24\xDF\x47\x51\x58\x7D\x0A\x2E\x5C\xE8\x27\x8E\xE3\xA4\xD6\x11\xD8\x96\x24\x9B\xF1\x89\x22\x4D\x14"
+ "\x47\x49\x64\xB6\x24\xE3\x79\x58\x96\x45\xA4\x35\xB6\x94\xD8\xF2\x06\x0A\x48\x89\x8E\x23\x82\xA0\x5C"
+ "\x75\x2F\xB0\xFB\xFA\xF2\x84\x61\x88\xBC\xDA\x92\x2E\x0D\x5C\x61\x44\x5D\x9A\x51\xA3\xEA\x90\x42\x56"
+ "\x24\xD7\x40\xA1\x54\xAA\x38\x96\x52\x26\xE7\xE5\xEA\x46\x1A\xD0\x5A\x73\xE2\xF8\x09\x4A\xA5\xA8\xBB"
+ "\x6A\x05\x8A\xC5\x78\xCB\xC5\xF3\xE7\x2A\xDD\xCE\xB1\x2D\x0A\x85\x12\xF9\x4B\x83\x5C\x29\x14\x29\x14"
+ "\x4B\x14\xC2\x90\x28\x8A\xAE\x49\x2F\x25\x96\x10\x89\x12\xB6\x5D\x89\x3E\x0C\x42\xDE\x3F\xFA\x3E\x41"
+ "\x60\xAA\x07\xB8\x72\x85\xAE\xA3\x87\x0E\x11\x96\x23\x10\xA0\x5C\x55\x81\x11\x42\x54\x7A\xFF\x50\xAE"
+ "\x87\xE6\x87\xAA\x64\xB8\x22\x07\x0F\x1C\x24\x0C\xC3\x2D\xEB\xD6\xFD\xA4\xEA\x14\xC8\xF6\xF6\x9F\xB6"
+ "\x9F\x3C\x71\xBE\xA7\xE7\x58\x0F\x46\x9B\xCA\xE9\x96\xE2\x26\x6D\x73\xE8\x27\x32\x1C\x44\x08\x4A\xC5"
+ "\x12\x6F\x6D\x7D\x8B\x42\x81\xB5\x35\xB7\xE2\x62\xD1\x5D\xFC\x97\xDD\xEF\x91\xCF\x0F\x00\xE0\xFB\x6E"
+ "\x25\xE2\xE1\xA6\x87\xBD\x1B\x63\x30\xC6\x10\x69\x4D\x6C\x0C\xAF\xBE\xFA\x3A\x4A\x79\x4C\x9C\xF8\xD9"
+ "\x39\x35\x03\x74\x76\xAE\xDA\xD2\x77\x2E\xFE\xF9\xF6\x37\xBA\xE8\xEF\xBF\x84\x31\x06\xA5\x92\x54\x18"
+ "\x6D\x30\x98\x8A\x43\x63\x92\x1E\xA1\xB5\x26\x8E\x63\xE2\x38\x66\x7D\xC7\x06\x7A\x3E\xE8\xE1\xEE\xBB"
+ "\x67\x30\x30\x50\xCC\xDD\xF2\x7D\xE0\xC9\x27\x9F\x5D\x73\xDB\x18\x7B\x51\xCB\xC3\x0F\x71\xD7\x94\xC9"
+ "\xF8\x9E\x9B\x48\x6C\x27\x9D\x6E\x28\xE7\x43\xF9\xEF\xBF\xD8\x4F\xD7\xE6\x2E\xFA\xCE\xF7\x73\xFF\xFD"
+ "\xCD\x1C\x3F\x7E\x9E\x6C\x36\x95\x1F\x3D\x7A\xE4\x5A\x7F\xDF\xA2\x89\x22\xCC\xE7\x67\xFE\xF8\xE0\xE2"
+ "\x9A\x6E\x44\x0B\x16\xFC\x70\xAE\xE7\x95\xD6\x4C\x9A\x3C\xBA\x61\xFA\x17\x67\x30\xED\x73\xD3\x50\x2A"
+ "\xF9\x19\x0D\x55\xC0\xE9\x93\xBD\xEC\xFB\xEB\x3E\xF6\xEF\xDB\x8F\x31\xE9\xF6\x59\xB3\x1E\x68\x3D\x76"
+ "\xAC\xB7\x67\xE6\xCC\x7B\x1A\x8A\xC5\x80\xCC\x87\x1B\xC8\x0D\xBE\x83\x29\x17\xB8\x58\xCC\xB6\x3F\xB8"
+ "\xFC\xD0\xD3\x55\x03\x0C\xD9\x13\x4F\x3C\xD7\xEA\x38\xE5\x85\xB6\x1D\x35\x8F\x1E\x33\x92\x6C\x5D\x9A"
+ "\xB8\x5C\xE6\xCC\x99\x3E\x4A\xA5\xB8\x3B\x8A\xEC\x5D\xE5\xB2\xB3\xB6\xB3\x73\x55\xCF\xF3\xCF\xFF\xA2"
+ "\x71\xC5\x8A\xEF\x77\xAF\x5C\xD9\xB1\xF9\x1E\x77\xF7\xDC\xB1\x99\xB3\x7C\x66\xA2\x47\xD8\xBB\x87\x0F"
+ "\x4E\x94\x39\x7F\xA5\xAE\xFD\xB1\x95\x37\x86\x10\xD5\xE4\x69\xFE\xFC\x1F\x35\x00\x0D\x00\x9B\x36\xBD"
+ "\xB8\xEB\x66\xEB\x5E\x79\x66\xFA\xE6\x29\x8D\x77\xCD\x6D\xFC\xC6\xF7\x28\x9F\xFA\x1B\x61\xEF\x1E\xC2"
+ "\xDE\xBD\x1C\xF9\x57\x99\xD3\x97\xB2\xED\xF3\xD7\x5E\x0F\x61\x57\x03\xB0\x69\xD3\x8B\x3D\x40\xCF\xFF"
+ "\x5A\x17\x87\x85\x86\x9C\xDF\x87\x15\x9E\x80\x71\xF7\x5D\x8D\x4F\x30\x95\xBD\x84\x87\x07\x5A\x3B\xBE"
+ "\x3B\x8D\x85\xBF\x3A\xFC\xF4\xCD\x4A\x3B\x29\xC1\x3F\x61\x86\x46\xAD\xD7\xAB\xB0\x4C\xCB\x3B\x3B\x7A"
+ "\xBB\x8F\xEC\x58\x8F\x15\x1C\xC7\x19\x37\x1D\x35\xFE\x4B\xA8\xF1\x4D\xDC\x3B\xCD\x65\x4C\xF6\x72\xEB"
+ "\x2F\x5B\xA7\xB5\xFD\x57\x00\x80\x37\xEF\x7C\x01\xFE\x5C\xFB\x15\xFB\x3B\xBF\x39\x9C\x0F\x42\xD3\xB2"
+ "\x6D\xEB\xC9\xEE\x03\xDB\x3A\xB0\x82\x9E\x04\xE2\x8E\x26\x9C\x3B\x9A\x98\x71\xAF\xC7\xB8\x11\x97\x5B"
+ "\x7F\xF6\xCD\xA9\x6D\xD7\x01\xDC\x28\x6A\x7F\x35\xC6\x5F\x5D\x9B\x12\x3F\xD8\x70\x24\x1F\x94\x69\x79"
+ "\xA3\xEB\x54\xF7\xDF\xB7\x76\x60\x95\x8E\xA1\xC6\x26\x4A\x38\xE3\x9B\xF8\xF2\x7D\x3E\x13\x3E\x35\xD8"
+ "\xBA\x62\x5E\x02\x21\x86\x03\xBC\x79\xE7\x0B\xD7\x6D\x38\xFB\xE5\xE5\x14\x97\x54\x77\x58\x87\xDB\xB2"
+ "\xD9\x53\x73\xB1\x36\x3B\xE7\xCE\x1B\xDB\x38\x7D\xF6\xB7\xD1\xFE\x64\xC2\x53\xDD\x84\xBD\x7B\x28\xF7"
+ "\xEE\x61\xC7\xEE\x22\x07\x3E\x4C\xB7\x8B\xE1\xD1\x02\x30\x33\x49\xC1\xEC\x97\x97\x57\x36\xBB\x15\x00"
+ "\x80\xE7\xBE\x3A\x25\x67\x0C\x3B\x17\x2C\xB8\xBD\x71\xC6\x9C\x6F\xA1\xFD\x29\x84\xA7\xF7\x13\xF6\xEE"
+ "\xE1\xE4\x3F\xF6\xD2\xB1\xCD\xBF\x96\x82\xE2\x12\xC4\x47\x1D\xDD\x68\xAE\x16\x5B\xF5\xF6\x3F\xF3\x06"
+ "\x5A\x3A\x7F\x77\xA6\xFB\x8F\x9D\xEB\x91\x85\x23\xA8\xB1\x5F\xE0\xA2\x99\xCC\xA6\x3F\xD4\x31\xAA\x69"
+ "\xE1\xF5\x9B\x0F\xCF\xF9\xC7\x71\x3E\xDC\x9E\xFD\xCA\x94\x1C\xB0\x73\x46\x53\x7D\xE3\x03\x73\xBE\xC6"
+ "\x6F\xD7\x6C\xE3\xF3\xF3\x96\xB0\xED\xDD\xA3\xF9\x4F\xC4\x41\x2D\x10\x5A\x38\x8D\xA3\x9A\x16\x72\xFC"
+ "\x5C\x39\x9F\xCF\x5F\x5E\x2C\x8C\x31\xFC\x3F\xED\xDF\x59\x90\xA8\x1E\xB1\x5A\x60\x2B\x00\x00\x00\x00"
+ "\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1567,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x0D\x00\x00\x0B\x0D\x01\xED\x07\xC0\x2C\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD3\x0A\x09\x13\x22\x05\xA6\x7E\x3C\x8C\x00\x00\x05\xAC\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x97\x5D\x6C\x1C\xD5\x15\xC7\x7F\x73\x67\x67\x3F\xEC\x64\x6D\x6F\x0C\x09\x36\x21\x09\x35\x91"
+ "\xD3\x7C\xC8\xF1\xB4\xA8\x6A\x08\x6D\x2A\x25\x91\x22\x24\x04\xA2\x6F\x40\x21\x60\xA8\x51\xC4\x53\xC8"
+ "\x43\x91\x90\xE0\xA1\x7D\xE4\xA1\x7D\x00\x56\x0E\x4D\x05\x0F\xED\x03\xFD\x78\xE0\x01\x82\x22\x11\x3E"
+ "\x5A\x09\x6F\xB0\x03\xB4\x02\xB6\x4A\x00\x67\x4D\xFC\xB1\xBB\xCE\xEE\xCE\xEC\xDE\x99\x7B\xFB\x30\xB3"
+ "\xEB\x5D\x3B\xEB\x35\x11\x52\x8F\xF4\x97\x66\xEE\x7F\xEE\x39\xE7\x9E\x7B\xE6\x9C\x7B\xE1\xFF\x2C\xC6"
+ "\x77\xF9\x78\x74\x7C\x6A\x07\xE8\x43\xA0\x46\x80\x11\xB4\x6A\xD2\xA1\xA7\xD1\x6A\x1A\x25\xCF\xD9\x9C"
+ "\xC9\x02\x2A\x9D\x4E\xEB\xEF\xC5\x81\xD1\xF1\xA9\x47\x81\x47\x80\xBB\x41\x03\x0A\x44\x14\x44\x3C\xF8"
+ "\x40\xB9\xE0\xBB\xCD\x53\x3E\x40\x79\xAF\xD9\x7A\xE2\x34\x20\xD3\xE9\xB4\xBA\x21\x07\x46\xC7\xA7\xF6"
+ "\x63\x88\x17\xD1\xEA\x67\x08\x13\xA2\xBD\x10\x4D\x11\x8D\x25\xD8\x9A\x5C\xE2\xC7\xB7\xE6\x01\x28\xB9"
+ "\xF0\xCE\xA5\x6D\x38\x6E\x0D\xAA\x73\xE0\x2E\x80\x96\x80\x76\xF0\xDD\x93\x36\x7F\xFA\x23\xE0\x5E\xCF"
+ "\x11\xA3\xC3\xAA\x4F\x03\x90\xD8\x42\x74\xC3\xCD\x3C\x76\xE7\x0C\x7B\x6F\xDF\xC0\xCE\x5B\xBB\x88\x47"
+ "\xC5\xAA\x39\x33\xF3\x55\xFE\xF9\xEF\x22\xE7\xFF\x03\x1F\x5D\xB2\xA0\x7C\x39\x20\xFC\xDA\x5F\x6D\x5E"
+ "\x7D\x1C\x58\x4A\xA7\xD3\x5E\x47\x07\x1A\xC6\xCD\x18\x24\x77\xF2\xE0\xFE\x6F\xB8\xF7\x40\x3F\x7D\x1B"
+ "\x22\x6D\xA3\xA5\x57\xA8\x3A\x7F\xB1\xC0\xCB\xE7\x2C\xBE\x9D\x9D\x05\xAF\x04\x4A\x4E\xDB\xFA\xF4\x11"
+ "\x60\xAE\x39\x12\x66\x5B\xE3\x91\x2E\xB6\x6E\xBD\x85\x93\x47\x4B\x1C\xFE\x51\x0A\x2B\x22\xF0\x14\x6D"
+ "\xE1\x2B\xDD\x82\xC1\xFE\x18\x07\x87\x21\x5F\xF2\xB8\x34\x67\x80\xF6\x37\xE7\xF4\xEE\x1F\x0E\x30\xF5"
+ "\x77\xDB\xB6\xBD\x4C\x26\xA3\x57\x39\x30\x3A\xFE\xF1\x7E\x30\xDE\xC4\xB4\x18\x1C\x1C\xE4\xD4\x3D\x9A"
+ "\xED\x9B\xE3\x48\x4F\xDF\x10\x22\xA6\xC1\xDE\xED\x09\xAE\x2E\x29\xBE\x5E\x00\xD0\x77\xE4\xE4\x8E\x0F"
+ "\x07\xC4\x67\x5F\x87\x4E\xB0\x72\x23\x5F\x05\x1F\x92\xC3\x1C\x3F\xE8\x92\xEC\x8A\x50\xA9\x6A\x7E\xFB"
+ "\x86\x43\xA5\xAA\xDB\x62\x2D\x5E\x69\x78\xF8\x50\x92\xA1\xDB\xFA\x02\x0B\xD1\xDE\xE7\x81\x3E\x20\xD2"
+ "\x12\x81\xD1\xF1\xCC\xA3\xA0\x9F\x24\x31\xC0\x43\x77\xE6\xD9\xB5\x6D\x03\xD2\xD7\x48\x5F\xF3\xD4\xB1"
+ "\x5E\x7E\xF3\xFA\x35\xF6\x6D\x33\x1A\x63\xCD\xE8\xC4\x6B\x60\x7B\xBF\xE2\xDD\x6C\x2F\xC8\xA5\x5B\x72"
+ "\x6A\x57\x61\xC0\x98\xBE\x60\xDB\x76\x6D\x39\x02\x5A\x3D\x02\x26\x9B\xFB\x37\x32\xBC\xAD\x9B\xB2\xAB"
+ "\x1A\x00\x98\x38\x91\xE2\x95\xB3\xB2\x65\x7C\xBD\x7C\xD9\x55\x24\xBB\x2D\xEE\x1B\x29\x82\x61\x81\x19"
+ "\xBF\x1F\xE8\x05\x2C\x01\x30\xFA\xEB\x8F\x76\x00\x77\x13\xDF\xC4\x2F\x86\x16\xF0\x7C\xA8\x54\xFD\x06"
+ "\xEA\x32\x71\x22\xC5\xEB\xEF\xF9\x2D\xDC\x7A\xF8\x62\xD9\xE3\xBF\xB9\x0A\x1A\x13\xE2\x9B\xC0\x30\x47"
+ "\x26\xAB\xC7\x76\x01\xF1\xFA\x7F\x75\x28\xD8\x9F\x14\xFD\xC9\x25\xCA\x4E\xDB\xC2\xC5\xC4\x89\x14\x8F"
+ "\xFD\x61\x91\x23\x7B\x54\x47\x7E\x76\xD1\xE5\xAB\x45\x83\x7F\xCD\x0C\x2E\x7F\x10\x75\xC0\x99\x05\xAB"
+ "\xE7\x00\x70\xA1\xBE\x05\x23\x00\x5B\x7A\x14\x1A\xDA\xAE\xB0\xD9\xC8\x5B\x9F\x88\x8E\xFC\x62\xC9\x6F"
+ "\x35\x0E\x44\x63\x89\xE0\x41\x44\x87\x81\xC4\xB2\x03\x66\x9C\xBE\x44\x8D\x92\xA3\x56\xA1\xDD\x4A\xDF"
+ "\xFB\xC2\x5A\x93\xFF\x66\x69\x23\x86\x01\x46\x53\x8D\x32\x05\x41\x1E\x08\x6B\x08\x88\x2F\x27\xA1\x88"
+ "\x93\x8C\xD5\x28\x57\x55\x03\x9D\x64\xE2\x44\x0A\x57\xAE\xBD\x5D\x00\x5A\xB7\x3A\x41\xA4\x1B\xB4\x36"
+ "\x1A\x49\x58\x2F\xC9\x65\x19\xE5\x9A\x43\x03\xEB\x91\x67\x7E\x39\xB8\x26\x7F\xFE\xB9\x15\xC6\x5B\x45"
+ "\x2C\x17\x77\xE5\x92\x77\xE2\x44\xC4\x72\x0B\x9F\x2D\x75\x76\xE0\xE0\x0B\x81\x91\xB5\xF8\x46\xE3\xA9"
+ "\x3B\xE2\x95\x97\x83\xD1\x38\x4C\xF8\xEE\x5D\x85\x6A\x0C\x4F\x47\xD6\x7D\x40\x69\x56\xBE\x1E\x3E\x22"
+ "\x40\xFA\x04\xAD\x5A\xCB\x2C\xA0\x22\x61\x11\x9A\xC6\x30\x29\x3B\x1E\x96\x19\xF9\xDE\x8D\x5B\x4D\x1D"
+ "\xC7\x71\x6B\x61\x8B\xAE\x66\x31\x91\x41\x0E\x28\x79\x0E\x80\xDA\x02\x42\x88\x55\x58\x29\x87\x7F\xF7"
+ "\xDD\x9C\x33\xC5\x32\xA8\x2D\x04\x83\xB5\x7C\x06\x70\x05\x40\x78\x86\xFB\x00\x67\x0E\xCB\x90\x24\x22"
+ "\xAD\x58\xA9\xDC\x95\x6B\x1B\xEF\x4B\xC8\x16\xD4\xF5\x58\x86\x04\x67\x0E\x94\x77\xD1\x4E\xBC\x75\x19"
+ "\x70\xEA\xF1\x56\x28\xEF\x35\x04\x3F\x5D\x2A\xCC\xF3\x83\xC1\xEE\x15\x6A\x2D\x00\x7E\xF5\xFB\x25\x6E"
+ "\xEF\xBB\x9E\xD9\x64\x07\x3E\x90\xEC\x4C\x39\xD8\x7F\xAF\xF4\x36\x26\xE5\x86\x03\xE9\x74\x5A\x8F\x8D"
+ "\x71\x7A\x92\x27\x1E\x76\x8A\x57\x7E\xA2\x36\x6F\xA7\xAF\xBB\xF5\x40\xFB\xF4\x2B\xF3\xF4\xC4\xDA\x2B"
+ "\xEF\xC4\xE7\xCB\x06\x4E\xF1\x4A\xB0\x7A\xF3\xCF\xFF\x00\x8A\x80\xDB\x9C\x71\x12\xDF\x3D\x85\x99\x78"
+ "\x37\x7B\x79\x86\xBB\xF6\xDD\x84\x65\x06\x4E\x3C\x7B\xE6\x0A\x1B\xD7\x50\xDE\x89\x97\xBE\x41\xF6\xF2"
+ "\x5C\xF0\xE2\xE6\x5E\x22\x46\x01\x28\x00\xB2\x91\x9F\x99\x4C\x46\xDF\x63\x47\x72\x39\xBD\x27\xEF\x2B"
+ "\x71\x74\xBE\x50\x65\x68\x20\x4A\xD4\x32\xB1\x4C\xE3\x86\x21\xF0\x78\x7F\x3A\x4F\xC5\x95\x50\xCB\xBF"
+ "\x68\x5B\x7F\x7B\x07\xC8\x01\x85\x74\x3A\xED\xAF\x4C\x71\xCF\xE6\xCC\xCB\xF8\xCE\xA9\x6B\x95\x1A\x67"
+ "\x27\xF3\xC8\xAA\x43\xCC\x12\x37\x04\x59\x75\x38\x3B\x99\xE7\x5A\xA5\x16\x18\x37\xFF\xF2\x06\xF0\x2D"
+ "\x90\x07\xBC\x55\x67\xC2\x4C\x26\x83\x6D\xDB\xFE\x00\x53\x53\x39\xBD\xBB\x28\x95\x79\xF8\xF3\x19\x17"
+ "\xA9\x04\x5B\x37\x09\xAC\x88\x20\x22\xE8\x08\x43\x7B\x4C\x7E\x59\xE1\xC3\x4F\x0B\x48\x4F\x35\x1B\xCF"
+ "\x01\x57\x01\xA7\x7E\x6B\xBA\x6E\x95\x1E\x1B\x1B\x13\x40\xD7\xA4\xF7\xC0\xCF\x89\xF6\x3E\x8F\x61\x8E"
+ "\xC6\x2C\xC1\x6D\x5B\xBA\xD8\x3D\xA0\x48\xA5\x7A\x30\x4D\xAB\x65\x8E\xEF\x4B\x16\x17\x8B\x7C\x7A\x45"
+ "\xF0\xD5\x6C\x85\xAA\x54\xA0\xBC\x8B\xB8\xB9\x97\xEC\xD8\x9B\x17\xC2\x95\x5F\x05\x2A\xCD\xC7\xF2\xB6"
+ "\x6D\x22\x74\x22\x0E\xF4\x4D\xEA\x07\x8F\x63\xC6\xEF\xC7\x30\x47\xEA\x7C\x22\x0A\xFD\x3D\x41\x0E\xCF"
+ "\x17\x3D\x9C\x5A\xD3\x64\xE5\x5D\xC4\x2B\xBD\x1D\x66\x7B\x01\x98\x0F\xC3\xBE\xEA\x76\xB4\xE6\xD5\x6C"
+ "\x6C\x6C\xCC\x08\xFB\x45\x37\xD0\x3B\x59\x3D\xB6\x0B\xAB\xE7\x00\x22\x3A\x8C\xB0\x86\xC2\x96\x1A\xB6"
+ "\x13\x99\xC5\xAF\x66\xA9\xE5\x33\x61\x91\x29\x87\xBF\x5A\x21\x7C\xF6\xAE\x77\x59\x5D\xD7\xE5\x34\x8C"
+ "\x86\x15\x46\x24\x11\x22\x1E\x8E\x89\x46\x31\x03\x09\xB8\x80\x13\xC2\xED\x74\x39\xFD\x1F\x79\x3A\x71"
+ "\x2E\xDF\x7C\x09\x0C\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+},
+
+{
+ 1557,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x0D\x00\x00\x0B\x0D\x01\xED\x07\xC0\x2C\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD3\x0A\x09\x13\x1F\x34\x9D\x48\x74\x08\x00\x00\x05\xA2\x49\x44\x41\x54\x78"
+ "\xDA\xC5\x97\x4B\x6C\x1C\x45\x1A\xC7\x7F\x5D\x3D\x3D\x0F\x3B\x19\x7B\x1C\xEF\x26\xB1\x09\x49\xC0\x44"
+ "\xCE\x66\x41\x8E\x1B\x38\x10\x02\x04\x14\x90\x22\xC4\x4B\x48\x5C\x02\xCB\x63\xAD\x5D\x1F\xB2\x27\x14"
+ "\xAD\xC4\x89\x95\x10\x48\x1C\x38\xEC\x1E\x80\x11\x81\x00\x17\x38\xF0\x3A\xE4\xC0\x43\x91\x40\x84\x87"
+ "\xF0\x04\x3B\x0A\xA0\x88\x11\x0E\xC4\x19\x27\x7E\xCC\x78\x32\x33\xDD\x3D\xD5\x5D\xB5\x87\x69\xCF\x8C"
+ "\xE3\x99\x38\xF1\x22\xAD\xA5\xBF\xE4\xA9\x7F\xD5\xF7\xFD\xBF\xAF\xAA\xBF\xFA\x0A\xFE\xCF\x7F\xC6\x95"
+ "\x4C\x1E\x1E\x1D\xDF\x0A\x7A\x0F\xA8\x21\x60\x08\xAD\x9A\x6C\xE8\x09\xB4\x9A\x40\xC9\xA3\x36\x87\xB3"
+ "\x80\x4A\xA7\xD3\xFA\x77\x11\x30\x3C\x3A\xFE\x04\xF0\x38\x70\x1B\x68\x40\x81\x88\x82\x88\xD7\x26\x28"
+ "\x17\x02\xB7\x79\xC9\x31\x94\xFF\xB6\xAD\x5F\x3B\x04\xC8\x74\x3A\xAD\x56\x25\x60\x78\x74\x7C\x27\x86"
+ "\x78\x09\xAD\x6E\x47\x98\x10\xED\x86\x68\x0F\xD1\x58\x82\x4D\xC9\x22\x37\x5D\x95\x07\xA0\xE4\xC2\x67"
+ "\x93\x9B\x71\xDC\x2A\x78\x33\xE0\xCE\x81\x96\x80\x76\x08\xDC\xA7\x6D\xDE\x7C\x03\x70\x5B\x09\x31\x56"
+ "\x88\xFA\x10\x00\x89\x0D\x44\xD7\xFC\x91\xA7\x6E\x9E\xE2\xFA\x6B\xD6\xB0\xED\xAA\x0E\xE2\x51\xB1\x6C"
+ "\xCD\xD4\xAC\xC7\xD7\x3F\x2E\xF0\xC5\x4F\xF0\xDD\xA4\x05\xE5\xD3\x35\x22\xA8\xBE\x6F\xF3\xFA\x5F\x81"
+ "\x62\x3A\x9D\xF6\x57\x14\x50\x77\x6E\xC6\x20\xB9\x8D\xFD\x3B\xCF\x70\xFF\xAE\x5E\x52\x6B\x22\x6D\xB3"
+ "\xA5\x2F\x32\xF5\xC5\x89\x02\xAF\x1C\xB5\x38\x37\x3D\x0D\x7E\x09\x94\x9C\xB0\xF5\xA1\xBB\x81\x99\xE6"
+ "\x4C\x98\x6D\x9D\x47\x3A\xD8\xB4\x69\x23\x4F\xDF\x53\x62\xEF\x8D\x3D\x58\x11\x81\xAF\x68\x8B\x40\xE9"
+ "\x25\xE8\xEF\x8D\xB1\x7B\x10\xF2\x25\x9F\xC9\x19\x03\x74\xB0\x3E\xA7\x77\xFC\xA9\x8F\xF1\x0F\x6D\xDB"
+ "\xF6\x33\x99\x8C\x5E\x26\x60\x78\xF4\xFB\x9D\x60\x1C\xC1\xB4\xE8\xEF\xEF\xE7\xE0\xBD\x9A\x2D\xEB\xE3"
+ "\x48\x5F\xAF\x0A\x11\xD3\xE0\xFA\x2D\x09\xCE\x17\x15\xBF\xCD\x01\xE8\xEB\x72\x72\xEB\x57\x7D\xE2\x87"
+ "\xDF\x42\x11\x5C\xBC\x91\xAF\x43\x00\xC9\x41\x9E\xDC\xED\x92\xEC\x88\x50\xF1\x74\x4B\x1C\xF9\xB6\xD0"
+ "\x96\x6B\xE6\x95\x86\xC7\xF6\x24\x19\xB8\x3A\x55\xF3\x10\xED\x7E\x16\x48\x01\x91\x25\x19\x18\x1E\xCD"
+ "\x3C\x01\xFA\x6F\x24\xFA\x78\xF4\xE6\x3C\xDB\x37\xAF\x41\x06\xBA\x25\xBE\x3C\x79\x81\x03\x0F\x6C\x64"
+ "\xF2\x9C\x7B\x59\xBC\x06\xB6\xF4\x2A\x3E\xCF\x76\x83\x2C\x6E\xCC\xA9\xED\x85\x3E\x63\xE2\xB8\x6D\xDB"
+ "\xD5\xC6\xA9\xD2\xEA\x71\x0C\x8B\xF5\xBD\x6B\x19\xDC\xEC\x52\x76\x5B\x7F\xBA\x27\x27\x2B\x1C\x78\x60"
+ "\x23\x40\xCB\x39\xED\xF8\x64\xA7\xC5\x83\x43\xB3\xBC\x7F\xCC\x02\x33\xFE\x10\x8A\xB7\x00\x27\x02\x30"
+ "\xFC\xF7\xEF\xB6\x02\xB7\x11\x5F\xC7\x9D\x03\x73\xF8\x41\x27\x7E\x10\x2C\x33\xFE\x4B\xCE\xAB\x1B\x07"
+ "\xA8\x78\xC1\x65\xF1\xD2\xD7\xCC\x15\xAB\x68\x4C\x88\xAF\x03\x67\x7A\x68\xCC\xDB\xB7\xDD\x8E\x1D\xC9"
+ "\x2F\x66\x60\x4F\x6D\x7F\x7A\xE8\x4D\x16\x29\x3B\xCB\x23\x3B\x5F\x90\x4B\x8C\x03\x4B\xE6\xB5\xE2\xB3"
+ "\x53\x15\x7E\x9D\x37\xF8\x66\xAA\xBF\x31\x18\x75\xC0\x99\x06\xAB\x6B\x17\x70\x7C\x51\xC0\x10\xC0\x86"
+ "\x2E\x85\x6E\x11\x59\xC9\x51\xCB\x8C\x37\x47\xD8\x8E\x9F\x2F\x05\x7C\x33\xB5\x79\xC9\x58\x34\x96\xA0"
+ "\x0A\x20\xA2\x83\x40\xA2\x21\xC0\x8C\x93\x4A\x54\x29\xB5\x88\xBE\x95\xF1\x45\xC7\x97\xE2\xCF\x14\xD7"
+ "\x62\x2C\x5E\x55\xE1\xB5\x64\x0A\xC0\xB0\x40\x04\x03\x28\xE2\x8D\x43\x28\xE2\x24\x63\x55\xCA\x5E\x43"
+ "\x40\x67\x4C\xB4\x35\xBE\x92\x38\x80\x53\xF3\x3D\x75\xE7\x86\xD1\x10\x41\xA4\x13\x3C\xC7\x00\xAC\x48"
+ "\x73\x49\x2E\xCB\x28\x17\x9C\x46\xA9\xFE\xE7\x23\xAB\x77\xBE\xA4\xDE\xB7\xBF\xF2\x44\xA3\x10\x29\x97"
+ "\xBC\x13\x67\xBA\x94\xA8\xE3\xA9\xFF\xCC\x5F\xD2\xF0\xEE\x7F\x5D\x61\xF3\x61\x84\x62\xFC\x72\x43\x41"
+ "\xBD\x99\x08\x5C\x0A\x5E\x8C\x5C\x69\xED\x12\xEC\x7B\x41\xFE\x6E\x22\x22\x22\xDC\x06\x2D\x41\xCB\x2C"
+ "\xA0\x44\x58\x84\x26\x6A\x9F\x95\x8F\x17\x98\xCB\x70\xD7\x73\xEA\x7F\x12\x61\x99\x35\x18\x06\xB5\x9E"
+ "\x01\x20\xF0\xB2\x80\xAC\x09\x50\xF2\x28\x00\xD5\x39\x84\x10\x2D\xB1\xF7\x79\x56\x2D\xC2\x14\x0D\x50"
+ "\x9D\xAB\x0D\x56\xF3\x19\xC0\x15\x00\x61\x0F\x77\x0C\x67\x06\xCB\x90\x24\x22\xAD\x71\xDF\x8B\x57\xB6"
+ "\x1D\xA9\x84\x24\x95\x68\xAC\xB7\x0C\x09\xCE\x0C\x28\xFF\x84\x9D\xF8\xF8\x74\xBD\x14\x03\x0A\xE5\xBF"
+ "\x8D\xE0\x96\x62\x61\x96\x6B\xFB\x3B\xDB\x3A\xF9\xCB\xBF\x1D\x0E\x1F\x48\x02\x70\x4D\xAA\xD8\x82\xA7"
+ "\xCE\xA7\xE2\xCE\x45\x95\xB1\x5C\xDB\x7F\xBF\xF4\x09\x26\x65\xC0\x11\x00\xE9\x74\x5A\xD7\x1A\x48\xFD"
+ "\xB5\xB3\x70\x16\xE5\x4B\xBA\x62\xD5\xB6\xF8\xC7\xAB\xB3\x00\x57\xC4\x2B\x5F\xE2\x2C\x9C\xAD\x45\x6F"
+ "\xBE\xF3\x11\xB0\x00\xB8\xCD\x3D\x96\x24\x70\x0F\x62\x26\x3E\xCF\x9E\x9E\xE2\xD6\x1B\xFE\x80\x65\xB6"
+ "\xEF\xAA\x9F\x39\x7C\x96\xB5\x31\x2E\x8B\x97\x81\x41\xF6\xF4\x4C\xED\x87\x9B\x7B\x99\x18\x05\xA0\x00"
+ "\xC8\x7A\x3F\x90\xC9\x64\xF4\xBD\x76\x24\x97\xD3\x7F\xCE\x07\x4A\xDC\x33\x5B\xF0\x18\xE8\x8B\x12\xB5"
+ "\x4C\x2C\xD3\x58\x35\x04\x3E\x5F\x4E\xE4\xA9\xB8\x12\xAA\xF9\x97\x6C\xEB\x83\xCF\x80\x1C\x50\x48\xA7"
+ "\xD3\xC1\xC5\x1D\x91\x6F\x73\xF8\x15\x02\xE7\xE0\x85\x4A\x95\x4F\xC7\xF2\x48\xCF\x21\x66\x89\x55\x41"
+ "\x7A\x0E\x9F\x8E\xE5\xB9\x50\xA9\xD6\x9C\x9B\xEF\xBE\x07\x9C\x03\xF2\x80\xBF\xAC\x27\xCC\x64\x32\xD8"
+ "\xB6\x1D\xF4\x31\x3E\x9E\xD3\x3B\x16\xA4\x32\xF7\x9E\x9A\x72\x91\x4A\xB0\x69\x9D\xC0\x8A\x08\x22\x82"
+ "\x15\x61\x68\x9F\xB1\x9F\x2B\x7C\x75\xB2\x80\xF4\x55\xB3\xF3\x1C\x70\x1E\x70\x16\x5F\x4D\x2D\xAB\xF4"
+ "\xC8\xC8\x88\x00\x3A\xC6\xFC\x87\xEF\x20\xDA\xFD\x2C\x86\x39\x1C\xB3\x04\x57\x6F\xE8\x60\x47\x9F\xA2"
+ "\xA7\xA7\x0B\xD3\xB4\x96\xAC\x09\x02\xC9\xFC\xFC\x02\x27\xCF\x0A\x7E\x9D\xAE\xE0\x49\x05\xCA\x3F\x81"
+ "\x9B\x7B\xD9\x8E\x1D\x39\x1E\x46\x7E\x1E\xA8\x34\xB7\xE5\x6D\xAF\x89\x50\x44\x1C\x48\x8D\xE9\xFD\x4F"
+ "\x62\xC6\x1F\xC2\x30\x87\x16\xF9\x44\x14\x7A\xBB\x6A\x67\x78\x76\xC1\xC7\xA9\x36\x2D\x56\xFE\x09\xFC"
+ "\xD2\x27\xE1\x69\x2F\x00\xB3\x61\xDA\x97\xBD\x8E\x2E\xF9\x34\x1B\x19\x19\x31\xC2\xEE\xB5\x13\xE8\x1E"
+ "\xF3\xF6\x6D\xC7\xEA\xDA\x85\x88\x0E\x22\xAC\x01\xB4\x6E\xAC\xD7\x32\x4B\xE0\x65\xA9\xE6\x33\x61\x91"
+ "\x29\x87\x9F\x5A\x21\xFC\xDF\x6F\xF5\x58\xBD\xAC\xC7\x69\x98\x0D\x2B\xCC\x48\x22\x44\x3C\x1C\x13\xF5"
+ "\x62\x06\x12\x70\x01\x27\x84\xBB\xD2\xE3\xF4\xBF\xC4\x07\x59\x45\x3E\x69\x0D\xF8\x00\x00\x00\x00\x49"
+ "\x45\x4E\x44\xAE\x42\x60\x82"
+ },
+
+ {
+ 807,
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x20\x00\x00\x00\x20\x08"
+ "\x06\x00\x00\x00\x73\x7A\x7A\xF4\x00\x00\x00\x06\x62\x4B\x47\x44\x00\xFF\x00\xFF\x00\xFF\xA0\xBD\xA7"
+ "\x93\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x0B\x13\x00\x00\x0B\x13\x01\x00\x9A\x9C\x18\x00\x00\x00"
+ "\x07\x74\x49\x4D\x45\x07\xD6\x02\x02\x07\x1F\x12\xE3\xD6\xA7\x2A\x00\x00\x02\xB4\x49\x44\x41\x54\x58"
+ "\xC3\xC5\x97\x3D\x6F\x14\x31\x10\x86\x9F\xDD\x1C\x11\x49\x41\x40\x24\x05\x12\x50\x22\xD1\x11\xE9\x10"
+ "\x91\x68\xE8\xE9\x40\x8A\x44\x49\x45\x89\xF8\x0B\x94\x74\x40\x8B\x52\x52\x44\x54\xFC\x0A\x8A\x88\x34"
+ "\x54\x74\x40\x83\x42\x8A\x84\x48\x24\x7B\xF6\xCC\x50\xEC\xC7\xD9\xDE\xDB\xDB\xCB\x87\x12\x4B\xD6\x8C"
+ "\xD7\x5E\xBF\xEF\xBE\x1E\xDB\x3B\x99\x99\x71\x91\x25\x03\x58\x7B\xF7\x63\xD5\x54\xAE\x49\x71\x94\xAB"
+ "\x08\x2A\x8A\x7A\x45\x7D\xE5\x87\x6D\xAF\xA8\x96\x56\xBC\xA0\x62\x98\x57\x54\x24\x7A\x47\x44\x50\x6F"
+ "\xA8\x48\xD9\xDF\x8C\x71\x7B\xBA\xFD\x62\x1B\x50\xC0\xB2\xB5\xF7\x3F\x9F\x67\xF9\xDC\xC6\xCA\xD2\x3C"
+ "\xE2\x15\x71\x56\xDA\xAA\x7A\x57\xFB\x86\x38\xC5\x7B\x45\xEA\x67\x4E\xF1\xDE\x1A\x3F\x1A\xEF\x0C\xDF"
+ "\x00\x2B\xA6\x8A\x3A\x8F\x16\x3B\x58\xB1\xF3\x92\x6F\xAF\x3E\x00\x47\x83\x2C\x9F\xDB\xB8\x7F\xE7\x2A"
+ "\x37\xAF\x2F\xE2\x1C\x38\x07\xA3\x51\x5C\x8B\xD0\x2F\x12\x3B\x82\x51\x51\xB6\x1B\x7F\x04\x2E\x03\x67"
+ "\xA0\x19\x70\xA9\xD2\x5B\x95\xEC\xF0\x0B\x36\x6F\x6F\x81\xCF\xC0\xEF\x1C\x18\x83\xFB\x92\x80\xF7\xE0"
+ "\x65\x5C\x25\xA8\xAA\x20\x5A\x5A\x55\xD0\xEA\x99\x5A\x6C\x4D\xA1\x15\x5E\x79\x4E\x66\xCB\x75\x6B\x19"
+ "\xB8\x3C\x80\xF2\x4B\xBC\x2F\x09\x84\x56\x7C\x0C\xDE\x90\x90\x92\x44\x44\x48\xDA\x84\x7A\xE2\x7B\x1E"
+ "\x98\x1B\x00\x3C\xBC\x11\x7C\x41\x3D\xA9\x8C\x27\x96\x29\x35\x55\xC8\xD7\xE4\xC5\x10\x81\x7A\x97\x95"
+ "\xC6\x28\x76\x17\x79\xF3\x71\xCC\x62\x80\xC1\xA3\xDB\xFD\xDB\x65\x73\x0B\x9E\x3D\xE8\x1F\x67\x66\x98"
+ "\x81\xAA\x55\xBE\x55\x7E\xD9\xF7\x77\x7F\x21\x22\x90\x9F\xE5\x39\x30\x09\xDC\xAA\xA5\x08\xC9\x44\x61"
+ "\x71\x56\x04\xBA\xC0\xE3\xB6\xA1\xAA\x09\x01\xB5\x73\x04\xA7\x4D\x80\x53\x2A\xD0\x2D\x7B\x1B\xFC\xD8"
+ "\x4B\xB0\xB9\x75\x72\xF0\x38\x08\x39\xFE\x12\xCC\x0A\x1E\x7F\x69\x0A\x4E\x6B\x8C\xC8\x0C\x0A\xF4\x83"
+ "\xD3\x01\x36\xAD\x5D\xAB\x15\x2B\x30\x48\x15\x48\xC1\xC3\x76\xDC\x97\xD5\x97\x69\x54\x1E\xDF\x2D\x3A"
+ "\x95\x50\x9D\xB4\x04\x81\x02\x7D\x5F\x3E\x5B\x50\x4E\x57\xA2\x15\x84\xE8\xD9\xFE\x90\xF4\x2D\xCB\x54"
+ "\x05\xD6\x87\xA7\x27\xD0\x1B\x13\xD2\x8A\x81\x78\x82\xF5\x61\xBC\x14\xEB\xC3\x72\xD2\x4F\x5F\x33\x9E"
+ "\xDC\x93\x68\x4B\xA5\xE7\x7C\xDA\xEE\x22\xD3\xBB\x0B\x42\x25\xC2\x97\xDA\xE0\x74\x82\x77\x6E\xCD\xF4"
+ "\x17\xA1\xEB\x20\xAA\x49\xD4\x13\x85\x7E\x7A\xB8\x1C\x47\x89\xB4\x0C\xBA\x0E\x22\x55\xE3\xE9\x6A\xFC"
+ "\x62\x37\xF8\xEC\x4A\xA4\x12\x4C\xBC\x0B\x26\x5D\x2A\xE3\x08\x3F\xB9\x12\x93\x97\x20\x51\xA0\xEB\x46"
+ "\x0B\xF7\xF8\x49\xC1\x75\x82\xDA\x51\x0C\x4C\xBB\x4E\x27\xF5\x4F\x03\x4F\xC7\xD4\xFD\xA9\xE2\x03\x53"
+ "\xE3\xE0\xE0\x1F\xAA\xDA\x1C\x95\x56\xD9\xB2\x5D\xFA\x6B\x2B\xC6\xEE\x9F\x8E\x31\x16\x3C\xAF\x40\x1A"
+ "\x98\x70\xD9\xCD\x70\xDE\x27\x04\xCC\x18\xBE\xFE\xDE\x24\x10\xEA\x05\x49\x33\x9D\x30\xE3\x09\x33\xA6"
+ "\xA4\x2F\x3D\x64\x66\x4D\xCD\xAE\x00\xB7\x80\xA5\x73\x4E\x0B\xF7\x81\x5F\x75\xDE\xB2\x10\xE4\x2F\xE7"
+ "\x55\x1C\x70\x98\x5D\x74\x76\x9C\x73\xC1\xE5\x3F\x07\xB4\x49\xC3\x70\xE9\xD2\x77\x00\x00\x00\x00\x49"
+ "\x45\x4E\x44\xAE\x42\x60\x82"
+ }
+};
+
+
+
+
+const QPixmap * KCHMIconStorage::getApplicationIcon( )
+{
+ static const char png_image_cr64_app_kchmviewer[] =
+ {
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x40\x00\x00\x00\x40\x08"
+ "\x06\x00\x00\x00\xAA\x69\x71\xDE\x00\x00\x14\xD6\x49\x44\x41\x54\x78\x9C\xED\x9B\x79\x78\xDC\xD5\x75"
+ "\xF7\x3F\xBF\x75\x34\xA3\x7D\x1B\x8D\xB6\xB1\xB5\xDA\x92\x6D\xC9\xC6\x2C\xC6\x16\x18\xB3\xC5\x35\x18"
+ "\xE2\x40\x5E\x0C\x4D\xC3\x9B\x14\x1B\x4C\x20\x4D\x9A\xC4\x6F\x13\x20\xD0\x82\x29\x10\x9A\xBC\x49\x4A"
+ "\x59\x42\xCA\x03\x26\x90\x02\x65\x09\x4D\x42\x48\x0B\xF1\x46\x08\x8B\x17\x24\x2F\xB2\xB1\x6C\x6B\x97"
+ "\x46\xDB\x68\x66\x34\x33\xBF\xED\xF6\x8F\xD1\x4C\x24\x4B\x36\x98\xC5\xEE\xD3\xE4\x3C\xCF\x7D\x7E\x9A"
+ "\xAB\x3B\xF7\x77\xBF\xDF\x73\xEE\x3D\xE7\xDC\x7B\x47\x12\x42\xF0\xA7\x2C\xF2\xA9\x1E\xC0\xA9\x96\x3F"
+ "\x13\x70\xAA\x07\x70\xAA\xE5\xCF\x04\x9C\xEA\x01\x9C\x6A\x51\x4F\xD5\x8B\xAF\x7E\xF0\x16\xD1\x31\xDC"
+ "\x43\xA5\xB7\x8C\x98\x69\xF0\xCC\xBA\x7B\xA4\x53\x31\x0E\xE9\x54\xB8\xC1\x0B\xEF\xBF\x51\x84\xCC\x18"
+ "\x92\x92\x30\x40\x55\x80\x25\x1C\xAA\xBD\x7E\x82\x91\x51\x5E\xBE\xF9\xFB\x27\x8D\x8C\x93\x4E\xC0\x17"
+ "\x1F\xFD\xAE\x38\x12\x0C\x10\xB7\xCD\x69\xFF\xEF\xD8\x36\x42\x38\x54\x15\x96\x33\x12\x1E\xE1\x95\xAF"
+ "\xFF\xF3\xA7\x4A\xC6\x49\x25\xE0\x33\x3F\xFA\x1B\x11\x8C\x45\x4E\xE8\x3B\x8E\x63\x53\x94\x91\xC3\x68"
+ "\x6C\x8C\x4D\xDF\x7C\xF8\x13\x27\xE3\xA4\x10\x70\xFB\x4B\x0F\x8B\xD7\x0F\x6C\xC7\x70\xEC\x63\xB6\x39"
+ "\xAF\xE4\x1C\x7E\xD7\xBD\xE5\xD8\x9D\x08\x81\x61\x19\x78\x33\xF3\x98\x91\xE7\xA3\xA2\xA0\x84\xBF\x5B"
+ "\x7E\xED\xC7\x26\xE4\x53\x27\xE0\x8E\x5F\x3C\x22\xB6\x1E\xDC\x45\xD8\x8C\x4F\xAA\x6F\x2A\x6A\x62\x56"
+ "\x7E\x25\xA7\xF9\x67\x93\x91\xAE\xA2\x28\x12\x86\xE1\x10\x0C\x19\xEC\xE8\x68\xE5\x77\x5D\x9B\x69\x8F"
+ "\xB4\x1F\xB3\x5F\xDB\xB6\xC9\xF6\x64\x52\x94\x99\x4B\x45\x41\x09\x77\x5D\x76\xFD\x47\x22\xE3\x53\x25"
+ "\xE0\x9A\x47\x6F\x15\xE1\x78\x94\xFE\x48\x30\x55\xE7\x4F\xF7\xB3\x76\xDE\xFF\xA5\xAE\x26\x0F\x6F\x81"
+ "\x1B\x01\x98\x8E\xC0\x72\x40\x95\x40\x96\xC0\xB2\x1C\x3A\xBA\x43\xBC\xDE\xD2\xCC\xC6\x03\x4F\x7E\xA8"
+ "\x77\xA5\xA9\x3A\xF9\xE9\x59\xD4\x14\x96\x71\xCF\xE7\x6E\xFA\xD0\x64\x7C\x6A\x04\xAC\xF8\xF1\xDF\x88"
+ "\x81\x48\x08\x59\xFE\x63\xA8\x51\x9E\xEE\x67\xFD\x92\xEB\x99\x57\x97\x8F\x29\x60\xF7\x90\x43\x73\xBF"
+ "\xCD\x60\x54\x60\x3B\x02\xC7\x71\x28\x4E\x97\x58\x50\xA4\x52\x9D\xAD\x10\x8B\x99\xBC\xB7\x27\xC0\x4F"
+ "\x9A\x1F\x3F\xAE\x35\x1C\x2D\x8A\x24\x53\x94\x99\x83\x37\x23\x97\x87\xBE\xF0\xED\xE3\x92\xF1\xA9\x10"
+ "\xF0\x97\x3F\xBD\x4D\xB4\x0D\xF6\x30\xB1\x67\x7F\xBA\x9F\x6F\x2C\x5E\xC3\xFC\x39\x85\x74\x46\x04\x2F"
+ "\xBD\x6F\x23\x0B\x41\x45\xB6\x44\x96\x4B\x42\x08\x30\x6D\x41\x67\xD0\x64\x4F\x6F\x1C\x5F\xA6\xCC\xE7"
+ "\xEB\x3C\xB8\x25\xC1\xCE\xE6\x3E\x6E\x7F\xFB\xAE\x13\x1A\x83\x5B\xD5\x09\xC7\xA3\x28\x48\xD4\xFB\x66"
+ "\x12\x37\x0C\x7E\x76\xFD\x5D\x53\xC8\xF8\xC4\x23\xC1\x55\x0F\xAD\x17\x9D\x23\x01\x8E\xA6\xF5\xA2\x19"
+ "\xE7\x31\x77\x76\x01\x47\x46\x05\x4F\x34\x9B\x64\xAA\x82\xD2\x0C\x89\x98\x25\xC8\x70\x49\x54\xE7\xAB"
+ "\x54\xE5\x29\xCC\xF6\x6A\x34\x96\xE8\x74\x0F\x9B\xFC\x60\xDB\x30\x11\x4B\x50\x5D\x99\x47\x93\xB7\xE9"
+ "\x84\xC6\x21\x84\xC0\xAD\xB9\x90\x25\x99\x5D\x1D\x07\xD8\xDB\xDD\x36\x6D\xBB\x4F\x94\x80\x73\xEF\x5F"
+ "\x2B\x42\xF1\x28\x71\xDB\x9A\x54\x5F\x9E\xEE\x67\xD9\x9C\x06\x0C\x07\x9E\xDE\x6B\xE0\x92\x05\x63\x86"
+ "\x43\x67\xD0\xA2\x63\xC4\x44\x41\xE0\xCF\x52\xA8\xCE\xD3\x58\x52\x9E\xC6\xC5\xD5\x1E\x72\xDD\x12\x9D"
+ "\x83\x06\x8F\xBF\x1B\xC4\xE3\xD1\x58\x39\xEB\xA2\x0F\x3D\x0E\x21\x04\x63\x46\x9C\xB1\x78\x94\x98\x11"
+ "\x07\xDB\x61\x49\xC9\xDC\x69\xDB\x7E\x22\xA1\xF0\xB7\x5F\x78\x40\x6C\x3D\xB8\x0B\xD3\x71\x30\xE2\xD1"
+ "\x29\xFF\x3F\xAF\xE4\x5C\xBC\x85\x1E\xDE\xE8\xB6\xE8\x0B\xDA\x64\xBA\x60\x28\xEC\x60\xDB\x89\xB2\xB1"
+ "\x37\xC4\x93\xF1\x28\x39\x6E\x85\x2F\x34\x15\x53\x59\x98\x86\x57\xB7\x11\xB6\xCD\xAB\xBB\x83\x7C\xA6"
+ "\xCA\x43\x41\xBE\x87\x25\x85\x4B\xD8\x16\xD8\x76\xCC\x71\x38\x8E\x83\x65\x5B\x38\x8E\x83\x00\x6C\xCB"
+ "\x42\x43\xE6\xA6\x33\x3F\x4B\x55\xBA\xF7\x93\x25\xE0\xAF\x37\x6E\x10\x03\xA1\x21\x86\xC6\x42\x48\x80"
+ "\xE9\x38\xC7\x6C\x3B\xAF\xB8\x1A\x24\x89\x37\xDB\x0D\x42\x51\x8B\xD1\x31\x1B\xDB\x72\xB0\x1D\xB0\x6D"
+ "\x07\xCB\x12\x58\xB6\x8E\x3D\xEA\x30\xA7\xD7\xA0\xB2\x30\x0D\x33\x6E\xD2\x39\x10\x63\x2C\x66\xB1\x69"
+ "\xFF\x28\x57\x9D\x96\x8B\x24\x1F\x7F\x71\x8F\x1A\x71\x04\xA0\x4A\x32\xA5\xD9\xF9\xF4\x0D\x07\xF8\xFA"
+ "\xA2\x2B\x99\x5B\x54\x81\x6D\x4F\x1F\x83\x9C\x10\x01\xAB\x1F\xF9\x8E\x70\x69\x3A\x6D\x03\xDD\xE4\xB8"
+ "\x33\x18\x33\x63\xB8\x54\x17\x61\x63\xAA\xD6\x27\x4A\x9A\xAE\x62\x5A\x0E\xFB\x3A\x47\x39\xD2\x3D\xC0"
+ "\x58\x38\x0C\x8A\x42\xF5\x4C\x2F\x67\x56\xE7\x91\xA1\xCB\x38\x42\x90\xE7\x51\x58\x52\xE1\x01\xA0\xB3"
+ "\x3F\xC2\xC0\xF0\x18\xB6\x69\xB2\xB7\x43\x41\xCC\xCF\x63\x69\x71\x13\x5B\xFB\xB6\x4E\xFB\x0E\xC3\x32"
+ "\x11\x80\x5B\xD5\xA8\xF2\x96\x13\x18\x19\xE0\x96\xA5\x5F\x60\x56\xA1\x1F\x4D\xD3\x30\x0C\xE3\xA3\x11"
+ "\x70\xD5\x23\xDF\x16\x8A\xAC\xD0\x3E\xD4\x8B\x47\xF7\x50\x90\x99\xCB\xDC\x92\x2A\x0E\x0E\x76\x12\x8A"
+ "\xC7\x26\xB9\xB9\x63\x8A\x04\xA6\x29\xE8\xEA\xEC\xA3\xAD\x75\x3F\x66\x3C\x4E\x5D\x6D\x31\x8F\x5D\x73"
+ "\x26\x59\x69\x93\x87\x60\x5A\x36\x4F\xBF\xD6\xC6\xB3\xBF\xEF\x26\x14\x1D\xC3\x8E\xC7\x08\x79\xCB\xB1"
+ "\x8F\x63\x61\xB6\x63\x63\x58\x26\x85\x19\x39\xCC\xC8\x2B\xA6\x77\x24\xC0\xD7\x16\x5D\xC1\xEC\xA2\x19"
+ "\xE8\xBA\x8E\x6D\xDB\x27\x66\x01\xCB\x6E\xFF\x92\xC8\xF7\x15\x71\x64\xA4\x17\x5D\xD1\xC8\x72\x67\x50"
+ "\x94\xED\x45\x96\x24\x4C\xC7\xA2\xB9\xE7\x20\xB6\xE3\x7C\x38\xF0\x40\xDC\xB0\x91\x10\xE8\x56\x0C\x47"
+ "\xC8\x08\x49\xA3\xC6\x97\x4D\x56\x9A\x4A\x4B\x5B\x80\xEF\x3F\xF3\x2E\x48\x32\xC3\x11\x83\x3D\x5D\x63"
+ "\x0C\xC6\x24\x6C\xDB\xC6\x32\xE3\x20\xC9\xE4\x6A\x89\x38\xA1\x2D\x78\x28\xD5\xA7\x61\x99\xD8\x8E\x83"
+ "\xED\x38\x68\x8A\xC2\x2C\xAF\x9F\xFC\x8C\x1C\x06\x42\x43\x7C\xF5\xAC\x55\xD4\xF9\x66\xE2\x76\xBB\x91"
+ "\x24\x89\x48\x24\x82\x24\x4D\x3F\x7D\xA6\x10\xB0\xF0\xA6\x55\x22\x3E\x16\x23\x22\x2C\xD2\xB3\x32\x90"
+ "\x65\x19\xD3\xB6\x08\xC5\x22\xC8\x92\x44\x30\x1A\x42\x92\xE5\x29\x6E\xEE\x78\xB2\xBB\xEF\x7D\xAA\x2A"
+ "\xCE\xA0\xAE\x30\x8D\xDD\x87\x34\x4C\x4B\x66\x6F\x67\x84\xA7\xB6\x1C\xE6\x3F\xDF\x6E\xE7\xE5\x7D\x63"
+ "\x64\x67\xB8\x18\x8D\x98\x98\xA6\x8C\xAC\xC8\x80\x84\x63\x38\xC8\x8E\xCD\x7C\x7F\x16\xB1\x98\xC5\x91"
+ "\x50\x07\xB6\x63\x13\x1D\x37\x67\x59\x82\x92\xEC\x7C\x66\xE4\x15\xA3\xC8\x32\x31\xD3\x60\xED\x69\x97"
+ "\x30\xA7\xA4\x12\x8F\xC7\x83\xA2\x28\xC4\xE3\x71\x2C\xD3\xE4\xF9\x6D\xBF\xE1\x95\x0D\xEB\xC5\xE6\x8D"
+ "\xBF\x98\xC4\xC4\x14\x02\xFE\xE2\xF4\xA5\xFC\x62\xF3\xAB\x44\xBB\x87\x70\x10\x28\x1E\x1D\x59\x92\x13"
+ "\x9D\x59\x06\xBA\xA2\x61\x8B\x63\x9B\xE3\x74\x72\x60\xE8\x10\xA1\xF0\x7C\x56\xCC\x2F\xE2\x85\x37\x0F"
+ "\x21\x29\x3A\x57\x2D\xAD\xE4\xAA\x25\x33\x58\x5C\x5F\x84\xFB\xD9\xDD\x78\xF3\x33\xE8\xEE\x19\xA6\xA1"
+ "\xBE\x98\xE1\x91\x08\xC2\x81\x07\x7F\xB1\x07\xB7\xE5\xB0\x68\x8E\x8F\x60\x30\xC6\xBE\xA1\xFD\x44\x0D"
+ "\x03\x09\xF0\x66\xE5\x32\x23\xCF\x87\x5B\x73\x01\xE0\x52\x34\xAE\xA9\x3F\x8F\x2A\x6F\x19\xE9\xE9\xE9"
+ "\x68\x9A\x86\x69\x9A\xA9\xF2\xDE\xFE\xBD\xB4\xB4\xEE\xE3\xF3\x37\x7C\x51\x3C\xFB\xD0\x13\x29\x12\xA6"
+ "\x10\x70\x79\xFD\x12\xD4\xC1\x28\xCF\xEF\xDE\x42\xA4\x6B\x00\xAD\x38\x07\x2D\x3D\x0D\xC9\xB1\xD0\xD5"
+ "\x13\x07\x0F\xB0\xAD\x7F\x2B\x97\xF4\x5C\xC0\x6C\x7F\x2E\x2B\xEA\x0B\x78\xFE\xBD\x01\xFE\xEB\xED\x1E"
+ "\xCE\x2E\x4F\x67\xD3\xCE\x2E\x46\x47\x63\x0C\x0C\x45\xF9\xED\x7B\x83\xF4\x8D\x18\xBC\xDF\x13\x41\x96"
+ "\x04\x66\x70\x84\x6F\x5D\x75\x3A\xAA\x2C\xB3\xA3\xBD\x85\xEE\x58\x17\x33\xF2\xBC\x94\xE6\x14\x91\xA6"
+ "\x6A\x00\x08\x20\x43\x77\xF3\x7F\xEA\xCE\xC1\x97\x53\x40\x7A\x7A\x3A\xBA\xAE\x27\x5C\xA2\x65\x61\x9A"
+ "\x26\x3F\x7D\xE5\x59\x5E\x7B\x6B\x1B\xB3\xCA\x67\x32\x11\x3C\x4C\x13\x0A\xEF\xD8\xB1\x43\xEC\xDA\xB5"
+ "\x8B\x8E\xA1\x3E\x9E\xDB\xBB\x19\xCD\x9B\x8D\x93\xAE\xA1\x8F\xBF\xF0\xA3\x4A\x93\x77\x09\xAB\x17\xAE"
+ "\x44\x4F\x53\xB8\xF5\xE1\x2D\x6C\x3E\x1C\xC6\x96\xD3\x41\xD6\x40\x52\x10\x88\xC4\xB4\x12\x02\xEC\x38"
+ "\x52\x28\xC0\x0D\x17\xD7\x72\xCD\xF2\x06\x02\x81\x51\x5E\xED\xF8\x25\xA6\x16\x45\x91\x26\x4F\xBF\x0C"
+ "\xDD\xC3\x17\x1A\x2F\x20\xD7\x93\x99\x02\x2F\x84\x20\x1E\x8F\x13\x8E\x44\xB8\xEF\x99\x47\xF8\xB7\x57"
+ "\x5F\xA6\x3A\xB7\x98\x2D\x4F\xBE\xFC\xC1\xA1\xB0\xA2\x28\xA4\xA5\xA5\x51\x9A\xE7\x65\x46\x4D\x15\x66"
+ "\x9A\xFC\xB1\xC1\x03\x6C\xED\xDF\xC6\x1B\xAD\xEF\x61\xC6\x6D\xEE\x5C\x73\x0E\x37\x9C\x5B\x4E\x8E\x39"
+ "\x00\xD1\x41\x84\x15\x06\x2B\x0A\xF1\x51\x9C\x91\x2E\xFC\xD2\x10\xFF\x78\xED\x19\x5C\xFD\x99\x79\x0C"
+ "\x0F\x8F\xD1\xDC\xBF\x1D\xD2\x4C\x34\x45\x45\x96\x65\x94\xF1\x92\xEB\xCE\xE4\x4B\x0B\x97\x53\x90\x99"
+ "\x43\x66\x66\x26\x2E\x57\x62\x3A\x24\x35\x7F\xDF\xBF\x3F\xCA\x73\x5B\x7E\x43\x65\x51\xE9\xB4\xE0\x61"
+ "\x1A\x0B\x68\x6E\x6E\x16\x2D\xAD\x7B\x79\xA6\xE3\x4D\xDA\x22\x01\x34\x45\x45\x55\x94\x8F\x4D\x00\x80"
+ "\x2A\x2B\xAC\xAE\x58\x4D\x43\xF9\x2C\x72\xB3\x3D\x84\xA2\x26\x6F\xB5\x74\xD0\x7A\x64\x90\x48\xCC\x20"
+ "\x37\xD3\x4D\x63\x8D\x8F\xFA\x4A\x2F\x8A\x24\x11\x18\x18\x65\xEF\xE0\x0E\xFA\x95\xEE\x29\x7D\x65\xBA"
+ "\x3C\x5C\xD3\x78\x01\xF9\x99\x39\x68\x9A\x86\xAE\xEB\x00\x98\xA6\x89\x61\x18\xDC\xF1\xF3\x07\xF8\xF7"
+ "\xCD\xBF\xA1\x32\xC7\xC7\xEF\x1E\xF8\xB7\x63\x46\x50\x53\x08\xD8\xF8\xFA\x4B\xE2\xB1\x77\x5E\x21\x10"
+ "\x1D\xE5\x92\x79\x8B\x29\xC8\xC8\xC5\x76\x6C\x5E\xD8\xB5\xE9\x84\x01\x97\xE7\x78\xB1\x1C\x1B\x5D\xD1"
+ "\x90\x25\x89\xB8\x6D\x11\x33\xE3\x14\xB9\x8A\xF9\x6C\xF9\x4A\xB2\xB2\xB3\xF0\x78\x74\x54\x55\x46\x92"
+ "\x24\x6C\xDB\xC1\x30\x6C\xC2\xE1\x18\x5D\x23\x9D\x74\x59\xEF\x33\x26\x87\xA7\xF4\x9B\xE3\xCE\xE0\xEA"
+ "\xC6\x0B\xC8\xCD\xC8\x42\xD3\x34\x34\x4D\x43\x08\x81\x6D\xDB\x18\x86\xC1\x6D\x3F\xFF\x31\x2F\xFD\xFE"
+ "\x35\x1A\x7D\x95\xBC\x78\xF7\x23\x1F\x3E\x1D\xBE\xF2\x1F\x6E\x12\x1D\x5A\x84\xA8\x65\xB2\xFE\xA2\xBF"
+ "\x64\x65\xC3\x39\xC4\x6D\x13\xD3\x36\x89\x9B\x26\x71\xCB\xC4\xB0\x12\xCF\xB8\x6D\x10\x33\x0D\xE2\x66"
+ "\xE2\x19\xB3\xFE\xF8\x39\x6A\xC6\x13\x6D\x6D\x13\x47\x38\x48\x48\x28\x92\x82\xAA\x28\xE8\xAA\x86\xAE"
+ "\xA8\x08\x40\x31\x5C\xB8\x9C\x4C\x90\x13\xE9\xB0\xE3\x38\x18\x66\x94\x90\x33\x44\x4C\x9D\x3E\xBA\xCC"
+ "\x73\x67\xB1\x7A\xFE\xF9\x64\xA7\x67\xA2\xEB\x3A\x8A\xA2\xA4\xC0\xC7\x8C\x38\xDF\x79\xFA\x87\xBC\xF2"
+ "\xCE\x16\xCE\xF2\xD7\xF3\xB3\x5B\x7E\xF0\x81\x1B\x23\x29\x2F\xB0\xE6\x9F\x6F\x13\xDD\xAE\x18\xB9\xEE"
+ "\x2C\xCE\x2A\xF2\x73\x69\xC3\x39\xA4\x69\x3A\xAA\xA2\x60\xDA\x2A\xBA\xAA\x93\x66\x99\x18\xB6\x85\x61"
+ "\x99\x58\xB6\x8D\x61\x9B\x98\xB6\x8D\xE5\x24\x8A\x6D\xDB\x38\xC2\xC1\x11\x02\x21\x04\x0E\x89\x40\xC5"
+ "\x1C\xFF\x9E\x69\xDB\x58\xE3\xED\x4D\xDB\xC2\x52\x6C\xA2\xF6\x20\xB6\xB0\xB1\xC7\xFB\x70\x64\x07\xC7"
+ "\x71\x50\x44\x62\x61\x9C\xB8\xE2\x15\xA4\x67\x73\x55\xE3\x32\x32\x3D\x19\xE8\xBA\x8E\x2C\xCB\x89\xF7"
+ "\x38\x0E\x51\x23\xCE\x37\x9E\xF8\x1E\x9B\x5A\xDE\x61\xD9\xAC\xD3\xF9\xC9\xDF\x6E\xF8\x50\xBB\x42\x92"
+ "\x10\x82\x3B\x5F\x7E\x54\xEC\x68\x79\x0F\x6F\x89\x8F\xE2\x7C\x2F\x08\x90\x65\x99\xAA\xC2\x52\x1A\x4A"
+ "\xAB\xA9\xF2\x96\x21\x23\x25\x40\x3A\x0E\xF6\xF8\xD3\xB4\xAD\x14\x78\xCB\xB1\x31\x2D\x6B\x52\x9D\x69"
+ "\x8F\x7F\x1E\x7F\x9A\x13\xC1\x3B\x09\x32\x4C\xDB\x4A\x81\x4F\xD6\x39\xC2\xC1\x1A\x7F\x8F\x23\x12\x99"
+ "\x5D\xA1\x27\x9B\xCF\x37\x9E\x47\x86\x3B\x7D\x8A\xE6\xA3\xF1\x18\x5F\x7B\xE2\x7B\x6C\xDE\xF3\x0E\x0B"
+ "\x2A\xEB\x78\xF6\x6F\xFF\xE9\xC4\xB6\xC4\x56\x3F\x7A\xAB\xF8\xBC\xFF\x6C\xAA\x4B\xFD\xF4\x47\x47\x39"
+ "\x38\xDC\xC5\x60\x3C\x82\x23\x01\x08\xD2\x34\x17\xF5\xC5\x33\x99\x57\x52\x85\x37\x2B\x0F\xC7\x71\xB0"
+ "\x85\x9D\x1A\xA4\x95\xB2\x02\x6B\x1C\xD4\x44\x02\xEC\x14\x01\x96\x93\x24\x61\x62\xFD\x64\xF0\xB6\xE3"
+ "\x60\x39\x16\x51\x33\x8E\x69\x5B\x08\x21\xF0\xE7\x14\xB1\xA2\x6E\x11\x99\x9E\x44\x80\x33\x51\xF3\x91"
+ "\x78\x94\x9B\x1F\xBF\x87\x3F\xB4\x36\x53\xEE\x2B\x61\xC8\x19\x63\x46\x9E\x8F\x17\xD6\xDD\xF7\xE1\x2D"
+ "\xE0\xC6\xA7\xEF\x13\x4D\xDE\xD9\x9C\x35\x73\x4E\x02\x9C\xE3\x30\x10\x1E\x66\xDF\x40\x17\x81\x78\x10"
+ "\x74\x05\x21\x12\x1B\x0D\xF9\xE9\x59\xD4\x17\x57\x50\x5F\x52\x41\x86\xCB\x93\xD2\xB0\x2D\x9C\x09\x44"
+ "\x24\xC0\x25\x48\x70\xC6\xFF\x4E\x80\x4D\x12\x61\xD9\x36\x66\xB2\x9D\x6D\x4F\xB2\x9C\xD1\x68\x84\x88"
+ "\x11\x43\x08\x87\xCA\xDC\x62\x96\xD7\x2D\xC2\x9D\x96\x86\xAE\xEB\xA9\x98\xDE\x71\x1C\xC2\xB1\x31\xBE"
+ "\xFA\xC4\x3D\xBC\xB9\xBF\x99\xD5\x8B\x97\x73\x56\xDD\x7C\x9E\x79\xE7\xB7\x6C\x6F\xDF\x4F\xB6\xDB\xC3"
+ "\x96\x6F\xFD\xE4\x03\x49\x90\x84\x10\x2C\xFB\xE1\x8D\xE2\x8A\xDA\x26\xAE\x5C\x70\x3E\x96\x65\x61\x59"
+ "\x56\x62\x45\x35\x4D\x02\xC1\x61\x76\x76\xB4\x72\x60\xB8\x1B\x27\x4D\x21\x3F\x27\x8F\x0C\x3D\x0D\x21"
+ "\xA0\x34\xB7\x90\xBA\xE2\x0A\x2A\x0B\x4A\xD0\x15\x15\x63\x7C\x33\x22\x01\xD0\x99\x6A\x15\xC2\xC2\xB2"
+ "\x8E\x9A\x1E\xE3\x6D\xCD\xF1\x76\xFD\xA1\x61\x82\xD1\x30\x42\x08\x6A\x0A\xCA\xB8\x78\xD6\x19\xB8\x5C"
+ "\x2E\x34\x4D\x4B\x81\x17\x42\x10\x1C\x0B\x73\xE3\xE3\x77\xB3\xF3\xD0\x3E\xFE\xAA\x69\x25\x8B\x66\x37"
+ "\xE2\x52\x35\xDC\xBA\x8B\x97\x77\x6D\xE1\xB9\xED\xAF\x53\xE5\x2D\xE1\xC5\x75\xF7\x1F\x97\x04\x15\xC0"
+ "\x97\x91\x4F\xC8\x8E\xE1\x76\xBB\x13\x59\xD8\x38\x01\xBA\x65\xE1\x4E\x4B\xA3\x24\xBF\x90\x68\x3C\xC6"
+ "\xEE\x8E\xF7\x79\x7D\xFF\x76\xDE\x89\x0E\x92\x9D\x97\xCB\xE0\xD8\x08\x5D\x23\x01\x74\x45\xA5\xA2\xA0"
+ "\x94\x7A\xDF\x4C\x7C\xD9\xF9\xA8\x8A\x82\x25\x27\xAD\x41\xC1\x56\x6C\x54\xDB\xC2\xB2\xD5\xF1\x7A\x0B"
+ "\xCD\x56\x53\x5A\x37\x6D\x0B\xDD\x51\x69\x1F\xEA\x23\x14\x1B\x43\x96\x24\x6A\x0B\xFD\x5C\x50\xBB\x10"
+ "\x97\xCB\x85\xAA\xAA\x29\xB3\x07\x08\x8E\x85\xB9\xFE\xF1\xBB\x68\x39\x72\x90\x35\xE7\x5F\xC1\xA2\x59"
+ "\x8D\xE8\xAA\x86\x4B\xD5\x71\xA9\x1A\x5F\x5E\x72\x19\x95\x85\xA5\x7C\xFF\x3F\x9F\x66\xF1\xF7\xD6\x8A"
+ "\x37\xBE\x75\x6C\x57\x28\x09\x21\x78\x78\xCB\x8B\x62\x77\xC7\x7E\xEE\xBF\xF2\x6B\x29\xF0\x49\x22\x92"
+ "\x31\xB5\x6D\xDB\x98\xA6\x89\xE3\x38\xF4\x0C\x05\x78\xA3\x75\x27\x9B\x0F\xEF\x22\x28\x1B\xF8\x0A\xBC"
+ "\x54\x15\x96\x51\x98\x91\x4B\xBA\xCB\x4D\x75\x61\x19\xB5\x3E\x3F\x39\xEE\x8C\xD4\xB4\xF8\xE3\x5A\xE1"
+ "\x60\x0B\x0B\xD3\x1A\xB7\x0E\x27\x51\xB7\xBF\xAF\x9D\xDE\xD1\x21\x24\xA0\xB6\xA0\x8C\xF3\x6B\x17\xA2"
+ "\x69\xDA\x14\xF0\x43\xE1\x20\x6B\x1F\xDF\x40\x6B\xD7\x61\xAE\x3F\xFF\x0A\xCE\xAE\x69\xC4\xA5\xE9\xE8"
+ "\x8A\x8A\x4B\x4D\x84\xEC\x09\x32\x34\xDE\x38\xD8\xCC\xB7\x5F\xFC\x17\x14\x59\xE6\xE2\xFA\xB3\xD8\x70"
+ "\xF9\xBA\x29\x44\xA4\xE2\x80\x6B\x1F\xBB\x43\x3C\x76\xED\x77\x71\x1C\x27\x55\x6C\xDB\x4E\x11\x90\x7C"
+ "\x4E\x24\x68\x2C\x16\x65\xD7\xA1\x7D\xFC\xAE\x75\x3B\xCD\x43\xED\xA8\x99\x2E\xAA\x8B\xFC\xD4\x7A\xFD"
+ "\x78\xF4\x34\xF2\xD2\xB3\xA9\xF1\x96\x51\x51\x50\x82\xAE\x68\x18\xB6\x99\xF2\x20\x29\xD7\xE9\xD8\xB4"
+ "\x74\xB7\xD1\x31\xD4\x07\x40\x6D\x41\x39\x4B\xAB\xE7\xE3\x72\xB9\x50\x14\x65\x12\xF8\xC1\x70\x90\xB5"
+ "\x4F\x6C\xE0\x40\x6F\x07\xEB\x97\xFF\x15\x8B\xAA\x1B\x52\xB1\x85\x26\x2B\xA8\x8A\x8A\xA6\x28\x68\x8A"
+ "\x06\x08\x0E\x0F\xF4\xF0\xC0\xA6\xE7\x18\x8C\x04\xE9\x09\x0E\xB0\xB4\x76\x01\x77\x5C\xBA\x76\xFA\x64"
+ "\x68\xF5\x4F\xBE\x23\x9E\xBA\x6E\x03\xB2\x24\x25\x36\x15\x93\xBE\x7C\x02\x11\x49\xE0\x49\xEB\x48\x16"
+ "\xC7\x71\xE8\x0C\xF4\xB2\x79\xCF\xBB\xFC\xBE\xBD\x85\x01\x31\x46\x69\x51\x31\x0D\xE5\x35\xE4\x7B\x72"
+ "\x40\x82\xD2\x9C\x42\x6A\xBC\xE5\xF8\xB2\xF2\x91\x24\x12\x41\x92\x23\xD8\xDE\xDE\xCA\xA1\x81\x44\xA8"
+ "\x5B\x5F\x34\x83\x25\x95\x0D\x29\x37\x37\x71\xCE\x0F\x84\x47\x58\xFB\xC4\x06\xDA\xFA\xBB\xF8\xEE\xCA"
+ "\xEB\x68\xAA\x9D\x8F\x2A\xAB\xE3\x79\x81\x82\x2A\x2B\xC8\x92\x44\x20\x32\x42\x73\xE7\xFB\xEC\xED\x39"
+ "\x4C\x30\x96\xD8\x08\x51\x91\x19\x0C\x0C\x10\xE8\xEA\xA1\xB4\xB8\x84\x7B\xFF\xFA\x5B\xD3\xA5\xC3\x12"
+ "\x31\xD3\xC0\xA3\xBB\x52\x3B\x3D\x42\x88\x44\xF2\xA1\x28\x93\x88\x38\x9A\x0C\xDB\xB6\xA9\x2C\xF5\x33"
+ "\xC3\x57\xCA\xE7\xA2\x17\xB2\xF3\xE0\x5E\x36\xED\xDB\xCE\x7F\xFD\x61\x2B\xF9\xDE\x02\x16\x54\xD6\x23"
+ "\x4B\x32\xDD\x23\x01\x74\x55\x63\x46\x5E\x31\x95\x05\x25\xEC\xEF\xEF\xA0\x7D\xA8\x17\x45\x96\xA9\x2F"
+ "\xAA\x60\xD1\xCC\xFA\x29\xE0\x01\xFA\x46\x87\x58\xBB\x71\x03\xED\x83\x7D\xDC\xB5\xEA\x46\x96\xD4\x34"
+ "\xA0\x48\x0A\x8A\xA2\xA0\x29\x0A\xA1\xD8\x18\xBB\x7A\x8F\xD0\xD2\xDD\x46\x7F\x68\x18\x49\x02\x09\x89"
+ "\x6C\xC5\x4D\x89\x2B\x1B\xAF\x9E\x89\x94\x51\xC9\x1B\xF6\x2E\xF6\x84\xBA\xA6\x2E\x82\x00\x65\x39\x85"
+ "\xBC\xBA\xE7\x4D\x2E\x9C\x7D\x26\x19\x69\xEE\x04\x25\x92\x84\x24\x49\x93\x88\x48\x5A\xC5\xB1\x2C\x43"
+ "\xD7\x75\xCE\x69\x38\x83\x25\x73\x17\x26\xAC\xA2\xE5\x6D\xB6\xBD\xF5\x16\x99\x05\x79\x2C\xAC\x9D\x8B"
+ "\x2C\xC9\x1C\x0C\x74\x72\xA0\xBF\x23\x31\x50\x49\xA2\xC1\x57\xC5\x99\x33\xEB\x50\xC7\x7D\xFC\x44\xF0"
+ "\x9D\xC3\xFD\xAC\xD9\x78\x37\xFD\xC1\x41\xEE\xBD\xE2\x26\x16\x55\xCD\x43\x95\x55\x6C\xC7\xE6\x60\xA0"
+ "\x8B\x9D\xED\xAD\x74\x05\x03\x48\x48\x08\x04\x4E\xDC\xC4\x63\x29\xF8\xD3\xF3\x29\x74\x67\xA1\x2A\x2A"
+ "\x32\x32\xBA\x5B\x27\xE4\xC4\xE9\x1F\x0B\x4E\x22\x60\x52\x2E\xB0\xFA\xD1\x5B\x45\xE7\x70\x1F\x17\xCE"
+ "\x3E\x93\x95\x0D\x4D\x34\x94\xD5\xA0\x29\x53\xB7\x0D\x27\x4E\x8F\x24\x01\xC9\xA8\xEC\xE8\x69\x92\x5C"
+ "\x2B\x76\xBC\xBF\x87\xAD\xAD\x3B\xC8\xCD\xCF\xC7\xEF\xF7\x63\x4B\x89\x3E\x1A\x4B\xAA\x38\xAD\x7C\x56"
+ "\x2A\xC0\x99\x08\xFE\xC8\x60\x0F\x6B\x36\xDE\xCD\x60\x64\x94\xFB\x56\x7D\x85\x45\x55\xF3\xE8\x1A\x09"
+ "\xB0\xBB\xA7\x8D\x43\x03\x3D\x89\xBC\xC3\x88\xD3\x3D\x12\x20\x36\x12\xA2\xCC\x95\x4B\x43\x51\x25\x65"
+ "\x05\x45\x68\x8A\x8A\x24\xCB\xA8\xAA\x8A\xAA\xAA\xE8\x9A\xCE\x8F\x36\x3F\x8B\x63\x5A\x3C\xF2\xD5\x3B"
+ "\x53\x2F\x99\xF6\x6C\x70\xE9\xFD\xEB\x84\x2C\x43\x9A\xE6\xE2\xF2\xC6\x73\xB9\x74\xDE\x12\xCA\x72\x8B"
+ "\xA6\x25\x22\xF9\x9C\x6E\xF1\x3C\x7A\xBD\x10\x42\x70\xA8\xA7\x83\xF6\x40\x0F\x8A\xC7\xC5\xCC\x32\x3F"
+ "\x0B\xCA\x6B\x51\x55\x15\xE5\xA8\x94\xFB\xF0\x60\x0F\x6B\x36\x6E\x60\x38\x1A\xE6\xB6\x15\x5F\x26\xD7"
+ "\x93\xC9\xBE\xDE\x23\x04\xA3\x61\x46\xA2\x21\x3A\x86\xFA\xE8\xEE\xEF\x25\xCB\xD2\x58\x5C\x52\x47\xC3"
+ "\x8C\x5A\xB2\x3C\x19\x28\x8A\x92\xF2\x1C\xC9\xA7\xA2\x28\xA4\xE9\x2E\xBE\xF3\x1F\x0F\x71\x96\x6F\x36"
+ "\x37\x5F\x79\xED\xF1\x09\x48\xCA\xAD\x2F\x3E\x28\xFE\xD0\xBE\x87\xE0\x58\x88\x7A\x5F\x05\xAB\x16\x2C"
+ "\xE3\xBC\xDA\x85\x64\xBB\xD3\x8F\x49\xC6\x44\x22\x26\x12\x72\xB4\x4B\x0D\x87\xC3\xF8\xFD\xFE\x54\x52"
+ "\x33\x51\xF3\x87\x06\xBA\x59\xFB\xE4\xDD\x0C\x47\xC3\x5C\x3A\xB7\x89\xBC\xF4\x4C\x82\xD1\x08\x07\x03"
+ "\x9D\xB4\xF5\x75\xE2\x84\x63\x34\xE6\xCE\xE4\xEC\x8A\xB9\x54\xFA\xCA\xD0\x35\x3D\x05\x5C\x51\x94\x54"
+ "\x91\x65\x39\x45\x80\xAA\xAA\xDC\xF0\xB3\x7F\xE4\xA5\x6F\xFE\xE8\xF8\x5B\x62\xC7\x92\xCB\xFE\xE5\x1B"
+ "\x42\x91\x64\xFA\x46\x07\x69\xAA\x9A\xCF\xAA\xD3\x96\xB1\xD0\x5F\x87\xAE\x1E\x7B\x8A\x4C\xB7\x5E\x24"
+ "\x89\x08\x87\xC3\xF8\x7C\x3E\x34\xED\x8F\xBB\x4D\x92\x24\xB1\xBF\xAF\x9D\x1B\x9E\xBC\x87\x90\x11\x65"
+ "\x79\xFD\xD9\x44\x8C\x31\xF6\x74\xB7\x31\x3C\x38\x44\xB9\x96\xCB\x62\xFF\x1C\x16\x54\xD6\x91\x93\x91"
+ "\x95\x02\x99\xD4\x74\x32\x5A\x4C\x12\x20\x49\x52\x8A\x04\x5B\x38\xAC\xFB\xD9\x3D\xBC\xF0\xF5\x1F\x7C"
+ "\x34\x02\x26\xCA\x97\x9F\xB8\x53\xEC\xED\x3D\x4C\xA6\xCB\xC3\x85\xB3\xCF\xE0\xB2\x86\x73\xA9\x2D\xF2"
+ "\x4F\x7B\x4E\xE0\x8C\x1F\x68\x1C\x3D\x35\xA2\xD1\x28\x39\x39\x39\x29\xED\x4B\x92\xC4\x9E\xEE\x36\x6E"
+ "\x78\xEA\x5E\x22\x66\x9C\xAA\x82\x12\xFA\x06\x03\x28\x61\x93\x05\xDE\x6A\x96\xD4\x34\x52\x5D\xEA\x47"
+ "\x91\x55\x64\x45\x9E\x56\xDB\x13\xB5\x9E\xEC\x33\x69\x59\x23\xD1\x30\xFF\xF0\xD2\xC3\x3C\xB6\x6E\xF2"
+ "\x11\xF9\x47\x3A\x1B\xFC\xD7\x2F\xDE\x26\x01\xAC\x7B\xEA\x5E\xB1\xAF\xF7\x08\xCF\xBC\x7B\x07\x35\xDE"
+ "\x32\x2E\x99\xBB\x98\x8B\xEA\x17\xE1\xCD\xCC\x4D\xB5\x4D\x0E\x20\xA9\x99\xE4\xA0\x54\x55\x4D\xC5\x1B"
+ "\xB2\x2C\xD3\xDC\x75\x90\xAF\x3C\x75\x2F\x21\x33\x4E\x8E\xAD\x42\x6F\x98\x2B\x2A\xCE\xE2\x8C\xDA\xB9"
+ "\xE4\x66\x66\x23\x8D\x03\x3C\xBA\x24\x01\x4F\x2C\x47\x8B\x24\x49\x84\x8D\x28\x06\x53\x77\xB4\x3F\xB1"
+ "\x0B\x12\x2B\x1F\x5C\x2F\x1C\xC7\xA2\x6F\x74\x88\xB3\x2B\xE6\x72\x79\xE3\xB9\x2C\xA9\x4A\x24\x28\x47"
+ "\x4F\x07\xC7\x71\x30\x0C\x23\x65\xFE\xBB\xBB\x0E\xF2\xB5\xE7\x7F\x48\xDC\x34\x59\x9A\x3F\x9B\xA6\xCA"
+ "\x79\xD4\x96\x57\xA2\x8F\x7B\x86\xA3\xE7\x77\xB2\x6E\xA2\x89\x1F\xEB\xE4\xA7\x27\x38\xC8\xAF\x5B\xB6"
+ "\xF1\xEA\xDE\xB7\x28\xCD\x2A\xE0\xE1\x2F\xDF\xFA\xF1\xA7\xC0\x07\xC9\x85\x3F\xB8\x59\x0C\x84\x87\xC9"
+ "\xF6\x64\xB0\xA2\xFE\x6C\x96\xCF\x39\x9B\x3A\xDF\xCC\x49\xAE\xD1\x34\x4D\x24\x49\x62\xE7\x91\x56\x6E"
+ "\x79\xF5\xA7\x68\xAA\xC6\x2D\x4D\x57\x53\x53\x50\x9A\x72\x5F\xC7\xD3\x76\x12\xFC\x74\x12\x89\x47\xD9"
+ "\x7C\x60\x07\xBF\x6A\xD9\xC6\xFE\xBE\x0E\x72\xD3\xB3\x68\xAA\x6C\x64\xFD\xA5\x53\x6F\x95\x7D\x6A\x77"
+ "\x84\x2E\xFA\xFE\x4D\x62\x20\x3C\x42\x75\x61\x19\x3D\xC1\x00\x39\x9E\x2C\x96\xD5\x2C\xE0\x82\x9A\xD3"
+ "\x29\xCE\xC8\x27\x6E\xC4\x79\xA3\x75\x07\xFF\xF4\xF6\x0B\xA4\x69\x3A\x1B\x2E\xBA\x8E\x99\x79\xBE\x49"
+ "\x80\x55\x55\x4D\x01\x9D\x38\x7D\xA6\xD3\xB6\xE5\xD8\xEC\xEA\x3C\xC0\xAF\xDE\xDB\xCA\x96\xF7\x77\x50"
+ "\x9A\xE3\x45\x57\x5D\x3C\x7E\xDD\x1D\x27\xFF\x8E\x50\x52\x3E\xF3\xFF\x6F\x16\x43\xE1\x20\x7F\x7F\xD9"
+ "\xF5\xB8\x54\x8D\x5F\xB6\xBC\xC1\xD6\xB6\x9D\x14\x7B\xF2\xA8\xC9\xF4\xF1\x5A\x57\x33\x19\xEE\x74\xBE"
+ "\xB7\xE2\x06\x66\xE6\x15\x4F\xD1\xF8\xD1\x26\x3E\x65\xAC\x92\x44\x5B\xA0\x8B\x5F\x37\x6F\xE3\xB5\xD6"
+ "\xB7\x19\x33\x62\x54\x15\x96\xF1\xC8\xB5\xB7\x7E\xA8\xDD\x20\x38\x09\xF7\x04\x97\xFF\xF0\xAB\xA2\x2F"
+ "\x38\xC4\x86\xCB\x6F\xE0\xE2\x39\x8B\x18\x19\x0B\xB1\xE9\xC0\x0E\x9E\xDB\xF1\x3A\x03\x91\x11\xEE\xBD"
+ "\x64\x1D\x95\x05\x25\xD3\x2E\x68\xD3\x69\x5A\x92\x24\x06\x23\xA3\x6C\xDA\xFF\x2E\xBF\x7C\x6F\x2B\xAD"
+ "\x7D\x87\xF1\x66\xE6\x71\x5A\x79\x1D\xB7\x5F\xBE\xE6\x84\xEF\x0A\x9E\x94\x9B\xA2\x2B\x7E\xFC\x75\xD1"
+ "\x35\xD4\xC7\x9D\x2B\xD7\xB2\xA2\xA1\x29\x75\x56\x3F\x16\x19\x43\x51\x27\x9B\xFB\x44\x13\x9F\x48\x40"
+ "\xDC\x32\x78\xFB\xF0\x1E\x9E\xDF\xFE\x1A\x7F\x38\xB4\x9B\xC2\xCC\x5C\x84\x2C\xF1\x1F\x5F\xF9\x78\x17"
+ "\xAB\x4F\xDA\x5D\xE1\xCB\x1E\xF8\xA6\x38\x32\xD0\xCD\x1D\x97\x5C\xC7\x5F\xCC\x5D\x8C\xE3\x38\xC4\xE3"
+ "\xF1\x54\xF6\x37\xDD\xC2\x26\x10\xEC\xEB\x6D\xE7\x57\xCD\x5B\x78\x65\xF7\xEF\x91\x24\xA8\x29\x9A\xC9"
+ "\xC2\xB2\xD9\xAC\x59\xFA\xD9\x4F\xE4\xDE\xF0\x49\xBD\x2C\x7D\xF9\x83\xDF\x14\x47\x06\x7A\x59\xBF\xF4"
+ "\x6A\x2E\x6D\x6C\xC2\xB4\xAC\x54\x12\x34\x31\xAA\xEB\x0F\x0D\xF3\x5A\xEB\xDB\xBC\xB8\x73\x13\x5D\x23"
+ "\xFD\x78\x33\x72\x99\x5B\x52\xCD\x5D\xAB\xA6\xEE\xE8\x7C\x5C\x39\xE9\xD7\xE5\x57\x3D\xB8\x5E\xB4\x0D"
+ "\x74\x71\x5D\xE3\x72\x56\x9D\xB6\x0C\x55\x55\x49\x73\xB9\x88\xD9\x26\xDB\x0E\x35\xF3\xEB\xE6\x6D\x34"
+ "\xF7\x1E\x64\x96\x6F\x06\xAA\xA4\xF0\xAF\x5F\xBA\xFD\x7F\xCF\x75\xF9\xA4\x7C\xEE\xA1\xFF\x27\x0E\x0E"
+ "\x74\x71\x79\xF9\xE9\xD4\xF9\xAB\xD9\xD6\xD9\xC2\x3B\x5D\xFB\xC9\x4B\xCF\xC6\x01\x5E\xB9\xF9\x83\x8F"
+ "\xB4\x3E\x29\x39\x25\x04\x00\x5C\xF9\xD0\xDF\x89\xFD\x81\x0E\xF2\xD3\xB3\xA8\x2A\x28\xE3\x8C\xF2\xD9"
+ "\x5C\xBF\xEC\x8A\x93\xFF\xB3\x99\x89\x99\xDB\xC9\x2E\x3F\xFE\xED\xCF\xC5\xA9\x7C\xBF\x10\xE2\xD4\x59"
+ "\xC0\xFF\x14\xF9\x93\xFF\xD9\xDC\x9F\x09\x38\xD5\x03\x38\xD5\xF2\x27\x4F\xC0\x7F\x03\x90\x91\x43\x51"
+ "\x9D\xE9\xB8\x2D\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82"
+ };
+
+ if ( !m_iconApplication )
+ {
+ m_iconApplication = new QPixmap ();
+ if ( !m_iconApplication->loadFromData ((const uchar*)png_image_cr64_app_kchmviewer, sizeof(png_image_cr64_app_kchmviewer) - 1, "PNG") )
+ qFatal ("Could not load application icon");
+ }
+
+ return m_iconApplication;
+}
+
+
+const QPixmap * KCHMIconStorage::getCloseWindowIcon( )
+{
+ static const char png_image_cancel[] =
+ {
+ "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x16\x00\x00\x00\x16\x08"
+ "\x06\x00\x00\x00\xC4\xB4\x6C\x3B\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xAF\xC8\x37\x05\x8A\xE9\x00"
+ "\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61"
+ "\x67\x65\x52\x65\x61\x64\x79\x71\xC9\x65\x3C\x00\x00\x03\x49\x49\x44\x41\x54\x78\xDA\x62\xFC\xFF\xFF"
+ "\x3F\xC3\xB9\x4B\xF7\xFE\x33\x31\x31\x32\x60\x03\xBF\x7E\xFF\x61\xF8\xFD\xEB\x37\xC3\xDF\xBF\xFF\x18"
+ "\x3E\x7E\xFA\x0A\x16\xF3\xF5\x30\xC7\xAE\x18\x09\x00\x04\x10\x0B\x88\x00\x19\x6A\xA0\xA3\x88\x21\xF9"
+ "\x0F\x68\xE9\x8F\x9F\x7F\x18\xFE\xFC\xF9\x07\xC6\x8F\x9E\xBC\x60\x10\xE0\xE7\x65\xD8\xBC\xE3\xE4\x7F"
+ "\x42\x86\x03\x04\x10\x13\x21\x9B\x99\x81\x96\x82\x2C\x66\x66\x82\x28\x65\x67\x63\x65\x30\x35\xD2\x04"
+ "\x1B\x8E\x4F\x1F\x40\x00\xE1\x35\x98\x89\x11\x68\x20\x33\x13\x03\x0B\x10\x33\xB3\x40\x1C\xC8\xC5\xC5"
+ "\xC1\x20\x22\xCC\xC3\xA0\xA5\xA1\x88\xD7\x70\x80\x00\x22\xE8\x62\x10\x60\x44\xF2\x34\x07\x3B\x33\xD8"
+ "\x22\x29\x49\x41\xBC\x2E\x07\x08\x20\x16\xE2\x0C\x86\x04\xC7\xDE\x7D\x47\x81\x18\x53\xBE\xF7\xD6\xED"
+ "\xFF\xC5\x79\x31\x28\x61\x0E\x10\x40\x04\x0D\x06\x19\x08\x4A\x39\xA0\x60\x49\x8A\x0F\x01\x8B\xFD\xFD"
+ "\xFB\x97\xE1\xC9\xD3\x57\xE0\x14\x03\x92\x5B\xB3\x66\x0D\x86\x3E\x80\x00\x62\x22\xD6\xC5\xE0\x88\x64"
+ "\x66\x04\x1B\xFA\xE5\xEB\x77\x70\x8A\x01\x85\x3F\x13\x33\x76\x23\x00\x02\x08\xBB\xE8\xDB\x67\x0C\x0C"
+ "\x7F\x7E\x81\x99\xFF\xFF\xFD\x07\xBB\x0A\x64\xD0\xB7\x6F\x3F\x19\xFE\x9D\x39\xC8\xF0\xEF\xCB\x27\x06"
+ "\x0E\x0E\x36\x60\x78\xB3\x33\x70\x02\x31\x36\x00\x10\x40\x98\x41\xF1\xF2\x01\x03\xC3\xE5\xA3\x40\x67"
+ "\x32\x33\xFC\xB3\xF1\x67\xF8\xC3\xC8\xCA\xF0\x17\x68\x38\x28\x1D\x73\x9C\xD9\xC3\x20\xB0\xA8\x8B\x81"
+ "\x9F\x47\x8C\xE1\x71\x7E\x0F\xC3\x3F\x2E\x5E\xA0\xDC\x3F\xAC\x06\x03\x04\x10\xA6\x8B\xAF\x9F\x66\x60"
+ "\xF8\xF4\x9E\x81\xE1\xD9\x3D\x06\xA6\xF5\x33\x18\x7E\x7D\xFA\x02\x74\xE9\x2F\x06\xC6\xA3\xDB\xC1\x86"
+ "\x32\x7C\xF8\xC4\xC0\x7E\xE5\x1C\x03\xFF\x8D\x0B\x0C\x6C\xC0\x34\xCD\xC6\xCA\x8A\xD5\x60\x80\x00\xC2"
+ "\x34\xD8\xD0\x91\x01\x98\x87\x19\x18\x3E\x02\x0D\xBF\x77\x9D\x81\x6B\x71\x0B\x03\xD7\x91\x4D\x0C\xBC"
+ "\xF3\x3B\xC0\x86\x82\xF0\x87\xEC\x66\x86\xEF\x56\x2E\xC0\x88\x65\x02\x87\x33\x36\x00\x10\x40\x4C\xE8"
+ "\x59\xF8\x1F\x9F\x30\xC3\x3F\xA7\x70\x86\xFF\x3F\x81\x86\x7F\xFA\xC0\xC0\x7C\xF3\x12\x03\xD7\xB2\x89"
+ "\x70\x43\x3F\xE5\xB4\x30\xFC\x70\x0F\x06\xA6\x65\x66\x70\x8A\x61\x62\xC2\x6E\x30\x40\x00\xA1\x88\xFE"
+ "\xFC\xF5\x07\x82\xF9\xC4\x18\x7E\x06\xE7\x02\x0D\xFF\x0D\x37\x10\x84\xBF\x25\x57\x30\xFC\xF2\x0A\x05"
+ "\xE6\x42\x26\x88\xA1\x8C\x4C\x60\x0B\xB0\x01\x80\x00\x42\x31\x98\x11\x09\x32\x3D\xB8\xC9\xC0\xF8\xFC"
+ "\x39\xC2\xE0\x8F\x5F\x19\xD8\x97\x2D\x60\x60\xFC\xF4\x11\x98\x54\x10\x39\xF2\xDF\x7F\xEC\x91\x07\x10"
+ "\x40\x58\xFD\xC1\x7C\x7C\x27\x03\xDB\x8C\x66\xB8\xA1\xFF\xFF\x01\x13\xCF\x87\x6F\x0C\xCC\xA7\xCE\x32"
+ "\x08\xF8\x79\x32\x30\x7D\xFA\x04\x4E\xDB\xE0\x1C\xC9\x88\x3D\x28\x00\x02\x88\x09\x9B\xA1\xAC\x48\x86"
+ "\xFE\x2C\xEE\x60\xF8\x36\x75\x35\xC3\x7F\x46\x2E\x06\x86\x6F\x40\xF9\xCB\x97\x18\xF8\xFD\x3D\x19\x18"
+ "\x3F\x7E\xC4\x9B\xA9\x00\x02\x08\xD3\xE0\x6D\x2B\xE0\x86\xFE\x2A\xE9\x64\xF8\xED\x1D\xC6\xF0\x57\x53"
+ "\x8F\xE1\xDB\x9A\x9D\x0C\xFF\xF9\xF9\x21\x89\x1F\x68\x38\xDB\xB1\xC3\x78\x0D\x06\x08\x20\x0C\x83\x7F"
+ "\x57\x4C\x62\xF8\x27\x22\xC3\xF0\xAB\xB4\x93\xE1\x8F\x4F\x18\x5C\xFC\xAF\x9E\x3E\xC3\xA7\xCD\x10\xC3"
+ "\xBF\x4C\x99\xC1\xF0\xC3\xC3\x1B\xAF\xC1\x00\x01\xC4\x82\x9E\xDC\x18\xB8\x78\x18\xFE\xCE\xD9\x0A\x8E"
+ "\xA0\x7F\xC0\x1C\x07\xC2\x90\xBC\x0D\x34\x5C\x57\x8F\xE1\xED\xBD\xA7\x40\x26\x90\x03\xCC\x89\x90\xAC"
+ "\x8E\x3D\xF2\x00\x02\x08\xC5\x60\x36\x56\x44\xD2\x81\x19\x08\xCA\xB2\xFF\xA1\x96\xB0\x00\x23\xEA\xFF"
+ "\x7F\x26\x30\x1B\x58\x1C\x81\x2D\x60\xFC\x83\xBD\x86\x02\x08\x20\x16\x48\xA9\xC5\xC4\x50\x5A\xD9\xC6"
+ "\x40\x4D\x00\x10\x60\x00\x30\xC9\x4F\x14\xFB\x0B\x87\xFC\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60"
+ "\x82"
+ };
+
+ if ( !m_iconCloseWindow )
+ {
+ m_iconCloseWindow = new QPixmap ();
+
+ if ( !m_iconCloseWindow->loadFromData ((const uchar*)png_image_cancel, sizeof(png_image_cancel) - 1, "PNG") )
+ qFatal ("Could not load cancel icon");
+ }
+
+ return m_iconCloseWindow;
+}
+
+
+
+KCHMIconStorage::KCHMIconStorage( )
+{
+ m_iconApplication = 0;
+ m_iconCloseWindow = 0;
+}
+
+
+KCHMIconStorage gIconStorage;
+
+
+const QPixmap * KCHMIconStorage::getToolbarPixmap( pixmap_index_t pix )
+{
+ return returnOrLoadImage ( (unsigned int) pix, png_image_toolbakicons + (pix - KCHMIconStorage::back));
+}
+
+
+const QPixmap * KCHMIconStorage::returnOrLoadImage( unsigned int id, const png_memory_image_t * image )
+{
+ QMap<unsigned int, QPixmap*>::iterator it = m_iconMap.find (id);
+
+ if ( it == m_iconMap.end() )
+ {
+ m_iconMap[id] = new QPixmap ();
+ if ( !m_iconMap[id]->loadFromData ((const uchar*)image->data, image->size, "PNG") )
+ qFatal ("Could not load image %d", id);
+ }
+
+ return m_iconMap[id];
+}
diff --git a/src/iconstorage.h b/src/iconstorage.h
new file mode 100644
index 0000000..0a7a14e
--- /dev/null
+++ b/src/iconstorage.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef ICON_STORAGE_H
+#define ICON_STORAGE_H
+
+#include <qmap.h>
+#include <qpixmap.h>
+
+
+class KCHMIconStorage
+{
+ public:
+ typedef struct
+ {
+ unsigned int size;
+ const char * data;
+ } png_memory_image_t;
+
+ enum pixmap_index_t
+ {
+ back = 1000,
+ bookmark_add,
+ fileopen,
+ print,
+ findnext,
+ findprev,
+ forward,
+ gohome,
+ viewsource,
+ view_decrease,
+ view_increase,
+ next_page,
+ prev_page,
+ locate_in_content
+ };
+
+ KCHMIconStorage();
+ const QPixmap * getToolbarPixmap (pixmap_index_t pix);
+ const QPixmap * getApplicationIcon();
+ const QPixmap * getCloseWindowIcon();
+
+ private:
+ const QPixmap * returnOrLoadImage (unsigned int id, const png_memory_image_t * image);
+
+ QMap<unsigned int, QPixmap*> m_iconMap;
+ QPixmap * m_iconApplication;
+ QPixmap * m_iconCloseWindow;
+};
+
+extern KCHMIconStorage gIconStorage;
+
+#endif /* ICON_STORAGE_H */
diff --git a/src/kchmbookmarkwindow.cpp b/src/kchmbookmarkwindow.cpp
new file mode 100644
index 0000000..2e332fa
--- /dev/null
+++ b/src/kchmbookmarkwindow.cpp
@@ -0,0 +1,239 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kchmbookmarkwindow.h"
+#include "kchmmainwindow.h"
+#include "kchmviewwindow.h"
+#include "kchmlistitemtooltip.h"
+#include "kchmtreeviewitem.h"
+
+#include "kchmbookmarkwindow.moc"
+
+KCHMBookmarkWindow::KCHMBookmarkWindow(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ QVBoxLayout * layout = new QVBoxLayout (this);
+ layout->setMargin (5);
+
+ m_bookmarkList = new KQListView (this);
+ m_bookmarkList->addColumn( "bookmark" ); // no need to i18n - the column is hidden
+ m_bookmarkList->header()->hide();
+ layout->addWidget (m_bookmarkList);
+
+ new KCHMListItemTooltip( m_bookmarkList );
+
+ QHBoxLayout * hlayout = new QHBoxLayout (layout);
+ QPushButton * add = new QPushButton ( i18n( "&Add" ), this);
+ QPushButton * edit = new QPushButton ( i18n( "&Edit" ), this);
+ QPushButton * del = new QPushButton ( i18n( "&Del" ), this);
+
+ hlayout->addWidget (add);
+ hlayout->addWidget (edit);
+ hlayout->addWidget (del);
+
+ connect( m_bookmarkList,
+ SIGNAL( doubleClicked ( QListViewItem *, const QPoint &, int) ),
+ this,
+ SLOT( onDoubleClicked ( QListViewItem *, const QPoint &, int) ) );
+
+ connect( add,
+ SIGNAL( clicked () ),
+ this,
+ SLOT( onAddBookmarkPressed( ) ) );
+
+ connect( del,
+ SIGNAL( clicked () ),
+ this,
+ SLOT( onDelBookmarkPressed( ) ) );
+
+ connect( edit,
+ SIGNAL( clicked () ),
+ this,
+ SLOT( onEditBookmarkPressed( ) ) );
+
+ connect( m_bookmarkList,
+ SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ),
+ this,
+ SLOT( slotContextMenuRequested ( QListViewItem *, const QPoint &, int ) ) );
+
+ m_menuBookmarks = 0;
+ m_contextMenu = 0;
+ m_listChanged = false;
+}
+
+void KCHMBookmarkWindow::onAddBookmarkPressed( )
+{
+ bool ok;
+ QString url = ::mainWindow->currentBrowser()->getOpenedPage();
+ QString title = ::mainWindow->chmFile()->getTopicByUrl(url);
+ QString name = QInputDialog::getText(
+ i18n( "%1 - add a bookmark") . arg(APP_NAME),
+ i18n( "Enter the name for this bookmark:" ),
+ QLineEdit::Normal,
+ title,
+ &ok,
+ this);
+
+ if ( !ok || name.isEmpty() )
+ return;
+
+ KCHMBookmarkTreeViewItem * item = new KCHMBookmarkTreeViewItem (
+ m_bookmarkList,
+ name,
+ url,
+ ::mainWindow->currentBrowser()->getScrollbarPosition() );
+
+ item->menuid = m_menuBookmarks->insertItem( name );
+ m_listChanged = true;
+}
+
+
+void KCHMBookmarkWindow::onDelBookmarkPressed( )
+{
+ KCHMBookmarkTreeViewItem * item = (KCHMBookmarkTreeViewItem *) m_bookmarkList->selectedItem();
+
+ if ( item )
+ {
+ m_menuBookmarks->removeItem( item->menuid );
+ delete item;
+ m_listChanged = true;
+ }
+}
+
+
+void KCHMBookmarkWindow::onEditBookmarkPressed( )
+{
+ KCHMBookmarkTreeViewItem * item = (KCHMBookmarkTreeViewItem *) m_bookmarkList->selectedItem();
+
+ if ( item )
+ {
+ bool ok;
+ QString name = QInputDialog::getText(
+ i18n( "%1 - edit the bookmark name") . arg(APP_NAME),
+ i18n( "Enter the name for this bookmark:" ),
+ QLineEdit::Normal,
+ item->name,
+ &ok,
+ this);
+
+ if ( !ok || name.isEmpty() )
+ return;
+
+ item->setText (0, name);
+ m_menuBookmarks->changeItem( item->menuid, name );
+ m_listChanged = true;
+ }
+}
+
+
+void KCHMBookmarkWindow::onDoubleClicked( QListViewItem * item, const QPoint &, int )
+{
+ if ( !item )
+ return;
+
+ KCHMBookmarkTreeViewItem * treeitem = (KCHMBookmarkTreeViewItem *) item;
+
+ if ( ::mainWindow->currentBrowser()->getOpenedPage() != treeitem->url )
+ ::mainWindow->openPage( treeitem->url, OPF_CONTENT_TREE | OPF_ADD2HISTORY );
+
+ ::mainWindow->currentBrowser()->setScrollbarPosition(treeitem->scroll_y);
+}
+
+
+void KCHMBookmarkWindow::restoreSettings( const KCHMSettings::bookmark_saved_settings_t & settings )
+{
+ for ( unsigned int i = 0; i < settings.size(); i++ )
+ {
+ KCHMBookmarkTreeViewItem * item = new KCHMBookmarkTreeViewItem (m_bookmarkList, settings[i].name, settings[i].url, settings[i].scroll_y);
+
+ item->menuid = m_menuBookmarks->insertItem( settings[i].name );
+ }
+}
+
+
+void KCHMBookmarkWindow::saveSettings( KCHMSettings::bookmark_saved_settings_t & settings )
+{
+ QListViewItemIterator it (m_bookmarkList);
+
+ settings.clear();
+
+ for ( ; it.current(); it++ )
+ {
+ KCHMBookmarkTreeViewItem * treeitem = (KCHMBookmarkTreeViewItem *) it.current();
+ settings.push_back (KCHMSettings::SavedBookmark(treeitem->name, treeitem->url, treeitem->scroll_y));
+ }
+}
+
+void KCHMBookmarkWindow::invalidate( )
+{
+ QListViewItemIterator it( m_bookmarkList );
+
+ for ( ; it.current(); it++ )
+ m_menuBookmarks->removeItem( ((KCHMBookmarkTreeViewItem *) it.current())->menuid );
+
+ m_bookmarkList->clear();
+}
+
+void KCHMBookmarkWindow::createMenu( KCHMMainWindow * parent )
+{
+ // Create the main Bookmark menu
+ m_menuBookmarks = new KQPopupMenu( parent );
+ parent->menuBar()->insertItem( i18n( "&Bookmarks"), m_menuBookmarks );
+
+ m_menuBookmarks->insertItem( i18n( "&Add bookmark"), this, SLOT(onAddBookmarkPressed()), CTRL+Key_B );
+ m_menuBookmarks->insertSeparator();
+
+ connect( m_menuBookmarks, SIGNAL( activated(int) ), this, SLOT ( onBookmarkSelected(int) ));
+}
+
+void KCHMBookmarkWindow::onBookmarkSelected( int bookmark )
+{
+ QListViewItemIterator it( m_bookmarkList );
+
+ for ( ; it.current(); it++ )
+ {
+ if ( ((KCHMBookmarkTreeViewItem *) it.current())->menuid == bookmark )
+ {
+ KCHMBookmarkTreeViewItem * treeitem = (KCHMBookmarkTreeViewItem *) it.current();
+
+ if ( ::mainWindow->currentBrowser()->getOpenedPage() != treeitem->url )
+ ::mainWindow->openPage( treeitem->url, OPF_CONTENT_TREE | OPF_ADD2HISTORY );
+
+ ::mainWindow->currentBrowser()->setScrollbarPosition(treeitem->scroll_y);
+ break;
+ }
+ }
+}
+
+void KCHMBookmarkWindow::slotContextMenuRequested( QListViewItem * item, const QPoint & point, int )
+{
+ if ( !m_contextMenu )
+ m_contextMenu = ::mainWindow->currentBrowser()->createListItemContextMenu( this );
+
+ if( item )
+ {
+ KCHMBookmarkTreeViewItem * treeitem = (KCHMBookmarkTreeViewItem *) item;
+
+ ::mainWindow->currentBrowser()->setTabKeeper( treeitem->url );
+ m_contextMenu->popup( point );
+ }
+}
+
diff --git a/src/kchmbookmarkwindow.h b/src/kchmbookmarkwindow.h
new file mode 100644
index 0000000..20057f4
--- /dev/null
+++ b/src/kchmbookmarkwindow.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMBOOKMARKWINDOW_H
+#define KCHMBOOKMARKWINDOW_H
+
+#include "kde-qt.h"
+#include "forwarddeclarations.h"
+#include "kchmsettings.h"
+
+/**
+@author Georgy Yunaev
+*/
+class KCHMBookmarkWindow : public QWidget
+{
+ Q_OBJECT
+ public:
+ KCHMBookmarkWindow(QWidget *parent = 0, const char *name = 0);
+ virtual ~KCHMBookmarkWindow() {};
+
+ void createMenu( KCHMMainWindow * parent );
+
+ void restoreSettings (const KCHMSettings::bookmark_saved_settings_t& settings);
+ void saveSettings (KCHMSettings::bookmark_saved_settings_t& settings);
+ void invalidate();
+
+ public slots:
+ void onAddBookmarkPressed ();
+ void slotContextMenuRequested ( QListViewItem *item, const QPoint &point, int column );
+
+ private slots:
+ void onBookmarkSelected( int );
+ void onDelBookmarkPressed( );
+ void onEditBookmarkPressed( );
+ void onDoubleClicked ( QListViewItem *, const QPoint &, int );
+
+ private:
+ KQPopupMenu * m_menuBookmarks;
+ KQListView * m_bookmarkList;
+ QString m_bookmarkFileName;
+ bool m_listChanged;
+ KQPopupMenu * m_contextMenu;
+};
+
+#endif
diff --git a/src/kchmconfig.cpp b/src/kchmconfig.cpp
new file mode 100644
index 0000000..f5058f3
--- /dev/null
+++ b/src/kchmconfig.cpp
@@ -0,0 +1,215 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kde-qt.h"
+#include "kchmconfig.h"
+#include "kchmsettings.h"
+#include "kchmmainwindow.h"
+
+
+KCHMConfig appConfig;
+
+const char * APP_PATHINUSERDIR = ".kchmviewer";
+
+
+KCHMConfig::KCHMConfig()
+{
+ QDir dir;
+ m_datapath = QDir::homeDirPath() + "/" + APP_PATHINUSERDIR;
+
+ dir.setPath (m_datapath);
+
+ if ( !dir.exists() && !dir.mkdir(m_datapath) )
+ qWarning ("Could not create directory %s", m_datapath.ascii());
+
+ m_LoadLatestFileOnStartup = false;
+ m_onNewChmClick = ACTION_ASK_USER;
+ m_onExternalLinkClick = ACTION_ASK_USER;
+ m_HistorySize = 10;
+ m_HistoryStoreExtra = true;
+ m_useSearchEngine = SEARCH_USE_MINE;
+
+ m_QtBrowserPath = "viewurl-netscape.sh '%s'";
+ m_kdeUseQTextBrowser = false;
+ m_kdeEnableJS = false;
+ m_kdeEnableJava = false;
+ m_kdeEnablePlugins = true;
+ m_kdeEnableRefresh = false;
+
+ m_advUseInternalEditor = true;
+ m_advExternalEditorPath = "kate '%s'";
+
+ m_lastOpenedDir = "";
+}
+
+
+KCHMConfig::~KCHMConfig()
+{
+}
+
+bool KCHMConfig::load()
+{
+ QFile file (m_datapath + "/config");
+ if ( !file.open (IO_ReadOnly) )
+ return false; // no error message - not actually a problem
+
+ QString line;
+ char readbuf[4096];
+ bool getting_history = false;
+ m_History.clear();
+
+ while ( file.readLine( readbuf, sizeof(readbuf) - 1 ) > 0 )
+ {
+ line = QString::fromUtf8( readbuf ).stripWhiteSpace();
+
+ // skip empty lines and comments
+ if ( line.isEmpty() || line[0] == '#' )
+ continue;
+
+ QRegExp rxsection ("^\\[(\\w+)\\]$"), rxkeypair ("^(\\w+)\\s*=\\s*(.*)$");
+
+ if ( rxsection.search ( line ) != -1 )
+ {
+ if ( rxsection.cap (1) == "settings" )
+ getting_history = false;
+ else if ( rxsection.cap (1) == "history" )
+ getting_history = true;
+ else
+ qWarning ("Unknown configuration section: %s", rxsection.cap (1).ascii());
+
+ continue;
+ }
+ else if ( !getting_history && rxkeypair.search ( line ) != -1 )
+ {
+ QString key (rxkeypair.cap (1)), value (rxkeypair.cap(2));
+
+ if ( key == "LoadLatestFileOnStartup" )
+ m_LoadLatestFileOnStartup = value.toInt() ? true : false;
+ else if ( key == "onNewChmClick" )
+ m_onNewChmClick = (choose_action_t) value.toInt();
+ else if ( key == "onExternalLinkClick" )
+ m_onExternalLinkClick = (choose_action_t) value.toInt();
+ else if ( key == "HistorySize" )
+ m_HistorySize = value.toInt();
+ else if ( key == "HistoryStoreExtra" )
+ m_HistoryStoreExtra = value.toInt() ? true : false;
+ else if ( key == "QtBrowserPath" )
+ m_QtBrowserPath = value;
+ else if ( key == "kdeUseQTextBrowser" )
+ m_kdeUseQTextBrowser = value.toInt() ? true : false;
+ else if ( key == "kdeEnableJS" )
+ m_kdeEnableJS = value.toInt() ? true : false;
+ else if ( key == "kdeEnableJava" )
+ m_kdeEnableJava = value.toInt() ? true : false;
+ else if ( key == "kdeEnablePlugins" )
+ m_kdeEnablePlugins = value.toInt() ? true : false;
+ else if ( key == "kdeEnableRefresh" )
+ m_kdeEnableRefresh = value.toInt() ? true : false;
+ else if ( key == "LastOpenedDir" )
+ m_lastOpenedDir = value;
+ else if ( key == "advUseInternalEditor" )
+ m_advUseInternalEditor = value.toInt() ? true : false;
+ else if ( key == "advExternalEditorPath" )
+ m_advExternalEditorPath = value;
+ else if ( key == "useSearchEngine" )
+ m_useSearchEngine = (use_search_engine) value.toInt();
+ else
+ qWarning ("Unknown key=value pair: %s", line.ascii());
+ }
+ else if ( getting_history )
+ {
+ if ( m_History.size() < m_HistorySize )
+ addFileToHistory( line );
+ }
+ else
+ qWarning ("Unknown line in configuration: %s", line.ascii());
+ }
+
+ return true;
+}
+
+bool KCHMConfig::save( )
+{
+ QFile file (m_datapath + "/config");
+ if ( !file.open (IO_WriteOnly) )
+ {
+ qWarning ("Could not write settings into file %s: %s", file.name().ascii(), file.errorString().ascii());
+ return false;
+ }
+
+ QTextStream stream( &file );
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+ stream << "[settings]\n";
+ stream << "LoadLatestFileOnStartup=" << m_LoadLatestFileOnStartup << "\n";
+
+ stream << "onNewChmClick=" << m_onNewChmClick << "\n";
+ stream << "onExternalLinkClick=" << m_onExternalLinkClick << "\n";
+ stream << "HistorySize=" << m_HistorySize << "\n";
+ stream << "HistoryStoreExtra=" << m_HistoryStoreExtra << "\n";
+
+ stream << "QtBrowserPath=" << m_QtBrowserPath << "\n";
+ stream << "kdeUseQTextBrowser=" << m_kdeUseQTextBrowser << "\n";
+ stream << "kdeEnableJS=" << m_kdeEnableJS << "\n";
+ stream << "kdeEnableJava=" << m_kdeEnableJava << "\n";
+ stream << "kdeEnablePlugins=" << m_kdeEnablePlugins << "\n";
+ stream << "kdeEnableRefresh=" << m_kdeEnableRefresh << "\n";
+ stream << "advUseInternalEditor=" << m_advUseInternalEditor << "\n";
+ stream << "advExternalEditorPath=" << m_advExternalEditorPath << "\n";
+ stream << "useSearchEngine=" << m_useSearchEngine << "\n";
+
+ stream << "LastOpenedDir=" << m_lastOpenedDir << "\n";
+
+ stream << "\n[history]\n";
+
+ // Do not write all the history, but only the needed amount
+ for ( unsigned int i = 0; i < m_History.size(); i++ )
+ stream << m_History[m_History.size() - 1 - i] << "\n";
+
+ // m_History
+ return true;
+}
+
+void KCHMConfig::addFileToHistory( const QString & file )
+{
+ QStringList::Iterator itr = m_History.find( file );
+
+ // check whether file already exists in history - more it forward
+ if ( itr != m_History.end() )
+ {
+ m_History.erase( itr );
+ m_History.push_back(file);
+ return;
+ }
+
+ if ( m_History.size() < m_HistorySize )
+ {
+ m_History.push_back( file );
+ return;
+ }
+
+ // Remove a file from the front
+ QString filetoremove = m_History[0];
+ m_History.erase( m_History.begin() );
+ m_History.push_back( file );
+
+ // And remove the appropriate history file
+ mainWindow->currentSettings()->removeSettings ( filetoremove );
+}
diff --git a/src/kchmconfig.h b/src/kchmconfig.h
new file mode 100644
index 0000000..c87ad48
--- /dev/null
+++ b/src/kchmconfig.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMCONFIG_H
+#define KCHMCONFIG_H
+
+#include <qstring.h>
+#include <qstringlist.h>
+
+extern const char * APP_PATHINUSERDIR;
+
+
+/**
+@author Georgy Yunaev
+*/
+class KCHMConfig
+{
+public:
+ enum choose_action_t
+ {
+ ACTION_ALWAYS_OPEN,
+ ACTION_ASK_USER,
+ ACTION_DONT_OPEN
+ };
+
+ enum use_search_engine
+ {
+ SEARCH_USE_CHM,
+ SEARCH_USE_MINE,
+ };
+
+ KCHMConfig();
+ ~KCHMConfig();
+
+ bool load();
+ bool save();
+
+ void addFileToHistory ( const QString& file );
+
+public:
+ QString m_datapath;
+ QString m_lastOpenedDir;
+
+ bool m_LoadLatestFileOnStartup;
+ choose_action_t m_onNewChmClick;
+ choose_action_t m_onExternalLinkClick;
+ unsigned int m_HistorySize;
+ bool m_HistoryStoreExtra;
+ use_search_engine m_useSearchEngine;
+
+ QString m_QtBrowserPath;
+ bool m_kdeUseQTextBrowser;
+ bool m_kdeEnableJS;
+ bool m_kdeEnableJava;
+ bool m_kdeEnablePlugins;
+ bool m_kdeEnableRefresh;
+
+ bool m_advUseInternalEditor;
+ QString m_advExternalEditorPath;
+
+ QStringList m_History;
+};
+
+extern KCHMConfig appConfig;
+
+#endif
diff --git a/src/kchmcontentswindow.cpp b/src/kchmcontentswindow.cpp
new file mode 100644
index 0000000..d145d41
--- /dev/null
+++ b/src/kchmcontentswindow.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kde-qt.h"
+
+#include "libchmfile.h"
+
+#include "kchmcontentswindow.h"
+#include "kchmlistitemtooltip.h"
+#include "kchmmainwindow.h"
+#include "kchmtreeviewitem.h"
+
+#include "kchmcontentswindow.moc"
+
+KCHMContentsWindow::KCHMContentsWindow(QWidget *parent, const char *name)
+ : KQListView(parent, name)
+{
+ m_contextMenu = 0;
+
+ addColumn( "Contents" ); // no i18n - this column is hidden
+ setSorting(-1);
+ setFocus();
+ setRootIsDecorated(true);
+ header()->hide();
+ setShowToolTips( false );
+
+ connect( this, SIGNAL( onItem ( QListViewItem * ) ), this, SLOT( slotOnItem( QListViewItem * ) ) );
+ connect( this,
+ SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ),
+ this,
+ SLOT( slotContextMenuRequested ( QListViewItem *, const QPoint &, int ) ) );
+
+
+ new KCHMListItemTooltip( this );
+}
+
+KCHMContentsWindow::~KCHMContentsWindow()
+{
+}
+
+void KCHMContentsWindow::slotContextMenuRequested( QListViewItem * item, const QPoint & point, int )
+{
+ if ( !m_contextMenu )
+ m_contextMenu = ::mainWindow->currentBrowser()->createListItemContextMenu( this );
+
+ if( item )
+ {
+ KCHMIndTocItem * treeitem = (KCHMIndTocItem*) item;
+ ::mainWindow->currentBrowser()->setTabKeeper( treeitem->getUrl() );
+ m_contextMenu->popup( point );
+ }
+}
+
+void KCHMContentsWindow::refillTableOfContents( )
+{
+ QValueVector< LCHMParsedEntry > data;
+
+ if ( !::mainWindow->chmFile()->parseTableOfContents( &data )
+ || data.size() == 0 )
+ {
+ qWarning ("CHM toc present but is empty; wrong parsing?");
+ return;
+ }
+
+ kchmFillListViewWithParsedData( this, data, &m_urlListMap );
+}
+
+KCHMIndTocItem * KCHMContentsWindow::getTreeItem( const QString & url )
+{
+ QString fixedstr = ::mainWindow->chmFile()->normalizeUrl( url );
+ QMap<QString, KCHMIndTocItem*>::const_iterator it = m_urlListMap.find( fixedstr );
+
+ if ( it == m_urlListMap.end() )
+ return 0;
+
+ return *it;
+}
diff --git a/src/kchmcontentswindow.h b/src/kchmcontentswindow.h
new file mode 100644
index 0000000..5860041
--- /dev/null
+++ b/src/kchmcontentswindow.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef INCLUDE_KCHMCONTENTSWINDOW_H
+#define INCLUDE_KCHMCONTENTSWINDOW_H
+
+#include "kde-qt.h"
+#include "kchmtreeviewitem.h"
+
+/**
+@author tim
+*/
+class KCHMContentsWindow : public KQListView
+{
+ Q_OBJECT
+ public:
+ KCHMContentsWindow( QWidget *parent = 0, const char *name = 0 );
+ ~KCHMContentsWindow();
+
+ QRect tip( const QPoint & p );
+
+ void refillTableOfContents();
+
+ KCHMIndTocItem * getTreeItem( const QString& url );
+
+ public slots:
+ void slotContextMenuRequested ( QListViewItem *item, const QPoint &point, int column );
+
+ private:
+ KQPopupMenu * m_contextMenu;
+ QMap<QString, KCHMIndTocItem*> m_urlListMap;
+};
+
+#endif /* INCLUDE_KCHMCONTENTSWINDOW_H */
diff --git a/src/kchmdialogchooseurlfromlist.cpp b/src/kchmdialogchooseurlfromlist.cpp
new file mode 100644
index 0000000..de33fc3
--- /dev/null
+++ b/src/kchmdialogchooseurlfromlist.cpp
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kde-qt.h"
+
+#include "kchmdialogchooseurlfromlist.h"
+#include "kchmtreeviewitem.h"
+
+KCHMDialogChooseUrlFromList::KCHMDialogChooseUrlFromList(const QStringList& urls, const QStringList& titles, QWidget* parent)
+ : QDialog(parent, 0, true)
+{
+ QVBoxLayout * layout = new QVBoxLayout (this);
+ layout->setMargin (5);
+
+ QListView * m_urlsList = new QListView (this);
+ m_urlsList->addColumn( i18n( "Topics" ) );
+
+ for ( unsigned int i = 0; i < urls.size(); i++ )
+ new KCHMSingleTreeViewItem (m_urlsList, titles[i], urls[i]);
+
+ layout->addWidget ( new QLabel( i18n( "Please select one of the topics below:"), this) );
+ layout->addWidget ( m_urlsList );
+
+ QHBoxLayout * hlayout = new QHBoxLayout (layout);
+ QPushButton * bok = new QPushButton( i18n( "&Ok" ), this);
+ QPushButton * bcancel = new QPushButton( i18n( "&Cancel" ), this);
+
+ hlayout->addWidget (bok);
+ hlayout->addWidget (bcancel);
+
+ connect( m_urlsList, SIGNAL( doubleClicked ( QListViewItem *, const QPoint &, int) ), this, SLOT( onDoubleClicked ( QListViewItem *, const QPoint &, int) ) );
+ connect( m_urlsList, SIGNAL( currentChanged ( QListViewItem *) ), this, SLOT( onCurrentChanged ( QListViewItem *) ) );
+
+ connect( bok, SIGNAL( clicked () ), this, SLOT( accept() ) );
+ connect( bcancel, SIGNAL( clicked () ), this, SLOT( reject() ) );
+ m_acceptedurl = QString::null;
+}
+
+void KCHMDialogChooseUrlFromList::onDoubleClicked( QListViewItem * , const QPoint &, int )
+{
+ accept();
+}
+
+void KCHMDialogChooseUrlFromList::onCurrentChanged( QListViewItem * item )
+{
+ if ( item )
+ m_acceptedurl = ((KCHMSingleTreeViewItem *) item)->getUrl();
+ else
+ m_acceptedurl = QString::null;
+}
+
+#include "kchmdialogchooseurlfromlist.moc"
diff --git a/src/kchmdialogchooseurlfromlist.h b/src/kchmdialogchooseurlfromlist.h
new file mode 100644
index 0000000..c7f2898
--- /dev/null
+++ b/src/kchmdialogchooseurlfromlist.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMDIALOGCHOOSEURLFROMLIST_H
+#define KCHMDIALOGCHOOSEURLFROMLIST_H
+
+#include <qdialog.h>
+#include <qlistview.h>
+
+/**
+@author tim
+*/
+class KCHMDialogChooseUrlFromList : public QDialog
+{
+Q_OBJECT
+public:
+ KCHMDialogChooseUrlFromList (const QStringList& urls, const QStringList& titles, QWidget* parent);
+ QString getSelectedItemUrl() { return m_acceptedurl; }
+
+private slots:
+ void onDoubleClicked( QListViewItem * item, const QPoint &, int );
+ void onCurrentChanged ( QListViewItem * item);
+
+private:
+ QListView * m_urlsList;
+ QString m_acceptedurl;
+};
+
+#endif
diff --git a/src/kchmindexwindow.cpp b/src/kchmindexwindow.cpp
new file mode 100644
index 0000000..6cc2a92
--- /dev/null
+++ b/src/kchmindexwindow.cpp
@@ -0,0 +1,179 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qlayout.h>
+#include <qheader.h>
+
+#include "libchmfile.h"
+
+#include "kchmmainwindow.h"
+#include "kchmindexwindow.h"
+#include "kchmlistitemtooltip.h"
+#include "kchmtreeviewitem.h"
+
+#include "kchmindexwindow.moc"
+
+KCHMIndexWindow::KCHMIndexWindow ( QWidget * parent, const char * name, WFlags f )
+ : QWidget (parent, name, f)
+{
+ QVBoxLayout * layout = new QVBoxLayout (this);
+ layout->setMargin (5);
+
+ m_indexFinder = new QLineEdit (this);
+ m_indexFinder->setFocus();
+
+ m_indexList = new KQListView (this);
+ m_indexList->addColumn( "idx" ); // it is hidden anyway
+ m_indexList->header()->hide();
+ m_indexList->setTreeStepSize (10);
+ m_indexList->setShowToolTips(true);
+ //m_indexList->setSorting( 0, true );
+
+ layout->addWidget (m_indexFinder);
+ layout->addSpacing (10);
+ layout->addWidget (m_indexList);
+
+ connect( m_indexFinder,
+ SIGNAL( textChanged (const QString &) ),
+ this,
+ SLOT( onTextChanged(const QString &) ) );
+
+ connect( m_indexFinder,
+ SIGNAL( returnPressed() ),
+ this,
+ SLOT( onReturnPressed() ) );
+
+ connect( m_indexList,
+ SIGNAL( doubleClicked ( QListViewItem *, const QPoint &, int) ),
+ this,
+ SLOT( onDoubleClicked ( QListViewItem *, const QPoint &, int) ) );
+
+ connect( m_indexList,
+ SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ),
+ this,
+ SLOT( slotContextMenuRequested ( QListViewItem *, const QPoint &, int ) ) );
+
+ m_indexListFilled = false;
+ m_lastSelectedItem = 0;
+ m_contextMenu = 0;
+
+ new KCHMListItemTooltip( m_indexList );
+}
+
+void KCHMIndexWindow::onTextChanged ( const QString & newvalue)
+{
+ m_lastSelectedItem = m_indexList->findItem (newvalue, 0, Qt::BeginsWith);
+
+ if ( m_lastSelectedItem )
+ {
+ m_indexList->ensureItemVisible (m_lastSelectedItem);
+ m_indexList->setCurrentItem (m_lastSelectedItem);
+ }
+}
+
+void KCHMIndexWindow::showEvent( QShowEvent * )
+{
+ if ( !::mainWindow->chmFile() || m_indexListFilled )
+ return;
+
+ m_indexListFilled = true;
+ refillIndex();
+}
+
+void KCHMIndexWindow::onReturnPressed( )
+{
+ emit ::mainWindow->slotOnTreeClicked ( m_lastSelectedItem );
+}
+
+
+void KCHMIndexWindow::invalidate( )
+{
+ m_indexList->clear();
+ m_indexListFilled = false;
+}
+
+void KCHMIndexWindow::onDoubleClicked( QListViewItem *item, const QPoint &, int )
+{
+ if ( !item )
+ return;
+
+ KCHMIndTocItem * treeitem = (KCHMIndTocItem*) item;
+
+ QString url = treeitem->getUrl();
+
+ if ( !url )
+ return;
+
+ if ( url[0] == ':' ) // 'see also' link
+ {
+ m_lastSelectedItem = m_indexList->findItem (url.mid(1), 0);
+ if ( m_lastSelectedItem )
+ {
+ m_indexList->ensureItemVisible (m_lastSelectedItem);
+ m_indexList->setCurrentItem (m_lastSelectedItem);
+ }
+ }
+ else
+ ::mainWindow->openPage( url, OPF_CONTENT_TREE | OPF_ADD2HISTORY );
+}
+
+void KCHMIndexWindow::slotContextMenuRequested( QListViewItem * item, const QPoint & point, int )
+{
+ if ( !m_contextMenu )
+ m_contextMenu = ::mainWindow->currentBrowser()->createListItemContextMenu( this );
+
+ if( item )
+ {
+ KCHMIndTocItem * treeitem = (KCHMIndTocItem*) item;
+
+ ::mainWindow->currentBrowser()->setTabKeeper( treeitem->getUrl() );
+ m_contextMenu->popup( point );
+ }
+}
+
+void KCHMIndexWindow::refillIndex( )
+{
+ QValueVector< LCHMParsedEntry > data;
+
+ if ( !::mainWindow->chmFile()->parseIndex( &data )
+ || data.size() == 0 )
+ {
+ qWarning ("CHM index present but is empty; wrong parsing?");
+ return;
+ }
+
+ kchmFillListViewWithParsedData( m_indexList, data, 0 );
+}
+
+void KCHMIndexWindow::search( const QString & index )
+{
+ if ( !::mainWindow->chmFile() )
+ return;
+
+ if ( !m_indexListFilled )
+ {
+ m_indexListFilled = true;
+ refillIndex();
+ }
+
+ m_indexFinder->setText( index );
+ onTextChanged( index );
+}
diff --git a/src/kchmindexwindow.h b/src/kchmindexwindow.h
new file mode 100644
index 0000000..1067c4e
--- /dev/null
+++ b/src/kchmindexwindow.h
@@ -0,0 +1,62 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMINDEXWINDOW_H
+#define KCHMINDEXWINDOW_H
+
+
+#include <qlineedit.h>
+#include <qlistview.h>
+
+
+/**
+@author Georgy Yunaev
+*/
+class KCHMIndexWindow : public QWidget
+{
+ Q_OBJECT
+ public:
+ KCHMIndexWindow ( QWidget * parent = 0, const char * name = 0, WFlags f = 0 );
+
+ void invalidate();
+ void search( const QString& index );
+
+ public slots:
+ void slotContextMenuRequested ( QListViewItem *item, const QPoint &point, int column );
+
+ private slots:
+ void onTextChanged ( const QString & newvalue);
+ void onReturnPressed ();
+ void onDoubleClicked ( QListViewItem *, const QPoint &, int);
+
+ private:
+ virtual void showEvent ( QShowEvent * );
+
+ void refillIndex();
+
+ QLineEdit * m_indexFinder;
+ KQListView * m_indexList;
+ KQPopupMenu * m_contextMenu;
+ QListViewItem * m_lastSelectedItem;
+ bool m_indexListFilled;
+};
+
+#endif
diff --git a/src/kchmkeyeventfilter.cpp b/src/kchmkeyeventfilter.cpp
new file mode 100644
index 0000000..67d4cc6
--- /dev/null
+++ b/src/kchmkeyeventfilter.cpp
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kchmkeyeventfilter.h"
+
+KCHMKeyEventFilter gKeyEventFilter;
+
+KCHMKeyEventFilter::KCHMKeyEventFilter()
+ : QObject()
+{
+ m_shiftPressed = false;
+ m_ctrlPressed = false;
+}
+
+bool KCHMKeyEventFilter::eventFilter( QObject *, QEvent *e )
+{
+ // Handle KeyPress and KeyRelease events
+ if ( e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease )
+ {
+ bool * ptr = 0;
+ QKeyEvent *k = (QKeyEvent *) e;
+
+ // We're interested only in Shift and Control
+ if ( k->key() == Qt::Key_Shift )
+ ptr = &m_shiftPressed;
+ else if ( k->key() == Qt::Key_Control )
+ ptr = &m_ctrlPressed;
+
+ // Set it
+ if ( ptr )
+ *ptr = e->type() == QEvent::KeyPress ? true : false;
+ }
+
+ return FALSE; // Standard event processing
+}
diff --git a/src/kchmkeyeventfilter.h b/src/kchmkeyeventfilter.h
new file mode 100644
index 0000000..7375293
--- /dev/null
+++ b/src/kchmkeyeventfilter.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef INCLUDE_KCHMKEYEVENTFILTER_H
+#define INCLUDE_KCHMKEYEVENTFILTER_H
+
+#include <qobject.h>
+
+/*!*
+ * This class must be installed as a global event handler. Its responsibility
+ * is to intercept keyboard events, and store the Shift and Ctrl keys state information.
+ * Unfortunately it seems to be the only way to do it in Qt.
+ */
+class KCHMKeyEventFilter : public QObject
+{
+ public:
+ KCHMKeyEventFilter();
+
+ bool isShiftPressed() const { return m_shiftPressed; }
+ bool isCtrlPressed() const { return m_ctrlPressed; }
+
+ private:
+ bool eventFilter( QObject *, QEvent *e );
+
+ bool m_shiftPressed;
+ bool m_ctrlPressed;
+};
+
+extern KCHMKeyEventFilter gKeyEventFilter;
+
+#endif /* INCLUDE_KCHMKEYEVENTFILTER_H */
diff --git a/src/kchmlistitemtooltip.h b/src/kchmlistitemtooltip.h
new file mode 100644
index 0000000..07014c8
--- /dev/null
+++ b/src/kchmlistitemtooltip.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef INCLUDE_KCHMLISTITEMTOOLTIP_H
+#define INCLUDE_KCHMLISTITEMTOOLTIP_H
+
+#include "kde-qt.h"
+#include "forwarddeclarations.h"
+
+/**
+@author tim
+*/
+class KCHMListItemTooltip : public QToolTip
+{
+ public:
+ KCHMListItemTooltip( KQListView *parent )
+ : QToolTip( parent->viewport() ) { m_pParent = parent; }
+
+ virtual ~KCHMListItemTooltip() {};
+
+ void maybeTip ( const QPoint & pos )
+ {
+ QListViewItem *it = m_pParent->itemAt( pos );
+
+ if ( !it )
+ return;
+
+ // Get the section the mouse is in
+ int section = m_pParent->header()->sectionAt (pos.x ());
+
+ // Get the rect of the whole item (the row for the tip)
+ QRect itemRect = m_pParent->itemRect( it );
+
+ // Get the rect of the whole section (the column for the tip)
+ QRect headerRect = m_pParent->header ()->sectionRect (section);
+
+ // "Intersect" row and column to get exact rect for the tip
+ QRect destRect( headerRect.left (), itemRect.top(), headerRect.width(), itemRect.height() );
+
+ int item_width = it->width( m_pParent->fontMetrics(), m_pParent, 0 )
+ + it->depth() * m_pParent->treeStepSize();
+
+ if ( m_pParent->rootIsDecorated() )
+ item_width += m_pParent->treeStepSize();
+
+ if ( item_width > m_pParent->viewport()->width() )
+ tip( destRect, it->text(0) );
+ }
+
+ private:
+ KQListView * m_pParent;
+};
+
+#endif /* INCLUDE_KCHMLISTITEMTOOLTIP_H */
diff --git a/src/kchmmainwindow.cpp b/src/kchmmainwindow.cpp
new file mode 100644
index 0000000..13417f1
--- /dev/null
+++ b/src/kchmmainwindow.cpp
@@ -0,0 +1,1298 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "kde-qt.h"
+
+#include <qaccel.h>
+#include <qevent.h>
+
+#include "libchmfile.h"
+#include "libchmfileimpl.h"
+#include "libchmurlfactory.h"
+
+#include "kchmmainwindow.h"
+#include "kchmconfig.h"
+#include "kchmindexwindow.h"
+#include "kchmsearchwindow.h"
+#include "kchmbookmarkwindow.h"
+#include "kchmtreeviewitem.h"
+#include "kchmsearchtoolbar.h"
+#include "kchmsettings.h"
+#include "kchmsetupdialog.h"
+#include "iconstorage.h"
+#include "kchmnavtoolbar.h"
+#include "kchmviewwindow.h"
+#include "kchmviewwindowmgr.h"
+#include "kchmkeyeventfilter.h"
+#include "kchmcontentswindow.h"
+
+#if !defined (USE_KDE)
+ #include "kqrunprocess.h"
+#endif
+
+#include "kchmmainwindow.moc"
+
+
+KCHMMainWindow::KCHMMainWindow()
+ : KQMainWindow ( 0, "KCHMMainWindow", WDestructiveClose )
+{
+ const unsigned int WND_X_SIZE = 700;
+ const unsigned int WND_Y_SIZE = 500;
+ const unsigned int SPLT_X_SIZE = 200;
+
+ m_FirstTimeShow = true;
+ m_chmFile = 0;
+
+ m_indexWindow = 0;
+ m_searchWindow = 0;
+ m_contentsWindow = 0;
+ m_viewWindowMgr = 0;
+
+ m_tabContextPage = -1;
+ m_tabIndexPage = -1;
+ m_tabSearchPage = -1;
+ m_tabBookmarkPage = -1;
+
+ setupSignals();
+
+ m_currentSettings = new KCHMSettings;
+
+ // Create the initial layout - a splitter with tab window in left, and text browser in right
+ m_windowSplitter = new QSplitter(this);
+ m_tabWidget = new KQTabWidget( m_windowSplitter );
+ m_viewWindowMgr = new KCHMViewWindowMgr( m_windowSplitter );
+
+ m_bookmarkWindow = new KCHMBookmarkWindow (m_tabWidget);
+
+ // Add the tabs
+ m_tabWidget->addTab( m_bookmarkWindow, i18n("Bookmarks") );
+
+ setupToolbarsAndMenu();
+
+ setCentralWidget( m_windowSplitter );
+
+ QValueList<int> sizes;
+ sizes.push_back (SPLT_X_SIZE);
+ sizes.push_back (WND_X_SIZE - SPLT_X_SIZE);
+ m_windowSplitter->setSizes (sizes);
+
+ resize (WND_X_SIZE, WND_Y_SIZE);
+
+#if defined (ENABLE_AUTOTEST_SUPPORT)
+ m_autoteststate = STATE_OFF;
+ m_useShortAutotest = false;
+#endif /* defined (ENABLE_AUTOTEST_SUPPORT) */
+
+ QAccel * accel = new QAccel( this );
+ accel->connectItem ( accel->insertItem ( Key_F11 ), this, SLOT ( slotToggleFullScreenMode() ) );
+ accel->connectItem ( accel->insertItem ( CTRL + Key_1), this, SLOT ( slotActivateContentTab() ) );
+ accel->connectItem ( accel->insertItem ( CTRL + Key_2), this, SLOT ( slotActivateIndexTab() ) );
+ accel->connectItem ( accel->insertItem ( CTRL + Key_3), this, SLOT ( slotActivateSearchTab() ) );
+ accel->connectItem ( accel->insertItem ( CTRL + Key_4), this, SLOT ( slotActivateBookmarkTab() ) );
+ accel->connectItem ( accel->insertItem ( Key_F3 ), m_searchToolbar, SLOT ( onBtnNextSearchResult() ) );
+
+ statusBar()->show();
+ setIcon( *gIconStorage.getApplicationIcon() );
+
+ m_aboutDlgMenuText = i18n( "%1 version %2\n\nCopyright (C) George Yunaev,"
+ "gyunaev@ulduzsoft.com, 2004-2007\nhttp://www.kchmviewer.net\n\n"
+ "Licensed under GNU GPL license.\n\n"
+ "Please check my another project, http://www.transientmail.com - temporary "
+ "e-mail address, which expires automatically." )
+ . arg(APP_NAME) . arg(APP_VERSION);
+}
+
+
+KCHMMainWindow::~KCHMMainWindow()
+{
+}
+
+
+void KCHMMainWindow::slotOpenMenuItemActivated()
+{
+#if defined (USE_KDE)
+ QString fn = KFileDialog::getOpenFileName( appConfig.m_lastOpenedDir, i18n("*.chm|Compressed Help Manual (*.chm)"), this);
+#else
+ QString fn = QFileDialog::getOpenFileName( appConfig.m_lastOpenedDir, i18n("Compressed Help Manual (*.chm)"), this);
+#endif
+
+ if ( !fn.isEmpty() )
+ loadChmFile( fn );
+ else
+ {
+ if ( !m_chmFile )
+ exit (1);
+
+ statusBar()->message( i18n("Loading aborted"), 2000 );
+ }
+}
+
+
+bool KCHMMainWindow::loadChmFile ( const QString &fileName, bool call_open_page )
+{
+ LCHMFile * new_chmfile = new LCHMFile();
+
+ if ( new_chmfile->loadFile( fileName ) )
+ {
+ // The new file is opened, so we can close the old one
+ if ( m_chmFile )
+ {
+ closeChmFile( );
+ delete m_chmFile;
+ }
+
+ m_chmFile = new_chmfile;
+
+ // Show current encoding in status bar
+ showInStatusBar( tr("Detected chm file charset: %1") . arg(m_chmFile->currentEncoding()->language) );
+
+ // Make the file name absolute; we'll need it later
+ QDir qd;
+ qd.setPath (fileName);
+ m_chmFilename = qd.absPath();
+
+ // Qt's 'dirname' does not work well
+ QFileInfo qf ( m_chmFilename );
+ appConfig.m_lastOpenedDir = qf.dirPath(true);
+
+ // Order the tabulations
+ int number_of_pages = 0;
+
+ if ( m_chmFile->hasTableOfContents() )
+ m_tabContextPage = number_of_pages++;
+ else
+ m_tabContextPage = -1;
+
+ if ( m_chmFile->hasIndexTable() )
+ m_tabIndexPage = number_of_pages++;
+ else
+ m_tabIndexPage = -1;
+
+ // We always show search
+ m_tabSearchPage = number_of_pages++;
+
+ m_tabBookmarkPage = number_of_pages;
+
+ showOrHideContextWindow( m_tabContextPage );
+ showOrHideIndexWindow( m_tabIndexPage );
+ showOrHideSearchWindow( m_tabSearchPage );
+
+ m_bookmarkWindow->invalidate();
+ m_navToolbar->updateIconStatus( false, false );
+ m_viewWindowMgr->invalidate();
+ refreshCurrentBrowser();
+
+ if ( m_currentSettings->loadSettings (fileName) )
+ {
+ const LCHMTextEncoding * encoding =
+ m_chmFile->impl()->lookupByLCID( m_currentSettings->m_activeencodinglcid );
+
+ m_tabWidget->setCurrentPage( m_currentSettings->m_activetabsystem );
+
+ if ( encoding )
+ {
+ m_chmFile->setCurrentEncoding( encoding );
+ m_searchToolbar->setChosenEncodingInMenu( encoding );
+ }
+
+ if ( m_searchWindow )
+ m_searchWindow->restoreSettings (m_currentSettings->m_searchhistory);
+
+ m_bookmarkWindow->restoreSettings (m_currentSettings->m_bookmarks);
+
+ if ( call_open_page )
+ {
+ m_viewWindowMgr->restoreSettings( m_currentSettings->m_viewwindows );
+ m_viewWindowMgr->setCurrentPage( m_currentSettings->m_activetabwindow );
+ }
+
+ // Restore the main window size
+ QValueList<int> sizes;
+ sizes.push_back( m_currentSettings->m_window_size_splitter );
+ sizes.push_back( m_currentSettings->m_window_size_x - m_currentSettings->m_window_size_splitter );
+
+ m_windowSplitter->setSizes( sizes );
+ resize( m_currentSettings->m_window_size_x, m_currentSettings->m_window_size_y );
+ }
+ else
+ {
+ m_tabWidget->setCurrentPage (0);
+ m_searchToolbar->setChosenEncodingInMenu( m_chmFile->currentEncoding() );
+
+ if ( call_open_page )
+ openPage( m_chmFile->homeUrl() );
+ }
+
+ m_searchToolbar->setEnabled (true);
+ appConfig.addFileToHistory( m_chmFilename );
+ updateHistoryMenu();
+ return true;
+ }
+ else
+ {
+ QMessageBox mbox(
+ i18n("%1 - failed to load the chm file") . arg(APP_NAME),
+ i18n("Unable to load the chm file %1") . arg(fileName),
+ QMessageBox::Critical,
+ QMessageBox::Ok,
+ QMessageBox::NoButton,
+ QMessageBox::NoButton);
+ mbox.exec();
+
+ statusBar()->message(
+ i18n("Could not load file %1").arg(fileName),
+ 2000 );
+ delete new_chmfile;
+ return false;
+ }
+}
+
+
+void KCHMMainWindow::slotPrintMenuItemActivated()
+{
+ currentBrowser()->printCurrentPage();
+}
+
+
+void KCHMMainWindow::slotAboutMenuItemActivated()
+{
+ QString caption = i18n( "About %1" ) . arg(APP_NAME);
+ QString text = m_aboutDlgMenuText;
+
+ // It is quite funny that the argument order differs
+#if defined (USE_KDE)
+ KMessageBox::about( this, text, caption );
+#else
+ QMessageBox::about( this, caption, text );
+#endif
+}
+
+
+void KCHMMainWindow::slotAboutQtMenuItemActivated()
+{
+ QMessageBox::aboutQt( this, APP_NAME);
+}
+
+void KCHMMainWindow::refreshCurrentBrowser( )
+{
+ QString title = m_chmFile->title();
+
+ if ( !title )
+ title = APP_NAME;
+ // KDE adds application name automatically, so we don't need it here
+#if !defined (USE_KDE)
+ else
+ title = (QString) APP_NAME + " - " + title;
+#endif
+
+ setCaption ( title );
+
+ currentBrowser()->invalidate();
+
+ if ( m_contentsWindow )
+ m_contentsWindow->refillTableOfContents();
+}
+
+void KCHMMainWindow::slotOnTreeClicked( QListViewItem * item )
+{
+ bool unused;
+
+ if ( !item )
+ return;
+
+ KCHMIndTocItem * treeitem = (KCHMIndTocItem*) item;
+ slotLinkClicked( treeitem->getUrl(), unused );
+}
+
+
+void KCHMMainWindow::slotLinkClicked ( const QString & link, bool& follow_link )
+{
+ if ( link.isEmpty() )
+ return;
+
+ if ( gKeyEventFilter.isShiftPressed() )
+ {
+ openPage( link, OPF_NEW_TAB | OPF_CONTENT_TREE );
+ follow_link = false;
+ }
+ else if ( gKeyEventFilter.isCtrlPressed() )
+ {
+ openPage( link, OPF_NEW_TAB | OPF_BACKGROUND );
+ follow_link = false;
+ }
+ else
+ // If the openPage failed, we do not need to follow the link.
+ follow_link = openPage( link, OPF_CONTENT_TREE | OPF_ADD2HISTORY );
+}
+
+
+bool KCHMMainWindow::openPage( const QString & srcurl, unsigned int flags )
+{
+ QString p1, p2, url = srcurl;
+
+ if ( url == "/" )
+ url = m_chmFile->homeUrl();
+
+ if ( LCHMUrlFactory::isRemoteURL (url, p1) )
+ {
+ switch ( appConfig.m_onExternalLinkClick )
+ {
+ case KCHMConfig::ACTION_DONT_OPEN:
+ break;
+
+ case KCHMConfig::ACTION_ASK_USER:
+ if ( QMessageBox::question(this,
+ i18n("%1 - remote link clicked - %2") . arg(APP_NAME) . arg(p1),
+ i18n("A remote link %1 will start the external program to open it.\n\nDo you want to continue?").arg( url ),
+ i18n("&Yes"), i18n("&No"),
+ QString::null, 0, 1 ) )
+ return false;
+
+ // no break! should continue to open.
+
+ case KCHMConfig::ACTION_ALWAYS_OPEN:
+ {
+#if defined (USE_KDE)
+ new KRun ( url );
+#else
+ run_process( appConfig.m_QtBrowserPath, url );
+#endif
+ }
+ break;
+ }
+
+ return false; // do not change the current page.
+ }
+
+ // Filter the URLs which do not need to be opened at all by Qt version
+ if ( LCHMUrlFactory::isJavascriptURL (url) )
+ {
+ QMessageBox::information( this,
+ i18n( "%1 - JavsScript link clicked") . arg(APP_NAME),
+ i18n( "You have clicked a JavaScript link.\nTo prevent security-related issues JavaScript URLs are disabled in CHM files.") );
+
+ return false;
+ }
+
+ if ( LCHMUrlFactory::isNewChmURL (url, p1, p2) && p1 != m_chmFilename )
+ {
+ if ( QMessageBox::question( this,
+ i18n( "%1 - link to a new CHM file clicked"). arg(APP_NAME),
+ i18n( "You have clicked a link, which leads to a new CHM file %1.\nThe current file will be closed.\n\nDo you want to continue?").arg( p1 ),
+ i18n( "&Yes" ), i18n( "&No" ),
+ QString::null, 0, 1 ) )
+ return false;
+
+ // Because chm file always contain relative link, and current filename is not changed,
+ // we need to form a new path
+ QFileInfo qfi( m_chmFilename );
+ QString newfilename = qfi.dirPath(true) + "/" + p1;
+
+ QStringList event_args;
+ event_args.push_back( newfilename );
+ event_args.push_back( p2 ); // url
+
+ qApp->postEvent( this, new KCHMUserEvent( "loadAndOpen", event_args ) );
+ return false;
+ }
+
+ KCHMViewWindow * vwnd = currentBrowser();
+ if ( flags & OPF_NEW_TAB )
+ vwnd = m_viewWindowMgr->addNewTab( !(flags & OPF_BACKGROUND) );
+
+ // Store current page and position to add it to history if we change it
+ int hist_scrollpos = currentBrowser()->getScrollbarPosition();
+ QString hist_url = currentBrowser()->getOpenedPage();
+
+ if ( vwnd->openUrl (url) )
+ {
+ // Open all the tree items to show current item (if needed)
+ if ( (flags & OPF_CONTENT_TREE) != 0 )
+ locateInContentTree( vwnd->getOpenedPage() );
+
+ if ( flags & OPF_ADD2HISTORY )
+ currentBrowser()->addNavigationHistory( hist_url, hist_scrollpos );
+ }
+
+ return true;
+}
+
+
+void KCHMMainWindow::showEvent( QShowEvent * )
+{
+ if ( !m_FirstTimeShow )
+ return;
+
+ m_FirstTimeShow = false;
+
+ if ( !parseCmdLineArgs( ) )
+ {
+ if ( appConfig.m_LoadLatestFileOnStartup && appConfig.m_History.size() > 0 )
+ {
+ if ( loadChmFile ( appConfig.m_History[0] ) )
+ return;
+ }
+
+ emit slotOpenMenuItemActivated();
+ }
+}
+
+void KCHMMainWindow::setupToolbarsAndMenu( )
+{
+ // Create a 'file' toolbar
+ QToolBar * toolbar = new QToolBar(this);
+
+ toolbar->setLabel( i18n( "File Operations") );
+
+ QPixmap iconFileOpen (*gIconStorage.getToolbarPixmap(KCHMIconStorage::fileopen));
+ QToolButton * fileOpen = new QToolButton (iconFileOpen,
+ i18n( "Open File" ),
+ QString::null,
+ this,
+ SLOT( slotOpenMenuItemActivated() ),
+ toolbar);
+
+ QString fileOpenText = i18n( "Click this button to open an existing chm file." );
+ QWhatsThis::add( fileOpen, fileOpenText );
+
+ QPixmap iconFilePrint (*gIconStorage.getToolbarPixmap(KCHMIconStorage::print));
+ QToolButton * filePrint = new QToolButton (iconFilePrint,
+ i18n( "Print File" ),
+ QString::null,
+ this,
+ SLOT( slotPrintMenuItemActivated() ),
+ toolbar);
+
+ QString filePrintText = i18n( "Click this button to print the current page");
+ QWhatsThis::add( filePrint, filePrintText );
+
+ // Setup the menu
+ KQPopupMenu * file = new KQPopupMenu( this );
+ menuBar()->insertItem( i18n( "&File"), file );
+
+ int id;
+ id = file->insertItem ( iconFileOpen, i18n( "&Open..."), this, SLOT( slotOpenMenuItemActivated() ), CTRL+Key_O );
+ file->setWhatsThis( id, fileOpenText );
+
+ id = file->insertItem( iconFilePrint, i18n( "&Print..."), this, SLOT( slotPrintMenuItemActivated() ), CTRL+Key_P );
+ file->setWhatsThis( id, filePrintText );
+
+ file->insertSeparator();
+ id = file->insertItem ( i18n( "E&xtract CHM content..."), this, SLOT( slotExtractCHM() ) );
+ file->setWhatsThis( id, i18n( "Click this button to extract the whole CHM file content into a specific directory") );
+ file->insertSeparator();
+
+ m_menuHistory = new KQPopupMenu( file );
+ connect ( m_menuHistory, SIGNAL( activated(int) ), this, SLOT ( slotHistoryMenuItemActivated(int) ));
+
+ file->insertItem( i18n( "&Recent files"), m_menuHistory );
+
+ file->insertSeparator();
+ file->insertItem( i18n( "&Quit"), qApp, SLOT( closeAllWindows() ), CTRL+Key_Q );
+
+ KQPopupMenu * menu_edit = new KQPopupMenu( this );
+ menuBar()->insertItem( i18n( "&Edit"), menu_edit );
+
+ menu_edit->insertItem ( i18n( "&Copy"), this, SLOT( slotBrowserCopy()), CTRL+Key_C );
+ menu_edit->insertItem ( i18n( "&Select all"), this, SLOT( slotBrowserSelectAll()), CTRL+Key_A );
+
+ menu_edit->insertSeparator();
+
+ // KCHMNavToolbar
+ m_navToolbar = new KCHMNavToolbar( this );
+
+ // KCHMSearchToolbar also adds 'view' menu
+ m_searchToolbar = new KCHMSearchAndViewToolbar (this);
+
+ // m_bookmarkWindow adds 'Bookmarks' menu
+ m_bookmarkWindow->createMenu( this );
+
+ // m_viewWindowMgr creates 'Window' menu
+ m_viewWindowMgr->createMenu( this );
+
+ KQPopupMenu * settings = new KQPopupMenu( this );
+ menuBar()->insertItem( i18n( "&Settings"), settings );
+ settings->insertItem( i18n( "&Change settings..."), this, SLOT( slotChangeSettingsMenuItemActivated() ));
+
+#if defined(USE_KDE)
+ QPopupMenu *help = helpMenu( m_aboutDlgMenuText );
+#else
+ KQPopupMenu * help = new KQPopupMenu( this );
+ help->insertItem( i18n( "&About"), this, SLOT( slotAboutMenuItemActivated() ), Key_F1 );
+ help->insertItem( i18n( "About &Qt"), this, SLOT( slotAboutQtMenuItemActivated() ));
+ help->insertSeparator();
+ help->insertItem( i18n( "What's &This"), this, SLOT(whatsThis()), SHIFT+Key_F1 );
+#endif
+
+ menuBar()->insertItem( i18n( "&Help"), help );
+ updateHistoryMenu();
+}
+
+void KCHMMainWindow::slotAddBookmark( )
+{
+ emit m_bookmarkWindow->onAddBookmarkPressed ();
+}
+
+void KCHMMainWindow::setTextEncoding( const LCHMTextEncoding * encoding )
+{
+ m_chmFile->setCurrentEncoding( encoding );
+ m_searchToolbar->setChosenEncodingInMenu( encoding );
+
+ // Because updateView() will call view->invalidate(), which clears the view->getOpenedPage(),
+ // we have to make a copy of it.
+ QString url = currentBrowser()->getOpenedPage();
+
+ // Regenerate the content and index trees
+ refreshCurrentBrowser();
+
+ currentBrowser()->openUrl( url );
+}
+
+void KCHMMainWindow::closeChmFile( )
+{
+ // Prepare the settings
+ if ( appConfig.m_HistoryStoreExtra )
+ {
+ m_currentSettings->m_activeencodinglcid = m_chmFile->currentEncoding()->winlcid;
+ m_currentSettings->m_activetabsystem = m_tabWidget->currentPageIndex( );
+ m_currentSettings->m_activetabwindow = m_viewWindowMgr->currentPageIndex( );
+
+ m_currentSettings->m_window_size_x = width();
+ m_currentSettings->m_window_size_y = height();
+ m_currentSettings->m_window_size_splitter = m_windowSplitter->sizes()[0];
+
+ if ( m_searchWindow )
+ m_searchWindow->saveSettings (m_currentSettings->m_searchhistory);
+
+ m_bookmarkWindow->saveSettings( m_currentSettings->m_bookmarks );
+
+ m_viewWindowMgr->saveSettings( m_currentSettings->m_viewwindows );
+
+ m_currentSettings->saveSettings( );
+ }
+
+ appConfig.save();
+}
+
+
+void KCHMMainWindow::closeEvent ( QCloseEvent * e )
+{
+ // Save the settings if we have something opened
+ if ( m_chmFile )
+ {
+ closeChmFile( );
+ delete m_chmFile;
+ m_chmFile = 0;
+ }
+
+ QMainWindow::closeEvent ( e );
+}
+
+bool KCHMMainWindow::parseCmdLineArgs( )
+{
+ QString filename = QString::null, search_query = QString::null;
+ QString search_index = QString::null, search_bookmark = QString::null;
+ bool do_autotest = false;
+
+#if defined (USE_KDE)
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if ( args->isSet("autotestmode") )
+ do_autotest = true;
+
+ if ( args->isSet("shortautotestmode") )
+ do_autotest = m_useShortAutotest = true;
+
+ search_query = args->getOption ("search");
+ search_index = args->getOption ("sindex");
+
+ if ( args->count() > 0 )
+ filename = args->arg(0);
+#else
+ // argv[0] in Qt is still a program name
+ for ( int i = 1; i < qApp->argc(); i++ )
+ {
+ if ( !strcmp (qApp->argv()[i], "--autotestmode") )
+ do_autotest = m_useShortAutotest = true;
+ else if ( !strcmp (qApp->argv()[i], "--shortautotestmode") )
+ do_autotest = true;
+ else if ( !strcmp (qApp->argv()[i], "--search") )
+ search_query = qApp->argv()[++i];
+ else if ( !strcmp (qApp->argv()[i], "--sindex") )
+ search_index = qApp->argv()[++i];
+ else if ( !strcmp (qApp->argv()[i], "-h") || !strcmp (qApp->argv()[i], "--help") )
+ {
+ fprintf (stderr, "Usage: %s [chmfile]\n", qApp->argv()[0]);
+ exit (1);
+ }
+ else
+ filename = qApp->argv()[i];
+ }
+#endif
+
+ if ( !filename.isEmpty() )
+ {
+ if ( !loadChmFile( QString::fromLocal8Bit( filename )) )
+ return true; // skip the latest checks, but do not exit from the program
+
+ if ( !search_index.isEmpty() )
+ {
+ QStringList event_args;
+ event_args.push_back( search_index );
+ qApp->postEvent( this, new KCHMUserEvent( "findInIndex", event_args ) );
+ }
+
+ if ( !search_query.isEmpty() )
+ {
+ QStringList event_args;
+ event_args.push_back( search_query );
+ qApp->postEvent( this, new KCHMUserEvent( "searchQuery", event_args ) );
+ }
+
+ if ( do_autotest )
+ {
+#if defined (ENABLE_AUTOTEST_SUPPORT)
+ if ( filename.isEmpty() )
+ qFatal ("Could not use Auto Test mode without a chm file!");
+
+ m_autoteststate = STATE_INITIAL;
+ showMinimized ();
+ runAutoTest();
+#else
+ qFatal ("Auto Test mode support is not compiled in.");
+#endif /* defined (ENABLE_AUTOTEST_SUPPORT) */
+ }
+ return true;
+ }
+
+ return false;
+}
+
+void KCHMMainWindow::slotBrowserSelectAll( )
+{
+ currentBrowser()->clipSelectAll();
+}
+
+void KCHMMainWindow::slotBrowserCopy( )
+{
+ currentBrowser()->clipCopy();
+}
+
+void KCHMMainWindow::slotChangeSettingsMenuItemActivated()
+{
+ KCHMSetupDialog dlg ( this );
+
+ // Set up the parameters
+ dlg.m_radioOnBeginOpenDialog->setChecked ( !appConfig.m_LoadLatestFileOnStartup );
+ dlg.m_radioOnBeginOpenLast->setChecked ( appConfig.m_LoadLatestFileOnStartup );
+ dlg.m_historySize->setValue ( appConfig.m_HistorySize );
+ dlg.m_rememberHistoryInfo->setChecked ( appConfig.m_HistoryStoreExtra );
+
+ dlg.m_radioExtLinkOpenAlways->setChecked ( appConfig.m_onExternalLinkClick == KCHMConfig::ACTION_ALWAYS_OPEN );
+ dlg.m_radioExtLinkAsk->setChecked ( appConfig.m_onExternalLinkClick == KCHMConfig::ACTION_ASK_USER );
+ dlg.m_radioExtLinkOpenNever->setChecked ( appConfig.m_onExternalLinkClick == KCHMConfig::ACTION_DONT_OPEN );
+
+ dlg.m_radioNewChmOpenAlways->setChecked ( appConfig.m_onNewChmClick == KCHMConfig::ACTION_ALWAYS_OPEN );
+ dlg.m_radioNewChmAsk->setChecked ( appConfig.m_onNewChmClick == KCHMConfig::ACTION_ASK_USER );
+ dlg.m_radioNewChmOpenNever->setChecked ( appConfig.m_onNewChmClick == KCHMConfig::ACTION_DONT_OPEN );
+
+#if defined (USE_KDE)
+ dlg.m_groupQtsettings->setEnabled ( false );
+ dlg.m_groupKDEsettings->setEnabled ( true );
+#else
+ dlg.m_groupQtsettings->setEnabled ( true );
+ dlg.m_groupKDEsettings->setEnabled ( false );
+#endif
+
+ dlg.m_qtBrowserPath->setText ( appConfig.m_QtBrowserPath );
+ dlg.m_radioUseQtextBrowser->setChecked ( appConfig.m_kdeUseQTextBrowser );
+ dlg.m_radioUseKHTMLPart->setChecked ( !appConfig.m_kdeUseQTextBrowser );
+
+ dlg.m_enableJS->setChecked ( appConfig.m_kdeEnableJS );
+ dlg.m_enablePlugins->setChecked ( appConfig.m_kdeEnablePlugins );
+ dlg.m_enableJava->setChecked ( appConfig.m_kdeEnableJava );
+ dlg.m_enableRefresh->setChecked ( appConfig.m_kdeEnableRefresh );
+
+ dlg.m_advExternalProgramName->setText( appConfig.m_advExternalEditorPath );
+ dlg.m_advViewSourceExternal->setChecked ( !appConfig.m_advUseInternalEditor );
+ dlg.m_advViewSourceInternal->setChecked ( appConfig.m_advUseInternalEditor );
+
+ // Search engine
+ dlg.m_useSearchEngineInternal->setChecked( appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_CHM );
+ dlg.m_useSearchEngineNew->setChecked( appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_MINE );
+
+ // Connect buddies
+ dlg.m_labelUseSearchEngineInternal->setBuddy( dlg.m_useSearchEngineInternal );
+ dlg.m_labelUseSearchEngineNew->setBuddy( dlg.m_useSearchEngineNew );
+
+ if ( dlg.exec() == QDialog::Accepted )
+ {
+ appConfig.m_LoadLatestFileOnStartup = dlg.m_radioOnBeginOpenLast->isChecked();
+ appConfig.m_HistorySize = dlg.m_historySize->value();
+ appConfig.m_HistoryStoreExtra = dlg.m_rememberHistoryInfo->isChecked();
+
+ if ( dlg.m_radioExtLinkOpenAlways->isChecked () )
+ appConfig.m_onExternalLinkClick = KCHMConfig::ACTION_ALWAYS_OPEN;
+ else if ( dlg.m_radioExtLinkAsk->isChecked () )
+ appConfig.m_onExternalLinkClick = KCHMConfig::ACTION_ASK_USER;
+ else
+ appConfig.m_onExternalLinkClick = KCHMConfig::ACTION_DONT_OPEN;
+
+ if ( dlg.m_radioNewChmOpenAlways->isChecked () )
+ appConfig.m_onNewChmClick = KCHMConfig::ACTION_ALWAYS_OPEN;
+ else if ( dlg.m_radioNewChmAsk->isChecked () )
+ appConfig.m_onNewChmClick = KCHMConfig::ACTION_ASK_USER;
+ else
+ appConfig.m_onNewChmClick = KCHMConfig::ACTION_DONT_OPEN;
+
+ appConfig.m_QtBrowserPath = dlg.m_qtBrowserPath->text();
+
+ // Check the changes
+ bool need_restart = false;
+
+ if ( appConfig.m_kdeEnableJS != dlg.m_enableJS->isChecked() )
+ {
+ need_restart = true;
+ appConfig.m_kdeEnableJS = dlg.m_enableJS->isChecked();
+ }
+
+ if ( appConfig.m_kdeEnablePlugins != dlg.m_enablePlugins->isChecked() )
+ {
+ need_restart = true;
+ appConfig.m_kdeEnablePlugins = dlg.m_enablePlugins->isChecked();
+ }
+
+ if ( appConfig.m_kdeEnableJava != dlg.m_enableJava->isChecked() )
+ {
+ need_restart = true;
+ appConfig.m_kdeEnableJava = dlg.m_enableJava->isChecked();
+ }
+
+ if ( appConfig.m_kdeEnableRefresh != dlg.m_enableRefresh->isChecked() )
+ {
+ need_restart = true;
+ appConfig.m_kdeEnableRefresh = dlg.m_enableRefresh->isChecked();
+ }
+
+ if ( appConfig.m_kdeUseQTextBrowser != dlg.m_radioUseQtextBrowser->isChecked() )
+ {
+ need_restart = true;
+ appConfig.m_kdeUseQTextBrowser = dlg.m_radioUseQtextBrowser->isChecked();
+ }
+
+ if ( dlg.m_useSearchEngineNew->isChecked()
+ && appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_CHM )
+ {
+ appConfig.m_useSearchEngine = KCHMConfig::SEARCH_USE_MINE;
+ m_searchWindow->invalidate();
+ }
+
+ if ( dlg.m_useSearchEngineInternal->isChecked()
+ && appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_MINE )
+ {
+ appConfig.m_useSearchEngine = KCHMConfig::SEARCH_USE_CHM;
+ m_searchWindow->invalidate();
+ }
+
+ appConfig.m_advExternalEditorPath = dlg.m_advExternalProgramName->text();
+ appConfig.m_advUseInternalEditor = dlg.m_advViewSourceExternal->isChecked();
+ appConfig.m_advUseInternalEditor = dlg.m_advViewSourceInternal->isChecked();
+
+ appConfig.save();
+
+ if ( need_restart )
+ QMessageBox::information(
+ this,
+ APP_NAME,
+ i18n( "Changing browser view options or search engine used\n"
+ "requires restarting the application to take effect." ) );
+ }
+}
+
+
+void KCHMMainWindow::setupSignals( )
+{
+#if defined(HAVE_SIGACTION)
+ struct sigaction sa;
+ memset ((char *)&sa, 0, sizeof(sa));
+ sigemptyset (&sa.sa_mask);
+ sigaddset (&sa.sa_mask, SIGCHLD);
+
+#ifdef SA_RESTART
+ sa.sa_flags = SA_RESTART;
+#endif
+
+ sa.sa_handler = SIG_IGN;
+ sigaction (SIGCHLD, &sa, (struct sigaction *)0);
+#else /* !HAVE_SIGACTION */
+ signal (SIGCHLD, SIG_IGN);
+#endif /* HAVE_SIGACTION */
+}
+
+void KCHMMainWindow::slotHistoryMenuItemActivated( int item )
+{
+ if ( item < 0 || item >= (signed) appConfig.m_History.size() )
+ qFatal ("KCHMMainWindow::slotHistoryMenuItemActivated: bad history menu id %d", item);
+
+ QString filename = appConfig.m_History[item];
+
+ // remove it, so it will be added again at the history top, and will not shitf anything.
+// appConfig.m_History.remove ( appConfig.m_History.begin() + item);
+ loadChmFile ( filename );
+}
+
+void KCHMMainWindow::updateHistoryMenu()
+{
+ m_menuHistory->clear ();
+
+ for ( int i = appConfig.m_History.size() - 1; i >= 0; i-- )
+ m_menuHistory->insertItem( appConfig.m_History[i], i );
+}
+
+void KCHMMainWindow::slotActivateContentTab( )
+{
+ if ( m_tabContextPage != -1 )
+ m_tabWidget->setCurrentPage( m_tabContextPage );
+}
+
+void KCHMMainWindow::slotActivateIndexTab( )
+{
+ if ( m_tabIndexPage != -1 )
+ m_tabWidget->setCurrentPage( m_tabIndexPage );
+}
+
+void KCHMMainWindow::slotActivateSearchTab( )
+{
+ if ( m_tabSearchPage != -1 )
+ m_tabWidget->setCurrentPage( m_tabSearchPage );
+}
+
+void KCHMMainWindow::slotActivateBookmarkTab( )
+{
+ m_tabWidget->setCurrentPage( m_tabBookmarkPage );
+}
+
+void KCHMMainWindow::showOrHideContextWindow( int tabindex )
+{
+ if ( tabindex == -1 )
+ {
+ if ( m_contentsWindow )
+ {
+ m_tabWidget->removePage (m_contentsWindow);
+ delete m_contentsWindow;
+ m_contentsWindow = 0;
+ }
+ }
+ else
+ {
+ if ( !m_contentsWindow )
+ {
+ m_contentsWindow = new KCHMContentsWindow( m_tabWidget );
+
+ // Handle clicking on m_contentsWindow element
+ connect( m_contentsWindow,
+ SIGNAL( clicked( QListViewItem* ) ),
+ this,
+ SLOT( slotOnTreeClicked( QListViewItem* ) ) );
+
+ connect( m_contentsWindow,
+ SIGNAL( doubleClicked ( QListViewItem *, const QPoint &, int ) ),
+ this,
+ SLOT( slotOnTreeDoubleClicked ( QListViewItem *, const QPoint &, int ) ) );
+
+ m_tabWidget->insertTab (m_contentsWindow, i18n( "Contents" ), tabindex);
+ }
+ }
+}
+
+void KCHMMainWindow::showOrHideIndexWindow( int tabindex )
+{
+ // Test whether to show/invalidate the index window
+ if ( tabindex == -1 )
+ {
+ if ( m_indexWindow )
+ {
+ m_tabWidget->removePage (m_indexWindow);
+ delete m_indexWindow;
+ m_indexWindow = 0;
+ }
+ }
+ else
+ {
+ if ( !m_indexWindow )
+ {
+ m_indexWindow = new KCHMIndexWindow (m_tabWidget);
+ m_tabWidget->insertTab (m_indexWindow, i18n( "Index" ), tabindex);
+ }
+ else
+ m_indexWindow->invalidate();
+ }
+}
+
+void KCHMMainWindow::showOrHideSearchWindow( int tabindex )
+{
+ if ( tabindex == -1 )
+ {
+ if ( m_searchWindow )
+ {
+ m_tabWidget->removePage (m_searchWindow);
+ delete m_searchWindow;
+ m_searchWindow = 0;
+ }
+ }
+ else
+ {
+ if ( !m_searchWindow )
+ {
+ m_searchWindow = new KCHMSearchWindow (m_tabWidget);
+ m_tabWidget->insertTab (m_searchWindow, i18n( "Search" ), tabindex);
+ }
+ else
+ m_searchWindow->invalidate();
+ }
+}
+
+void KCHMMainWindow::slotEnableFullScreenMode( bool enable )
+{
+ if ( enable )
+ {
+ if ( !isFullScreen() )
+ {
+ showFullScreen ();
+ menuBar()->hide();
+ statusBar()->hide();
+ }
+ }
+ else
+ {
+ if ( isFullScreen() )
+ {
+ showNormal ();
+ menuBar()->show();
+ statusBar()->show();
+ }
+ }
+}
+
+void KCHMMainWindow::slotShowContentsWindow( bool show )
+{
+ if ( show )
+ m_tabWidget->show();
+ else
+ m_tabWidget->hide();
+}
+
+void KCHMMainWindow::slotToggleFullScreenMode( )
+{
+ slotEnableFullScreenMode( !isFullScreen() );
+}
+
+void KCHMMainWindow::slotLocateInContentWindow( )
+{
+ // There may be no content tab at all
+ if ( !m_contentsWindow || m_tabContextPage == -1 )
+ return;
+
+ // Activate a content tab
+ m_tabWidget->setCurrentPage( m_tabContextPage );
+
+ if ( m_contentsWindow )
+ {
+ // Open all the tree items to show current item (if needed)
+ KCHMIndTocItem * treeitem = m_contentsWindow->getTreeItem( currentBrowser()->getOpenedPage() );
+
+ if ( treeitem )
+ {
+ KCHMIndTocItem * itemparent = treeitem;
+
+ while ( (itemparent = (KCHMIndTocItem*) itemparent->parent()) != 0 )
+ itemparent->setOpen(true);
+
+ m_contentsWindow->setCurrentItem (treeitem);
+ m_contentsWindow->ensureItemVisible (treeitem);
+ }
+ else
+ statusBar()->message( i18n( "Could not locate opened topic in content window"), 2000 );
+ }
+}
+
+void KCHMMainWindow::slotExtractCHM( )
+{
+ QStringList files;
+
+#if defined (USE_KDE)
+ QString outdir = KFileDialog::getExistingDirectory (
+ QString::null,
+ this,
+ i18n("Choose a directory to store CHM content") );
+#else
+ QString outdir = QFileDialog::getExistingDirectory (
+ QString::null,
+ this,
+ 0,
+ i18n("Choose a directory to store CHM content"),
+ TRUE );
+#endif
+
+ if ( outdir.isEmpty() )
+ return;
+
+ outdir += "/";
+
+ // Enumerate all the files in archive
+ if ( !m_chmFile || !m_chmFile->enumerateFiles( &files ) )
+ return;
+
+ KQProgressModalDialog progress( i18n("Extracting CHM content"), i18n("Extracting files..."), i18n("Abort"), files.size(), this );
+
+ for ( unsigned int i = 0; i < files.size(); i++ )
+ {
+ progress.setProgress( i );
+
+ if ( (i % 3) == 0 )
+ {
+ qApp->processEvents();
+
+ if ( progress.wasCancelled() )
+ break;
+ }
+
+ // Extract the file
+ QByteArray buf;
+
+ if ( m_chmFile->getFileContentAsBinary( &buf, files[i] ) )
+ {
+ // Split filename to get the list of subdirectories
+ QStringList dirs = QStringList::split( '/', files[i] );
+
+ // Walk through the list of subdirectories, and create them if needed
+ // dirlevel is used to detect extra .. and prevent overwriting files
+ // outside the directory (like creating the file images/../../../../../etc/passwd
+ unsigned int i, dirlevel = 0;
+ QStringList dirlist;
+
+ for ( i = 0; i < dirs.size() - 1; i++ )
+ {
+ // Skip .. which lead too far above
+ if ( dirs[i] == ".." )
+ {
+ if ( dirlevel > 0 )
+ {
+ dirlevel--;
+ dirlist.pop_back();
+ }
+ }
+ else
+ {
+ dirlist.push_back( dirs[i] );
+
+ QDir dir ( outdir + dirlist.join( "/" ) );
+ if ( !dir.exists() )
+ {
+ if ( !dir.mkdir( dir.path() ) )
+ qWarning( "Could not create subdir %s\n", dir.path().ascii() );
+ }
+ }
+ }
+
+ QString filename = outdir + dirlist.join( "/" ) + "/" + dirs[i];
+ QFile wf( filename );
+ if ( !wf.open( IO_WriteOnly ) )
+ {
+ qWarning( "Could not write file %s\n", filename.ascii() );
+ continue;
+ }
+
+ wf. writeBlock( buf );
+ wf.close();
+ }
+ else
+ qWarning( "Could not get file %s\n", files[i].ascii() );
+ }
+
+ progress.setProgress( files.size() );
+}
+
+KCHMViewWindow * KCHMMainWindow::currentBrowser( ) const
+{
+ return m_viewWindowMgr->current();
+}
+
+void KCHMMainWindow::slotOpenPageInNewTab( )
+{
+ openPage( currentBrowser()->getNewTabLink(), OPF_NEW_TAB | OPF_CONTENT_TREE );
+}
+
+void KCHMMainWindow::slotOpenPageInNewBackgroundTab( )
+{
+ openPage( currentBrowser()->getNewTabLink(), OPF_NEW_TAB | OPF_BACKGROUND );
+}
+
+void KCHMMainWindow::slotBrowserChanged( KCHMViewWindow * newbrowser )
+{
+ locateInContentTree( newbrowser->getOpenedPage() );
+}
+
+void KCHMMainWindow::locateInContentTree( const QString & url )
+{
+ if ( !m_contentsWindow )
+ return;
+
+ KCHMIndTocItem * treeitem = m_contentsWindow->getTreeItem( url );
+
+ if ( treeitem )
+ {
+ KCHMIndTocItem * itemparent = treeitem;
+ while ( (itemparent = (KCHMIndTocItem*) itemparent->parent()) != 0 )
+ itemparent->setOpen(true);
+
+ m_contentsWindow->setCurrentItem (treeitem);
+ m_contentsWindow->ensureItemVisible (treeitem);
+ }
+}
+
+void KCHMMainWindow::slotOnTreeDoubleClicked( QListViewItem * item, const QPoint &, int )
+{
+ // Open/close only existing item which have children
+ if ( !item || item->childCount() == 0 )
+ return;
+
+ item->setOpen( !item->isOpen() );
+ item->repaint();
+}
+
+bool KCHMMainWindow::event( QEvent * e )
+{
+ if ( e->type() == QEvent::User )
+ return handleUserEvent( (KCHMUserEvent*) e );
+
+ return QWidget::event( e );
+}
+
+bool KCHMMainWindow::handleUserEvent( const KCHMUserEvent * event )
+{
+ if ( event->m_action == "loadAndOpen" )
+ {
+ if ( event->m_args.size() != 1 && event->m_args.size() != 2 )
+ qFatal("handleUserEvent: event loadAndOpen must receive 1 or 2 args");
+
+ QString chmfile = event->m_args[0];
+ QString openurl = event->m_args.size() > 1 ? event->m_args[1] : "/";
+
+ return loadChmFile( chmfile, false ) && openPage( openurl );
+ }
+ else if ( event->m_action == "openPage" )
+ {
+ if ( event->m_args.size() != 1 )
+ qFatal("handleUserEvent: event openPage must receive 1 arg");
+
+ return openPage( event->m_args[0] );
+ }
+ else if ( event->m_action == "findInIndex" )
+ {
+ if ( event->m_args.size() != 1 )
+ qFatal( "handleUserEvent: event searchQuery must receive 1 arg" );
+
+ if ( m_tabIndexPage == -1 )
+ return false;
+
+ slotActivateIndexTab();
+ m_indexWindow->search( event->m_args[0] );
+ return true;
+ }
+ else if ( event->m_action == "searchQuery" )
+ {
+ if ( event->m_args.size() != 1 )
+ qFatal( "handleUserEvent: event searchQuery must receive 1 arg" );
+
+ if ( m_tabSearchPage == -1 )
+ return false;
+
+ slotActivateSearchTab();
+ m_searchWindow->execSearchQueryInGui( event->m_args[0] );
+ return true;
+ }
+ else
+ qWarning( "Unknown user event received: %s", event->m_action.ascii() );
+
+ return false;
+}
+
+
+#if defined (ENABLE_AUTOTEST_SUPPORT)
+void KCHMMainWindow::runAutoTest()
+{
+ KCHMIndTocItem * item;
+
+ switch (m_autoteststate)
+ {
+ case STATE_INITIAL:
+ if ( m_contentsWindow && !m_useShortAutotest )
+ {
+ m_autotestlistiterator = QListViewItemIterator (m_contentsWindow);
+ m_autoteststate = STATE_CONTENTS_OPENNEXTPAGE;
+ }
+ else
+ m_autoteststate = STATE_OPEN_INDEX;
+
+ QTimer::singleShot (500, this, SLOT(runAutoTest()) );
+ break; // allow to finish the initialization sequence
+
+ case STATE_CONTENTS_OPENNEXTPAGE:
+ if ( (item = (KCHMIndTocItem *) m_autotestlistiterator.current()) != 0 )
+ {
+ openPage( item->getUrl(), OPF_CONTENT_TREE | OPF_ADD2HISTORY );
+ m_autotestlistiterator++;
+ }
+ else
+ m_autoteststate = STATE_OPEN_INDEX;
+
+ QTimer::singleShot (50, this, SLOT(runAutoTest()) );
+ break;
+
+ case STATE_OPEN_INDEX:
+ if ( m_indexWindow )
+ m_tabWidget->setCurrentPage (1);
+
+ m_autoteststate = STATE_SHUTDOWN;
+ QTimer::singleShot (500, this, SLOT(runAutoTest()) );
+ break;
+
+ case STATE_SHUTDOWN:
+ qApp->quit();
+ break;
+
+ default:
+ break;
+ }
+}
+#endif /* defined (ENABLE_AUTOTEST_SUPPORT) */
+
+
+//TODO: KDE: xmlgui
+//TODO: Search result highlighting
diff --git a/src/kchmmainwindow.h b/src/kchmmainwindow.h
new file mode 100644
index 0000000..7381567
--- /dev/null
+++ b/src/kchmmainwindow.h
@@ -0,0 +1,191 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMMAINWINDOW_H
+#define KCHMMAINWINDOW_H
+
+#include "kde-qt.h"
+
+#include "libchmfile.h"
+
+#include "forwarddeclarations.h"
+#include "kchmviewwindow.h"
+
+
+#define ENABLE_AUTOTEST_SUPPORT
+
+//! OpenPage extra flags, specifying extra behavior
+
+//! Locate this page in the content tree, and move the cursor there
+static const unsigned int OPF_CONTENT_TREE = 1 << 0;
+//! Add the previous page into the history
+static const unsigned int OPF_ADD2HISTORY = 1 << 1;
+//! Open the page in a new tab
+static const unsigned int OPF_NEW_TAB = 1 << 2;
+//! Open the page in a new tab in background
+static const unsigned int OPF_BACKGROUND = 1 << 3;
+
+//! Those events could be sent to main window to do useful things. See handleUserEvents()
+class KCHMUserEvent : public QEvent
+{
+ public:
+ KCHMUserEvent( const QString& action, const QStringList& args = QStringList())
+ : QEvent( QEvent::User ), m_action(action), m_args(args) {};
+
+ QString m_action;
+ QStringList m_args;
+};
+
+
+class KCHMMainWindow : public KQMainWindow
+{
+ Q_OBJECT
+
+ public:
+ KCHMMainWindow();
+ ~KCHMMainWindow();
+
+ bool openPage ( const QString &url, unsigned int flags = OPF_CONTENT_TREE );
+
+ LCHMFile * chmFile() const { return m_chmFile; }
+ const QString& getOpenedFileName () { return m_chmFilename; }
+
+ KCHMViewWindow * currentBrowser() const;
+ KCHMContentsWindow * contentsWindow() const { return m_contentsWindow; }
+ KCHMSettings * currentSettings() const { return m_currentSettings; }
+ KCHMViewWindowMgr* viewWindowMgr() const { return m_viewWindowMgr; }
+ KCHMNavToolbar * navigationToolbar() const { return m_navToolbar; }
+ KCHMSearchWindow * searchWindow() const { return m_searchWindow; }
+
+ void showInStatusBar (const QString& text) { statusBar()->message( text, 2000 ); }
+ void setTextEncoding (const LCHMTextEncoding * enc);
+
+ public slots:
+ void slotOnTreeClicked( QListViewItem *item );
+ void slotOnTreeDoubleClicked( QListViewItem *item, const QPoint &, int );
+
+ void slotAddBookmark ( );
+ void slotOpenPageInNewTab( );
+ void slotOpenPageInNewBackgroundTab( );
+ void slotEnableFullScreenMode( bool enable );
+ void slotShowContentsWindow( bool show );
+ void slotLocateInContentWindow( );
+ void slotBrowserChanged( KCHMViewWindow * newbrowser );
+
+ private slots:
+ void slotLinkClicked ( const QString & link, bool& follow_link );
+
+ void slotOpenMenuItemActivated();
+ void slotPrintMenuItemActivated();
+
+ void slotAboutMenuItemActivated();
+ void slotAboutQtMenuItemActivated();
+
+ void slotActivateContentTab();
+ void slotActivateIndexTab();
+ void slotActivateSearchTab();
+ void slotActivateBookmarkTab();
+
+ void slotBrowserSelectAll();
+ void slotBrowserCopy();
+ void slotExtractCHM();
+
+ void slotChangeSettingsMenuItemActivated();
+ void slotHistoryMenuItemActivated ( int );
+
+ void slotToggleFullScreenMode( );
+
+ void slotNavigateBack() { currentBrowser()->navigateBack(); }
+ void slotNavigateHome() { currentBrowser()->navigateHome(); }
+ void slotNavigateForward(){ currentBrowser()->navigateForward(); }
+
+ private:
+ bool parseCmdLineArgs();
+ void showEvent( QShowEvent * );
+ void closeEvent ( QCloseEvent * e );
+ void setupSignals ();
+
+ void setupToolbarsAndMenu ( );
+ bool loadChmFile ( const QString &fileName, bool call_open_page = true );
+ void closeChmFile();
+ void refreshCurrentBrowser();
+ void updateHistoryMenu();
+
+ void showOrHideContextWindow( int tabindex );
+ void showOrHideIndexWindow( int tabindex );
+ void showOrHideSearchWindow( int tabindex );
+
+ // User events
+ bool event ( QEvent * e );
+ bool handleUserEvent( const KCHMUserEvent * event );
+
+ void locateInContentTree( const QString& url );
+
+ QString m_chmFilename;
+ QString m_aboutDlgMenuText; // to show in KDE or Qt about dialogs
+
+ KCHMViewWindowMgr * m_viewWindowMgr;
+ KCHMIndexWindow * m_indexWindow;
+ KCHMSearchWindow * m_searchWindow;
+ KCHMBookmarkWindow * m_bookmarkWindow;
+ KCHMContentsWindow * m_contentsWindow;
+
+ KQTabWidget * m_tabWidget;
+ QSplitter * m_windowSplitter;
+
+ KCHMSearchAndViewToolbar * m_searchToolbar;
+ KCHMNavToolbar * m_navToolbar;
+
+ KCHMSettings * m_currentSettings;
+
+ LCHMFile * m_chmFile;
+ bool m_FirstTimeShow;
+
+ KQPopupMenu * m_menuHistory;
+
+ int m_tabContextPage;
+ int m_tabIndexPage;
+ int m_tabSearchPage;
+ int m_tabBookmarkPage;
+
+#if defined (ENABLE_AUTOTEST_SUPPORT)
+ enum auto_test_state_t
+ {
+ STATE_OFF,
+ STATE_INITIAL,
+ STATE_CONTENTS_OPENNEXTPAGE,
+ STATE_OPEN_INDEX,
+ STATE_SHUTDOWN
+ };
+
+ bool m_useShortAutotest;
+ auto_test_state_t m_autoteststate;
+ QListViewItemIterator m_autotestlistiterator;
+
+ private slots:
+ void runAutoTest();
+#endif /* defined (ENABLE_AUTOTEST_SUPPORT) */
+
+};
+
+extern KCHMMainWindow * mainWindow;
+
+#endif // KCHMMAINWINDOW_H
diff --git a/src/kchmnavtoolbar.cpp b/src/kchmnavtoolbar.cpp
new file mode 100644
index 0000000..f0f004f
--- /dev/null
+++ b/src/kchmnavtoolbar.cpp
@@ -0,0 +1,75 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kde-qt.h"
+#include "kchmnavtoolbar.h"
+#include "kchmmainwindow.h"
+#include "kchmviewwindow.h"
+#include "iconstorage.h"
+
+
+KCHMNavToolbar::KCHMNavToolbar( KCHMMainWindow *parent )
+ : QToolBar( parent )
+{
+ // Initialize toolbar
+ setLabel( i18n( "Navigation") );
+
+ QPixmap iconBackward (*gIconStorage.getToolbarPixmap(KCHMIconStorage::back));
+ m_toolbarIconBackward = new QToolButton (iconBackward,
+ i18n( "Move backward in history"),
+ QString::null,
+ parent,
+ SLOT( slotNavigateBack() ),
+ this);
+ QWhatsThis::add( m_toolbarIconBackward, i18n( "Click this button to move backward in browser history") );
+
+ QPixmap iconForward (*gIconStorage.getToolbarPixmap(KCHMIconStorage::forward));
+ m_toolbarIconForward = new QToolButton (iconForward,
+ i18n( "Move forward in history"),
+ QString::null,
+ parent,
+ SLOT( slotNavigateForward() ),
+ this);
+ QWhatsThis::add( m_toolbarIconForward, i18n( "Click this button to move forward in browser history") );
+
+ QPixmap iconHome = (*gIconStorage.getToolbarPixmap(KCHMIconStorage::gohome));
+ QToolButton * hb = new QToolButton (iconHome,
+ i18n( "Go to the home page"),
+ QString::null,
+ parent,
+ SLOT( slotNavigateHome() ),
+ this);
+ QWhatsThis::add( hb, i18n( "Click this button to move to the home page") );
+}
+
+
+KCHMNavToolbar::~KCHMNavToolbar()
+{
+}
+
+void KCHMNavToolbar::updateIconStatus( bool enable_backward, bool enable_forward )
+{
+ m_toolbarIconBackward->setEnabled( enable_backward );
+ m_toolbarIconForward->setEnabled ( enable_forward );
+}
+
+
+#include "kchmnavtoolbar.moc"
diff --git a/src/kchmnavtoolbar.h b/src/kchmnavtoolbar.h
new file mode 100644
index 0000000..ea10c84
--- /dev/null
+++ b/src/kchmnavtoolbar.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef INCLUDE_KCHMNAVHISTORY_H
+#define INCLUDE_KCHMNAVHISTORY_H
+
+#include "forwarddeclarations.h"
+
+class KCHMNavToolbar : public QToolBar
+{
+Q_OBJECT
+public:
+ KCHMNavToolbar( KCHMMainWindow *parent );
+ ~KCHMNavToolbar();
+
+public slots:
+ void updateIconStatus( bool enable_backward, bool enable_forward );
+
+private:
+ QToolButton * m_toolbarIconBackward;
+ QToolButton * m_toolbarIconForward;
+};
+
+#endif /* INCLUDE_KCHMNAVHISTORY_H */
diff --git a/src/kchmsearchengine.cpp b/src/kchmsearchengine.cpp
new file mode 100644
index 0000000..6bd6c5e
--- /dev/null
+++ b/src/kchmsearchengine.cpp
@@ -0,0 +1,257 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qapplication.h>
+
+#include "kchmmainwindow.h"
+#include "kchmsearchengine.h"
+#include "kchmconfig.h"
+#include "kchmsettings.h"
+#include "libchmurlfactory.h"
+
+#include "kchmsearchengine_impl.h"
+
+#include "kchmsearchengine.moc"
+
+
+
+KCHMSearchEngine::KCHMSearchEngine()
+{
+ m_Index = 0;
+ m_progressDlg = 0;
+}
+
+
+KCHMSearchEngine::~KCHMSearchEngine()
+{
+ delete m_Index;
+ delete m_progressDlg;
+}
+
+void KCHMSearchEngine::processEvents( )
+{
+ // Do it twice; some events generate other events
+ qApp->eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
+ qApp->eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
+}
+
+
+void KCHMSearchEngine::cancelButtonPressed( )
+{
+ m_Index->setLastWinClosed();
+}
+
+
+bool KCHMSearchEngine::loadOrGenerateIndex( )
+{
+ if ( m_Index )
+ return true;
+
+ QString indexfiledict = ::mainWindow->currentSettings()->searchIndexDictFilename();
+ QString indexfiledoc = ::mainWindow->currentSettings()->searchIndexDocFilename();
+ QStringList documents;
+
+ m_Index = new QtAs::Index( documents, appConfig.m_datapath );
+ m_Index->setDictionaryFile( indexfiledict );
+ m_Index->setDocListFile( indexfiledoc );
+
+ m_progressDlg = new QProgressDialog( 0 );
+ connect( m_progressDlg, SIGNAL( canceled() ), this, SLOT( cancelButtonPressed() ) );
+
+ connect( m_Index, SIGNAL( indexingProgress( int ) ), this, SLOT( setIndexingProgress( int ) ) );
+ KCHMShowWaitCursor waitcursor;
+
+ QFile f( indexfiledict );
+ if ( !f.exists() )
+ {
+ ::mainWindow->statusBar()->message( tr( "Generating search index..." ) );
+
+ // Get the list of files in CHM archive
+ QStringList alldocuments;
+
+ m_progressDlg->setCaption( tr( "Generating search index..." ) );
+ m_progressDlg->setLabelText( tr( "Generating search index..." ) );
+ m_progressDlg->setTotalSteps( 100 );
+ m_progressDlg->reset();
+ m_progressDlg->show();
+ processEvents();
+
+ if ( !::mainWindow->chmFile()->enumerateFiles( &alldocuments ) )
+ {
+ delete m_progressDlg;
+ m_progressDlg = 0;
+ return false;
+ }
+
+ // Process the list keeping only HTML documents there
+ for ( unsigned int i = 0; i < alldocuments.size(); i++ )
+ if ( alldocuments[i].endsWith( ".html", false ) || alldocuments[i].endsWith( ".htm", false ) )
+ documents.push_back( LCHMUrlFactory::makeURLabsoluteIfNeeded( alldocuments[i] ) );
+
+ m_Index->setDocList( documents );
+
+ if ( m_Index->makeIndex() != -1 )
+ {
+ m_Index->writeDict();
+ m_keywordDocuments.clear();
+ }
+ else
+ return false;
+ }
+ else
+ {
+ ::mainWindow->statusBar()->message( tr( "Reading dictionary..." ) );
+ processEvents();
+
+ m_Index->readDict();
+ }
+
+ ::mainWindow->statusBar()->message( tr( "Done" ), 3000 );
+ delete m_progressDlg;
+ m_progressDlg = 0;
+
+ return true;
+}
+
+
+void KCHMSearchEngine::setIndexingProgress( int progress )
+{
+ if ( progress <= 100 )
+ m_progressDlg->setProgress( progress );
+
+ processEvents();
+}
+
+// Helper class to simplity state management and data keeping
+class SearchDataKeeper
+{
+ public:
+ SearchDataKeeper() { m_inPhrase = false; }
+
+ void beginPhrase()
+ {
+ phrase_terms.clear();
+ m_inPhrase = true;
+ }
+
+ void endPhrase()
+ {
+ m_inPhrase = false;
+ phrasewords += phrase_terms;
+ phrases.push_back( phrase_terms.join(" ") );
+ }
+
+ bool isInPhrase() const { return m_inPhrase; }
+
+ void addTerm( const QString& term )
+ {
+ if ( !term.isEmpty() )
+ {
+ terms.push_back( term );
+
+ if ( m_inPhrase )
+ phrase_terms.push_back( term );
+ }
+ }
+
+ // Should contain all the search terms present in query, includind those from phrases. One element - one term .
+ QStringList terms;
+
+ // Should contain phrases present in query without quotes. One element - one phrase.
+ QStringList phrases;
+
+ // Should contain all the terms present in all the phrases (but not outside).
+ QStringList phrasewords;
+
+ private:
+ bool m_inPhrase;
+ QStringList phrase_terms;
+};
+
+
+bool KCHMSearchEngine::searchQuery( const QString & query, QStringList * results, unsigned int limit )
+{
+ // Characters which split the words. We need to make them separate tokens
+ QString splitChars = m_Index->getCharsSplit();
+
+ // Characters which are part of the word. We should keep them apart.
+ QString partOfWordChars = m_Index->getCharsPartOfWord();
+
+ SearchDataKeeper keeper;
+
+ // State machine variables
+ QString term;
+
+ for ( unsigned int i = 0; i < query.length(); i++ )
+ {
+ QChar ch = query[i].lower();
+
+ // a quote either begins or ends the phrase
+ if ( ch == '"' )
+ {
+ keeper.addTerm( term );
+
+ if ( keeper.isInPhrase() )
+ keeper.endPhrase();
+ else
+ keeper.beginPhrase();
+
+ continue;
+ }
+
+ // If new char does not stop the word, add ot and continue
+ if ( ch.isLetterOrNumber() || partOfWordChars.find( ch ) != -1 )
+ {
+ term.append( ch );
+ continue;
+ }
+
+ // If it is a split char, add this term and split char as separate term
+ if ( splitChars.find( ch ) != -1 )
+ {
+ // Add existing term if present
+ keeper.addTerm( term );
+
+ // Change the term variable, so it will be added when we exit this block
+ term = ch;
+ }
+
+ // Just add the word; it is most likely a space or terminated by tokenizer.
+ keeper.addTerm( term );
+ term = QString::null;
+ }
+
+ keeper.addTerm( term );
+
+ if ( keeper.isInPhrase() )
+ {
+ QMessageBox::warning( 0, i18n( "Search" ), i18n( "A closing quote character is missing." ) );
+ return false;
+ }
+
+ KCHMShowWaitCursor waitcursor;
+ QStringList foundDocs = m_Index->query( keeper.terms, keeper.phrases, keeper.phrasewords );
+
+ for ( QStringList::iterator it = foundDocs.begin(); it != foundDocs.end() && limit > 0; ++it, limit-- )
+ results->push_back( *it );
+
+ return true;
+}
diff --git a/src/kchmsearchengine.h b/src/kchmsearchengine.h
new file mode 100644
index 0000000..8aab6e5
--- /dev/null
+++ b/src/kchmsearchengine.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMSEARCHENGINE_H
+#define KCHMSEARCHENGINE_H
+
+#include <qobject.h>
+#include <qmap.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qprogressdialog.h>
+
+#include "libchmfile.h"
+
+namespace QtAs { class Index; };
+
+
+class KCHMSearchEngine : public QObject
+{
+ Q_OBJECT
+
+ public:
+ KCHMSearchEngine();
+ ~KCHMSearchEngine();
+
+ bool loadOrGenerateIndex();
+ bool searchQuery ( const QString& query, QStringList * results, unsigned int limit = 100 );
+
+
+ private slots:
+ void setIndexingProgress( int progress );
+ void cancelButtonPressed();
+
+ private:
+ void processEvents();
+
+ // Used during the index generation
+ QProgressDialog * m_progressDlg;
+ QStringList m_keywordDocuments;
+ QtAs::Index * m_Index;
+};
+
+#endif
diff --git a/src/kchmsearchengine_impl.cpp b/src/kchmsearchengine_impl.cpp
new file mode 100644
index 0000000..286832a
--- /dev/null
+++ b/src/kchmsearchengine_impl.cpp
@@ -0,0 +1,572 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Portions Copyright (C) 2000-2005 Trolltech AS. *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+
+#include <qfile.h>
+#include <qdir.h>
+#include <qstringlist.h>
+#include <qdict.h>
+#include <qapplication.h>
+
+#include <ctype.h>
+
+#include "kchmsearchengine_impl.h"
+#include "kchmmainwindow.h"
+#include "libchmfileimpl.h"
+
+
+namespace QtAs {
+
+// Those characters are splitters (i.e. split the word), but added themselves into dictionary too.
+// This makes the dictionary MUCH larger, but ensure that for the piece of "window->print" both
+// search for "print" and "->print" will find it.
+static const char SPLIT_CHARACTERS[] = "!()*&^%#@[]{}':;,.?/|/?<>\\-+=~`";
+
+// Those characters are parts of word - for example, '_' is here, and search for _debug will find only _debug.
+static const char WORD_CHARACTERS[] = "$_";
+
+
+int TermList::compareItems( QPtrCollection::Item i1, QPtrCollection::Item i2 )
+{
+ if( ( (Term*)i1 )->frequency == ( (Term*)i2 )->frequency )
+ return 0;
+ if( ( (Term*)i1 )->frequency < ( (Term*)i2 )->frequency )
+ return -1;
+ return 1;
+}
+
+QDataStream &operator>>( QDataStream &s, Document &l )
+{
+ s >> l.docNumber;
+ s >> l.frequency;
+ return s;
+}
+
+QDataStream &operator<<( QDataStream &s, const Document &l )
+{
+ s << (Q_INT16)l.docNumber;
+ s << (Q_INT16)l.frequency;
+ return s;
+}
+
+Index::Index( const QString &dp, const QString & )
+ : QObject( 0, 0 ), dict( 8999 ), docPath( dp )
+{
+ lastWindowClosed = false;
+ connect( qApp, SIGNAL( lastWindowClosed() ),
+ this, SLOT( setLastWinClosed() ) );
+}
+
+Index::Index( const QStringList &dl, const QString & )
+ : QObject( 0, 0 ), dict( 20011 )
+{
+ docList = dl;
+ lastWindowClosed = false;
+ connect( qApp, SIGNAL( lastWindowClosed() ),
+ this, SLOT( setLastWinClosed() ) );
+}
+
+void Index::setLastWinClosed()
+{
+ lastWindowClosed = true;
+}
+
+void Index::setDictionaryFile( const QString &f )
+{
+ dictFile = f;
+}
+
+void Index::setDocListFile( const QString &f )
+{
+ docListFile = f;
+}
+
+void Index::setDocList( const QStringList &lst )
+{
+ docList = lst;
+}
+
+bool Index::makeIndex()
+{
+ if ( docList.isEmpty() )
+ return false;
+
+ QStringList::Iterator it = docList.begin();
+ int steps = docList.count() / 100;
+
+ if ( !steps )
+ steps++;
+
+ int prog = 0;
+
+ for ( int i = 0; it != docList.end(); ++it, ++i )
+ {
+ if ( lastWindowClosed )
+ return false;
+
+ parseDocument( *it, i );
+
+ if ( i%steps == 0 )
+ {
+ prog++;
+ emit indexingProgress( prog );
+ }
+ }
+
+ return true;
+}
+
+
+void Index::insertInDict( const QString &str, int docNum )
+{
+ Entry *e = 0;
+ if ( dict.count() )
+ e = dict[ str ];
+
+ if ( e )
+ {
+ if ( e->documents.first().docNumber != docNum )
+ e->documents.prepend( Document( docNum, 1 ) );
+ else
+ e->documents.first().frequency++;
+ }
+ else
+ {
+ dict.insert( str, new Entry( docNum ) );
+ }
+}
+
+
+bool Index::parseDocumentToStringlist( const QString & filename, QStringList & tokenlist )
+{
+ QString parsedbuf, parseentity;
+ QString text;
+
+ if ( !::mainWindow->chmFile()->getFileContentAsString( &text, filename ) )
+ {
+ qWarning( "Index::parseDocument: Could not retrieve the content at %s", filename.ascii() );
+ return false;
+ }
+
+ if ( text.isNull() )
+ {
+ qWarning( "Index::parseDocument: Retrieved content for %s is empty", filename.ascii() );
+ return false;
+ }
+
+ m_charssplit = SPLIT_CHARACTERS;
+ m_charsword = WORD_CHARACTERS;
+
+ tokenlist.clear();
+
+ // State machine states
+ enum state_t
+ {
+ STATE_OUTSIDE_TAGS, // outside HTML tags; parse text
+ STATE_IN_HTML_TAG, // inside HTML tags; wait for end tag
+ STATE_IN_QUOTES, // inside HTML tags and inside quotes; wait for end quote (in var QuoteChar)
+ STATE_IN_HTML_ENTITY, // inside HTML entity; parse the entity
+ };
+
+ state_t state = STATE_OUTSIDE_TAGS;
+ QChar QuoteChar; // used in STATE_IN_QUOTES
+
+ for ( unsigned int j = 0; j < text.length(); j++ )
+ {
+ QChar ch = text[j];
+
+ if ( (j % 20000) == 0 )
+ qApp->processEvents( QEventLoop::ExcludeUserInput );
+
+ if ( state == STATE_IN_HTML_TAG )
+ {
+ // We are inside HTML tag.
+ // Ignore everything until we see '>' (end of HTML tag) or quote char (quote start)
+ if ( ch == '"' || ch == '\'' )
+ {
+ state = STATE_IN_QUOTES;
+ QuoteChar = ch;
+ }
+ else if ( ch == '>' )
+ state = STATE_OUTSIDE_TAGS;
+
+ continue;
+ }
+ else if ( state == STATE_IN_QUOTES )
+ {
+ // We are inside quoted text inside HTML tag.
+ // Ignore everything until we see the quote character again
+ if ( ch == QuoteChar )
+ state = STATE_IN_HTML_TAG;
+
+ continue;
+ }
+ else if ( state == STATE_IN_HTML_ENTITY )
+ {
+ // We are inside encoded HTML entity (like &nbsp;).
+ // Collect to parsedbuf everything until we see ;
+ if ( ch.isLetterOrNumber() )
+ {
+ // get next character of this entity
+ parseentity.append( ch );
+ continue;
+ }
+
+ // The entity ended
+ state = STATE_OUTSIDE_TAGS;
+
+ // Some shitty HTML does not terminate entities correctly. Screw it.
+ if ( ch != ';' && ch != '<' )
+ {
+ if ( parseentity.isEmpty() )
+ {
+ // straight '&' symbol. Add and continue.
+ parsedbuf += "&";
+ }
+ else
+ qWarning( "Index::parseDocument: incorrectly terminated HTML entity '&%s%c', ignoring", parseentity.ascii(), ch.latin1() );
+
+ j--; // parse this character again, but in different state
+ continue;
+ }
+
+ // Don't we have a space?
+ if ( parseentity.lower() != "nbsp" )
+ {
+ QString entity = ::mainWindow->chmFile()->impl()->decodeEntity( parseentity );
+
+ if ( entity.isNull() )
+ {
+ // decodeEntity() already printed error message
+ //qWarning( "Index::parseDocument: failed to decode entity &%s;", parsedbuf.ascii() );
+ continue;
+ }
+
+ parsedbuf += entity;
+ continue;
+ }
+ else
+ ch = ' '; // We got a space, so treat it like it, and not add it to parsebuf
+ }
+
+ //
+ // Now process STATE_OUTSIDE_TAGS
+ //
+
+ // Check for start of HTML tag, and switch to STATE_IN_HTML_TAG if it is
+ if ( ch == '<' )
+ {
+ state = STATE_IN_HTML_TAG;
+ goto tokenize_buf;
+ }
+
+ // Check for start of HTML entity
+ if ( ch == '&' )
+ {
+ state = STATE_IN_HTML_ENTITY;
+ parseentity = QString::null;
+ continue;
+ }
+
+ // Replace quote by ' - quotes are used in search window to set the phrase
+ if ( ch == '"' )
+ ch = '\'';
+
+ // Ok, we have a valid character outside HTML tags, and probably some in buffer already.
+ // If it is char or letter, add it and continue
+ if ( ch.isLetterOrNumber() || m_charsword.find( ch ) != -1 )
+ {
+ parsedbuf.append( ch );
+ continue;
+ }
+
+ // If it is a split char, add the word to the dictionary, and then add the char itself.
+ if ( m_charssplit.find( ch ) != -1 )
+ {
+ if ( !parsedbuf.isEmpty() )
+ tokenlist.push_back( parsedbuf.lower() );
+
+ tokenlist.push_back( ch.lower() );
+ parsedbuf = QString::null;
+ continue;
+ }
+
+tokenize_buf:
+ // Just add the word; it is most likely a space or terminated by tokenizer.
+ if ( !parsedbuf.isEmpty() )
+ {
+ tokenlist.push_back( parsedbuf.lower() );
+ parsedbuf = QString::null;
+ }
+ }
+
+ // Add the last word if still here - for broken htmls.
+ if ( !parsedbuf.isEmpty() )
+ tokenlist.push_back( parsedbuf.lower() );
+
+ return true;
+}
+
+
+void Index::parseDocument( const QString &filename, int docNum )
+{
+ QStringList terms;
+
+ if ( !parseDocumentToStringlist( filename, terms ) )
+ return;
+
+ for ( QStringList::Iterator it = terms.begin(); it != terms.end(); ++it )
+ insertInDict( *it, docNum );
+}
+
+
+void Index::writeDict()
+{
+ QDictIterator<Entry> it( dict );
+ QFile f( dictFile );
+
+ if ( !f.open( IO_WriteOnly ) )
+ {
+ qWarning( "Index::writeDict: could not write dictionary file %s", dictFile.ascii() );
+ return;
+ }
+
+ QDataStream s( &f );
+ s << (int) 1; // version
+ s << m_charssplit;
+ s << m_charsword;
+
+ for( ; it.current(); ++it )
+ {
+ Entry *e = it.current();
+ s << it.currentKey();
+ s << e->documents;
+ }
+
+ f.close();
+ writeDocumentList();
+}
+
+void Index::writeDocumentList()
+{
+ QFile f( docListFile );
+ if ( !f.open( IO_WriteOnly ) )
+ {
+ qWarning( "Index::writeDocumentList: could not write dictionary file %s", docListFile.ascii() );
+ return;
+ }
+ QDataStream s( &f );
+ s << docList;
+}
+
+bool Index::readDict()
+{
+ QFile f( dictFile );
+ if ( !f.open( IO_ReadOnly ) )
+ return false;
+
+ dict.clear();
+ QDataStream s( &f );
+ QString key;
+ int version;
+ QValueList<Document> docs;
+
+ s >> version;
+ s >> m_charssplit;
+ s >> m_charsword;
+
+ while ( !s.atEnd() )
+ {
+ s >> key;
+ s >> docs;
+ dict.insert( key, new Entry( docs ) );
+ }
+
+ f.close();
+ return dict.size() > 0 && readDocumentList();
+}
+
+bool Index::readDocumentList()
+{
+ QFile f( docListFile );
+ if ( !f.open( IO_ReadOnly ) )
+ return false;
+ QDataStream s( &f );
+ s >> docList;
+ return true;
+}
+
+QStringList Index::query( const QStringList &terms, const QStringList &termSeq, const QStringList &seqWords )
+{
+ TermList termList;
+
+ QStringList::ConstIterator it = terms.begin();
+ for ( it = terms.begin(); it != terms.end(); ++it )
+ {
+ Entry *e = 0;
+
+ if ( dict[ *it ] )
+ {
+ e = dict[ *it ];
+ termList.append( new Term( *it, e->documents.count(), e->documents ) );
+ }
+ else
+ {
+ return QStringList();
+ }
+ }
+
+ termList.sort();
+
+ Term *minTerm = termList.first();
+
+ if ( !termList.count() )
+ return QStringList();
+
+ termList.removeFirst();
+
+ QValueList<Document> minDocs = minTerm->documents;
+ QValueList<Document>::iterator C;
+ QValueList<Document>::ConstIterator It;
+ Term *t = termList.first();
+
+ for ( ; t; t = termList.next() )
+ {
+ QValueList<Document> docs = t->documents;
+ C = minDocs.begin();
+
+ while ( C != minDocs.end() )
+ {
+ bool found = false;
+
+ for ( It = docs.begin(); It != docs.end(); ++It )
+ {
+ if ( (*C).docNumber == (*It).docNumber )
+ {
+ (*C).frequency += (*It).frequency;
+ found = true;
+ break;
+ }
+ }
+
+ if ( !found )
+ C = minDocs.remove( C );
+ else
+ ++C;
+ }
+ }
+
+ QStringList results;
+ qHeapSort( minDocs );
+
+ if ( termSeq.isEmpty() )
+ {
+ for ( C = minDocs.begin(); C != minDocs.end(); ++C )
+ results << docList[ (int)(*C).docNumber ];
+
+ return results;
+ }
+
+ QString fileName;
+
+ for ( C = minDocs.begin(); C != minDocs.end(); ++C )
+ {
+ fileName = docList[ (int)(*C).docNumber ];
+
+ if ( searchForPhrases( termSeq, seqWords, fileName ) )
+ results << fileName;
+ }
+
+ return results;
+}
+
+
+bool Index::searchForPhrases( const QStringList &phrases, const QStringList &words, const QString &filename )
+{
+ QStringList parsed_document;
+
+ if ( !parseDocumentToStringlist( filename, parsed_document ) )
+ return false;
+
+ miniDict.clear();
+
+ // Initialize the dictionary with the words in phrase(s)
+ for ( QStringList::ConstIterator cIt = words.begin(); cIt != words.end(); ++cIt )
+ miniDict.insert( *cIt, new PosEntry( 0 ) );
+
+ // Fill the dictionary with the words from the document
+ unsigned int word_offset = 3;
+ for ( QStringList::ConstIterator it = parsed_document.begin(); it != parsed_document.end(); it++, word_offset++ )
+ {
+ PosEntry * entry = miniDict[ *it ];
+
+ if ( entry )
+ entry->positions.append( word_offset );
+ }
+
+ // Dump it
+/*
+ QDictIterator<PosEntry> it( miniDict );
+ for( ; it.current(); ++it )
+ {
+ QString text( it.currentKey() );
+ QValueList<uint> pos = miniDict[text]->positions;
+ for ( unsigned int i = 1; i < pos.size(); i++ )
+ text += " " + QString::number( pos[i] );
+
+ qDebug( "%s", text.ascii());
+ }
+*/
+
+ QValueList<uint> first_word_positions;
+
+ for ( QStringList::ConstIterator phrase_it = phrases.begin(); phrase_it != phrases.end(); phrase_it++ )
+ {
+ QStringList phrasewords = QStringList::split( ' ', *phrase_it );
+ first_word_positions = miniDict[ phrasewords[0] ]->positions;
+
+ for ( unsigned int j = 1; j < phrasewords.count(); ++j )
+ {
+ QValueList<uint> next_word_it = miniDict[ phrasewords[j] ]->positions;
+ QValueList<uint>::iterator dict_it = first_word_positions.begin();
+
+ while ( dict_it != first_word_positions.end() )
+ {
+ if ( next_word_it.find( *dict_it + 1 ) != next_word_it.end() )
+ {
+ (*dict_it)++;
+ ++dict_it;
+ }
+ else
+ dict_it = first_word_positions.remove( dict_it );
+ }
+ }
+ }
+
+ if ( first_word_positions.count() )
+ return true;
+
+ return false;
+}
+
+
+};
diff --git a/src/kchmsearchengine_impl.h b/src/kchmsearchengine_impl.h
new file mode 100644
index 0000000..b8a9fe6
--- /dev/null
+++ b/src/kchmsearchengine_impl.h
@@ -0,0 +1,151 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Portions Copyright (C) 2000-2005 Trolltech AS. *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef QASSISTANTINDEX_H
+#define QASSISTANTINDEX_H
+
+#include <qstringlist.h>
+#include <qdict.h>
+#include <qdatastream.h>
+#include <qobject.h>
+
+namespace QtAs
+{
+
+struct Document
+{
+ Document( int d, int f ) : docNumber( d ), frequency( f ) {}
+ Document() : docNumber( -1 ), frequency( 0 ) {}
+ bool operator==( const Document &doc ) const
+ {
+ return docNumber == doc.docNumber;
+ }
+
+ bool operator<( const Document &doc ) const
+ {
+ return frequency > doc.frequency;
+ }
+
+ bool operator<=( const Document &doc ) const
+ {
+ return frequency >= doc.frequency;
+ }
+
+ bool operator>( const Document &doc ) const
+ {
+ return frequency < doc.frequency;
+ }
+
+ Q_INT16 docNumber;
+ Q_INT16 frequency;
+};
+
+QDataStream &operator>>( QDataStream &s, Document &l );
+QDataStream &operator<<( QDataStream &s, const Document &l );
+
+class Index : public QObject
+{
+ Q_OBJECT
+ public:
+ struct Entry
+ {
+ Entry( int d ) { documents.append( Document( d, 1 ) ); }
+ Entry( QValueList<Document> l ) : documents( l ) {}
+ QValueList<Document> documents;
+ };
+
+ struct PosEntry
+ {
+ PosEntry( int p ) { positions.append( p ); }
+ QValueList<uint> positions;
+ };
+
+ Index( const QString &dp, const QString &hp );
+ Index( const QStringList &dl, const QString &hp );
+
+ void writeDict();
+ bool readDict();
+ bool makeIndex();
+ QStringList query( const QStringList&, const QStringList&, const QStringList& );
+
+ void setDictionaryFile( const QString& );
+ void setDocListFile( const QString& );
+ void setDocList( const QStringList & );
+ QString getCharsSplit() const { return m_charssplit; }
+ QString getCharsPartOfWord() const { return m_charsword; }
+
+ signals:
+ void indexingProgress( int );
+
+ public slots:
+ void setLastWinClosed();
+
+ private:
+ void setupDocumentList();
+ bool parseDocumentToStringlist( const QString& filename, QStringList& tokenlist );
+ void parseDocument( const QString& filename, int docnum );
+ void insertInDict( const QString&, int );
+
+ void writeDocumentList();
+ bool readDocumentList();
+
+ QStringList getWildcardTerms( const QString& );
+ QStringList split( const QString& );
+ QValueList<Document> setupDummyTerm( const QStringList& );
+ bool searchForPhrases( const QStringList &phrases, const QStringList &words, const QString &filename );
+
+ QStringList docList;
+ QDict<Entry> dict;
+ QDict<PosEntry> miniDict;
+ QString docPath;
+ QString dictFile;
+ QString docListFile;
+ bool lastWindowClosed;
+
+ // Those characters are splitters (i.e. split the word), but added themselves into dictionary too.
+ // This makes the dictionary MUCH larger, but ensure that for the piece of "window->print" both
+ // search for "print" and "->print" will find it.
+ QString m_charssplit;
+
+ // Those characters are parts of word - for example, '_' is here, and search for _debug will find only _debug.
+ QString m_charsword;
+};
+
+struct Term
+{
+ Term( const QString &t, int f, QValueList<Document> l ) : term( t ), frequency( f ), documents( l ) {}
+
+ QString term;
+ int frequency;
+ QValueList<Document> documents;
+};
+
+class TermList : public QPtrList<Term>
+{
+ public:
+ TermList() : QPtrList<Term>() {}
+ int compareItems( QPtrCollection::Item i1, QPtrCollection::Item i2 );
+};
+
+};
+
+#endif /* QASSISTANTINDEX_H */
diff --git a/src/kchmsearchtoolbar.cpp b/src/kchmsearchtoolbar.cpp
new file mode 100644
index 0000000..617cf7b
--- /dev/null
+++ b/src/kchmsearchtoolbar.cpp
@@ -0,0 +1,438 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qtoolbutton.h>
+#include <qcombobox.h>
+#include <qlineedit.h>
+#include <qtextedit.h>
+#include <qaccel.h>
+#include <qpopupmenu.h>
+#include <qmenubar.h>
+
+#include "libchmfile.h"
+#include "libchmfileimpl.h"
+
+#include "kchmmainwindow.h"
+#include "kchmviewwindow.h"
+#include "kchmconfig.h"
+#include "kchmsearchtoolbar.h"
+#include "kqrunprocess.h"
+#include "kchmtreeviewitem.h"
+#include "kchmcontentswindow.h"
+#include "iconstorage.h"
+
+#include "kchmsearchtoolbar.moc"
+
+static KQPopupMenu *menu_langlist, *menu_enclist;
+
+KCHMSearchAndViewToolbar::KCHMSearchAndViewToolbar( KCHMMainWindow * parent )
+ : QToolBar (parent)
+{
+ // Toolbar label
+ setLabel( i18n( "Find in page") );
+
+ // Load the pixmaps
+ QPixmap iconPrev (*gIconStorage.getToolbarPixmap(KCHMIconStorage::findprev));
+ QPixmap iconNext (*gIconStorage.getToolbarPixmap(KCHMIconStorage::findnext));
+ QPixmap iconFontInc (*gIconStorage.getToolbarPixmap(KCHMIconStorage::view_increase));
+ QPixmap iconFontDec (*gIconStorage.getToolbarPixmap(KCHMIconStorage::view_decrease));
+ QPixmap iconViewSource (*gIconStorage.getToolbarPixmap(KCHMIconStorage::viewsource));
+ QPixmap iconAddBookmark (*gIconStorage.getToolbarPixmap(KCHMIconStorage::bookmark_add));
+ QPixmap iconNextPage (*gIconStorage.getToolbarPixmap(KCHMIconStorage::next_page));
+ QPixmap iconPrevPage (*gIconStorage.getToolbarPixmap(KCHMIconStorage::prev_page));
+ QPixmap iconLocateInContent (*gIconStorage.getToolbarPixmap(KCHMIconStorage::locate_in_content));
+
+ // Create the combobox to enter the find text
+ m_findBox = new QComboBox (TRUE, this);
+ m_findBox->setMinimumWidth (200);
+ connect( m_findBox->lineEdit(), SIGNAL( returnPressed() ), this, SLOT( onReturnPressed() ) );
+ QWhatsThis::add( m_findBox, i18n( "Enter here the text to search in the current page.") );
+
+ QAccel *acc = new QAccel( this );
+ acc->connectItem( acc->insertItem(Key_F+CTRL), this, SLOT( onAccelFocusSearchField() ) );
+
+ // Button 'prevous search result'
+ m_buttonPrev = new QToolButton (iconPrev,
+ i18n( "Previous search result"),
+ QString::null,
+ this,
+ SLOT(onBtnPrevSearchResult()),
+ this);
+ QWhatsThis::add( m_buttonPrev, i18n( "Click this button to find previous search result.") );
+
+ // Button 'next search result'
+ m_buttonNext = new QToolButton (iconNext,
+ i18n( "Next search result"),
+ QString::null,
+ this,
+ SLOT(onBtnNextSearchResult()),
+ this);
+ QWhatsThis::add( m_buttonNext, i18n( "Click this button to find next search result.") );
+
+ // Button 'locate in content'
+ m_buttonLocateInContent = new QToolButton( iconLocateInContent,
+ i18n( "Locate this topic in content window"),
+ QString::null,
+ this,
+ SLOT( onBtnLocateInContentWindow() ),
+ this );
+ QWhatsThis::add( m_buttonLocateInContent, i18n( "Click this button to find current topic in the content window, and open it.") );
+
+ // Button 'increase font size'
+ m_buttonFontInc = new QToolButton (iconFontInc,
+ i18n( "Increase font size"),
+ QString::null,
+ this,
+ SLOT(onBtnFontInc()),
+ this);
+ QWhatsThis::add( m_buttonFontInc, i18n( "Click this button to increase the font size.") );
+
+ // Button 'decrease font size'
+ m_buttonFontDec = new QToolButton (iconFontDec,
+ i18n( "Decrease font size"),
+ QString::null,
+ this,
+ SLOT(onBtnFontDec()),
+ this);
+ QWhatsThis::add( m_buttonFontDec, i18n( "Click this button to decrease the font size.") );
+
+ // Button 'view HTML source'
+ m_buttonViewSource = new QToolButton (iconViewSource,
+ i18n( "View HTML source"),
+ QString::null,
+ this,
+ SLOT(onBtnViewSource()),
+ this);
+ QWhatsThis::add( m_buttonViewSource, i18n( "Click this button to open a separate window with the page HTML source.") );
+
+ // Button 'add a bookmark'
+ m_buttonAddBookmark = new QToolButton (iconAddBookmark,
+ i18n( "Add to bookmarks"),
+ QString::null,
+ this,
+ SLOT(onBtnAddBookmark()),
+ this);
+ QWhatsThis::add( m_buttonAddBookmark, i18n( "Click this button to add the current page to the bookmarks list.") );
+
+ m_buttonPrevPageInTOC = new QToolButton( iconPrevPage,
+ i18n( "Prev page in TOC"),
+ QString::null,
+ this,
+ SLOT(onBtnPrevPageInToc()),
+ this);
+ QWhatsThis::add( m_buttonAddBookmark, i18n( "Click this button to go to previous page in Table Of Content.") );
+
+ m_buttonNextPageInTOC = new QToolButton (iconNextPage,
+ i18n( "Next page in TOC"),
+ QString::null,
+ this,
+ SLOT(onBtnNextPageInToc()),
+ this);
+ QWhatsThis::add( m_buttonAddBookmark, i18n( "Click this button to go to next page in Table of Content.") );
+
+ // Create the approptiate menu entries in 'View' main menu
+ m_MenuView = new KQPopupMenu( parent );
+ parent->menuBar()->insertItem( i18n( "&View"), m_MenuView );
+
+ m_MenuView->insertItem( i18n( "&Increase font"), this, SLOT(onBtnFontInc()), CTRL+Key_Plus );
+ m_MenuView->insertItem( i18n( "&Decrease font"), this, SLOT(onBtnFontDec()), CTRL+Key_Minus );
+ m_MenuView->insertItem( i18n( "&View HTML source"), this, SLOT(onBtnViewSource()), CTRL+Key_U );
+
+ m_MenuView->insertSeparator();
+ m_MenuView->insertItem( i18n( "&Bookmark this page"), this, SLOT(onBtnAddBookmark()), CTRL+Key_T );
+ m_MenuView->insertSeparator();
+
+ m_menuShowFullscreenMenuID = m_MenuView->insertItem( i18n( "&Full screen"), this,
+ SLOT(onBtnFullScreen()), Key_F11 );
+ m_menuShowContentWindowMenuID = m_MenuView->insertItem( i18n( "&Show contents window"), this,
+ SLOT(onBtnToggleContentWindow()), Key_F9 );
+ m_MenuView->insertItem( i18n( "&Locate in contents window"), this,
+ SLOT(onBtnLocateInContentWindow()), CTRL+Key_L );
+
+ m_MenuView->setItemChecked( m_menuShowFullscreenMenuID, false );
+ m_MenuView->setItemChecked( m_menuShowContentWindowMenuID, true );
+ m_MenuView->insertSeparator();
+
+ // Create the language selection menu.
+ menu_langlist = new KQPopupMenu( parent );
+ KQPopupMenu * menu_sublang = 0;
+
+ // Because the encoding menu is very large, it is not reasonable to have a slot for every item.
+ // It is simplier just to use a single slot for any menu item of this submenu.
+ connect (menu_langlist, SIGNAL( activated(int) ), this, SLOT ( onMenuActivated(int) ));
+
+ // Add the language entries
+ const LCHMTextEncoding * enctable = LCHMFileImpl::getTextEncodingTable();
+ int idx;
+
+ for ( idx = 0; (enctable + idx)->language; idx++ )
+ {
+ // See the next item; does is have the same charset as current?
+ const LCHMTextEncoding * item = enctable + idx;
+ const LCHMTextEncoding * nextitem = enctable + idx + 1;
+
+ if ( nextitem->language
+ && !strcmp( item->language, nextitem->language) )
+ {
+ // If charset is the same as next one, create a new popup menu.
+ // If the menu is already created, add to it
+ if ( !menu_sublang )
+ {
+ menu_sublang = new KQPopupMenu( menu_langlist );
+ connect (menu_sublang, SIGNAL( activated(int) ), this, SLOT ( onMenuActivated(int) ));
+ }
+
+ menu_sublang->insertItem( item->sublanguage, idx );
+ continue;
+ }
+
+ // If the next charset differs from this one,
+ // add a submenu if menu_sublang is already created.
+ // otherwise, just add an item
+ if ( menu_sublang )
+ {
+ menu_sublang->insertItem( item->sublanguage, idx );
+ menu_langlist->insertItem( item->language, menu_sublang );
+ menu_sublang = 0;
+ }
+ else
+ menu_langlist->insertItem( item->language, idx );
+ }
+
+ m_MenuView->insertItem( i18n( "&Set language"), menu_langlist );
+ m_checkedEncodingInMenu = -1;
+ m_checkedLanguageInMenu = -1;
+
+ // Special menu for very smart people just to select codepage
+ QMap<QString,bool> addedCharsets;
+ menu_enclist = new KQPopupMenu( parent );
+
+ connect (menu_enclist, SIGNAL( activated(int) ), this, SLOT ( onMenuActivated(int) ));
+
+ // Add the codepage entries
+ for ( idx = 0; (enctable + idx)->language; idx++ )
+ {
+ const LCHMTextEncoding * item = enctable + idx;
+
+ // This menu is only for charsets, so we won't add duplicate charset twice
+ if ( addedCharsets.find( item->qtcodec ) != addedCharsets.end() )
+ continue;
+
+ addedCharsets[ item->qtcodec ] = true;
+ menu_enclist->insertItem( item->qtcodec, idx );
+ }
+
+ m_MenuView->insertItem( i18n( "&Set codepage"), menu_enclist );
+
+ QWhatsThis::whatsThisButton( this );
+}
+
+void KCHMSearchAndViewToolbar::setEnabled( bool enable )
+{
+ m_findBox->setEnabled (enable);
+ m_buttonPrev->setEnabled (enable);
+ m_buttonNext->setEnabled (enable);
+ m_buttonFontInc->setEnabled (enable);
+ m_buttonFontDec->setEnabled (enable);
+ m_buttonViewSource->setEnabled (enable);
+ m_buttonAddBookmark->setEnabled (enable);
+
+ bool enable_toc_nav_buttons = ::mainWindow->contentsWindow() && enable;
+ m_buttonNextPageInTOC->setEnabled( enable_toc_nav_buttons );
+ m_buttonPrevPageInTOC->setEnabled( enable_toc_nav_buttons );
+}
+
+void KCHMSearchAndViewToolbar::onReturnPressed( )
+{
+ search( true );
+}
+
+void KCHMSearchAndViewToolbar::onBtnPrevSearchResult( )
+{
+ search( false );
+}
+
+void KCHMSearchAndViewToolbar::onBtnNextSearchResult( )
+{
+ search( true );
+}
+
+void KCHMSearchAndViewToolbar::search( bool search_forward )
+{
+ QString searchexpr = m_findBox->lineEdit()->text();
+
+ if ( searchexpr.isEmpty() )
+ return;
+
+ ::mainWindow->currentBrowser()->searchWord( searchexpr, search_forward, false );
+}
+
+void KCHMSearchAndViewToolbar::onBtnFontInc( )
+{
+ ::mainWindow->currentBrowser()->addZoomFactor(1);
+}
+
+void KCHMSearchAndViewToolbar::onBtnFontDec( )
+{
+ ::mainWindow->currentBrowser()->addZoomFactor(-1);
+}
+
+void KCHMSearchAndViewToolbar::onBtnViewSource( )
+{
+ QString text;
+
+ if ( !::mainWindow->chmFile()->getFileContentAsString( &text, ::mainWindow->currentBrowser()->getOpenedPage() ) )
+ return;
+
+ if ( appConfig.m_advUseInternalEditor )
+ {
+ QTextEdit * editor = new QTextEdit ( 0 );
+ editor->setTextFormat ( Qt::PlainText );
+ editor->setText (text);
+ editor->setCaption ( QString(APP_NAME) + " - view HTML source of " + ::mainWindow->currentBrowser()->getOpenedPage() );
+ editor->resize (800, 600);
+ editor->show();
+ }
+ else
+ {
+ QFile file;
+ m_tempFileKeeper.generateTempFile( file );
+
+ file.writeBlock( text.utf8() );
+ run_process( appConfig.m_advExternalEditorPath, file.name() );
+ }
+}
+
+void KCHMSearchAndViewToolbar::onBtnAddBookmark( )
+{
+ emit ::mainWindow->slotAddBookmark();
+}
+
+void KCHMSearchAndViewToolbar::onMenuActivated( int id )
+{
+ const LCHMTextEncoding * enc = LCHMFileImpl::getTextEncodingTable() + id;
+ ::mainWindow->setTextEncoding( enc );
+}
+
+void KCHMSearchAndViewToolbar::setChosenEncodingInMenu( const LCHMTextEncoding * enc)
+{
+ if ( m_checkedEncodingInMenu != -1 )
+ menu_enclist->setItemChecked( m_checkedEncodingInMenu, false );
+
+ if ( m_checkedLanguageInMenu != -1 )
+ menu_langlist->setItemChecked( m_checkedLanguageInMenu, false );
+
+ int idx = LCHMFileImpl::getEncodingIndex( enc );
+ if ( idx == -1 )
+ return;
+
+ menu_langlist->setItemChecked( idx, true );
+ m_checkedLanguageInMenu = idx;
+
+ // For encoding, we need to set up charset!
+ const LCHMTextEncoding * enctable = LCHMFileImpl::getTextEncodingTable();
+ for ( idx = 0; (enctable + idx)->language; idx++ )
+ {
+ // See the next item; does is have the same charset as current?
+ const LCHMTextEncoding * item = enctable + idx;
+
+ // This menu is only for charsets, so we won't add duplicate charset twice
+ if ( !strcmp( item->qtcodec, enc->qtcodec ) )
+ {
+ menu_enclist->setItemChecked ( idx, true);
+ m_checkedEncodingInMenu = idx;
+ break;
+ }
+ }
+}
+
+void KCHMSearchAndViewToolbar::onBtnNextPageInToc()
+{
+ KCHMContentsWindow * cwnd = ::mainWindow->contentsWindow();
+
+ if ( !cwnd )
+ return;
+
+ // Try to find current list item
+ KCHMIndTocItem * current = cwnd->getTreeItem( ::mainWindow->currentBrowser()->getOpenedPage() );
+
+ if ( !current )
+ return;
+
+ QListViewItemIterator lit( current );
+ lit++;
+
+ if ( lit.current() )
+ ::mainWindow->openPage( ((KCHMIndTocItem *) lit.current() )->getUrl(), OPF_CONTENT_TREE | OPF_ADD2HISTORY );
+}
+
+void KCHMSearchAndViewToolbar::onBtnPrevPageInToc()
+{
+ KCHMContentsWindow * cwnd = ::mainWindow->contentsWindow();
+
+ if ( !cwnd )
+ return;
+
+ // Try to find current list item
+ KCHMIndTocItem * current = cwnd->getTreeItem( ::mainWindow->currentBrowser()->getOpenedPage() );
+
+ if ( !current )
+ return;
+
+ QListViewItemIterator lit( current );
+ lit--;
+
+ if ( lit.current() )
+ ::mainWindow->openPage( ((KCHMIndTocItem *) lit.current() )->getUrl(), OPF_CONTENT_TREE | OPF_ADD2HISTORY );
+}
+
+void KCHMSearchAndViewToolbar::onAccelFocusSearchField( )
+{
+ m_findBox->setFocus();
+}
+
+void KCHMSearchAndViewToolbar::onBtnToggleContentWindow( )
+{
+ showContentsWindow( !m_MenuView->isItemChecked( m_menuShowContentWindowMenuID ) );
+}
+
+void KCHMSearchAndViewToolbar::onBtnFullScreen( )
+{
+ setFullScreen( !m_MenuView->isItemChecked( m_menuShowFullscreenMenuID ) );
+}
+
+void KCHMSearchAndViewToolbar::setFullScreen( bool enable )
+{
+ ::mainWindow->slotEnableFullScreenMode( enable );
+ m_MenuView->setItemChecked( m_menuShowFullscreenMenuID, enable );
+}
+
+void KCHMSearchAndViewToolbar::showContentsWindow( bool enable )
+{
+ ::mainWindow->slotShowContentsWindow( enable );
+ m_MenuView->setItemChecked( m_menuShowContentWindowMenuID, enable );
+}
+
+void KCHMSearchAndViewToolbar::onBtnLocateInContentWindow( )
+{
+ ::mainWindow->slotLocateInContentWindow( );
+}
+
diff --git a/src/kchmsearchtoolbar.h b/src/kchmsearchtoolbar.h
new file mode 100644
index 0000000..be0cd99
--- /dev/null
+++ b/src/kchmsearchtoolbar.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMSEARCHTOOLBAR_H
+#define KCHMSEARCHTOOLBAR_H
+
+#include "kde-qt.h"
+
+#include "forwarddeclarations.h"
+
+#include "kqtempfile.h"
+
+/**
+@author Georgy Yunaev
+*/
+class KCHMSearchAndViewToolbar : public QToolBar
+{
+ Q_OBJECT
+ public:
+ KCHMSearchAndViewToolbar (KCHMMainWindow *parent);
+
+ void setEnabled (bool enable);
+ void setChosenEncodingInMenu( const LCHMTextEncoding * encoding );
+
+ private slots:
+ void onReturnPressed();
+ void onBtnPrevSearchResult();
+ void onBtnNextSearchResult();
+ void onAccelFocusSearchField();
+
+ void onBtnFontInc();
+ void onBtnFontDec();
+ void onBtnViewSource();
+ void onBtnAddBookmark();
+ void onBtnNextPageInToc();
+ void onBtnPrevPageInToc();
+ void onMenuActivated ( int id );
+ void onBtnFullScreen();
+ void onBtnLocateInContentWindow();
+ void onBtnToggleContentWindow();
+
+ void setFullScreen( bool enable );
+ void showContentsWindow( bool enable );
+
+ private:
+ void search (bool forward);
+
+ KQPopupMenu * m_MenuView;
+ QComboBox * m_findBox;
+ QToolButton * m_buttonPrev;
+ QToolButton * m_buttonNext;
+ QToolButton * m_buttonFontInc;
+ QToolButton * m_buttonFontDec;
+ QToolButton * m_buttonViewSource;
+ QToolButton * m_buttonAddBookmark;
+ QToolButton * m_buttonNextPageInTOC;
+ QToolButton * m_buttonPrevPageInTOC;
+ QToolButton * m_buttonLocateInContent;
+
+ int m_checkedLanguageInMenu;
+ int m_checkedEncodingInMenu;
+
+ int m_menuShowFullscreenMenuID;
+ int m_menuShowContentWindowMenuID;
+
+ KQTempFileKeeper m_tempFileKeeper;
+};
+
+#endif
diff --git a/src/kchmsearchwindow.cpp b/src/kchmsearchwindow.cpp
new file mode 100644
index 0000000..790cc62
--- /dev/null
+++ b/src/kchmsearchwindow.cpp
@@ -0,0 +1,246 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "libchmfile.h"
+
+#include "kchmsearchwindow.h"
+#include "kchmmainwindow.h"
+#include "kchmconfig.h"
+#include "kchmlistitemtooltip.h"
+#include "kchmtreeviewitem.h"
+#include "kchmsearchengine.h"
+
+#include "kchmsearchwindow.moc"
+
+
+KCHMSearchWindow::KCHMSearchWindow( QWidget * parent, const char * name, WFlags f )
+ : QWidget (parent, name, f)
+{
+ QVBoxLayout * layout = new QVBoxLayout (this);
+ layout->setMargin(6);
+ layout->setSpacing(6);
+
+ // Labels <type words to search> and <help>
+ QHBoxLayout * labellayout = new QHBoxLayout();
+ labellayout->addWidget( new QLabel( i18n( "Type in word(s) to search for:"), this) );
+ labellayout->addStretch( 10 );
+
+ KCHMClickableLabel * helplink = new KCHMClickableLabel( i18n( "<a href=\"q\"><b>Help</b></a>"), this );
+ connect( helplink, SIGNAL( clicked() ), this, SLOT( onHelpClicked() ) );
+ helplink->setCursor( QCursor( Qt::PointingHandCursor ) );
+
+ labellayout->addWidget ( helplink );
+ layout->addLayout( labellayout );
+
+ m_searchQuery = new QComboBox (TRUE, this);
+ m_searchQuery->setFocus();
+ m_searchQuery->setMaxCount (10);
+ m_searchQuery->setSizePolicy ( QSizePolicy ( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
+
+ QPushButton * searchButton = new QPushButton ( i18n("Go"), this);
+ searchButton->setSizePolicy ( QSizePolicy ( QSizePolicy::Minimum, QSizePolicy::Fixed ) );
+
+ QHBoxLayout * hlayout = new QHBoxLayout ( layout );
+ hlayout->addWidget ( m_searchQuery );
+ hlayout->addWidget ( searchButton );
+
+ m_searchList = new KQListView (this);
+ m_searchList->addColumn( i18n( "Title" ) );
+ m_searchList->addColumn( i18n( "Location" ) );
+ m_searchList->setShowToolTips(true);
+
+ connect( searchButton,
+ SIGNAL( clicked () ),
+ this,
+ SLOT( onReturnPressed() ) );
+
+ connect( m_searchQuery->lineEdit(),
+ SIGNAL( returnPressed() ),
+ this,
+ SLOT( onReturnPressed() ) );
+
+ connect( m_searchList,
+ SIGNAL( doubleClicked ( QListViewItem *, const QPoint &, int) ),
+ this,
+ SLOT( onDoubleClicked ( QListViewItem *, const QPoint &, int) ) );
+
+ connect( m_searchList,
+ SIGNAL( contextMenuRequested( QListViewItem *, const QPoint& , int ) ),
+ this,
+ SLOT( slotContextMenuRequested ( QListViewItem *, const QPoint &, int ) ) );
+
+ //layout->addSpacing (10);
+ layout->addWidget (m_searchList);
+
+ new KCHMListItemTooltip( m_searchList );
+ m_contextMenu = 0;
+ m_searchEngine = 0;
+}
+
+void KCHMSearchWindow::invalidate( )
+{
+ m_searchList->clear();
+ m_searchQuery->clear();
+ m_searchQuery->lineEdit()->clear();
+
+ delete m_searchEngine;
+ m_searchEngine = 0;
+}
+
+void KCHMSearchWindow::onReturnPressed( )
+{
+ QStringList results;
+ QString text = m_searchQuery->lineEdit()->text();
+
+ if ( text.isEmpty() )
+ return;
+
+ m_searchList->clear();
+
+ if ( searchQuery( text, &results ) )
+ {
+ if ( !results.empty() )
+ {
+ for ( unsigned int i = 0; i < results.size(); i++ )
+ {
+ new KCMSearchTreeViewItem ( m_searchList,
+ ::mainWindow->chmFile()->getTopicByUrl( results[i] ),
+ results[i],
+ results[i] );
+ }
+
+ ::mainWindow->showInStatusBar( i18n( "Search returned %1 result(s)" ) . arg(results.size()) );
+ }
+ else
+ ::mainWindow->showInStatusBar( i18n( "Search returned no results") );
+ }
+ else
+ ::mainWindow->showInStatusBar( i18n( "Search failed") );
+}
+
+
+void KCHMSearchWindow::onDoubleClicked( QListViewItem *item, const QPoint &, int)
+{
+ if ( !item )
+ return;
+
+ KCMSearchTreeViewItem * treeitem = (KCMSearchTreeViewItem *) item;
+ ::mainWindow->openPage( treeitem->getUrl(), OPF_ADD2HISTORY );
+}
+
+void KCHMSearchWindow::restoreSettings( const KCHMSettings::search_saved_settings_t & settings )
+{
+ for ( unsigned int i = 0; i < settings.size(); i++ )
+ m_searchQuery->insertItem (settings[i]);
+}
+
+void KCHMSearchWindow::saveSettings( KCHMSettings::search_saved_settings_t & settings )
+{
+ settings.clear();
+
+ for ( int i = 0; i < m_searchQuery->count(); i++ )
+ settings.push_back (m_searchQuery->text(i));
+}
+
+
+void KCHMSearchWindow::onHelpClicked( )
+{
+ if ( appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_MINE )
+ {
+ QMessageBox::information ( this,
+ i18n( "How to use search"),
+ i18n( "<html><p>The improved search engine allows you to search for a word, symbol or phrase, which is set of words and symbols included in quotes. Only the documents which include all the terms speficide in th search query are shown; no prefixes needed.<p>Unlike MS CHM internal search index, my improved search engine indexes everything, including special symbols. Therefore it is possible to search (and find!) for something like <i>$q = new ChmFile();</i>. This search also fully supports Unicode, which means that you can search in non-English documents.<p>If you want to search for a quote symbol, use quotation mark instead. The engine treats a quote and a quotation mark as the same symbol, which allows to use them in phrases.</html>") );
+ }
+ else
+ {
+ QMessageBox::information ( this,
+ i18n( "How to use search"),
+ i18n( "The search query can contain a few prefixes.\nA set of words inside the quote marks mean that you are searching for exact phrase.\nA word with minus sign means that it should be absent in the search result.\nA word with plus mark or without any mark means that it must be present in the search result.\n\nNote that only letters and digits are indexed.\nYou cannot search for non-character symbols other than underscope, and those symbols will be removed from the search query.\nFor example, search for 'C' will give the same result as searching for 'C++'.") );
+ }
+}
+
+void KCHMSearchWindow::slotContextMenuRequested( QListViewItem * item, const QPoint & point, int )
+{
+ if ( !m_contextMenu )
+ m_contextMenu = ::mainWindow->currentBrowser()->createListItemContextMenu( this );
+
+ if( item )
+ {
+ KCMSearchTreeViewItem * treeitem = (KCMSearchTreeViewItem *) item;
+
+ ::mainWindow->currentBrowser()->setTabKeeper( treeitem->getUrl() );
+ m_contextMenu->popup( point );
+ }
+}
+
+bool KCHMSearchWindow::initSearchEngine( )
+{
+ m_searchEngine = new KCHMSearchEngine();
+
+ if ( !m_searchEngine->loadOrGenerateIndex() )
+ {
+ delete m_searchEngine;
+ m_searchEngine = 0;
+ return false;
+ }
+
+ return true;
+}
+
+
+void KCHMSearchWindow::execSearchQueryInGui( const QString & query )
+{
+ m_searchQuery->lineEdit()->setText( query );
+ onReturnPressed();
+}
+
+
+bool KCHMSearchWindow::searchQuery( const QString & query, QStringList * results )
+{
+ if ( appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_MINE )
+ {
+ if ( !m_searchEngine && !initSearchEngine() )
+ return false;
+ }
+ else if ( !::mainWindow->chmFile()->hasSearchTable() )
+ {
+ QMessageBox::information ( this,
+ i18n( "Search is not available" ),
+ i18n( "<p>The search feature is not avaiable for this chm file."
+ "<p>The old search engine depends on indexes present in chm files itself. Not every chm file has an index; it is set up"
+ " during chm file creation. Therefore if the search index was not created during chm file creation, this makes search "
+ "impossible.<p>Solution: use new search engine (menu Settings/Advanced), which generates its own index.") );
+ return false;
+ }
+
+ if ( query.isEmpty() )
+ return false;
+
+ KCHMShowWaitCursor waitcursor;
+ bool result;
+
+ if ( appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_MINE )
+ result = m_searchEngine->searchQuery( query, results );
+ else
+ result = ::mainWindow->chmFile()->searchQuery( query, results );
+
+ return result;
+}
diff --git a/src/kchmsearchwindow.h b/src/kchmsearchwindow.h
new file mode 100644
index 0000000..1834165
--- /dev/null
+++ b/src/kchmsearchwindow.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMSEARCHWINDOW_H
+#define KCHMSEARCHWINDOW_H
+
+#include "kde-qt.h"
+
+#include "kchmsettings.h"
+#include "forwarddeclarations.h"
+
+
+/**
+@author Georgy Yunaev
+*/
+class KCHMSearchEngine;
+
+
+class KCHMClickableLabel : public QLabel
+{
+ Q_OBJECT
+ public:
+ KCHMClickableLabel( const QString& label, QWidget * parent )
+ : QLabel( label, parent ) {};
+
+ virtual ~KCHMClickableLabel() {};
+
+ signals:
+ void clicked();
+
+ protected:
+ virtual void mousePressEvent ( QMouseEvent * ) { emit clicked(); }
+};
+
+
+class KCHMSearchWindow : public QWidget
+{
+ Q_OBJECT
+ public:
+ KCHMSearchWindow ( QWidget * parent = 0, const char * name = 0, WFlags f = 0 );
+
+ void invalidate();
+ void restoreSettings (const KCHMSettings::search_saved_settings_t& settings);
+ void saveSettings (KCHMSettings::search_saved_settings_t& settings);
+ void execSearchQueryInGui( const QString& query );
+ bool searchQuery( const QString& query, QStringList * results );
+
+ public slots:
+ void slotContextMenuRequested ( QListViewItem *item, const QPoint &point, int column );
+
+ private slots:
+ void onHelpClicked();
+ void onReturnPressed ();
+ void onDoubleClicked ( QListViewItem *, const QPoint &, int);
+
+ private:
+ bool initSearchEngine();
+
+ private:
+ QComboBox * m_searchQuery;
+ KQListView * m_searchList;
+ KQPopupMenu * m_contextMenu;
+
+ KCHMSearchEngine* m_searchEngine;
+};
+
+#endif
diff --git a/src/kchmsettings.cpp b/src/kchmsettings.cpp
new file mode 100644
index 0000000..dcdcffa
--- /dev/null
+++ b/src/kchmsettings.cpp
@@ -0,0 +1,298 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qdatastream.h>
+
+#include "kchmsettings.h"
+#include "kchmconfig.h"
+
+static Q_INT32 SETTINGS_MAGIC = 0xD8AB4E76;
+static Q_INT32 SETTINGS_VERSION = 4;
+
+/*
+ * The order is important!
+ * To be compatible with next versions, you may add items ONLY before the MARKER_END!
+ */
+enum marker_t
+{
+ MARKER_FILESIZE = 1,
+ MARKER_FILETIME,
+
+ MARKER_ACTIVETABSYSTEM,
+ MARKER_ACTIVETABWINDOW,
+ MARKER_ACTIVEENCODING,
+ MARKER_SEARCHHISTORY,
+ MARKER_WINDOW_SIZE,
+
+ MARKER_BOOKMARKS,
+ MARKER_VIEWINDOWS,
+
+ MARKER_CONTENTSDATA,
+ MARKER_INDEXDATA,
+
+ // This should be the last
+ MARKER_END = 0x7FFF
+};
+
+// Helpers for serialization of SavedBookmark through QDataStream
+static inline QDataStream& operator<< ( QDataStream& s, const KCHMSettings::SavedBookmark& b )
+{
+ s << b.name;
+ s << b.url;
+ s << b.scroll_y;
+ return s;
+}
+
+static inline QDataStream& operator>> ( QDataStream& s, KCHMSettings::SavedBookmark& b )
+{
+ s >> b.name;
+ s >> b.url;
+ s >> b.scroll_y;
+ return s;
+}
+
+// Helpers for serialization of SavedViewWindow through QDataStream
+static inline QDataStream& operator<< ( QDataStream& s, const KCHMSettings::SavedViewWindow& b )
+{
+ // Store the version first. Later we can increase it when adding new members.
+ s << 1;
+ s << b.url;
+ s << b.scroll_y;
+ s << b.zoom;
+ return s;
+}
+
+static inline QDataStream& operator>> ( QDataStream& s, KCHMSettings::SavedViewWindow& b )
+{
+ Q_INT32 version;
+
+ s >> version;
+ s >> b.url;
+ s >> b.scroll_y;
+ s >> b.zoom;
+ return s;
+}
+
+
+KCHMSettings::KCHMSettings( )
+{
+ m_activetabsystem = 0;
+ m_activetabwindow = 0;
+ m_activeencodinglcid = 0;
+
+ m_window_size_x = 700;
+ m_window_size_y = 500;
+ m_window_size_splitter = 200;
+}
+
+
+bool KCHMSettings::loadSettings( const QString & filename )
+{
+ m_activetabsystem = 0;
+ m_activetabwindow = 0;
+ m_activeencodinglcid = 0;
+
+ m_searchhistory.clear();
+ m_bookmarks.clear();
+ m_viewwindows.clear();
+
+ QFileInfo finfo ( filename );
+
+ m_settingsFile = QString::null;
+ m_searchDictFile = QString::null;
+ m_searchDocFile = QString::null;
+
+ if ( !finfo.size() )
+ return false;
+
+ // Init those params, as they'll be used during save the first time even if the file is not here
+ m_currentfilesize = finfo.size();
+ m_currentfiledate = finfo.lastModified().toTime_t();
+
+ getFilenames( filename, &m_settingsFile, &m_searchDictFile, &m_searchDocFile );
+
+ QFile file( m_settingsFile );
+
+ if ( !file.open (IO_ReadOnly) )
+ return false; // it's ok, file may not exist
+
+ QDataStream stream (&file);
+
+ // Read and check header
+ Q_INT32 data;
+ bool complete_read = false;
+ stream >> data; // magic
+
+ if ( data != SETTINGS_MAGIC )
+ {
+ qWarning ("file %s has bad magic value, ignoring it.", file.name().ascii());
+ return false;
+ }
+
+ stream >> data; // version
+ if ( data > SETTINGS_VERSION )
+ {
+ qWarning ("file %s has unsupported data version %d, ignoring it.", file.name().ascii(), data);
+ return false;
+ }
+
+ // Read everything by marker
+ while ( 1 )
+ {
+ stream >> data; // marker
+ if ( data == MARKER_END )
+ {
+ complete_read = true;
+ break;
+ }
+
+ switch (data)
+ {
+ case MARKER_FILESIZE:
+ stream >> m_currentfilesize;
+ if ( m_currentfilesize != finfo.size() )
+ {
+ m_currentfilesize = finfo.size();
+ return false;
+ }
+ break;
+
+ case MARKER_FILETIME:
+ stream >> m_currentfiledate;
+ if ( m_currentfiledate != finfo.lastModified().toTime_t() )
+ {
+ m_currentfiledate = finfo.lastModified().toTime_t();
+ return false;
+ }
+ break;
+
+ case MARKER_ACTIVETABSYSTEM:
+ stream >> m_activetabsystem;
+ break;
+
+ case MARKER_ACTIVETABWINDOW:
+ stream >> m_activetabwindow;
+ break;
+
+ case MARKER_ACTIVEENCODING:
+ stream >> m_activeencodinglcid;
+ break;
+
+ case MARKER_WINDOW_SIZE:
+ stream >> m_window_size_x;
+ stream >> m_window_size_y;
+ stream >> m_window_size_splitter;
+ break;
+
+ case MARKER_SEARCHHISTORY:
+ stream >> m_searchhistory;
+ break;
+
+ case MARKER_BOOKMARKS:
+ stream >> m_bookmarks;
+ break;
+
+ case MARKER_VIEWINDOWS:
+ stream >> m_viewwindows;
+ break;
+ }
+ }
+
+ return complete_read;
+}
+
+
+bool KCHMSettings::saveSettings( )
+{
+ QFile file( m_settingsFile );
+ if ( !file.open (IO_WriteOnly) )
+ {
+ qWarning ("Could not write settings into file %s: %s", file.name().ascii(), file.errorString().ascii());
+ return false;
+ }
+
+ QDataStream stream (&file);
+
+ // Save header
+ stream << SETTINGS_MAGIC;
+ stream << SETTINGS_VERSION;
+
+ // Save size and last-modified
+ stream << MARKER_FILESIZE;
+ stream << m_currentfilesize;
+ stream << MARKER_FILETIME;
+ stream << m_currentfiledate;
+
+ // Save generic settings
+ stream << MARKER_ACTIVETABSYSTEM;
+ stream << m_activetabsystem;
+
+ // Save generic settings
+ stream << MARKER_ACTIVETABWINDOW;
+ stream << m_activetabwindow;
+
+ stream << MARKER_ACTIVEENCODING;
+ stream << m_activeencodinglcid;
+
+ // Save search history vector
+ stream << MARKER_SEARCHHISTORY;
+ stream << m_searchhistory;
+
+ // Save window size and splitter position
+ stream << MARKER_WINDOW_SIZE;
+ stream << m_window_size_x;
+ stream << m_window_size_y;
+ stream << m_window_size_splitter;
+
+ stream << MARKER_BOOKMARKS;
+ stream << m_bookmarks;
+
+ stream << MARKER_VIEWINDOWS;
+ stream << m_viewwindows;
+
+ stream << MARKER_END;
+ return true;
+}
+
+
+void KCHMSettings::removeSettings( const QString & filename )
+{
+ QString settingsfile, dictfile, doclistfile;
+
+ getFilenames( filename, &settingsfile, &dictfile, &doclistfile );
+
+ QFile::remove( settingsfile );
+ QFile::remove( dictfile );
+ QFile::remove( doclistfile );
+}
+
+
+void KCHMSettings::getFilenames(const QString & helpfilename, QString * settingsfile, QString * dictfile, QString * doclistfile )
+{
+ QFileInfo finfo ( helpfilename );
+ QString prefix = appConfig.m_datapath + "/" + finfo.baseName();
+
+ *settingsfile = prefix + ".kchmviewer";
+ *dictfile = prefix + ".dict";
+ *doclistfile = prefix + ".doclist";
+}
diff --git a/src/kchmsettings.h b/src/kchmsettings.h
new file mode 100644
index 0000000..2eb67b7
--- /dev/null
+++ b/src/kchmsettings.h
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMSETTINGS_H
+#define KCHMSETTINGS_H
+
+#include <qstring.h>
+#include <qvaluelist.h>
+
+
+/**
+@author Georgy Yunaev
+*/
+class SavedBookmark;
+class QFileInfo;
+
+
+class KCHMSettings
+{
+ public:
+ KCHMSettings ();
+
+ bool loadSettings (const QString& filename);
+ bool saveSettings ( );
+ void removeSettings ( const QString& filename );
+
+ QString searchIndexDictFilename() const { return m_searchDictFile; }
+ QString searchIndexDocFilename() const { return m_searchDocFile; }
+
+ class SavedBookmark
+ {
+ public:
+ SavedBookmark() { scroll_y = 0; }
+ SavedBookmark (QString n, QString u, int y) : name(n), url(u), scroll_y(y) {};
+
+ QString name;
+ QString url;
+ int scroll_y;
+ };
+
+ class SavedViewWindow
+ {
+ public:
+ SavedViewWindow() { scroll_y = 0; zoom = 0; }
+ SavedViewWindow (QString u, int y, int z) : url(u), scroll_y(y), zoom(z) {};
+
+ QString url;
+ int scroll_y;
+ int zoom;
+ };
+
+ typedef QValueList<QString> search_saved_settings_t;
+ typedef QValueList<SavedBookmark> bookmark_saved_settings_t;
+ typedef QValueList<SavedViewWindow> viewindow_saved_settings_t;
+
+ int m_window_size_x;
+ int m_window_size_y;
+ int m_window_size_splitter;
+ int m_activetabsystem;
+ int m_activetabwindow;
+ int m_activeencodinglcid;
+ search_saved_settings_t m_searchhistory;
+ bookmark_saved_settings_t m_bookmarks;
+ viewindow_saved_settings_t m_viewwindows;
+
+ private:
+ void getFilenames(const QString & helpfilename, QString * settingsfile, QString * dictfile, QString * doclistfile );
+
+ unsigned int m_currentfilesize;
+ unsigned int m_currentfiledate;
+ QString m_settingsFile;
+ QString m_searchDictFile;
+ QString m_searchDocFile;
+};
+
+#endif
diff --git a/src/kchmsetupdialog.cpp b/src/kchmsetupdialog.cpp
new file mode 100644
index 0000000..05c1647
--- /dev/null
+++ b/src/kchmsetupdialog.cpp
@@ -0,0 +1,395 @@
+/****************************************************************************
+** Form implementation generated from reading ui file './kchmsetupdialog.ui'
+**
+** Created: Sat Jun 16 22:08:58 2007
+** by: The User Interface Compiler ($Id: qt/main.cpp 3.3.8 edited Jan 11 14:47 $)
+**
+** WARNING! All changes made in this file will be lost!
+****************************************************************************/
+
+#include "kchmsetupdialog.h"
+
+#include <qvariant.h>
+#include <qpushbutton.h>
+#include <qtabwidget.h>
+#include <qwidget.h>
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qgroupbox.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qwhatsthis.h>
+
+/*
+ * Constructs a KCHMSetupDialog as a child of 'parent', with the
+ * name 'name' and widget flags set to 'f'.
+ *
+ * The dialog will by default be modeless, unless you set 'modal' to
+ * TRUE to construct a modal dialog.
+ */
+KCHMSetupDialog::KCHMSetupDialog( QWidget* parent, const char* name, bool modal, WFlags fl )
+ : QDialog( parent, name, modal, fl )
+{
+ if ( !name )
+ setName( "MyDialog1" );
+ setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)1, 0, 0, sizePolicy().hasHeightForWidth() ) );
+ setSizeGripEnabled( FALSE );
+ setModal( TRUE );
+ MyDialog1Layout = new QVBoxLayout( this, 11, 6, "MyDialog1Layout");
+ MyDialog1Layout->setResizeMode( QLayout::Minimum );
+
+ tabWidget = new QTabWidget( this, "tabWidget" );
+
+ Widget8 = new QWidget( tabWidget, "Widget8" );
+ Widget8Layout = new QVBoxLayout( Widget8, 11, 6, "Widget8Layout");
+
+ layout4 = new QHBoxLayout( 0, 0, 6, "layout4");
+
+ buttonGroup1 = new QButtonGroup( Widget8, "buttonGroup1" );
+ buttonGroup1->setColumnLayout(0, Qt::Vertical );
+ buttonGroup1->layout()->setSpacing( 6 );
+ buttonGroup1->layout()->setMargin( 11 );
+ buttonGroup1Layout = new QVBoxLayout( buttonGroup1->layout() );
+ buttonGroup1Layout->setAlignment( Qt::AlignTop );
+
+ m_radioOnBeginOpenDialog = new QRadioButton( buttonGroup1, "m_radioOnBeginOpenDialog" );
+ buttonGroup1Layout->addWidget( m_radioOnBeginOpenDialog );
+
+ m_radioOnBeginOpenLast = new QRadioButton( buttonGroup1, "m_radioOnBeginOpenLast" );
+ buttonGroup1Layout->addWidget( m_radioOnBeginOpenLast );
+ layout4->addWidget( buttonGroup1 );
+
+ buttonGroup2 = new QButtonGroup( Widget8, "buttonGroup2" );
+ buttonGroup2->setColumnLayout(0, Qt::Vertical );
+ buttonGroup2->layout()->setSpacing( 6 );
+ buttonGroup2->layout()->setMargin( 11 );
+ buttonGroup2Layout = new QVBoxLayout( buttonGroup2->layout() );
+ buttonGroup2Layout->setAlignment( Qt::AlignTop );
+
+ layout3 = new QHBoxLayout( 0, 0, 6, "layout3");
+
+ textLabel1 = new QLabel( buttonGroup2, "textLabel1" );
+ layout3->addWidget( textLabel1 );
+
+ m_historySize = new QSpinBox( buttonGroup2, "m_historySize" );
+ m_historySize->setValue( 10 );
+ layout3->addWidget( m_historySize );
+
+ textLabel2 = new QLabel( buttonGroup2, "textLabel2" );
+ layout3->addWidget( textLabel2 );
+ buttonGroup2Layout->addLayout( layout3 );
+
+ m_rememberHistoryInfo = new QCheckBox( buttonGroup2, "m_rememberHistoryInfo" );
+ buttonGroup2Layout->addWidget( m_rememberHistoryInfo );
+ layout4->addWidget( buttonGroup2 );
+ Widget8Layout->addLayout( layout4 );
+
+ groupBox1 = new QGroupBox( Widget8, "groupBox1" );
+ groupBox1->setColumnLayout(0, Qt::Vertical );
+ groupBox1->layout()->setSpacing( 6 );
+ groupBox1->layout()->setMargin( 11 );
+ groupBox1Layout = new QHBoxLayout( groupBox1->layout() );
+ groupBox1Layout->setAlignment( Qt::AlignTop );
+
+ buttonGroup4 = new QButtonGroup( groupBox1, "buttonGroup4" );
+ buttonGroup4->setColumnLayout(0, Qt::Vertical );
+ buttonGroup4->layout()->setSpacing( 6 );
+ buttonGroup4->layout()->setMargin( 11 );
+ buttonGroup4Layout = new QVBoxLayout( buttonGroup4->layout() );
+ buttonGroup4Layout->setAlignment( Qt::AlignTop );
+
+ m_radioExtLinkOpenAlways = new QRadioButton( buttonGroup4, "m_radioExtLinkOpenAlways" );
+ buttonGroup4Layout->addWidget( m_radioExtLinkOpenAlways );
+
+ m_radioExtLinkAsk = new QRadioButton( buttonGroup4, "m_radioExtLinkAsk" );
+ buttonGroup4Layout->addWidget( m_radioExtLinkAsk );
+
+ m_radioExtLinkOpenNever = new QRadioButton( buttonGroup4, "m_radioExtLinkOpenNever" );
+ buttonGroup4Layout->addWidget( m_radioExtLinkOpenNever );
+ groupBox1Layout->addWidget( buttonGroup4 );
+
+ buttonGroup5 = new QButtonGroup( groupBox1, "buttonGroup5" );
+ buttonGroup5->setColumnLayout(0, Qt::Vertical );
+ buttonGroup5->layout()->setSpacing( 6 );
+ buttonGroup5->layout()->setMargin( 11 );
+ buttonGroup5Layout = new QVBoxLayout( buttonGroup5->layout() );
+ buttonGroup5Layout->setAlignment( Qt::AlignTop );
+
+ m_radioNewChmOpenAlways = new QRadioButton( buttonGroup5, "m_radioNewChmOpenAlways" );
+ buttonGroup5Layout->addWidget( m_radioNewChmOpenAlways );
+
+ m_radioNewChmAsk = new QRadioButton( buttonGroup5, "m_radioNewChmAsk" );
+ buttonGroup5Layout->addWidget( m_radioNewChmAsk );
+
+ m_radioNewChmOpenNever = new QRadioButton( buttonGroup5, "m_radioNewChmOpenNever" );
+ buttonGroup5Layout->addWidget( m_radioNewChmOpenNever );
+ groupBox1Layout->addWidget( buttonGroup5 );
+ Widget8Layout->addWidget( groupBox1 );
+ tabWidget->insertTab( Widget8, QString::fromLatin1("") );
+
+ Widget9 = new QWidget( tabWidget, "Widget9" );
+ Widget9Layout = new QVBoxLayout( Widget9, 11, 6, "Widget9Layout");
+
+ m_groupQtsettings = new QGroupBox( Widget9, "m_groupQtsettings" );
+ m_groupQtsettings->setColumnLayout(0, Qt::Vertical );
+ m_groupQtsettings->layout()->setSpacing( 6 );
+ m_groupQtsettings->layout()->setMargin( 11 );
+ m_groupQtsettingsLayout = new QHBoxLayout( m_groupQtsettings->layout() );
+ m_groupQtsettingsLayout->setAlignment( Qt::AlignTop );
+
+ textLabel1_2 = new QLabel( m_groupQtsettings, "textLabel1_2" );
+ textLabel1_2->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)7, 0, 0, textLabel1_2->sizePolicy().hasHeightForWidth() ) );
+ textLabel1_2->setLineWidth( 1 );
+ textLabel1_2->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ m_groupQtsettingsLayout->addWidget( textLabel1_2 );
+
+ m_qtBrowserPath = new QLineEdit( m_groupQtsettings, "m_qtBrowserPath" );
+ m_qtBrowserPath->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)0, 0, 0, m_qtBrowserPath->sizePolicy().hasHeightForWidth() ) );
+ m_groupQtsettingsLayout->addWidget( m_qtBrowserPath );
+ Widget9Layout->addWidget( m_groupQtsettings );
+
+ m_groupKDEsettings = new QGroupBox( Widget9, "m_groupKDEsettings" );
+ m_groupKDEsettings->setColumnLayout(0, Qt::Vertical );
+ m_groupKDEsettings->layout()->setSpacing( 6 );
+ m_groupKDEsettings->layout()->setMargin( 11 );
+ m_groupKDEsettingsLayout = new QHBoxLayout( m_groupKDEsettings->layout() );
+ m_groupKDEsettingsLayout->setAlignment( Qt::AlignTop );
+
+ buttonGroup5_2 = new QButtonGroup( m_groupKDEsettings, "buttonGroup5_2" );
+ buttonGroup5_2->setColumnLayout(0, Qt::Vertical );
+ buttonGroup5_2->layout()->setSpacing( 6 );
+ buttonGroup5_2->layout()->setMargin( 11 );
+ buttonGroup5_2Layout = new QVBoxLayout( buttonGroup5_2->layout() );
+ buttonGroup5_2Layout->setAlignment( Qt::AlignTop );
+
+ m_radioUseQtextBrowser = new QRadioButton( buttonGroup5_2, "m_radioUseQtextBrowser" );
+ buttonGroup5_2Layout->addWidget( m_radioUseQtextBrowser );
+
+ m_radioUseKHTMLPart = new QRadioButton( buttonGroup5_2, "m_radioUseKHTMLPart" );
+ buttonGroup5_2Layout->addWidget( m_radioUseKHTMLPart );
+ m_groupKDEsettingsLayout->addWidget( buttonGroup5_2 );
+
+ groupKhtmlSecurity = new QGroupBox( m_groupKDEsettings, "groupKhtmlSecurity" );
+ groupKhtmlSecurity->setColumnLayout(0, Qt::Vertical );
+ groupKhtmlSecurity->layout()->setSpacing( 6 );
+ groupKhtmlSecurity->layout()->setMargin( 11 );
+ groupKhtmlSecurityLayout = new QGridLayout( groupKhtmlSecurity->layout() );
+ groupKhtmlSecurityLayout->setAlignment( Qt::AlignTop );
+
+ m_enableJS = new QCheckBox( groupKhtmlSecurity, "m_enableJS" );
+
+ groupKhtmlSecurityLayout->addWidget( m_enableJS, 0, 0 );
+
+ m_enablePlugins = new QCheckBox( groupKhtmlSecurity, "m_enablePlugins" );
+
+ groupKhtmlSecurityLayout->addWidget( m_enablePlugins, 0, 1 );
+
+ m_enableJava = new QCheckBox( groupKhtmlSecurity, "m_enableJava" );
+
+ groupKhtmlSecurityLayout->addWidget( m_enableJava, 1, 0 );
+
+ m_enableRefresh = new QCheckBox( groupKhtmlSecurity, "m_enableRefresh" );
+
+ groupKhtmlSecurityLayout->addWidget( m_enableRefresh, 1, 1 );
+ m_groupKDEsettingsLayout->addWidget( groupKhtmlSecurity );
+ Widget9Layout->addWidget( m_groupKDEsettings );
+ tabWidget->insertTab( Widget9, QString::fromLatin1("") );
+
+ TabPage = new QWidget( tabWidget, "TabPage" );
+ TabPageLayout = new QVBoxLayout( TabPage, 11, 6, "TabPageLayout");
+
+ buttonGroup7 = new QButtonGroup( TabPage, "buttonGroup7" );
+ buttonGroup7->setColumnLayout(0, Qt::Vertical );
+ buttonGroup7->layout()->setSpacing( 6 );
+ buttonGroup7->layout()->setMargin( 11 );
+ buttonGroup7Layout = new QVBoxLayout( buttonGroup7->layout() );
+ buttonGroup7Layout->setAlignment( Qt::AlignTop );
+
+ m_advViewSourceInternal = new QRadioButton( buttonGroup7, "m_advViewSourceInternal" );
+ buttonGroup7Layout->addWidget( m_advViewSourceInternal );
+
+ m_advViewSourceExternal = new QRadioButton( buttonGroup7, "m_advViewSourceExternal" );
+ buttonGroup7Layout->addWidget( m_advViewSourceExternal );
+
+ layout4_2 = new QHBoxLayout( 0, 0, 6, "layout4_2");
+
+ textLabel1_3 = new QLabel( buttonGroup7, "textLabel1_3" );
+ layout4_2->addWidget( textLabel1_3 );
+
+ m_advExternalProgramName = new QLineEdit( buttonGroup7, "m_advExternalProgramName" );
+ layout4_2->addWidget( m_advExternalProgramName );
+ buttonGroup7Layout->addLayout( layout4_2 );
+ TabPageLayout->addWidget( buttonGroup7 );
+
+ groupBox6 = new QButtonGroup( TabPage, "groupBox6" );
+ groupBox6->setColumnLayout(0, Qt::Vertical );
+ groupBox6->layout()->setSpacing( 6 );
+ groupBox6->layout()->setMargin( 11 );
+ groupBox6Layout = new QGridLayout( groupBox6->layout() );
+ groupBox6Layout->setAlignment( Qt::AlignTop );
+
+ m_useSearchEngineInternal = new QRadioButton( groupBox6, "m_useSearchEngineInternal" );
+
+ groupBox6Layout->addWidget( m_useSearchEngineInternal, 1, 0 );
+
+ m_labelUseSearchEngineInternal = new QLabel( groupBox6, "m_labelUseSearchEngineInternal" );
+ m_labelUseSearchEngineInternal->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 10, 0, m_labelUseSearchEngineInternal->sizePolicy().hasHeightForWidth() ) );
+ m_labelUseSearchEngineInternal->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+
+ groupBox6Layout->addWidget( m_labelUseSearchEngineInternal, 1, 1 );
+
+ m_useSearchEngineNew = new QRadioButton( groupBox6, "m_useSearchEngineNew" );
+
+ groupBox6Layout->addWidget( m_useSearchEngineNew, 0, 0 );
+
+ m_labelUseSearchEngineNew = new QLabel( groupBox6, "m_labelUseSearchEngineNew" );
+ m_labelUseSearchEngineNew->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 10, 0, m_labelUseSearchEngineNew->sizePolicy().hasHeightForWidth() ) );
+ m_labelUseSearchEngineNew->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+
+ groupBox6Layout->addWidget( m_labelUseSearchEngineNew, 0, 1 );
+ TabPageLayout->addWidget( groupBox6 );
+ tabWidget->insertTab( TabPage, QString::fromLatin1("") );
+ MyDialog1Layout->addWidget( tabWidget );
+
+ Layout1 = new QHBoxLayout( 0, 0, 6, "Layout1");
+
+ buttonHelp = new QPushButton( this, "buttonHelp" );
+ buttonHelp->setAutoDefault( TRUE );
+ Layout1->addWidget( buttonHelp );
+ Horizontal_Spacing2 = new QSpacerItem( 20, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ Layout1->addItem( Horizontal_Spacing2 );
+
+ buttonOk = new QPushButton( this, "buttonOk" );
+ buttonOk->setAutoDefault( TRUE );
+ buttonOk->setDefault( TRUE );
+ Layout1->addWidget( buttonOk );
+
+ buttonCancel = new QPushButton( this, "buttonCancel" );
+ buttonCancel->setAutoDefault( TRUE );
+ Layout1->addWidget( buttonCancel );
+ MyDialog1Layout->addLayout( Layout1 );
+ languageChange();
+ resize( QSize(654, 343).expandedTo(minimumSizeHint()) );
+ clearWState( WState_Polished );
+
+ // signals and slots connections
+ connect( buttonOk, SIGNAL( clicked() ), this, SLOT( accept() ) );
+ connect( buttonCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
+ connect( m_radioUseKHTMLPart, SIGNAL( toggled(bool) ), groupKhtmlSecurity, SLOT( setEnabled(bool) ) );
+ connect( m_advViewSourceExternal, SIGNAL( toggled(bool) ), m_advExternalProgramName, SLOT( setEnabled(bool) ) );
+ connect( m_radioUseQtextBrowser, SIGNAL( toggled(bool) ), groupKhtmlSecurity, SLOT( setDisabled(bool) ) );
+
+ // tab order
+ setTabOrder( m_advViewSourceInternal, m_advViewSourceExternal );
+ setTabOrder( m_advViewSourceExternal, m_useSearchEngineNew );
+ setTabOrder( m_useSearchEngineNew, m_useSearchEngineInternal );
+ setTabOrder( m_useSearchEngineInternal, tabWidget );
+ setTabOrder( tabWidget, m_radioOnBeginOpenDialog );
+ setTabOrder( m_radioOnBeginOpenDialog, m_radioOnBeginOpenLast );
+ setTabOrder( m_radioOnBeginOpenLast, m_historySize );
+ setTabOrder( m_historySize, m_rememberHistoryInfo );
+ setTabOrder( m_rememberHistoryInfo, m_radioExtLinkOpenAlways );
+ setTabOrder( m_radioExtLinkOpenAlways, m_radioExtLinkAsk );
+ setTabOrder( m_radioExtLinkAsk, m_radioExtLinkOpenNever );
+ setTabOrder( m_radioExtLinkOpenNever, m_radioNewChmOpenAlways );
+ setTabOrder( m_radioNewChmOpenAlways, m_radioNewChmAsk );
+ setTabOrder( m_radioNewChmAsk, m_radioNewChmOpenNever );
+ setTabOrder( m_radioNewChmOpenNever, m_qtBrowserPath );
+ setTabOrder( m_qtBrowserPath, m_radioUseQtextBrowser );
+ setTabOrder( m_radioUseQtextBrowser, m_radioUseKHTMLPart );
+ setTabOrder( m_radioUseKHTMLPart, m_enableJS );
+ setTabOrder( m_enableJS, m_enablePlugins );
+ setTabOrder( m_enablePlugins, m_enableJava );
+ setTabOrder( m_enableJava, m_enableRefresh );
+ setTabOrder( m_enableRefresh, m_advExternalProgramName );
+ setTabOrder( m_advExternalProgramName, buttonHelp );
+ setTabOrder( buttonHelp, buttonOk );
+ setTabOrder( buttonOk, buttonCancel );
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+KCHMSetupDialog::~KCHMSetupDialog()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+/*
+ * Sets the strings of the subwidgets using the current
+ * language.
+ */
+void KCHMSetupDialog::languageChange()
+{
+ setCaption( tr( "KchmViewer settings" ) );
+ buttonGroup1->setTitle( tr( "If no arguments given on load" ) );
+ m_radioOnBeginOpenDialog->setText( tr( "Open the 'open CHM file' dialog" ) );
+ m_radioOnBeginOpenLast->setText( tr( "Open the &last used CHM file, if exist" ) );
+ m_radioOnBeginOpenLast->setAccel( QKeySequence( tr( "Alt+L" ) ) );
+ buttonGroup2->setTitle( tr( "History" ) );
+ textLabel1->setText( tr( "Store history information for" ) );
+ m_historySize->setPrefix( QString::null );
+ textLabel2->setText( tr( "latest files" ) );
+ m_rememberHistoryInfo->setText( tr( "R&emember extra information for history files" ) );
+ m_rememberHistoryInfo->setAccel( QKeySequence( tr( "Alt+E" ) ) );
+ QToolTip::add( m_rememberHistoryInfo, tr( "Remembers the information about the files, which were opened. Remembers last opened page, search history, font size, bookmarks and so on." ) );
+ groupBox1->setTitle( tr( "CHM security settings" ) );
+ buttonGroup4->setTitle( tr( "When external link clicked" ) );
+ m_radioExtLinkOpenAlways->setText( tr( "Alwa&ys open it in external browser" ) );
+ m_radioExtLinkOpenAlways->setAccel( QKeySequence( tr( "Alt+Y" ) ) );
+ m_radioExtLinkAsk->setText( tr( "Ask for confirmation" ) );
+ m_radioExtLinkOpenNever->setText( tr( "Do not open the link" ) );
+ m_radioExtLinkOpenNever->setAccel( QKeySequence( QString::null ) );
+ buttonGroup5->setTitle( tr( "When link pointed to a new CHM file clicked" ) );
+ m_radioNewChmOpenAlways->setText( tr( "Always open a new CHM file" ) );
+ m_radioNewChmAsk->setText( tr( "Ask for confirmation" ) );
+ m_radioNewChmOpenNever->setText( tr( "Do not open a new CHM file" ) );
+ tabWidget->changeTab( Widget8, tr( "General behavior" ) );
+ m_groupQtsettings->setTitle( tr( "Qt version settings" ) );
+ textLabel1_2->setText( tr( "Enter the path to the program, which will be used as a browser for external links. A <i>%s</i> symbol will be replaced by the URL clicked." ) );
+ m_groupKDEsettings->setTitle( tr( "KDE version settings" ) );
+ buttonGroup5_2->setTitle( tr( "To show HTML content, use" ) );
+ m_radioUseQtextBrowser->setText( tr( "&QTextBrowser-based widget" ) );
+ m_radioUseQtextBrowser->setAccel( QKeySequence( tr( "Alt+Q" ) ) );
+ m_radioUseKHTMLPart->setText( tr( "&KHTMLPart-based widget" ) );
+ m_radioUseKHTMLPart->setAccel( QKeySequence( tr( "Alt+K" ) ) );
+ groupKhtmlSecurity->setTitle( tr( "KHTMLPart security" ) );
+ m_enableJS->setText( tr( "Enable Java&Script" ) );
+ m_enableJS->setAccel( QKeySequence( tr( "Alt+S" ) ) );
+ m_enablePlugins->setText( tr( "Enable &plugins" ) );
+ m_enablePlugins->setAccel( QKeySequence( tr( "Alt+P" ) ) );
+ m_enableJava->setText( tr( "Enable &Java" ) );
+ m_enableJava->setAccel( QKeySequence( tr( "Alt+J" ) ) );
+ m_enableRefresh->setText( tr( "Enable &refresh" ) );
+ m_enableRefresh->setAccel( QKeySequence( tr( "Alt+R" ) ) );
+ tabWidget->changeTab( Widget9, tr( "Version-specific settings" ) );
+ buttonGroup7->setTitle( tr( "View HTML source command uses" ) );
+ m_advViewSourceInternal->setText( tr( "Built-in HTML source viewer" ) );
+ m_advViewSourceInternal->setAccel( QKeySequence( QString::null ) );
+ m_advViewSourceExternal->setText( tr( "E&xternal program, specified below" ) );
+ m_advViewSourceExternal->setAccel( QKeySequence( tr( "Alt+X" ) ) );
+ textLabel1_3->setText( tr( "External program:" ) );
+ groupBox6->setTitle( tr( "Search engine to use" ) );
+ m_useSearchEngineInternal->setText( QString::null );
+ m_labelUseSearchEngineInternal->setText( tr( "Use the search based on internal CHM index. This engine cannot search for any symbols except underscode, does not support multibyte languages, and is not always available." ) );
+ m_useSearchEngineNew->setText( QString::null );
+ m_labelUseSearchEngineNew->setText( tr( "Use new kchmviewer internal search engine (recommended). This engine indexes symbols, so it is possible to search for special symbols (like \"C++\"). All languages are supported. The index will be generated before the first search." ) );
+ tabWidget->changeTab( TabPage, tr( "Advanced" ) );
+ buttonHelp->setText( tr( "&Help" ) );
+ buttonHelp->setAccel( QKeySequence( tr( "F1" ) ) );
+ buttonOk->setText( tr( "&OK" ) );
+ buttonOk->setAccel( QKeySequence( QString::null ) );
+ buttonCancel->setText( tr( "&Cancel" ) );
+ buttonCancel->setAccel( QKeySequence( QString::null ) );
+}
+
+void KCHMSetupDialog::m_radioUseKHTMLPart_toggled(bool)
+{
+ qWarning( "KCHMSetupDialog::m_radioUseKHTMLPart_toggled(bool): Not implemented yet" );
+}
+
+#include "kchmsetupdialog.moc"
diff --git a/src/kchmsetupdialog.ui b/src/kchmsetupdialog.ui
new file mode 100644
index 0000000..c65d0fa
--- /dev/null
+++ b/src/kchmsetupdialog.ui
@@ -0,0 +1,710 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KCHMSetupDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>MyDialog1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>654</width>
+ <height>343</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="caption">
+ <string>KchmViewer settings</string>
+ </property>
+ <property name="sizeGripEnabled">
+ <bool>false</bool>
+ </property>
+ <property name="modal">
+ <bool>true</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <property name="resizeMode">
+ <enum>Minimum</enum>
+ </property>
+ <widget class="QTabWidget">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget8</cstring>
+ </property>
+ <attribute name="title">
+ <string>General behavior</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup1</cstring>
+ </property>
+ <property name="title">
+ <string>If no arguments given on load</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioOnBeginOpenDialog</cstring>
+ </property>
+ <property name="text">
+ <string>Open the 'open CHM file' dialog</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioOnBeginOpenLast</cstring>
+ </property>
+ <property name="text">
+ <string>Open the &amp;last used CHM file, if exist</string>
+ </property>
+ <property name="accel">
+ <string>Alt+L</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup2</cstring>
+ </property>
+ <property name="title">
+ <string>History</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout3</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Store history information for</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>m_historySize</cstring>
+ </property>
+ <property name="prefix">
+ <string></string>
+ </property>
+ <property name="value">
+ <number>10</number>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>latest files</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>m_rememberHistoryInfo</cstring>
+ </property>
+ <property name="text">
+ <string>R&amp;emember extra information for history files</string>
+ </property>
+ <property name="accel">
+ <string>Alt+E</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Remembers the information about the files, which were opened. Remembers last opened page, search history, font size, bookmarks and so on.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string>CHM security settings</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup4</cstring>
+ </property>
+ <property name="title">
+ <string>When external link clicked</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioExtLinkOpenAlways</cstring>
+ </property>
+ <property name="text">
+ <string>Alwa&amp;ys open it in external browser</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Y</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioExtLinkAsk</cstring>
+ </property>
+ <property name="text">
+ <string>Ask for confirmation</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioExtLinkOpenNever</cstring>
+ </property>
+ <property name="text">
+ <string>Do not open the link</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup5</cstring>
+ </property>
+ <property name="title">
+ <string>When link pointed to a new CHM file clicked</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioNewChmOpenAlways</cstring>
+ </property>
+ <property name="text">
+ <string>Always open a new CHM file</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioNewChmAsk</cstring>
+ </property>
+ <property name="text">
+ <string>Ask for confirmation</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioNewChmOpenNever</cstring>
+ </property>
+ <property name="text">
+ <string>Do not open a new CHM file</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget9</cstring>
+ </property>
+ <attribute name="title">
+ <string>Version-specific settings</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupQtsettings</cstring>
+ </property>
+ <property name="title">
+ <string>Qt version settings</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="lineWidth">
+ <number>1</number>
+ </property>
+ <property name="text">
+ <string>Enter the path to the program, which will be used as a browser for external links. A &lt;i&gt;%s&lt;/i&gt; symbol will be replaced by the URL clicked.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_qtBrowserPath</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>m_groupKDEsettings</cstring>
+ </property>
+ <property name="title">
+ <string>KDE version settings</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup5_2</cstring>
+ </property>
+ <property name="title">
+ <string>To show HTML content, use</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioUseQtextBrowser</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;QTextBrowser-based widget</string>
+ </property>
+ <property name="accel">
+ <string>Alt+Q</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_radioUseKHTMLPart</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;KHTMLPart-based widget</string>
+ </property>
+ <property name="accel">
+ <string>Alt+K</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupKhtmlSecurity</cstring>
+ </property>
+ <property name="title">
+ <string>KHTMLPart security</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0">
+ <property name="name">
+ <cstring>m_enableJS</cstring>
+ </property>
+ <property name="text">
+ <string>Enable Java&amp;Script</string>
+ </property>
+ <property name="accel">
+ <string>Alt+S</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>m_enablePlugins</cstring>
+ </property>
+ <property name="text">
+ <string>Enable &amp;plugins</string>
+ </property>
+ <property name="accel">
+ <string>Alt+P</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>m_enableJava</cstring>
+ </property>
+ <property name="text">
+ <string>Enable &amp;Java</string>
+ </property>
+ <property name="accel">
+ <string>Alt+J</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>m_enableRefresh</cstring>
+ </property>
+ <property name="text">
+ <string>Enable &amp;refresh</string>
+ </property>
+ <property name="accel">
+ <string>Alt+R</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>TabPage</cstring>
+ </property>
+ <attribute name="title">
+ <string>Advanced</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>buttonGroup7</cstring>
+ </property>
+ <property name="title">
+ <string>View HTML source command uses</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_advViewSourceInternal</cstring>
+ </property>
+ <property name="text">
+ <string>Built-in HTML source viewer</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QRadioButton">
+ <property name="name">
+ <cstring>m_advViewSourceExternal</cstring>
+ </property>
+ <property name="text">
+ <string>E&amp;xternal program, specified below</string>
+ </property>
+ <property name="accel">
+ <string>Alt+X</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>External program:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_advExternalProgramName</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>groupBox6</cstring>
+ </property>
+ <property name="title">
+ <string>Search engine to use</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>m_useSearchEngineInternal</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>m_labelUseSearchEngineInternal</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>10</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Use the search based on internal CHM index. This engine cannot search for any symbols except underscode, does not support multibyte languages, and is not always available.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>m_useSearchEngineNew</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>m_labelUseSearchEngineNew</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>10</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Use new kchmviewer internal search engine (recommended). This engine indexes symbols, so it is possible to search for special symbols (like "C++"). All languages are supported. The index will be generated before the first search.</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignVCenter</set>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </vbox>
+ </widget>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonHelp</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Help</string>
+ </property>
+ <property name="accel">
+ <string>F1</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Horizontal Spacing2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonOk</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;OK</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>buttonCancel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ <property name="accel">
+ <string></string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>buttonOk</sender>
+ <signal>clicked()</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonCancel</sender>
+ <signal>clicked()</signal>
+ <receiver>MyDialog1</receiver>
+ <slot>reject()</slot>
+ </connection>
+ <connection>
+ <sender>m_radioUseKHTMLPart</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>groupKhtmlSecurity</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_advViewSourceExternal</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>m_advExternalProgramName</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>m_radioUseQtextBrowser</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>groupKhtmlSecurity</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>m_advViewSourceInternal</tabstop>
+ <tabstop>m_advViewSourceExternal</tabstop>
+ <tabstop>m_useSearchEngineNew</tabstop>
+ <tabstop>m_useSearchEngineInternal</tabstop>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>m_radioOnBeginOpenDialog</tabstop>
+ <tabstop>m_radioOnBeginOpenLast</tabstop>
+ <tabstop>m_historySize</tabstop>
+ <tabstop>m_rememberHistoryInfo</tabstop>
+ <tabstop>m_radioExtLinkOpenAlways</tabstop>
+ <tabstop>m_radioExtLinkAsk</tabstop>
+ <tabstop>m_radioExtLinkOpenNever</tabstop>
+ <tabstop>m_radioNewChmOpenAlways</tabstop>
+ <tabstop>m_radioNewChmAsk</tabstop>
+ <tabstop>m_radioNewChmOpenNever</tabstop>
+ <tabstop>m_qtBrowserPath</tabstop>
+ <tabstop>m_radioUseQtextBrowser</tabstop>
+ <tabstop>m_radioUseKHTMLPart</tabstop>
+ <tabstop>m_enableJS</tabstop>
+ <tabstop>m_enablePlugins</tabstop>
+ <tabstop>m_enableJava</tabstop>
+ <tabstop>m_enableRefresh</tabstop>
+ <tabstop>m_advExternalProgramName</tabstop>
+ <tabstop>buttonHelp</tabstop>
+ <tabstop>buttonOk</tabstop>
+ <tabstop>buttonCancel</tabstop>
+</tabstops>
+<slots>
+ <slot>m_radioUseKHTMLPart_toggled( bool )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/src/kchmsourcefactory.cpp b/src/kchmsourcefactory.cpp
new file mode 100644
index 0000000..8b4232c
--- /dev/null
+++ b/src/kchmsourcefactory.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qcstring.h>
+#include <qimage.h>
+#include <qdir.h>
+
+#include "libchmfile.h"
+#include "libchmurlfactory.h"
+
+#include "kchmmainwindow.h"
+#include "kchmviewwindow.h"
+#include "kchmsourcefactory.h"
+#include "kchmviewwindow_qtextbrowser.h"
+
+
+KCHMSourceFactory::KCHMSourceFactory (KCHMViewWindow * viewwindow)
+ : QMimeSourceFactory()
+{
+ m_viewWindow = viewwindow;
+}
+
+
+const QMimeSource * KCHMSourceFactory::data( const QString & abs_name ) const
+{
+ QString data, file, path = abs_name;
+
+ // Retreive the data from chm file
+ LCHMFile * chm = ::mainWindow->chmFile();
+
+ if ( !chm )
+ return 0;
+
+ int pos = path.find ('#');
+ if ( pos != -1 )
+ path = path.left (pos);
+
+ // To handle a single-image pages, we need to generate the HTML page to show
+ // this image. We did it in KCHMViewWindow::handleStartPageAsImage; now we need
+ // to generate the HTML page, and set it.
+ if ( LCHMUrlFactory::handleFileType( path, data ) )
+ {
+ ((QMimeSourceFactory*)this)->setText (path, data);
+ }
+ else if ( path.endsWith (".htm") || path.endsWith (".html") )
+ {
+ if ( chm->getFileContentAsString( &data, path ) )
+ ((QMimeSourceFactory*)this)->setText (path, data);
+ }
+ else
+ {
+ // treat as image
+ QImage img;
+ QByteArray buf;
+
+ QString fpath = KCHMViewWindow_QTextBrowser::decodeUrl( path );
+
+ if ( chm->getFileContentAsBinary( &buf, fpath ) )
+ {
+ if ( img.loadFromData ( (const uchar *) buf.data(), buf.size() ) )
+ ((QMimeSourceFactory*)this)->setImage (path, img);
+ }
+ else
+ {
+ ((QMimeSourceFactory*)this)->setImage( path, img );
+ qWarning( "Could not resolve file %s\n", path.ascii() );
+ }
+ }
+
+ return QMimeSourceFactory::data (path);
+}
+
+QString KCHMSourceFactory::makeAbsolute ( const QString & abs_or_rel_name, const QString & ) const
+{
+ return m_viewWindow->makeURLabsolute ( abs_or_rel_name, false );
+}
diff --git a/src/kchmsourcefactory.h b/src/kchmsourcefactory.h
new file mode 100644
index 0000000..dd03968
--- /dev/null
+++ b/src/kchmsourcefactory.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMSOURCEFACTORY_H
+#define KCHMSOURCEFACTORY_H
+
+#include <qmime.h>
+#include "forwarddeclarations.h"
+
+/**
+@author Georgy Yunaev
+*/
+class KCHMSourceFactory : public QMimeSourceFactory
+{
+public:
+ KCHMSourceFactory (KCHMViewWindow * viewwindow);
+
+ virtual const QMimeSource * data ( const QString & abs_name ) const;
+ virtual QString makeAbsolute ( const QString & abs_or_rel_name, const QString & context ) const;
+
+private:
+ KCHMViewWindow * m_viewWindow;
+};
+
+#endif
diff --git a/src/kchmtreeviewitem.cpp b/src/kchmtreeviewitem.cpp
new file mode 100644
index 0000000..7a82a39
--- /dev/null
+++ b/src/kchmtreeviewitem.cpp
@@ -0,0 +1,286 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qstringlist.h>
+#include <qstyle.h>
+
+#include "kchmtreeviewitem.h"
+#include "kchmmainwindow.h"
+#include "kchmdialogchooseurlfromlist.h"
+#include "iconstorage.h"
+
+
+KCHMIndTocItem::KCHMIndTocItem( QListViewItem * parent, QListViewItem * after, QString name, QString aurl, int image) : QListViewItem(parent, after, name), url(aurl), image_number(image)
+{
+}
+
+KCHMIndTocItem::KCHMIndTocItem( QListView * parent, QListViewItem * after, QString name, QString aurl, int image) : QListViewItem(parent, after, name), url(aurl), image_number(image)
+{
+}
+
+
+const QPixmap * KCHMIndTocItem::pixmap( int i ) const
+{
+ int imagenum;
+
+ if ( i || image_number == LCHMBookIcons::IMAGE_NONE || image_number == LCHMBookIcons::IMAGE_INDEX )
+ return 0;
+
+ if ( firstChild () )
+ {
+ if ( isOpen() )
+ imagenum = (image_number == LCHMBookIcons::IMAGE_AUTO) ? 1 : image_number;
+ else
+ imagenum = (image_number == LCHMBookIcons::IMAGE_AUTO) ? 0 : image_number + 1;
+ }
+ else
+ imagenum = (image_number == LCHMBookIcons::IMAGE_AUTO) ? 10 : image_number;
+
+ return ::mainWindow->chmFile()->getBookIconPixmap( imagenum );
+}
+
+
+QString KCHMIndTocItem::getUrl( ) const
+{
+ if ( url.find ('|') == -1 )
+ return url;
+
+ // Create a dialog with URLs, and show it, so user can select an URL he/she wants.
+ QStringList urls = QStringList::split ('|', url);
+ QStringList titles;
+ LCHMFile * xchm = ::mainWindow->chmFile();
+
+ for ( unsigned int i = 0; i < urls.size(); i++ )
+ {
+ QString title = xchm->getTopicByUrl (urls[i]);
+
+ if ( !title )
+ {
+ qWarning ("Could not get item name for url '%s'", urls[i].ascii());
+ titles.push_back(QString::null);
+ }
+ else
+ titles.push_back(title);
+ }
+
+ KCHMDialogChooseUrlFromList dlg (urls, titles, ::mainWindow);
+
+ if ( dlg.exec() == QDialog::Accepted )
+ return dlg.getSelectedItemUrl();
+
+ return QString::null;
+}
+
+
+void KCHMIndTocItem::paintBranches( QPainter * p, const QColorGroup & cg, int w, int y, int h )
+{
+ if ( image_number != LCHMBookIcons::IMAGE_INDEX )
+ QListViewItem::paintBranches(p, cg, w, y, h);
+ else
+ {
+ // Too bad that listView()->paintEmptyArea( p, QRect( 0, 0, w, h ) ) is protected.
+ // Taken from qt-x11-free-3.0.4/src/widgets/qlistview.cpp
+ QStyleOption opt( 0, 0 );
+ QStyle::SFlags how = QStyle::Style_Default | QStyle::Style_Enabled;
+
+ listView()->style().drawComplexControl( QStyle::CC_ListView,
+ p, listView(), QRect( 0, 0, w, h ), cg,
+ how, QStyle::SC_ListView, QStyle::SC_None,
+ opt );
+ }
+}
+
+
+void KCHMIndTocItem::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int align )
+{
+ QColorGroup newcg ( cg );
+ QColor c = newcg.text();
+
+ if ( url.find ('|') != -1 )
+ newcg.setColor( QColorGroup::Text, Qt::red );
+ else if ( url[0] == ':' )
+ newcg.setColor( QColorGroup::Text, Qt::lightGray );
+ else
+ {
+ QListViewItem::paintCell( p, cg, column, width, align );
+ return;
+ }
+
+ QListViewItem::paintCell( p, newcg, column, width, align );
+ newcg.setColor( QColorGroup::Text, c );
+}
+
+
+void KCHMIndTocItem::setOpen( bool open )
+{
+ if ( image_number != LCHMBookIcons::IMAGE_INDEX || open )
+ QListViewItem::setOpen (open);
+}
+
+void kchmFillListViewWithParsedData( QListView * list, const QValueVector< LCHMParsedEntry >& data, QMap<QString, KCHMIndTocItem*> * map )
+{
+ QValueVector< KCHMIndTocItem *> lastchild;
+ QValueVector< KCHMIndTocItem *> rootentry;
+
+ if ( map )
+ map->clear();
+
+ list->clear();
+
+ for ( unsigned int i = 0; i < data.size(); i++ )
+ {
+ unsigned int indent = data[i].indent;
+
+ // Do we need to add another indent?
+ if ( indent >= lastchild.size() )
+ {
+ lastchild.resize( indent + 1 );
+ lastchild[indent] = 0;
+
+ rootentry.resize( indent + 1 );
+ rootentry[indent] = 0;
+ }
+
+ // Create the node
+ KCHMIndTocItem * item;
+ QString url = data[i].urls.join ("|");
+
+ if ( indent == 0 )
+ item = new KCHMIndTocItem( list, lastchild[indent], data[i].name, url, data[i].imageid );
+ else
+ {
+ // New non-root entry. It is possible (for some buggy CHMs) that there is no previous entry: previoous entry had indent 1,
+ // and next entry has indent 3. Backtracking it up, creating missing entries.
+ if ( rootentry[indent-1] == 0 )
+ qFatal("Child entry indented as %d with no root entry!", indent);
+
+ item = new KCHMIndTocItem( rootentry[indent-1], lastchild[indent], data[i].name, url, data[i].imageid );
+ }
+
+ // Hack: if map is 0, we have index, so make it open
+ if ( map )
+ {
+ for ( unsigned int li = 0; li < data[i].urls.size(); li++ )
+ map->insert( data[i].urls[li], item );
+ }
+ else
+ item->setOpen( true );
+
+ lastchild[indent] = item;
+ rootentry[indent] = item;
+ }
+
+ list->triggerUpdate();
+/*
+ KCHMMainTreeViewItem * item;
+
+ if ( !root_indent_offset_set )
+ {
+ root_indent_offset_set = true;
+ root_indent_offset = indent;
+
+ if ( root_indent_offset > 1 )
+ qWarning("CHM has improper index; root indent offset is %d", root_indent_offset);
+ }
+
+ int real_indent = indent - root_indent_offset;
+ QString url = urls.join ("|");
+
+ if ( real_indent == 0 )
+ {
+ // New root entry
+ item = new KCHMMainTreeViewItem (tree, lastchild[real_indent], name, url, imagenum);
+ DEBUGPARSER(("<root object>: '%s', new rootentry %08X\n", name.ascii(), item));
+ }
+ else
+ {
+ // New non-root entry
+ if ( !rootentry[real_indent-1] )
+ qFatal("CHMFile::ParseAndFillTopicsTree: child entry \"%s\" indented as %d with no root entry!", name.ascii(), real_indent);
+
+ item = new KCHMMainTreeViewItem (rootentry[real_indent-1], lastchild[real_indent], name, url, imagenum);
+ DEBUGPARSER(("<object>: '%s', indent %d, rootentry %08X, item %08X\n", name.ascii(), real_indent, rootentry[real_indent-1], item));
+ }
+
+ lastchild[real_indent] = item;
+ rootentry[real_indent] = item;
+
+ if ( asIndex )
+ rootentry[real_indent]->setOpen(true);
+
+ // There are no 'titles' in index file
+ if ( add2treemap )
+ {
+ for ( unsigned int li = 0; li < urls.size(); li++ )
+ m_treeUrlMap[urls[li]] = item;
+ }
+ }
+ else
+ {
+ if ( !urls.isEmpty() )
+ qDebug ("CHMFile::ParseAndFillTopicsTree: <object> tag with url \"%s\" is parsed, but name is empty.", urls[0].ascii());
+ else
+ qDebug ("CHMFile::ParseAndFillTopicsTree: <object> tag is parsed, but both name and url are empty.");
+ }
+
+ name = QString::null;
+ urls.clear();
+ in_object = false;
+ imagenum = defaultimagenum;
+ }
+ }
+ else if ( tagword == "ul" ) // increase indent level
+ {
+ // Fix for buggy help files
+ if ( ++indent >= MAX_NEST_DEPTH )
+ qFatal("CHMFile::ParseAndFillTopicsTree: max nest depth (%d) is reached, error in help file", MAX_NEST_DEPTH);
+
+ lastchild[indent] = 0;
+ rootentry[indent] = 0;
+
+ // This intended to fix <ul><ul>, which was seen in some buggy chm files,
+ // and brokes rootentry[indent-1] check
+ int real_indent = indent - root_indent_offset;
+ if ( real_indent > 1
+ && rootentry[real_indent - 1] == 0
+ && rootentry[real_indent - 2] != 0 )
+ {
+ rootentry[real_indent - 1] = rootentry[real_indent - 2];
+ qWarning("Broken CHM index/content: tree autocorrection enabled.");
+ }
+
+ DEBUGPARSER(("<ul>: new indent is %d, last rootentry was %08X\n", indent - root_indent_offset, rootentry[indent-1]));
+ }
+ else if ( tagword == "/ul" ) // decrease indent level
+ {
+ if ( --indent < root_indent_offset )
+ indent = root_indent_offset;
+
+ rootentry[indent] = 0;
+ DEBUGPARSER(("</ul>: new intent is %d\n", indent - root_indent_offset));
+ }
+
+ pos = i;
+ }
+
+ return true;
+*/
+}
diff --git a/src/kchmtreeviewitem.h b/src/kchmtreeviewitem.h
new file mode 100644
index 0000000..7dd7011
--- /dev/null
+++ b/src/kchmtreeviewitem.h
@@ -0,0 +1,100 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef CTREEVIEWITEM_H
+#define CTREEVIEWITEM_H
+
+#include <qlistview.h>
+#include <qvaluevector.h>
+
+#include "libchmfile.h"
+
+/**
+@author Georgy Yunaev
+*/
+//! This is a list item used both in Index and Table Of Content trees
+class KCHMIndTocItem : public QListViewItem
+{
+ public:
+ KCHMIndTocItem( QListViewItem* parent, QListViewItem* after, QString name, QString aurl, int image);
+ KCHMIndTocItem( QListView* parent, QListViewItem* after, QString name, QString url, int image);
+
+ QString getUrl() const;
+ virtual void setOpen ( bool open );
+
+ private:
+ virtual void paintBranches ( QPainter * p, const QColorGroup & cg, int w, int y, int h );
+ virtual void paintCell ( QPainter * p, const QColorGroup & cg, int column, int width, int align );
+ virtual const QPixmap * pixmap( int i ) const;
+
+ QString url;
+ int image_number;
+};
+
+
+class KCMSearchTreeViewItem : public QListViewItem
+{
+ public:
+ KCMSearchTreeViewItem (QListView* parent, QString name, QString loc, QString url)
+ : QListViewItem (parent, name, loc)
+ {
+ this->url = url;
+ }
+
+ QString getUrl() const { return url; }
+
+ private:
+ QString url;
+};
+
+
+class KCHMSingleTreeViewItem : public QListViewItem
+{
+ public:
+ KCHMSingleTreeViewItem (QListView* parent, QString name, QString url)
+ : QListViewItem (parent, name)
+ {
+ this->url = url;
+ }
+
+ QString getUrl() const { return url; }
+
+ private:
+ QString url;
+};
+
+
+class KCHMBookmarkTreeViewItem : public QListViewItem
+{
+ public:
+ KCHMBookmarkTreeViewItem (QListView* parent, QString n, QString u, int s)
+ : QListViewItem (parent, n), url(u), name(n), scroll_y(s) { menuid = 0; }
+
+ QString url;
+ QString name;
+ int scroll_y;
+ int menuid;
+};
+
+
+void kchmFillListViewWithParsedData( QListView * list, const QValueVector< LCHMParsedEntry >& data, QMap<QString, KCHMIndTocItem*> * map );
+
+#endif
diff --git a/src/kchmviewwindow.cpp b/src/kchmviewwindow.cpp
new file mode 100644
index 0000000..3eea6ca
--- /dev/null
+++ b/src/kchmviewwindow.cpp
@@ -0,0 +1,314 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+// Do not use tr() or i18n() in this file - this class is not derived from QObject.
+
+#include <qregexp.h>
+#include <qstring.h>
+#include <qdir.h>
+
+#include "libchmfile.h"
+#include "libchmurlfactory.h"
+
+#include "kchmconfig.h"
+#include "kchmviewwindow.h"
+#include "kchmmainwindow.h"
+#include "kchmviewwindowmgr.h"
+#include "kchmnavtoolbar.h"
+
+
+KCHMViewWindow::KCHMViewWindow( QTabWidget * parent )
+{
+ invalidate();
+ m_contextMenu = 0;
+ m_contextMenuLink = 0;
+ m_historyMaxSize = 25;
+
+ m_parentTabWidget = parent;
+}
+
+KCHMViewWindow::~KCHMViewWindow()
+{
+}
+
+void KCHMViewWindow::invalidate( )
+{
+ m_base_url = "/";
+ m_openedPage = QString::null;
+ m_newTabLinkKeeper = QString::null;
+
+ m_historyCurrentPos = 0;
+ m_history.clear();
+
+ updateNavigationToolbar();
+}
+
+
+
+QString KCHMViewWindow::makeURLabsolute ( const QString & url, bool set_as_base )
+{
+ QString p1, p2, newurl = url;
+
+ if ( !LCHMUrlFactory::isRemoteURL (url, p1)
+ && !LCHMUrlFactory::isJavascriptURL (url)
+ && !LCHMUrlFactory::isNewChmURL (url, p1, p2) )
+ {
+ newurl = QDir::cleanDirPath (url);
+
+ // Normalize url, so it becomes absolute
+ if ( newurl[0] != '/' )
+ newurl = m_base_url + "/" + newurl;
+
+ newurl = QDir::cleanDirPath (newurl);
+
+ if ( set_as_base )
+ {
+ m_base_url = newurl;
+
+ // and set up new baseurl
+ int i = newurl.findRev('/');
+ if ( i != -1 )
+ m_base_url = QDir::cleanDirPath (newurl.left (i + 1));
+ }
+ }
+
+//qDebug ("KCHMViewWindow::makeURLabsolute (%s) -> (%s)", url.ascii(), newurl.ascii());
+ return newurl;
+}
+
+bool KCHMViewWindow::openUrl ( const QString& origurl )
+{
+ QString chmfile, page, newurl = origurl;
+
+ if ( !origurl )
+ return true;
+
+ // URL could be a complete ms-its link. The file should be already loaded (for QTextBrowser),
+ // or will be loaded (for kio slave). We care only about the path component.
+ if ( LCHMUrlFactory::isNewChmURL( newurl, chmfile, page ) )
+ {
+ // If a new chm file is opened here, and we do not use KCHMLPart, we better abort
+ if ( chmfile != ::mainWindow->getOpenedFileName() && appConfig.m_kdeUseQTextBrowser )
+ qFatal("KCHMViewWindow::openUrl(): opened new chm file %s while current is %s",
+ chmfile.ascii(), ::mainWindow->getOpenedFileName().ascii() );
+
+ // It is OK to have a new file in chm for KHTMLPart
+ newurl = page;
+ }
+
+ makeURLabsolute (newurl);
+ handleStartPageAsImage( newurl );
+
+ if ( openPage (newurl) )
+ {
+ m_newTabLinkKeeper = QString::null;
+ m_openedPage = newurl;
+
+ mainWindow->viewWindowMgr()->setTabName( this );
+ return true;
+ }
+
+ return false;
+}
+
+void KCHMViewWindow::handleStartPageAsImage( QString & link )
+{
+ // Handle pics
+ if ( link.endsWith( ".jpg", false )
+ || link.endsWith( ".jpeg", false )
+ || link.endsWith( ".gif", false )
+ || link.endsWith( ".png", false )
+ || link.endsWith( ".bmp", false ) )
+ link += LCHMUrlFactory::getInternalUriExtension();
+}
+
+
+KQPopupMenu * KCHMViewWindow::createStandardContextMenu( QWidget * parent )
+{
+ KQPopupMenu * contextMenu = new KQPopupMenu( parent );
+
+ contextMenu->insertItem ( "&Copy", ::mainWindow, SLOT(slotBrowserCopy()) );
+ contextMenu->insertItem ( "&Select all", ::mainWindow, SLOT(slotBrowserSelectAll()) );
+
+ return contextMenu;
+}
+
+
+KQPopupMenu * KCHMViewWindow::getContextMenu( const QString & link, QWidget * parent )
+{
+ if ( link.isNull() )
+ {
+ // standard context menu
+ if ( !m_contextMenu )
+ m_contextMenu = createStandardContextMenu( parent );
+
+ return m_contextMenu;
+ }
+ else
+ {
+ // Open in New Tab context menu
+ // standard context menu
+ if ( !m_contextMenuLink )
+ {
+ m_contextMenuLink = createStandardContextMenu( parent );
+ m_contextMenuLink->insertSeparator();
+
+ m_contextMenuLink->insertItem ( "&Open this link in a new tab", ::mainWindow, SLOT(slotOpenPageInNewTab()), QKeySequence("Shift+Enter") );
+
+ m_contextMenuLink->insertItem ( "&Open this link in a new background tab", ::mainWindow, SLOT(slotOpenPageInNewBackgroundTab()), QKeySequence("Ctrl+Enter") );
+ }
+
+ setTabKeeper( link );
+ return m_contextMenuLink;
+ }
+}
+
+QString KCHMViewWindow::getTitle() const
+{
+ QString title = ::mainWindow->chmFile()->getTopicByUrl( m_openedPage );
+
+ if ( title.isEmpty() )
+ title = m_openedPage;
+
+ return title;
+}
+
+
+void KCHMViewWindow::navigateForward()
+{
+ if ( m_historyCurrentPos < m_history.size() )
+ {
+ m_historyCurrentPos++;
+ ::mainWindow->openPage( m_history[m_historyCurrentPos].getUrl() );
+ setScrollbarPosition( m_history[m_historyCurrentPos].getScrollPosition() );
+
+ // By default navigation starts with empty array, and a new entry is added when
+ // you change the current page (or it may not be added). So to have the whole system
+ // worked, the m_historyCurrentPos should never be m_history.size() - 1, it should be
+ // either greater or lesser.
+ //
+ // This is a dirty hack - but the whole navigation system now looks to me like
+ // it was written by some drunk monkey - which is probably not far from The Real Truth.
+ // Shame on me - Tim.
+ if ( m_historyCurrentPos == (m_history.size() - 1) )
+ m_historyCurrentPos++;
+ }
+
+ updateNavigationToolbar();
+}
+
+void KCHMViewWindow::navigateBack( )
+{
+ if ( m_historyCurrentPos > 0 )
+ {
+ // If we're on top of list, and pressing Back, the last page is still
+ // not in list - so add it, if it is not still here
+ if ( m_historyCurrentPos == m_history.size() )
+ {
+ if ( m_history[m_historyCurrentPos-1].getUrl() != m_openedPage )
+ m_history.push_back( KCHMUrlHistory( m_openedPage, getScrollbarPosition() ) );
+ else
+ {
+ // part 2 of the navigation hack - see navigateForward() comment
+ m_history[m_historyCurrentPos-1].setScrollPosition( getScrollbarPosition() );
+ m_historyCurrentPos--;
+ }
+ }
+
+ m_historyCurrentPos--;
+
+ ::mainWindow->openPage( m_history[m_historyCurrentPos].getUrl() );
+ setScrollbarPosition( m_history[m_historyCurrentPos].getScrollPosition() );
+ }
+
+ updateNavigationToolbar();
+}
+
+void KCHMViewWindow::navigateHome( )
+{
+ ::mainWindow->openPage( ::mainWindow->chmFile()->homeUrl() );
+}
+
+void KCHMViewWindow::addNavigationHistory( const QString & url, int scrollpos )
+{
+ // shred the 'forward' history
+ if ( m_historyCurrentPos < m_history.size() )
+ m_history.erase( m_history.at( m_historyCurrentPos ), m_history.end());
+
+ // do not grow the history if already max size
+ if ( m_history.size() >= m_historyMaxSize )
+ m_history.pop_front();
+
+ m_history.push_back( KCHMUrlHistory( url, scrollpos ) );
+ m_historyCurrentPos = m_history.size();
+
+ updateNavigationToolbar();
+}
+
+void KCHMViewWindow::updateNavigationToolbar( )
+{
+ // Dump navigation for debugging
+#if 0
+ qDebug("\nNavigation dump (%d entries, current pos %d)", m_history.size(), m_historyCurrentPos );
+ for ( unsigned int i = 0; i < m_history.size(); i++ )
+ qDebug("[%02d]: %s [%d]", i, m_history[i].getUrl().ascii(), m_history[i].getScrollPosition());
+#endif
+
+ if ( mainWindow )
+ {
+ mainWindow->navigationToolbar()->updateIconStatus(
+ m_historyCurrentPos > 0,
+ m_historyCurrentPos < (m_history.size() - 1) );
+ }
+}
+
+KQPopupMenu * KCHMViewWindow::createListItemContextMenu( QWidget * w )
+{
+ KQPopupMenu * contextMenu = new KQPopupMenu( w );
+
+ contextMenu->insertItem ( "&Open this link in a new tab",
+ ::mainWindow,
+ SLOT( slotOpenPageInNewTab() ),
+ QKeySequence( "Shift+Enter" ) );
+
+ contextMenu->insertItem ( "&Open this link in a new background tab",
+ ::mainWindow,
+ SLOT( slotOpenPageInNewBackgroundTab() ),
+ QKeySequence( "Ctrl+Enter" ) );
+
+ return contextMenu;
+}
+
+void KCHMViewWindow::setTabKeeper( const QString & link )
+{
+ // If we clicked on relative link, make sure we convert it to absolute right now,
+ // because later we will not have access to this view window variables
+ m_newTabLinkKeeper = link;
+ if ( m_newTabLinkKeeper[0] == '#' && !m_openedPage.isEmpty() )
+ {
+ // Clean up opened page URL
+ int pos = m_openedPage.find ('#');
+ QString fixedpath = pos == -1 ? m_openedPage : m_openedPage.left (pos);
+ m_newTabLinkKeeper = fixedpath + m_newTabLinkKeeper;
+ }
+
+ m_newTabLinkKeeper = makeURLabsolute( m_newTabLinkKeeper, false );
+}
diff --git a/src/kchmviewwindow.h b/src/kchmviewwindow.h
new file mode 100644
index 0000000..a114eac
--- /dev/null
+++ b/src/kchmviewwindow.h
@@ -0,0 +1,156 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMVIEWWINDOW_H
+#define KCHMVIEWWINDOW_H
+
+#include "forwarddeclarations.h"
+#include "kde-qt.h"
+
+/**
+@author Georgy Yunaev
+*/
+class KCHMViewWindow
+{
+public:
+ KCHMViewWindow ( QTabWidget * parent );
+ virtual ~KCHMViewWindow();
+
+ //! Open a page from current chm archive
+ bool openUrl (const QString& url );
+
+ QString getBaseUrl() const { return m_base_url; }
+ QString getOpenedPage() const { return m_openedPage; }
+ QString getNewTabLink() const { return m_newTabLinkKeeper; }
+ QString makeURLabsolute ( const QString &url, bool set_as_base = true );
+
+public:
+ // virtual members, which should be implemented by viewers
+ //! Invalidate current view, doing all the cleanups etc.
+ virtual void invalidate();
+
+ //! Popups the print dialog, and prints the current page on the printer.
+ virtual bool printCurrentPage() = 0;
+
+ //! Continues the find-in-page search forward or backward
+ virtual void searchWord( const QString & word, bool forward = true, bool casesensitive = false ) = 0;
+
+ //! Return current ZoomFactor.
+ virtual int getZoomFactor() const = 0;
+
+ //! Sets ZoomFactor. The value returned by getZoomFactor(), given to this function, should give the same result.
+ virtual void setZoomFactor (int zoom) = 0;
+
+ //! Relatively changes ZoomFactor. Most common values are -1 and 1.
+ virtual void addZoomFactor (int value) = 0;
+
+ virtual QObject * getQObject() = 0;
+ virtual QWidget * getQWidget() = 0;
+
+ /*!
+ * Return current scrollbar position in view window. Saved on program exit.
+ * There is no restriction on returned value, except that giving this value to
+ * setScrollbarPosition() should move the scrollbar in the same position.
+ */
+ virtual int getScrollbarPosition() = 0;
+
+ //! Sets the scrollbar position.
+ virtual void setScrollbarPosition(int pos) = 0;
+
+ //! Select the content of the whole page
+ virtual void clipSelectAll() = 0;
+
+ //! Copies the selected content to the clipboard
+ virtual void clipCopy() = 0;
+
+ //! Returns the window title
+ virtual QString getTitle() const;
+
+ //! Navigation stuff
+ virtual void navigateBack();
+ virtual void navigateHome();
+ virtual void navigateForward();
+
+ //! Navigation auxiliary stuff
+ virtual void setHistoryMaxSize (unsigned int size) { m_historyMaxSize = size; }
+ virtual void addNavigationHistory( const QString & url, int scrollpos );
+ virtual void updateNavigationToolbar();
+
+ /*!
+ * Used by contents window (and probably by other windows in future) to show
+ * context menu in listviews. Put here to futher reuse code in index and search windows.
+ */
+ KQPopupMenu * createListItemContextMenu ( QWidget * w );
+ void setTabKeeper ( const QString& link );
+
+
+protected: /* signals */
+ /*!
+ * Emitted when the user clicked on the link, before the page changed.
+ * If linkClicked() return false, the current page should NOT change.
+ * Otherwise it should be changed to the new link value.
+ */
+ virtual void signalLinkClicked ( const QString & newlink, bool& follow_link ) = 0;
+
+protected:
+ virtual bool openPage ( const QString& url ) = 0;
+ virtual void handleStartPageAsImage( QString& link );
+
+ KQPopupMenu * getContextMenu( const QString& link, QWidget * parent );
+ KQPopupMenu * createStandardContextMenu( QWidget * parent );
+
+ //! History
+ class KCHMUrlHistory
+ {
+ public:
+ KCHMUrlHistory() { scrollbarpos = 0; }
+ KCHMUrlHistory( const QString& _url, int _scrollbarpos )
+ : url(_url), scrollbarpos(_scrollbarpos) {};
+
+ const QString& getUrl() const { return url; }
+ int getScrollPosition() const { return scrollbarpos; }
+ void setScrollPosition( int pos ) { scrollbarpos = pos; }
+
+ private:
+ QString url;
+ int scrollbarpos;
+ };
+
+ unsigned int m_historyMaxSize;
+ unsigned int m_historyCurrentPos;
+
+ QValueList<KCHMUrlHistory> m_history;
+
+ KQPopupMenu * m_contextMenu;
+ KQPopupMenu * m_contextMenuLink;
+
+ // This member keeps a "open new tab" link between getContextMenu() call and appropriate
+ // slot call
+ QString m_newTabLinkKeeper;
+
+ QString m_openedPage;
+ QString m_lastOpenedPage;
+ QString m_base_url;
+
+ QTabWidget * m_parentTabWidget;
+};
+
+#endif
diff --git a/src/kchmviewwindow_qtextbrowser.cpp b/src/kchmviewwindow_qtextbrowser.cpp
new file mode 100644
index 0000000..1ab7bf6
--- /dev/null
+++ b/src/kchmviewwindow_qtextbrowser.cpp
@@ -0,0 +1,270 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qprinter.h>
+#include <qpainter.h>
+#include <qsimplerichtext.h>
+#include <qpaintdevicemetrics.h>
+
+#include "kde-qt.h"
+#include "kchmmainwindow.h"
+#include "kchmviewwindow_qtextbrowser.h"
+
+/*
+ * If defined, all the data viewed is kept in source factory. It increases the response time
+ * when a user opens the page he has already seen, in cost of everything which has been opened
+ * is stored in memory, increasing memory usage.
+ *
+ * If not defined, on any page change the source factory cleans up, saving the memory, but
+ * increasing the page loading time in case the page has the same images, or the page is opened
+ * second time.
+ */
+#define KEEP_ALL_OPENED_DATA_IN_SOURCE_FACTORY
+
+KCHMViewWindow_QTextBrowser::KCHMViewWindow_QTextBrowser( QTabWidget * parent )
+ : QTextBrowser ( parent ), KCHMViewWindow ( parent )
+{
+ m_zoomfactor = 0;
+ m_sourcefactory = 0;
+ invalidate();
+
+ setTextFormat ( Qt::RichText );
+ connect( this, SIGNAL( linkClicked (const QString &) ), this, SLOT( slotLinkClicked(const QString &) ) );
+}
+
+
+KCHMViewWindow_QTextBrowser::~KCHMViewWindow_QTextBrowser()
+{
+ delete m_sourcefactory;
+}
+
+bool KCHMViewWindow_QTextBrowser::openPage (const QString& url)
+{
+ // If we're using a memory saving scheme, we destroy MimeSourceFactory (including all the stored data)
+ // when opening a new page. It saves some memory, but spends more time while looking for already loaded
+ // images and HTML pages
+#if !defined (KEEP_ALL_OPENED_DATA_IN_SOURCE_FACTORY)
+ delete m_sourcefactory;
+ m_sourcefactory = new KCHMSourceFactory;
+ setMimeSourceFactory (m_sourcefactory);
+#endif
+
+ setSource (url);
+ return true;
+}
+
+void KCHMViewWindow_QTextBrowser::setSource ( const QString & name )
+{
+ if ( m_allowSourceChange )
+ {
+ // Do URI decoding, qtextbrowser does stupid job.
+ QString fixedname = decodeUrl( name );
+ QTextBrowser::setSource (fixedname);
+ }
+ else
+ m_allowSourceChange = true;
+}
+
+void KCHMViewWindow_QTextBrowser::setZoomFactor( int zoom )
+{
+ m_zoomfactor = zoom;
+
+ if ( zoom < 0 )
+ QTextBrowser::zoomOut( -zoom );
+ else if ( zoom > 0 )
+ QTextBrowser::zoomIn( zoom);
+}
+
+void KCHMViewWindow_QTextBrowser::invalidate( )
+{
+ delete m_sourcefactory;
+ m_sourcefactory = new KCHMSourceFactory (this);
+ setMimeSourceFactory (m_sourcefactory);
+ m_zoomfactor = 0;
+ m_allowSourceChange = true;
+ m_searchLastIndex = 0;
+ m_searchLastParagraph = 0;
+ m_searchText = QString::null;
+ reload();
+
+ KCHMViewWindow::invalidate( );
+}
+
+int KCHMViewWindow_QTextBrowser::getScrollbarPosition( )
+{
+ return contentsY ();
+}
+
+void KCHMViewWindow_QTextBrowser::setScrollbarPosition( int pos )
+{
+ setContentsPos (0, pos);
+}
+
+void KCHMViewWindow_QTextBrowser::addZoomFactor( int value )
+{
+ setZoomFactor( value);
+}
+
+void KCHMViewWindow_QTextBrowser::slotLinkClicked( const QString & newlink )
+{
+ emit signalLinkClicked (newlink, m_allowSourceChange);
+}
+
+
+bool KCHMViewWindow_QTextBrowser::printCurrentPage( )
+{
+#if !defined (QT_NO_PRINTER)
+ QPrinter printer( QPrinter::HighResolution );
+ printer.setFullPage(TRUE);
+
+ if ( printer.setup( this ) )
+ {
+ QPainter p( &printer );
+
+ if( !p.isActive() ) // starting printing failed
+ return false;
+
+ QPaintDeviceMetrics metrics(p.device());
+ int dpiy = metrics.logicalDpiY();
+ int margin = (int) ( (2/2.54)*dpiy ); // 2 cm margins
+ QRect body( margin, margin, metrics.width() - 2*margin, metrics.height() - 2*margin );
+ QSimpleRichText richText( text(),
+ QFont(),
+ context(),
+ styleSheet(),
+ mimeSourceFactory(),
+ body.height() );
+ richText.setWidth( &p, body.width() );
+ QRect view( body );
+
+ int page = 1;
+
+ do
+ {
+ richText.draw( &p, body.left(), body.top(), view, colorGroup() );
+ view.moveBy( 0, body.height() );
+ p.translate( 0 , -body.height() );
+ p.drawText( view.right() - p.fontMetrics().width( QString::number(page) ),
+ view.bottom() + p.fontMetrics().ascent() + 5, QString::number(page) );
+
+ if ( view.top() >= richText.height() )
+ break;
+
+ QString msg = i18n( "Printing (page %1)...") .arg(page);
+ ::mainWindow->showInStatusBar( msg );
+
+ printer.newPage();
+ page++;
+ }
+ while (TRUE);
+
+ ::mainWindow->showInStatusBar( i18n( "Printing completed") );
+ return true;
+ }
+
+ ::mainWindow->showInStatusBar( i18n( "Printing aborted") );
+ return false;
+
+#else /* QT_NO_PRINTER */
+
+ QMessageBox::warning( this,
+ i18n( "%1 - could not print") . arg(APP_NAME),
+ i18n( "Could not print.\nYour Qt library has been compiled without printing support");
+ return false;
+
+#endif /* QT_NO_PRINTER */
+}
+
+
+void KCHMViewWindow_QTextBrowser::searchWord( const QString & word, bool forward, bool )
+{
+ if ( m_searchText == word )
+ {
+ if ( forward && (m_searchLastIndex || m_searchLastParagraph) )
+ m_searchLastIndex += m_searchText.length();
+ }
+ else
+ {
+ m_searchLastParagraph = m_searchLastIndex = 0;
+ m_searchText = word;
+ }
+
+ if ( find (m_searchText, false, false, forward, &m_searchLastParagraph, &m_searchLastIndex) )
+ ::mainWindow->showInStatusBar( i18n( "Search failed") );
+}
+
+void KCHMViewWindow_QTextBrowser::clipSelectAll( )
+{
+ selectAll (TRUE);
+}
+
+void KCHMViewWindow_QTextBrowser::clipCopy( )
+{
+ copy ();
+}
+
+
+// Shamelessly stolen from Qt
+QString KCHMViewWindow_QTextBrowser::decodeUrl( const QString &input )
+{
+ QString temp;
+
+ int i = 0;
+ int len = input.length();
+ int a, b;
+ QChar c;
+ while (i < len)
+ {
+ c = input[i];
+ if (c == '%' && i + 2 < len)
+ {
+ a = input[++i];
+ b = input[++i];
+
+ if (a >= '0' && a <= '9') a -= '0';
+ else if (a >= 'a' && a <= 'f') a = a - 'a' + 10;
+ else if (a >= 'A' && a <= 'F') a = a - 'A' + 10;
+
+ if (b >= '0' && b <= '9') b -= '0';
+ else if (b >= 'a' && b <= 'f') b = b - 'a' + 10;
+ else if (b >= 'A' && b <= 'F') b = b - 'A' + 10;
+
+ temp.append( (QChar)((a << 4) | b ) );
+ }
+ else
+ {
+ temp.append( c );
+ }
+
+ ++i;
+ }
+
+ return temp;
+}
+
+QPopupMenu * KCHMViewWindow_QTextBrowser::createPopupMenu( const QPoint & pos )
+{
+ KQPopupMenu * menu = getContextMenu( anchorAt( pos ), this );
+ menu->exec( mapToGlobal( contentsToViewport( pos ) ) );
+ return 0;
+}
+
+#include "kchmviewwindow_qtextbrowser.moc"
diff --git a/src/kchmviewwindow_qtextbrowser.h b/src/kchmviewwindow_qtextbrowser.h
new file mode 100644
index 0000000..662bd57
--- /dev/null
+++ b/src/kchmviewwindow_qtextbrowser.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMVIEWWINDOW_QTEXTBROWSER_H
+#define KCHMVIEWWINDOW_QTEXTBROWSER_H
+
+#include "kde-qt.h"
+
+#include "kchmviewwindow.h"
+#include "kchmsourcefactory.h"
+
+/**
+@author Georgy Yunaev
+*/
+class KCHMViewWindow_QTextBrowser : public QTextBrowser, public KCHMViewWindow
+{
+Q_OBJECT
+public:
+ KCHMViewWindow_QTextBrowser( QTabWidget * parent );
+ ~KCHMViewWindow_QTextBrowser();
+
+ //! Open a page from current chm archive
+ virtual bool openPage (const QString& url);
+
+ //! Invalidate current view, doing all the cleanups etc.
+ virtual void invalidate();
+
+ //! Return current ZoomFactor.
+ virtual int getZoomFactor() const { return m_zoomfactor; }
+
+ //! Sets ZoomFactor. The value returned by getZoomFactor(), given to this function, should give the same result.
+ virtual void setZoomFactor (int zoom);
+
+ //! Relatively changes ZoomFactor. Most common values are -1 and 1.
+ virtual void addZoomFactor (int value);
+
+ //! Popups the print dialog, and prints the current page on the printer.
+ virtual bool printCurrentPage();
+
+ //! Initiates the find-in-page search, if succeed, cursor moved to the first entry
+ virtual void searchWord( const QString & word, bool forward = true, bool casesensitive = false );
+
+ //! Select the content of the whole page
+ virtual void clipSelectAll();
+
+ //! Copies the selected content to the clipboard
+ virtual void clipCopy();
+
+ /*!
+ * Return current scrollbar position in view window. Saved on program exit.
+ * There is no restriction on returned value, except that giving this value to
+ * setScrollbarPosition() should move the scrollbar in the same position.
+ */
+ virtual int getScrollbarPosition();
+
+ //! Sets the scrollbar position.
+ virtual void setScrollbarPosition(int pos);
+
+ virtual QObject * getQObject() { return this; }
+ virtual QWidget * getQWidget() { return this; }
+
+ static QString decodeUrl( const QString &url );
+
+signals:
+ /*!
+ * Emitted when the user clicked on the link, before the page changed.
+ * If signalLinkClicked() sets follow_link to false, the current page should NOT change.
+ * Otherwise it should be changed to the new link value.
+ */
+ void signalLinkClicked ( const QString & newlink, bool& follow_link );
+
+private slots:
+ virtual void slotLinkClicked (const QString & newlink);
+
+private:
+ QPopupMenu * createPopupMenu ( const QPoint & pos );
+ void setSource ( const QString & name );
+
+ int m_zoomfactor;
+ bool m_allowSourceChange;
+ int m_searchLastIndex;
+ int m_searchLastParagraph;
+ QString m_searchText;
+
+ KCHMSourceFactory * m_sourcefactory;
+};
+
+
+#endif /* KCHMVIEWWINDOW_QTEXTBROWSER_H */
diff --git a/src/kchmviewwindowmgr.cpp b/src/kchmviewwindowmgr.cpp
new file mode 100644
index 0000000..dd6a984
--- /dev/null
+++ b/src/kchmviewwindowmgr.cpp
@@ -0,0 +1,344 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qaccel.h>
+
+#include "kchmconfig.h"
+#include "kchmmainwindow.h"
+#include "kchmviewwindow.h"
+#include "kchmviewwindowmgr.h"
+#include "iconstorage.h"
+
+#include "kchmviewwindow_qtextbrowser.h"
+
+#if defined (USE_KDE)
+ #include "kde/kchmviewwindow_khtmlpart.h"
+#endif
+
+
+KCHMViewWindowMgr::KCHMViewWindowMgr( QWidget *parent )
+ : QTabWidget( parent ) //QTabWidget
+{
+ m_MenuWindow = 0;
+
+ // on current tab changed
+ connect( this, SIGNAL( currentChanged(QWidget *) ), this, SLOT( onTabChanged(QWidget *) ) );
+
+ // Create an iconset for the button
+ QIconSet iset( *gIconStorage.getCloseWindowIcon() );
+
+ // Create a pushbutton
+ m_closeButton = new QPushButton( iset, QString::null, this );
+ m_closeButton->setFlat( true );
+ m_closeButton->setEnabled( false );
+ connect( m_closeButton, SIGNAL( clicked() ), this, SLOT( closeCurrentWindow() ) );
+
+ setCornerWidget( m_closeButton, TopRight);
+}
+
+KCHMViewWindowMgr::~KCHMViewWindowMgr( )
+{
+}
+
+void KCHMViewWindowMgr::createMenu( KCHMMainWindow * parent )
+{
+ // Create the approptiate menu entries in 'View' main menu
+ m_MenuWindow = new KQPopupMenu( parent );
+ parent->menuBar()->insertItem( i18n( "&Window"), m_MenuWindow );
+
+ m_menuIdClose = m_MenuWindow->insertItem( i18n( "&Close"), this, SLOT( closeCurrentWindow()), CTRL+Key_W );
+ m_MenuWindow->insertSeparator();
+
+ //connect( m_MenuWindow, SIGNAL( activated(int) ), this, SLOT ( onCloseWindow(int) ));
+ connect( m_MenuWindow, SIGNAL( activated(int) ), this, SLOT ( onActiveWindow(int) ));
+}
+
+void KCHMViewWindowMgr::invalidate()
+{
+ deleteAllWindows();
+ addNewTab( true );
+}
+
+
+KCHMViewWindow * KCHMViewWindowMgr::current()
+{
+ QWidget * w = currentPage();
+ WindowsIterator it;
+
+ if ( !w || (it = m_Windows.find( w )) == m_Windows.end() )
+ qFatal( "KCHMViewWindowMgr::current called without any windows!" );
+
+ return it.data().window;
+}
+
+KCHMViewWindow * KCHMViewWindowMgr::addNewTab( bool set_active )
+{
+ KCHMViewWindow * viewvnd;
+
+#if defined (USE_KDE)
+ if ( !appConfig.m_kdeUseQTextBrowser )
+ viewvnd = new KCHMViewWindow_KHTMLPart( this );
+ else
+#endif
+ viewvnd = new KCHMViewWindow_QTextBrowser( this );
+
+ QWidget * widget = viewvnd->getQWidget();
+ m_Windows[widget].window = viewvnd;
+ m_Windows[widget].menuitem = 0;
+ m_Windows[widget].widget = widget;
+
+ addTab( widget, "" );
+
+ Q_ASSERT( m_Windows.size() == (unsigned int) count() );
+
+ // Set active if it is the first tab
+ if ( set_active || m_Windows.size() == 1 )
+ showPage( widget );
+
+ // Handle clicking on link in browser window
+ connect( viewvnd->getQObject(), SIGNAL( signalLinkClicked (const QString &, bool &) ), ::mainWindow, SLOT( slotLinkClicked(const QString &, bool &) ) );
+
+ return viewvnd;
+}
+
+void KCHMViewWindowMgr::deleteAllWindows( )
+{
+ // No it++ - we removing the window by every closeWindow call
+ while ( m_Windows.begin() != m_Windows.end() )
+ closeWindow( m_Windows.begin().data() );
+}
+
+void KCHMViewWindowMgr::setTabName( KCHMViewWindow * window )
+{
+ WindowsIterator it = m_Windows.find( window->getQWidget() );
+
+ if ( it == m_Windows.end() )
+ qFatal( "KCHMViewWindowMgr::setTabName called with unknown window!" );
+
+ QString title = window->getTitle();
+
+ // Trim too long string
+ if ( title.length() > 25 )
+ title = title.left( 22 ) + "...";
+
+ setTabLabel( window->getQWidget(), title );
+
+ if ( it.data().menuitem == 0 )
+ {
+ // find the empty menuid
+ int menuid;
+
+ if ( !m_idSlot.empty() )
+ {
+ menuid = *m_idSlot.begin();
+ m_idSlot.erase( m_idSlot.begin() );
+ }
+ else
+ menuid = m_Windows.size();
+
+ QString menutitle = "&" + QString::number(menuid) + " " + title;
+ it.data().menuitem = menuid;
+ m_MenuWindow->insertItem(menutitle, menuid);
+ updateTabAccel();
+ }
+ else
+ {
+ QString menutitle = "&" + QString::number(it.data().menuitem) + " " + title;
+ m_MenuWindow->changeItem( it.data().menuitem, menutitle );
+ }
+
+ updateCloseButtons();
+}
+
+void KCHMViewWindowMgr::closeCurrentWindow( )
+{
+ // Do not allow to close the last window
+ if ( m_Windows.size() == 1 )
+ return;
+
+ QWidget * w = currentPage();
+ WindowsIterator it;
+
+ if ( !w || (it = m_Windows.find( w )) == m_Windows.end() )
+ qFatal( "KCHMViewWindowMgr::closeCurrentWindow called without any windows!" );
+
+ closeWindow( it.data() );
+}
+
+void KCHMViewWindowMgr::closeWindow( const tab_window_t & tab )
+{
+ WindowsIterator it = m_Windows.find( tab.widget );
+
+ if ( it == m_Windows.end() )
+ qFatal( "KCHMViewWindowMgr::closeWindow called with unknown widget!" );
+
+ if ( tab.menuitem != 0 )
+ {
+ m_MenuWindow->removeItem( tab.menuitem );
+ m_idSlot.push_back( tab.menuitem );
+ }
+
+ removePage( tab.widget );
+ delete tab.window;
+
+ m_Windows.remove( it );
+ updateCloseButtons();
+ updateTabAccel();
+}
+
+void KCHMViewWindowMgr::onCloseWindow( int id )
+{
+ for ( WindowsIterator it = m_Windows.begin(); it != m_Windows.end(); it++ )
+ {
+ if ( it.data().menuitem != id )
+ continue;
+
+ closeWindow( it.data() );
+ break;
+ }
+}
+
+
+void KCHMViewWindowMgr::onActiveWindow(int id)
+{
+ for (WindowsIterator it = m_Windows.begin(); it != m_Windows.end(); ++it)
+ {
+ if ( it.data().menuitem != id )
+ continue;
+
+ QWidget *widget = it.data().widget;
+ showPage(widget);
+ break;
+ }
+}
+
+
+void KCHMViewWindowMgr::restoreSettings( const KCHMSettings::viewindow_saved_settings_t & settings )
+{
+ // Destroy pre-created tab
+ closeWindow( m_Windows.begin().data() );
+
+ for ( unsigned int i = 0; i < settings.size(); i++ )
+ {
+ KCHMViewWindow * window = addNewTab( false );
+ window->openUrl( settings[i].url ); // will call setTabName()
+ window->setScrollbarPosition( settings[i].scroll_y );
+ window->setZoomFactor( settings[i].zoom );
+ }
+}
+
+
+void KCHMViewWindowMgr::saveSettings( KCHMSettings::viewindow_saved_settings_t & settings )
+{
+ settings.clear();
+
+ for ( int i = 0; i < count(); i++ )
+ {
+ QWidget * p = page( i );
+ WindowsIterator it = m_Windows.find( p );
+
+ if ( it == m_Windows.end() )
+ qFatal( "KCHMViewWindowMgr::saveSettings: could not find widget!" );
+
+ settings.push_back(
+ KCHMSettings::SavedViewWindow(
+ it.data().window->getOpenedPage(),
+ it.data().window->getScrollbarPosition(),
+ it.data().window->getZoomFactor()) );
+ }
+}
+
+void KCHMViewWindowMgr::updateCloseButtons( )
+{
+ m_MenuWindow->setItemEnabled( m_menuIdClose, m_Windows.size() > 1 );
+ m_closeButton->setEnabled( m_Windows.size() > 1 );
+}
+
+void KCHMViewWindowMgr::onTabChanged( QWidget * newtab )
+{
+ WindowsIterator it = m_Windows.find( newtab );
+
+ if ( it == m_Windows.end() )
+ qFatal( "KCHMViewWindowMgr::onTabChanged called with unknown widget!" );
+
+ it.data().window->updateNavigationToolbar();
+ mainWindow->slotBrowserChanged( it.data().window );
+}
+
+
+void KCHMViewWindowMgr::updateTabAccel()
+{
+ WindowsIterator it;
+ for ( it = m_Windows.begin(); it != m_Windows.end(); ++it )
+ {
+ int menuid = it.data().menuitem;
+ int index = indexOf(it.data().widget);
+
+ if ( index <= 9 )
+ {
+ if ( index < 9 )
+ index++;
+ else
+ index = 0;
+
+ m_MenuWindow->setAccel(ALT + key(index), menuid);
+ }
+ }
+}
+
+QKeySequence KCHMViewWindowMgr::key(int i)
+{
+ switch (i)
+ {
+ case 0:
+ return Key_0;
+
+ case 1:
+ return Key_1;
+
+ case 2:
+ return Key_2;
+
+ case 3:
+ return Key_3;
+
+ case 4:
+ return Key_4;
+
+ case 5:
+ return Key_5;
+
+ case 6:
+ return Key_6;
+
+ case 7:
+ return Key_7;
+
+ case 8:
+ return Key_8;
+
+ default:
+ return Key_9;
+ }
+}
+
+
+#include "kchmviewwindowmgr.moc"
diff --git a/src/kchmviewwindowmgr.h b/src/kchmviewwindowmgr.h
new file mode 100644
index 0000000..2b07544
--- /dev/null
+++ b/src/kchmviewwindowmgr.h
@@ -0,0 +1,90 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef INCLUDE_KCHMVIEWWINDOWMGR_H
+#define INCLUDE_KCHMVIEWWINDOWMGR_H
+
+#include "kde-qt.h"
+#include "forwarddeclarations.h"
+#include "kchmsettings.h"
+
+#include <qvaluevector.h>
+
+class KCHMViewWindowMgr : public QTabWidget
+{
+ Q_OBJECT
+ public:
+ KCHMViewWindowMgr( QWidget *parent = 0 );
+ ~KCHMViewWindowMgr( );
+
+ // Returns a handle to a currently viewed window.
+ // Guaranteeed to return a valid handle, or aborts.
+ KCHMViewWindow * current();
+
+ // Adds a new tab, creating a new browser window
+ KCHMViewWindow * addNewTab( bool set_active );
+
+ // Sets the tab name and updates Windows menu
+ void setTabName( KCHMViewWindow* window );
+
+ void invalidate();
+
+ // Creates a Window menu
+ void createMenu( KCHMMainWindow * parent );
+
+ // Saves and restores current settings between sessions
+ void restoreSettings( const KCHMSettings::viewindow_saved_settings_t& settings );
+ void saveSettings( KCHMSettings::viewindow_saved_settings_t& settings );
+
+ public slots:
+ void closeCurrentWindow();
+
+ protected slots:
+ void onTabChanged( QWidget * newtab );
+ void onCloseWindow( int id );
+ void onActiveWindow( int id );
+ void updateCloseButtons();
+
+ private:
+ typedef struct
+ {
+ QWidget * widget;
+ KCHMViewWindow * window;
+ int menuitem;
+ } tab_window_t;
+
+ void closeWindow( const tab_window_t& tab );
+ void deleteAllWindows();
+ void updateTabAccel();
+ QKeySequence key(int);
+
+ QMap<QWidget*,tab_window_t> m_Windows;
+ typedef QMap<QWidget*,tab_window_t>::iterator WindowsIterator;
+
+ QValueList<int> m_idSlot;
+ typedef QValueList<int>::iterator IdIterator;
+
+ QPushButton * m_closeButton;
+ KQPopupMenu * m_MenuWindow;
+ int m_menuIdClose;
+};
+
+#endif /* INCLUDE_KCHMVIEWWINDOWMGR_H */
diff --git a/src/kde-qt.cpp b/src/kde-qt.cpp
new file mode 100644
index 0000000..6c3929f
--- /dev/null
+++ b/src/kde-qt.cpp
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kde-qt.h"
+
+#if defined (USE_KDE)
+KQListView::KQListView( QWidget * parent, const char * name, int )
+ : KListView (parent, name)
+#else
+KQListView::KQListView( QWidget * parent, const char * name, int f )
+ : QListView (parent, name, f)
+#endif
+{
+}
+
+#if defined (USE_KDE)
+KQProgressModalDialog::KQProgressModalDialog ( const QString & captionText, const QString & labelText, const QString & cancelButtonText, int totalSteps, QWidget * creator )
+ : KProgressDialog( creator, 0, captionText, labelText, true )
+{
+ setAllowCancel( true );
+ showCancelButton( true );
+ setAutoClose( true );
+ setButtonText( cancelButtonText );
+ setTotalSteps( totalSteps );
+ setMinimumDuration( 1 );
+}
+#else
+KQProgressModalDialog::KQProgressModalDialog ( const QString & captionText, const QString & labelText, const QString & cancelButtonText, int totalSteps, QWidget * creator )
+ : QProgressDialog( labelText, cancelButtonText, totalSteps, creator, 0, false )
+{
+ setCaption( captionText );
+ setMinimumDuration( 1 );
+}
+#endif
diff --git a/src/kde-qt.h b/src/kde-qt.h
new file mode 100644
index 0000000..58ee4a1
--- /dev/null
+++ b/src/kde-qt.h
@@ -0,0 +1,148 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KDE_QT_H
+#define KDE_QT_H
+
+#include "config.h"
+
+#if defined (USE_KDE)
+
+ #define KQ_CLASSNAME(name) K##name
+ #define KQ_DECLARECLASS(name) class KQ##name : public K##name
+
+ #include <kapplication.h>
+ #include <kmainwindow.h>
+ #include <kstatusbar.h>
+ #include <kmenubar.h>
+ #include <kcmdlineargs.h>
+ #include <klocale.h>
+ #include <klistview.h>
+ #include <kfiledialog.h>
+ #include <khtml_part.h>
+ #include <ktabwidget.h>
+ #include <kpopupmenu.h>
+ #include <kmessagebox.h>
+ #include <kprogress.h>
+ #include <krun.h>
+
+#else /* !USE_KDE */
+
+ #define KQ_CLASSNAME(name) Q##name
+
+ #include <qapplication.h>
+ #include <qmainwindow.h>
+ #include <qstring.h>
+ #include <qstatusbar.h>
+ #include <qlistview.h>
+ #include <qfiledialog.h>
+ #include <qmenubar.h>
+ #include <qtabwidget.h>
+ #include <qmessagebox.h>
+ #include <qprogressdialog.h>
+
+ #define i18n(A) tr(A)
+
+#endif /* USE_KDE */
+
+/* common non-wrapped UI classes */
+#include <qsplitter.h>
+#include <qtoolbutton.h>
+#include <qheader.h>
+#include <qtextbrowser.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+#include <qpushbutton.h>
+
+/* common utility classes */
+#include <qwhatsthis.h>
+#include <qstring.h>
+#include <qtextedit.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qmap.h>
+#include <qeventloop.h>
+
+class KQMainWindow : public KQ_CLASSNAME(MainWindow)
+{
+public:
+ KQMainWindow ( QWidget * parent, const char * name, WFlags f )
+ : KQ_CLASSNAME(MainWindow) (parent, name, f) {};
+};
+
+
+class KQListView : public KQ_CLASSNAME(ListView)
+{
+public:
+ KQListView(QWidget *parent = 0, const char *name = 0, int f = 0);
+};
+
+
+class KQProgressModalDialog : public KQ_CLASSNAME(ProgressDialog)
+{
+ public:
+ KQProgressModalDialog ( const QString & captionText, const QString & labelText, const QString & cancelButtonText, int totalSteps, QWidget * creator = 0 );
+
+ // Seems like people have fun making classes incompatible
+#if defined (USE_KDE)
+ void setTotalSteps( int totalSteps ) { progressBar ()->setTotalSteps( totalSteps ); }
+ void setProgress( int progress ) { progressBar ()->setProgress( progress ); }
+#else
+ bool wasCancelled() { return wasCanceled(); }
+#endif
+};
+
+class KQTabWidget : public KQ_CLASSNAME(TabWidget)
+{
+public:
+ KQTabWidget (QWidget *parent = 0, const char *name = 0, int f = 0)
+ : KQ_CLASSNAME(TabWidget) (parent, name, f) {};
+};
+
+class KQPopupMenu : public KQ_CLASSNAME(PopupMenu)
+{
+public:
+ KQPopupMenu (QWidget *parent = 0 )
+ : KQ_CLASSNAME(PopupMenu) (parent) {};
+};
+
+#include <qinputdialog.h>
+#include <qcheckbox.h>
+#include <qtextedit.h>
+#include <qradiobutton.h>
+#include <qspinbox.h>
+#include <qgroupbox.h>
+#include <qbuttongroup.h>
+#include <qtooltip.h>
+
+
+class KCHMShowWaitCursor
+{
+ public:
+ KCHMShowWaitCursor() { QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) ); }
+ ~KCHMShowWaitCursor() { QApplication::restoreOverrideCursor(); }
+};
+
+
+#endif /* KDE_QT_H */
diff --git a/src/kde/Makefile.am b/src/kde/Makefile.am
new file mode 100644
index 0000000..e095be6
--- /dev/null
+++ b/src/kde/Makefile.am
@@ -0,0 +1,8 @@
+lib_LIBRARIES=libkdeextra.a
+libkdeextra_a_SOURCES = kchmdcopiface.cpp kchmdcopiface.skel kchmviewwindow_khtmlpart.cpp
+noinst_HEADERS = kchmdcopiface.h kchmviewwindow_khtmlpart.h
+
+INCLUDES = $(QT_INCLUDES) $(CHM_INCLUDES) $(KDE_INCLUDES) $(LIBCHMFILE_INCLUDES)
+
+METASOURCES = AUTO
+KDE_OPTIONS = qtonly
diff --git a/src/kde/kchmdcopiface.cpp b/src/kde/kchmdcopiface.cpp
new file mode 100644
index 0000000..967380e
--- /dev/null
+++ b/src/kde/kchmdcopiface.cpp
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * Copyright (C) 2004-2005 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kchmdcopiface.h"
+#include "kchmdcopiface.moc"
+
+#include "kchmmainwindow.h"
+#include "kchmsearchwindow.h"
+
+
+KCHMDCOPIface::KCHMDCOPIface(QObject *parent, const char *name)
+ : QObject(parent, name), DCOPObject( "KCHMDCOPIface" )
+{
+}
+
+
+KCHMDCOPIface::~KCHMDCOPIface()
+{
+}
+
+
+void KCHMDCOPIface::loadHelpFile( const QString & filename, const QString & page2open )
+{
+ QStringList args;
+
+ args.push_back( filename );
+ args.push_back( page2open );
+
+ qApp->postEvent( ::mainWindow, new KCHMUserEvent( "loadAndOpen", args ) );
+}
+
+
+void KCHMDCOPIface::openPage( const QString & page2open )
+{
+ QStringList args;
+
+ args.push_back( page2open );
+ qApp->postEvent( ::mainWindow, new KCHMUserEvent( "openPage", args ) );
+}
+
+
+void KCHMDCOPIface::guiFindInIndex( const QString & word )
+{
+ QStringList args;
+
+ args.push_back( word );
+ qApp->postEvent( ::mainWindow, new KCHMUserEvent( "findInIndex", args ) );
+}
+
+
+void KCHMDCOPIface::guiSearchQuery( const QString & query )
+{
+ QStringList args;
+
+ args.push_back( query );
+ qApp->postEvent( ::mainWindow, new KCHMUserEvent( "searchQuery", args ) );
+}
+
+QStringList KCHMDCOPIface::searchQuery( const QString & query )
+{
+ QStringList results;
+
+ if ( ::mainWindow->searchWindow()->searchQuery( query, &results ) )
+ return results;
+ else
+ return QStringList();
+}
+
diff --git a/src/kde/kchmdcopiface.h b/src/kde/kchmdcopiface.h
new file mode 100644
index 0000000..c062fc8
--- /dev/null
+++ b/src/kde/kchmdcopiface.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * Copyright (C) 2004-2005 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMDCOPIFACE_H
+#define KCHMDCOPIFACE_H
+
+#include <qobject.h>
+#include <dcopobject.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+class KCHMDCOPIface : public QObject, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+
+ public:
+ KCHMDCOPIface( QObject *parent = 0, const char *name = 0 );
+ ~KCHMDCOPIface();
+
+ k_dcop:
+ //! Loads a CHM file \a filename , and opens the URL \a url. Use URL "/" to open default homepage
+ void loadHelpFile( const QString& filename, const QString& url );
+
+ //! Opens a specific \a url inside the loaded CHM file
+ void openPage( const QString& url );
+
+ //! Tries to find word in index, opening the index window and scrolling it there
+ void guiFindInIndex( const QString& word );
+
+ //! Executes a search in GUI. \a query contains the complete search query.
+ void guiSearchQuery( const QString& query );
+
+ //! Executes a search; GUI is not involved and user sees nothing.
+ //! \a query contains the complete search query.
+ //! Returns a list of URLs, or empty array if nothing os
+ QStringList searchQuery( const QString& query );
+};
+
+#endif
diff --git a/src/kde/kchmdcopiface_skel.cpp b/src/kde/kchmdcopiface_skel.cpp
new file mode 100644
index 0000000..130a60f
--- /dev/null
+++ b/src/kde/kchmdcopiface_skel.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** DCOP Skeleton generated by dcopidl2cpp from kchmdcopiface.kidl
+**
+** WARNING! All changes made in this file will be lost!
+**
+*****************************************************************************/
+
+#include "./kchmdcopiface.h"
+
+#include <kdatastream.h>
+
+
+static const char* const KCHMDCOPIface_ftable[6][3] = {
+ { "void", "loadHelpFile(QString,QString)", "loadHelpFile(QString filename,QString url)" },
+ { "void", "openPage(QString)", "openPage(QString url)" },
+ { "void", "guiFindInIndex(QString)", "guiFindInIndex(QString word)" },
+ { "void", "guiSearchQuery(QString)", "guiSearchQuery(QString query)" },
+ { "QStringList", "searchQuery(QString)", "searchQuery(QString query)" },
+ { 0, 0, 0 }
+};
+static const int KCHMDCOPIface_ftable_hiddens[5] = {
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+bool KCHMDCOPIface::process(const QCString &fun, const QByteArray &data, QCString& replyType, QByteArray &replyData)
+{
+ if ( fun == KCHMDCOPIface_ftable[0][1] ) { // void loadHelpFile(QString,QString)
+ QString arg0;
+ QString arg1;
+ QDataStream arg( data, IO_ReadOnly );
+ if (arg.atEnd()) return false;
+ arg >> arg0;
+ if (arg.atEnd()) return false;
+ arg >> arg1;
+ replyType = KCHMDCOPIface_ftable[0][0];
+ loadHelpFile(arg0, arg1 );
+ } else if ( fun == KCHMDCOPIface_ftable[1][1] ) { // void openPage(QString)
+ QString arg0;
+ QDataStream arg( data, IO_ReadOnly );
+ if (arg.atEnd()) return false;
+ arg >> arg0;
+ replyType = KCHMDCOPIface_ftable[1][0];
+ openPage(arg0 );
+ } else if ( fun == KCHMDCOPIface_ftable[2][1] ) { // void guiFindInIndex(QString)
+ QString arg0;
+ QDataStream arg( data, IO_ReadOnly );
+ if (arg.atEnd()) return false;
+ arg >> arg0;
+ replyType = KCHMDCOPIface_ftable[2][0];
+ guiFindInIndex(arg0 );
+ } else if ( fun == KCHMDCOPIface_ftable[3][1] ) { // void guiSearchQuery(QString)
+ QString arg0;
+ QDataStream arg( data, IO_ReadOnly );
+ if (arg.atEnd()) return false;
+ arg >> arg0;
+ replyType = KCHMDCOPIface_ftable[3][0];
+ guiSearchQuery(arg0 );
+ } else if ( fun == KCHMDCOPIface_ftable[4][1] ) { // QStringList searchQuery(QString)
+ QString arg0;
+ QDataStream arg( data, IO_ReadOnly );
+ if (arg.atEnd()) return false;
+ arg >> arg0;
+ replyType = KCHMDCOPIface_ftable[4][0];
+ QDataStream _replyStream( replyData, IO_WriteOnly );
+ _replyStream << searchQuery(arg0 );
+ } else {
+ return DCOPObject::process( fun, data, replyType, replyData );
+ }
+ return true;
+}
+
+QCStringList KCHMDCOPIface::interfaces()
+{
+ QCStringList ifaces = DCOPObject::interfaces();
+ ifaces += "KCHMDCOPIface";
+ return ifaces;
+}
+
+QCStringList KCHMDCOPIface::functions()
+{
+ QCStringList funcs = DCOPObject::functions();
+ for ( int i = 0; KCHMDCOPIface_ftable[i][2]; i++ ) {
+ if (KCHMDCOPIface_ftable_hiddens[i])
+ continue;
+ QCString func = KCHMDCOPIface_ftable[i][0];
+ func += ' ';
+ func += KCHMDCOPIface_ftable[i][2];
+ funcs << func;
+ }
+ return funcs;
+}
+
+
diff --git a/src/kde/kchmviewwindow_khtmlpart.cpp b/src/kde/kchmviewwindow_khtmlpart.cpp
new file mode 100644
index 0000000..e68e53d
--- /dev/null
+++ b/src/kde/kchmviewwindow_khtmlpart.cpp
@@ -0,0 +1,163 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <qclipboard.h>
+
+#include <khtmlview.h>
+#include <kfinddialog.h>
+
+#include "kde-qt.h"
+#include "kchmmainwindow.h"
+#include "kchmconfig.h"
+#include "kchmviewwindow_khtmlpart.h"
+
+#include "kchmviewwindow_khtmlpart.moc"
+
+
+QWidget * KCHMViewWindow_KHTMLPart::getQWidget()
+{
+ return view();
+}
+
+KCHMViewWindow_KHTMLPart::KCHMViewWindow_KHTMLPart( QTabWidget * parent )
+ : KHTMLPart ( parent ), KCHMViewWindow ( parent )
+{
+ m_zoomfactor = 0;
+ m_currentEncoding = 0;
+ m_searchForward = true;
+
+ invalidate();
+
+ connect( browserExtension(), SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ),
+ this, SLOT ( onOpenURLRequest( const KURL &, const KParts::URLArgs & )) );
+
+ connect( this, SIGNAL ( popupMenu ( const QString &, const QPoint &) ),
+ this, SLOT ( onPopupMenu ( const QString &, const QPoint &) ) );
+}
+
+
+KCHMViewWindow_KHTMLPart::~KCHMViewWindow_KHTMLPart()
+{
+}
+
+bool KCHMViewWindow_KHTMLPart::openPage (const QString& url)
+{
+ // Set or change the encoding
+ if ( m_currentEncoding != ::mainWindow->chmFile()->currentEncoding() )
+ {
+ m_currentEncoding = ::mainWindow->chmFile()->currentEncoding();
+ setEncoding ( m_currentEncoding->qtcodec, TRUE );
+ }
+
+ QString fullurl = "ms-its:" + ::mainWindow->getOpenedFileName() + "::" + url;
+ openURL ( KURL(fullurl) );
+
+ return true;
+}
+
+void KCHMViewWindow_KHTMLPart::setZoomFactor( int zoom )
+{
+ m_zoomfactor = zoom;
+
+ // Default ZoomFactor is 100, any increase or decrease should modify this value.
+ KHTMLPart::setZoomFactor ( 100 + (m_zoomfactor * 10) );
+}
+
+void KCHMViewWindow_KHTMLPart::invalidate( )
+{
+ m_zoomfactor = 0;
+ m_searchForward = true;
+ m_searchText = QString::null;
+
+ setJScriptEnabled ( appConfig.m_kdeEnableJS );
+ setJavaEnabled ( appConfig.m_kdeEnableJava );
+ setMetaRefreshEnabled ( appConfig.m_kdeEnableRefresh );
+ setPluginsEnabled ( appConfig.m_kdeEnablePlugins );
+
+ KCHMViewWindow::invalidate( );
+}
+
+int KCHMViewWindow_KHTMLPart::getScrollbarPosition( )
+{
+ return view()->contentsY ();
+}
+
+void KCHMViewWindow_KHTMLPart::setScrollbarPosition( int pos )
+{
+ view()->scrollBy (0, pos);
+}
+
+void KCHMViewWindow_KHTMLPart::addZoomFactor( int value )
+{
+ setZoomFactor( m_zoomfactor + value);
+}
+
+bool KCHMViewWindow_KHTMLPart::printCurrentPage()
+{
+ view()->print();
+ return true;
+}
+
+void KCHMViewWindow_KHTMLPart::searchWord( const QString & word, bool forward, bool )
+{
+ if ( word != m_searchText || forward != m_searchForward )
+ {
+ m_searchText = word;
+ m_searchForward = forward;
+
+ findText ( word, forward ? 0 : KFindDialog::FindBackwards, ::mainWindow, 0 );
+ }
+
+ findTextNext ();
+}
+
+void KCHMViewWindow_KHTMLPart::onOpenURLRequest( const KURL & url, const KParts::URLArgs & )
+{
+ bool sourcechange = true;
+ emit signalLinkClicked ( url.prettyURL(), sourcechange );
+}
+
+void KCHMViewWindow_KHTMLPart::slotLinkClicked( const QString & newlink )
+{
+ bool notused;
+ emit signalLinkClicked (newlink, notused);
+}
+
+
+void KCHMViewWindow_KHTMLPart::clipSelectAll()
+{
+ selectAll ();
+}
+
+void KCHMViewWindow_KHTMLPart::clipCopy()
+{
+ QString text = selectedText();
+
+ if ( !text.isEmpty() )
+ QApplication::clipboard()->setText( text );
+}
+
+void KCHMViewWindow_KHTMLPart::onPopupMenu ( const QString &url, const QPoint & point )
+{
+ KQPopupMenu * menu = getContextMenu( url, view() );
+ menu->exec( point );
+}
+
diff --git a/src/kde/kchmviewwindow_khtmlpart.h b/src/kde/kchmviewwindow_khtmlpart.h
new file mode 100644
index 0000000..5799f62
--- /dev/null
+++ b/src/kde/kchmviewwindow_khtmlpart.h
@@ -0,0 +1,114 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KCHMVIEWWINDOW_KHTMLPART_H
+#define KCHMVIEWWINDOW_KHTMLPART_H
+
+#include "kde-qt.h"
+
+#include "kchmviewwindow.h"
+#include "kchmsourcefactory.h"
+#include "libchmtextencoding.h"
+
+
+/**
+@author Georgy Yunaev
+*/
+/*
+ * For Qt-only version, we cannot compile KCHMViewWindow_KHTMLPart. However,
+ * we cannot just exclude it, because it would not generate a MOC file for a KDE
+ * version. Therefore we declare it, and compile the .moc file, but do not provide
+ * the class methods.
+ */
+#if defined (USE_KDE)
+class KCHMViewWindow_KHTMLPart : public KHTMLPart, public KCHMViewWindow
+{
+Q_OBJECT
+public:
+ KCHMViewWindow_KHTMLPart( QTabWidget * parent );
+ ~KCHMViewWindow_KHTMLPart();
+
+ //! Open a page from current chm archive
+ virtual bool openPage (const QString& url);
+
+ //! Invalidate current view, doing all the cleanups etc.
+ virtual void invalidate();
+
+ //! Return current ZoomFactor.
+ virtual int getZoomFactor() const { return m_zoomfactor; }
+
+ //! Sets ZoomFactor. The value returned by getZoomFactor(), given to this function, should give the same result.
+ virtual void setZoomFactor (int zoom);
+
+ //! Relatively changes ZoomFactor. Most common values are -1 and 1.
+ virtual void addZoomFactor (int value);
+
+ //! Popups the print dialog, and prints the current page on the printer.
+ virtual bool printCurrentPage();
+
+ //! Initiates the find-in-page search, if succeed, cursor moved to the first entry
+ virtual void searchWord( const QString & word, bool forward = true, bool casesensitive = false );
+
+ //! Select the content of the whole page
+ virtual void clipSelectAll();
+
+ //! Copies the selected content to the clipboard
+ virtual void clipCopy();
+
+ /*!
+ * Return current scrollbar position in view window. Saved on program exit.
+ * There is no restriction on returned value, except that giving this value to
+ * setScrollbarPosition() should move the scrollbar in the same position.
+ */
+ virtual int getScrollbarPosition();
+
+ //! Sets the scrollbar position.
+ virtual void setScrollbarPosition(int pos);
+
+ virtual QObject * getQObject() { return this; }
+ virtual QWidget * getQWidget();
+
+signals:
+ /*!
+ * Emitted when the user clicked on the link, before the page changed.
+ * If signalLinkClicked() sets follow_link to false, the current page should NOT change.
+ * Otherwise it should be changed to the new link value.
+ */
+ void signalLinkClicked ( const QString & newlink, bool& follow_link );
+
+private slots:
+ virtual void slotLinkClicked ( const QString & newlink);
+ virtual void onOpenURLRequest( const KURL &, const KParts::URLArgs & );
+ virtual void onPopupMenu ( const QString & url, const QPoint & point );
+
+private:
+ void setSource ( const QString & name );
+
+ int m_zoomfactor;
+ bool m_searchForward;
+ QString m_searchText;
+
+ const LCHMTextEncoding * m_currentEncoding;
+};
+
+#endif /* USE_KDE */
+
+#endif /* KCHMVIEWWINDOW_KHTMLPART_H */
diff --git a/src/kqrunprocess.h b/src/kqrunprocess.h
new file mode 100644
index 0000000..4ac1b9a
--- /dev/null
+++ b/src/kqrunprocess.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <stdlib.h>
+#include <unistd.h>
+
+static bool run_process( const QString& command, const QString& filename )
+{
+ QString safefilename = filename;
+ QString preparedcommand = command;
+
+ // To be safe, URL should contain no quotes, apostrofes and \0 symbols
+ safefilename.remove (QRegExp ("['\"\0]"));
+ preparedcommand.replace( "%s", safefilename );
+
+ // And run an external command with fork()s
+ switch ( fork() )
+ {
+ case -1:
+ return false;
+
+ case 0: // child
+ if ( fork() != 0 )
+ exit(0); // exit immediately - our child is now has init as his parent
+
+ system( preparedcommand.ascii() );
+ exit (0);
+
+ default: // parent
+ break;
+ }
+
+ return true;
+}
diff --git a/src/kqtempfile.cpp b/src/kqtempfile.cpp
new file mode 100644
index 0000000..46018c4
--- /dev/null
+++ b/src/kqtempfile.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdio.h>
+
+#include "kqtempfile.h"
+
+
+KQTempFileKeeper::KQTempFileKeeper( )
+{
+#if defined(WIN32)
+ m_tempDir = ::GetTempDirectory();
+#else
+ if ( getenv("TEMP") )
+ m_tempDir = getenv("TEMP");
+ else if ( getenv("TMP") )
+ m_tempDir = getenv("TMP");
+ else
+ m_tempDir = "/tmp";
+#endif
+
+ m_fileNumber = 1;
+}
+
+KQTempFileKeeper::~ KQTempFileKeeper( )
+{
+ destroyTempFiles();
+}
+
+bool KQTempFileKeeper::generateTempFile( QFile & file, const QString & tempdir )
+{
+ QString usetempdir = ((tempdir != QString::null) ? tempdir : m_tempDir) + "/";
+
+ while( 1 )
+ {
+ char fnbuf[128];
+ sprintf( fnbuf, "KQTEMPFILE%d-%d-%d.tmp", (int) getpid(), (int) time(0), m_fileNumber++ );
+
+ file.setName( usetempdir + fnbuf );
+ if ( file.open( IO_WriteOnly ) )
+ break;
+ }
+
+ return true;
+}
+
+void KQTempFileKeeper::destroyTempFiles( )
+{
+ for ( unsigned int i = 0; i < m_tempFiles.size(); i++ )
+ QFile::remove( m_tempFiles[i] );
+}
diff --git a/src/kqtempfile.h b/src/kqtempfile.h
new file mode 100644
index 0000000..6440067
--- /dev/null
+++ b/src/kqtempfile.h
@@ -0,0 +1,53 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#ifndef KQTEMPFILE_H
+#define KQTEMPFILE_H
+
+#include <qvaluevector.h>
+#include <qfile.h>
+
+/*
+ * This class generates temp file names in race condition-safe way,
+ * returns QFile and filename pairs, keeps the track of opened temp files,
+ * and deletes them when program exist.
+ */
+
+class KQTempFileKeeper
+{
+ public:
+ KQTempFileKeeper();
+ ~KQTempFileKeeper();
+
+ //! Generates a temporary file name, and creates it on disk at the same time.
+ //! Returns the file. If tempdir is not empty, it is used as temp directory.
+ bool generateTempFile( QFile& file, const QString& tempdir = QString::null );
+
+ //! Closes and removes all the files from disk
+ void destroyTempFiles();
+
+ private:
+ QValueVector<QString> m_tempFiles;
+ QString m_tempDir;
+ unsigned int m_fileNumber;
+};
+
+#endif /* KQTEMPFILE_H */
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..f79bbca
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (C) 2004-2007 by Georgy Yunaev, gyunaev@ulduzsoft.com *
+ * Please do not use email address above for bug reports; see *
+ * the README file *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "kde-qt.h"
+
+#include "kchmmainwindow.h"
+#include "kchmconfig.h"
+#include "kchmkeyeventfilter.h"
+
+#if defined (USE_KDE)
+ #include <kaboutdata.h>
+ #include <dcopclient.h>
+
+ #include "kde/kchmdcopiface.h"
+#endif
+
+KCHMMainWindow * mainWindow;
+
+
+int main( int argc, char ** argv )
+{
+#if defined (USE_KDE)
+ static KCmdLineOptions options[] =
+ {
+ { "autotestmode", "Perform auto testing", 0 },
+ { "shortautotestmode", "Perform short auto testing", 0 },
+ { "+[chmfile]", "A CHM file to show", 0 },
+ { "search <query>", I18N_NOOP("'--search <query>' specifies the search query to search, and activate the first entry if found"), 0 },
+ { "sindex <word>", I18N_NOOP("'--sindex <word>' specifies the word to find in index, and activate if found"), 0 },
+ KCmdLineLastOption
+ };
+
+ KAboutData aboutdata ( "kchmviewer",
+ APP_NAME,
+ APP_VERSION,
+ I18N_NOOP("CHM file viewer"),
+ KAboutData::License_GPL,
+ "(c) 2004-2007 George Yunaev, gyunaev@ulduzsoft.com",
+ 0,
+ "http://www.kchmviewer.net",
+ "gyunaev@ulduzsoft.com");
+
+ KLocale::setMainCatalogue( "kchmviewer" );
+ KCmdLineArgs::init (argc, argv, &aboutdata);
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KApplication app;
+#else
+ QApplication app( argc, argv );
+#endif
+
+ appConfig.load();
+ app.installEventFilter( &gKeyEventFilter );
+
+#if defined(USE_KDE)
+ // DCOP stuff
+ KCHMDCOPIface iface;
+
+ DCOPClient *client = kapp->dcopClient();
+
+ if ( !client->attach() )
+ qWarning("DCOP attach failed");
+
+ //QCString realAppId = client->registerAs( kapp->name() );
+ QCString realAppId = client->registerAs( "kchmviewer" );
+#endif
+
+ mainWindow = new KCHMMainWindow();
+ mainWindow->show();
+
+#if !defined(USE_KDE)
+ app.connect( &app, SIGNAL(lastWindowClosed()), &app, SLOT(quit()) );
+#else
+ app.setMainWidget( mainWindow );
+#endif
+
+ return app.exec();
+}
diff --git a/src/pics/Makefile.am b/src/pics/Makefile.am
new file mode 100644
index 0000000..d085bb3
--- /dev/null
+++ b/src/pics/Makefile.am
@@ -0,0 +1,2 @@
+# Install the icons into the global KDE directories
+KDE_ICON = AUTO
diff --git a/src/pics/cr128-app-kchmviewer.png b/src/pics/cr128-app-kchmviewer.png
new file mode 100644
index 0000000..6635d97
--- /dev/null
+++ b/src/pics/cr128-app-kchmviewer.png
Binary files differ
diff --git a/src/pics/cr48-app-kchmviewer.png b/src/pics/cr48-app-kchmviewer.png
new file mode 100644
index 0000000..5a42d77
--- /dev/null
+++ b/src/pics/cr48-app-kchmviewer.png
Binary files differ
diff --git a/src/pics/cr64-app-kchmviewer.png b/src/pics/cr64-app-kchmviewer.png
new file mode 100644
index 0000000..970dbf2
--- /dev/null
+++ b/src/pics/cr64-app-kchmviewer.png
Binary files differ