init
authorsr <sr@localhost.localdomain>
Tue, 29 Dec 2009 13:52:43 +0000 (16:52 +0300)
committersr <sr@localhost.localdomain>
Tue, 29 Dec 2009 13:52:43 +0000 (16:52 +0300)
242 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
Doxyfile [new file with mode: 0644]
INSTALL [new file with mode: 0644]
README [new file with mode: 0644]
README.MACOSX [new file with mode: 0644]
README.WINDOWS [new file with mode: 0644]
THANKS [new file with mode: 0644]
build-stamp [new file with mode: 0644]
configure-stamp [new file with mode: 0644]
debian/changelog [new file with mode: 0644]
debian/compat [new file with mode: 0644]
debian/control [new file with mode: 0644]
debian/copyright [new file with mode: 0644]
debian/dirs [new file with mode: 0644]
debian/docs [new file with mode: 0644]
debian/files [new file with mode: 0644]
debian/menu [new file with mode: 0644]
debian/qstardict.1 [new file with mode: 0644]
debian/qstardict.postinst.debhelper [new file with mode: 0644]
debian/qstardict.postrm.debhelper [new file with mode: 0644]
debian/qstardict.substvars [new file with mode: 0644]
debian/qstardict.xpm [new file with mode: 0644]
debian/rules [new file with mode: 0755]
debian/watch [new file with mode: 0644]
kdeplasma/CMakeLists.txt [new file with mode: 0644]
kdeplasma/COMPILING [new file with mode: 0644]
kdeplasma/applet/CMakeLists.txt [new file with mode: 0644]
kdeplasma/applet/Messages.sh [new file with mode: 0755]
kdeplasma/applet/dict.cpp [new file with mode: 0644]
kdeplasma/applet/dict.h [new file with mode: 0644]
kdeplasma/applet/plasma-qstardict-default.desktop [new file with mode: 0644]
kdeplasma/dataengine/CMakeLists.txt [new file with mode: 0644]
kdeplasma/dataengine/Messages.sh [new file with mode: 0755]
kdeplasma/dataengine/config.h.cmake [new file with mode: 0644]
kdeplasma/dataengine/dictengine.cpp [new file with mode: 0644]
kdeplasma/dataengine/dictengine.h [new file with mode: 0644]
kdeplasma/dataengine/plasma-dataengine-qstardict.desktop [new file with mode: 0644]
plugins/dictplugin.h [new file with mode: 0644]
plugins/multitran/README [new file with mode: 0644]
plugins/multitran/multitran.cpp [new file with mode: 0644]
plugins/multitran/multitran.h [new file with mode: 0644]
plugins/multitran/multitran.pro [new file with mode: 0644]
plugins/multitran/multitran.pro.user [new file with mode: 0644]
plugins/plugin.pri [new file with mode: 0644]
plugins/plugins.pri [new file with mode: 0644]
plugins/plugins.pro [new file with mode: 0644]
plugins/plugins.pro.user [new file with mode: 0644]
plugins/stardict/dictziplib.cpp [new file with mode: 0644]
plugins/stardict/dictziplib.hpp [new file with mode: 0644]
plugins/stardict/dictziplib.o [new file with mode: 0644]
plugins/stardict/distance.cpp [new file with mode: 0644]
plugins/stardict/distance.h [new file with mode: 0644]
plugins/stardict/distance.o [new file with mode: 0644]
plugins/stardict/file.hpp [new file with mode: 0644]
plugins/stardict/lib.cpp [new file with mode: 0644]
plugins/stardict/lib.h [new file with mode: 0644]
plugins/stardict/lib.o [new file with mode: 0644]
plugins/stardict/mapfile.hpp [new file with mode: 0644]
plugins/stardict/moc_settingsdialog.cpp [new file with mode: 0644]
plugins/stardict/moc_settingsdialog.o [new file with mode: 0644]
plugins/stardict/moc_stardict.cpp [new file with mode: 0644]
plugins/stardict/moc_stardict.o [new file with mode: 0644]
plugins/stardict/pixmaps/arrow-down.png [new file with mode: 0644]
plugins/stardict/pixmaps/arrow-up.png [new file with mode: 0644]
plugins/stardict/pixmaps/list-add.png [new file with mode: 0644]
plugins/stardict/pixmaps/list-remove.png [new file with mode: 0644]
plugins/stardict/pixmaps/pixmaps.qrc [new file with mode: 0644]
plugins/stardict/qrc_pixmaps.cpp [new file with mode: 0644]
plugins/stardict/qrc_pixmaps.o [new file with mode: 0644]
plugins/stardict/settingsdialog.cpp [new file with mode: 0644]
plugins/stardict/settingsdialog.h [new file with mode: 0644]
plugins/stardict/settingsdialog.o [new file with mode: 0644]
plugins/stardict/settingsdialog.ui [new file with mode: 0644]
plugins/stardict/stardict.cpp [new file with mode: 0644]
plugins/stardict/stardict.h [new file with mode: 0644]
plugins/stardict/stardict.o [new file with mode: 0644]
plugins/stardict/stardict.pro [new file with mode: 0644]
plugins/stardict/stardict.pro.user [new file with mode: 0644]
plugins/stardict/ui_settingsdialog.h [new file with mode: 0644]
plugins/swac/pixmaps/pixmaps.qrc [new file with mode: 0644]
plugins/swac/pixmaps/sound.png [new file with mode: 0755]
plugins/swac/swac.cpp [new file with mode: 0644]
plugins/swac/swac.h [new file with mode: 0644]
plugins/swac/swac.pro [new file with mode: 0644]
plugins/web/adddictionarydialog.ui [new file with mode: 0644]
plugins/web/moc_settingsdialog.cpp [new file with mode: 0644]
plugins/web/moc_settingsdialog.o [new file with mode: 0644]
plugins/web/moc_web.cpp [new file with mode: 0644]
plugins/web/moc_web.o [new file with mode: 0644]
plugins/web/pixmaps/edit.png [new file with mode: 0644]
plugins/web/pixmaps/list-add.png [new file with mode: 0644]
plugins/web/pixmaps/list-remove.png [new file with mode: 0644]
plugins/web/pixmaps/pixmaps.qrc [new file with mode: 0644]
plugins/web/qrc_pixmaps.cpp [new file with mode: 0644]
plugins/web/qrc_pixmaps.o [new file with mode: 0644]
plugins/web/settingsdialog.cpp [new file with mode: 0644]
plugins/web/settingsdialog.h [new file with mode: 0644]
plugins/web/settingsdialog.o [new file with mode: 0644]
plugins/web/settingsdialog.ui [new file with mode: 0644]
plugins/web/ui_adddictionarydialog.h [new file with mode: 0644]
plugins/web/ui_settingsdialog.h [new file with mode: 0644]
plugins/web/web.cpp [new file with mode: 0644]
plugins/web/web.h [new file with mode: 0644]
plugins/web/web.o [new file with mode: 0644]
plugins/web/web.pro [new file with mode: 0644]
plugins/web/web.pro.user [new file with mode: 0644]
qstardict.pri [new file with mode: 0644]
qstardict.pro [new file with mode: 0644]
qstardict.pro.user [new file with mode: 0644]
qstardict/application.cpp [new file with mode: 0644]
qstardict/application.h [new file with mode: 0644]
qstardict/application.o [new file with mode: 0644]
qstardict/cssedit.cpp [new file with mode: 0644]
qstardict/cssedit.h [new file with mode: 0644]
qstardict/cssedit.o [new file with mode: 0644]
qstardict/cssedit.ui [new file with mode: 0644]
qstardict/dbusadaptor.cpp [new file with mode: 0644]
qstardict/dbusadaptor.h [new file with mode: 0644]
qstardict/dbusadaptor.o [new file with mode: 0644]
qstardict/dictbrowser.cpp [new file with mode: 0644]
qstardict/dictbrowser.h [new file with mode: 0644]
qstardict/dictbrowser.o [new file with mode: 0644]
qstardict/dictcore.cpp [new file with mode: 0644]
qstardict/dictcore.h [new file with mode: 0644]
qstardict/dictcore.o [new file with mode: 0644]
qstardict/dictwidget.cpp [new file with mode: 0644]
qstardict/dictwidget.h [new file with mode: 0644]
qstardict/dictwidget.o [new file with mode: 0644]
qstardict/keyboard.cpp [new file with mode: 0644]
qstardict/keyboard.h [new file with mode: 0644]
qstardict/keyboard.o [new file with mode: 0644]
qstardict/main.cpp [new file with mode: 0644]
qstardict/main.o [new file with mode: 0644]
qstardict/mainwindow.cpp [new file with mode: 0644]
qstardict/mainwindow.h [new file with mode: 0644]
qstardict/mainwindow.o [new file with mode: 0644]
qstardict/mainwindow.ui [new file with mode: 0644]
qstardict/moc_application.cpp [new file with mode: 0644]
qstardict/moc_application.o [new file with mode: 0644]
qstardict/moc_cssedit.cpp [new file with mode: 0644]
qstardict/moc_cssedit.o [new file with mode: 0644]
qstardict/moc_dbusadaptor.cpp [new file with mode: 0644]
qstardict/moc_dbusadaptor.o [new file with mode: 0644]
qstardict/moc_dictbrowser.cpp [new file with mode: 0644]
qstardict/moc_dictbrowser.o [new file with mode: 0644]
qstardict/moc_dictcore.cpp [new file with mode: 0644]
qstardict/moc_dictcore.o [new file with mode: 0644]
qstardict/moc_dictwidget.cpp [new file with mode: 0644]
qstardict/moc_dictwidget.o [new file with mode: 0644]
qstardict/moc_mainwindow.cpp [new file with mode: 0644]
qstardict/moc_mainwindow.o [new file with mode: 0644]
qstardict/moc_popupwindow.cpp [new file with mode: 0644]
qstardict/moc_popupwindow.o [new file with mode: 0644]
qstardict/moc_resizablepopup.cpp [new file with mode: 0644]
qstardict/moc_resizablepopup.o [new file with mode: 0644]
qstardict/moc_selection.cpp [new file with mode: 0644]
qstardict/moc_selection.o [new file with mode: 0644]
qstardict/moc_settingsdialog.cpp [new file with mode: 0644]
qstardict/moc_settingsdialog.o [new file with mode: 0644]
qstardict/moc_trayicon.cpp [new file with mode: 0644]
qstardict/moc_trayicon.o [new file with mode: 0644]
qstardict/pixmaps/application-exit.png [new file with mode: 0644]
qstardict/pixmaps/arrow-down.png [new file with mode: 0644]
qstardict/pixmaps/arrow-left.png [new file with mode: 0644]
qstardict/pixmaps/arrow-right.png [new file with mode: 0644]
qstardict/pixmaps/arrow-up.png [new file with mode: 0644]
qstardict/pixmaps/clear-right.png [new file with mode: 0644]
qstardict/pixmaps/configure.png [new file with mode: 0644]
qstardict/pixmaps/dialog-information.png [new file with mode: 0644]
qstardict/pixmaps/dialog-warning.png [new file with mode: 0644]
qstardict/pixmaps/document-print.png [new file with mode: 0644]
qstardict/pixmaps/document-save-as.png [new file with mode: 0644]
qstardict/pixmaps/download.png [new file with mode: 0644]
qstardict/pixmaps/go-next.png [new file with mode: 0644]
qstardict/pixmaps/go-previous.png [new file with mode: 0644]
qstardict/pixmaps/help-contents.png [new file with mode: 0644]
qstardict/pixmaps/list-add.png [new file with mode: 0644]
qstardict/pixmaps/list-remove.png [new file with mode: 0644]
qstardict/pixmaps/pixmaps.qrc [new file with mode: 0644]
qstardict/pixmaps/qstardict-disabled.png [new file with mode: 0644]
qstardict/pixmaps/qstardict.icns [new file with mode: 0644]
qstardict/pixmaps/qstardict.ico [new file with mode: 0644]
qstardict/pixmaps/qstardict.png [new file with mode: 0644]
qstardict/pixmaps/search-filter.png [new file with mode: 0644]
qstardict/pixmaps/speaker.png [new file with mode: 0644]
qstardict/pixmaps/view-refresh.png [new file with mode: 0644]
qstardict/popupwindow.cpp [new file with mode: 0644]
qstardict/popupwindow.h [new file with mode: 0644]
qstardict/popupwindow.o [new file with mode: 0644]
qstardict/qrc_pixmaps.cpp [new file with mode: 0644]
qstardict/qrc_pixmaps.o [new file with mode: 0644]
qstardict/qstardict.desktop [new file with mode: 0644]
qstardict/qstardict.png [new file with mode: 0644]
qstardict/qstardict.pro [new file with mode: 0644]
qstardict/qstardict.rc [new file with mode: 0644]
qstardict/resizablepopup.cpp [new file with mode: 0644]
qstardict/resizablepopup.h [new file with mode: 0644]
qstardict/resizablepopup.o [new file with mode: 0644]
qstardict/selection.cpp [new file with mode: 0644]
qstardict/selection.h [new file with mode: 0644]
qstardict/selection.o [new file with mode: 0644]
qstardict/settingsdialog.cpp [new file with mode: 0644]
qstardict/settingsdialog.h [new file with mode: 0644]
qstardict/settingsdialog.o [new file with mode: 0644]
qstardict/settingsdialog.ui [new file with mode: 0644]
qstardict/speaker.cpp [new file with mode: 0644]
qstardict/speaker.h [new file with mode: 0644]
qstardict/speaker.o [new file with mode: 0644]
qstardict/translations/qstardict-bg_BG.qm [new file with mode: 0644]
qstardict/translations/qstardict-bg_BG.ts [new file with mode: 0644]
qstardict/translations/qstardict-cs_CZ.qm [new file with mode: 0644]
qstardict/translations/qstardict-cs_CZ.ts [new file with mode: 0644]
qstardict/translations/qstardict-de_DE.qm [new file with mode: 0644]
qstardict/translations/qstardict-de_DE.ts [new file with mode: 0644]
qstardict/translations/qstardict-es_ES.qm [new file with mode: 0644]
qstardict/translations/qstardict-es_ES.ts [new file with mode: 0644]
qstardict/translations/qstardict-fr_FR.qm [new file with mode: 0644]
qstardict/translations/qstardict-fr_FR.ts [new file with mode: 0644]
qstardict/translations/qstardict-it_IT.qm [new file with mode: 0644]
qstardict/translations/qstardict-it_IT.ts [new file with mode: 0644]
qstardict/translations/qstardict-pl_PL.qm [new file with mode: 0644]
qstardict/translations/qstardict-pl_PL.ts [new file with mode: 0644]
qstardict/translations/qstardict-pt_BR.qm [new file with mode: 0644]
qstardict/translations/qstardict-pt_BR.ts [new file with mode: 0644]
qstardict/translations/qstardict-ru_RU.qm [new file with mode: 0644]
qstardict/translations/qstardict-ru_RU.ts [new file with mode: 0644]
qstardict/translations/qstardict-ua_UA.qm [new file with mode: 0644]
qstardict/translations/qstardict-ua_UA.ts [new file with mode: 0644]
qstardict/translations/qstardict-zh_CN.qm [new file with mode: 0644]
qstardict/translations/qstardict-zh_CN.ts [new file with mode: 0644]
qstardict/translations/qstardict-zh_TW.qm [new file with mode: 0644]
qstardict/translations/qstardict-zh_TW.ts [new file with mode: 0644]
qstardict/translations/translations.pri [new file with mode: 0644]
qstardict/trayicon.cpp [new file with mode: 0644]
qstardict/trayicon.h [new file with mode: 0644]
qstardict/trayicon.o [new file with mode: 0644]
qstardict/ui_cssedit.h [new file with mode: 0644]
qstardict/ui_mainwindow.h [new file with mode: 0644]
qstardict/ui_settingsdialog.h [new file with mode: 0644]
welcome [deleted file]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..4fbcc4c
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,15 @@
+Alexander Rodin <rodin.alexander@gmail.com>
+
+The authors of the StarDict plugin:
+    Hu Zheng <huzheng_001@163.com>
+    Opera Wang <wangvisual@sohu.com>
+    Rickard E. Faith <faith@dict.org>
+
+The author of the SWAC plugin:
+    Nicolas Vion <nico@picapo.net>
+
+The author of the Multitran plugin and KDE 4 plasmoid:
+    Nick Shaforostoff <shaforostoff@kde.ru>
+
+QStarDict uses the Oxygen icons (http://oxygen-icons.org)
+
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..d511905
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,339 @@
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                           Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                   GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                           NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                    END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..7095764
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,119 @@
+* Version 0.01 - initial release
+* Version 0.02
+       - add dictionary directories selection in settings dialog
+       - redesign menus
+       - add Oxygen icons
+       - add "Save translation" action
+       - add pop up window opacity item to settings dialog
+       - rename actions
+       - add .desktop file
+* Version 0.03
+       - fix bug when build fails on x86_64
+       - fix categories in .desktop file
+       - add option "Show pop up only if modifier pressed" in settings dialog
+       - improve selection scanning
+       - fix bug with closing window when it must hide
+       - setting Qt 4.2 compitibility
+       - add russian translation
+       - add traditional chinese translation
+* Version 0.04
+       - add ukrainian translation
+       - fix bug when popup window violates from desktop
+       - add translations reformater
+       - add popup window timeout before hide after mouse over to settings dialog
+       - fix bug with "Up" buttons in settings dialog
+       - add popup window default width and height items to settings dialog
+       - change PopupWindow base class from QWidget to QFrame
+       - add D-Bus support
+       - make popup window resizable
+       - add current translation title to main window header
+* Version 0.05
+       - fix bug with hard font-family in translation CSS
+       - make popup window border more useful
+       - fix bug with words list
+       - add simplified chinese translation
+       - fix bug with uncorrect displayed hierarchical lists
+       - set to run only one instance of application
+       - set to search for dictionaries recursively
+* Version 0.06
+       - add bulgarian translation
+       - add speech support
+       - fix bug with broken main window title when search is empty
+* Version 0.07
+       - add "translate" and "translateHtml" methods to D-Bus interface
+       - change license from GPLv3 to GPLv2
+* Version 0.08
+       - add czech translation
+       - fix bug with multiple running from different users
+       - add brazilian portuguese translation
+       - update the traditional chinese translation
+       - add support for configurable instant search
+       - add support for separate translations
+* Version 0.09
+       - add polish translation
+       - fix bug with instant search
+       - add italian translation
+       - fix bug with simlinks to dictionaries
+       - add german translation
+       - improve popup window
+       - update the german translation
+       - reorganize project
+       - add basic Windows support
+       - add plugins support
+       - add toolbar to dictionary widget
+       - add for links in translations (by pressing Ctrl and clicking on the word)
+       - improve instant search
+       - improve popup window
+       - add support for closing popup by double click on toolbar
+* Version 0.10
+       - change tray icon if scanning disabled
+       - add font editor
+       - some improves and bugfixes
+* Version 0.11
+       - fix bug with bad source word
+       - fix bug with removed last letter in translation
+* Version 0.12
+       - update italian translation
+       - add support for popup window moving
+* Version 0.12.1
+       - fix critical bug with popup window
+* Version 0.12.2
+       - fix bug with building on Ubuntu Hardy
+* Version 0.12.3
+       - update simplified chinese translation
+* Version 0.12.4
+       - update polish translation
+* Version 0.12.5
+       - fix bug with main window title
+* Version 0.12.6
+       - update german translation
+* Version 0.12.7
+       - fix bug with empty speech cmd
+* Version 0.12.8
+       - add localization for standard Qt dialogs
+       - add support for Escape key in main window
+       - update ukrainian translation
+       - update chinese translation
+       - fix bug with speaker
+       - remove alphabetical sorting of results
+       - improve saving
+       - add a tooltip for the tray icon
+* Version 0.12.9
+       - update german translation
+       - fix typo in the COPYING filename
+* Version 0.13.0
+       - add french and turkish translation
+       - improve Windows port
+       - add SWAC and Multitran plugins
+       - add command line support
+       - improve the simplified chinese translation
+       - fix bug with settings saving
+       - improve D-Bus support
+       - fix bug with Qt 4.5
+* Version 0.13.1
+       - fix bugs with installation
+       - add spanish translation
+       - update italian and german translations
+* Version 0.13.2
+       - improve system tray support
+       - improve the save dialog
diff --git a/Doxyfile b/Doxyfile
new file mode 100644 (file)
index 0000000..75388c5
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,1356 @@
+# Doxyfile 1.5.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = qstardict
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = devel-doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, 
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), 
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, 
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, 
+# and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = 
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = 
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = 
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = *.h *.cpp
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = 
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = 
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             = 
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default) 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES (the default) 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = 
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is enabled by default, which results in a transparent 
+# background. Warning: Depending on the platform used, enabling this option 
+# may lead to badly anti-aliased labels on the edges of a graph (i.e. they 
+# become hard to read).
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..5e0a029
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,27 @@
+You need Qt >= 4.2 and glib >= 2.0. If you have QtDBus module QStarDict
+will be compiled with D-Bus support.
+
+To disable D-Bus support add
+    NO_DBUS=1
+to qmake arguments.
+
+To disable translations add
+    NO_TRANSLATIONS=1
+to qmake arguments.
+
+If you want to select plugins to compile add
+    ENABLED_PLUGINS="plugin1 plugin2 ..."
+to qmake arguments.
+Available plugins:
+    * stardict - supports StarDict dictionaries
+    * web - supports any web search engine
+    * swac - supports SWAC speaking system (http://shtooka.net)
+    * multitran - supports Multitran dictionaries (http://multitran.sourceforge.net)
+By default the only "stardict" and "web" plugins enabled.
+
+To build and install:
+1)     qmake [switches]
+2)     make
+3)     make install
+
+If you want to compile KDE 4 plasmoid please read kdeplasma/COMPILING.
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..06229bb
--- /dev/null
+++ b/README
@@ -0,0 +1,12 @@
+QStarDict is a StarDict clone written with using Qt4. The user interface
+is similar to StarDict.
+
+Main features
+* Full support of StarDict dictionaries
+* Working in system tray
+* Scanning mouse selection and showing popup window with translation of
+selected word
+* Translations reformatting
+* Pronouncing translated word
+* Plugins support
+* KDE 4 plasmoid
diff --git a/README.MACOSX b/README.MACOSX
new file mode 100644 (file)
index 0000000..74f6131
--- /dev/null
@@ -0,0 +1,38 @@
+QStarDict for Mac OS X is set to be built as a "bundle" application.\r
+\r
+Distributed packages should contain all required stuff to run out-of-the-box.\r
+\r
+All following notes are important for developers.\r
+\r
+\r
+BUILDING REQUIREMENTS:\r
+ * Qt4 libraries/frameworks (tested with macport's qt4-mac+universal)\r
+ * glib2 devel environment (I'm using macports for it too)\r
+ * all other libraries are propably part of mac's OS\r
+\r
+\r
+CONFIRURE PHASE:\r
+qmake\r
+  it will build qstardict and install it into /opt (sudo make install will be required)\r
+  or:\r
+qmake INSTALL_PREFIX=/absolute/path/to/selected/dir\r
+  it will build qstardict and install it into this location.\r
+  The path *must* be absolute. Relative path will cause install problems.\r
+\r
+example:\r
+qmake INSTALL_PREFIX=/Users/pvanek/oss/qstardict/release\r
+\r
+\r
+MAKE PHASE:\r
+just run: make\r
+\r
+INSTALL PHASE:\r
+make install\r
+\r
+DEPLOY PHASE:\r
+macdeployqt path/to/QStarDict.app/\r
+or:\r
+macdeployqt path/to/QStarDict.app/ -dmg\r
+for dmg build (but I'm using another tool for it)\r
+\r
+\r
diff --git a/README.WINDOWS b/README.WINDOWS
new file mode 100644 (file)
index 0000000..2685cbf
--- /dev/null
@@ -0,0 +1,20 @@
+qmake params for Windows:\r
+\r
+GLIB2PATH - path to the Glib-2.x development environment (includes, ...)\r
+\r
+ZLIBPATH - path to the Zlib development environment (includes, ...)\r
+\r
+sample usage:\r
+qmake GLIB2PATH=d:\oss\glib\ ZLIBPATH=d:\oss\zlib\\r
+\r
+\r
+\r
+\r
+Requirements:\r
+\r
+Glib2 development env.\r
+\r
+Glib2 runtime env.\r
+\r
+Zlib env.\r
+\r
diff --git a/THANKS b/THANKS
new file mode 100644 (file)
index 0000000..5c41d90
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,24 @@
+Thanks to:
+    Petr Vanek whoes offer some improves and add the Windows support
+    Andrew Gaydenko whoes help to fix a  bug with building in x86_64
+    Vadim Kalinnikov whoes give a hosting
+    Hoopoe whoes add a traditional chinese translation
+    Yurij Goncharuck whoes fix bug when popup window violates from desktop and add ukrainian translation
+    Truth whoes add a simplified chinese translation
+    Nikola Valentinov Petrov whoes add a bulgarian translation
+    Jiri Hlinka whoes add a czech translation
+    Klaos Lacerda and Bruno Gonçalves whoes add a brazilian portuguese translation
+    Zhengpeng Hou whoes update the traditional chinese translation
+    Grzegorz Gibas whoes add the polosh translation
+    Simone Solinas whoes add the italian translation
+    Stefan Kombrink whoes improve the popup window and update german translation
+    Matthias Fehring whoes update german translations
+    Albert Tugushev whoes help to fix bug with empty speech cmd
+    Ilya Kotov whoes help to improve localization
+    Alex Koudr whoes help with with mouse scanning on Windows
+    Nicolas Vion whoes add the french translation
+    Andriy Rysin whoes add the command line support
+    Yao Ziyuan whoes improve the simplified chinese translation
+    Serdar Soytetir whoes add the turkish translation
+    Sergey Ilinyh whoes help and improve D-Bus support
+    Frank Ren whoes improve the save dialog
diff --git a/build-stamp b/build-stamp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/configure-stamp b/configure-stamp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/debian/changelog b/debian/changelog
new file mode 100644 (file)
index 0000000..df0a5dd
--- /dev/null
@@ -0,0 +1,39 @@
+qstardict (0.13.1-6) unstable; urgency=low
+
+  * Final Version
+
+ -- SR <sbir@list.ru>  Fri, 29 Dec 2009 16:33:00 +0300
+
+qstardict (0.13.1-5) unstable; urgency=low
+
+  * Fixed GUI
+
+ -- SR <sbir@list.ru>  Fri, 28 Dec 2009 23:27:00 +0300
+
+qstardict (0.13.1-4) unstable; urgency=low
+
+  * Fixed GUI
+  * Updated to Qt 4.6
+
+ -- SR <sbir@list.ru>  Fri, 26 Dec 2009 21:03:00 +0300
+
+qstardict (0.13.1-3) unstable; urgency=low
+
+  * Fixed GUI
+  * Updated from svn
+  * Code quirks cleaned
+
+ -- SR <sbir@list.ru>  Fri, 26 Dec 2009 01:13:54 +0300
+
+qstardict (0.13.1-2) unstable; urgency=low
+
+  * Fixed GUI
+
+ -- SR <sbir@list.ru>  Fri, 25 Dec 2009 20:13:54 +0300
+
+qstardict (0.13.1-1) unstable; urgency=low
+
+  * Initial release (Closes: #nnnn)  <nnnn is the bug number of your ITP>
+
+ -- SR <sbir@list.ru>  Fri, 25 Dec 2009 17:13:54 +0300
+
diff --git a/debian/compat b/debian/compat
new file mode 100644 (file)
index 0000000..7ed6ff8
--- /dev/null
@@ -0,0 +1 @@
+5
diff --git a/debian/control b/debian/control
new file mode 100644 (file)
index 0000000..c002294
--- /dev/null
@@ -0,0 +1,27 @@
+Source: qstardict
+Version: 0.13.1-6
+Section: x11
+Priority: optional
+Maintainer: SR <sbir@list.ru>
+Build-Depends: debhelper (>= 5), libqt4-dev (>= 4.4.0), libglib2.0-dev, zlib1g-dev, libx11-dev
+Standards-Version: 3.8.0
+Homepage: http://qstardict.ylsoftware.com
+
+Package: qstardict
+Architecture: any
+Depends: ${shlibs:Depends}
+Suggests: festival
+Description: International dictionary written using Qt4
+ QStarDict is a modern international dictionary written using Qt4.
+ .
+ Main features
+  * Full support of StarDict dictionaries
+  * Fuzzy search
+  * Support for hyper links in translations
+  * Working from the system tray
+  * Scanning mouse selection and showing pop-up windows with translation of
+    selected words
+  * Translations reformatting
+  * Pronouncing of the translated words
+  * Plugins support
+
diff --git a/debian/copyright b/debian/copyright
new file mode 100644 (file)
index 0000000..101d47f
--- /dev/null
@@ -0,0 +1,34 @@
+This package was debianized by Alexander Rodin <rodin.alexander@gmail.com> on
+Thu, 30 Aug 2007 10:15:32 +0400.
+
+It was downloaded from http://qstardict.ylsoftware.com
+
+Upstream Authors:
+    Alexander Rodin <rodin.aleander@gmail.com>
+    Hu Zheng <huzheng_001@163.com>
+    Opera Wang <wangvisual@sohu.com>
+    Rickard E. Faith <faith@dict.org>
+
+This software is copyright (c) 2007 by Alexander Rodin
+
+License:
+
+   This package 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 package 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 package; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+On Debian systems, the complete text of the GNU General
+Public License can be found in `/usr/share/common-licenses/GPL'.
+
+The Debian packaging is (C) 2007, Alexander Rodin <rodin.alexander@gmail.com>
+and is licensed under the GPL, see above.
diff --git a/debian/dirs b/debian/dirs
new file mode 100644 (file)
index 0000000..ca882bb
--- /dev/null
@@ -0,0 +1,2 @@
+usr/bin
+usr/sbin
diff --git a/debian/docs b/debian/docs
new file mode 100644 (file)
index 0000000..8d6f5b5
--- /dev/null
@@ -0,0 +1,2 @@
+README
+README.WINDOWS
diff --git a/debian/files b/debian/files
new file mode 100644 (file)
index 0000000..56c6827
--- /dev/null
@@ -0,0 +1 @@
+qstardict_0.13.1-6_armel.deb x11 optional
diff --git a/debian/menu b/debian/menu
new file mode 100644 (file)
index 0000000..7f87cc2
--- /dev/null
@@ -0,0 +1,2 @@
+?package(qstardict):needs="X11" section="Applications/Text" \
+  title="QStarDict" command="/usr/bin/qstardict" icon="/usr/share/pixmaps/qstardict.xpm"
diff --git a/debian/qstardict.1 b/debian/qstardict.1
new file mode 100644 (file)
index 0000000..0dce2bf
--- /dev/null
@@ -0,0 +1,91 @@
+.\" -*- nroff -*-
+.TH QSTARDICT 1 "November 11, 2007"
+.SH NAME
+\fBqstardict\fP \- a Qt4 dictionary
+.SH DESCRIPTION
+\fBQStarDict\fP is a StarDict clone written with Qt4. The user interface is similar to StarDict. You can start QStarDict from the menu or by running the \fBqstardict\fP command.
+.SH TRANSLATION REFORMATTING AND ABBREVIATION EXPANSION
+QStarDict can reformat translations and expand dictionary abbreviations. For example this translation:
+.PP
+.nf
+1> First _val. of _w. 2> Second _val. of _w. ...
+.PP
+can be shown as
+.PP
+.nf
+1. Fist value of word
+2. Second value of word
+3. ...
+.PP
+But reformatting and expanding takes additional CPU time. If the translation reformatting and instant search are both turned on this can decrease QStarDict performance.
+.SH DICTIONARIES
+
+Dictionaries for StarDict plugin are in \fBStarDict\fP format and by default must be placed into /usr/share/stardict/dic or ~/.stardict/dic directories. A dictionary must consist of three files:
+
+ - .dict[.dz] file - main dictionary file
+ - .idx - index file
+ - .ifo - description file
+
+These files must be placed together in one directory.
+.SH PRONOUNCING PROGRAMS
+QStarDict can pronounce words using external program when popup window is shown. You must set a voice program to pronounce text from stdin. By default this is \fBfestival\fP with \fB--tts\fP option.
+.SH D-BUS
+QStarDict supports D-Bus message bus. List of available methods:
+.PP
+.BI "void org.qstardict.dbus.showPopup(\^QString\ "text "\^)"
+.br
+.BI "void org.qstardict.dbus.showTranslation(\^QString\ "text "\^)"
+.br
+.BI "QString org.qstardict.dbus.translate(\^QString\ "text "\^)"
+.br
+.BI "QString org.qstardict.dbus.translateHtml(\^QString\ "text "\^)"
+.br
+.BI "QDBusVariant org.freedesktop.DBus.Properties.Get(\^QString\ "interface_name ", \^QString\ "property_name ")"
+.br
+.BI "void org.freedesktop.DBus.Properties.Set(\^QString\ "interface_name ", \^QString\ "property_name ", \^QDBusVariant\ "value "\^)"
+.br
+.BI "QString org.freedesktop.DBus.Introspectable.Introspect()"
+.br
+
+.PP
+List of available properties:
+.PP
+.BI "readwrite int org.qstardict.dbus.mainWindowVisible"
+
+.PP
+You can call these methods from your applications or by using the \fBqdbus\fP program.
+This command
+.PP
+.nf
+qdbus\ org.qstardict.dbus\ /qstardict\ org.qstardict.dbus.showPopup\ "text"
+.PP
+will show a QStarDict popup window with a translation of the "text".
+.PP
+If you want to show/hide QStarDict window using keyboard shortcuts you must bind the following command to a shortcut:
+.PP
+.nf
+qdbus\ org.qstardict.dbus\ /qstardict\ org.freedesktop.DBus.Properties.Set\ \\
+.br
+org.qstardict.dbus mainWindowVisible\ \\
+.br
+$(( ! $(qdbus org.qstardict.dbus\ /qstardict\ \\
+.br
+org.freedesktop.DBus.Properties.Get\ org.qstardict.dbus mainWindowVisible)))
+
+.de URL
+\\$2 \(laURL: \\$1 \(ra\\$3
+..
+.if \n[.g] .mso www.tmac
+.SH HOMEPAGE
+.URL "http://qstardict.ylsoftware.com" "QStarDict website"
+.SH AUTHOR
+\fBQStarDict\fP was written by Alexander Rodin <rodin.alexander@gmail.com>.
+.PP
+This manual page was written by Alexander Rodin <rodin.alexander@gmail.com>,
+for the Debian project (but may be used by others).
+
+.SH SEE ALSO
+.BR stardict(1)
+.BR sdcv(1)
+.BR qdbus(1)
+
diff --git a/debian/qstardict.postinst.debhelper b/debian/qstardict.postinst.debhelper
new file mode 100644 (file)
index 0000000..8637a4e
--- /dev/null
@@ -0,0 +1,5 @@
+# Automatically added by dh_installmenu
+if [ "$1" = "configure" ] && [ -x "`which update-menus 2>/dev/null`" ]; then
+       update-menus
+fi
+# End automatically added section
diff --git a/debian/qstardict.postrm.debhelper b/debian/qstardict.postrm.debhelper
new file mode 100644 (file)
index 0000000..2b4be4f
--- /dev/null
@@ -0,0 +1,3 @@
+# Automatically added by dh_installmenu
+if [ -x "`which update-menus 2>/dev/null`" ]; then update-menus ; fi
+# End automatically added section
diff --git a/debian/qstardict.substvars b/debian/qstardict.substvars
new file mode 100644 (file)
index 0000000..29aea29
--- /dev/null
@@ -0,0 +1 @@
+shlibs:Depends=libc6 (>= 2.5.0-1), libgcc1 (>= 1:4.2.1), libglib2.0-0 (>= 2.20.0), libqt4-core (>= 4.5.3~git20090723), libqt4-dbus (>= 4.5.3~git20090723), libqt4-gui (>= 4.5.3~git20090723), libqt4-network (>= 4.5.3~git20090723), libqt4-xml (>= 4.5.3~git20090723), libstdc++6 (>= 4.2.1), libx11-6, zlib1g (>= 1:1.2.1)
diff --git a/debian/qstardict.xpm b/debian/qstardict.xpm
new file mode 100644 (file)
index 0000000..a39a150
--- /dev/null
@@ -0,0 +1,365 @@
+/* XPM */
+static char * qstardict_menu_xpm[] = {
+"32 32 330 2",
+"      c None",
+".     c #202020",
+"+     c #4E4E4E",
+"@     c #4F4F4F",
+"#     c #525251",
+"$     c #7E9271",
+"%     c #7D926F",
+"&     c #7B916D",
+"*     c #7A916C",
+"=     c #778E68",
+"-     c #748D64",
+";     c #738C63",
+">     c #718B60",
+",     c #708A5F",
+"'     c #6E895D",
+")     c #6C885B",
+"!     c #698658",
+"~     c #698657",
+"{     c #688656",
+"]     c #658452",
+"^     c #648251",
+"/     c #486E30",
+"(     c #535353",
+"_     c #C0C0C0",
+":     c #C2C2C2",
+"<     c #C4C4C4",
+"[     c #C6C6C6",
+"}     c #C8C8C8",
+"|     c #C9C9C9",
+"1     c #CDCDCD",
+"2     c #CECECE",
+"3     c #D0D0D0",
+"4     c #D2D2D2",
+"5     c #D4D4D4",
+"6     c #D5D5D5",
+"7     c #D6D6D6",
+"8     c #D7D7D7",
+"9     c #D8D8D8",
+"0     c #DADADA",
+"a     c #DBDBDB",
+"b     c #DCDCDC",
+"c     c #DEDEDE",
+"d     c #DFDFDF",
+"e     c #9BA993",
+"f     c #235B00",
+"g     c #0D0D0D",
+"h     c #393939",
+"i     c #3B3B3B",
+"j     c #646F47",
+"k     c #7A955A",
+"l     c #869C53",
+"m     c #759157",
+"n     c #749155",
+"o     c #739053",
+"p     c #728F52",
+"q     c #719051",
+"r     c #73914F",
+"s     c #75924D",
+"t     c #6F8D4D",
+"u     c #6E8E4C",
+"v     c #6E8E4B",
+"w     c #6D8D4A",
+"x     c #6C8C49",
+"y     c #6C8C48",
+"z     c #61843B",
+"A     c #3F6C14",
+"B     c #010101",
+"C     c #070707",
+"D     c #040404",
+"E     c #2C4C02",
+"F     c #70A000",
+"G     c #71A000",
+"H     c #609600",
+"I     c #468600",
+"J     c #468700",
+"K     c #478700",
+"L     c #488800",
+"M     c #6C9E00",
+"N     c #4D8B00",
+"O     c #498800",
+"P     c #498900",
+"Q     c #4A8900",
+"R     c #4A8A00",
+"S     c #4B8A00",
+"T     c #4C8B02",
+"U     c #0B0B0B",
+"V     c #0A0A0A",
+"W     c #050505",
+"X     c #284A02",
+"Y     c #528E00",
+"Z     c #679B00",
+"`     c #7EA900",
+" .    c #508D00",
+"..    c #639900",
+"+.    c #4C8B00",
+"@.    c #4D8C00",
+"#.    c #020202",
+"$.    c #0F0F0F",
+"%.    c #0E0E0E",
+"&.    c #060606",
+"*.    c #080808",
+"=.    c #2A4D03",
+"-.    c #5A9300",
+";.    c #73A200",
+">.    c #669A00",
+",.    c #619800",
+"'.    c #508E00",
+").    c #4E8C00",
+"!.    c #4E8D00",
+"~.    c #030303",
+"{.    c #131313",
+"].    c #111111",
+"^.    c #2D5004",
+"/.    c #609700",
+"(.    c #80AA00",
+"_.    c #4F8D00",
+":.    c #4F8E00",
+"<.    c #181818",
+"[.    c #141414",
+"}.    c #090909",
+"|.    c #0C0C0C",
+"1.    c #2F5305",
+"2.    c #6D9F00",
+"3.    c #679C00",
+"4.    c #5D9600",
+"5.    c #528F00",
+"6.    c #518E00",
+"7.    c #518F00",
+"8.    c #1C1C1C",
+"9.    c #325606",
+"0.    c #6FA000",
+"a.    c #5E9600",
+"b.    c #529000",
+"c.    c #539000",
+"d.    c #1A1A1A",
+"e.    c #121212",
+"f.    c #345906",
+"g.    c #549000",
+"h.    c #72A300",
+"i.    c #549100",
+"j.    c #559100",
+"k.    c #242424",
+"l.    c #1D1D1D",
+"m.    c #375C06",
+"n.    c #4F8805",
+"o.    c #51860B",
+"p.    c #51870B",
+"q.    c #68940B",
+"r.    c #5F8F0B",
+"s.    c #518708",
+"t.    c #4F8A00",
+"u.    c #559200",
+"v.    c #569200",
+"w.    c #569300",
+"x.    c #282828",
+"y.    c #1F1F1F",
+"z.    c #171717",
+"A.    c #395F07",
+"B.    c #76964B",
+"C.    c #BCC4B0",
+"D.    c #F2F2F2",
+"E.    c #D7DAD2",
+"F.    c #C0C8B0",
+"G.    c #C1C8B4",
+"H.    c #CACEC5",
+"I.    c #C0CBB2",
+"J.    c #80A153",
+"K.    c #548F02",
+"L.    c #5D9700",
+"M.    c #579300",
+"N.    c #579400",
+"O.    c #589400",
+"P.    c #2C2C2C",
+"Q.    c #222222",
+"R.    c #101010",
+"S.    c #191919",
+"T.    c #3C6208",
+"U.    c #508703",
+"V.    c #A2B884",
+"W.    c #639A00",
+"X.    c #5A9102",
+"Y.    c #759940",
+"Z.    c #E1E5DB",
+"`.    c #C0CBB0",
+" +    c #598F0A",
+".+    c #599400",
+"++    c #599500",
+"@+    c #2F2F2F",
+"#+    c #3E6508",
+"$+    c #518803",
+"%+    c #A3B884",
+"&+    c #699E00",
+"*+    c #609900",
+"=+    c #5B9600",
+"-+    c #649121",
+";+    c #F2F3F1",
+">+    c #B0BF98",
+",+    c #5E9800",
+"'+    c #5A9600",
+")+    c #333333",
+"!+    c #262626",
+"~+    c #416909",
+"{+    c #528A03",
+"]+    c #A3B984",
+"^+    c #649B00",
+"/+    c #ADBF92",
+"(+    c #FBFBFA",
+"_+    c #63911C",
+":+    c #5C9700",
+"<+    c #363636",
+"[+    c #446D09",
+"}+    c #548B03",
+"|+    c #A4B984",
+"1+    c #5A9500",
+"2+    c #669C00",
+"3+    c #84A551",
+"4+    c #FFFFFF",
+"5+    c #89A859",
+"6+    c #5D9800",
+"7+    c #5E9900",
+"8+    c #383838",
+"9+    c #292929",
+"0+    c #151515",
+"a+    c #47700A",
+"b+    c #568C03",
+"c+    c #A4BA84",
+"d+    c #5B9700",
+"e+    c #699F00",
+"f+    c #7CA03A",
+"g+    c #9BB473",
+"h+    c #609A00",
+"i+    c #5F9A00",
+"j+    c #3A3A3A",
+"k+    c #2A2A2A",
+"l+    c #252525",
+"m+    c #49720A",
+"n+    c #578D03",
+"o+    c #A5BA84",
+"p+    c #689E00",
+"q+    c #7CA042",
+"r+    c #96B16A",
+"s+    c #619B00",
+"t+    c #3C3C3C",
+"u+    c #272727",
+"v+    c #4B740B",
+"w+    c #588E03",
+"x+    c #5F9900",
+"y+    c #649C00",
+"z+    c #9AB369",
+"A+    c #7FA240",
+"B+    c #629B00",
+"C+    c #629C00",
+"D+    c #639C00",
+"E+    c #3D3D3D",
+"F+    c #2B2B2B",
+"G+    c #4D750C",
+"H+    c #5A8F03",
+"I+    c #A6BB84",
+"J+    c #619A00",
+"K+    c #609802",
+"L+    c #D0D7C3",
+"M+    c #E4E7DF",
+"N+    c #629606",
+"O+    c #669E00",
+"P+    c #649D00",
+"Q+    c #3F3F3F",
+"R+    c #4F780C",
+"S+    c #5B9003",
+"T+    c #A7BB84",
+"U+    c #619A01",
+"V+    c #9BB174",
+"W+    c #F9F9F9",
+"X+    c #84A446",
+"Y+    c #659E00",
+"Z+    c #669F00",
+"`+    c #1B1B1B",
+" @    c #404040",
+".@    c #2D2D2D",
+"+@    c #50790D",
+"@@    c #619211",
+"#@    c #688E28",
+"$@    c #F3F3F3",
+"%@    c #B0BF96",
+"&@    c #6E9727",
+"*@    c #739B2F",
+"=@    c #8BAA56",
+"-@    c #C5CFB3",
+";@    c #DEE2D8",
+">@    c #7FA142",
+",@    c #69A000",
+"'@    c #679F00",
+")@    c #68A000",
+"!@    c #1E1E1E",
+"~@    c #424242",
+"{@    c #507A0E",
+"]@    c #779C3D",
+"^@    c #AABD8B",
+"/@    c #ABBE8B",
+"(@    c #A9BD88",
+"_@    c #9BB472",
+":@    c #7A9F3D",
+"<@    c #609604",
+"[@    c #639D00",
+"}@    c #313131",
+"|@    c #507A0F",
+"1@    c #5C9600",
+"2@    c #232323",
+"3@    c #434343",
+"4@    c #343434",
+"5@    c #4F7B10",
+"6@    c #444444",
+"7@    c #212121",
+"8@    c #4F7B11",
+"9@    c #5C9800",
+"0@    c #3E3E3E",
+"a@    c #323232",
+"b@    c #4C7A10",
+"c@    c #47750D",
+"d@    c #161616",
+"e@    c #42710B",
+"f@    c #366007",
+"g@    c #3E7600",
+"h@    c #3F7500",
+"i@    c #407600",
+"j@    c #407700",
+"k@    c #417700",
+"l@    c #417800",
+"m@    c #427800",
+"n@    c #437900",
+"o@    c #437800",
+"                                                                ",
+"        . + + @ # $ % & * = = - ; > , ' ) ! ~ { ] ^ /           ",
+"        ( _ : < [ } | 1 2 3 4 5 6 7 8 9 0 a b c c d e f         ",
+"        g h i i i j k l m n n o p q r s t u v w x y z A         ",
+"        B C C D D E F G H I J K K K L M N O P Q Q R S T         ",
+"        B U V D W X Y Z ` L L L L O P  ...R S S +.+.+.@.        ",
+"        #.$.%.&.*.=.L -.;.>.P Q R R S S ,.'.+.@.@.).).!.        ",
+"        ~.{.].C V ^.P Q /.(.+.S +.+.+.@._.,.).!._._.:.'.        ",
+"        D <.[.}.|.1.S S +.2.3.@.@.).).!._.4.5.'.'.6.7.7.        ",
+"        D 8.<.U $.9.N @.@.).0.'._._.'.'.'.5.a.5.5.b.c.c.        ",
+"        &.. d.|.e.f.).!._._.g.h.'.7.7.5.5.b.4.i.c.i.i.j.        ",
+"        C k.l.%.[.m.'.'.n.o.p.q.r.s.t.c.i.i.u.4.u.u.v.w.        ",
+"        *.x.y.$.z.A.7.5.B.C.D.E.F.G.H.I.J.K.v.L.M.M.N.O.        ",
+"        V P.Q.R.S.T.c.c.i.U.D.V.W.W.X.Y.Z.`. +.+L..+++++        ",
+"        |.@+k.e.8.#+i.u.u.$+D.%+M.&+*+=+-+;+>+.+,+'+'+=+        ",
+"        g )+!+{.y.~+v.w.M.{+D.]+O.,+^+W.=+/+(+_+:+,+:+L.        ",
+"        R.<+x.[.Q.[+O.O.O.}+D.|+1+'+2+,+^+3+4+5+6+*+,+7+        ",
+"        ].8+9+0+k.a+++1+'+b+D.c+d+:+:+e+,+f+4+g+7+h+i+h+        ",
+"        {.j+k+z.l+m+=+=+:+n+D.o+6+,+,+h+p+q+4+r+h+h+s+s+        ",
+"        0+t+k+<.u+v+:+6+6+w+D.o+x+x+i+h+y+z+4+A+B+C+C+D+        ",
+"        z.E+F+S.9+G+,+7+x+H+D.I+h+J+s+s+K+L+M+N+O+P+P+P+        ",
+"        S.Q+P.d.F+R+x+h+h+S+D.T+B+C+C+U+V+W+X+O+Y+O+O+Z+        ",
+"        `+ @P.`+.@+@7+x+@@#@$@%@&@*@=@-@;@>@Y+,@'@'@'@)@        ",
+"        !@~@.@8.@+{@:+6+]@^@^@^@/@(@_@:@<@D+[@P+Z+O+O+Z+        ",
+"        . ~@.@!@}@|@'+=+1@:+:+6+,+,+7+x+h+h+h+B+C+D+[@P+        ",
+"        2@3@P.y.4@5@O.O..+++1+1+=+=+:+L.6+,+,+x+i+h+J+s+        ",
+"        !+6@P.7@<+8@j.u.v.v.M.M.O.O..+1+1+'+=+:+:+9@,+7+        ",
+"        l+0@u+. a@b@5.5.c.c.c.i.i.u.u.v.w.M.O.O..+++1+'+        ",
+"        y.a@y.`+k+c@).!._. .'.'.6.7.5.5.c.c.g.i.j.u.u.w.        ",
+"        `+!+z.d@. e@Q S S S S +.+.@.).).).!._. .'.6.6.          ",
+"        R.z.g g [.f@g@h@h@h@h@h@i@j@k@k@l@l@m@m@n@n@o@          ",
+"                                                                "};
diff --git a/debian/rules b/debian/rules
new file mode 100755 (executable)
index 0000000..db6bbe3
--- /dev/null
@@ -0,0 +1,68 @@
+#!/usr/bin/make -f
+
+CFLAGS = -Wall
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+       CFLAGS += -O0
+else
+       CFLAGS += -O2
+endif
+
+configure: configure-stamp
+configure-stamp:
+       dh_testdir
+       qmake-qt4
+       touch configure-stamp
+
+build: build-stamp
+
+build-stamp: configure-stamp 
+       dh_testdir
+       $(MAKE) CFLAGS="$(CFLAGS)"
+       touch $@
+
+clean:
+       dh_testdir
+       dh_testroot
+       rm -f build-stamp configure-stamp
+       if test -f $(CURDIR)/Makefile; then \
+               $(MAKE) distclean; \
+       fi
+       if test -f $(CURDIR)/qstardict/moc_dbusadaptor.o; then \
+           rm -f $(CURDIR)/qstardict/moc_dbusadaptor.o; \
+       fi
+       if test -f $(CURDIR)/qstardict/dbusadaptor.o; then \
+           rm -f $(CURDIR)/qstardict/dbusadaptor.o; \
+       fi
+       dh_clean
+
+install:
+       dh_testdir
+       dh_testroot
+       dh_clean -k
+       dh_installdirs
+       cd $(CURDIR)/qstardict && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/qstardict install
+       cd $(CURDIR)/plugins && $(MAKE) INSTALL_ROOT=$(CURDIR)/debian/qstardict install
+       mkdir -p $(CURDIR)/debian/qstardict/usr/share/pixmaps
+       cp $(CURDIR)/debian/qstardict.xpm $(CURDIR)/debian/qstardict/usr/share/pixmaps/qstardict.xpm
+       cp $(CURDIR)/qstardict/qstardict.png $(CURDIR)/debian/qstardict/usr/share/pixmaps/qstardict.png
+       mkdir -p $(CURDIR)/debian/qstardict/usr/share/applications/hildon/
+       cp $(CURDIR)/qstardict/qstardict.desktop $(CURDIR)/debian/qstardict/usr/share/applications/hildon/qstardict.desktop
+
+binary-indep: build install
+
+binary-arch: install
+       dh_testdir
+       dh_testroot
+       dh_installmenu
+       dh_strip
+       dh_compress
+       dh_fixperms
+       dh_installdeb
+       dh_shlibdeps
+       dh_gencontrol
+       dh_md5sums
+       dh_builddeb
+
+binary: binary-indep binary-arch
+.PHONY: build clean binary-indep binary-arch binary install configure
diff --git a/debian/watch b/debian/watch
new file mode 100644 (file)
index 0000000..0b6723a
--- /dev/null
@@ -0,0 +1,2 @@
+version=3
+http://qstardict.ylsoftware.com/files/qstardict-(.*)\.tar\.bz2
diff --git a/kdeplasma/CMakeLists.txt b/kdeplasma/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c262ef4
--- /dev/null
@@ -0,0 +1,12 @@
+project(kdeplasma-qstardict)
+
+find_package(KDE4 REQUIRED)
+include (KDE4Defaults)
+include(MacroOptionalAddSubdirectory)
+
+add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
+include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})
+
+
+add_subdirectory(applet)
+add_subdirectory(dataengine)
\ No newline at end of file
diff --git a/kdeplasma/COMPILING b/kdeplasma/COMPILING
new file mode 100644 (file)
index 0000000..b9836f5
--- /dev/null
@@ -0,0 +1,3 @@
+mkdir build
+cd build
+cmakekde ..
\ No newline at end of file
diff --git a/kdeplasma/applet/CMakeLists.txt b/kdeplasma/applet/CMakeLists.txt
new file mode 100644 (file)
index 0000000..b4ff19a
--- /dev/null
@@ -0,0 +1,11 @@
+project(plasma-qstardict)
+
+set(qstardict_SRCS
+    dict.cpp)
+
+kde4_add_plugin(plasma_applet_qstardict ${qstardict_SRCS})
+target_link_libraries(plasma_applet_qstardict ${KDE4_PLASMA_LIBS} ${KDE4_KDEUI_LIBS}
+)
+
+install(TARGETS plasma_applet_qstardict DESTINATION ${PLUGIN_INSTALL_DIR})
+install(FILES plasma-qstardict-default.desktop DESTINATION ${SERVICES_INSTALL_DIR})
diff --git a/kdeplasma/applet/Messages.sh b/kdeplasma/applet/Messages.sh
new file mode 100755 (executable)
index 0000000..e4483a7
--- /dev/null
@@ -0,0 +1,2 @@
+#! /usr/bin/env bash
+$XGETTEXT *.cpp -o $podir/plasma_applet_qstardict.pot
diff --git a/kdeplasma/applet/dict.cpp b/kdeplasma/applet/dict.cpp
new file mode 100644 (file)
index 0000000..7e0a6b3
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ *   Copyright (C) 2008 Nick Shaforostoff <shaforostoff@kde.ru>
+ *
+ *   based on work by:
+ *   Copyright (C) 2007 Thomas Georgiou <TAGeorgiou@gmail.com> and Jeff Cooper <weirdsox11@gmail.com>
+ *
+ *   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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dict.h"
+
+#include <QGraphicsProxyWidget>
+#include <QGraphicsLinearLayout>
+#include <QTimer>
+// #include <QWebView>
+#include <QTextBrowser>
+
+#include <KDebug>
+#include <KIcon>
+#include <KStandardDirs>
+#include <KLineEdit>
+#include <KEditListBox>
+#include <QListView>
+#include <QTreeView>
+#include <QStringListModel>
+
+#include <KConfigDialog>
+#include <KConfigGroup>
+
+#include <Plasma/Animator>
+#include <Plasma/IconWidget>
+#include <Plasma/LineEdit>
+
+#define AUTO_DEFINE_TIMEOUT 500
+
+using namespace Plasma;
+
+
+
+const char* translationCSS =
+    "body {\n"
+        "font-size: 10pt; }\n"
+    "font.dict_name {\n"
+        "color: blue;\n"
+        "font-style: italic; }\n"
+    "font.title {\n"
+        "font-size: 16pt;\n"
+        "font-weight: bold; }\n"
+    "font.explanation {\n"
+        "color: #7f7f7f;\n"
+        "font-style: italic; }\n"
+    "font.abbreviature {\n"
+        "font-style: italic; }\n"
+    "font.example {\n"
+        "font-style: italic; }\n"
+    "font.transcription {\n"
+        "font-weight: bold; }\n";
+
+
+QStarDictApplet::QStarDictApplet(QObject *parent, const QVariantList &args)
+    : Plasma::Applet(parent, args)
+    , m_dictsModel(0)
+      //m_flash(0)
+{
+    setHasConfigurationInterface(true);
+    setAspectRatioMode(Plasma::IgnoreAspectRatio);
+    resize(500,200);
+}
+
+QStarDictApplet::~QStarDictApplet()
+{
+    m_defBrowser->deleteLater();
+}
+
+void QStarDictApplet::init()
+{
+//     KConfigGroup cg = config();
+
+    m_wordEdit = new LineEdit(this);
+    m_wordEdit->nativeWidget()->setClearButtonShown( true );
+    m_wordEdit->nativeWidget()->setClickMessage(i18n("Enter word to define here"));
+    m_wordEdit->show();
+    Plasma::Animator::self()->animateItem(m_wordEdit, Plasma::Animator::AppearAnimation);
+
+//     m_defBrowser = new QWebView();
+    m_defBrowser = new QTextBrowser();
+    m_defBrowser->document()->setDefaultStyleSheet(QLatin1String(translationCSS));
+    m_defBrowserProxy = new QGraphicsProxyWidget(this);
+    m_defBrowserProxy->setWidget(m_defBrowser);
+    m_defBrowserProxy->hide();
+//  Icon in upper-left corner
+       QString iconpath = KStandardDirs::locate("icon", "oxygen/scalable/apps/accessories-dictionary.svgz");
+    m_icon = new Plasma::IconWidget(this);
+    m_icon->setSvg(iconpath);
+
+//  Position lineedits
+    //const int wordEditOffset = 40;
+    m_icon->setPos(12,3);
+    //m_wordProxyWidget->setPos(15 + wordEditOffset,7);
+    //m_wordProxyWidget->show();
+    // TODO m_wordEdit->setDefaultTextColor(Plasma::Theme::self()->color(Plasma::Theme::TextColor));
+
+//  Timer for auto-define
+    m_timer = new QTimer(this);
+    m_timer->setInterval(AUTO_DEFINE_TIMEOUT);
+    m_timer->setSingleShot(true);
+    connect(m_timer, SIGNAL(timeout()), this, SLOT(define()));
+
+    m_horLayout = new QGraphicsLinearLayout(Qt::Horizontal);
+    m_horLayout->addItem(m_icon);
+    m_horLayout->addItem(m_wordEdit);
+    m_layout = new QGraphicsLinearLayout(Qt::Vertical);
+    m_layout->addItem(m_horLayout);
+    m_layout->addItem(m_defBrowserProxy);
+    setLayout(m_layout);
+
+    m_source.clear();
+    dataEngine("qstardict")->connectSource(m_source, this);
+    connect(m_wordEdit, SIGNAL(editingFinished()), this, SLOT(define()));
+    connect(m_wordEdit->nativeWidget(), SIGNAL(textChanged(const QString&)), this, SLOT(autoDefine(const QString&)));
+
+    dataEngine("qstardict")->connectSource("list-dictionaries", this);
+
+    //connect(m_defEdit, SIGNAL(linkActivated(const QString&)), this, SLOT(linkDefine(const QString&)));
+
+//  This is the fix for links/selecting text
+    //QGraphicsItem::GraphicsItemFlags flags = m_defEdit->flags();
+    //flags ^= QGraphicsItem::ItemIsMovable;
+   // m_defEdit->setFlags(flags);
+
+    /*m_flash = new Plasma::Flash(this);
+    m_flash->setColor(Qt::gray);
+    QFont fnt = qApp->font();
+    fnt.setBold(true);
+    m_flash->setFont(fnt);
+    m_flash->setPos(25,-10);
+    m_flash->resize(QSize(200,20));*/
+
+
+
+    KConfigGroup cg = config();
+    m_dicts = cg.readEntry("KnownDictionaries", QStringList());
+    QStringList activeDictNames = cg.readEntry("ActiveDictionaries", QStringList());
+    for (QStringList::const_iterator i = m_dicts.constBegin(); i != m_dicts.constEnd(); ++i)
+        m_activeDicts[*i]=activeDictNames.contains(*i);
+}
+
+
+void QStarDictApplet::linkDefine(const QString &text)
+{
+    kDebug() <<"ACTIVATED";
+    m_wordEdit->setText(text);
+    define();
+}
+
+void QStarDictApplet::dataUpdated(const QString& source, const Plasma::DataEngine::Data &data)
+{
+    if (source=="list-dictionaries")
+    {
+        QStringList newDicts=data["dictionaries"].toStringList();
+        bool changed=false;
+        for (QStringList::const_iterator i = newDicts.constBegin(); i != newDicts.constEnd(); ++i)
+        {
+            if (!m_dicts.contains(*i))
+            {
+                m_dicts<<*i;
+                m_activeDicts[*i]=true;
+                changed=true;
+            }
+        }
+        QStringList::iterator it = m_dicts.begin();
+        while (it != m_dicts.end())
+        {
+            if (!newDicts.contains(*it))
+            {
+                it=m_dicts.erase(it);
+                changed=true;
+            }
+            else
+                ++it;
+        }
+        if (changed)
+            configAccepted();
+//             cg.writeEntry("KnownDictionaries", m_dicts);
+
+    }
+//     Q_UNUSED(source);
+    /*if (m_flash) {
+        m_flash->kill();
+    }*/
+    if (!m_source.isEmpty()) {
+        m_defBrowserProxy->show();
+        // TODO Phase::self()->animateItem(m_defBrowserProxy, Phase::Appear);
+    }
+/*    if (data.contains("gcide")) {
+        QString defHeader;
+        m_defList = data[QString("gcide")].toString().split("<!--PAGE START-->"); //<!--DEFINITION START-->
+        for (int n = 0; n < m_defList.size(); ++n)
+        {
+            if (m_defList[n].contains("<!--DEFINITION START-->") && m_defList[n].contains("<!--PERIOD-->")) {
+                defHeader=m_defList[n];
+            } else if (m_defList[n].contains("<!--DEFINITION START-->")) {
+                defHeader=m_defList.takeAt(n);
+            }
+            if (n < m_defList.size() && !m_defList[n].contains("<!--DEFINITION START-->"))
+                m_defList[n].prepend(defHeader);
+        }
+        if (m_defList.size() > 1)
+            m_defList.removeAt(0);
+        m_i = m_defList.begin();
+        m_defEdit->setHtml(*m_i);
+        if (m_i != --m_defList.end())
+            m_rightArrow->show();
+        else
+            m_rightArrow->hide();
+        m_leftArrow->hide();
+    } */
+    if (data.contains("text")) {
+        m_defBrowser->setHtml(data[QString("text")].toString());
+//         m_defBrowser->setHtml(wnToHtml(data[QString("wn")].toString()));
+    }
+    updateGeometry();
+}
+
+void QStarDictApplet::define()
+{
+
+    if (m_timer->isActive())
+        m_timer->stop();
+
+    QString newSource=m_wordEdit->text();
+    QStringList dictsList;
+    for (QStringList::const_iterator i = m_dicts.constBegin(); i != m_dicts.constEnd(); ++i)
+        if (m_activeDicts.contains(*i) && m_activeDicts.value(*i))
+            dictsList<<*i;
+    if (!newSource.isEmpty() && !dictsList.isEmpty())
+        newSource.prepend(dictsList.join(",")+':');
+
+    if (newSource == m_source)
+        return;
+
+    dataEngine("qstardict")->disconnectSource(m_source, this);
+
+    qWarning()<<"here"<<newSource;
+
+    if (!newSource.isEmpty())
+    {   //get new definition
+        //m_flash->flash(i18n("Looking up ") + m_word);
+        m_source = newSource;
+        dataEngine("qstardict")->connectSource(m_source, this);
+        qWarning()<<"connectSource"<<m_source;
+    }
+    else
+    {    //make the definition box disappear
+        // TODO Phase::self()->animateItem(m_defBrowserProxy, Phase::Disappear);
+        m_defBrowserProxy->hide();
+    }
+
+    updateConstraints();
+}
+
+void QStarDictApplet::autoDefine(const QString &word)
+{
+    Q_UNUSED(word)
+    m_timer->start();
+}
+
+
+class CheckableStringListModel: public QStringListModel
+{
+public:
+    CheckableStringListModel(QObject* parent, const QStringList& dicts, const QHash<QString,bool>& activeDicts_)
+        : QStringListModel(parent)
+        , activeDicts(activeDicts_)
+    {
+        setStringList(dicts);
+/*        setHeaderData (0, Qt::Horizontal, "020", Qt::DisplayRole);
+        setHeaderData (0, Qt::Vertical, "020", Qt::DisplayRole);*/
+    }
+    QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const
+    {
+        if (role!=Qt::DisplayRole)
+            return QVariant();
+        return i18n("Dictionary");
+    }
+    Qt::DropActions supportedDropActions(){return Qt::MoveAction;}
+    Qt::ItemFlags flags(const QModelIndex& index) const
+    {
+        if (!index.isValid())
+            return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled;
+        return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled;
+    }
+    bool setData (const QModelIndex& index, const QVariant& value, int role=Qt::EditRole)
+    {
+        if (role==Qt::CheckStateRole)
+        {
+            activeDicts[stringList().at(index.row())]=value.toInt()==Qt::Checked;
+            return true;
+        }
+        else
+            return QStringListModel::setData(index,value,role);
+    }
+    QVariant data(const QModelIndex& index, int role=Qt::EditRole) const
+    {
+        if (!index.isValid())
+            return QVariant();
+
+        if (role==Qt::CheckStateRole)
+            return (  activeDicts.contains(stringList().at(index.row()))&&activeDicts.value(stringList().at(index.row()))  )?Qt::Checked:Qt::Unchecked;
+        return QStringListModel::data(index,role);
+    }
+
+public:
+    QHash<QString,bool> activeDicts;
+};
+
+
+void QStarDictApplet::createConfigurationInterface(KConfigDialog *parent)
+{
+//     KConfigGroup cg = config();
+
+    //QWidget *widget = new QWidget(parent);
+//     QListView* widget=new KEditListBox(i18n("Dictionaries activation and order"),
+//                            KEditListBox::CustomEditor::CustomEditor(),
+//                            parent,
+//                            "dict-order",
+//                            false,
+//                            KEditListBox::UpDown);
+//     QListView* widget=new QListView(parent);
+    QTreeView* widget=new QTreeView(parent);
+    widget->setDragEnabled(true);
+    widget->setAcceptDrops(true);
+//     widget->viewposrt()->setAcceptDrops(true);
+    widget->setDragDropMode(QAbstractItemView::InternalMove);
+    widget->setDropIndicatorShown(true);
+    widget->setItemsExpandable(false);
+    widget->setAllColumnsShowFocus(true);
+    widget->setRootIsDecorated(false);
+
+    delete m_dictsModel;
+    m_dictsModel=new CheckableStringListModel(parent,m_dicts,m_activeDicts);
+    widget->setModel(m_dictsModel);
+
+//     parent->setButtons( KDialog::Ok | KDialog::Cancel | KDialog::Apply );
+    parent->addPage(widget, parent->windowTitle(), Applet::icon());
+    connect(parent, SIGNAL(applyClicked()), this, SLOT(configAccepted()));
+    connect(parent, SIGNAL(okClicked()), this, SLOT(configAccepted()));
+}
+
+void QStarDictApplet::configAccepted()
+{
+    if (m_dictsModel)
+    {
+        m_dicts=m_dictsModel->stringList();
+        m_activeDicts=m_dictsModel->activeDicts;
+    }
+    KConfigGroup cg = config();
+    cg.writeEntry("KnownDictionaries", m_dicts);
+
+    QStringList activeDictNames;
+    for (QStringList::const_iterator i = m_dicts.constBegin(); i != m_dicts.constEnd(); ++i)
+        if (m_activeDicts.contains(*i) && m_activeDicts.value(*i))
+            activeDictNames<<*i;
+
+    cg.writeEntry("ActiveDictionaries", activeDictNames);
+
+    define();
+    emit configNeedsSaving();
+}
+
+#include "dict.moc"
diff --git a/kdeplasma/applet/dict.h b/kdeplasma/applet/dict.h
new file mode 100644 (file)
index 0000000..89a553b
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *   Copyright (C) 2008 Nick Shaforostoff <shaforostoff@kde.ru>
+ *
+ *   based on work by:
+ *   Copyright (C) 2007 Thomas Georgiou <TAGeorgiou@gmail.com> and Jeff Cooper <weirdsox11@gmail.com>
+ *
+ *   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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DICT_H
+#define DICT_H
+
+#include <Plasma/Applet>
+#include <Plasma/DataEngine>
+
+class QTimer;
+class CheckableStringListModel;
+
+class QTextBrowser;
+class QGraphicsProxyWidget;
+class QGraphicsLinearLayout;
+
+namespace Plasma
+{
+    class IconWidget;
+    class LineEdit;
+}
+
+class QStarDictApplet: public Plasma::Applet
+{
+    Q_OBJECT
+    public:
+        QStarDictApplet(QObject *parent, const QVariantList &args);
+        ~QStarDictApplet();
+
+    void init();
+        void setPath(const QString&);
+
+    public slots:
+        void dataUpdated(const QString &name, const Plasma::DataEngine::Data &data);
+        void autoDefine(const QString &word);
+        void linkDefine(const QString &word);
+
+    protected slots:
+        void define();
+        void configAccepted();
+
+    protected:
+        void createConfigurationInterface(KConfigDialog *parent);
+
+    private:
+        QString m_source;
+        QTimer* m_timer;
+        //QGraphicsPixmapItem *m_graphicsIcon;
+        QGraphicsLinearLayout *m_layout;
+        QGraphicsLinearLayout *m_horLayout;
+        Plasma::LineEdit *m_wordEdit;
+        //Plasma::Flash *m_flash;
+        QStringList m_defList;
+        QStringList::iterator m_i;
+        QTextBrowser* m_defBrowser;
+        QGraphicsProxyWidget *m_defBrowserProxy;
+        Plasma::IconWidget *m_icon;
+
+//         QList< QPair<QString, bool> > m_dicts;
+        QPointer<CheckableStringListModel> m_dictsModel;
+        QStringList m_dicts;
+        QHash<QString,bool> m_activeDicts;
+};
+
+K_EXPORT_PLASMA_APPLET(qstardict, QStarDictApplet)
+
+#endif
diff --git a/kdeplasma/applet/plasma-qstardict-default.desktop b/kdeplasma/applet/plasma-qstardict-default.desktop
new file mode 100644 (file)
index 0000000..b65f1bd
--- /dev/null
@@ -0,0 +1,94 @@
+[Desktop Entry]
+Name=QStarDict Dictionary
+Name[ca]=QStarDict Diccionari
+Name[cs]=QStarDict Slovník
+Name[csb]=QStarDict Slowôrz
+Name[da]=QStarDict Ordbog
+Name[de]=QStarDict Wörterbuch
+Name[el]=QStarDict Λεξικό
+Name[es]=QStarDict Diccionario
+Name[et]=QStarDict Sõnaraamat
+Name[fi]=QStarDict Sanakirja
+Name[fr]=QStarDict Dictionnaire
+Name[ga]=QStarDict Foclóir
+Name[gl]=QStarDict Dicionario
+Name[hu]=QStarDict Szótár
+Name[it]=QStarDict Dizionario
+Name[ja]=QStarDict 辞書
+Name[km]=QStarDict វចនានុក្រម
+Name[ko]=QStarDict 사전
+Name[lv]=QStarDict Vārdnīca
+Name[ms]=QStarDict Kamus
+Name[nds]=QStarDict Wöörbook
+Name[nl]=QStarDict Woordenboek
+Name[nn]=QStarDict Ordbok
+Name[oc]=QStarDict Diccionari
+Name[pa]=QStarDict ਡਿਕਸ਼ਨਰੀ
+Name[pl]=QStarDict Słownik
+Name[pt]=QStarDict Dicionário
+Name[pt_BR]=QStarDict Dicionário
+Name[ro]=QStarDict Dicționar
+Name[ru]=Словарь QStarDict
+Name[sl]=QStarDict Slovar
+Name[sr]=QStarDict речник
+Name[sr@latin]=QStarDict rečnik
+Name[sv]=QStarDict Ordlista
+Name[th]=QStarDict พจนานุกรม
+Name[tr]=QStarDict Sözlük
+Name[uk]=Словник QStarDict
+Name[wa]=QStarDict Motî
+Name[x-test]=xxQStarDict Dictionaryxx
+Name[zh_CN]=QStarDict 词典
+Name[zh_TW]=QStarDict 字典
+Comment=Look up the meaning of words
+Comment[ca]=Cerca el significat de les paraules
+Comment[cs]=Vyhledat význam slov
+Comment[csb]=Szëkôj za znaczeniama słów
+Comment[da]=Slå ords betydning op
+Comment[de]=Die Bedeutung von Wörtern nachschlagen
+Comment[el]=Αναζήτηση σημασίας λέξεων
+Comment[es]=Busca el significado de las palabras
+Comment[et]=Sõnade tähenduse otsimine
+Comment[fi]=Etsi sanojen merkityksiä
+Comment[fr]=Recherche la signification d'un mot
+Comment[ga]=Aimsigh sainmhíniú ar fhocal
+Comment[gl]=Procura o significado de palabras
+Comment[hu]=Angol nyelvű értelmező szótár
+Comment[it]=Cerca il significato delle parole
+Comment[ja]=単語の意味を調べます
+Comment[km]=រក​មើល​អត្ថន័យ​របស់​ពាក្យ
+Comment[ko]=단어의 뜻을 찾습니다
+Comment[lv]=Uzmeklē vārdu nozīmes
+Comment[nds]=Kiekt de Bedüden vun Wöör na
+Comment[nl]=Zoek de betekenis van woorden op
+Comment[nn]=Slå opp tydinga til ord
+Comment[pa]=ਸ਼ਬਦਾਂ ਦੇ ਅਰਥ ਵੇਖੋ
+Comment[pl]=Szukanie znaczeń słów
+Comment[pt]=Procurar o significado das palavras
+Comment[pt_BR]=Procurar o significado das palavras
+Comment[ro]=Caută semnificația cuvintelor
+Comment[sl]=Poiščite pomen besed
+Comment[sr]=Потражите значења речи
+Comment[sr@latin]=Potražite značenja reči
+Comment[sv]=Slå upp ords betydelse
+Comment[th]=ค้นหาความหมายของคำ
+Comment[tr]=Sözcüklerin anlamlarına hızlı ulaşmak için
+Comment[uk]=Погляньте на значення слів
+Comment[wa]=Cache après çou k' volèt dire les mots
+Comment[x-test]=xxLook up the meaning of wordsxx
+Comment[zh_CN]=查找词义
+Comment[zh_TW]=查看單字的意義
+Type=Service
+Icon=accessories-dictionary
+
+X-KDE-ServiceTypes=Plasma/Applet
+X-KDE-Library=plasma_applet_qstardict
+X-KDE-PluginInfo-Author=Nick Shaforostoff
+X-KDE-PluginInfo-Email=shaforostoff@kde.ru
+X-KDE-PluginInfo-Name=qstardict
+X-KDE-PluginInfo-Version=pre0.1
+X-KDE-PluginInfo-Website=http://youonlylivetwice.info/
+X-KDE-PluginInfo-Category=Language
+X-KDE-PluginInfo-Depends=
+X-KDE-PluginInfo-License=GPL
+X-KDE-PluginInfo-EnabledByDefault=true
diff --git a/kdeplasma/dataengine/CMakeLists.txt b/kdeplasma/dataengine/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2efd9b9
--- /dev/null
@@ -0,0 +1,24 @@
+project(plasma-qstardictengine)
+
+INCLUDE_DIRECTORIES(
+       ${CMAKE_CURRENT_SOURCE_DIR}/../../plugins)
+
+
+set(qstardict_engine_SRCS
+    dictengine.cpp
+)
+
+kde4_add_plugin(plasma_engine_qstardict ${qstardict_engine_SRCS})
+target_link_libraries(plasma_engine_qstardict
+${KDE4_KDECORE_LIBS}
+${KDE4_PLASMA_LIBS}
+)
+
+set(QSTARDICT_PLUGINS_DIR ${LIB_INSTALL_DIR}/qstardict/plugins)
+
+configure_file(config.h.cmake config.h)
+
+
+install(TARGETS plasma_engine_qstardict DESTINATION ${PLUGIN_INSTALL_DIR})
+install(FILES plasma-dataengine-qstardict.desktop DESTINATION ${SERVICES_INSTALL_DIR} )
+
diff --git a/kdeplasma/dataengine/Messages.sh b/kdeplasma/dataengine/Messages.sh
new file mode 100755 (executable)
index 0000000..29218d3
--- /dev/null
@@ -0,0 +1,2 @@
+#! /usr/bin/env bash
+$XGETTEXT *.cpp -o $podir/plasma_engine_dict.pot
diff --git a/kdeplasma/dataengine/config.h.cmake b/kdeplasma/dataengine/config.h.cmake
new file mode 100644 (file)
index 0000000..4384bbf
--- /dev/null
@@ -0,0 +1,4 @@
+
+//#define QSTARDICT_PLUGINS_DIR "${QSTARDICT_PLUGINS_DIR}"
+
+#define QSTARDICT_PLUGINS_DIR "/usr/lib/qstardict/plugins"
diff --git a/kdeplasma/dataengine/dictengine.cpp b/kdeplasma/dataengine/dictengine.cpp
new file mode 100644 (file)
index 0000000..2e9afb5
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ *   Copyright (C) 2008 Nick Shaforostoff <shaforostoff@kde.ru>
+ *
+ *   based on work by:
+ *   Copyright (C) 2007 Thomas Georgiou <TAGeorgiou@gmail.com> and Jeff Cooper <weirdsox11@gmail.com>
+ *
+ *   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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "dictengine.h"
+#include "dictplugin.h"
+#include "config.h"
+
+#include <QPluginLoader>
+#include <QPointer>
+#include <QMap>
+#include <QTimer>
+#include <QTime>
+#include <QSettings>
+#include <KDebug>
+// #include <KLocale>
+
+#include <Plasma/DataContainer>
+
+#define MEMORYFREE_DELAY 60000
+
+
+/**
+ * This class represents a dictionary provided by a plugin
+ */
+class Dictionary
+{
+    public:
+        Dictionary(const QString &plugin, const QString &name)
+            : m_plugin(plugin)
+            , m_name(name)
+        {}
+        Dictionary()
+        {}
+
+        const QString &plugin() const {return m_plugin;}
+        const QString &name() const {return m_name;}
+        void setPlugin(const QString &plugin) {m_plugin=plugin;}
+        void setName(const QString &name) {m_name=name;}
+        bool operator == (const Dictionary &dict) {return m_name==dict.m_name && m_plugin==dict.m_plugin;}
+
+    private:
+        QString m_plugin;
+        QString m_name;
+};
+
+
+struct QStarDictEngine::Private
+{
+    QString currentWord;
+    QTimer timer;
+
+    QHash<QString, QPointer<QPluginLoader> > plugins; //name to pointer
+//     QList<Dictionary> dicts;
+//     QHash<QString, QString> dictToPlugin; //name to metastructure
+    QHash<QString, Dictionary> dicts; //name to metastructure
+
+};
+
+
+
+
+
+
+QStarDictEngine::QStarDictEngine(QObject* parent, const QVariantList& args)
+    : Plasma::DataEngine(parent, args)
+    , d(new Private)
+{
+    Q_UNUSED(args)
+//     QTime a;a.start();
+#ifdef Q_OS_WIN
+    QFileInfoList files = QDir(QSTARDICT_PLUGINS_DIR).entryInfoList(QStringList("*0.dll"),QDir::Files|QDir::NoDotAndDotDot);
+    for (QFileInfoList::const_iterator i = files.begin(); i != files.end(); ++i)
+        d->plugins[i->fileName().left(i->fileName().length()-5))]=0;
+#else
+    qWarning()<<QSTARDICT_PLUGINS_DIR;
+    QFileInfoList files = QDir(QSTARDICT_PLUGINS_DIR).entryInfoList(QStringList("lib*.so"),QDir::Files|QDir::NoDotAndDotDot);
+    for (QFileInfoList::const_iterator i = files.begin(); i != files.end(); ++i)
+        d->plugins[i->fileName().mid(3, i->fileName().length()-6)]=0;
+#endif
+
+
+
+    // use cache to not load redudant plugins? 16->10 ms
+//     QSettings settings("qstardict","qstardict");
+//     m_dictDirs = settings.value("Multitran/dictDirs", m_dictDirs).toStringList();
+
+    d->timer.setInterval(MEMORYFREE_DELAY);
+    d->timer.setSingleShot(true);
+    connect(&d->timer, SIGNAL(timeout()), this, SLOT(unloadPlugins()));
+
+
+    QList<QString> plugins=d->plugins.keys();
+    for (QList<QString>::const_iterator i = plugins.constBegin(); i != plugins.constEnd(); ++i)
+    {
+//         QStringList dicts = settings.value(*i+"/dicts", QStringList()).toStringList();
+//         if (!dicts.isEmpty())
+//         {
+            QStarDict::DictPlugin* plugin = dictPlugin(*i);
+            if (!plugin)
+                continue;
+            QStringList dicts=plugin->availableDicts();
+//             settings.setValue(*i+"/dicts", QVariant(dicts));
+//            plugin->setdicts(dicts);
+//         }
+        for (QStringList::const_iterator j = dicts.constBegin(); j != dicts.constEnd(); ++j)
+            d->dicts[*j]=Dictionary(*i, *j);
+//             d->dicts<<Dictionary(*i, *j);
+    }
+//     qWarning()<<a.elapsed();
+
+}
+
+QStarDictEngine::~QStarDictEngine()
+{
+    unloadPlugins();
+    delete d;
+}
+
+
+
+QStarDict::DictPlugin* QStarDictEngine::dictPlugin(const QString &name)
+{
+    if (! d->plugins.contains(name) )
+        return 0;
+    if (! d->plugins.value(name) )
+    {
+#ifdef Q_OS_WIN
+        QString pluginFilename = QSTARDICT_PLUGINS_DIR "/" + name + "0.dll";
+#else 
+        QString pluginFilename = QSTARDICT_PLUGINS_DIR "/" "lib" + name + ".so";
+#endif
+        QPluginLoader* plugin = new QPluginLoader(pluginFilename);
+        if (! plugin->load())
+        {
+            kWarning() << plugin->errorString();
+            delete plugin;
+            return 0;
+        }
+        d->plugins[name]=plugin;
+    }
+
+    return qobject_cast<QStarDict::DictPlugin*>(d->plugins.value(name)->instance());
+}
+
+void QStarDictEngine::unloadPlugins()
+{
+    for (QHash<QString, QPointer<QPluginLoader> >::iterator i = d->plugins.begin(); i != d->plugins.end(); ++i)
+    {
+        if (*i)
+        {
+            (*i)->instance()->deleteLater();
+            (*i)->deleteLater();
+        }
+    }
+
+}
+
+bool QStarDictEngine::sourceRequestEvent(const QString &word)
+{
+    qWarning()<<"sourceRequestEvent"<<word;
+    d->timer.start();//delay freeing resources / activate delayed resources freeing
+
+    if (word=="list-dictionaries")
+    {
+        QStringList result;
+        int i=d->plugins.keys().size();
+        while (--i>=0)
+        {
+            QStarDict::DictPlugin* plugin = dictPlugin(d->plugins.keys().at(i));
+            if (!plugin)
+                continue;
+            result << plugin->availableDicts();
+        }
+        setData("list-dictionaries", "dictionaries", result);
+        qWarning()<<result;
+        return true;
+    }
+
+    QString simplifiedWord;
+    QStringList queriedDicts;
+    int pos=word.indexOf(':');
+    if (pos!=-1)
+    {
+        queriedDicts=word.left(pos).split(',');
+        simplifiedWord=word.mid(pos+1).simplified();
+    }
+    else
+        simplifiedWord=word.simplified();
+    qWarning()<<"simplifiedWord"<<simplifiedWord;
+    qWarning()<<"queriedDicts"<<queriedDicts;
+
+    if (queriedDicts.isEmpty())
+        for (QHash<QString,Dictionary>::const_iterator i = d->dicts.constBegin(); i != d->dicts.constEnd(); ++i)
+            queriedDicts<<i->name();
+
+    d->currentWord = word;
+    QString result;
+
+    if (simplifiedWord.length() == 0)
+    {
+        setData(d->currentWord, "text", QString());
+        return true;
+    }
+
+    for (QStringList::const_iterator i = queriedDicts.constBegin(); i != queriedDicts.constEnd(); ++i)
+    {
+        if (!d->dicts.contains(*i))
+            continue;
+        QStarDict::DictPlugin* plugin = dictPlugin(d->dicts.value(*i).plugin());
+        if (!plugin)
+            continue;
+        QStringList ld=plugin->loadedDicts();
+        if (!ld.contains(*i))
+            plugin->setLoadedDicts(ld<<*i);
+        if ( !plugin->isTranslatable(*i, simplifiedWord))
+            continue;
+        QStarDict::DictPlugin::Translation translation = plugin->translate(*i, simplifiedWord);
+        if (translation.translation().isEmpty())
+            continue;
+        result += "<p>\n"
+            "<font class=\"dict_name\">" + translation.dictName() + "</font><br>\n"
+            "<font class=\"title\">" + translation.title() + "</font><br>\n"
+            + translation.translation() + "</p>\n";
+    }
+
+    setData(d->currentWord, "text", result);
+    return true;
+}
+
+
+
+
+
+#include "dictengine.moc"
diff --git a/kdeplasma/dataengine/dictengine.h b/kdeplasma/dataengine/dictengine.h
new file mode 100644 (file)
index 0000000..7f0f012
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ *   Copyright (C) 2008 Nick Shaforostoff <shaforostoff@kde.ru>
+ *
+ *   based on work by:
+ *   Copyright (C) 2007 Thomas Georgiou <TAGeorgiou@gmail.com> and Jeff Cooper <weirdsox11@gmail.com>
+ *
+ *   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, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef DICTENGINE_H
+#define DICTENGINE_H
+#include <Plasma/DataEngine>
+#include <QString>
+#include <QList>
+namespace QStarDict {class DictPlugin;}
+
+/**
+ * This class evaluates the basic expressions given in the interface.
+ */
+
+
+class QStarDictEngine : public Plasma::DataEngine
+{
+    Q_OBJECT
+
+    public:
+        QStarDictEngine(QObject* parent, const QVariantList& args );
+        ~QStarDictEngine();
+
+    protected:
+        bool sourceRequestEvent(const QString &word);
+    private:
+        /**
+         * also loads plugin if it's not loaded
+         */
+        QStarDict::DictPlugin* dictPlugin(const QString &name);
+
+    private slots:
+        void unloadPlugins();
+    private:
+        class Private;
+        Private * const d;
+};
+
+K_EXPORT_PLASMA_DATAENGINE(qstardict, QStarDictEngine)
+
+#endif
diff --git a/kdeplasma/dataengine/plasma-dataengine-qstardict.desktop b/kdeplasma/dataengine/plasma-dataengine-qstardict.desktop
new file mode 100644 (file)
index 0000000..5a9a439
--- /dev/null
@@ -0,0 +1,92 @@
+[Desktop Entry]
+Name=QStarDict Dictionary
+Name[be@latin]=QStarDict Słoŭnik
+Name[el]=QStarDict Λεξικό
+Name[gl]=QStarDict Dicionario
+Name[gu]=QStarDict ડિક્શનરી
+Name[he]=QStarDict מילון
+Name[kk]=QStarDict Сөздік
+Name[km]=QStarDict វចនានុក្រម
+Name[kn]=QStarDict ಶಬ್ದಕೋಶ 
+Name[nb]=QStarDict Ordbok
+Name[nds]=QStarDict Wöörbook
+Name[pa]=QStarDict ਡਿਕਸ਼ਨਰੀ
+Name[pt]=QStarDict Dicionário
+Name[pt_BR]=QStarDict Dicionário
+Name[ro]=QStarDict Dicționar
+Name[ru]=Словарь QStarDict
+Name[sv]=QStarDict Ordlista
+Name[tr]=QStarDict Sözlük
+Name[uk]=Словник QStarDict
+Name[x-test]=xxQStarDict Dictionaryxx
+Name[zh_TW]=QStarDict 字典
+Comment=Look up word meanings
+Comment[af]=Slaan woordbetekenisse na
+Comment[be@latin]=Pošuk značeńniaŭ słovaŭ
+Comment[bg]=Търсене на думи
+Comment[bn_IN]=শব্দের অর্থ অনুসন্ধান করুন
+Comment[ca]=Cerca els significats de paraules
+Comment[cs]=Vyhledávání významu slov
+Comment[da]=Slå ords betydning op
+Comment[de]=Nachschlagen von Wortbedeutungen
+Comment[el]=Αναζήτηση σημασίας λέξεων
+Comment[eo]=Serĉi difinojn de vortoj
+Comment[es]=Buscar significado de las palabras
+Comment[et]=Sõna tähenduse otsimine
+Comment[fi]=Tarkista sanojen merkityksiä
+Comment[fr]=Connaître la signification des mots
+Comment[fy]=Sykje de wurdbetekenissen op
+Comment[ga]=Aimsigh sainmhíniú ar fhocal
+Comment[gl]=Procura o significado de palabras
+Comment[gu]=શબ્દનાં અર્થો શોધો
+Comment[he]=בדיקת משמעות מלה
+Comment[hu]=Értelmező szótár
+Comment[is]=Flettu upp merkingu orða
+Comment[it]=Cerca il significato di una parola
+Comment[ja]=単語の意味を調べる
+Comment[kk]=Сөздің мәнін қарастыру
+Comment[km]=រក​មើល​អត្ថន័យ​របស់​ពាក្យ
+Comment[kn]=ಪದಗಳ ಅರ್ಥಗಳಿಗನ್ನು ಹುಡುಕು
+Comment[ko]=단어의 뜻 찾기
+Comment[lv]=Atrod vārdu nozīmes
+Comment[ml]=വാക്കുകളുടെ അര്‍ത്ഥങ്ങള്‍ നിഘണ്ടുവില്‍ തിരയുക 
+Comment[mr]=शब्दांचे अर्थ शोधण्याकरीता लुकअप
+Comment[nb]=Slå opp betydningen av ord
+Comment[nds]=Woortbedüden naslaan
+Comment[ne]=शब्दको अर्थ हेर्नुहोस्
+Comment[nl]=Zoek de betekenis van woorden op
+Comment[nn]=Slå opp tydinga til ord
+Comment[pa]=ਸ਼ਬਦ ਅਰਥ ਖੋਜ
+Comment[pl]=Wyszukiwanie znaczenia słów
+Comment[pt]=Procurar os significados das palavras
+Comment[pt_BR]=Procurar os significados das palavras
+Comment[ro]=Caută înțelesul cuvintelor
+Comment[ru]=Выяснение значения слов
+Comment[se]=Oza maid sátni máksá
+Comment[sl]=Poiščite pomene besed
+Comment[sr]=Потражите значења речи
+Comment[sr@latin]=Potražite značenja reči
+Comment[sv]=Slå upp ords betydelse
+Comment[te]=పదము అర్ధాలను చూడుము
+Comment[th]=ค้นหาความหมายของคำ
+Comment[tr]=Sözcük anlamlarına bak
+Comment[uk]=Пошук значень слів
+Comment[wa]=Cweri çou k' vout dire on mot
+Comment[x-test]=xxLook up word meaningsxx
+Comment[zh_CN]=查阅单词含义
+Comment[zh_TW]=尋找單字的意義
+X-KDE-ServiceTypes=Plasma/DataEngine
+Type=Service
+Icon=accessories-dictionary
+X-KDE-Library=plasma_engine_qstardict
+
+X-KDE-PluginInfo-Author=Nick Shaforostoff
+X-KDE-PluginInfo-Email=shaforostoff@kde.ru
+X-KDE-PluginInfo-Name=qstardict
+X-KDE-PluginInfo-Version=0.1
+X-KDE-PluginInfo-Website=
+X-KDE-PluginInfo-Category=
+X-KDE-PluginInfo-Depends=
+X-KDE-PluginInfo-License=
+
+
diff --git a/plugins/dictplugin.h b/plugins/dictplugin.h
new file mode 100644 (file)
index 0000000..b7d733f
--- /dev/null
@@ -0,0 +1,294 @@
+/*****************************************************************************
+ * dictplugin.h - QStarDict, a StarDict clone written using Qt               *
+ * Copyright (C) 2008 Alexander Rodin                                        *
+ *                                                                           *
+ * 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 DICTPLUGIN_H
+#define DICTPLUGIN_H
+
+#include <QtPlugin>
+#include <QStringList>
+#include <QDir>
+#include <QCoreApplication>
+#include <QVariant>
+
+namespace QStarDict
+{
+
+/**
+ * This is a base class for all dictionary plugins classes.
+ */
+class DictPlugin
+{
+    public:
+        /**
+         * This enum describes a features of dictionary plugin.
+         */
+        enum Feature
+        {
+            /**
+             * No features.
+             */
+            None          = 0x00,
+            /**
+             * Dictionary plugin can search for similar words using
+             * fuzzy algoritms.
+             */
+            SearchSimilar = 0x01,
+            /**
+             * Dictionary plugin has a settings dialog.
+             */
+            SettingsDialog = 0x02,
+        };
+        Q_DECLARE_FLAGS(Features, Feature)
+
+        /**
+         * This class represents information about dictionary.
+         */
+        class DictInfo
+        {
+            public:
+                /**
+                 * Construct empty DictInfo object.
+                 */
+                DictInfo()
+                    : m_wordsCount(-1L)
+                { }
+                /**
+                 * Construct DictInfo object from data.
+                 * @param plugin A plugin name
+                 * @param name A dictionary name
+                 * @param author A dictionary author
+                 * @param desription A dictionary description
+                 * @param wordsCount A count of words that available in dictionary
+                 */
+                DictInfo(const QString &plugin,
+                         const QString &name,
+                         const QString &author = QString(),
+                         const QString &description = QString(),
+                         long wordsCount = -1L)
+                    : m_plugin(plugin),
+                      m_name(name),
+                      m_author(author),
+                      m_description(description),
+                      m_wordsCount(wordsCount)
+                { }
+
+                const QString &plugin() const
+                { return m_plugin; }
+                const QString &name() const
+                { return m_name; }
+                const QString &author() const
+                { return m_author; }
+                const QString &description() const
+                { return m_description; }
+                long wordsCount() const
+                { return m_wordsCount; }
+
+                void setPlugin(const QString &plugin)
+                { m_plugin = plugin; }
+                void setName(const QString &name)
+                { m_name = name; }
+                void setAuthor(const QString &author)
+                { m_author = author; }
+                void setDescription(const QString &description)
+                { m_description = description; }
+                void setWordsCount(long wordsCount)
+                { m_wordsCount = wordsCount; }
+
+            private:
+                QString m_plugin;
+                QString m_name;
+                QString m_author;
+                QString m_description;
+                long m_wordsCount;
+        };
+
+        /**
+         * This class represent a translation.
+         */
+        class Translation
+        {
+            public:
+                /**
+                 * Construct an empty translation.
+                 */
+                Translation()
+                { }
+
+                /**
+                 * Construct a translation from data.
+                 * @param title A translation title
+                 * @param dictName A full dictionary name
+                 * @param translation A translation
+                 */
+                Translation(const QString &title,
+                        const QString &dictName,
+                        const QString &translation)
+                    : m_title(title),
+                      m_dictName(dictName),
+                      m_translation(translation)
+                { }
+
+                /**
+                 * Return the translation title.
+                 */
+                const QString &title() const
+                { return m_title; }
+
+                /**
+                 * Return the dictionary name.
+                 */
+                const QString &dictName() const
+                { return m_dictName; }
+
+                /**
+                 * Return the translation.
+                 */
+                const QString &translation() const
+                { return m_translation; }
+
+                /**
+                 * Set a translation title.
+                 */
+                void setTitle(const QString &title)
+                { m_title = title; }
+
+                /**
+                 * Set a dictionary name.
+                 */
+                void setDictName(const QString &dictName)
+                { m_dictName = dictName; }
+
+                /**
+                 * Set a translation.
+                 */
+                void setTranslation(const QString &translation)
+                { m_translation = translation; }
+
+            private:
+                QString m_title;
+                QString m_dictName;
+                QString m_translation;
+        };
+
+        /**
+         * Destructor.
+         */
+        virtual ~DictPlugin() { }
+
+        /**
+         * Return the plugin name.
+         */
+        virtual QString name() const = 0;
+
+        /**
+         * Return the plugin version.
+         */
+        virtual QString version() const = 0;
+
+        /**
+         * Return the plugin description.
+         */
+        virtual QString description() const = 0;
+
+        /**
+         * Return the plugin authors.
+         */
+        virtual QStringList authors() const = 0;
+
+        /**
+         * Return a features supported by dictionary plugin.
+         */
+        virtual Features features() const
+        { return Features(None); }
+
+        /**
+         * Return a list of available dictionaries.
+         */
+        virtual QStringList availableDicts() const = 0;
+
+        /**
+         * Return a list of loaded dictionaries.
+         */
+        virtual QStringList loadedDicts() const = 0;
+
+        /**
+         * Set a list of loaded dictionaries.
+         */
+        virtual void setLoadedDicts(const QStringList &loadedDicts) = 0;
+
+        /**
+         * Return true if translation exists in dictionary,
+         * otherwise returns false.
+         */
+        virtual bool isTranslatable(const QString &dict, const QString &word) = 0;
+        /**
+         * Return translation for word from dictionary. If word not found
+         * returns empty string.
+         */
+        virtual Translation translate(const QString &dict, const QString &word) = 0;
+        /**
+         * Return a list of similar to "word" words from all loaded dictionaries.
+         * Works only if SearchSimilar feature is enabled.
+         */
+        virtual QStringList findSimilarWords(const QString &dict, const QString &word)
+        { Q_UNUSED(dict); return QStringList(word); }
+        
+        /**
+         * Return a required resource. Scheme of URLs:
+         *   plugin://plugin_name/...
+         */
+        virtual QVariant resource(int type, const QUrl &name)
+        { Q_UNUSED(type) Q_UNUSED(name) return QVariant(); }
+
+        /**
+         * Return an information about dictionary. The dictionary may be not loaded
+         * but available.
+         */
+        virtual DictInfo dictInfo(const QString &dict) = 0;
+
+        /**
+         * Run a settings dialog and return QDialog::DialogCode.
+         */
+        virtual int execSettingsDialog(QWidget *parent = 0)
+        { Q_UNUSED(parent); return 0; }
+
+    protected:
+        /**
+         * Return a directory that contains plugin's data.
+         */
+        QString workPath() const
+        {
+            QString path = QDir::homePath() + "/.config/qstardict/pluginsdata/" + name();
+
+            if (! QDir::root().exists(path))
+                QDir::root().mkpath(path);
+            return path;
+        }
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(DictPlugin::Features)
+
+}
+
+Q_DECLARE_INTERFACE(QStarDict::DictPlugin, "org.qstardict.DictPlugin/1.0")
+
+#endif // DICTPLUGIN_H
+
+// vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab cindent
+
diff --git a/plugins/multitran/README b/plugins/multitran/README
new file mode 100644 (file)
index 0000000..dd93577
--- /dev/null
@@ -0,0 +1,27 @@
+You need the following external libraries to compile the plugin:
+libmtsupport
+libbtree
+libfacet
+libmtquery
+
+
+FILE=libmtsupport-0.0.1alpha2
+wget http://youonlylivetwice.info/multitran/$FILE.7z && 7z x $FILE.7z && cd $FILE && make && sudo make install
+
+FILE=libbtree-0.0.1alpha2
+wget http://youonlylivetwice.info/multitran/$FILE.7z && 7z x $FILE.7z && cd $FILE && make && sudo make install
+
+FILE=libfacet-0.0.1alpha2
+wget http://youonlylivetwice.info/multitran/$FILE.7z && 7z x $FILE.7z && cd $FILE && make && sudo make install
+
+FILE=libmtquery-0.0.1alpha3-shaforostoff
+wget http://youonlylivetwice.info/multitran/$FILE.7z && 7z x $FILE.7z && cd $FILE && make && sudo make install
+
+Then put this dir into qstardict/plugins and run qmake && make && sudo make install
+
+
+
+Download multitran-data.tar.bz2 from multitran.sf.net
+tar xjf multitran-data.tar.bz2 && cd multitran-data && make && sudo make install
+
+See multitran.sf.net and multitran.ru for details
\ No newline at end of file
diff --git a/plugins/multitran/multitran.cpp b/plugins/multitran/multitran.cpp
new file mode 100644 (file)
index 0000000..bfb5dee
--- /dev/null
@@ -0,0 +1,252 @@
+/*****************************************************************************
+ * This file is a part of QStarDict, a StarDict clone written using Qt       *
+ * multitran.cpp - Plugin for multitran-data (multitran.sf.net)              *
+ * Copyright (C) 2008 Nick Shaforostoff                                      *
+ * Copyright (C) 2004 Stanislav Ievlev                                       *
+ *                                                                           *
+ * 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 "multitran.h"
+//#include "settingsdialog.h"
+
+#include <QCoreApplication>
+// #include <QSettings>
+#include <QTextCodec>
+
+
+/*
+/usr/include/mt/query
+/usr/include/btree
+/usr/include/mt/support
+/usr/include/facet
+*/
+#include <facet/identification.hh>
+#include <facet/alphabet.hh>
+#include <facet/typographic.hh>
+#include <mt/query/linguas.hh>
+#include <mt/query/translation.hh>
+#include <mt/query/singleton.hh>
+#include <mt/query/config.hh>
+#include <mt/query/file_map.hh>
+#include <mt/support/path.hh>
+#include <mt/query/lgk.hh>
+#include <mt/support/str.hh>
+#include <mt/query/lang_info.hh>
+
+#include <algorithm>
+#include <functional>
+#include <memory>
+
+#include <iostream>
+#include <stdexcept>
+#include <vector>
+#include <string>
+
+
+
+typedef mt::singleton_array<mt::file_map> txtdb_type;
+
+struct compare_names
+{
+    compare_names(const std::string& from,const std::string& to):
+        from_(from),
+        to_(to)
+    {}
+    bool operator()(const mt::lang_pair& lng1,const mt::lang_pair& lng2)
+    {
+        return distance(lng1) < distance(lng2);
+    }
+    int distance(const mt::lang_pair& lng)
+    {
+        std::string from_name=mt::lang_name(lng.first);
+        std::string to_name=mt::lang_name(lng.second);
+
+        return (!from_.empty() && !from_name.compare(0,from_.size(),from_)) +
+                (!to_.empty() && !to_name.compare(0,to_.size(),to_));
+    }
+    std::string from_,to_;
+};
+
+int compare_articles(const mt::article& a1,const mt::article& a2)
+{
+    if (a1.lgk() != a2.lgk())
+        return a2.lgk() > a1.lgk();
+    else
+        return a2.subject() > a1.subject();
+}
+
+
+
+struct show
+{
+    show(std::string& r_, bool& found_): r(r_),found(found_) {}
+    void operator()(mt::article_set as)
+    {
+        mt::file_map& subj = txtdb_type::instance(mt::datapath+mt::path_separator()+"subjects.txt");
+        mt::file_map& spart = txtdb_type::instance(mt::datapath+mt::path_separator()+"speechparts.txt");
+
+        if (!as.articles_.empty())
+        {
+            found=true;
+            std::sort(as.articles_.begin(),as.articles_.end(),compare_articles);
+
+            int prev_lgk = -1;
+            std::string prev_subject = "x";
+            for(size_t i=0;i<as.articles_.size();++i)
+            {
+                const mt::article& a = as.articles_[i];
+                if (prev_lgk != a.lgk())
+                {
+                    r+="<tr><td><b>"+a.orig()+","+
+                    spart.any_name(mt::to_string<int>(mt::speech_part(a.lgk())))+"</b></td></tr>";
+                    prev_lgk = a.lgk();
+                    prev_subject = "x";//reset subject
+                }
+                if (prev_subject != a.subject())
+                {
+                    r+="<tr><td></td><td><font class=\"explanation\">";
+                    r+=subj.any_name(a.subject());
+                    r+="</font></td><td>";
+                    r+=a.translated();
+                    prev_subject = a.subject();
+                }
+                else
+                    r+=", "+a.translated();
+            }
+            r+="</td></tr>";
+        }
+    }
+    std::string &r;
+    bool& found;
+};
+
+std::string do_translate(const std::string& text,mt::lang_code from,mt::lang_code to)
+{
+    bool found=false;
+    std::string r="<table>";
+    mt::phrase ph;
+    mt::fill_phrase(ph,text,from);
+    mt::translation tr(ph,from,to);
+    std::for_each(tr.asets().begin(), tr.asets().end(), show(r,found));
+    r+="</table>";
+    if (found)
+        return r;
+    return "";
+}
+
+
+
+
+
+
+
+
+
+
+Multitran::Multitran(QObject *parent)
+    : QObject(parent)
+{
+//     QSettings settings("qstardict","qstardict");
+//     m_dictDirs = settings.value("Multitran/dictDirs", m_dictDirs).toStringList();
+//     m_reformatLists = settings.value("Multitran/reformatLists", true).toBool();
+}
+
+Multitran::~Multitran()
+{
+//     QSettings settings("qstardict","qstardict");
+//     settings.setValue("Multitran/dictDirs", m_dictDirs);
+//     settings.setValue("Multitran/reformatLists", m_reformatLists);
+}
+
+QStringList Multitran::availableDicts() const
+{
+    return QStringList("Multitran");
+}
+
+void Multitran::setLoadedDicts(const QStringList &loadedDicts)
+{
+}
+
+Multitran::DictInfo Multitran::dictInfo(const QString &dict)
+{
+//     ::DictInfo nativeInfo;
+//     nativeInfo.wordcount = 0;
+
+    DictInfo result(name(), dict);
+    result.setAuthor("Multitran.ru");
+    result.setDescription(tr("1 mln words excerpt of multitran.ru"));
+    result.setWordsCount(-1);
+    return result;
+}
+
+bool Multitran::isTranslatable(const QString &dict, const QString &word)
+{
+    return true;
+}
+
+Multitran::Translation Multitran::translate(const QString &dict, const QString &word)
+{
+    QTextCodec* c=QTextCodec::codecForMib(2251);
+    std::string text=c->fromUnicode(word).data();
+    std::string from_lang,to_lang;
+
+    int i=word.size();
+    while(--i>=0)
+        if (word.at(i).unicode()>127)
+            break;
+
+    if (i!=-1)
+        from_lang="russian";
+    else
+        from_lang="english";
+
+    mt::linguas avail_langs;
+    mt::linguas::iterator lang = std::max_element(avail_langs.begin(),
+                                                avail_langs.end(),
+                                                compare_names(from_lang,to_lang));
+    if (lang == avail_langs.end() ||
+    (!from_lang.empty() && !to_lang.empty() && (compare_names(from_lang,to_lang).distance(*lang)!=2)))
+    {
+        //std::cerr<<"illegal language names"<<std::endl;
+        return Translation();
+    }
+
+    //"<hr width=50%><center><b>multitran</b><center><hr width=50%>";
+    QString queryResult=c->toUnicode(do_translate(lower_str(lang->first,text),
+                        lang->first,lang->second).c_str());
+
+    if (queryResult.isEmpty())
+        return Translation();
+
+    return Translation(word,"Multitran",queryResult);
+}
+
+QStringList Multitran::findSimilarWords(const QString &dict, const QString &word)
+{
+    return QStringList();
+}
+
+int Multitran::execSettingsDialog(QWidget *parent)
+{
+    //::SettingsDialog dialog(this, parent);
+    //return dialog.exec();
+    return 0;
+}
+
+
+Q_EXPORT_PLUGIN2(multitran, Multitran)
+
+// vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab cindent textwidth=120 formatoptions=tc
diff --git a/plugins/multitran/multitran.h b/plugins/multitran/multitran.h
new file mode 100644 (file)
index 0000000..a4fcc9d
--- /dev/null
@@ -0,0 +1,73 @@
+/*****************************************************************************
+ * This file is a part of QStarDict, a StarDict clone written using Qt       *
+ * multitran.cpp - Plugin for multitran-data (multitran.sf.net)              *
+ * Copyright (C) 2008 Nick Shaforostoff                                      *
+ *                                                                           *
+ * 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 MULTITRAN_H
+#define MULTITRAN_H
+
+#include "../dictplugin.h"
+
+#include <string>
+#include <QVector>
+#include <QHash>
+
+class Multitran: public QObject, public QStarDict::DictPlugin
+{
+    Q_OBJECT
+    Q_INTERFACES(QStarDict::DictPlugin)
+
+    public:
+        Multitran(QObject *parent = 0);
+        ~Multitran();
+
+        QString name() const
+        { return "multitran"; }
+        QString version() const
+        { return "0.1"; }
+        QString description() const
+        { return "The Multitran plugin"; }
+        QStringList authors() const
+        { return QStringList()
+            << tr("Stanislav Ievlev <inger@altlinux.org>")
+            << tr("Nick Shaforostoff <shaforostoff@kde.ru>"); }
+        Features features() const
+        { return Features(/*SearchSimilar | SettingsDialog*/); }
+
+        QStringList availableDicts() const;
+        QStringList loadedDicts() const {return QStringList("Multitran");}//{ return m_loadedDicts.keys(); }
+        void setLoadedDicts(const QStringList &loadedDicts);
+        DictInfo dictInfo(const QString &dict);
+
+        bool isTranslatable(const QString &dict, const QString &word);
+        Translation translate(const QString &dict, const QString &word);
+        virtual QStringList findSimilarWords(const QString &dict, const QString &word);
+
+        int execSettingsDialog(QWidget *parent);
+
+        //friend class SettingsDialog;
+
+    private:
+        QStringList m_dictDirs;
+        QHash<QString, int> m_loadedDicts;
+};
+
+#endif // MULTITRAN_H
+
+// vim: tabstop=4 softtabstop=4 shiftwidth=4 expandtab cindent
+
diff --git a/plugins/multitran/multitran.pro b/plugins/multitran/multitran.pro
new file mode 100644 (file)
index 0000000..45bf611
--- /dev/null
@@ -0,0 +1,32 @@
+#############################################################################
+# multitran.pro - QStarDict, a StarDict clone written using Qt              #
+# Copyright (C) 2008 Nick Shaforostoff                                      #
+#                                                                           #
+# 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.               #
+#############################################################################
+
+TARGET = multitran
+include(../plugin.pri)
+win32:CONFIG += plugin
+
+HEADERS += multitran.h
+
+
+SOURCES += multitran.cpp
+
+; FORMS += settingsdialog.ui
+; RESOURCES += pixmaps/pixmaps.qrc
+
+LIBS += -lmtquery -lmtsupport -lbtree -lfacet
diff --git a/plugins/multitran/multitran.pro.user b/plugins/multitran/multitran.pro.user
new file mode 100644 (file)
index 0000000..f13e63d
--- /dev/null
@@ -0,0 +1,208 @@
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+  <variable>RunConfiguration0-Arguments</variable>
+  <valuelist type="QVariantList" />
+ </data>
+ <data>
+  <variable>RunConfiguration0-BaseEnvironmentBase</variable>
+  <value type="int" >2</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-Executable</variable>
+  <value type="QString" ></value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-RunConfiguration.name</variable>
+  <value type="QString" >Особая программа</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UseTerminal</variable>
+  <value type="bool" >false</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserEnvironmentChanges</variable>
+  <valuelist type="QVariantList" />
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserName</variable>
+  <value type="QString" ></value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserSetName</variable>
+  <value type="bool" >false</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-WorkingDirectory</variable>
+  <value type="QString" >$BUILDDIR</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-type</variable>
+  <value type="QString" >ProjectExplorer.CustomExecutableRunConfiguration</value>
+ </data>
+ <data>
+  <variable>activeRunConfiguration</variable>
+  <value type="int" >0</value>
+ </data>
+ <data>
+  <variable>activebuildconfiguration</variable>
+  <value type="QString" >Debug</value>
+ </data>
+ <data>
+  <variable>buildConfiguration-Debug</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Debug</value>
+   <value key="QtVersionId" type="int" >0</value>
+   <value key="buildConfiguration" type="int" >2</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildConfiguration-Release</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Release</value>
+   <value key="QtVersionId" type="int" >0</value>
+   <value key="buildConfiguration" type="int" >0</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Debug-buildstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Debug</value>
+   <valuelist key="qmakeArgs" type="QVariantList" />
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Debug-buildstep1</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Debug</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Debug-cleanstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Debug</value>
+   <valuelist key="abstractProcess.Environment" type="QVariantList" >
+    <value type="QString" >CVS_RSH=ssh</value>
+    <value type="QString" >DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-bagdqcmK5c,guid=f7d0bf226fac5c3da47675b04b363172</value>
+    <value type="QString" >DESKTOP_SESSION=LXDE</value>
+    <value type="QString" >DESKTOP_STARTUP_ID=</value>
+    <value type="QString" >DISPLAY=:0.0</value>
+    <value type="QString" >GTK_IM_MODULE=xim</value>
+    <value type="QString" >G_BROKEN_FILENAMES=1</value>
+    <value type="QString" >HISTCONTROL=ignoreboth</value>
+    <value type="QString" >HISTSIZE=1000</value>
+    <value type="QString" >HOME=/home/sr</value>
+    <value type="QString" >HOSTNAME=localhost.localdomain</value>
+    <value type="QString" >IMSETTINGS_INTEGRATE_DESKTOP=yes</value>
+    <value type="QString" >IMSETTINGS_MODULE=none</value>
+    <value type="QString" >KDEDIRS=/usr</value>
+    <value type="QString" >KDE_IS_PRELINKED=1</value>
+    <value type="QString" >LANG=ru_RU.UTF-8</value>
+    <value type="QString" >LANGUAGE=</value>
+    <value type="QString" >LESSOPEN=|/usr/bin/lesspipe.sh %s</value>
+    <value type="QString" >LOGNAME=sr</value>
+    <value type="QString" >MAIL=/var/spool/mail/sr</value>
+    <value type="QString" >PATH=/usr/lib/qt4/bin:/usr/lib/qt-3.3/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/lib/ccache:/bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/sr/bin</value>
+    <value type="QString" >PREFERRED=/usr/bin/startlxde</value>
+    <value type="QString" >PWD=/home/sr</value>
+    <value type="QString" >QTDIR=/usr</value>
+    <value type="QString" >QTINC=/usr/lib/qt-3.3/include</value>
+    <value type="QString" >QTLIB=/usr/lib/qt-3.3/lib</value>
+    <value type="QString" >QT_IM_MODULE=xim</value>
+    <value type="QString" >SAL_USE_VCLPLUGIN=gtk</value>
+    <value type="QString" >SHELL=/bin/bash</value>
+    <value type="QString" >SHLVL=0</value>
+    <value type="QString" >SSH_AGENT_PID=1548</value>
+    <value type="QString" >SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass</value>
+    <value type="QString" >SSH_AUTH_SOCK=/tmp/ssh-VhmwRI1547/agent.1547</value>
+    <value type="QString" >TERM=linux</value>
+    <value type="QString" >USER=sr</value>
+    <value type="QString" >XAUTHORITY=/home/sr/.Xauthority</value>
+    <value type="QString" >XDG_CONFIG_HOME=/home/sr/.config</value>
+    <value type="QString" >XDG_MENU_PREFIX=lxde-</value>
+    <value type="QString" >XDG_SESSION_COOKIE=70d798b87bfd4320b56adc5e4b099497-1261842802.980542-1836464560</value>
+    <value type="QString" >XMODIFIERS=@im=none</value>
+    <value type="QString" >_LXSESSION_PID=1547</value>
+   </valuelist>
+   <value key="abstractProcess.IgnoreReturnValue" type="bool" >true</value>
+   <valuelist key="abstractProcess.arguments" type="QVariantList" >
+    <value type="QString" >clean</value>
+    <value type="QString" >-w</value>
+   </valuelist>
+   <value key="abstractProcess.command" type="QString" >/usr/bin/make</value>
+   <value key="abstractProcess.enabled" type="bool" >true</value>
+   <value key="abstractProcess.workingDirectory" type="QString" >/home/sr/nokia/qsdport/qstardict/plugins/multitran</value>
+   <value key="cleanConfig" type="bool" >true</value>
+   <valuelist key="makeargs" type="QVariantList" >
+    <value type="QString" >clean</value>
+   </valuelist>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-buildstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Release</value>
+   <valuelist key="qmakeArgs" type="QVariantList" />
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-buildstep1</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Release</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-cleanstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Release</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfigurations</variable>
+  <valuelist type="QVariantList" >
+   <value type="QString" >Debug</value>
+   <value type="QString" >Release</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>buildstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" ></value>
+   <value key="mkspec" type="QString" ></value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildstep1</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" ></value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildsteps</variable>
+  <valuelist type="QVariantList" >
+   <value type="QString" >trolltech.qt4projectmanager.qmake</value>
+   <value type="QString" >trolltech.qt4projectmanager.make</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>cleanstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" ></value>
+   <value key="clean" type="bool" >true</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>cleansteps</variable>
+  <valuelist type="QVariantList" >
+   <value type="QString" >trolltech.qt4projectmanager.make</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>defaultFileEncoding</variable>
+  <value type="QByteArray" >UTF-8</value>
+ </data>
+ <data>
+  <variable>project</variable>
+  <valuemap type="QVariantMap" />
+ </data>
+</qtcreator>
diff --git a/plugins/plugin.pri b/plugins/plugin.pri
new file mode 100644 (file)
index 0000000..e79749c
--- /dev/null
@@ -0,0 +1,30 @@
+#############################################################################
+# plugin.pri - QStarDict, a StarDict clone written using Qt                 #
+# Copyright (C) 2008 Alexander Rodin                                        #
+#                                                                           #
+# 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.               #
+#############################################################################
+
+isEmpty(TARGET):error(You must set TARGET before including $$_FILE_)
+
+TEMPLATE = lib
+include(../qstardict.pri)
+
+CONFIG += plugin
+INCLUDEPATH += $$dirname(PWD)
+
+target.path = $$PLUGINS_DIR
+INSTALLS += target
+
diff --git a/plugins/plugins.pri b/plugins/plugins.pri
new file mode 100644 (file)
index 0000000..12c3a80
--- /dev/null
@@ -0,0 +1 @@
+ENABLED_PLUGINS = stardict web
diff --git a/plugins/plugins.pro b/plugins/plugins.pro
new file mode 100644 (file)
index 0000000..74026fb
--- /dev/null
@@ -0,0 +1,24 @@
+#############################################################################
+# plugins.pro - QStarDict, a StarDict clone written using Qt                #
+# Copyright (C) 2008 Alexander Rodin                                        #
+#                                                                           #
+# 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(plugins.pri)
+
+TEMPLATE = subdirs
+SUBDIRS = $$ENABLED_PLUGINS
+
diff --git a/plugins/plugins.pro.user b/plugins/plugins.pro.user
new file mode 100644 (file)
index 0000000..4ddfce0
--- /dev/null
@@ -0,0 +1,183 @@
+<!DOCTYPE QtCreatorProject>
+<qtcreator>
+ <data>
+  <variable>RunConfiguration0-Arguments</variable>
+  <valuelist type="QVariantList" />
+ </data>
+ <data>
+  <variable>RunConfiguration0-BaseEnvironmentBase</variable>
+  <value type="int" >2</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-Executable</variable>
+  <value type="QString" ></value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-RunConfiguration.name</variable>
+  <value type="QString" >Особая программа</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UseTerminal</variable>
+  <value type="bool" >false</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserEnvironmentChanges</variable>
+  <valuelist type="QVariantList" />
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserName</variable>
+  <value type="QString" ></value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-UserSetName</variable>
+  <value type="bool" >false</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-WorkingDirectory</variable>
+  <value type="QString" >$BUILDDIR</value>
+ </data>
+ <data>
+  <variable>RunConfiguration0-type</variable>
+  <value type="QString" >ProjectExplorer.CustomExecutableRunConfiguration</value>
+ </data>
+ <data>
+  <variable>activeRunConfiguration</variable>
+  <value type="int" >0</value>
+ </data>
+ <data>
+  <variable>activebuildconfiguration</variable>
+  <value type="QString" >Release</value>
+ </data>
+ <data>
+  <variable>buildConfiguration-Release</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Release</value>
+   <value key="QtVersionId" type="int" >2</value>
+   <value key="buildConfiguration" type="int" >0</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-buildstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Release</value>
+   <valuelist key="qmakeArgs" type="QVariantList" >
+    <value type="QString" >-spec</value>
+    <value type="QString" >/usr/lib/qt4/mkspecs/linux-g++</value>
+   </valuelist>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-buildstep1</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Release</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfiguration-Release-cleanstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" >Release</value>
+   <valuelist key="abstractProcess.Environment" type="QVariantList" >
+    <value type="QString" >CVS_RSH=ssh</value>
+    <value type="QString" >DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-liSSBDpJTL,guid=19f17afa031d807e2beccafd4b34b4e0</value>
+    <value type="QString" >DESKTOP_SESSION=LXDE</value>
+    <value type="QString" >DESKTOP_STARTUP_ID=</value>
+    <value type="QString" >DISPLAY=:0.0</value>
+    <value type="QString" >GTK_IM_MODULE=xim</value>
+    <value type="QString" >G_BROKEN_FILENAMES=1</value>
+    <value type="QString" >HISTCONTROL=ignoreboth</value>
+    <value type="QString" >HISTSIZE=1000</value>
+    <value type="QString" >HOME=/home/sr</value>
+    <value type="QString" >HOSTNAME=localhost.localdomain</value>
+    <value type="QString" >IMSETTINGS_INTEGRATE_DESKTOP=yes</value>
+    <value type="QString" >IMSETTINGS_MODULE=none</value>
+    <value type="QString" >KDEDIRS=/usr</value>
+    <value type="QString" >KDE_IS_PRELINKED=1</value>
+    <value type="QString" >LANG=ru_RU.UTF-8</value>
+    <value type="QString" >LANGUAGE=</value>
+    <value type="QString" >LESSOPEN=|/usr/bin/lesspipe.sh %s</value>
+    <value type="QString" >LOGNAME=sr</value>
+    <value type="QString" >MAIL=/var/spool/mail/sr</value>
+    <value type="QString" >PATH=/usr/lib/qt4/bin:/usr/lib/qt-3.3/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/lib/ccache:/bin:/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/sr/bin</value>
+    <value type="QString" >PREFERRED=/usr/bin/startlxde</value>
+    <value type="QString" >PWD=/home/sr</value>
+    <value type="QString" >QTDIR=/usr</value>
+    <value type="QString" >QTINC=/usr/lib/qt-3.3/include</value>
+    <value type="QString" >QTLIB=/usr/lib/qt-3.3/lib</value>
+    <value type="QString" >QT_IM_MODULE=xim</value>
+    <value type="QString" >SAL_USE_VCLPLUGIN=gtk</value>
+    <value type="QString" >SHELL=/bin/bash</value>
+    <value type="QString" >SHLVL=0</value>
+    <value type="QString" >SSH_AGENT_PID=1436</value>
+    <value type="QString" >SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass</value>
+    <value type="QString" >SSH_AUTH_SOCK=/tmp/ssh-UYUHJr1435/agent.1435</value>
+    <value type="QString" >TERM=linux</value>
+    <value type="QString" >USER=sr</value>
+    <value type="QString" >XAUTHORITY=/home/sr/.Xauthority</value>
+    <value type="QString" >XDG_CONFIG_HOME=/home/sr/.config</value>
+    <value type="QString" >XDG_MENU_PREFIX=lxde-</value>
+    <value type="QString" >XDG_SESSION_COOKIE=70d798b87bfd4320b56adc5e4b099497-1261745376.866111-1590722281</value>
+    <value type="QString" >XMODIFIERS=@im=none</value>
+    <value type="QString" >_LXSESSION_PID=1435</value>
+   </valuelist>
+   <value key="abstractProcess.IgnoreReturnValue" type="bool" >true</value>
+   <valuelist key="abstractProcess.arguments" type="QVariantList" >
+    <value type="QString" >clean</value>
+    <value type="QString" >-w</value>
+   </valuelist>
+   <value key="abstractProcess.command" type="QString" >/usr/bin/make</value>
+   <value key="abstractProcess.enabled" type="bool" >true</value>
+   <value key="abstractProcess.workingDirectory" type="QString" >/home/sr/nokia/qsdport/qstardict/plugins</value>
+   <value key="cleanConfig" type="bool" >true</value>
+   <valuelist key="makeargs" type="QVariantList" >
+    <value type="QString" >clean</value>
+   </valuelist>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildconfigurations</variable>
+  <valuelist type="QVariantList" >
+   <value type="QString" >Release</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>buildstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" ></value>
+   <value key="mkspec" type="QString" ></value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildstep1</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" ></value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>buildsteps</variable>
+  <valuelist type="QVariantList" >
+   <value type="QString" >trolltech.qt4projectmanager.qmake</value>
+   <value type="QString" >trolltech.qt4projectmanager.make</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>cleanstep0</variable>
+  <valuemap type="QVariantMap" >
+   <value key="ProjectExplorer.BuildConfiguration.DisplayName" type="QString" ></value>
+   <value key="clean" type="bool" >true</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>cleansteps</variable>
+  <valuelist type="QVariantList" >
+   <value type="QString" >trolltech.qt4projectmanager.make</value>
+  </valuelist>
+ </data>
+ <data>
+  <variable>defaultFileEncoding</variable>
+  <value type="QByteArray" >UTF-8</value>
+ </data>
+ <data>
+  <variable>project</variable>
+  <valuemap type="QVariantMap" />
+ </data>
+</qtcreator>
diff --git a/plugins/stardict/dictziplib.cpp b/plugins/stardict/dictziplib.cpp
new file mode 100644 (file)
index 0000000..b6b3bc3
--- /dev/null
@@ -0,0 +1,546 @@
+/* dictziplib.c --
+* http://stardict.sourceforge.net
+* Copyright (C) 2003-2003 Hu Zheng <huzheng_001@163.com>
+* This file is a modify version of dictd-1.9.7's data.c
+*
+* data.c -- 
+* Created: Tue Jul 16 12:45:41 1996 by faith@dict.org
+* Revised: Sat Mar 30 10:46:06 2002 by faith@dict.org
+* Copyright 1996, 1997, 1998, 2000, 2002 Rickard E. Faith (faith@dict.org)
+* 
+*
+*  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 Library General Public License for more details.
+*
+*  You should have received a copy of the GNU General Public License
+*  along with this program; if not, write to the Free Software
+*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+//#define HAVE_MMAP //it will defined in config.h. this can be done by configure.in with a AC_FUNC_MMAP.
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <QtGlobal>
+
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#ifdef Q_OS_UNIX
+#include <unistd.h>
+#endif
+#ifdef Q_OS_WIN32
+#include <io.h>
+#endif
+#include <limits.h>
+#include <fcntl.h>
+
+#include <sys/stat.h>
+
+
+#include "dictziplib.hpp"
+
+#define USE_CACHE 1
+
+#define BUFFERSIZE 10240
+
+/*
+ * Output buffer must be greater than or
+ * equal to 110% of input buffer size, plus
+ * 12 bytes. 
+*/
+#define OUT_BUFFER_SIZE 0xffffL
+
+#define IN_BUFFER_SIZE ((unsigned long)((double)(OUT_BUFFER_SIZE - 12) * 0.89))
+
+/* For gzip-compatible header, as defined in RFC 1952 */
+
+/* Magic for GZIP (rfc1952)                */
+#define GZ_MAGIC1     0x1f     /* First magic byte                        */
+#define GZ_MAGIC2     0x8b     /* Second magic byte                       */
+
+/* FLaGs (bitmapped), from rfc1952         */
+#define GZ_FTEXT      0x01     /* Set for ASCII text                      */
+#define GZ_FHCRC      0x02     /* Header CRC16                            */
+#define GZ_FEXTRA     0x04     /* Optional field (random access index)    */
+#define GZ_FNAME      0x08     /* Original name                           */
+#define GZ_COMMENT    0x10     /* Zero-terminated, human-readable comment */
+#define GZ_MAX           2     /* Maximum compression                     */
+#define GZ_FAST          4     /* Fasted compression                      */
+
+/* These are from rfc1952                  */
+#define GZ_OS_FAT        0     /* FAT filesystem (MS-DOS, OS/2, NT/Win32) */
+#define GZ_OS_AMIGA      1     /* Amiga                                   */
+#define GZ_OS_VMS        2     /* VMS (or OpenVMS)                        */
+#define GZ_OS_UNIX       3      /* Unix                                    */
+#define GZ_OS_VMCMS      4      /* VM/CMS                                  */
+#define GZ_OS_ATARI      5      /* Atari TOS                               */
+#define GZ_OS_HPFS       6      /* HPFS filesystem (OS/2, NT)              */
+#define GZ_OS_MAC        7      /* Macintosh                               */
+#define GZ_OS_Z          8      /* Z-System                                */
+#define GZ_OS_CPM        9      /* CP/M                                    */
+#define GZ_OS_TOPS20    10      /* TOPS-20                                 */
+#define GZ_OS_NTFS      11      /* NTFS filesystem (NT)                    */
+#define GZ_OS_QDOS      12      /* QDOS                                    */
+#define GZ_OS_ACORN     13      /* Acorn RISCOS                            */
+#define GZ_OS_UNKNOWN  255      /* unknown                                 */
+
+#define GZ_RND_S1       'R'    /* First magic for random access format    */
+#define GZ_RND_S2       'A'    /* Second magic for random access format   */
+
+#define GZ_ID1           0     /* GZ_MAGIC1                               */
+#define GZ_ID2           1     /* GZ_MAGIC2                               */
+#define GZ_CM            2     /* Compression Method (Z_DEFALTED)         */
+#define GZ_FLG          3      /* FLaGs (see above)                       */
+#define GZ_MTIME         4     /* Modification TIME                       */
+#define GZ_XFL           8     /* eXtra FLags (GZ_MAX or GZ_FAST)         */
+#define GZ_OS            9     /* Operating System                        */
+#define GZ_XLEN         10     /* eXtra LENgth (16bit)                    */
+#define GZ_FEXTRA_START 12     /* Start of extra fields                   */
+#define GZ_SI1          12     /* Subfield ID1                            */
+#define GZ_SI2          13      /* Subfield ID2                            */
+#define GZ_SUBLEN       14     /* Subfield length (16bit)                 */
+#define GZ_VERSION      16      /* Version for subfield format             */
+#define GZ_CHUNKLEN     18     /* Chunk length (16bit)                    */
+#define GZ_CHUNKCNT     20     /* Number of chunks (16bit)                */
+#define GZ_RNDDATA      22     /* Random access data (16bit)              */
+
+#define DICT_UNKNOWN    0
+#define DICT_TEXT       1
+#define DICT_GZIP       2
+#define DICT_DZIP       3
+
+
+int dictData::read_header(const std::string &fname, int computeCRC)
+{
+    FILE *str;
+    int id1, id2, si1, si2;
+    char buffer[BUFFERSIZE];
+    int extraLength, subLength;
+    int i;
+    char *pt;
+    int c;
+    struct stat sb;
+    unsigned long crc = crc32( 0L, Z_NULL, 0 );
+    int count;
+    unsigned long offset;
+
+    if (!(str = fopen(fname.c_str(), "rb")))
+    {
+        //err_fatal_errno( __FUNCTION__,
+        //       "Cannot open data file \"%s\" for read\n", filename );
+    }
+
+    this->headerLength = GZ_XLEN - 1;
+    this->type = DICT_UNKNOWN;
+
+    id1 = getc( str );
+    id2 = getc( str );
+
+    if (id1 != GZ_MAGIC1 || id2 != GZ_MAGIC2)
+    {
+        this->type = DICT_TEXT;
+        fstat( fileno( str ), &sb );
+        this->compressedLength = this->length = sb.st_size;
+        this->origFilename = fname;
+        this->mtime = sb.st_mtime;
+        if (computeCRC)
+        {
+            rewind( str );
+            while (!feof( str ))
+            {
+                if ((count = fread( buffer, 1, BUFFERSIZE, str )))
+                {
+                    crc = crc32(crc, (Bytef *)buffer, count);
+                }
+            }
+        }
+        this->crc = crc;
+        fclose( str );
+        return 0;
+    }
+    this->type = DICT_GZIP;
+
+    this->method = getc( str );
+    this->flags = getc( str );
+    this->mtime = getc( str ) << 0;
+    this->mtime |= getc( str ) << 8;
+    this->mtime |= getc( str ) << 16;
+    this->mtime |= getc( str ) << 24;
+    this->extraFlags = getc( str );
+    this->os = getc( str );
+
+    if (this->flags & GZ_FEXTRA)
+    {
+        extraLength = getc( str ) << 0;
+        extraLength |= getc( str ) << 8;
+        this->headerLength += extraLength + 2;
+        si1 = getc( str );
+        si2 = getc( str );
+
+        if (si1 == GZ_RND_S1 || si2 == GZ_RND_S2)
+        {
+            subLength = getc( str ) << 0;
+            subLength |= getc( str ) << 8;
+            this->version = getc( str ) << 0;
+            this->version |= getc( str ) << 8;
+
+            if (this->version != 1)
+            {
+                //err_internal( __FUNCTION__,
+                //       "dzip header version %d not supported\n",
+                //       this->version );
+            }
+
+            this->chunkLength = getc( str ) << 0;
+            this->chunkLength |= getc( str ) << 8;
+            this->chunkCount = getc( str ) << 0;
+            this->chunkCount |= getc( str ) << 8;
+
+            if (this->chunkCount <= 0)
+            {
+                fclose( str );
+                return 5;
+            }
+            this->chunks = (int *)malloc(sizeof( this->chunks[0] )
+                                         * this->chunkCount );
+            for (i = 0; i < this->chunkCount; i++)
+            {
+                this->chunks[i] = getc( str ) << 0;
+                this->chunks[i] |= getc( str ) << 8;
+            }
+            this->type = DICT_DZIP;
+        }
+        else
+        {
+            fseek( str, this->headerLength, SEEK_SET );
+        }
+    }
+
+    if (this->flags & GZ_FNAME)
+    { /* FIXME! Add checking against header len */
+        pt = buffer;
+        while ((c = getc( str )) && c != EOF)
+            * pt++ = c;
+        *pt = '\0';
+
+        this->origFilename = buffer;
+        this->headerLength += this->origFilename.length() + 1;
+    }
+    else
+    {
+        this->origFilename = "";
+    }
+
+    if (this->flags & GZ_COMMENT)
+    { /* FIXME! Add checking for header len */
+        pt = buffer;
+        while ((c = getc( str )) && c != EOF)
+            * pt++ = c;
+        *pt = '\0';
+        comment = buffer;
+        headerLength += comment.length() + 1;
+    }
+    else
+    {
+        comment = "";
+    }
+
+    if (this->flags & GZ_FHCRC)
+    {
+        getc( str );
+        getc( str );
+        this->headerLength += 2;
+    }
+
+    if (ftell( str ) != this->headerLength + 1)
+    {
+        //err_internal( __FUNCTION__,
+        //    "File position (%lu) != header length + 1 (%d)\n",
+        //  ftell( str ), this->headerLength + 1 );
+    }
+
+    fseek( str, -8, SEEK_END );
+    this->crc = getc( str ) << 0;
+    this->crc |= getc( str ) << 8;
+    this->crc |= getc( str ) << 16;
+    this->crc |= getc( str ) << 24;
+    this->length = getc( str ) << 0;
+    this->length |= getc( str ) << 8;
+    this->length |= getc( str ) << 16;
+    this->length |= getc( str ) << 24;
+    this->compressedLength = ftell( str );
+
+    /* Compute offsets */
+    this->offsets = (unsigned long *)malloc( sizeof( this->offsets[0] )
+                    * this->chunkCount );
+    for (offset = this->headerLength + 1, i = 0;
+            i < this->chunkCount;
+            i++)
+    {
+        this->offsets[i] = offset;
+        offset += this->chunks[i];
+    }
+
+    fclose( str );
+    return 0;
+}
+
+bool dictData::open(const std::string& fname, int computeCRC)
+{
+    struct stat sb;
+    int j;
+    int fd;
+
+    this->initialized = 0;
+
+#ifdef Q_OS_UNIX
+    if (stat(fname.c_str(), &sb) || !S_ISREG(sb.st_mode))
+#elif defined(Q_OS_WIN32)
+    if (_stat(fname.c_str(), &sb) || !(sb.stMode & _S_IFREG))
+#endif
+    {
+        //err_warning( __FUNCTION__,
+        //   "%s is not a regular file -- ignoring\n", fname );
+        return false;
+    }
+
+    if (read_header(fname, computeCRC))
+    {
+        //err_fatal( __FUNCTION__,
+        // "\"%s\" not in text or dzip format\n", fname );
+        return false;
+    }
+
+    if ((fd = ::open(fname.c_str(), O_RDONLY )) < 0)
+    {
+        //err_fatal_errno( __FUNCTION__,
+        //       "Cannot open data file \"%s\"\n", fname );
+        return false;
+    }
+    if (fstat(fd, &sb))
+    {
+        //err_fatal_errno( __FUNCTION__,
+        //       "Cannot stat data file \"%s\"\n", fname );
+        return false;
+    }
+
+    this->size = sb.st_size;
+    ::close(fd);
+    if (!mapfile.open(fname.c_str(), size))
+        return false;
+
+    this->start = mapfile.begin();
+    this->end = this->start + this->size;
+
+    for (j = 0; j < DICT_CACHE_SIZE; j++)
+    {
+        cache[j].chunk = -1;
+        cache[j].stamp = -1;
+        cache[j].inBuffer = NULL;
+        cache[j].count = 0;
+    }
+
+    return true;
+}
+
+void dictData::close()
+{
+    int i;
+
+    if (this->chunks)
+        free(this->chunks);
+    if (this->offsets)
+        free(this->offsets);
+
+    if (this->initialized)
+    {
+        if (inflateEnd( &this->zStream ))
+        {
+            //err_internal( __FUNCTION__,
+            //       "Cannot shut down inflation engine: %s\n",
+            //     this->zStream.msg );
+        }
+    }
+
+    for (i = 0; i < DICT_CACHE_SIZE; ++i)
+    {
+        if (this -> cache [i].inBuffer)
+            free (this -> cache [i].inBuffer);
+    }
+}
+
+void dictData::read(char *buffer, unsigned long start, unsigned long size)
+{
+    char *pt;
+    unsigned long end;
+    int count;
+    char *inBuffer;
+    char outBuffer[OUT_BUFFER_SIZE];
+    int firstChunk, lastChunk;
+    int firstOffset, lastOffset;
+    int i, j;
+    int found, target, lastStamp;
+    static int stamp = 0;
+
+    end = start + size;
+
+    //buffer = malloc( size + 1 );
+
+    //PRINTF(DBG_UNZIP,
+    // ("dict_data_read( %p, %lu, %lu )\n",
+    //h, start, size ));
+
+
+    switch (this->type)
+    {
+    case DICT_GZIP:
+        //err_fatal( __FUNCTION__,
+        // "Cannot seek on pure gzip format files.\n"
+        // "Use plain text (for performance)"
+        // " or dzip format (for space savings).\n" );
+        break;
+    case DICT_TEXT:
+        memcpy( buffer, this->start + start, size );
+        //buffer[size] = '\0';
+        break;
+    case DICT_DZIP:
+        if (!this->initialized)
+        {
+            ++this->initialized;
+            this->zStream.zalloc = NULL;
+            this->zStream.zfree = NULL;
+            this->zStream.opaque = NULL;
+            this->zStream.next_in = 0;
+            this->zStream.avail_in = 0;
+            this->zStream.next_out = NULL;
+            this->zStream.avail_out = 0;
+            if (inflateInit2( &this->zStream, -15 ) != Z_OK)
+            {
+                //err_internal( __FUNCTION__,
+                //  "Cannot initialize inflation engine: %s\n",
+                //this->zStream.msg );
+            }
+        }
+        firstChunk = start / this->chunkLength;
+        firstOffset = start - firstChunk * this->chunkLength;
+        lastChunk = end / this->chunkLength;
+        lastOffset = end - lastChunk * this->chunkLength;
+        //PRINTF(DBG_UNZIP,
+        // ("   start = %lu, end = %lu\n"
+        //"firstChunk = %d, firstOffset = %d,"
+        //" lastChunk = %d, lastOffset = %d\n",
+        //start, end, firstChunk, firstOffset, lastChunk, lastOffset ));
+        for (pt = buffer, i = firstChunk; i <= lastChunk; i++)
+        {
+
+            /* Access cache */
+            found = 0;
+            target = 0;
+            lastStamp = INT_MAX;
+            for (j = 0; j < DICT_CACHE_SIZE; j++)
+            {
+#if USE_CACHE
+                if (this->cache[j].chunk == i)
+                {
+                    found = 1;
+                    target = j;
+                    break;
+                }
+#endif
+                if (this->cache[j].stamp < lastStamp)
+                {
+                    lastStamp = this->cache[j].stamp;
+                    target = j;
+                }
+            }
+
+            this->cache[target].stamp = ++stamp;
+            if (found)
+            {
+                count = this->cache[target].count;
+                inBuffer = this->cache[target].inBuffer;
+            }
+            else
+            {
+                this->cache[target].chunk = i;
+                if (!this->cache[target].inBuffer)
+                    this->cache[target].inBuffer = (char *)malloc( IN_BUFFER_SIZE );
+                inBuffer = this->cache[target].inBuffer;
+
+                if (this->chunks[i] >= OUT_BUFFER_SIZE )
+                {
+                    //err_internal( __FUNCTION__,
+                    //    "this->chunks[%d] = %d >= %ld (OUT_BUFFER_SIZE)\n",
+                    //  i, this->chunks[i], OUT_BUFFER_SIZE );
+                }
+                memcpy( outBuffer, this->start + this->offsets[i], this->chunks[i] );
+
+                this->zStream.next_in = (Bytef *)outBuffer;
+                this->zStream.avail_in = this->chunks[i];
+                this->zStream.next_out = (Bytef *)inBuffer;
+                this->zStream.avail_out = IN_BUFFER_SIZE;
+                if (inflate( &this->zStream, Z_PARTIAL_FLUSH ) != Z_OK)
+                {
+                    //err_fatal( __FUNCTION__, "inflate: %s\n", this->zStream.msg );
+                }
+                if (this->zStream.avail_in)
+                {
+                    //err_internal( __FUNCTION__,
+                    //    "inflate did not flush (%d pending, %d avail)\n",
+                    //  this->zStream.avail_in, this->zStream.avail_out );
+                }
+
+                count = IN_BUFFER_SIZE - this->zStream.avail_out;
+
+                this->cache[target].count = count;
+            }
+
+            if (i == firstChunk)
+            {
+                if (i == lastChunk)
+                {
+                    memcpy( pt, inBuffer + firstOffset, lastOffset - firstOffset);
+                    pt += lastOffset - firstOffset;
+                }
+                else
+                {
+                    if (count != this->chunkLength )
+                    {
+                        //err_internal( __FUNCTION__,
+                        //     "Length = %d instead of %d\n",
+                        //count, this->chunkLength );
+                    }
+                    memcpy( pt, inBuffer + firstOffset,
+                            this->chunkLength - firstOffset );
+                    pt += this->chunkLength - firstOffset;
+                }
+            }
+            else if (i == lastChunk)
+            {
+                memcpy( pt, inBuffer, lastOffset );
+                pt += lastOffset;
+            }
+            else
+            {
+                assert( count == this->chunkLength );
+                memcpy( pt, inBuffer, this->chunkLength );
+                pt += this->chunkLength;
+            }
+        }
+        //*pt = '\0';
+        break;
+    case DICT_UNKNOWN:
+        //err_fatal( __FUNCTION__, "Cannot read unknown file type\n" );
+        break;
+    }
+}
diff --git a/plugins/stardict/dictziplib.hpp b/plugins/stardict/dictziplib.hpp
new file mode 100644 (file)
index 0000000..78c0866
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __DICT_ZIP_LIB_H__
+#define __DICT_ZIP_LIB_H__
+
+#include <ctime>
+#include <string>
+#include <zlib.h>
+
+#include "mapfile.hpp"
+
+
+#define DICT_CACHE_SIZE 5
+
+struct dictCache
+{
+    int chunk;
+    char *inBuffer;
+    int stamp;
+    int count;
+};
+
+struct dictData
+{
+    dictData()
+    {}
+    bool open(const std::string& filename, int computeCRC);
+    void close();
+    void read(char *buffer, unsigned long start, unsigned long size);
+    ~dictData()
+    {
+        close();
+    }
+private:
+    const char *start; /* start of mmap'd area */
+    const char *end;           /* end of mmap'd area */
+    unsigned long size;                /* size of mmap */
+
+    int type;
+    z_stream zStream;
+    int initialized;
+
+    int headerLength;
+    int method;
+    int flags;
+    time_t mtime;
+    int extraFlags;
+    int os;
+    int version;
+    int chunkLength;
+    int chunkCount;
+    int *chunks;
+    unsigned long *offsets;    /* Sum-scan of chunks. */
+    std::string origFilename;
+    std::string comment;
+    unsigned long crc;
+    unsigned long length;
+    unsigned long compressedLength;
+    dictCache cache[DICT_CACHE_SIZE];
+    MapFile mapfile;
+
+    int read_header(const std::string &filename, int computeCRC);
+};
+
+#endif//!__DICT_ZIP_LIB_H__
diff --git a/plugins/stardict/dictziplib.o b/plugins/stardict/dictziplib.o
new file mode 100644 (file)
index 0000000..5a5b14b
Binary files /dev/null and b/plugins/stardict/dictziplib.o differ
diff --git a/plugins/stardict/distance.cpp b/plugins/stardict/distance.cpp
new file mode 100644 (file)
index 0000000..ebf98c5
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+   writer : Opera Wang
+   E-Mail : wangvisual AT sohu DOT com
+   License: GPL
+*/
+
+/* filename: distance.cc */
+/*
+http://www.merriampark.com/ld.htm
+What is Levenshtein Distance?
+Levenshtein distance (LD) is a measure of the similarity between two strings, 
+which we will refer to as the source string (s) and the target string (t). 
+The distance is the number of deletions, insertions, or substitutions required
+ to transform s into t. For example,
+    * If s is "test" and t is "test", then LD(s,t) = 0, because no transformations are needed. 
+    The strings are already identical.
+    * If s is "test" and t is "tent", then LD(s,t) = 1, because one substitution
+     (change "s" to "n") is sufficient to transform s into t.
+The greater the Levenshtein distance, the more different the strings are.
+Levenshtein distance is named after the Russian scientist Vladimir Levenshtein,
+ who devised the algorithm in 1965. If you can't spell or pronounce Levenshtein,
+ the metric is also sometimes called edit distance.
+The Levenshtein distance algorithm has been used in:
+    * Spell checking
+    * Speech recognition
+    * DNA analysis
+    * Plagiarism detection 
+*/
+
+
+#include <stdlib.h>
+#include <string.h> 
+//#include <stdio.h>
+
+#include "distance.h"
+
+#define OPTIMIZE_ED 
+/*
+Cover transposition, in addition to deletion,
+insertion and substitution. This step is taken from:
+Berghel, Hal ; Roach, David : "An Extension of Ukkonen's 
+Enhanced Dynamic Programming ASM Algorithm"
+(http://www.acm.org/~hlb/publications/asm/asm.html)
+*/
+#define COVER_TRANSPOSITION
+
+/****************************************/
+/*Implementation of Levenshtein distance*/
+/****************************************/
+
+EditDistance::EditDistance()
+{
+    currentelements = 2500; // It's enough for most conditions :-)
+    d = (int*)malloc(sizeof(int) * currentelements);
+}
+
+EditDistance::~EditDistance()
+{
+    //    printf("size:%d\n",currentelements);
+    if (d)
+        free(d);
+}
+
+#ifdef OPTIMIZE_ED
+int EditDistance::CalEditDistance(const gunichar *s, const gunichar *t, const int limit)
+/*Compute levenshtein distance between s and t, this is using QUICK algorithm*/
+{
+    int n = 0, m = 0, iLenDif, k, i, j, cost;
+    // Remove leftmost matching portion of strings
+    while ( *s && (*s == *t) )
+    {
+        s++;
+        t++;
+    }
+
+    while (s[n])
+    {
+        n++;
+    }
+    while (t[m])
+    {
+        m++;
+    }
+
+    // Remove rightmost matching portion of strings by decrement n and m.
+    while ( n && m && (*(s + n - 1) == *(t + m - 1)) )
+    {
+        n--;
+        m--;
+    }
+    if ( m == 0 || n == 0 || d == (int*)0 )
+        return (m + n);
+    if ( m < n )
+    {
+        const gunichar * temp = s;
+        int itemp = n;
+        s = t;
+        t = temp;
+        n = m;
+        m = itemp;
+    }
+    iLenDif = m - n;
+    if ( iLenDif >= limit )
+        return iLenDif;
+    // step 1
+    n++;
+    m++;
+    //    d=(int*)malloc(sizeof(int)*m*n);
+    if ( m*n > currentelements )
+    {
+        currentelements = m * n * 2;    // double the request
+        d = (int*)realloc(d, sizeof(int) * currentelements);
+        if ( (int*)0 == d )
+            return (m + n);
+    }
+    // step 2, init matrix
+    for (k = 0;k < n;k++)
+        d[k] = k;
+    for (k = 1;k < m;k++)
+        d[k*n] = k;
+    // step 3
+    for (i = 1;i < n;i++)
+    {
+        // first calculate column, d(i,j)
+        for ( j = 1;j < iLenDif + i;j++ )
+        {
+            cost = s[i - 1] == t[j - 1] ? 0 : 1;
+            d[j*n + i] = minimum(d[(j - 1) * n + i] + 1, d[j * n + i - 1] + 1, d[(j - 1) * n + i - 1] + cost);
+#ifdef COVER_TRANSPOSITION
+
+            if ( i >= 2 && j >= 2 && (d[j*n + i] - d[(j - 2)*n + i - 2] == 2)
+                    && (s[i - 2] == t[j - 1]) && (s[i - 1] == t[j - 2]) )
+                d[j*n + i]--;
+#endif
+
+        }
+        // second calculate row, d(k,j)
+        // now j==iLenDif+i;
+        for ( k = 1;k <= i;k++ )
+        {
+            cost = s[k - 1] == t[j - 1] ? 0 : 1;
+            d[j*n + k] = minimum(d[(j - 1) * n + k] + 1, d[j * n + k - 1] + 1, d[(j - 1) * n + k - 1] + cost);
+#ifdef COVER_TRANSPOSITION
+
+            if ( k >= 2 && j >= 2 && (d[j*n + k] - d[(j - 2)*n + k - 2] == 2)
+                    && (s[k - 2] == t[j - 1]) && (s[k - 1] == t[j - 2]) )
+                d[j*n + k]--;
+#endif
+
+        }
+        // test if d(i,j) limit gets equal or exceed
+        if ( d[j*n + i] >= limit )
+        {
+            return d[j*n + i];
+        }
+    }
+    // d(n-1,m-1)
+    return d[n*m - 1];
+}
+#else
+int EditDistance::CalEditDistance(const char *s, const char *t, const int limit)
+{
+    //Step 1
+    int k, i, j, n, m, cost;
+    n = strlen(s);
+    m = strlen(t);
+    if ( n != 0 && m != 0 && d != (int*)0 )
+    {
+        m++;
+        n++;
+        if ( m*n > currentelements )
+        {
+            currentelements = m * n * 2;
+            d = (int*)realloc(d, sizeof(int) * currentelements);
+            if ( (int*)0 == d )
+                return (m + n);
+        }
+        //Step 2
+        for (k = 0;k < n;k++)
+            d[k] = k;
+        for (k = 0;k < m;k++)
+            d[k*n] = k;
+        //Step 3 and 4
+        for (i = 1;i < n;i++)
+            for (j = 1;j < m;j++)
+            {
+                //Step 5
+                if (s[i - 1] == t[j - 1])
+                    cost = 0;
+                else
+                    cost = 1;
+                //Step 6
+                d[j*n + i] = minimum(d[(j - 1) * n + i] + 1, d[j * n + i - 1] + 1, d[(j - 1) * n + i - 1] + cost);
+#ifdef COVER_TRANSPOSITION
+
+                if ( i >= 2 && j >= 2 && (d[j*n + i] - d[(j - 2)*n + i - 2] == 2)
+                        && (s[i - 2] == t[j - 1]) && (s[i - 1] == t[j - 2]) )
+                    d[j*n + i]--;
+#endif
+
+            }
+        return d[n*m - 1];
+    }
+    else
+        return (n + m);
+}
+#endif
diff --git a/plugins/stardict/distance.h b/plugins/stardict/distance.h
new file mode 100644 (file)
index 0000000..88d8e46
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef DISTANCE_H
+#define DISTANCE_H
+
+#include <glib.h>
+
+class EditDistance
+{
+    private:
+        int *d;
+        int currentelements;
+        /*Gets the minimum of three values */
+        inline int minimum( const int a, const int b, const int c )
+        {
+            int min = a;
+            if ( b < min )
+                min = b;
+            if ( c < min )
+                min = c;
+            return min;
+        };
+    public:
+        EditDistance( );
+        ~EditDistance( );
+        int CalEditDistance( const gunichar *s, const gunichar *t, const int limit );
+};
+
+#endif
diff --git a/plugins/stardict/distance.o b/plugins/stardict/distance.o
new file mode 100644 (file)
index 0000000..d1b5ce8
Binary files /dev/null and b/plugins/stardict/distance.o differ
diff --git a/plugins/stardict/file.hpp b/plugins/stardict/file.hpp
new file mode 100644 (file)
index 0000000..ee96eec
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef _FILE_HPP_
+#define _FILE_HPP_
+
+#include <algorithm>
+#include <glib.h>
+#include <list>
+#include <string>
+
+
+typedef std::list<std::string> List;
+
+template <typename Function>
+void __for_each_file(const std::string& dirname, const std::string& suff,
+                     const List& order_list, const List& disable_list,
+                     Function f)
+{
+    GDir *dir = g_dir_open(dirname.c_str(), 0, NULL);
+    if (dir)
+    {
+        const gchar *filename;
+
+        while ((filename = g_dir_read_name(dir)) != NULL)
+        {
+            std::string fullfilename(dirname + G_DIR_SEPARATOR_S + filename);
+            if (g_file_test(fullfilename.c_str(), G_FILE_TEST_IS_DIR))
+                __for_each_file(fullfilename, suff, order_list, disable_list, f);
+            else if (g_str_has_suffix(filename, suff.c_str()) &&
+                     std::find(order_list.begin(), order_list.end(),
+                               fullfilename) == order_list.end())
+            {
+                bool disable = std::find(disable_list.begin(),
+                                         disable_list.end(),
+                                         fullfilename) != disable_list.end();
+                f(fullfilename, disable);
+            }
+        }
+        g_dir_close(dir);
+    }
+}
+
+template <typename Function>
+void for_each_file(const List& dirs_list, const std::string& suff,
+                   const List& order_list, const List& disable_list,
+                   Function f)
+{
+    List::const_iterator it;
+    for (it = order_list.begin(); it != order_list.end(); ++it)
+    {
+        bool disable = std::find(disable_list.begin(), disable_list.end(),
+                                 *it) != disable_list.end();
+        f(*it, disable);
+    }
+    for (it = dirs_list.begin(); it != dirs_list.end(); ++it)
+        __for_each_file(*it, suff, order_list, disable_list, f);
+}
+
+#endif//!_FILE_HPP_
diff --git a/plugins/stardict/lib.cpp b/plugins/stardict/lib.cpp
new file mode 100644 (file)
index 0000000..e18183f
--- /dev/null
@@ -0,0 +1,1925 @@
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <algorithm>
+#include <cstring>
+#include <cctype>
+
+#include <sys/stat.h>
+#include <zlib.h>
+#include <glib/gstdio.h>
+
+#include "distance.h"
+#include "file.hpp"
+#include "mapfile.hpp"
+
+#include "lib.h"
+
+// Notice: read src/tools/DICTFILE_FORMAT for the dictionary
+// file's format information!
+
+
+static inline bool bIsVowel(gchar inputchar)
+{
+    gchar ch = g_ascii_toupper(inputchar);
+    return ( ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U' );
+}
+
+static bool bIsPureEnglish(const gchar *str)
+{
+    // i think this should work even when it is UTF8 string :).
+    for (int i = 0; str[i] != 0; i++)
+        //if(str[i]<0)
+        //if(str[i]<32 || str[i]>126) // tab equal 9,so this is not OK.
+        // Better use isascii() but not str[i]<0 while char is default unsigned in arm
+        if (!isascii(str[i]))
+            return false;
+    return true;
+}
+
+static inline gint stardict_strcmp(const gchar *s1, const gchar *s2)
+{
+    gint a = g_ascii_strcasecmp(s1, s2);
+    if (a == 0)
+        return strcmp(s1, s2);
+    else
+        return a;
+}
+
+bool DictInfo::load_from_ifo_file(const std::string& ifofilename,
+                                  bool istreedict)
+{
+    ifo_file_name = ifofilename;
+    gchar *buffer;
+    if (!g_file_get_contents(ifofilename.c_str(), &buffer, NULL, NULL))
+        return false;
+
+#define TREEDICT_MAGIC_DATA "StarDict's treedict ifo file\nversion=2.4.2\n"
+#define DICT_MAGIC_DATA "StarDict's dict ifo file\nversion=2.4.2\n"
+
+    const gchar *magic_data = istreedict ? TREEDICT_MAGIC_DATA : DICT_MAGIC_DATA;
+    if (!g_str_has_prefix(buffer, magic_data))
+    {
+        g_free(buffer);
+        return false;
+    }
+
+    gchar *p1, *p2, *p3;
+
+    p1 = buffer + strlen(magic_data) - 1;
+
+    p2 = strstr(p1, "\nwordcount=");
+    if (!p2)
+    {
+        g_free(buffer);
+        return false;
+    }
+
+    p3 = strchr(p2 + sizeof("\nwordcount=") - 1, '\n');
+    gchar *tmpstr = (gchar *)g_memdup(p2 + sizeof("\nwordcount=") - 1, p3 - (p2 + sizeof("\nwordcount=") - 1) + 1);
+    tmpstr[p3 - (p2 + sizeof("\nwordcount=") - 1)] = '\0';
+    wordcount = atol(tmpstr);
+    g_free(tmpstr);
+
+    if (istreedict)
+    {
+        p2 = strstr(p1, "\ntdxfilesize=");
+        if (!p2)
+        {
+            g_free(buffer);
+            return false;
+        }
+        p3 = strchr(p2 + sizeof("\ntdxfilesize=") - 1, '\n');
+        tmpstr = (gchar *)g_memdup(p2 + sizeof("\ntdxfilesize=") - 1, p3 - (p2 + sizeof("\ntdxfilesize=") - 1) + 1);
+        tmpstr[p3 - (p2 + sizeof("\ntdxfilesize=") - 1)] = '\0';
+        index_file_size = atol(tmpstr);
+        g_free(tmpstr);
+    }
+    else
+    {
+
+        p2 = strstr(p1, "\nidxfilesize=");
+        if (!p2)
+        {
+            g_free(buffer);
+            return false;
+        }
+
+        p3 = strchr(p2 + sizeof("\nidxfilesize=") - 1, '\n');
+        tmpstr = (gchar *)g_memdup(p2 + sizeof("\nidxfilesize=") - 1, p3 - (p2 + sizeof("\nidxfilesize=") - 1) + 1);
+        tmpstr[p3 - (p2 + sizeof("\nidxfilesize=") - 1)] = '\0';
+        index_file_size = atol(tmpstr);
+        g_free(tmpstr);
+    }
+
+    p2 = strstr(p1, "\nbookname=");
+
+    if (!p2)
+    {
+        g_free(buffer);
+        return false;
+    }
+
+    p2 = p2 + sizeof("\nbookname=") - 1;
+    p3 = strchr(p2, '\n');
+    bookname.assign(p2, p3 - p2);
+
+    p2 = strstr(p1, "\nauthor=");
+    if (p2)
+    {
+        p2 = p2 + sizeof("\nauthor=") - 1;
+        p3 = strchr(p2, '\n');
+        author.assign(p2, p3 - p2);
+    }
+
+    p2 = strstr(p1, "\nemail=");
+    if (p2)
+    {
+        p2 = p2 + sizeof("\nemail=") - 1;
+        p3 = strchr(p2, '\n');
+        email.assign(p2, p3 - p2);
+    }
+
+    p2 = strstr(p1, "\nwebsite=");
+    if (p2)
+    {
+        p2 = p2 + sizeof("\nwebsite=") - 1;
+        p3 = strchr(p2, '\n');
+        website.assign(p2, p3 - p2);
+    }
+
+    p2 = strstr(p1, "\ndate=");
+    if (p2)
+    {
+        p2 = p2 + sizeof("\ndate=") - 1;
+        p3 = strchr(p2, '\n');
+        date.assign(p2, p3 - p2);
+    }
+
+    p2 = strstr(p1, "\ndescription=");
+    if (p2)
+    {
+        p2 = p2 + sizeof("\ndescription=") - 1;
+        p3 = strchr(p2, '\n');
+        description.assign(p2, p3 - p2);
+    }
+
+    p2 = strstr(p1, "\nsametypesequence=");
+    if (p2)
+    {
+        p2 += sizeof("\nsametypesequence=") - 1;
+        p3 = strchr(p2, '\n');
+        sametypesequence.assign(p2, p3 - p2);
+    }
+
+    g_free(buffer);
+
+    return true;
+}
+//===================================================================
+DictBase::DictBase()
+{
+    dictfile = NULL;
+    cache_cur = 0;
+}
+
+DictBase::~DictBase()
+{
+    if (dictfile)
+        fclose(dictfile);
+}
+
+gchar* DictBase::GetWordData(guint32 idxitem_offset, guint32 idxitem_size)
+{
+    for (int i = 0; i < WORDDATA_CACHE_NUM; i++)
+        if (cache[i].data && cache[i].offset == idxitem_offset)
+            return cache[i].data;
+
+    if (dictfile)
+        fseek(dictfile, idxitem_offset, SEEK_SET);
+
+    gchar *data;
+    if (!sametypesequence.empty())
+    {
+        gchar *origin_data = (gchar *)g_malloc(idxitem_size);
+
+        if (dictfile)
+            fread(origin_data, idxitem_size, 1, dictfile);
+        else
+            dictdzfile->read(origin_data, idxitem_offset, idxitem_size);
+
+        guint32 data_size;
+        gint sametypesequence_len = sametypesequence.length();
+        //there have sametypesequence_len char being omitted.
+        data_size = idxitem_size + sizeof(guint32) + sametypesequence_len;
+        //if the last item's size is determined by the end up '\0',then +=sizeof(gchar);
+        //if the last item's size is determined by the head guint32 type data,then +=sizeof(guint32);
+        switch (sametypesequence[sametypesequence_len - 1])
+        {
+        case 'm':
+        case 't':
+        case 'y':
+        case 'l':
+        case 'g':
+        case 'x':
+            data_size += sizeof(gchar);
+            break;
+        case 'W':
+        case 'P':
+            data_size += sizeof(guint32);
+            break;
+        default:
+            if (g_ascii_isupper(sametypesequence[sametypesequence_len - 1]))
+                data_size += sizeof(guint32);
+            else
+                data_size += sizeof(gchar);
+            break;
+        }
+        data = (gchar *)g_malloc(data_size);
+        gchar *p1, *p2;
+        p1 = data + sizeof(guint32);
+        p2 = origin_data;
+        guint32 sec_size;
+        //copy the head items.
+        for (int i = 0; i < sametypesequence_len - 1; i++)
+        {
+            *p1 = sametypesequence[i];
+            p1 += sizeof(gchar);
+            switch (sametypesequence[i])
+            {
+            case 'm':
+            case 't':
+            case 'y':
+            case 'l':
+            case 'g':
+            case 'x':
+                sec_size = strlen(p2) + 1;
+                memcpy(p1, p2, sec_size);
+                p1 += sec_size;
+                p2 += sec_size;
+                break;
+            case 'W':
+            case 'P':
+                sec_size = *reinterpret_cast<guint32 *>(p2);
+                sec_size += sizeof(guint32);
+                memcpy(p1, p2, sec_size);
+                p1 += sec_size;
+                p2 += sec_size;
+                break;
+            default:
+                if (g_ascii_isupper(sametypesequence[i]))
+                {
+                    sec_size = *reinterpret_cast<guint32 *>(p2);
+                    sec_size += sizeof(guint32);
+                }
+                else
+                {
+                    sec_size = strlen(p2) + 1;
+                }
+                memcpy(p1, p2, sec_size);
+                p1 += sec_size;
+                p2 += sec_size;
+                break;
+            }
+        }
+        //calculate the last item 's size.
+        sec_size = idxitem_size - (p2 - origin_data);
+        *p1 = sametypesequence[sametypesequence_len - 1];
+        p1 += sizeof(gchar);
+        switch (sametypesequence[sametypesequence_len - 1])
+        {
+        case 'm':
+        case 't':
+        case 'y':
+        case 'l':
+        case 'g':
+        case 'x':
+            memcpy(p1, p2, sec_size);
+            p1 += sec_size;
+            *p1 = '\0'; //add the end up '\0';
+            break;
+        case 'W':
+        case 'P':
+            *reinterpret_cast<guint32 *>(p1) = sec_size;
+            p1 += sizeof(guint32);
+            memcpy(p1, p2, sec_size);
+            break;
+        default:
+            if (g_ascii_isupper(sametypesequence[sametypesequence_len - 1]))
+            {
+                *reinterpret_cast<guint32 *>(p1) = sec_size;
+                p1 += sizeof(guint32);
+                memcpy(p1, p2, sec_size);
+            }
+            else
+            {
+                memcpy(p1, p2, sec_size);
+                p1 += sec_size;
+                *p1 = '\0';
+            }
+            break;
+        }
+        g_free(origin_data);
+        *reinterpret_cast<guint32 *>(data) = data_size;
+    }
+    else
+    {
+        data = (gchar *)g_malloc(idxitem_size + sizeof(guint32));
+        if (dictfile)
+            fread(data + sizeof(guint32), idxitem_size, 1, dictfile);
+        else
+            dictdzfile->read(data + sizeof(guint32), idxitem_offset, idxitem_size);
+        *reinterpret_cast<guint32 *>(data) = idxitem_size + sizeof(guint32);
+    }
+    g_free(cache[cache_cur].data);
+
+    cache[cache_cur].data = data;
+    cache[cache_cur].offset = idxitem_offset;
+    cache_cur++;
+    if (cache_cur == WORDDATA_CACHE_NUM)
+        cache_cur = 0;
+    return data;
+}
+
+inline bool DictBase::containSearchData()
+{
+    if (sametypesequence.empty())
+        return true;
+
+    return sametypesequence.find_first_of("mlgxty") != std::string::npos;
+}
+
+bool DictBase::SearchData(std::vector<std::string> &SearchWords, guint32 idxitem_offset, guint32 idxitem_size, gchar *origin_data)
+{
+    int nWord = SearchWords.size();
+    std::vector<bool> WordFind(nWord, false);
+    int nfound = 0;
+
+    if (dictfile)
+        fseek(dictfile, idxitem_offset, SEEK_SET);
+    if (dictfile)
+        fread(origin_data, idxitem_size, 1, dictfile);
+    else
+        dictdzfile->read(origin_data, idxitem_offset, idxitem_size);
+    gchar *p = origin_data;
+    guint32 sec_size;
+    int j;
+    if (!sametypesequence.empty())
+    {
+        gint sametypesequence_len = sametypesequence.length();
+        for (int i = 0; i < sametypesequence_len - 1; i++)
+        {
+            switch (sametypesequence[i])
+            {
+            case 'm':
+            case 't':
+            case 'y':
+            case 'l':
+            case 'g':
+            case 'x':
+                for (j = 0; j < nWord; j++)
+                    if (!WordFind[j] && strstr(p, SearchWords[j].c_str()))
+                    {
+                        WordFind[j] = true;
+                        ++nfound;
+                    }
+
+
+                if (nfound == nWord)
+                    return true;
+                sec_size = strlen(p) + 1;
+                p += sec_size;
+                break;
+            default:
+                if (g_ascii_isupper(sametypesequence[i]))
+                {
+                    sec_size = *reinterpret_cast<guint32 *>(p);
+                    sec_size += sizeof(guint32);
+                }
+                else
+                {
+                    sec_size = strlen(p) + 1;
+                }
+                p += sec_size;
+            }
+        }
+        switch (sametypesequence[sametypesequence_len - 1])
+        {
+        case 'm':
+        case 't':
+        case 'y':
+        case 'l':
+        case 'g':
+        case 'x':
+            sec_size = idxitem_size - (p - origin_data);
+            for (j = 0; j < nWord; j++)
+                if (!WordFind[j] &&
+                        g_strstr_len(p, sec_size, SearchWords[j].c_str()))
+                {
+                    WordFind[j] = true;
+                    ++nfound;
+                }
+
+
+            if (nfound == nWord)
+                return true;
+            break;
+        }
+    }
+    else
+    {
+        while (guint32(p - origin_data) < idxitem_size)
+        {
+            switch (*p)
+            {
+            case 'm':
+            case 't':
+            case 'y':
+            case 'l':
+            case 'g':
+            case 'x':
+                for (j = 0; j < nWord; j++)
+                    if (!WordFind[j] && strstr(p, SearchWords[j].c_str()))
+                    {
+                        WordFind[j] = true;
+                        ++nfound;
+                    }
+
+                if (nfound == nWord)
+                    return true;
+                sec_size = strlen(p) + 1;
+                p += sec_size;
+                break;
+            default:
+                if (g_ascii_isupper(*p))
+                {
+                    sec_size = *reinterpret_cast<guint32 *>(p);
+                    sec_size += sizeof(guint32);
+                }
+                else
+                {
+                    sec_size = strlen(p) + 1;
+                }
+                p += sec_size;
+            }
+        }
+    }
+    return false;
+}
+
+class offset_index : public index_file
+{
+    public:
+        offset_index() : idxfile(NULL)
+        {}
+        ~offset_index();
+        bool load(const std::string& url, gulong wc, gulong fsize);
+        const gchar *get_key(glong idx);
+        void get_data(glong idx);
+        const gchar *get_key_and_data(glong idx);
+        bool lookup(const char *str, glong &idx);
+    private:
+        static const gint ENTR_PER_PAGE = 32;
+        static const char *CACHE_MAGIC;
+
+        std::vector<guint32> wordoffset;
+        FILE *idxfile;
+        gulong wordcount;
+
+        gchar wordentry_buf[256 + sizeof(guint32)*2]; // The length of "word_str" should be less than 256. See src/tools/DICTFILE_FORMAT.
+        struct index_entry
+        {
+            glong idx;
+            std::string keystr;
+            void assign(glong i, const std::string& str)
+            {
+                idx = i;
+                keystr.assign(str);
+            }
+        };
+        index_entry first, last, middle, real_last;
+
+        struct page_entry
+        {
+            gchar *keystr;
+            guint32 off, size;
+        };
+        std::vector<gchar> page_data;
+        struct page_t
+        {
+            glong idx;
+            page_entry entries[ENTR_PER_PAGE];
+
+            page_t(): idx( -1)
+            {}
+            void fill(gchar *data, gint nent, glong idx_);
+        }
+        page;
+        gulong load_page(glong page_idx);
+        const gchar *read_first_on_page_key(glong page_idx);
+        const gchar *get_first_on_page_key(glong page_idx);
+        bool load_cache(const std::string& url);
+        bool save_cache(const std::string& url);
+        static strlist_t get_cache_variant(const std::string& url);
+};
+
+const char *offset_index::CACHE_MAGIC = "StarDict's Cache, Version: 0.1";
+
+class wordlist_index : public index_file
+{
+    public:
+        wordlist_index() : idxdatabuf(NULL)
+        {}
+        ~wordlist_index();
+        bool load(const std::string& url, gulong wc, gulong fsize);
+        const gchar *get_key(glong idx);
+        void get_data(glong idx);
+        const gchar *get_key_and_data(glong idx);
+        bool lookup(const char *str, glong &idx);
+    private:
+        gchar *idxdatabuf;
+        std::vector<gchar *> wordlist;
+};
+
+void offset_index::page_t::fill(gchar *data, gint nent, glong idx_)
+{
+    idx = idx_;
+    gchar *p = data;
+    glong len;
+    for (gint i = 0; i < nent; ++i)
+    {
+        entries[i].keystr = p;
+        len = strlen(p);
+        p += len + 1;
+        entries[i].off = g_ntohl(*reinterpret_cast<guint32 *>(p));
+        p += sizeof(guint32);
+        entries[i].size = g_ntohl(*reinterpret_cast<guint32 *>(p));
+        p += sizeof(guint32);
+    }
+}
+
+offset_index::~offset_index()
+{
+    if (idxfile)
+        fclose(idxfile);
+}
+
+inline const gchar *offset_index::read_first_on_page_key(glong page_idx)
+{
+    fseek(idxfile, wordoffset[page_idx], SEEK_SET);
+    guint page_size = wordoffset[page_idx + 1] - wordoffset[page_idx];
+    fread(wordentry_buf, std::min<guint>(sizeof(wordentry_buf), page_size), 1, idxfile); //TODO: check returned values, deal with word entry that strlen>255.
+    return wordentry_buf;
+}
+
+inline const gchar *offset_index::get_first_on_page_key(glong page_idx)
+{
+    if (page_idx < middle.idx)
+    {
+        if (page_idx == first.idx)
+            return first.keystr.c_str();
+        return read_first_on_page_key(page_idx);
+    }
+    else if (page_idx > middle.idx)
+    {
+        if (page_idx == last.idx)
+            return last.keystr.c_str();
+        return read_first_on_page_key(page_idx);
+    }
+    else
+        return middle.keystr.c_str();
+}
+
+bool offset_index::load_cache(const std::string& url)
+{
+    strlist_t vars = get_cache_variant(url);
+
+    for (strlist_t::const_iterator it = vars.begin(); it != vars.end(); ++it)
+    {
+        struct stat idxstat, cachestat;
+        if (g_stat(url.c_str(), &idxstat) != 0 ||
+                g_stat(it->c_str(), &cachestat) != 0)
+            continue;
+        if (cachestat.st_mtime < idxstat.st_mtime)
+            continue;
+        MapFile mf;
+        if (!mf.open(it->c_str(), cachestat.st_size))
+            continue;
+        if (strncmp(mf.begin(), CACHE_MAGIC, strlen(CACHE_MAGIC)) != 0)
+            continue;
+        memcpy(&wordoffset[0], mf.begin() + strlen(CACHE_MAGIC), wordoffset.size()*sizeof(wordoffset[0]));
+        return true;
+
+    }
+
+    return false;
+}
+
+strlist_t offset_index::get_cache_variant(const std::string& url)
+{
+    strlist_t res;
+    res.push_back(url + ".oft");
+    if (!g_file_test(g_get_user_cache_dir(), G_FILE_TEST_EXISTS) &&
+            g_mkdir(g_get_user_cache_dir(), 0700) == -1)
+        return res;
+
+    std::string cache_dir = std::string(g_get_user_cache_dir()) + G_DIR_SEPARATOR_S + "sdcv";
+
+    if (!g_file_test(cache_dir.c_str(), G_FILE_TEST_EXISTS))
+    {
+        if (g_mkdir(cache_dir.c_str(), 0700) == -1)
+            return res;
+    }
+    else if (!g_file_test(cache_dir.c_str(), G_FILE_TEST_IS_DIR))
+        return res;
+
+    gchar *base = g_path_get_basename(url.c_str());
+    res.push_back(cache_dir + G_DIR_SEPARATOR_S + base + ".oft");
+    g_free(base);
+    return res;
+}
+
+bool offset_index::save_cache(const std::string& url)
+{
+    strlist_t vars = get_cache_variant(url);
+    for (strlist_t::const_iterator it = vars.begin(); it != vars.end(); ++it)
+    {
+        FILE *out = fopen(it->c_str(), "wb");
+        if (!out)
+            continue;
+        if (fwrite(CACHE_MAGIC, 1, strlen(CACHE_MAGIC), out) != strlen(CACHE_MAGIC))
+            continue;
+        if (fwrite(&wordoffset[0], sizeof(wordoffset[0]), wordoffset.size(), out) != wordoffset.size())
+            continue;
+        fclose(out);
+        printf("save to cache %s\n", url.c_str());
+        return true;
+    }
+    return false;
+}
+
+bool offset_index::load(const std::string& url, gulong wc, gulong fsize)
+{
+    wordcount = wc;
+    gulong npages = (wc - 1) / ENTR_PER_PAGE + 2;
+    wordoffset.resize(npages);
+    if (!load_cache(url))
+    { //map file will close after finish of block
+        MapFile map_file;
+        if (!map_file.open(url.c_str(), fsize))
+            return false;
+        const gchar *idxdatabuffer = map_file.begin();
+
+        const gchar *p1 = idxdatabuffer;
+        gulong index_size;
+        guint32 j = 0;
+        for (guint32 i = 0; i < wc; i++)
+        {
+            index_size = strlen(p1) + 1 + 2 * sizeof(guint32);
+            if (i % ENTR_PER_PAGE == 0)
+            {
+                wordoffset[j] = p1 - idxdatabuffer;
+                ++j;
+            }
+            p1 += index_size;
+        }
+        wordoffset[j] = p1 - idxdatabuffer;
+        if (!save_cache(url))
+            fprintf(stderr, "cache update failed\n");
+    }
+
+    if (!(idxfile = fopen(url.c_str(), "rb")))
+    {
+        wordoffset.resize(0);
+        return false;
+    }
+
+    first.assign(0, read_first_on_page_key(0));
+    last.assign(wordoffset.size() - 2, read_first_on_page_key(wordoffset.size() - 2));
+    middle.assign((wordoffset.size() - 2) / 2, read_first_on_page_key((wordoffset.size() - 2) / 2));
+    real_last.assign(wc - 1, get_key(wc - 1));
+
+    return true;
+}
+
+inline gulong offset_index::load_page(glong page_idx)
+{
+    gulong nentr = ENTR_PER_PAGE;
+    if (page_idx == glong(wordoffset.size() - 2))
+        if ((nentr = wordcount % ENTR_PER_PAGE) == 0)
+            nentr = ENTR_PER_PAGE;
+
+
+    if (page_idx != page.idx)
+    {
+        page_data.resize(wordoffset[page_idx + 1] - wordoffset[page_idx]);
+        fseek(idxfile, wordoffset[page_idx], SEEK_SET);
+        fread(&page_data[0], 1, page_data.size(), idxfile);
+        page.fill(&page_data[0], nentr, page_idx);
+    }
+
+    return nentr;
+}
+
+const gchar *offset_index::get_key(glong idx)
+{
+    load_page(idx / ENTR_PER_PAGE);
+    glong idx_in_page = idx % ENTR_PER_PAGE;
+    wordentry_offset = page.entries[idx_in_page].off;
+    wordentry_size = page.entries[idx_in_page].size;
+
+    return page.entries[idx_in_page].keystr;
+}
+
+void offset_index::get_data(glong idx)
+{
+    get_key(idx);
+}
+
+const gchar *offset_index::get_key_and_data(glong idx)
+{
+    return get_key(idx);
+}
+
+bool offset_index::lookup(const char *str, glong &idx)
+{
+    bool bFound = false;
+    glong iFrom;
+    glong iTo = wordoffset.size() - 2;
+    gint cmpint;
+    glong iThisIndex;
+    if (stardict_strcmp(str, first.keystr.c_str()) < 0)
+    {
+        idx = 0;
+        return false;
+    }
+    else if (stardict_strcmp(str, real_last.keystr.c_str()) > 0)
+    {
+        idx = INVALID_INDEX;
+        return false;
+    }
+    else
+    {
+        iFrom = 0;
+        iThisIndex = 0;
+        while (iFrom <= iTo)
+        {
+            iThisIndex = (iFrom + iTo) / 2;
+            cmpint = stardict_strcmp(str, get_first_on_page_key(iThisIndex));
+            if (cmpint > 0)
+                iFrom = iThisIndex + 1;
+            else if (cmpint < 0)
+                iTo = iThisIndex - 1;
+            else
+            {
+                bFound = true;
+                break;
+            }
+        }
+        if (!bFound)
+            idx = iTo;    //prev
+        else
+            idx = iThisIndex;
+    }
+    if (!bFound)
+    {
+        gulong netr = load_page(idx);
+        iFrom = 1; // Needn't search the first word anymore.
+        iTo = netr - 1;
+        iThisIndex = 0;
+        while (iFrom <= iTo)
+        {
+            iThisIndex = (iFrom + iTo) / 2;
+            cmpint = stardict_strcmp(str, page.entries[iThisIndex].keystr);
+            if (cmpint > 0)
+                iFrom = iThisIndex + 1;
+            else if (cmpint < 0)
+                iTo = iThisIndex - 1;
+            else
+            {
+                bFound = true;
+                break;
+            }
+        }
+        idx *= ENTR_PER_PAGE;
+        if (!bFound)
+            idx += iFrom;    //next
+        else
+            idx += iThisIndex;
+    }
+    else
+    {
+        idx *= ENTR_PER_PAGE;
+    }
+    return bFound;
+}
+
+wordlist_index::~wordlist_index()
+{
+    g_free(idxdatabuf);
+}
+
+bool wordlist_index::load(const std::string& url, gulong wc, gulong fsize)
+{
+    gzFile in = gzopen(url.c_str(), "rb");
+    if (in == NULL)
+        return false;
+
+    idxdatabuf = (gchar *)g_malloc(fsize);
+
+    gulong len = gzread(in, idxdatabuf, fsize);
+    gzclose(in);
+
+    if (len != fsize)
+        return false;
+
+    wordlist.resize(wc + 1);
+    gchar *p1 = idxdatabuf;
+    guint32 i;
+    for (i = 0; i < wc; i++)
+    {
+        wordlist[i] = p1;
+        p1 += strlen(p1) + 1 + 2 * sizeof(guint32);
+    }
+    wordlist[wc] = p1;
+
+    return true;
+}
+
+const gchar *wordlist_index::get_key(glong idx)
+{
+    return wordlist[idx];
+}
+
+void wordlist_index::get_data(glong idx)
+{
+    gchar *p1 = wordlist[idx] + strlen(wordlist[idx]) + sizeof(gchar);
+    wordentry_offset = g_ntohl(*reinterpret_cast<guint32 *>(p1));
+    p1 += sizeof(guint32);
+    wordentry_size = g_ntohl(*reinterpret_cast<guint32 *>(p1));
+}
+
+const gchar *wordlist_index::get_key_and_data(glong idx)
+{
+    get_data(idx);
+    return get_key(idx);
+}
+
+bool wordlist_index::lookup(const char *str, glong &idx)
+{
+    bool bFound = false;
+    glong iTo = wordlist.size() - 2;
+
+    if (stardict_strcmp(str, get_key(0)) < 0)
+    {
+        idx = 0;
+    }
+    else if (stardict_strcmp(str, get_key(iTo)) > 0)
+    {
+        idx = INVALID_INDEX;
+    }
+    else
+    {
+        glong iThisIndex = 0;
+        glong iFrom = 0;
+        gint cmpint;
+        while (iFrom <= iTo)
+        {
+            iThisIndex = (iFrom + iTo) / 2;
+            cmpint = stardict_strcmp(str, get_key(iThisIndex));
+            if (cmpint > 0)
+                iFrom = iThisIndex + 1;
+            else if (cmpint < 0)
+                iTo = iThisIndex - 1;
+            else
+            {
+                bFound = true;
+                break;
+            }
+        }
+        if (!bFound)
+            idx = iFrom;    //next
+        else
+            idx = iThisIndex;
+    }
+    return bFound;
+}
+
+//===================================================================
+bool Dict::load(const std::string& ifofilename)
+{
+    gulong idxfilesize;
+    if (!load_ifofile(ifofilename, idxfilesize))
+        return false;
+
+    std::string fullfilename(ifofilename);
+    fullfilename.replace(fullfilename.length() - sizeof("ifo") + 1, sizeof("ifo") - 1, "dict.dz");
+
+    if (g_file_test(fullfilename.c_str(), G_FILE_TEST_EXISTS))
+    {
+        dictdzfile.reset(new dictData);
+        if (!dictdzfile->open(fullfilename, 0))
+        {
+            //g_print("open file %s failed!\n",fullfilename);
+            return false;
+        }
+    }
+    else
+    {
+        fullfilename.erase(fullfilename.length() - sizeof(".dz") + 1, sizeof(".dz") - 1);
+        dictfile = fopen(fullfilename.c_str(), "rb");
+        if (!dictfile)
+        {
+            //g_print("open file %s failed!\n",fullfilename);
+            return false;
+        }
+    }
+
+    fullfilename = ifofilename;
+    fullfilename.replace(fullfilename.length() - sizeof("ifo") + 1, sizeof("ifo") - 1, "idx.gz");
+
+    if (g_file_test(fullfilename.c_str(), G_FILE_TEST_EXISTS))
+    {
+        idx_file.reset(new wordlist_index);
+    }
+    else
+    {
+        fullfilename.erase(fullfilename.length() - sizeof(".gz") + 1, sizeof(".gz") - 1);
+        idx_file.reset(new offset_index);
+    }
+
+    if (!idx_file->load(fullfilename, wordcount, idxfilesize))
+        return false;
+
+    //g_print("bookname: %s , wordcount %lu\n", bookname.c_str(), narticles());
+    return true;
+}
+
+bool Dict::load_ifofile(const std::string& ifofilename, gulong &idxfilesize)
+{
+    DictInfo dict_info;
+    if (!dict_info.load_from_ifo_file(ifofilename, false))
+        return false;
+    if (dict_info.wordcount == 0)
+        return false;
+
+
+
+    ifo_file_name = dict_info.ifo_file_name;
+    wordcount = dict_info.wordcount;
+    bookname = dict_info.bookname;
+
+    idxfilesize = dict_info.index_file_size;
+
+    sametypesequence = dict_info.sametypesequence;
+
+    return true;
+}
+
+bool Dict::LookupWithRule(GPatternSpec *pspec, glong *aIndex, int iBuffLen)
+{
+    int iIndexCount = 0;
+
+    for (guint32 i = 0; i < narticles() && iIndexCount < iBuffLen - 1; i++)
+        if (g_pattern_match_string(pspec, get_key(i)))
+            aIndex[iIndexCount++] = i;
+
+    aIndex[iIndexCount] = -1; // -1 is the end.
+
+    return (iIndexCount > 0);
+}
+
+//===================================================================
+Libs::Libs(progress_func_t f)
+{
+    progress_func = f;
+    iMaxFuzzyDistance = MAX_FUZZY_DISTANCE; //need to read from cfg.
+}
+
+Libs::~Libs()
+{
+    for (std::vector<Dict *>::iterator p = oLib.begin(); p != oLib.end(); ++p)
+        delete *p;
+}
+
+void Libs::load_dict(const std::string& url)
+{
+    Dict *lib = new Dict;
+    if (lib->load(url))
+        oLib.push_back(lib);
+    else
+        delete lib;
+}
+
+class DictLoader
+{
+    public:
+        DictLoader(Libs& lib_): lib(lib_)
+        {}
+        void operator()(const std::string& url, bool disable)
+        {
+            if (!disable)
+                lib.load_dict(url);
+        }
+    private:
+        Libs& lib;
+};
+
+void Libs::load(const strlist_t& dicts_dirs,
+                const strlist_t& order_list,
+                const strlist_t& disable_list)
+{
+    for_each_file(dicts_dirs, ".ifo", order_list, disable_list,
+                  DictLoader(*this));
+}
+
+class DictReLoader
+{
+    public:
+        DictReLoader(std::vector<Dict *> &p, std::vector<Dict *> &f,
+                     Libs& lib_) : prev(p), future(f), lib(lib_)
+        {}
+        void operator()(const std::string& url, bool disable)
+        {
+            if (!disable)
+            {
+                Dict *dict = find(url);
+                if (dict)
+                    future.push_back(dict);
+                else
+                    lib.load_dict(url);
+            }
+        }
+    private:
+        std::vector<Dict *> &prev;
+        std::vector<Dict *> &future;
+        Libs& lib;
+
+        Dict *find(const std::string& url)
+        {
+            std::vector<Dict *>::iterator it;
+            for (it = prev.begin(); it != prev.end(); ++it)
+                if ((*it)->ifofilename() == url)
+                    break;
+            if (it != prev.end())
+            {
+                Dict *res = *it;
+                prev.erase(it);
+                return res;
+            }
+            return NULL;
+        }
+};
+
+void Libs::reload(const strlist_t& dicts_dirs,
+                  const strlist_t& order_list,
+                  const strlist_t& disable_list)
+{
+    std::vector<Dict *> prev(oLib);
+    oLib.clear();
+    for_each_file(dicts_dirs, ".ifo", order_list, disable_list,
+                  DictReLoader(prev, oLib, *this));
+    for (std::vector<Dict *>::iterator it = prev.begin(); it != prev.end(); ++it)
+        delete *it;
+}
+
+const gchar *Libs::poGetCurrentWord(glong * iCurrent)
+{
+    const gchar *poCurrentWord = NULL;
+    const gchar *word;
+    for (std::vector<Dict *>::size_type iLib = 0; iLib<oLib.size(); iLib++)
+    {
+        if (iCurrent[iLib] == INVALID_INDEX)
+            continue;
+        if ( iCurrent[iLib] >= narticles(iLib) || iCurrent[iLib] < 0)
+            continue;
+        if ( poCurrentWord == NULL )
+        {
+            poCurrentWord = poGetWord(iCurrent[iLib], iLib);
+        }
+        else
+        {
+            word = poGetWord(iCurrent[iLib], iLib);
+
+            if (stardict_strcmp(poCurrentWord, word) > 0 )
+                poCurrentWord = word;
+        }
+    }
+    return poCurrentWord;
+}
+
+const gchar *
+Libs::poGetNextWord(const gchar *sWord, glong *iCurrent)
+{
+    // the input can be:
+    // (word,iCurrent),read word,write iNext to iCurrent,and return next word. used by TopWin::NextCallback();
+    // (NULL,iCurrent),read iCurrent,write iNext to iCurrent,and return next word. used by AppCore::ListWords();
+    const gchar *poCurrentWord = NULL;
+    std::vector<Dict *>::size_type iCurrentLib = 0;
+    const gchar *word;
+
+    for (std::vector<Dict *>::size_type iLib = 0;iLib<oLib.size();iLib++)
+    {
+        if (sWord)
+            oLib[iLib]->Lookup(sWord, iCurrent[iLib]);
+        if (iCurrent[iLib] == INVALID_INDEX)
+            continue;
+        if (iCurrent[iLib] >= narticles(iLib) || iCurrent[iLib] < 0)
+            continue;
+        if (poCurrentWord == NULL )
+        {
+            poCurrentWord = poGetWord(iCurrent[iLib], iLib);
+            iCurrentLib = iLib;
+        }
+        else
+        {
+            word = poGetWord(iCurrent[iLib], iLib);
+
+            if (stardict_strcmp(poCurrentWord, word) > 0 )
+            {
+                poCurrentWord = word;
+                iCurrentLib = iLib;
+            }
+        }
+    }
+    if (poCurrentWord)
+    {
+        iCurrent[iCurrentLib]
+        ++;
+        for (std::vector<Dict *>::size_type iLib = 0;iLib<oLib.size();iLib++)
+        {
+            if (iLib == iCurrentLib)
+                continue;
+            if (iCurrent[iLib] == INVALID_INDEX)
+                continue;
+            if ( iCurrent[iLib] >= narticles(iLib) || iCurrent[iLib] < 0)
+                continue;
+            if (strcmp(poCurrentWord, poGetWord(iCurrent[iLib], iLib)) == 0 )
+                iCurrent[iLib]++;
+        }
+        poCurrentWord = poGetCurrentWord(iCurrent);
+    }
+    return poCurrentWord;
+}
+
+
+const gchar *
+Libs::poGetPreWord(glong * iCurrent)
+{
+    // used by TopWin::PreviousCallback(); the iCurrent is cached by AppCore::TopWinWordChange();
+    const gchar *poCurrentWord = NULL;
+    std::vector<Dict *>::size_type iCurrentLib = 0;
+    const gchar *word;
+
+    for (std::vector<Dict *>::size_type iLib = 0;iLib<oLib.size();iLib++)
+    {
+        if (iCurrent[iLib] == INVALID_INDEX)
+            iCurrent[iLib] = narticles(iLib);
+        else
+        {
+            if ( iCurrent[iLib] > narticles(iLib) || iCurrent[iLib] <= 0)
+                continue;
+        }
+        if ( poCurrentWord == NULL )
+        {
+            poCurrentWord = poGetWord(iCurrent[iLib] - 1, iLib);
+            iCurrentLib = iLib;
+        }
+        else
+        {
+            word = poGetWord(iCurrent[iLib] - 1, iLib);
+            if (stardict_strcmp(poCurrentWord, word) < 0 )
+            {
+                poCurrentWord = word;
+                iCurrentLib = iLib;
+            }
+        }
+    }
+
+    if (poCurrentWord)
+    {
+        iCurrent[iCurrentLib]
+        --;
+        for (std::vector<Dict *>::size_type iLib = 0;iLib<oLib.size();iLib++)
+        {
+            if (iLib == iCurrentLib)
+                continue;
+            if (iCurrent[iLib] > narticles(iLib) || iCurrent[iLib] <= 0)
+                continue;
+            if (strcmp(poCurrentWord, poGetWord(iCurrent[iLib] - 1, iLib)) == 0)
+            {
+                iCurrent[iLib]--;
+            }
+            else
+            {
+                if (iCurrent[iLib] == narticles(iLib))
+                    iCurrent[iLib] = INVALID_INDEX;
+            }
+        }
+    }
+    return poCurrentWord;
+}
+
+bool Libs::LookupSimilarWord(const gchar* sWord, glong & iWordIndex, int iLib)
+{
+    glong iIndex;
+    bool bFound = false;
+    gchar *casestr;
+
+    if (!bFound)
+    {
+        // to lower case.
+        casestr = g_utf8_strdown(sWord, -1);
+        if (strcmp(casestr, sWord))
+        {
+            if (oLib[iLib]->Lookup(casestr, iIndex))
+                bFound = true;
+        }
+        g_free(casestr);
+        // to upper case.
+        if (!bFound)
+        {
+            casestr = g_utf8_strup(sWord, -1);
+            if (strcmp(casestr, sWord))
+            {
+                if (oLib[iLib]->Lookup(casestr, iIndex))
+                    bFound = true;
+            }
+            g_free(casestr);
+        }
+        // Upper the first character and lower others.
+        if (!bFound)
+        {
+            gchar *nextchar = g_utf8_next_char(sWord);
+            gchar *firstchar = g_utf8_strup(sWord, nextchar - sWord);
+            nextchar = g_utf8_strdown(nextchar, -1);
+            casestr = g_strdup_printf("%s%s", firstchar, nextchar);
+            g_free(firstchar);
+            g_free(nextchar);
+            if (strcmp(casestr, sWord))
+            {
+                if (oLib[iLib]->Lookup(casestr, iIndex))
+                    bFound = true;
+            }
+            g_free(casestr);
+        }
+    }
+
+    if (bIsPureEnglish(sWord))
+    {
+        // If not Found , try other status of sWord.
+        int iWordLen = strlen(sWord);
+        bool isupcase;
+
+        gchar *sNewWord = (gchar *)g_malloc(iWordLen + 1);
+
+        //cut one char "s" or "d"
+        if (!bFound && iWordLen > 1)
+        {
+            isupcase = sWord[iWordLen - 1] == 'S' || !strncmp(&sWord[iWordLen - 2], "ED", 2);
+            if (isupcase || sWord[iWordLen - 1] == 's' || !strncmp(&sWord[iWordLen - 2], "ed", 2))
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 1] = '\0'; // cut "s" or "d"
+                if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                    bFound = true;
+                else if (isupcase || g_ascii_isupper(sWord[0]))
+                {
+                    casestr = g_ascii_strdown(sNewWord, -1);
+                    if (strcmp(casestr, sNewWord))
+                    {
+                        if (oLib[iLib]->Lookup(casestr, iIndex))
+                            bFound = true;
+                    }
+                    g_free(casestr);
+                }
+            }
+        }
+
+        //cut "ly"
+        if (!bFound && iWordLen > 2)
+        {
+            isupcase = !strncmp(&sWord[iWordLen - 2], "LY", 2);
+            if (isupcase || (!strncmp(&sWord[iWordLen - 2], "ly", 2)))
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 2] = '\0';  // cut "ly"
+                if (iWordLen > 5 && sNewWord[iWordLen - 3] == sNewWord[iWordLen - 4]
+                        && !bIsVowel(sNewWord[iWordLen - 4]) &&
+                        bIsVowel(sNewWord[iWordLen - 5]))
+                { //doubled
+
+                    sNewWord[iWordLen - 3] = '\0';
+                    if ( oLib[iLib]->Lookup(sNewWord, iIndex) )
+                        bFound = true;
+                    else
+                    {
+                        if (isupcase || g_ascii_isupper(sWord[0]))
+                        {
+                            casestr = g_ascii_strdown(sNewWord, -1);
+                            if (strcmp(casestr, sNewWord))
+                            {
+                                if (oLib[iLib]->Lookup(casestr, iIndex))
+                                    bFound = true;
+                            }
+                            g_free(casestr);
+                        }
+                        if (!bFound)
+                            sNewWord[iWordLen - 3] = sNewWord[iWordLen - 4];  //restore
+                    }
+                }
+                if (!bFound)
+                {
+                    if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                        bFound = true;
+                    else if (isupcase || g_ascii_isupper(sWord[0]))
+                    {
+                        casestr = g_ascii_strdown(sNewWord, -1);
+                        if (strcmp(casestr, sNewWord))
+                        {
+                            if (oLib[iLib]->Lookup(casestr, iIndex))
+                                bFound = true;
+                        }
+                        g_free(casestr);
+                    }
+                }
+            }
+        }
+
+        //cut "ing"
+        if (!bFound && iWordLen > 3)
+        {
+            isupcase = !strncmp(&sWord[iWordLen - 3], "ING", 3);
+            if (isupcase || !strncmp(&sWord[iWordLen - 3], "ing", 3) )
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 3] = '\0';
+                if ( iWordLen > 6 && (sNewWord[iWordLen - 4] == sNewWord[iWordLen - 5])
+                        && !bIsVowel(sNewWord[iWordLen - 5]) &&
+                        bIsVowel(sNewWord[iWordLen - 6]))
+                {  //doubled
+                    sNewWord[iWordLen - 4] = '\0';
+                    if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                        bFound = true;
+                    else
+                    {
+                        if (isupcase || g_ascii_isupper(sWord[0]))
+                        {
+                            casestr = g_ascii_strdown(sNewWord, -1);
+                            if (strcmp(casestr, sNewWord))
+                            {
+                                if (oLib[iLib]->Lookup(casestr, iIndex))
+                                    bFound = true;
+                            }
+                            g_free(casestr);
+                        }
+                        if (!bFound)
+                            sNewWord[iWordLen - 4] = sNewWord[iWordLen - 5];  //restore
+                    }
+                }
+                if ( !bFound )
+                {
+                    if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                        bFound = true;
+                    else if (isupcase || g_ascii_isupper(sWord[0]))
+                    {
+                        casestr = g_ascii_strdown(sNewWord, -1);
+                        if (strcmp(casestr, sNewWord))
+                        {
+                            if (oLib[iLib]->Lookup(casestr, iIndex))
+                                bFound = true;
+                        }
+                        g_free(casestr);
+                    }
+                }
+                if (!bFound)
+                {
+                    if (isupcase)
+                        strcat(sNewWord, "E"); // add a char "E"
+                    else
+                        strcat(sNewWord, "e"); // add a char "e"
+                    if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                        bFound = true;
+                    else if (isupcase || g_ascii_isupper(sWord[0]))
+                    {
+                        casestr = g_ascii_strdown(sNewWord, -1);
+                        if (strcmp(casestr, sNewWord))
+                        {
+                            if (oLib[iLib]->Lookup(casestr, iIndex))
+                                bFound = true;
+                        }
+                        g_free(casestr);
+                    }
+                }
+            }
+        }
+
+        //cut two char "es"
+        if (!bFound && iWordLen > 3)
+        {
+            isupcase = (!strncmp(&sWord[iWordLen - 2], "ES", 2) &&
+                        (sWord[iWordLen - 3] == 'S' ||
+                         sWord[iWordLen - 3] == 'X' ||
+                         sWord[iWordLen - 3] == 'O' ||
+                         (iWordLen > 4 && sWord[iWordLen - 3] == 'H' &&
+                          (sWord[iWordLen - 4] == 'C' ||
+                           sWord[iWordLen - 4] == 'S'))));
+            if (isupcase ||
+                    (!strncmp(&sWord[iWordLen - 2], "es", 2) &&
+                     (sWord[iWordLen - 3] == 's' || sWord[iWordLen - 3] == 'x' ||
+                      sWord[iWordLen - 3] == 'o' ||
+                      (iWordLen > 4 && sWord[iWordLen - 3] == 'h' &&
+                       (sWord[iWordLen - 4] == 'c' || sWord[iWordLen - 4] == 's')))))
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 2] = '\0';
+                if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                    bFound = true;
+                else if (isupcase || g_ascii_isupper(sWord[0]))
+                {
+                    casestr = g_ascii_strdown(sNewWord, -1);
+                    if (strcmp(casestr, sNewWord))
+                    {
+                        if (oLib[iLib]->Lookup(casestr, iIndex))
+                            bFound = true;
+                    }
+                    g_free(casestr);
+                }
+            }
+        }
+
+        //cut "ed"
+        if (!bFound && iWordLen > 3)
+        {
+            isupcase = !strncmp(&sWord[iWordLen - 2], "ED", 2);
+            if (isupcase || !strncmp(&sWord[iWordLen - 2], "ed", 2))
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 2] = '\0';
+                if (iWordLen > 5 && (sNewWord[iWordLen - 3] == sNewWord[iWordLen - 4])
+                        && !bIsVowel(sNewWord[iWordLen - 4]) &&
+                        bIsVowel(sNewWord[iWordLen - 5]))
+                { //doubled
+                    sNewWord[iWordLen - 3] = '\0';
+                    if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                        bFound = true;
+                    else
+                    {
+                        if (isupcase || g_ascii_isupper(sWord[0]))
+                        {
+                            casestr = g_ascii_strdown(sNewWord, -1);
+                            if (strcmp(casestr, sNewWord))
+                            {
+                                if (oLib[iLib]->Lookup(casestr, iIndex))
+                                    bFound = true;
+                            }
+                            g_free(casestr);
+                        }
+                        if (!bFound)
+                            sNewWord[iWordLen - 3] = sNewWord[iWordLen - 4];  //restore
+                    }
+                }
+                if (!bFound)
+                {
+                    if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                        bFound = true;
+                    else if (isupcase || g_ascii_isupper(sWord[0]))
+                    {
+                        casestr = g_ascii_strdown(sNewWord, -1);
+                        if (strcmp(casestr, sNewWord))
+                        {
+                            if (oLib[iLib]->Lookup(casestr, iIndex))
+                                bFound = true;
+                        }
+                        g_free(casestr);
+                    }
+                }
+            }
+        }
+
+        // cut "ied" , add "y".
+        if (!bFound && iWordLen > 3)
+        {
+            isupcase = !strncmp(&sWord[iWordLen - 3], "IED", 3);
+            if (isupcase || (!strncmp(&sWord[iWordLen - 3], "ied", 3)))
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 3] = '\0';
+                if (isupcase)
+                    strcat(sNewWord, "Y"); // add a char "Y"
+                else
+                    strcat(sNewWord, "y"); // add a char "y"
+                if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                    bFound = true;
+                else if (isupcase || g_ascii_isupper(sWord[0]))
+                {
+                    casestr = g_ascii_strdown(sNewWord, -1);
+                    if (strcmp(casestr, sNewWord))
+                    {
+                        if (oLib[iLib]->Lookup(casestr, iIndex))
+                            bFound = true;
+                    }
+                    g_free(casestr);
+                }
+            }
+        }
+
+        // cut "ies" , add "y".
+        if (!bFound && iWordLen > 3)
+        {
+            isupcase = !strncmp(&sWord[iWordLen - 3], "IES", 3);
+            if (isupcase || (!strncmp(&sWord[iWordLen - 3], "ies", 3)))
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 3] = '\0';
+                if (isupcase)
+                    strcat(sNewWord, "Y"); // add a char "Y"
+                else
+                    strcat(sNewWord, "y"); // add a char "y"
+                if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                    bFound = true;
+                else if (isupcase || g_ascii_isupper(sWord[0]))
+                {
+                    casestr = g_ascii_strdown(sNewWord, -1);
+                    if (strcmp(casestr, sNewWord))
+                    {
+                        if (oLib[iLib]->Lookup(casestr, iIndex))
+                            bFound = true;
+                    }
+                    g_free(casestr);
+                }
+            }
+        }
+
+        // cut "er".
+        if (!bFound && iWordLen > 2)
+        {
+            isupcase = !strncmp(&sWord[iWordLen - 2], "ER", 2);
+            if (isupcase || (!strncmp(&sWord[iWordLen - 2], "er", 2)))
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 2] = '\0';
+                if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                    bFound = true;
+                else if (isupcase || g_ascii_isupper(sWord[0]))
+                {
+                    casestr = g_ascii_strdown(sNewWord, -1);
+                    if (strcmp(casestr, sNewWord))
+                    {
+                        if (oLib[iLib]->Lookup(casestr, iIndex))
+                            bFound = true;
+                    }
+                    g_free(casestr);
+                }
+            }
+        }
+
+        // cut "est".
+        if (!bFound && iWordLen > 3)
+        {
+            isupcase = !strncmp(&sWord[iWordLen - 3], "EST", 3);
+            if (isupcase || (!strncmp(&sWord[iWordLen - 3], "est", 3)))
+            {
+                strcpy(sNewWord, sWord);
+                sNewWord[iWordLen - 3] = '\0';
+                if (oLib[iLib]->Lookup(sNewWord, iIndex))
+                    bFound = true;
+                else if (isupcase || g_ascii_isupper(sWord[0]))
+                {
+                    casestr = g_ascii_strdown(sNewWord, -1);
+                    if (strcmp(casestr, sNewWord))
+                    {
+                        if (oLib[iLib]->Lookup(casestr, iIndex))
+                            bFound = true;
+                    }
+                    g_free(casestr);
+                }
+            }
+        }
+
+        g_free(sNewWord);
+    }
+
+    if (bFound)
+        iWordIndex = iIndex;
+#if 0
+
+    else
+    {
+        //don't change iWordIndex here.
+        //when LookupSimilarWord all failed too, we want to use the old LookupWord index to list words.
+        //iWordIndex = INVALID_INDEX;
+    }
+#endif
+    return bFound;
+}
+
+bool Libs::SimpleLookupWord(const gchar* sWord, glong & iWordIndex, int iLib)
+{
+    bool bFound = oLib[iLib]->Lookup(sWord, iWordIndex);
+    if (!bFound)
+        bFound = LookupSimilarWord(sWord, iWordIndex, iLib);
+    return bFound;
+}
+
+struct Fuzzystruct
+{
+    char * pMatchWord;
+    int iMatchWordDistance;
+};
+
+inline bool operator<(const Fuzzystruct & lh, const Fuzzystruct & rh)
+{
+    if (lh.iMatchWordDistance != rh.iMatchWordDistance)
+        return lh.iMatchWordDistance < rh.iMatchWordDistance;
+
+    if (lh.pMatchWord && rh.pMatchWord)
+        return stardict_strcmp(lh.pMatchWord, rh.pMatchWord) < 0;
+
+    return false;
+}
+
+static inline void unicode_strdown(gunichar *str)
+{
+    while (*str)
+    {
+        *str = g_unichar_tolower(*str);
+        ++str;
+    }
+}
+
+bool Libs::LookupWithFuzzy(const gchar *sWord, gchar *reslist[], gint reslist_size, gint iLib)
+{
+    if (sWord[0] == '\0')
+        return false;
+
+    Fuzzystruct *oFuzzystruct = new Fuzzystruct[reslist_size];
+
+    for (int i = 0; i < reslist_size; i++)
+    {
+        oFuzzystruct[i].pMatchWord = NULL;
+        oFuzzystruct[i].iMatchWordDistance = iMaxFuzzyDistance;
+    }
+    int iMaxDistance = iMaxFuzzyDistance;
+    int iDistance;
+    bool Found = false;
+    EditDistance oEditDistance;
+
+    glong iCheckWordLen;
+    const char *sCheck;
+    gunichar *ucs4_str1, *ucs4_str2;
+    glong ucs4_str2_len;
+
+    ucs4_str2 = g_utf8_to_ucs4_fast(sWord, -1, &ucs4_str2_len);
+    unicode_strdown(ucs4_str2);
+
+//    for (std::vector<Dict *>::size_type iLib = 0; iLib<oLib.size(); iLib++)
+//    {
+    if (progress_func)
+        progress_func();
+
+    //if (stardict_strcmp(sWord, poGetWord(0,iLib))>=0 && stardict_strcmp(sWord, poGetWord(narticles(iLib)-1,iLib))<=0) {
+    //there are Chinese dicts and English dicts...
+    if (TRUE)
+    {
+        const int iwords = narticles(iLib);
+        for (int index = 0; index < iwords; index++)
+        {
+            sCheck = poGetWord(index, iLib);
+            // tolower and skip too long or too short words
+            iCheckWordLen = g_utf8_strlen(sCheck, -1);
+            if (iCheckWordLen - ucs4_str2_len >= iMaxDistance ||
+                    ucs4_str2_len - iCheckWordLen >= iMaxDistance)
+                continue;
+            ucs4_str1 = g_utf8_to_ucs4_fast(sCheck, -1, NULL);
+            if (iCheckWordLen > ucs4_str2_len)
+                ucs4_str1[ucs4_str2_len] = 0;
+            unicode_strdown(ucs4_str1);
+
+            iDistance = oEditDistance.CalEditDistance(ucs4_str1, ucs4_str2, iMaxDistance);
+            g_free(ucs4_str1);
+            if (iDistance < iMaxDistance && iDistance < ucs4_str2_len)
+            {
+                // when ucs4_str2_len=1,2 we need less fuzzy.
+                Found = true;
+                bool bAlreadyInList = false;
+                int iMaxDistanceAt = 0;
+                for (int j = 0; j < reslist_size; j++)
+                {
+                    if (oFuzzystruct[j].pMatchWord &&
+                            strcmp(oFuzzystruct[j].pMatchWord, sCheck) == 0 )
+                    { //already in list
+                        bAlreadyInList = true;
+                        break;
+                    }
+                    //find the position,it will certainly be found (include the first time) as iMaxDistance is set by last time.
+                    if (oFuzzystruct[j].iMatchWordDistance == iMaxDistance )
+                    {
+                        iMaxDistanceAt = j;
+                    }
+                }
+                if (!bAlreadyInList)
+                {
+                    if (oFuzzystruct[iMaxDistanceAt].pMatchWord)
+                        g_free(oFuzzystruct[iMaxDistanceAt].pMatchWord);
+                    oFuzzystruct[iMaxDistanceAt].pMatchWord = g_strdup(sCheck);
+                    oFuzzystruct[iMaxDistanceAt].iMatchWordDistance = iDistance;
+                    // calc new iMaxDistance
+                    iMaxDistance = iDistance;
+                    for (int j = 0; j < reslist_size; j++)
+                    {
+                        if (oFuzzystruct[j].iMatchWordDistance > iMaxDistance)
+                            iMaxDistance = oFuzzystruct[j].iMatchWordDistance;
+                    } // calc new iMaxDistance
+                }   // add to list
+            }   // find one
+        }   // each word
+    }   // ok for search
+//    }   // each lib
+    g_free(ucs4_str2);
+
+    if (Found) // sort with distance
+        std::sort(oFuzzystruct, oFuzzystruct + reslist_size);
+
+    for (gint i = 0; i < reslist_size; ++i)
+        reslist[i] = oFuzzystruct[i].pMatchWord;
+
+    delete[] oFuzzystruct;
+
+    return Found;
+}
+
+inline bool less_for_compare(const char *lh, const char *rh)
+{
+    return stardict_strcmp(lh, rh) < 0;
+}
+
+gint Libs::LookupWithRule(const gchar *word, gchar **ppMatchWord)
+{
+    glong aiIndex[MAX_MATCH_ITEM_PER_LIB + 1];
+    gint iMatchCount = 0;
+    GPatternSpec *pspec = g_pattern_spec_new(word);
+
+    for (std::vector<Dict *>::size_type iLib = 0; iLib<oLib.size(); iLib++)
+    {
+        //if(oLibs.LookdupWordsWithRule(pspec,aiIndex,MAX_MATCH_ITEM_PER_LIB+1-iMatchCount,iLib))
+        // -iMatchCount,so save time,but may got less result and the word may repeat.
+
+        if (oLib[iLib]->
+                LookupWithRule(pspec, aiIndex, MAX_MATCH_ITEM_PER_LIB + 1))
+        {
+            if (progress_func)
+                progress_func();
+            for (int i = 0; aiIndex[i] != -1; i++)
+            {
+                const gchar * sMatchWord = poGetWord(aiIndex[i], iLib);
+                bool bAlreadyInList = false;
+                for (int j = 0; j < iMatchCount; j++)
+                {
+                    if (strcmp(ppMatchWord[j], sMatchWord) == 0)
+                    { //already in list
+                        bAlreadyInList = true;
+                        break;
+                    }
+                }
+                if (!bAlreadyInList)
+                    ppMatchWord[iMatchCount++] = g_strdup(sMatchWord);
+            }
+        }
+    }
+    g_pattern_spec_free(pspec);
+
+    if (iMatchCount) // sort it.
+        std::sort(ppMatchWord, ppMatchWord + iMatchCount, less_for_compare);
+
+    return iMatchCount;
+}
+
+bool Libs::LookupData(const gchar *sWord, std::vector<gchar *> *reslist)
+{
+    std::vector<std::string> SearchWords;
+    std::string SearchWord;
+    const char *p = sWord;
+    while (*p)
+    {
+        if (*p == '\\')
+        {
+            p++;
+            switch (*p)
+            {
+            case ' ':
+                SearchWord += ' ';
+                break;
+            case '\\':
+                SearchWord += '\\';
+                break;
+            case 't':
+                SearchWord += '\t';
+                break;
+            case 'n':
+                SearchWord += '\n';
+                break;
+            default:
+                SearchWord += *p;
+            }
+        }
+        else if (*p == ' ')
+        {
+            if (!SearchWord.empty())
+            {
+                SearchWords.push_back(SearchWord);
+                SearchWord.clear();
+            }
+        }
+        else
+        {
+            SearchWord += *p;
+        }
+        p++;
+    }
+    if (!SearchWord.empty())
+    {
+        SearchWords.push_back(SearchWord);
+        SearchWord.clear();
+    }
+    if (SearchWords.empty())
+        return false;
+
+    guint32 max_size = 0;
+    gchar *origin_data = NULL;
+    for (std::vector<Dict *>::size_type i = 0; i<oLib.size(); ++i)
+    {
+        if (!oLib[i]->
+                containSearchData())
+            continue;
+        if (progress_func)
+            progress_func();
+        const gulong iwords = narticles(i);
+        const gchar *key;
+        guint32 offset, size;
+        for (gulong j = 0;
+                j < iwords;
+                ++j)
+        {
+            oLib[i]
+            ->get_key_and_data(j, &key, &offset, &size);
+            if (size > max_size)
+            {
+                origin_data = (gchar *)g_realloc(origin_data, size);
+                max_size = size;
+            }
+            if (oLib[i]->SearchData(SearchWords, offset, size, origin_data))
+                reslist[i].push_back(g_strdup(key));
+        }
+    }
+    g_free(origin_data);
+
+    std::vector<Dict *>::size_type i;
+    for (i = 0; i<oLib.size(); ++i)
+        if (!reslist[i].empty())
+            break;
+
+    return i != oLib.size();
+}
+
+/**************************************************/
+query_t analyze_query(const char *s, std::string& res)
+{
+    if (!s || !*s)
+    {
+        res = "";
+        return qtSIMPLE;
+    }
+    if (*s == '/')
+    {
+        res = s + 1;
+        return qtFUZZY;
+    }
+
+    if (*s == '|')
+    {
+        res = s + 1;
+        return qtDATA;
+    }
+
+    bool regexp = false;
+    const char *p = s;
+    res = "";
+    for (; *p; res += *p, ++p)
+    {
+        if (*p == '\\')
+        {
+            ++p;
+            if (!*p)
+                break;
+            continue;
+        }
+        if (*p == '*' || *p == '?')
+            regexp = true;
+    }
+    if (regexp)
+        return qtREGEXP;
+
+    return qtSIMPLE;
+}
diff --git a/plugins/stardict/lib.h b/plugins/stardict/lib.h
new file mode 100644 (file)
index 0000000..c17835d
--- /dev/null
@@ -0,0 +1,199 @@
+#ifndef __SD_LIB_H__
+#define __SD_LIB_H__
+
+#include <cstdio>
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "dictziplib.hpp"
+
+const int MAX_MATCH_ITEM_PER_LIB = 100;
+const int MAX_FUZZY_DISTANCE = 3; // at most MAX_FUZZY_DISTANCE-1 differences allowed when find similar words
+
+struct cacheItem
+{
+    guint32 offset;
+    gchar *data;
+    //write code here to make it inline
+    cacheItem()
+    {
+        data = NULL;
+    }
+    ~cacheItem()
+    {
+        g_free(data);
+    }
+};
+
+const int WORDDATA_CACHE_NUM = 10;
+const int INVALID_INDEX = -100;
+
+class DictBase
+{
+    public:
+        DictBase();
+        ~DictBase();
+        gchar * GetWordData(guint32 idxitem_offset, guint32 idxitem_size);
+        bool containSearchData();
+        bool SearchData(std::vector<std::string> &SearchWords, guint32 idxitem_offset, guint32 idxitem_size, gchar *origin_data);
+    protected:
+        std::string sametypesequence;
+        FILE *dictfile;
+        std::auto_ptr<dictData> dictdzfile;
+    private:
+        cacheItem cache[WORDDATA_CACHE_NUM];
+        gint cache_cur;
+};
+
+//this structure contain all information about dictionary
+struct DictInfo
+{
+    std::string ifo_file_name;
+    guint32 wordcount;
+    std::string bookname;
+    std::string author;
+    std::string email;
+    std::string website;
+    std::string date;
+    std::string description;
+    guint32 index_file_size;
+    std::string sametypesequence;
+    bool load_from_ifo_file(const std::string& ifofilename, bool istreedict);
+};
+
+class index_file
+{
+    public:
+        guint32 wordentry_offset;
+        guint32 wordentry_size;
+
+        virtual ~index_file()
+        {}
+        virtual bool load(const std::string& url, gulong wc, gulong fsize) = 0;
+        virtual const gchar *get_key(glong idx) = 0;
+        virtual void get_data(glong idx) = 0;
+        virtual const gchar *get_key_and_data(glong idx) = 0;
+        virtual bool lookup(const char *str, glong &idx) = 0;
+};
+
+class Dict : public DictBase
+{
+    private:
+        std::string ifo_file_name;
+        gulong wordcount;
+        std::string bookname;
+
+        std::auto_ptr<index_file> idx_file;
+
+        bool load_ifofile(const std::string& ifofilename, gulong &idxfilesize);
+    public:
+        Dict()
+        {}
+        bool load(const std::string& ifofilename);
+
+        gulong narticles()
+        {
+            return wordcount;
+        }
+        const std::string& dict_name()
+        {
+            return bookname;
+        }
+        const std::string& ifofilename()
+        {
+            return ifo_file_name;
+        }
+
+        const gchar *get_key(glong index)
+        {
+            return idx_file->get_key(index);
+        }
+        gchar *get_data(glong index)
+        {
+            idx_file->get_data(index);
+            return DictBase::GetWordData(idx_file->wordentry_offset, idx_file->wordentry_size);
+        }
+        void get_key_and_data(glong index, const gchar **key, guint32 *offset, guint32 *size)
+        {
+            *key = idx_file->get_key_and_data(index);
+            *offset = idx_file->wordentry_offset;
+            *size = idx_file->wordentry_size;
+        }
+        bool Lookup(const char *str, glong &idx)
+        {
+            return idx_file->lookup(str, idx);
+        }
+
+        bool LookupWithRule(GPatternSpec *pspec, glong *aIndex, int iBuffLen);
+};
+
+typedef std::list<std::string> strlist_t;
+
+class Libs
+{
+    public:
+        typedef void (*progress_func_t)(void);
+
+        Libs(progress_func_t f = NULL);
+        ~Libs();
+        void load_dict(const std::string& url);
+        void load(const strlist_t& dicts_dirs,
+                  const strlist_t& order_list,
+                  const strlist_t& disable_list);
+        void reload(const strlist_t& dicts_dirs,
+                    const strlist_t& order_list,
+                    const strlist_t& disable_list);
+
+        glong narticles(int idict)
+        {
+            return oLib[idict]->narticles();
+        }
+        const std::string& dict_name(int idict)
+        {
+            return oLib[idict]->dict_name();
+        }
+        gint ndicts()
+        {
+            return oLib.size();
+        }
+
+        const gchar * poGetWord(glong iIndex, int iLib)
+        {
+            return oLib[iLib]->get_key(iIndex);
+        }
+        gchar * poGetWordData(glong iIndex, int iLib)
+        {
+            if (iIndex == INVALID_INDEX)
+                return NULL;
+            return oLib[iLib]->get_data(iIndex);
+        }
+        const gchar *poGetCurrentWord(glong *iCurrent);
+        const gchar *poGetNextWord(const gchar *word, glong *iCurrent);
+        const gchar *poGetPreWord(glong *iCurrent);
+        bool LookupWord(const gchar* sWord, glong& iWordIndex, int iLib)
+        {
+            return oLib[iLib]->Lookup(sWord, iWordIndex);
+        }
+        bool LookupSimilarWord(const gchar* sWord, glong & iWordIndex, int iLib);
+        bool SimpleLookupWord(const gchar* sWord, glong & iWordIndex, int iLib);
+
+
+        bool LookupWithFuzzy(const gchar *sWord, gchar *reslist[], gint reslist_size, gint iLib);
+        gint LookupWithRule(const gchar *sWord, gchar *reslist[]);
+        bool LookupData(const gchar *sWord, std::vector<gchar *> *reslist);
+    private:
+        std::vector<Dict *> oLib; // word Libs.
+        int iMaxFuzzyDistance;
+        progress_func_t progress_func;
+};
+
+
+typedef enum {
+    qtSIMPLE, qtREGEXP, qtFUZZY, qtDATA
+} query_t;
+
+extern query_t analyze_query(const char *s, std::string& res);
+
+#endif//!__SD_LIB_H__
diff --git a/plugins/stardict/lib.o b/plugins/stardict/lib.o
new file mode 100644 (file)
index 0000000..8004243
Binary files /dev/null and b/plugins/stardict/lib.o differ
diff --git a/plugins/stardict/mapfile.hpp b/plugins/stardict/mapfile.hpp
new file mode 100644 (file)
index 0000000..8323ea7
--- /dev/null
@@ -0,0