36 Commits

Author SHA1 Message Date
Evgeniy A. Dushistov
0cd29823cf ready for 0.5.2 release 2017-08-16 10:14:23 +03:00
Evgeniy A. Dushistov
8f16ceae59 refactoring: apply clang-format rules 2017-08-09 07:46:27 +03:00
Evgeniy A. Dushistov
d0c0a0837f fix: do not give interactive menu via pager
fixes #28
2017-08-09 07:41:33 +03:00
Evgeniy Dushistov
d5698bdf33 Merge pull request #26 from ecraven/no-fuzzy-option
Add -e for exact searches (no fuzzy matches).
2017-07-31 21:16:31 +03:00
Peter
7518be74f9 Regenerate translations in po/
Run xgettext -k_ src/*.cpp and merge with msgmerge.
2017-07-31 19:27:12 +02:00
Peter
59a821c8f9 Update man page, add -x, -j and -e.
Also fix a few typos.
2017-07-31 19:10:02 +02:00
Evgeniy A. Dushistov
c9a55c90bd update NEWS 2017-07-29 23:32:59 +03:00
Peter
e85927e562 Add -e for exact searches (no fuzzy matches).
Only exact matches (or synonyms) are returned for simple searches.
2017-07-28 11:39:34 +02:00
Evgeniy Dushistov
586215fda7 Merge pull request #25 from ecraven/add-content-types
Add additional type identifiers h,w,k
2017-07-28 00:09:29 +03:00
Peter
835dffcaf8 Add additional type identifiers h,w,k
Like for xdxf, no processing is done, the raw content is shown.
2017-07-27 08:15:45 +02:00
Evgeniy Dushistov
af6362f5df Merge pull request #23 from sleep-walker/master
fix FSF address in LICENSE
2017-07-27 00:30:30 +03:00
Evgeniy Dushistov
25dd4c8264 Merge pull request #22 from ecraven/json
Add json output, fix #6
2017-07-26 23:55:59 +03:00
Tomáš Čech
98e98d0746 fix FSF address 2017-07-26 22:39:28 +02:00
Peter
3105823e8b Add option --json-output (-j)
If given -j, format the output of -l and of searches as JSON.
2017-07-26 22:07:23 +02:00
Evgeniy A. Dushistov
edf73656aa update manpage about $(HOME)/.sdcv_ordering
This should close #5
2017-07-13 00:15:30 +03:00
Peter
5f0f6e036f Add option --only-data-dir (-x)
Only use the dictionaries in data-dir, do not search in user and system directories

This makes testing much easier
2017-07-07 08:39:26 +02:00
Evgeniy A. Dushistov
6c01e22961 add note in NEWS about fixing #8 2017-07-07 00:20:41 +03:00
Evgeniy A. Dushistov
214fbbf91e fix portability issue in PR #20 , plus simplify code 2017-07-07 00:19:50 +03:00
Evgeniy Dushistov
f510300f59 Merge pull request #20 from ecraven/master
Add support for .syn synonym files.
2017-07-06 23:57:19 +03:00
Peter
aa42132243 Add tests for synonyms 2017-07-06 19:54:36 +02:00
Peter
4b52181898 Add support for .syn synonym files.
Fixes #8.
2017-07-06 19:46:15 +02:00
Evgeniy A. Dushistov
72a15b70a7 simplify parsing of integers in ifo file 2017-07-06 13:11:02 +03:00
Evgeniy A. Dushistov
4c367fc12c fix build with clang 3.4.1 #19 2017-07-06 11:41:58 +03:00
Evgeniy A. Dushistov
b2ced870ab fix potential undefined behaviour
fix #19
2017-07-04 22:33:14 +03:00
Evgeniy A. Dushistov
b4fc882f25 update NEWS for 0.5.1 2017-04-25 09:52:36 +03:00
Evgeniy A. Dushistov
82a06b8e69 msgmerge -vU ru.po sdcv.pot 2017-04-22 21:44:35 +03:00
Evgeniy A. Dushistov
73d6098010 version bump 2017-04-22 21:30:07 +03:00
Evgeniy A. Dushistov
5c1357840c Merge branch 'order_dist_list' 2017-04-22 21:25:58 +03:00
Evgeniy A. Dushistov
1667de0650 cleanups for specify "dictionary order by" 2017-04-22 21:23:00 +03:00
Evgeniy A. Dushistov
97b13e6702 remove not used code 2017-04-22 20:52:18 +03:00
Evgeniy Dushistov
d9f273b858 Merge pull request #14 from citrin/fix_pager
Fix using SDCV_PAGER
2017-03-07 16:07:09 -08:00
Anton Yuzhaninov
84367a5744 Fix using SDCV_PAGER
Stream opened with popen() should be closed with pclose() as documented
in popen(3) man.
2017-03-07 18:37:52 -05:00
Evgeniy A. Dushistov
7df514e117 fix build without readline 2017-02-17 17:38:57 +03:00
Evgeniy Dushistov
a1a614b81f Merge pull request #13 from wordempire/patch-1
Update CMakeLists.txt
2017-01-24 04:48:18 +03:00
Jelle Licht
913fd0a312 Update CMakeLists.txt
Also add READLINE_INCLUDE_DIR when building
2017-01-24 02:36:28 +01:00
Cong Gu
2d95bd0b12 specify dictionary order by -u switches or ~/.sdcv_ordering 2016-09-25 01:13:43 -05:00
37 changed files with 3782 additions and 3264 deletions

View File

@@ -22,6 +22,7 @@ matrix:
- g++-4.8
- cmake
- libglib2.0-dev
- jq
# - env: COMPILER_VERSION=3.5
# os: linux
# compiler: clang++

View File

@@ -27,11 +27,15 @@ if (NOT GLIB2_FOUND)
"make sure that you install it")
endif()
find_path(READLINE_INCLUDE_DIR readline/readline.h)
find_library(READLINE_LIBRARY NAMES readline)
if (READLINE_INCLUDE_DIR AND READLINE_LIBRARY)
set(WITH_READLINE True)
endif ()
set(WITH_READLINE True CACHE BOOL "Use readline library")
if (WITH_READLINE)
find_path(READLINE_INCLUDE_DIR readline/readline.h)
find_library(READLINE_LIBRARY NAMES readline)
if (NOT (READLINE_INCLUDE_DIR AND READLINE_LIBRARY))
set(WITH_READLINE False CACHE FORCE)
endif ()
endif (WITH_READLINE)
option(ENABLE_NLS "Enable NLS support" True)
@@ -84,6 +88,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake
include_directories(
${ZLIB_INCLUDE_DIR}
${GLIB2_INCLUDE_DIRS}
${READLINE_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/src/lib
${CMAKE_CURRENT_BINARY_DIR}
)
@@ -96,7 +101,7 @@ set(CPACK_PACKAGE_VENDOR "Evgeniy Dushistov <dushistov@mail.ru>")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.org")
set(CPACK_PACKAGE_VERSION_MAJOR "0")
set(CPACK_PACKAGE_VERSION_MINOR "5")
set(CPACK_PACKAGE_VERSION_PATCH "0-beta4")
set(CPACK_PACKAGE_VERSION_PATCH "2")
set(sdcv_VERSION
"${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
@@ -139,6 +144,10 @@ if (BUILD_TESTS)
add_sdcv_shell_test(t_list)
add_sdcv_shell_test(t_use)
add_sdcv_shell_test(t_only_data_dir)
add_sdcv_shell_test(t_synonyms)
add_sdcv_shell_test(t_json)
add_sdcv_shell_test(t_exact)
add_sdcv_shell_test(t_interactive)
add_sdcv_shell_test(t_utf8output)
add_sdcv_shell_test(t_utf8input)

11
LICENSE
View File

@@ -1,10 +1,11 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
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
@@ -305,7 +306,7 @@ the "copyright" line and a pointer to where the full notice is found.
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
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.

12
NEWS
View File

@@ -1,3 +1,15 @@
Version 0.5.2
Synonyms index support (.syn files) by Peter <craven@gmx.net>
Add support of json output by Peter <craven@gmx.net> (--json-output)
Add -e for exact searches (no fuzzy matches) by Peter <craven@gmx.net>
Fix build with clang 3.4.1
fix FSF address in license by Tomáš Čech <sleep_walker@suse.com>
Version 0.5.1
Fix usage of SDCV_PAGER by Anton Yuzhaninov
Fix build without readline<
specify dictionary order by -u switches or ~/.sdcv_ordering by Cong Gu
Version 0.5
- add option to colorize output
- Roman Imankulov's patch to better use of readline

View File

@@ -25,9 +25,16 @@ See sdcv man page for usage description.
If you find bug reports it via email to dushistov at mail dot ru.
Be sure to include the word "sdcv" somewhere in the "Subject:" field.
* Notes to developer
** make source code release
#+BEGIN_SRC sh
make package_source
#+END_SRC
** update translation
#+BEGIN_SRC sh
cd po
xgettext -k_ ../src/*.cpp -o new.pot
msgmerge -U sdcv.pot new.pot
rm new.pot
for i in `ls *.po`; do msgmerge -U $i sdcv.pot; done
#+END_SRC

View File

@@ -9,78 +9,92 @@ sdcv \- console version of StarDict program
[list of words]
.SH DESCRIPTION
.I sdcv
is simple, cross-platform text-base utility
for work with dictionaries in StarDict's format.
The word from "list of words" may be string
with leading '/' for using Fuzzy search algorithm,
with leading '|' for using full-text search,
string may contain '?' and '*' for using regexp search.
It work in interactive and not interactive mode.
is a simple, cross-platform text-based utility
for working with dictionaries in StarDict format.
Each word from "list of words" may be a string
with a leading '/' for using a Fuzzy search algorithm,
with a leading '|' for using full-text search,
and the string may contain '?' and '*' for regexp search.
It works in interactive and non-interactive mode.
To exit from interactive mode press Ctrl+D.
In interactive mode,
if sdcv was compiled with readline library support,
you can use UP and DOWN keys to work through history.
you can use the UP and DOWN keys to cycle through history.
.SH OPTIONS
.TP 8
.B "\-h \-\-help"
display help message and exit
Display help message and exit
.TP 8
.B "\-v \-\-verbose"
display version and exit
Display version and exit
.TP 8
.B "\-l \-\-list\-dicts"
display list of available dictionaries and exit
Display list of available dictionaries and exit
.TP 8
.B "\-u \-\-use\-dict filename"
for search use only dictionary with this bookname
For search use only dictionary with this bookname
.TP 8
.B "\-n \-\-non\-interactive"
for use in scripts
For use in scripts
.TP 8
.B "\-x \-\-only\-data\-dir"
For use in scripts: only use the dictionaries in data-dir, do not search in user and system directories
.TP 8
.B "\-e \-\-exact\-search"
Do not fuzzy-search for similar words, only return exact matches
.TP 8
.B "\-j \-\-json"
Print the results of list-dicts and searches as json, not as plain text.
For use in automatically processing the results of a dictionary lookup.
.TP 8
.B "\-\-utf8\-output"
Force sdcv not use conversation to locale charset, output in utf8
Force sdcv to not convert to locale charset, output in utf8
.TP 8
.B "\-\-utf8\-input"
Force sdcv not use conversation from locale charset, suppose that
input in utf8
Force sdcv to not convert from locale charset, assume that
input is in utf8
.TP 8
.B "\-\-data\-dir path/to/directory"
Use this directory as path to stardict data directory. This is mean that
sdcv search dictionaries in data-dir/dic directory.
Use this directory as the path to the stardict data directory. This means that
sdcv searches for dictionaries in data-dir/dic directory.
.TP 8
.B "\-\-color"
Use ANSI escape code for colorize sdcv output
Use ANSI escape codes for colorizing sdcv output (does not work with json output).
.SH FILES
.TP
/usr/share/stardict/dic
/usr/share/stardict/dic
.TP
$(HOME)/.stardict/dic
Place, where sdcv expect to find dictionaries.
Instead of /usr/share/stardict/dic you can use everything
that you want, just set STARDICT_DATA_DIR environment variable.
Place where sdcv expects to find dictionaries.
Instead of /usr/share/stardict/dic you can use any directory
you want, just set the STARDICT_DATA_DIR environment variable.
For example, if you have dictionaries in /mnt/data/stardict-dicts/dic,
set STARDICT_DATA_DIR to /mnt/data/stardict-dicts.
.TP
$(HOME)/.sdcv_history
This file include last $(SDCV_HISTSIZE) words, which you seek with sdcv.
SDCV use this file only if it was compiled with readline library support.
This file includes the last $(SDCV_HISTSIZE) words, which you sought with sdcv.
SDCV uses this file only if it was compiled with readline library support.
.TP
$(HOME)/.sdcv_ordering
This is a text file containing one dictionary bookname per line.
It specifies in which order the results of a search should be shown.
.SH ENVIRONMENT
Environment Variables Used By \fIsdcv\fR:
.TP 20
.B STARDICT_DATA_DIR
If set, sdcv use this variable as data directory, this is mean that sdcv
search dictionaries in $\fBSTARDICT_DATA_DIR\fR\\dic
If set, sdcv uses this variable as the data directory, this means that sdcv
searches dictionaries in $\fBSTARDICT_DATA_DIR\fR\\dic
.TP 20
.B SDCV_HISTSIZE
If set, sdcv wrote in $(HOME)/.sdcv_history only last $(SDCV_HISTSIZE) words,
which you seek using sdcv. If it is not set, then last 2000 words saved in $(HOME)/.sdcv_history.
If set, sdcv writes in $(HOME)/.sdcv_history the last $(SDCV_HISTSIZE) words,
which you look up using sdcv. If it is not set, then the last 2000 words are saved in $(HOME)/.sdcv_history.
.TP 20
.B SDCV_PAGER
If SDCV_PAGER is set, its value is used as the name of the program
to use to display the dictionary's article.
If SDCV_PAGER is set, its value is used as the name of the program
to use to display the dictionary article.
.SH BUGS
Email bug reports to dushistov at mail dot ru. Be sure to include the word
"sdcv" somewhere in the "Subject:" field.

188
po/cs.po
View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sdcv 0.4.2\n"
"Report-Msgid-Bugs-To: dushistov@mail.ru\n"
"POT-Creation-Date: 2008-09-24 10:54+0200\n"
"POT-Creation-Date: 2017-08-16 09:52+0300\n"
"PO-Revision-Date: 2008-09-24 10:42+0200\n"
"Last-Translator: Michal Čihař <michal@cihar.com>\n"
"Language-Team: Czech <cs@li.org>\n"
@@ -16,102 +16,25 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
#: src/sdcv.cpp:108
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version zobrazí informace o verzi a skončí\n"
#: src/sdcv.cpp:110
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr "-l, --list-dicts zobrazí seznam dostupných slovníků a skončí\n"
#: src/sdcv.cpp:112
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr "-u, --use-dict jméno vyhledávat jen v zadaném slovníku\n"
#: src/sdcv.cpp:113
msgid "bookname"
msgstr ""
#: src/sdcv.cpp:115
msgid "for use in scripts"
msgstr ""
#: src/sdcv.cpp:117
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output výstup musí být v utf8\n"
#: src/sdcv.cpp:119
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input vstup musí být v utf8\n"
#: src/sdcv.cpp:121
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr ""
"--data-dir cesta/někam použít tento adresář jako cestu ke slovníkům "
"stardict\n"
#: src/sdcv.cpp:122
msgid "path/to/dir"
msgstr ""
#: src/sdcv.cpp:129
msgid " words"
msgstr ""
#: src/sdcv.cpp:135
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: src/sdcv.cpp:141
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Konzolová verze Stardictu, verze %s\n"
#: src/sdcv.cpp:170
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "Jméno slovníku Počet slov\n"
#: src/sdcv.cpp:192
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "g_mkdir selhalo: %s\n"
#: src/sdcv.cpp:208
msgid "Enter word or phrase: "
msgstr "Zadejte slovo nebo frázi: "
#: src/sdcv.cpp:216
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Nebyla zadáno nic k přeložení.\n"
#: src/libwrapper.cpp:248
#: ../src/libwrapper.cpp:300
msgid "popen failed"
msgstr "popen selhalo"
#: src/libwrapper.cpp:285 src/utils.cpp:67
#: ../src/libwrapper.cpp:340
#, c-format
msgid "Can not convert %s to utf8.\n"
msgstr "Nepodařilo se převést %s do utf8.\n"
#: src/libwrapper.cpp:342 src/libwrapper.cpp:370
#: ../src/libwrapper.cpp:398 ../src/libwrapper.cpp:432
#, fuzzy, c-format
msgid "Found %zu items, similar to %s.\n"
msgstr "Nalezeno %d záznamů podobných %s.\n"
#: src/libwrapper.cpp:356
#: ../src/libwrapper.cpp:416
msgid "Your choice[-1 to abort]: "
msgstr "Vaše volba [-1 pro ukončení]: "
#: src/libwrapper.cpp:365
#: ../src/libwrapper.cpp:426
#, fuzzy, c-format
msgid ""
"Invalid choice.\n"
@@ -120,12 +43,107 @@ msgstr ""
"Chybná volba.\n"
"Musí být mezi 0 a %d nebo -1.\n"
#: src/libwrapper.cpp:381
#: ../src/libwrapper.cpp:445
#, c-format
msgid "Nothing similar to %s, sorry :(\n"
msgstr "Nic podobného %s nenalezeno, promiň :(\n"
#: src/utils.cpp:45
#: ../src/sdcv.cpp:88
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version zobrazí informace o verzi a skončí\n"
#: ../src/sdcv.cpp:90
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr "-l, --list-dicts zobrazí seznam dostupných slovníků a skončí\n"
#: ../src/sdcv.cpp:92
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr "-u, --use-dict jméno vyhledávat jen v zadaném slovníku\n"
#: ../src/sdcv.cpp:93
msgid "bookname"
msgstr ""
#: ../src/sdcv.cpp:95
msgid "for use in scripts"
msgstr ""
#: ../src/sdcv.cpp:97
msgid "print the result formatted as JSON"
msgstr ""
#: ../src/sdcv.cpp:99
msgid "do not fuzzy-search for similar words, only return exact matches"
msgstr ""
#: ../src/sdcv.cpp:101
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output výstup musí být v utf8\n"
#: ../src/sdcv.cpp:103
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input vstup musí být v utf8\n"
#: ../src/sdcv.cpp:105
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr ""
"--data-dir cesta/někam použít tento adresář jako cestu ke slovníkům "
"stardict\n"
#: ../src/sdcv.cpp:106
msgid "path/to/dir"
msgstr ""
#: ../src/sdcv.cpp:108
msgid ""
"only use the dictionaries in data-dir, do not search in user and system "
"directories"
msgstr ""
#: ../src/sdcv.cpp:110
msgid "colorize the output"
msgstr ""
#: ../src/sdcv.cpp:115
msgid " words"
msgstr ""
#: ../src/sdcv.cpp:121
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: ../src/sdcv.cpp:127
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Konzolová verze Stardictu, verze %s\n"
#: ../src/sdcv.cpp:202
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "g_mkdir selhalo: %s\n"
#: ../src/sdcv.cpp:217
msgid "Enter word or phrase: "
msgstr "Zadejte slovo nebo frázi: "
#: ../src/sdcv.cpp:225
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Nebyla zadáno nic k přeložení.\n"
#: ../src/sdcv.cpp:237
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "Jméno slovníku Počet slov\n"
#: ../src/utils.cpp:48
#, fuzzy, c-format
msgid "Can not convert %s to current locale.\n"
msgstr "Nepodařilo se převést %s do utf8.\n"

198
po/fr.po
View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sdcv 0.4.2\n"
"Report-Msgid-Bugs-To: dushistov@mail.ru\n"
"POT-Creation-Date: 2008-09-24 10:54+0200\n"
"POT-Creation-Date: 2017-08-16 09:52+0300\n"
"PO-Revision-Date: 2009-06-15 23:20+0800\n"
"Language-Team: Vincent Petry <PVince81@yahoo.fr>\n"
"Language: \n"
@@ -18,107 +18,25 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: src/sdcv.cpp:108
#, fuzzy
msgid "display version information and exit"
msgstr ""
"-v, --version afficher les informations de version et sortir\n"
#: src/sdcv.cpp:110
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr ""
"-l, --list-dicts afficher la liste des dictionnaires disponibles et "
"sortir\n"
#: src/sdcv.cpp:112
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr ""
"-u, --use-dict nom_dict pour chercher seulement en utilisant le "
"dictionnaire spécifié\n"
#: src/sdcv.cpp:113
msgid "bookname"
msgstr ""
#: src/sdcv.cpp:115
msgid "for use in scripts"
msgstr ""
#: src/sdcv.cpp:117
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output force la sortie au format utf8\n"
#: src/sdcv.cpp:119
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input force l'entrée de sdcv au format utf8\n"
#: src/sdcv.cpp:121
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr ""
"--data-dir chemin utiliser ce chemin pour trouver les données de "
"stardict\n"
#: src/sdcv.cpp:122
msgid "path/to/dir"
msgstr ""
#: src/sdcv.cpp:129
msgid " words"
msgstr ""
#: src/sdcv.cpp:135
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: src/sdcv.cpp:141
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Version console de Stardict, version %s\n"
#: src/sdcv.cpp:170
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "Nom dictionnaire Nombre de mots\n"
#: src/sdcv.cpp:192
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "Échec de g_mkdir : %s\n"
#: src/sdcv.cpp:208
msgid "Enter word or phrase: "
msgstr "Entrez un mot ou une phrase: "
#: src/sdcv.cpp:216
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Il n'y a pas de mots/phrases à traduire.\n"
#: src/libwrapper.cpp:248
#: ../src/libwrapper.cpp:300
msgid "popen failed"
msgstr "Échec de popen"
#: src/libwrapper.cpp:285 src/utils.cpp:67
#: ../src/libwrapper.cpp:340
#, c-format
msgid "Can not convert %s to utf8.\n"
msgstr "Ne peut convertir %s au format utf8.\n"
#: src/libwrapper.cpp:342 src/libwrapper.cpp:370
#: ../src/libwrapper.cpp:398 ../src/libwrapper.cpp:432
#, fuzzy, c-format
msgid "Found %zu items, similar to %s.\n"
msgstr "Trouvé %d éléments similaires à %s.\n"
#: src/libwrapper.cpp:356
#: ../src/libwrapper.cpp:416
msgid "Your choice[-1 to abort]: "
msgstr "Votre choix[-1 pour abandonner] : "
#: src/libwrapper.cpp:365
#: ../src/libwrapper.cpp:426
#, fuzzy, c-format
msgid ""
"Invalid choice.\n"
@@ -127,12 +45,112 @@ msgstr ""
"Selection invalide.\n"
"Veuillez choisir un nombre entre 0 et %d, ou -1.\n"
#: src/libwrapper.cpp:381
#: ../src/libwrapper.cpp:445
#, c-format
msgid "Nothing similar to %s, sorry :(\n"
msgstr "Aucun mot/phrase similaire à %s, désolé :(\n"
#: src/utils.cpp:45
#: ../src/sdcv.cpp:88
#, fuzzy
msgid "display version information and exit"
msgstr ""
"-v, --version afficher les informations de version et sortir\n"
#: ../src/sdcv.cpp:90
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr ""
"-l, --list-dicts afficher la liste des dictionnaires disponibles et "
"sortir\n"
#: ../src/sdcv.cpp:92
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr ""
"-u, --use-dict nom_dict pour chercher seulement en utilisant le "
"dictionnaire spécifié\n"
#: ../src/sdcv.cpp:93
msgid "bookname"
msgstr ""
#: ../src/sdcv.cpp:95
msgid "for use in scripts"
msgstr ""
#: ../src/sdcv.cpp:97
msgid "print the result formatted as JSON"
msgstr ""
#: ../src/sdcv.cpp:99
msgid "do not fuzzy-search for similar words, only return exact matches"
msgstr ""
#: ../src/sdcv.cpp:101
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output force la sortie au format utf8\n"
#: ../src/sdcv.cpp:103
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input force l'entrée de sdcv au format utf8\n"
#: ../src/sdcv.cpp:105
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr ""
"--data-dir chemin utiliser ce chemin pour trouver les données de "
"stardict\n"
#: ../src/sdcv.cpp:106
msgid "path/to/dir"
msgstr ""
#: ../src/sdcv.cpp:108
msgid ""
"only use the dictionaries in data-dir, do not search in user and system "
"directories"
msgstr ""
#: ../src/sdcv.cpp:110
msgid "colorize the output"
msgstr ""
#: ../src/sdcv.cpp:115
msgid " words"
msgstr ""
#: ../src/sdcv.cpp:121
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: ../src/sdcv.cpp:127
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Version console de Stardict, version %s\n"
#: ../src/sdcv.cpp:202
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "Échec de g_mkdir : %s\n"
#: ../src/sdcv.cpp:217
msgid "Enter word or phrase: "
msgstr "Entrez un mot ou une phrase: "
#: ../src/sdcv.cpp:225
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Il n'y a pas de mots/phrases à traduire.\n"
#: ../src/sdcv.cpp:237
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "Nom dictionnaire Nombre de mots\n"
#: ../src/utils.cpp:48
#, c-format
msgid "Can not convert %s to current locale.\n"
msgstr "Ne peut pas convertir %s dans la locale courante.\n"

180
po/ru.po
View File

@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: sdcv 0.5\n"
"Report-Msgid-Bugs-To: dushistov@mail.ru\n"
"POT-Creation-Date: 2008-09-24 10:54+0200\n"
"PO-Revision-Date: 2013-07-07 18:49+0400\n"
"POT-Creation-Date: 2017-08-16 09:52+0300\n"
"PO-Revision-Date: 2017-08-16 10:05+0300\n"
"Last-Translator: Evgeniy Dushistov <dushistov@mail.ru>\n"
"Language-Team: Russian <ru@li.org>\n"
"Language: ru\n"
@@ -19,99 +19,25 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: src/sdcv.cpp:80
msgid "display version information and exit"
msgstr "показать номер версии и завершить работу"
#: src/sdcv.cpp:82
msgid "display list of available dictionaries and exit"
msgstr "показать список доступных словарей и завершить работу"
#: src/sdcv.cpp:84
msgid "for search use only dictionary with this bookname"
msgstr "для поиска использовать только этот словарь с таким именем"
#: src/sdcv.cpp:85
msgid "bookname"
msgstr "имя_словаря"
#: src/sdcv.cpp:87
msgid "for use in scripts"
msgstr "для использования в скриптах"
#: src/sdcv.cpp:89
msgid "output must be in utf8"
msgstr "вывод программы должен быть в utf8"
#: src/sdcv.cpp:91
msgid "input of sdcv in utf8"
msgstr "ввод программы в utf8"
#: src/sdcv.cpp:93
msgid "use this directory as path to stardict data directory"
msgstr ""
"использовать эту директорию в качестве пути к \"stardict data\" директории"
#: src/sdcv.cpp:94
msgid "path/to/dir"
msgstr "путь/до/директории"
#: src/sdcv.cpp:96
msgid "colorize the output"
msgstr "раскрашивать вывод в разные цвета"
#: src/sdcv.cpp:101
msgid " words"
msgstr "слова"
#: src/sdcv.cpp:107
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr "Неправильный аргумент командой строки: %s\n"
#: src/sdcv.cpp:113
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Консольная версия StarDict, версия %s\n"
#: src/sdcv.cpp:139
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "Название словаря Количество слов\n"
#: src/sdcv.cpp:174
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "g_mkdir завершился с ошибкой: %s\n"
#: src/sdcv.cpp:189
msgid "Enter word or phrase: "
msgstr "Введите слово или фразу: "
#: src/sdcv.cpp:197
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Не задано слова/фразы для перевода.\n"
#: src/libwrapper.cpp:280
#: ../src/libwrapper.cpp:300
msgid "popen failed"
msgstr "функция popen завершилась с ошибкой"
#: src/libwrapper.cpp:317 src/utils.cpp:67
#: ../src/libwrapper.cpp:340
#, c-format
msgid "Can not convert %s to utf8.\n"
msgstr "Не могу преобразовать %s в utf8.\n"
#: src/libwrapper.cpp:371 src/libwrapper.cpp:402
#: ../src/libwrapper.cpp:398 ../src/libwrapper.cpp:432
#, c-format
msgid "Found %zu items, similar to %s.\n"
msgstr "Найдено %zu слов, похожих на %s.\n"
#: src/libwrapper.cpp:388
#: ../src/libwrapper.cpp:416
msgid "Your choice[-1 to abort]: "
msgstr "Ваш выбор[-1 - отмена]: "
#: src/libwrapper.cpp:397
#: ../src/libwrapper.cpp:426
#, c-format
msgid ""
"Invalid choice.\n"
@@ -120,12 +46,100 @@ msgstr ""
"Неправильный выбор.\n"
"Должно быть от 0 до %zu или -1.\n"
#: src/libwrapper.cpp:413
#: ../src/libwrapper.cpp:445
#, c-format
msgid "Nothing similar to %s, sorry :(\n"
msgstr "Ничего похожего на %s, извините :(\n"
#: src/utils.cpp:45
#: ../src/sdcv.cpp:88
msgid "display version information and exit"
msgstr "показать номер версии и завершить работу"
#: ../src/sdcv.cpp:90
msgid "display list of available dictionaries and exit"
msgstr "показать список доступных словарей и завершить работу"
#: ../src/sdcv.cpp:92
msgid "for search use only dictionary with this bookname"
msgstr "для поиска использовать только этот словарь с таким именем"
#: ../src/sdcv.cpp:93
msgid "bookname"
msgstr "имя_словаря"
#: ../src/sdcv.cpp:95
msgid "for use in scripts"
msgstr "для использования в скриптах"
#: ../src/sdcv.cpp:97
msgid "print the result formatted as JSON"
msgstr "выдать результат в JSON формате"
#: ../src/sdcv.cpp:99
msgid "do not fuzzy-search for similar words, only return exact matches"
msgstr "не использовать нечеткий поиск похожих слов, вернуть только точные совпадения"
#: ../src/sdcv.cpp:101
msgid "output must be in utf8"
msgstr "вывод программы должен быть в utf8"
#: ../src/sdcv.cpp:103
msgid "input of sdcv in utf8"
msgstr "ввод программы в utf8"
#: ../src/sdcv.cpp:105
msgid "use this directory as path to stardict data directory"
msgstr ""
"использовать эту директорию в качестве пути к \"stardict data\" директории"
#: ../src/sdcv.cpp:106
msgid "path/to/dir"
msgstr "путь/до/директории"
#: ../src/sdcv.cpp:108
msgid ""
"only use the dictionaries in data-dir, do not search in user and system "
"directories"
msgstr "использовать словари только из data-dir, не искать в пользовательских и системных каталогах"
#: ../src/sdcv.cpp:110
msgid "colorize the output"
msgstr "раскрашивать вывод в разные цвета"
#: ../src/sdcv.cpp:115
msgid " words"
msgstr "слова"
#: ../src/sdcv.cpp:121
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr "Неправильный аргумент командой строки: %s\n"
#: ../src/sdcv.cpp:127
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Консольная версия StarDict, версия %s\n"
#: ../src/sdcv.cpp:202
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "g_mkdir завершился с ошибкой: %s\n"
#: ../src/sdcv.cpp:217
msgid "Enter word or phrase: "
msgstr "Введите слово или фразу: "
#: ../src/sdcv.cpp:225
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Не задано слова/фразы для перевода.\n"
#: ../src/sdcv.cpp:237
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "Название словаря Количество слов\n"
#: ../src/utils.cpp:48
#, c-format
msgid "Can not convert %s to current locale.\n"
msgstr "Не могу преобразовать %s в локальную кодировку.\n"

View File

@@ -7,118 +7,133 @@ msgid ""
msgstr ""
"Project-Id-Version: sdcv 0.5\n"
"Report-Msgid-Bugs-To: dushistov@mail.ru\n"
"POT-Creation-Date: 2008-09-24 10:54+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"POT-Creation-Date: 2017-08-16 09:52+0300\n"
"PO-Revision-Date: 2017-08-16 10:01+0300\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/sdcv.cpp:76
msgid "display version information and exit"
msgstr ""
#: src/sdcv.cpp:78
msgid "display list of available dictionaries and exit"
msgstr ""
#: src/sdcv.cpp:84
msgid "for search use only dictionary with this bookname"
msgstr ""
#: src/sdcv.cpp:85
msgid "bookname"
msgstr ""
#: src/sdcv.cpp:87
msgid "for use in scripts"
msgstr ""
#: src/sdcv.cpp:89
msgid "output must be in utf8"
msgstr ""
#: src/sdcv.cpp:91
msgid "input of sdcv in utf8"
msgstr ""
#: src/sdcv.cpp:93
msgid "use this directory as path to stardict data directory"
msgstr ""
#: src/sdcv.cpp:94
msgid "path/to/dir"
msgstr ""
#: src/sdcv.cpp:96
msgid "colorize the output"
msgstr ""
#: src/sdcv.cpp:101
msgid " words"
msgstr ""
#: src/sdcv.cpp:107
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: src/sdcv.cpp:113
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr ""
#: src/sdcv.cpp:139
#, c-format
msgid "Dictionary's name Word count\n"
msgstr ""
#: src/sdcv.cpp:174
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr ""
#: src/sdcv.cpp:189
msgid "Enter word or phrase: "
msgstr ""
#: src/sdcv.cpp:197
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr ""
#: src/libwrapper.cpp:280
#: ../src/libwrapper.cpp:300
msgid "popen failed"
msgstr ""
#: src/libwrapper.cpp:317 src/utils.cpp:67
#: ../src/libwrapper.cpp:340
#, c-format
msgid "Can not convert %s to utf8.\n"
msgstr ""
#: src/libwrapper.cpp:371 src/libwrapper.cpp:402
#: ../src/libwrapper.cpp:398 ../src/libwrapper.cpp:432
#, c-format
msgid "Found %zu items, similar to %s.\n"
msgstr ""
#: src/libwrapper.cpp:388
#: ../src/libwrapper.cpp:416
msgid "Your choice[-1 to abort]: "
msgstr ""
#: src/libwrapper.cpp:397
#: ../src/libwrapper.cpp:426
#, c-format
msgid ""
"Invalid choice.\n"
"It must be from 0 to %zu or -1.\n"
msgstr ""
#: src/libwrapper.cpp:413
#: ../src/libwrapper.cpp:445
#, c-format
msgid "Nothing similar to %s, sorry :(\n"
msgstr ""
#: src/utils.cpp:45
#: ../src/sdcv.cpp:88
msgid "display version information and exit"
msgstr ""
#: ../src/sdcv.cpp:90
msgid "display list of available dictionaries and exit"
msgstr ""
#: ../src/sdcv.cpp:92
msgid "for search use only dictionary with this bookname"
msgstr ""
#: ../src/sdcv.cpp:93
msgid "bookname"
msgstr ""
#: ../src/sdcv.cpp:95
msgid "for use in scripts"
msgstr ""
#: ../src/sdcv.cpp:97
msgid "print the result formatted as JSON"
msgstr ""
#: ../src/sdcv.cpp:99
msgid "do not fuzzy-search for similar words, only return exact matches"
msgstr ""
#: ../src/sdcv.cpp:101
msgid "output must be in utf8"
msgstr ""
#: ../src/sdcv.cpp:103
msgid "input of sdcv in utf8"
msgstr ""
#: ../src/sdcv.cpp:105
msgid "use this directory as path to stardict data directory"
msgstr ""
#: ../src/sdcv.cpp:106
msgid "path/to/dir"
msgstr ""
#: ../src/sdcv.cpp:108
msgid ""
"only use the dictionaries in data-dir, do not search in user and system "
"directories"
msgstr ""
#: ../src/sdcv.cpp:110
msgid "colorize the output"
msgstr ""
#: ../src/sdcv.cpp:115
msgid " words"
msgstr ""
#: ../src/sdcv.cpp:121
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: ../src/sdcv.cpp:127
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr ""
#: ../src/sdcv.cpp:202
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr ""
#: ../src/sdcv.cpp:217
msgid "Enter word or phrase: "
msgstr ""
#: ../src/sdcv.cpp:225
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr ""
#: ../src/sdcv.cpp:237
#, c-format
msgid "Dictionary's name Word count\n"
msgstr ""
#: ../src/utils.cpp:48
#, c-format
msgid "Can not convert %s to current locale.\n"
msgstr ""

190
po/sk.po
View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sdcv 0.3.2\n"
"Report-Msgid-Bugs-To: dushistov@mail.ru\n"
"POT-Creation-Date: 2008-09-24 10:54+0200\n"
"POT-Creation-Date: 2017-08-16 09:52+0300\n"
"PO-Revision-Date: 2007-09-11 00:22+0100\n"
"Last-Translator: Ivan Masár <helix84@centrum.sk>\n"
"Language-Team: Slovak <sk-i18n@lists.linux.sk>\n"
@@ -18,104 +18,26 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: src/sdcv.cpp:108
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version zobrazí informácie o verzii a skončí\n"
#: src/sdcv.cpp:110
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr ""
"-l, --list-dicts zobrazí zoznam dostupných slovníkov a skončí\n"
#: src/sdcv.cpp:112
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr "-u, --use-dict názov použiť pre hľadanie iba zvolený slovník\n"
#: src/sdcv.cpp:113
msgid "bookname"
msgstr ""
#: src/sdcv.cpp:115
msgid "for use in scripts"
msgstr ""
#: src/sdcv.cpp:117
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output výstup musí byť v utf8\n"
#: src/sdcv.cpp:119
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input vstup pre sdcv je v utf8\n"
#: src/sdcv.cpp:121
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr ""
"--data-dir path/to/dir použiť tento priečinok ako cestu pre stardict "
"dátový priečinok\n"
#: src/sdcv.cpp:122
msgid "path/to/dir"
msgstr ""
#: src/sdcv.cpp:129
msgid " words"
msgstr ""
#: src/sdcv.cpp:135
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: src/sdcv.cpp:141
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Konzolová verzia StarDict, verzia %s\n"
#: src/sdcv.cpp:170
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "názov slovníka počet slov\n"
#: src/sdcv.cpp:192
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "g_mkdir zlyhalo: %s\n"
#: src/sdcv.cpp:208
msgid "Enter word or phrase: "
msgstr "Vložte slovo alebo frázu: "
#: src/sdcv.cpp:216
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Nie je čo preložiť.\n"
#: src/libwrapper.cpp:248
#: ../src/libwrapper.cpp:300
msgid "popen failed"
msgstr "popen zlyhalo"
#: src/libwrapper.cpp:285 src/utils.cpp:67
#: ../src/libwrapper.cpp:340
#, c-format
msgid "Can not convert %s to utf8.\n"
msgstr "nie je možné konvertovať %s na utf8.\n"
#: src/libwrapper.cpp:342 src/libwrapper.cpp:370
#: ../src/libwrapper.cpp:398 ../src/libwrapper.cpp:432
#, fuzzy, c-format
msgid "Found %zu items, similar to %s.\n"
msgstr "Nájdené %d položiek, podobných %s,\n"
#: src/libwrapper.cpp:356
#: ../src/libwrapper.cpp:416
#, fuzzy
msgid "Your choice[-1 to abort]: "
msgstr "Vaša voľba[-1 zruší]: "
#: src/libwrapper.cpp:365
#: ../src/libwrapper.cpp:426
#, fuzzy, c-format
msgid ""
"Invalid choice.\n"
@@ -124,12 +46,108 @@ msgstr ""
"Neplatná voľba.\n"
"Musí byť od 0 do %d alebo -1.\n"
#: src/libwrapper.cpp:381
#: ../src/libwrapper.cpp:445
#, c-format
msgid "Nothing similar to %s, sorry :(\n"
msgstr "Ľutujem, nič sa nepodobá na %s :(\n"
#: src/utils.cpp:45
#: ../src/sdcv.cpp:88
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version zobrazí informácie o verzii a skončí\n"
#: ../src/sdcv.cpp:90
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr ""
"-l, --list-dicts zobrazí zoznam dostupných slovníkov a skončí\n"
#: ../src/sdcv.cpp:92
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr "-u, --use-dict názov použiť pre hľadanie iba zvolený slovník\n"
#: ../src/sdcv.cpp:93
msgid "bookname"
msgstr ""
#: ../src/sdcv.cpp:95
msgid "for use in scripts"
msgstr ""
#: ../src/sdcv.cpp:97
msgid "print the result formatted as JSON"
msgstr ""
#: ../src/sdcv.cpp:99
msgid "do not fuzzy-search for similar words, only return exact matches"
msgstr ""
#: ../src/sdcv.cpp:101
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output výstup musí byť v utf8\n"
#: ../src/sdcv.cpp:103
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input vstup pre sdcv je v utf8\n"
#: ../src/sdcv.cpp:105
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr ""
"--data-dir path/to/dir použiť tento priečinok ako cestu pre stardict "
"dátový priečinok\n"
#: ../src/sdcv.cpp:106
msgid "path/to/dir"
msgstr ""
#: ../src/sdcv.cpp:108
msgid ""
"only use the dictionaries in data-dir, do not search in user and system "
"directories"
msgstr ""
#: ../src/sdcv.cpp:110
msgid "colorize the output"
msgstr ""
#: ../src/sdcv.cpp:115
msgid " words"
msgstr ""
#: ../src/sdcv.cpp:121
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: ../src/sdcv.cpp:127
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Konzolová verzia StarDict, verzia %s\n"
#: ../src/sdcv.cpp:202
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "g_mkdir zlyhalo: %s\n"
#: ../src/sdcv.cpp:217
msgid "Enter word or phrase: "
msgstr "Vložte slovo alebo frázu: "
#: ../src/sdcv.cpp:225
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Nie je čo preložiť.\n"
#: ../src/sdcv.cpp:237
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "názov slovníka počet slov\n"
#: ../src/utils.cpp:48
#, c-format
msgid "Can not convert %s to current locale.\n"
msgstr "Nie je možné konvertovať %s na aktuálne locale.\n"

194
po/uk.po
View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sdcv 0.3\n"
"Report-Msgid-Bugs-To: dushistov@mail.ru\n"
"POT-Creation-Date: 2008-09-24 10:54+0200\n"
"POT-Creation-Date: 2017-08-16 09:52+0300\n"
"PO-Revision-Date: 2004-12-14 17:54+0300\n"
"Last-Translator: <dubyk@lsl.lviv.ua>\n"
"Language-Team: Ukrainian <dubyk@lsl.lviv.ua>\n"
@@ -19,106 +19,26 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: src/sdcv.cpp:108
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version показати номер версії і завершити роботу\n"
#: src/sdcv.cpp:110
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr ""
"-l, --list-dicts показати список доступних словників і завершити "
"роботу\n"
#: src/sdcv.cpp:112
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr ""
"-u, --use-dict ім`я словника для пошуку використовувати лише цей словник\n"
#: src/sdcv.cpp:113
msgid "bookname"
msgstr ""
#: src/sdcv.cpp:115
msgid "for use in scripts"
msgstr ""
#: src/sdcv.cpp:117
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output вивід програми повинен бути в utf8\n"
#: src/sdcv.cpp:119
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input ввід програми в utf8\n"
#: src/sdcv.cpp:121
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr ""
"--data-dir тека використовувати цю теку як шлях до stardict data "
"directory\n"
#: src/sdcv.cpp:122
msgid "path/to/dir"
msgstr ""
#: src/sdcv.cpp:129
msgid " words"
msgstr ""
#: src/sdcv.cpp:135
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: src/sdcv.cpp:141
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Консольна версія Зоряного словника [Stardict], номер версії %s\n"
#: src/sdcv.cpp:170
#, fuzzy, c-format
msgid "Dictionary's name Word count\n"
msgstr "назва словника кількість слів\n"
#: src/sdcv.cpp:192
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr ""
#: src/sdcv.cpp:208
msgid "Enter word or phrase: "
msgstr "ВведЁть слово або фразу: "
#: src/sdcv.cpp:216
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Не задано слова/фрази для перекладу.\n"
#: src/libwrapper.cpp:248
#: ../src/libwrapper.cpp:300
msgid "popen failed"
msgstr ""
#: src/libwrapper.cpp:285 src/utils.cpp:67
#: ../src/libwrapper.cpp:340
#, c-format
msgid "Can not convert %s to utf8.\n"
msgstr "Не можу перетворити %s у utf8.\n"
#: src/libwrapper.cpp:342 src/libwrapper.cpp:370
#: ../src/libwrapper.cpp:398 ../src/libwrapper.cpp:432
#, fuzzy, c-format
msgid "Found %zu items, similar to %s.\n"
msgstr "Знайдено %d слів, схожих на %s.\n"
#: src/libwrapper.cpp:356
#: ../src/libwrapper.cpp:416
#, fuzzy
msgid "Your choice[-1 to abort]: "
msgstr "Ваш вибір: "
#: src/libwrapper.cpp:365
#: ../src/libwrapper.cpp:426
#, fuzzy, c-format
msgid ""
"Invalid choice.\n"
@@ -127,12 +47,110 @@ msgstr ""
"Неправильний вибір.\n"
"Повинно бути від 0 до %d.\n"
#: src/libwrapper.cpp:381
#: ../src/libwrapper.cpp:445
#, c-format
msgid "Nothing similar to %s, sorry :(\n"
msgstr "Нічого схожого на %s, даруйте :(\n"
#: src/utils.cpp:45
#: ../src/sdcv.cpp:88
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version показати номер версії і завершити роботу\n"
#: ../src/sdcv.cpp:90
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr ""
"-l, --list-dicts показати список доступних словників і завершити "
"роботу\n"
#: ../src/sdcv.cpp:92
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr ""
"-u, --use-dict ім`я словника для пошуку використовувати лише цей словник\n"
#: ../src/sdcv.cpp:93
msgid "bookname"
msgstr ""
#: ../src/sdcv.cpp:95
msgid "for use in scripts"
msgstr ""
#: ../src/sdcv.cpp:97
msgid "print the result formatted as JSON"
msgstr ""
#: ../src/sdcv.cpp:99
msgid "do not fuzzy-search for similar words, only return exact matches"
msgstr ""
#: ../src/sdcv.cpp:101
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output вивід програми повинен бути в utf8\n"
#: ../src/sdcv.cpp:103
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input ввід програми в utf8\n"
#: ../src/sdcv.cpp:105
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr ""
"--data-dir тека використовувати цю теку як шлях до stardict data "
"directory\n"
#: ../src/sdcv.cpp:106
msgid "path/to/dir"
msgstr ""
#: ../src/sdcv.cpp:108
msgid ""
"only use the dictionaries in data-dir, do not search in user and system "
"directories"
msgstr ""
#: ../src/sdcv.cpp:110
msgid "colorize the output"
msgstr ""
#: ../src/sdcv.cpp:115
msgid " words"
msgstr ""
#: ../src/sdcv.cpp:121
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: ../src/sdcv.cpp:127
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Консольна версія Зоряного словника [Stardict], номер версії %s\n"
#: ../src/sdcv.cpp:202
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr ""
#: ../src/sdcv.cpp:217
msgid "Enter word or phrase: "
msgstr "ВведЁть слово або фразу: "
#: ../src/sdcv.cpp:225
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "Не задано слова/фрази для перекладу.\n"
#: ../src/sdcv.cpp:237
#, fuzzy, c-format
msgid "Dictionary's name Word count\n"
msgstr "назва словника кількість слів\n"
#: ../src/utils.cpp:48
#, c-format
msgid "Can not convert %s to current locale.\n"
msgstr "Не можу перетворити %s у локальне кодування.\n"

View File

@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: sdcv 0.3\n"
"Report-Msgid-Bugs-To: dushistov@mail.ru\n"
"POT-Creation-Date: 2008-09-24 10:54+0200\n"
"POT-Creation-Date: 2017-08-16 09:52+0300\n"
"PO-Revision-Date: 2005-1-17 00:58+0800\n"
"Last-Translator: Cai Qian <caiqian@gnome.org>\n"
"Language-Team: Simplified Chinese\n"
@@ -15,101 +15,26 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/sdcv.cpp:108
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version 显示版本信息并退出\n"
#: src/sdcv.cpp:110
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr "-l, --list-dicts 显示可用的字典列表并退出\n"
#: src/sdcv.cpp:112
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr "-u, --use-dict 字典名 只使用指定的字典进行单词搜索\n"
#: src/sdcv.cpp:113
msgid "bookname"
msgstr ""
#: src/sdcv.cpp:115
msgid "for use in scripts"
msgstr ""
#: src/sdcv.cpp:117
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output 输出必须是 UTF-8\n"
#: src/sdcv.cpp:119
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input sdcv 的输入为 UTF-8\n"
#: src/sdcv.cpp:121
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr "--data-dir 目录路径 指定 Stardict 数据所在目录的路径\n"
#: src/sdcv.cpp:122
msgid "path/to/dir"
msgstr ""
#: src/sdcv.cpp:129
msgid " words"
msgstr ""
#: src/sdcv.cpp:135
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: src/sdcv.cpp:141
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Stardict 的控制台版本,版本为 %s\n"
#: src/sdcv.cpp:170
#, fuzzy, c-format
msgid "Dictionary's name Word count\n"
msgstr "字典名 单词量\n"
#: src/sdcv.cpp:192
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr ""
#: src/sdcv.cpp:208
msgid "Enter word or phrase: "
msgstr "请输入单词或短语:"
#: src/sdcv.cpp:216
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "没有供翻译的单词或短语。\n"
#: src/libwrapper.cpp:248
#: ../src/libwrapper.cpp:300
msgid "popen failed"
msgstr ""
#: src/libwrapper.cpp:285 src/utils.cpp:67
#: ../src/libwrapper.cpp:340
#, c-format
msgid "Can not convert %s to utf8.\n"
msgstr "无法将 %s 转换为 UTF-8。\n"
#: src/libwrapper.cpp:342 src/libwrapper.cpp:370
#: ../src/libwrapper.cpp:398 ../src/libwrapper.cpp:432
#, fuzzy, c-format
msgid "Found %zu items, similar to %s.\n"
msgstr "发现 %d 条记录和 %s 相似。\n"
#: src/libwrapper.cpp:356
#: ../src/libwrapper.cpp:416
#, fuzzy
msgid "Your choice[-1 to abort]: "
msgstr "您的选择为:"
#: src/libwrapper.cpp:365
#: ../src/libwrapper.cpp:426
#, fuzzy, c-format
msgid ""
"Invalid choice.\n"
@@ -118,12 +43,105 @@ msgstr ""
"无效的选择。\n"
"必须是 0 到 %d。\n"
#: src/libwrapper.cpp:381
#: ../src/libwrapper.cpp:445
#, c-format
msgid "Nothing similar to %s, sorry :(\n"
msgstr "对不起,没有发现和 %s 相似的 :(\n"
#: src/utils.cpp:45
#: ../src/sdcv.cpp:88
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version 显示版本信息并退出\n"
#: ../src/sdcv.cpp:90
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr "-l, --list-dicts 显示可用的字典列表并退出\n"
#: ../src/sdcv.cpp:92
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr "-u, --use-dict 字典名 只使用指定的字典进行单词搜索\n"
#: ../src/sdcv.cpp:93
msgid "bookname"
msgstr ""
#: ../src/sdcv.cpp:95
msgid "for use in scripts"
msgstr ""
#: ../src/sdcv.cpp:97
msgid "print the result formatted as JSON"
msgstr ""
#: ../src/sdcv.cpp:99
msgid "do not fuzzy-search for similar words, only return exact matches"
msgstr ""
#: ../src/sdcv.cpp:101
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output 输出必须是 UTF-8\n"
#: ../src/sdcv.cpp:103
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input sdcv 的输入为 UTF-8\n"
#: ../src/sdcv.cpp:105
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr "--data-dir 目录路径 指定 Stardict 数据所在目录的路径\n"
#: ../src/sdcv.cpp:106
msgid "path/to/dir"
msgstr ""
#: ../src/sdcv.cpp:108
msgid ""
"only use the dictionaries in data-dir, do not search in user and system "
"directories"
msgstr ""
#: ../src/sdcv.cpp:110
msgid "colorize the output"
msgstr ""
#: ../src/sdcv.cpp:115
msgid " words"
msgstr ""
#: ../src/sdcv.cpp:121
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: ../src/sdcv.cpp:127
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Stardict 的控制台版本,版本为 %s\n"
#: ../src/sdcv.cpp:202
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr ""
#: ../src/sdcv.cpp:217
msgid "Enter word or phrase: "
msgstr "请输入单词或短语:"
#: ../src/sdcv.cpp:225
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "没有供翻译的单词或短语。\n"
#: ../src/sdcv.cpp:237
#, fuzzy, c-format
msgid "Dictionary's name Word count\n"
msgstr "字典名 单词量\n"
#: ../src/utils.cpp:48
#, c-format
msgid "Can not convert %s to current locale.\n"
msgstr "无法将 %s 转换为当前 Locale。\n"

View File

@@ -8,122 +8,158 @@ msgid ""
msgstr ""
"Project-Id-Version: sdcv 0.4.2\n"
"Report-Msgid-Bugs-To: dushistov@mail.ru\n"
"POT-Creation-Date: 2006-04-24 15:18+0400\n"
"POT-Creation-Date: 2017-08-16 09:52+0300\n"
"PO-Revision-Date: 2013-06-12 14:11+0800\n"
"Last-Translator: Wei-Lun Chao <bluebat@member.fsf.org>\n"
"Language-Team: Chinese (traditional) <zh-l10n@linux.org.tw>\n"
"Language: zh_TW\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: src/sdcv.cpp:127
#, c-format
msgid ""
"Unknown option.\n"
"Try '%s --help' for more information.\n"
msgstr ""
"不明選項。\n"
"更多資訊請看 '%s --help'。\n"
#: src/sdcv.cpp:134
#, c-format
msgid "Usage: %s [OPTIONS] words\n"
msgstr "用法:%s [選項] 單字…\n"
#: src/sdcv.cpp:135
#, c-format
msgid "-h, --help display this help and exit\n"
msgstr "-h, --help 顯示本輔助並離開\n"
#: src/sdcv.cpp:136
#, c-format
msgid "-v, --version display version information and exit\n"
msgstr "-v, --version 顯示版本資訊並離開\n"
#: src/sdcv.cpp:137
#, c-format
msgid "-l, --list-dicts display list of available dictionaries and exit\n"
msgstr "-l, --list-dicts 顯示可用的字典清單並離開\n"
#: src/sdcv.cpp:138
#, c-format
msgid "-u, --use-dict bookname for search use only dictionary with this bookname\n"
msgstr "-u, --use-dict 字典名 只使用指定的字典進行單字搜尋\n"
#: src/sdcv.cpp:139
#, c-format
msgid "-n, --non-interactive for use in scripts\n"
msgstr "-n, --non-interactive 在指令稿中使用\n"
#: src/sdcv.cpp:140
#, c-format
msgid "--utf8-output output must be in utf8\n"
msgstr "--utf8-output 輸出必須是 UTF-8\n"
#: src/sdcv.cpp:141
#, c-format
msgid "--utf8-input input of sdcv in utf8\n"
msgstr "--utf8-input sdcv 的輸入為 UTF-8\n"
#: src/sdcv.cpp:142
#, c-format
msgid "--data-dir path/to/dir use this directory as path to stardict data directory\n"
msgstr "--data-dir 目錄路徑 指定 Stardict 資料所在目錄的路徑\n"
#: src/sdcv.cpp:148
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Stardict 的主控臺版本,版本為 %s\n"
#: src/sdcv.cpp:169
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "字典名稱 單字數量\n"
#: src/sdcv.cpp:191
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "g_mkdir 失敗:%s\n"
#: src/sdcv.cpp:207
msgid "Enter word or phrase: "
msgstr "請輸入單字或片語:"
#: src/sdcv.cpp:215
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "沒有可供翻譯的單字或片語。\n"
#: src/libwrapper.cpp:245
#: ../src/libwrapper.cpp:300
msgid "popen failed"
msgstr "popen 失敗"
#: src/libwrapper.cpp:282
#: ../src/libwrapper.cpp:340
#, c-format
msgid "Can not convert %s to utf8.\n"
msgstr "無法將 %s 轉換為 UTF-8。\n"
#: src/libwrapper.cpp:339 src/libwrapper.cpp:371
#, c-format
msgid "Found %d items, similar to %s.\n"
#: ../src/libwrapper.cpp:398 ../src/libwrapper.cpp:432
#, fuzzy, c-format
msgid "Found %zu items, similar to %s.\n"
msgstr "找到 %d 項紀錄和 %s 相似。\n"
#: src/libwrapper.cpp:352
#, c-format
#: ../src/libwrapper.cpp:416
msgid "Your choice[-1 to abort]: "
msgstr "您的選擇是[-1 表示放棄]"
#: src/libwrapper.cpp:366
#, c-format
#: ../src/libwrapper.cpp:426
#, fuzzy, c-format
msgid ""
"Invalid choise.\n"
"It must be from 0 to %d or -1.\n"
"Invalid choice.\n"
"It must be from 0 to %zu or -1.\n"
msgstr ""
"無效的選擇。\n"
"必須是 0 到 %d 之間或 -1。\n"
#: src/libwrapper.cpp:382
#: ../src/libwrapper.cpp:445
#, c-format
msgid "Nothing similar to %s, sorry :(\n"
msgstr "抱歉,沒有和 %s 相似者 :(\n"
#: ../src/sdcv.cpp:88
#, fuzzy
msgid "display version information and exit"
msgstr "-v, --version 顯示版本資訊並離開\n"
#: ../src/sdcv.cpp:90
#, fuzzy
msgid "display list of available dictionaries and exit"
msgstr "-l, --list-dicts 顯示可用的字典清單並離開\n"
#: ../src/sdcv.cpp:92
#, fuzzy
msgid "for search use only dictionary with this bookname"
msgstr "-u, --use-dict 字典名 只使用指定的字典進行單字搜尋\n"
#: ../src/sdcv.cpp:93
msgid "bookname"
msgstr ""
#: ../src/sdcv.cpp:95
msgid "for use in scripts"
msgstr ""
#: ../src/sdcv.cpp:97
msgid "print the result formatted as JSON"
msgstr ""
#: ../src/sdcv.cpp:99
msgid "do not fuzzy-search for similar words, only return exact matches"
msgstr ""
#: ../src/sdcv.cpp:101
#, fuzzy
msgid "output must be in utf8"
msgstr "--utf8-output 輸出必須是 UTF-8\n"
#: ../src/sdcv.cpp:103
#, fuzzy
msgid "input of sdcv in utf8"
msgstr "--utf8-input sdcv 的輸入為 UTF-8\n"
#: ../src/sdcv.cpp:105
#, fuzzy
msgid "use this directory as path to stardict data directory"
msgstr "--data-dir 目錄路徑 指定 Stardict 資料所在目錄的路徑\n"
#: ../src/sdcv.cpp:106
msgid "path/to/dir"
msgstr ""
#: ../src/sdcv.cpp:108
msgid ""
"only use the dictionaries in data-dir, do not search in user and system "
"directories"
msgstr ""
#: ../src/sdcv.cpp:110
msgid "colorize the output"
msgstr ""
#: ../src/sdcv.cpp:115
msgid " words"
msgstr ""
#: ../src/sdcv.cpp:121
#, c-format
msgid "Invalid command line arguments: %s\n"
msgstr ""
#: ../src/sdcv.cpp:127
#, c-format
msgid "Console version of Stardict, version %s\n"
msgstr "Stardict 的主控臺版本,版本為 %s\n"
#: ../src/sdcv.cpp:202
#, c-format
msgid "g_mkdir failed: %s\n"
msgstr "g_mkdir 失敗:%s\n"
#: ../src/sdcv.cpp:217
msgid "Enter word or phrase: "
msgstr "請輸入單字或片語:"
#: ../src/sdcv.cpp:225
#, c-format
msgid "There are no words/phrases to translate.\n"
msgstr "沒有可供翻譯的單字或片語。\n"
#: ../src/sdcv.cpp:237
#, c-format
msgid "Dictionary's name Word count\n"
msgstr "字典名稱 單字數量\n"
#: ../src/utils.cpp:48
#, fuzzy, c-format
msgid "Can not convert %s to current locale.\n"
msgstr "無法將 %s 轉換為 UTF-8。\n"
#~ msgid ""
#~ "Unknown option.\n"
#~ "Try '%s --help' for more information.\n"
#~ msgstr ""
#~ "不明選項。\n"
#~ "更多資訊請看 '%s --help'。\n"
#~ msgid "Usage: %s [OPTIONS] words\n"
#~ msgstr "用法:%s [選項] 單字…\n"
#~ msgid "-h, --help display this help and exit\n"
#~ msgstr "-h, --help 顯示本輔助並離開\n"
#~ msgid "-n, --non-interactive for use in scripts\n"
#~ msgstr "-n, --non-interactive 在指令稿中使用\n"

View File

@@ -21,25 +21,24 @@
*
* 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.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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"
#include "config.h"
#endif
#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <limits.h>
#include <fcntl.h>
#include <limits.h>
#include <unistd.h>
#include <sys/stat.h>
#include "dictziplib.hpp"
#define USE_CACHE 1
@@ -57,426 +56,424 @@
/* 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 */
/* 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 */
/* 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 */
/* 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_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
#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;
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 );
if (!(str = fopen(fname.c_str(), "rb"))) {
//err_fatal_errno( __FUNCTION__,
// "Cannot open data file \"%s\" for read\n", filename );
return -1;
}
}
this->headerLength = GZ_XLEN - 1;
this->type = DICT_UNKNOWN;
this->headerLength = GZ_XLEN - 1;
this->type = DICT_UNKNOWN;
id1 = getc( str );
id2 = getc( str );
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;
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 );
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 (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 (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 );
}
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;
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->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';
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 = "";
}
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_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 (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 );
}
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 );
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];
}
/* 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;
fclose(str);
return 0;
}
bool DictData::open(const std::string& fname, int computeCRC)
bool DictData::open(const std::string &fname, int computeCRC)
{
struct stat sb;
int fd;
struct stat sb;
int fd;
this->initialized = 0;
this->initialized = 0;
if (stat(fname.c_str(), &sb) || !S_ISREG(sb.st_mode)) {
//err_warning( __FUNCTION__,
// "%s is not a regular file -- ignoring\n", fname );
return false;
}
if (stat(fname.c_str(), &sb) || !S_ISREG(sb.st_mode)) {
//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 (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;
}
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->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;
this->start = mapfile.begin();
this->end = this->start + this->size;
for (size_t j = 0; j < DICT_CACHE_SIZE; j++) {
cache[j].chunk = -1;
cache[j].stamp = -1;
cache[j].inBuffer = nullptr;
cache[j].count = 0;
}
for (size_t j = 0; j < DICT_CACHE_SIZE; j++) {
cache[j].chunk = -1;
cache[j].stamp = -1;
cache[j].inBuffer = nullptr;
cache[j].count = 0;
}
return true;
return true;
}
void DictData::close()
{
if (this->chunks)
free(this->chunks);
if (this->offsets)
free(this->offsets);
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 );
}
}
if (this->initialized) {
if (inflateEnd(&this->zStream)) {
//err_internal( __FUNCTION__,
// "Cannot shut down inflation engine: %s\n",
// this->zStream.msg );
}
}
for (size_t i = 0; i < DICT_CACHE_SIZE; ++i){
if (this -> cache [i].inBuffer)
free (this -> cache [i].inBuffer);
}
for (size_t 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;
int found, target, lastStamp;
static int stamp = 0;
char *pt;
unsigned long end;
int count;
char *inBuffer;
char outBuffer[OUT_BUFFER_SIZE];
int firstChunk, lastChunk;
int firstOffset, lastOffset;
int i;
int found, target, lastStamp;
static int stamp = 0;
end = start + size;
end = start + size;
//buffer = malloc( size + 1 );
//buffer = malloc( size + 1 );
//PRINTF(DBG_UNZIP,
// ("dict_data_read( %p, %lu, %lu )\n",
//h, start, size ));
//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 = nullptr;
this->zStream.zfree = nullptr;
this->zStream.opaque = nullptr;
this->zStream.next_in = 0;
this->zStream.avail_in = 0;
this->zStream.next_out = nullptr;
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++) {
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 = nullptr;
this->zStream.zfree = nullptr;
this->zStream.opaque = nullptr;
this->zStream.next_in = 0;
this->zStream.avail_in = 0;
this->zStream.next_out = nullptr;
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 (size_t j = 0; j < DICT_CACHE_SIZE; j++) {
/* Access cache */
found = 0;
target = 0;
lastStamp = INT_MAX;
for (size_t j = 0; j < DICT_CACHE_SIZE; j++) {
#if USE_CACHE
if (this->cache[j].chunk == i) {
found = 1;
target = j;
break;
}
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;
}
}
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;
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] );
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 );
}
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;
count = IN_BUFFER_SIZE - this->zStream.avail_out;
this->cache[target].count = count;
}
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;
}
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;
}
}

View File

@@ -7,49 +7,50 @@
#include "mapfile.hpp"
struct DictCache {
int chunk;
char *inBuffer;
int stamp;
int count;
int chunk;
char *inBuffer;
int stamp;
int count;
};
class DictData {
class DictData
{
public:
static const size_t DICT_CACHE_SIZE = 5;
static const size_t DICT_CACHE_SIZE = 5;
DictData() {}
~DictData() { close(); }
bool open(const std::string &filename, int computeCRC);
void close();
void read(char *buffer, unsigned long start, unsigned long size);
DictData() {}
~DictData() { close(); }
bool open(const std::string& filename, int computeCRC);
void close();
void read(char *buffer, unsigned long start, unsigned long size);
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;
const char *start; /* start of mmap'd area */
const char *end; /* end of mmap'd area */
unsigned long size; /* size of mmap */
int read_header(const std::string &filename, int computeCRC);
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);
};

View File

@@ -33,7 +33,6 @@ The Levenshtein distance algorithm has been used in:
* Plagiarism detection
*/
#include <cstdlib>
#include <cstring>
@@ -56,43 +55,39 @@ Enhanced Dynamic Programming ASM Algorithm"
static inline int minimum(const int a, const int b, const int c)
{
int min = a;
if ( b < min )
if (b < min)
min = b;
if ( c < min )
if (c < min)
min = c;
return min;
}
int EditDistance::CalEditDistance(const gunichar *s,const gunichar *t,const int limit)
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;
int n = 0, m = 0, iLenDif, k, i, j, cost;
// Remove leftmost matching portion of strings
while ( *s && (*s==*t) )
{
while (*s && (*s == *t)) {
s++;
t++;
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--;
while (s[n]) {
n++;
}
if ( m==0 || n==0 || d==nullptr )
return (m+n);
if ( m < n )
{
const gunichar * temp = s;
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 == nullptr)
return (m + n);
if (m < n) {
const gunichar *temp = s;
int itemp = n;
s = t;
t = temp;
@@ -100,55 +95,51 @@ int EditDistance::CalEditDistance(const gunichar *s,const gunichar *t,const int
m = itemp;
}
iLenDif = m - n;
if ( iLenDif >= limit )
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 = static_cast<int*>(realloc(d, sizeof(int) * currentelements));
if ( nullptr == d )
return (m+n);
n++;
m++;
// d=(int*)malloc(sizeof(int)*m*n);
if (m * n > currentelements) {
currentelements = m * n * 2; // double the request
d = static_cast<int *>(realloc(d, sizeof(int) * currentelements));
if (nullptr == d)
return (m + n);
}
// step 2, init matrix
for (k=0;k<n;k++)
for (k = 0; k < n; k++)
d[k] = k;
for (k=1;k<m;k++)
d[k*n] = k;
for (k = 1; k < m; k++)
d[k * n] = k;
// step 3
for (i=1;i<n;i++)
{
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);
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]--;
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);
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]--;
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];
if (d[j * n + i] >= limit) {
return d[j * n + i];
}
}
// d(n-1,m-1)
return d[n*m-1];
return d[n * m - 1];
}

View File

@@ -3,21 +3,24 @@
#include <cstdlib>
#include <glib.h>
class EditDistance {
class EditDistance
{
public:
EditDistance() {
EditDistance()
{
currentelements = 2500; // It's enough for most conditions :-)
d = static_cast<int *>(malloc(sizeof(int)*currentelements));
d = static_cast<int *>(malloc(sizeof(int) * currentelements));
}
~EditDistance() {
~EditDistance()
{
if (d != nullptr)
free(d);
}
EditDistance(const EditDistance&) = delete;
EditDistance& operator=(const EditDistance&) = delete;
int CalEditDistance( const gunichar *s, const gunichar *t, const int limit );
EditDistance(const EditDistance &) = delete;
EditDistance &operator=(const EditDistance &) = delete;
int CalEditDistance(const gunichar *s, const gunichar *t, const int limit);
private:
int *d;
int currentelements;
};

View File

@@ -15,11 +15,11 @@
*
* 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.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#include "config.h"
#endif
#include <cstring>
@@ -48,373 +48,405 @@ static const char *ABR_VISFMT = ESC_GREEN;
static std::string xdxf2text(const char *p, bool colorize_output)
{
std::string res;
for (; *p; ++p) {
if (*p != '<') {
if (g_str_has_prefix(p, "&gt;")) {
res += ">";
p += 3;
} else if (g_str_has_prefix(p, "&lt;")) {
res += "<";
p += 3;
} else if (g_str_has_prefix(p, "&amp;")) {
res += "&";
p += 4;
} else if (g_str_has_prefix(p, "&quot;")) {
res += "\"";
p += 5;
} else if (g_str_has_prefix(p, "&apos;")) {
res += "\'";
p += 5;
} else
res += *p;
continue;
}
std::string res;
for (; *p; ++p) {
if (*p != '<') {
if (g_str_has_prefix(p, "&gt;")) {
res += ">";
p += 3;
} else if (g_str_has_prefix(p, "&lt;")) {
res += "<";
p += 3;
} else if (g_str_has_prefix(p, "&amp;")) {
res += "&";
p += 4;
} else if (g_str_has_prefix(p, "&quot;")) {
res += "\"";
p += 5;
} else if (g_str_has_prefix(p, "&apos;")) {
res += "\'";
p += 5;
} else
res += *p;
continue;
}
const char *next = strchr(p, '>');
if (!next)
continue;
const char *next = strchr(p, '>');
if (!next)
continue;
const std::string name(p+1, next-p-1);
const std::string name(p + 1, next - p - 1);
if (name == "abr")
res += colorize_output ? ABR_VISFMT : "";
else if (name=="/abr")
res += colorize_output ? ESC_END : "";
else if (name == "k") {
const char *begin = next;
if ((next = strstr(begin, "</k>")) != nullptr)
next += sizeof("</k>") - 1 - 1;
else
next = begin;
if (name == "abr")
res += colorize_output ? ABR_VISFMT : "";
else if (name == "/abr")
res += colorize_output ? ESC_END : "";
else if (name == "k") {
const char *begin = next;
if ((next = strstr(begin, "</k>")) != nullptr)
next += sizeof("</k>") - 1 - 1;
else
next = begin;
} else if (name == "kref") {
res += colorize_output ? KREF_VISFMT : "";
} else if (name == "/kref") {
res += colorize_output ? ESC_END : "";
} else if (name == "b")
res += colorize_output ? ESC_BOLD : "";
else if (name=="/b")
res += colorize_output ? ESC_END : "";
else if (name == "i")
res += colorize_output ? ESC_ITALIC : "";
else if (name == "/i")
res += colorize_output ? ESC_END : "";
else if (name == "tr") {
} else if (name == "b")
res += colorize_output ? ESC_BOLD : "";
else if (name == "/b")
res += colorize_output ? ESC_END : "";
else if (name == "i")
res += colorize_output ? ESC_ITALIC : "";
else if (name == "/i")
res += colorize_output ? ESC_END : "";
else if (name == "tr") {
if (colorize_output)
res += TRANSCRIPTION_VISFMT;
res += "[";
} else if (name == "/tr") {
res += "]";
res += "[";
} else if (name == "/tr") {
res += "]";
if (colorize_output)
res += ESC_END;
} else if (name == "ex")
res += colorize_output ? EXAMPLE_VISFMT : "";
else if (name == "/ex")
res += colorize_output ? ESC_END : "";
else if (!name.empty() && name[0] == 'c' && name != "co") {
std::string::size_type pos = name.find("code");
if (pos != std::string::npos) {
pos += sizeof("code=\"") - 1;
std::string::size_type end_pos = name.find("\"");
const std::string color(name, pos, end_pos - pos);
res += "";
} else {
res += "";
}
} else if (name == "/c")
res += "";
} else if (name == "ex")
res += colorize_output ? EXAMPLE_VISFMT : "";
else if (name == "/ex")
res += colorize_output ? ESC_END : "";
else if (!name.empty() && name[0] == 'c' && name != "co") {
std::string::size_type pos = name.find("code");
if (pos != std::string::npos) {
pos += sizeof("code=\"") - 1;
std::string::size_type end_pos = name.find("\"");
const std::string color(name, pos, end_pos - pos);
res += "";
} else {
res += "";
}
} else if (name == "/c")
res += "";
p = next;
}
return res;
p = next;
}
return res;
}
static std::string parse_data(const gchar *data, bool colorize_output)
{
if (!data)
return "";
if (!data)
return "";
std::string res;
guint32 data_size, sec_size = 0;
gchar *m_str;
const gchar *p = data;
data_size = get_uint32(p);
p += sizeof(guint32);
while (guint32(p - data)<data_size) {
switch (*p++) {
case 'm':
case 'l': //need more work...
sec_size = strlen(p);
if (sec_size) {
res+="\n";
m_str = g_strndup(p, sec_size);
res += m_str;
g_free(m_str);
}
sec_size++;
break;
case 'g':
case 'x':
sec_size = strlen(p);
if (sec_size) {
res+="\n";
m_str = g_strndup(p, sec_size);
res += xdxf2text(m_str, colorize_output);
g_free(m_str);
}
sec_size++;
break;
case 't':
sec_size = strlen(p);
if(sec_size){
res += "\n";
std::string res;
guint32 data_size, sec_size = 0;
gchar *m_str;
const gchar *p = data;
data_size = get_uint32(p);
p += sizeof(guint32);
while (guint32(p - data) < data_size) {
switch (*p++) {
case 'h': // HTML data
case 'w': // WikiMedia markup data
case 'm': // plain text, utf-8
case 'l': // not utf-8, some other locale encoding, discouraged, need more work...
sec_size = strlen(p);
if (sec_size) {
res += "\n";
m_str = g_strndup(p, sec_size);
res += m_str;
g_free(m_str);
}
sec_size++;
break;
case 'g': // pango markup data
case 'x': // xdxf
sec_size = strlen(p);
if (sec_size) {
res += "\n";
m_str = g_strndup(p, sec_size);
res += xdxf2text(m_str, colorize_output);
g_free(m_str);
}
sec_size++;
break;
case 't': // english phonetic string
sec_size = strlen(p);
if (sec_size) {
res += "\n";
if (colorize_output)
res += TRANSCRIPTION_VISFMT;
res += "[" + std::string(p, sec_size) + "]";
res += "[" + std::string(p, sec_size) + "]";
if (colorize_output)
res += ESC_END;
}
sec_size++;
break;
case 'k':
case 'y':
sec_size = strlen(p);
}
sec_size++;
break;
case 'k': // KingSoft PowerWord data
case 'y': // chinese YinBiao or japanese kana, utf-8
sec_size = strlen(p);
if (sec_size)
res += std::string(p, sec_size);
sec_size++;
break;
case 'W':
case 'P':
sec_size = get_uint32(p);
sec_size += sizeof(guint32);
break;
}
p += sec_size;
}
sec_size++;
break;
case 'W': // wav file
case 'P': // picture data
sec_size = get_uint32(p);
sec_size += sizeof(guint32);
break;
}
p += sec_size;
}
return res;
return res;
}
void Library::SimpleLookup(const std::string &str, TSearchResultList& res_list)
void Library::SimpleLookup(const std::string &str, TSearchResultList &res_list)
{
glong ind;
res_list.reserve(ndicts());
for (gint idict = 0; idict < ndicts(); ++idict)
if (SimpleLookupWord(str.c_str(), ind, idict))
res_list.push_back(
TSearchResult(dict_name(idict),
glong ind;
res_list.reserve(ndicts());
for (gint idict = 0; idict < ndicts(); ++idict)
if (SimpleLookupWord(str.c_str(), ind, idict))
res_list.push_back(
TSearchResult(dict_name(idict),
poGetWord(ind, idict),
parse_data(poGetWordData(ind, idict), colorize_output_)));
}
void Library::LookupWithFuzzy(const std::string &str, TSearchResultList& res_list)
void Library::LookupWithFuzzy(const std::string &str, TSearchResultList &res_list)
{
static const int MAXFUZZY=10;
static const int MAXFUZZY = 10;
gchar *fuzzy_res[MAXFUZZY];
if (!Libs::LookupWithFuzzy(str.c_str(), fuzzy_res, MAXFUZZY))
return;
gchar *fuzzy_res[MAXFUZZY];
if (!Libs::LookupWithFuzzy(str.c_str(), fuzzy_res, MAXFUZZY))
return;
for (gchar **p = fuzzy_res, **end = (fuzzy_res + MAXFUZZY); p != end && *p; ++p) {
SimpleLookup(*p, res_list);
g_free(*p);
}
for (gchar **p = fuzzy_res, **end = (fuzzy_res + MAXFUZZY); p != end && *p; ++p) {
SimpleLookup(*p, res_list);
g_free(*p);
}
}
void Library::LookupWithRule(const std::string &str, TSearchResultList& res_list)
void Library::LookupWithRule(const std::string &str, TSearchResultList &res_list)
{
std::vector<gchar *> match_res((MAX_MATCH_ITEM_PER_LIB) * ndicts());
std::vector<gchar *> match_res((MAX_MATCH_ITEM_PER_LIB)*ndicts());
const gint nfound = Libs::LookupWithRule(str.c_str(), &match_res[0]);
if (nfound == 0)
return;
const gint nfound = Libs::LookupWithRule(str.c_str(), &match_res[0]);
if (nfound == 0)
return;
for (gint i = 0; i < nfound; ++i) {
SimpleLookup(match_res[i], res_list);
g_free(match_res[i]);
}
for (gint i = 0; i < nfound; ++i) {
SimpleLookup(match_res[i], res_list);
g_free(match_res[i]);
}
}
void Library::LookupData(const std::string &str, TSearchResultList& res_list)
void Library::LookupData(const std::string &str, TSearchResultList &res_list)
{
std::vector<std::vector<gchar *> > drl(ndicts());
if (!Libs::LookupData(str.c_str(), &drl[0]))
return;
for (int idict = 0; idict < ndicts(); ++idict)
for (gchar *res : drl[idict]) {
SimpleLookup(res, res_list);
g_free(res);
}
std::vector<std::vector<gchar *>> drl(ndicts());
if (!Libs::LookupData(str.c_str(), &drl[0]))
return;
for (int idict = 0; idict < ndicts(); ++idict)
for (gchar *res : drl[idict]) {
SimpleLookup(res, res_list);
g_free(res);
}
}
void Library::print_search_result(FILE *out, const TSearchResult & res)
void Library::print_search_result(FILE *out, const TSearchResult &res, bool &first_result)
{
std::string loc_bookname, loc_def, loc_exp;
std::string loc_bookname, loc_def, loc_exp;
if (!utf8_output_){
loc_bookname = utf8_to_locale_ign_err(res.bookname);
loc_def = utf8_to_locale_ign_err(res.def);
loc_exp = utf8_to_locale_ign_err(res.exp);
}
if (!utf8_output_) {
loc_bookname = utf8_to_locale_ign_err(res.bookname);
loc_def = utf8_to_locale_ign_err(res.def);
loc_exp = utf8_to_locale_ign_err(res.exp);
}
if (json_) {
if (!first_result) {
fputs(",", out);
} else {
first_result = false;
}
fprintf(out, "{\"dict\": \"%s\",\"word\":\"%s\",\"definition\":\"%s\"}",
json_escape_string(res.bookname).c_str(),
json_escape_string(res.def).c_str(),
json_escape_string(res.exp).c_str());
fprintf(out,
"-->%s%s%s\n"
"-->%s%s%s\n"
"%s\n\n",
colorize_output_ ? NAME_OF_DICT_VISFMT : "",
utf8_output_ ? res.bookname.c_str() : loc_bookname.c_str(),
colorize_output_ ? ESC_END : "",
colorize_output_ ? SEARCH_TERM_VISFMT : "",
utf8_output_ ? res.def.c_str() : loc_def.c_str(),
colorize_output_ ? ESC_END : "",
utf8_output_ ? res.exp.c_str() : loc_exp.c_str());
} else {
fprintf(out,
"-->%s%s%s\n"
"-->%s%s%s\n"
"%s\n\n",
colorize_output_ ? NAME_OF_DICT_VISFMT : "",
utf8_output_ ? res.bookname.c_str() : loc_bookname.c_str(),
colorize_output_ ? ESC_END : "",
colorize_output_ ? SEARCH_TERM_VISFMT : "",
utf8_output_ ? res.def.c_str() : loc_def.c_str(),
colorize_output_ ? ESC_END : "",
utf8_output_ ? res.exp.c_str() : loc_exp.c_str());
}
}
namespace {
class sdcv_pager {
public:
sdcv_pager(bool ignore_env = false) {
namespace
{
class sdcv_pager final
{
public:
explicit sdcv_pager(bool ignore_env = false)
{
output = stdout;
if (ignore_env) {
return;
}
const gchar *pager = g_getenv("SDCV_PAGER");
if (pager && (output = popen(pager, "w")) == nullptr) {
perror(_("popen failed"));
output = stdout;
if (ignore_env)
return;
const gchar *pager = g_getenv("SDCV_PAGER");
if (pager && (output = popen(pager, "w")) == nullptr) {
perror(_("popen failed"));
output = stdout;
}
}
sdcv_pager(const sdcv_pager&) = delete;
sdcv_pager& operator=(const sdcv_pager&) = delete;
~sdcv_pager() {
if (output != stdout)
fclose(output);
}
sdcv_pager(const sdcv_pager &) = delete;
sdcv_pager &operator=(const sdcv_pager &) = delete;
~sdcv_pager()
{
if (output != stdout) {
pclose(output);
}
FILE *get_stream() { return output; }
private:
FILE *output;
};
}
FILE *get_stream() { return output; }
private:
FILE *output;
};
}
bool Library::process_phrase(const char *loc_str, IReadLine &io, bool force)
{
if (nullptr == loc_str)
return true;
if (nullptr == loc_str)
return true;
std::string query;
std::string query;
analyze_query(loc_str, query);
if (!query.empty())
io.add_to_history(query.c_str());
analyze_query(loc_str, query);
if (!query.empty())
io.add_to_history(query.c_str());
gsize bytes_read;
gsize bytes_written;
gsize bytes_read;
gsize bytes_written;
glib::Error err;
glib::CharStr str;
if (!utf8_input_)
str.reset(g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, get_addr(err)));
else
str.reset(g_strdup(loc_str));
if (!utf8_input_)
str.reset(g_locale_to_utf8(loc_str, -1, &bytes_read, &bytes_written, get_addr(err)));
else
str.reset(g_strdup(loc_str));
if (nullptr == get_impl(str)) {
fprintf(stderr, _("Can not convert %s to utf8.\n"), loc_str);
fprintf(stderr, "%s\n", err->message);
return false;
}
if (nullptr == get_impl(str)) {
fprintf(stderr, _("Can not convert %s to utf8.\n"), loc_str);
fprintf(stderr, "%s\n", err->message);
return false;
}
if (str[0] == '\0')
return true;
if (str[0] == '\0')
return true;
TSearchResultList res_list;
TSearchResultList res_list;
switch (analyze_query(get_impl(str), query)) {
case qtFUZZY:
LookupWithFuzzy(query, res_list);
break;
case qtREGEXP:
LookupWithRule(query, res_list);
break;
case qtSIMPLE:
SimpleLookup(get_impl(str), res_list);
if (res_list.empty())
LookupWithFuzzy(get_impl(str), res_list);
break;
case qtDATA:
LookupData(query, res_list);
break;
default:
/*nothing*/;
}
switch (analyze_query(get_impl(str), query)) {
case qtFUZZY:
LookupWithFuzzy(query, res_list);
break;
case qtREGEXP:
LookupWithRule(query, res_list);
break;
case qtSIMPLE:
SimpleLookup(get_impl(str), res_list);
if (res_list.empty() && fuzzy_)
LookupWithFuzzy(get_impl(str), res_list);
break;
case qtDATA:
LookupData(query, res_list);
break;
default:
/*nothing*/;
}
if (!res_list.empty()) {
/* try to be more clever, if there are
bool first_result = true;
if (json_) {
fputc('[', stdout);
}
if (!res_list.empty()) {
/* try to be more clever, if there are
one or zero results per dictionary show all
*/
bool show_all_results = true;
typedef std::map< std::string, int, std::less<std::string> > DictResMap;
if (!force) {
DictResMap res_per_dict;
for (const TSearchResult& search_res : res_list) {
auto r = res_per_dict.equal_range(search_res.bookname);
DictResMap tmp(r.first, r.second);
if (tmp.empty()) //there are no yet such bookname in map
res_per_dict.insert(DictResMap::value_type(search_res.bookname, 1));
else {
++((tmp.begin())->second);
if (tmp.begin()->second > 1) {
show_all_results = false;
break;
}
}
}
}//if (!force)
bool show_all_results = true;
typedef std::map<std::string, int, std::less<std::string>> DictResMap;
if (!force) {
DictResMap res_per_dict;
for (const TSearchResult &search_res : res_list) {
auto r = res_per_dict.equal_range(search_res.bookname);
DictResMap tmp(r.first, r.second);
if (tmp.empty()) //there are no yet such bookname in map
res_per_dict.insert(DictResMap::value_type(search_res.bookname, 1));
else {
++((tmp.begin())->second);
if (tmp.begin()->second > 1) {
show_all_results = false;
break;
}
}
}
} //if (!force)
if (!show_all_results && !force) {
printf(_("Found %zu items, similar to %s.\n"), res_list.size(),
utf8_output_ ? get_impl(str) : utf8_to_locale_ign_err(get_impl(str)).c_str());
for (size_t i = 0; i < res_list.size(); ++i) {
if (!show_all_results && !force) {
if (!json_) {
printf(_("Found %zu items, similar to %s.\n"), res_list.size(),
utf8_output_ ? get_impl(str) : utf8_to_locale_ign_err(get_impl(str)).c_str());
}
for (size_t i = 0; i < res_list.size(); ++i) {
const std::string loc_bookname = utf8_to_locale_ign_err(res_list[i].bookname);
const std::string loc_def = utf8_to_locale_ign_err(res_list[i].def);
printf("%zu)%s%s%s-->%s%s%s\n", i,
printf("%zu)%s%s%s-->%s%s%s\n", i,
colorize_output_ ? NAME_OF_DICT_VISFMT : "",
utf8_output_ ? res_list[i].bookname.c_str() : loc_bookname.c_str(),
utf8_output_ ? res_list[i].bookname.c_str() : loc_bookname.c_str(),
colorize_output_ ? ESC_END : "",
colorize_output_ ? SEARCH_TERM_VISFMT : "",
utf8_output_ ? res_list[i].def.c_str() : loc_def.c_str(),
utf8_output_ ? res_list[i].def.c_str() : loc_def.c_str(),
colorize_output_ ? ESC_END : "");
}
int choise;
std::unique_ptr<IReadLine> choice_readline(create_readline_object());
for (;;) {
}
int choise;
std::unique_ptr<IReadLine> choice_readline(create_readline_object());
for (;;) {
std::string str_choise;
choice_readline->read(_("Your choice[-1 to abort]: "), str_choise);
sscanf(str_choise.c_str(), "%d", &choise);
if (choise >= 0 && choise < int(res_list.size())) {
sdcv_pager pager;
choice_readline->read(_("Your choice[-1 to abort]: "), str_choise);
sscanf(str_choise.c_str(), "%d", &choise);
if (choise >= 0 && choise < int(res_list.size())) {
sdcv_pager pager;
io.add_to_history(res_list[choise].def.c_str());
print_search_result(pager.get_stream(), res_list[choise]);
break;
} else if (choise == -1){
break;
} else
printf(_("Invalid choice.\nIt must be from 0 to %zu or -1.\n"),
res_list.size()-1);
}
} else {
sdcv_pager pager(force);
fprintf(pager.get_stream(), _("Found %zu items, similar to %s.\n"),
res_list.size(), utf8_output_ ? get_impl(str) : utf8_to_locale_ign_err(get_impl(str)).c_str());
for (const TSearchResult& search_res : res_list)
print_search_result(pager.get_stream(), search_res);
}
print_search_result(pager.get_stream(), res_list[choise], first_result);
break;
} else if (choise == -1) {
break;
} else
printf(_("Invalid choice.\nIt must be from 0 to %zu or -1.\n"),
res_list.size() - 1);
}
} else {
sdcv_pager pager(force || json_);
if (!json_) {
fprintf(pager.get_stream(), _("Found %zu items, similar to %s.\n"),
res_list.size(), utf8_output_ ? get_impl(str) : utf8_to_locale_ign_err(get_impl(str)).c_str());
}
for (const TSearchResult &search_res : res_list) {
print_search_result(pager.get_stream(), search_res, first_result);
}
}
} else {
std::string loc_str;
if (!utf8_output_)
loc_str = utf8_to_locale_ign_err(get_impl(str));
} else {
std::string loc_str;
if (!utf8_output_)
loc_str = utf8_to_locale_ign_err(get_impl(str));
if (!json_)
printf(_("Nothing similar to %s, sorry :(\n"), utf8_output_ ? get_impl(str) : loc_str.c_str());
}
printf(_("Nothing similar to %s, sorry :(\n"), utf8_output_ ? get_impl(str) : loc_str.c_str());
}
return true;
if (json_) {
fputs("]\n", stdout);
}
return true;
}

View File

@@ -3,41 +3,52 @@
#include <string>
#include <vector>
#include "stardict_lib.hpp"
#include "readline.hpp"
#include "stardict_lib.hpp"
//this structure is wrapper and it need for unification
//results of search whith return Dicts class
struct TSearchResult {
std::string bookname;
std::string def;
std::string exp;
std::string bookname;
std::string def;
std::string exp;
TSearchResult(const std::string& bookname_, const std::string& def_, const std::string& exp_)
: bookname(bookname_), def(def_), exp(exp_)
{
}
TSearchResult(const std::string &bookname_, const std::string &def_, const std::string &exp_)
: bookname(bookname_)
, def(def_)
, exp(exp_)
{
}
};
typedef std::vector<TSearchResult> TSearchResultList;
//this class is wrapper around Dicts class for easy use
//of it
class Library : public Libs {
class Library : public Libs
{
public:
Library(bool uinput, bool uoutput, bool colorize_output):
utf8_input_(uinput), utf8_output_(uoutput), colorize_output_(colorize_output) {}
Library(bool uinput, bool uoutput, bool colorize_output, bool use_json, bool no_fuzzy)
: utf8_input_(uinput)
, utf8_output_(uoutput)
, colorize_output_(colorize_output)
, json_(use_json)
{
setVerbose(!use_json);
setFuzzy(!no_fuzzy);
}
bool process_phrase(const char *loc_str, IReadLine &io, bool force = false);
bool process_phrase(const char *loc_str, IReadLine &io, bool force = false);
private:
bool utf8_input_;
bool utf8_input_;
bool utf8_output_;
bool colorize_output_;
bool json_;
void SimpleLookup(const std::string &str, TSearchResultList& res_list);
void LookupWithFuzzy(const std::string &str, TSearchResultList& res_list);
void LookupWithRule(const std::string &str, TSearchResultList& res_lsit);
void LookupData(const std::string &str, TSearchResultList& res_list);
void print_search_result(FILE *out, const TSearchResult & res);
void SimpleLookup(const std::string &str, TSearchResultList &res_list);
void LookupWithFuzzy(const std::string &str, TSearchResultList &res_list);
void LookupWithRule(const std::string &str, TSearchResultList &res_lsit);
void LookupData(const std::string &str, TSearchResultList &res_list);
void print_search_result(FILE *out, const TSearchResult &res, bool &first_result);
};

View File

@@ -1,27 +1,29 @@
#pragma once
#ifdef HAVE_CONFIG_H
# include "config.h"
#include "config.h"
#endif
#ifdef HAVE_MMAP
# include <sys/types.h>
# include <fcntl.h>
# include <sys/mman.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#endif
#ifdef _WIN32
# include <windows.h>
#include <windows.h>
#endif
#include <glib.h>
class MapFile {
class MapFile
{
public:
MapFile() {}
~MapFile();
MapFile(const MapFile&) = delete;
MapFile& operator=(const MapFile&) = delete;
MapFile(const MapFile &) = delete;
MapFile &operator=(const MapFile &) = delete;
bool open(const char *file_name, unsigned long file_size);
gchar *begin() { return data; }
private:
char *data = nullptr;
unsigned long size = 0ul;
@@ -35,51 +37,50 @@ private:
inline bool MapFile::open(const char *file_name, unsigned long file_size)
{
size=file_size;
size = file_size;
#ifdef HAVE_MMAP
if ((mmap_fd = ::open(file_name, O_RDONLY)) < 0) {
//g_print("Open file %s failed!\n",fullfilename);
return false;
}
data = (gchar *)mmap( nullptr, file_size, PROT_READ, MAP_SHARED, mmap_fd, 0);
if ((void *)data == (void *)(-1)) {
//g_print("mmap file %s failed!\n",idxfilename);
data=nullptr;
return false;
}
#elif defined( _WIN32)
hFile = CreateFile(file_name, GENERIC_READ, 0, nullptr, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, 0);
hFileMap = CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0,
file_size, nullptr);
data = (gchar *)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, file_size);
if ((mmap_fd = ::open(file_name, O_RDONLY)) < 0) {
//g_print("Open file %s failed!\n",fullfilename);
return false;
}
data = (gchar *)mmap(nullptr, file_size, PROT_READ, MAP_SHARED, mmap_fd, 0);
if ((void *)data == (void *)(-1)) {
//g_print("mmap file %s failed!\n",idxfilename);
data = nullptr;
return false;
}
#elif defined(_WIN32)
hFile = CreateFile(file_name, GENERIC_READ, 0, nullptr, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, 0);
hFileMap = CreateFileMapping(hFile, nullptr, PAGE_READONLY, 0,
file_size, nullptr);
data = (gchar *)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, file_size);
#else
gsize read_len;
if (!g_file_get_contents(file_name, &data, &read_len, nullptr))
return false;
gsize read_len;
if (!g_file_get_contents(file_name, &data, &read_len, nullptr))
return false;
if (read_len != file_size)
return false;
if (read_len != file_size)
return false;
#endif
return true;
return true;
}
inline MapFile::~MapFile()
{
if (!data)
return;
if (!data)
return;
#ifdef HAVE_MMAP
munmap(data, size);
close(mmap_fd);
munmap(data, size);
close(mmap_fd);
#else
# ifdef _WIN32
UnmapViewOfFile(data);
CloseHandle(hFileMap);
CloseHandle(hFile);
# else
g_free(data);
# endif
#endif
#ifdef _WIN32
UnmapViewOfFile(data);
CloseHandle(hFileMap);
CloseHandle(hFile);
#else
g_free(data);
#endif
#endif
}

View File

@@ -1,4 +1,4 @@
/*
/*
* This file part of sdcv - console version of Stardict program
* http://sdcv.sourceforge.net
* Copyright (C) 2005 Evgeniy <dushistov@mail.ru>
@@ -15,18 +15,18 @@
*
* 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.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#include "config.h"
#endif
#include <cstdio>
#include <cstdlib>
#ifdef WITH_READLINE
# include <readline/readline.h>
# include <readline/history.h>
#include <readline/history.h>
#include <readline/readline.h>
#endif
#include <glib.h>
@@ -34,72 +34,82 @@
#include "readline.hpp"
bool stdio_getline(FILE *in, std::string &str)
{
assert(in != nullptr);
str.clear();
int ch;
while ((ch = fgetc(in)) != EOF && ch != '\n')
str += ch;
return EOF != ch;
}
#ifndef WITH_READLINE
namespace {
static bool stdio_getline(FILE *in, std::string & str)
namespace
{
class dummy_readline : public IReadLine
{
public:
bool read(const std::string &banner, std::string &line) override
{
str.clear();
int ch;
while ((ch=fgetc(in)) != EOF && ch != '\n')
str += ch;
return EOF != ch;
printf("%s", banner.c_str());
return stdio_getline(stdin, line);
}
class dummy_readline : public IReadLine {
public:
bool read(const string& banner, string& line) override {
printf("%s", banner.c_str());
return stdio_getline(stdin, line);
}
};
};
}
#else
namespace {
class real_readline : public IReadLine {
namespace
{
class real_readline : public IReadLine
{
public:
real_readline() {
rl_readline_name = "sdcv";
using_history();
const std::string histname = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".sdcv_history";
read_history(histname.c_str());
}
public:
real_readline()
{
rl_readline_name = "sdcv";
using_history();
const std::string histname = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".sdcv_history";
read_history(histname.c_str());
}
~real_readline() {
const std::string histname = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".sdcv_history";
write_history(histname.c_str());
const gchar *hist_size_str=g_getenv("SDCV_HISTSIZE");
int hist_size;
if (!hist_size_str || sscanf(hist_size_str, "%d", &hist_size)<1)
hist_size = 2000;
history_truncate_file(histname.c_str(), hist_size);
}
~real_readline()
{
const std::string histname = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".sdcv_history";
write_history(histname.c_str());
const gchar *hist_size_str = g_getenv("SDCV_HISTSIZE");
int hist_size;
if (!hist_size_str || sscanf(hist_size_str, "%d", &hist_size) < 1)
hist_size = 2000;
history_truncate_file(histname.c_str(), hist_size);
}
bool read(const std::string &banner, std::string& line) override {
char *phrase = nullptr;
phrase = readline(banner.c_str());
if (phrase) {
line = phrase;
free(phrase);
return true;
}
return false;
bool read(const std::string &banner, std::string &line) override
{
char *phrase = nullptr;
phrase = readline(banner.c_str());
if (phrase) {
line = phrase;
free(phrase);
return true;
}
return false;
}
void add_to_history(const std::string& phrase) override {
add_history(phrase.c_str());
}
};
void add_to_history(const std::string &phrase) override
{
add_history(phrase.c_str());
}
};
}
#endif//WITH_READLINE
#endif //WITH_READLINE
IReadLine *create_readline_object()
{
#ifdef WITH_READLINE
return new real_readline;
return new real_readline;
#else
return new dummy_readline;
return new dummy_readline;
#endif
}

View File

@@ -2,13 +2,14 @@
#include <string>
class IReadLine {
class IReadLine
{
public:
virtual ~IReadLine() {}
virtual bool read(const std::string &banner, std::string& line) = 0;
virtual void add_to_history(const std::string&) {}
virtual ~IReadLine() {}
virtual bool read(const std::string &banner, std::string &line) = 0;
virtual void add_to_history(const std::string &) {}
};
extern std::string sdcv_readline;
extern IReadLine *create_readline_object();
extern bool stdio_getline(FILE *in, std::string &str);

View File

@@ -1,4 +1,4 @@
/*
/*
* This file part of sdcv - console version of Stardict program
* http://sdcv.sourceforge.net
* Copyright (C) 2003-2006 Evgeniy <dushistov@mail.ru>
@@ -15,18 +15,20 @@
*
* 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.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <algorithm>
#include <cerrno>
#include <clocale>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -54,9 +56,11 @@ static void free_str_array(gchar **arr)
}
namespace glib
{
typedef ResourceWrapper<gchar *, gchar *, free_str_array> StrArr;
using StrArr = ResourceWrapper<gchar *, gchar *, free_str_array>;
}
static void list_dicts(const std::list<std::string> &dicts_dir_list, bool use_json);
int main(int argc, char *argv[]) try {
setlocale(LC_ALL, "");
#if ENABLE_NLS
@@ -71,9 +75,12 @@ int main(int argc, char *argv[]) try {
gboolean show_list_dicts = FALSE;
glib::StrArr use_dict_list;
gboolean non_interactive = FALSE;
gboolean json_output = FALSE;
gboolean no_fuzzy = FALSE;
gboolean utf8_output = FALSE;
gboolean utf8_input = FALSE;
glib::CharStr opt_data_dir;
gboolean only_data_dir = FALSE;
gboolean colorize = FALSE;
const GOptionEntry entries[] = {
@@ -86,6 +93,10 @@ int main(int argc, char *argv[]) try {
_("bookname") },
{ "non-interactive", 'n', 0, G_OPTION_ARG_NONE, &non_interactive,
_("for use in scripts"), nullptr },
{ "json-output", 'j', 0, G_OPTION_ARG_NONE, &json_output,
_("print the result formatted as JSON"), nullptr },
{ "exact-search", 'e', 0, G_OPTION_ARG_NONE, &no_fuzzy,
_("do not fuzzy-search for similar words, only return exact matches"), nullptr },
{ "utf8-output", '0', 0, G_OPTION_ARG_NONE, &utf8_output,
_("output must be in utf8"), nullptr },
{ "utf8-input", '1', 0, G_OPTION_ARG_NONE, &utf8_input,
@@ -93,9 +104,11 @@ int main(int argc, char *argv[]) try {
{ "data-dir", '2', 0, G_OPTION_ARG_STRING, get_addr(opt_data_dir),
_("use this directory as path to stardict data directory"),
_("path/to/dir") },
{ "only-data-dir", 'x', 0, G_OPTION_ARG_NONE, &only_data_dir,
_("only use the dictionaries in data-dir, do not search in user and system directories"), nullptr },
{ "color", 'c', 0, G_OPTION_ARG_NONE, &colorize,
_("colorize the output"), nullptr },
{ nullptr },
{},
};
glib::Error error;
@@ -118,10 +131,12 @@ int main(int argc, char *argv[]) try {
const gchar *stardict_data_dir = g_getenv("STARDICT_DATA_DIR");
std::string data_dir;
if (!opt_data_dir) {
if (stardict_data_dir)
data_dir = stardict_data_dir;
else
data_dir = "/usr/share/stardict/dic";
if (!only_data_dir) {
if (stardict_data_dir)
data_dir = stardict_data_dir;
else
data_dir = "/usr/share/stardict/dic";
}
} else {
data_dir = get_impl(opt_data_dir);
}
@@ -130,58 +145,72 @@ int main(int argc, char *argv[]) try {
if (!homedir)
homedir = g_get_home_dir();
const std::list<std::string> dicts_dir_list = {
std::string(homedir) + G_DIR_SEPARATOR + ".stardict" + G_DIR_SEPARATOR + "dic",
data_dir
};
std::list<std::string> dicts_dir_list;
if (!only_data_dir)
dicts_dir_list.push_back(std::string(homedir) + G_DIR_SEPARATOR + ".stardict" + G_DIR_SEPARATOR + "dic");
dicts_dir_list.push_back(data_dir);
if (show_list_dicts) {
printf(_("Dictionary's name Word count\n"));
std::list<std::string> order_list, disable_list;
for_each_file(dicts_dir_list, ".ifo", order_list,
disable_list, [](const std::string &filename, bool) -> void {
DictInfo dict_info;
if (dict_info.load_from_ifo_file(filename, false)) {
const std::string bookname = utf8_to_locale_ign_err(dict_info.bookname);
printf("%s %d\n", bookname.c_str(), dict_info.wordcount);
}
});
list_dicts(dicts_dir_list, json_output);
return EXIT_SUCCESS;
}
std::list<std::string> disable_list;
if (use_dict_list) {
std::list<std::string> empty_list;
std::map<std::string, std::string> bookname_to_ifo;
for_each_file(dicts_dir_list, ".ifo", std::list<std::string>(), std::list<std::string>(),
[&bookname_to_ifo](const std::string &fname, bool) {
DictInfo dict_info;
const bool load_ok = dict_info.load_from_ifo_file(fname, false);
if (!load_ok)
return;
bookname_to_ifo[dict_info.bookname] = dict_info.ifo_file_name;
});
for_each_file(dicts_dir_list, ".ifo", empty_list, empty_list,
[&disable_list, &use_dict_list](const std::string &filename, bool) -> void {
DictInfo dict_info;
const bool load_ok = dict_info.load_from_ifo_file(filename, false);
if (!load_ok)
return;
std::list<std::string> order_list;
if (use_dict_list != nullptr) {
for (auto &&x : bookname_to_ifo) {
gchar **p = get_impl(use_dict_list);
for (; *p != nullptr; ++p)
if (x.first.compare(*p) == 0) {
break;
}
if (*p == nullptr) {
disable_list.push_back(x.second);
}
}
for (gchar **p = get_impl(use_dict_list); *p != nullptr; ++p)
if (strcmp(*p, dict_info.bookname.c_str()) == 0)
return;
disable_list.push_back(dict_info.ifo_file_name);
});
// add bookname to list
gchar **p = get_impl(use_dict_list);
while (*p) {
order_list.push_back(bookname_to_ifo.at(*p));
++p;
}
} else {
const std::string odering_cfg_file = std::string(homedir) + G_DIR_SEPARATOR_S ".sdcv_ordering";
FILE *ordering_file = fopen(odering_cfg_file.c_str(), "r");
if (ordering_file != nullptr) {
std::string line;
while (stdio_getline(ordering_file, line)) {
order_list.push_back(bookname_to_ifo.at(line));
}
fclose(ordering_file);
}
}
const std::string conf_dir = std::string(g_get_home_dir()) + G_DIR_SEPARATOR + ".stardict";
if (g_mkdir(conf_dir.c_str(), S_IRWXU) == -1 && errno != EEXIST)
if (g_mkdir(conf_dir.c_str(), S_IRWXU) == -1 && errno != EEXIST) {
fprintf(stderr, _("g_mkdir failed: %s\n"), strerror(errno));
}
Library lib(utf8_input, utf8_output, colorize);
std::list<std::string> empty_list;
lib.load(dicts_dir_list, empty_list, disable_list);
Library lib(utf8_input, utf8_output, colorize, json_output, no_fuzzy);
lib.load(dicts_dir_list, order_list, disable_list);
std::unique_ptr<IReadLine> io(create_readline_object());
if (optind < argc) {
for (int i = optind; i < argc; ++i)
if (!lib.process_phrase(argv[i], *io, non_interactive))
if (!lib.process_phrase(argv[i], *io, non_interactive)) {
return EXIT_FAILURE;
}
} else if (!non_interactive) {
std::string phrase;
@@ -200,3 +229,32 @@ int main(int argc, char *argv[]) try {
fprintf(stderr, "Internal error: %s\n", ex.what());
exit(EXIT_FAILURE);
}
static void list_dicts(const std::list<std::string> &dicts_dir_list, bool use_json)
{
bool first_entry = true;
if (!use_json)
printf(_("Dictionary's name Word count\n"));
else
fputc('[', stdout);
std::list<std::string> order_list, disable_list;
for_each_file(dicts_dir_list, ".ifo", order_list,
disable_list, [use_json, &first_entry](const std::string &filename, bool) -> void {
DictInfo dict_info;
if (dict_info.load_from_ifo_file(filename, false)) {
const std::string bookname = utf8_to_locale_ign_err(dict_info.bookname);
if (use_json) {
if (first_entry) {
first_entry = false;
} else {
fputc(',', stdout); // comma between entries
}
printf("{\"name\": \"%s\", \"wordcount\": \"%d\"}", json_escape_string(bookname).c_str(), dict_info.wordcount);
} else {
printf("%s %d\n", bookname.c_str(), dict_info.wordcount);
}
}
});
if (use_json)
fputs("]\n", stdout);
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,16 +2,17 @@
#include <cstdio>
#include <cstring>
#include <functional>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <functional>
#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
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
inline guint32 get_uint32(const gchar *addr)
{
@@ -25,159 +26,190 @@ inline void set_uint32(gchar *addr, guint32 val)
memcpy(addr, &val, sizeof(guint32));
}
struct cacheItem {
guint32 offset;
gchar *data;
//write code here to make it inline
cacheItem() { data = nullptr;}
~cacheItem() { g_free(data); }
guint32 offset;
gchar *data;
//write code here to make it inline
cacheItem() { data = nullptr; }
~cacheItem() { g_free(data); }
};
const int WORDDATA_CACHE_NUM = 10;
const int INVALID_INDEX=-100;
const int INVALID_INDEX = -100;
class DictBase {
class DictBase
{
public:
DictBase() {}
~DictBase() {
DictBase() {}
~DictBase()
{
if (dictfile)
fclose(dictfile);
}
DictBase(const DictBase&) = delete;
DictBase& operator=(const DictBase&) = delete;
gchar * GetWordData(guint32 idxitem_offset, guint32 idxitem_size);
bool containSearchData() const {
DictBase(const DictBase &) = delete;
DictBase &operator=(const DictBase &) = delete;
gchar *GetWordData(guint32 idxitem_offset, guint32 idxitem_size);
bool containSearchData() const
{
if (sametypesequence.empty())
return true;
return sametypesequence.find_first_of("mlgxty") != std::string::npos;
}
bool SearchData(std::vector<std::string> &SearchWords, guint32 idxitem_offset, guint32 idxitem_size, gchar *origin_data);
bool SearchData(std::vector<std::string> &SearchWords, guint32 idxitem_offset, guint32 idxitem_size, gchar *origin_data);
protected:
std::string sametypesequence;
FILE *dictfile = nullptr;
std::unique_ptr<DictData> dictdzfile;
std::string sametypesequence;
FILE *dictfile = nullptr;
std::unique_ptr<DictData> dictdzfile;
private:
cacheItem cache[WORDDATA_CACHE_NUM];
gint cache_cur = 0;
cacheItem cache[WORDDATA_CACHE_NUM];
gint cache_cur = 0;
};
//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;
std::string ifo_file_name;
guint32 wordcount;
guint32 syn_wordcount;
std::string bookname;
std::string author;
std::string email;
std::string website;
std::string date;
std::string description;
guint32 index_file_size;
guint32 syn_file_size;
std::string sametypesequence;
bool load_from_ifo_file(const std::string& ifofilename, bool istreedict);
bool load_from_ifo_file(const std::string &ifofilename, bool istreedict);
};
class IIndexFile {
class IIndexFile
{
public:
guint32 wordentry_offset;
guint32 wordentry_size;
guint32 wordentry_offset;
guint32 wordentry_size;
virtual ~IIndexFile() {}
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;
virtual ~IIndexFile() {}
virtual bool load(const std::string &url, gulong wc, gulong fsize, bool verbose) = 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 {
class SynFile
{
public:
Dict() {}
Dict(const Dict&) = delete;
Dict& operator=(const Dict&) = delete;
bool load(const std::string& ifofilename);
bool load(const std::string &url, gulong wc);
bool lookup(const char *str, glong &idx);
gulong narticles() const { return wordcount; }
const std::string& dict_name() const { return bookname; }
const std::string& ifofilename() const { return ifo_file_name; }
private:
std::map<std::string, gulong> synonyms;
};
const gchar *get_key(glong index) { return idx_file->get_key(index); }
gchar *get_data(glong index) {
class Dict : public DictBase
{
public:
Dict() {}
Dict(const Dict &) = delete;
Dict &operator=(const Dict &) = delete;
bool load(const std::string &ifofilename, bool verbose);
gulong narticles() const { return wordcount; }
const std::string &dict_name() const { return bookname; }
const std::string &ifofilename() const { 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) {
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 Lookup(const char *str, glong &idx);
bool LookupWithRule(GPatternSpec *pspec, glong *aIndex, int iBuffLen);
private:
std::string ifo_file_name;
gulong wordcount;
std::string bookname;
bool LookupWithRule(GPatternSpec *pspec, glong *aIndex, int iBuffLen);
std::unique_ptr<IIndexFile> idx_file;
bool load_ifofile(const std::string& ifofilename, gulong &idxfilesize);
};
class Libs {
public:
Libs(std::function<void(void)> f = std::function<void(void)>()) {
progress_func = f;
iMaxFuzzyDistance = MAX_FUZZY_DISTANCE; //need to read from cfg.
}
~Libs();
Libs(const Libs&) = delete;
Libs& operator=(const Libs&) = delete;
void load_dict(const std::string& url);
void load(const std::list<std::string>& dicts_dirs,
const std::list<std::string>& order_list,
const std::list<std::string>& disable_list);
void reload(const std::list<std::string>& dicts_dirs,
const std::list<std::string>& order_list,
const std::list<std::string>& disable_list);
glong narticles(int idict) const { return oLib[idict]->narticles(); }
const std::string& dict_name(int idict) const { return oLib[idict]->dict_name(); }
gint ndicts() const { 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 nullptr;
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 LookupWithRule(const gchar *sWord, gchar *reslist[]);
bool LookupData(const gchar *sWord, std::vector<gchar *> *reslist);
private:
std::vector<Dict *> oLib; // word Libs.
int iMaxFuzzyDistance;
std::function<void(void)> progress_func;
std::string ifo_file_name;
gulong wordcount;
gulong syn_wordcount;
std::string bookname;
std::unique_ptr<IIndexFile> idx_file;
std::unique_ptr<SynFile> syn_file;
bool load_ifofile(const std::string &ifofilename, gulong &idxfilesize);
};
class Libs
{
public:
Libs(std::function<void(void)> f = std::function<void(void)>())
{
progress_func = f;
iMaxFuzzyDistance = MAX_FUZZY_DISTANCE; //need to read from cfg.
}
void setVerbose(bool verbose) { verbose_ = verbose; }
void setFuzzy(bool fuzzy) { fuzzy_ = fuzzy; }
~Libs();
Libs(const Libs &) = delete;
Libs &operator=(const Libs &) = delete;
void load_dict(const std::string &url);
void load(const std::list<std::string> &dicts_dirs,
const std::list<std::string> &order_list,
const std::list<std::string> &disable_list);
glong narticles(int idict) const { return oLib[idict]->narticles(); }
const std::string &dict_name(int idict) const { return oLib[idict]->dict_name(); }
gint ndicts() const { 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 nullptr;
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 LookupWithRule(const gchar *sWord, gchar *reslist[]);
bool LookupData(const gchar *sWord, std::vector<gchar *> *reslist);
protected:
bool fuzzy_;
private:
std::vector<Dict *> oLib; // word Libs.
int iMaxFuzzyDistance;
std::function<void(void)> progress_func;
bool verbose_;
};
enum query_t {
qtSIMPLE, qtREGEXP, qtFUZZY, qtDATA
qtSIMPLE,
qtREGEXP,
qtFUZZY,
qtDATA
};
extern query_t analyze_query(const char *s, std::string& res);
extern query_t analyze_query(const char *s, std::string &res);

View File

@@ -15,78 +15,117 @@
*
* 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.
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#include "config.h"
#endif
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <glib.h>
#include <glib/gi18n.h>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include "utils.hpp"
std::string utf8_to_locale_ign_err(const std::string& utf8_str)
std::string utf8_to_locale_ign_err(const std::string &utf8_str)
{
std::string res;
std::string res;
const char *charset;
if (g_get_charset(&charset))
res = utf8_str;
else {
const char *charset;
if (g_get_charset(&charset))
res = utf8_str;
else {
gsize bytes_read, bytes_written;
glib::Error err;
glib::CharStr tmp(g_convert_with_fallback(utf8_str.c_str(), -1, charset, "UTF-8", nullptr,
&bytes_read, &bytes_written, get_addr(err)));
if (nullptr == get_impl(tmp)){
fprintf(stderr, _("Can not convert %s to current locale.\n"), utf8_str.c_str());
fprintf(stderr, "%s\n", err->message);
exit(EXIT_FAILURE);
}
res = get_impl(tmp);
}
if (nullptr == get_impl(tmp)) {
fprintf(stderr, _("Can not convert %s to current locale.\n"), utf8_str.c_str());
fprintf(stderr, "%s\n", err->message);
exit(EXIT_FAILURE);
}
res = get_impl(tmp);
}
return res;
return res;
}
static void __for_each_file(const std::string& dirname, const std::string& suff,
const std::list<std::string>& order_list, const std::list<std::string>& disable_list,
const std::function<void (const std::string&, bool)>& f)
static void __for_each_file(const std::string &dirname, const std::string &suff,
const std::list<std::string> &order_list, const std::list<std::string> &disable_list,
const std::function<void(const std::string &, bool)> &f)
{
GDir *dir = g_dir_open(dirname.c_str(), 0, nullptr);
GDir *dir = g_dir_open(dirname.c_str(), 0, nullptr);
if (dir) {
const gchar *filename;
const gchar *filename;
while ((filename = g_dir_read_name(dir))!=nullptr) {
const 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()) {
const bool disable = std::find(disable_list.begin(),
disable_list.end(),
fullfilename)!=disable_list.end();
while ((filename = g_dir_read_name(dir)) != nullptr) {
const 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()) {
const bool disable = std::find(disable_list.begin(),
disable_list.end(),
fullfilename)
!= disable_list.end();
f(fullfilename, disable);
}
}
g_dir_close(dir);
}
}
}
g_dir_close(dir);
}
}
void for_each_file(const std::list<std::string>& dirs_list, const std::string& suff,
const std::list<std::string>& order_list, const std::list<std::string>& disable_list,
const std::function<void (const std::string&, bool)>& f)
void for_each_file(const std::list<std::string> &dirs_list, const std::string &suff,
const std::list<std::string> &order_list, const std::list<std::string> &disable_list,
const std::function<void(const std::string &, bool)> &f)
{
for (const std::string & item : order_list) {
const bool disable = std::find(disable_list.begin(), disable_list.end(), item) != disable_list.end();
f(item, disable);
}
for (const std::string& item : dirs_list)
__for_each_file(item, suff, order_list, disable_list, f);
for (const std::string &item : order_list) {
const bool disable = std::find(disable_list.begin(), disable_list.end(), item) != disable_list.end();
f(item, disable);
}
for (const std::string &item : dirs_list)
__for_each_file(item, suff, order_list, disable_list, f);
}
// based on https://stackoverflow.com/questions/7724448/simple-json-string-escape-for-c/33799784#33799784
std::string json_escape_string(const std::string &s)
{
std::ostringstream o;
for (auto c = s.cbegin(); c != s.cend(); c++) {
switch (*c) {
case '"':
o << "\\\"";
break;
case '\\':
o << "\\\\";
break;
case '\b':
o << "\\b";
break;
case '\f':
o << "\\f";
break;
case '\n':
o << "\\n";
break;
case '\r':
o << "\\r";
break;
case '\t':
o << "\\t";
break;
default:
if ('\x00' <= *c && *c <= '\x1f') {
o << "\\u"
<< std::hex << std::setw(4) << std::setfill('0') << (int)*c;
} else {
o << *c;
}
}
}
return o.str();
}

View File

@@ -1,68 +1,78 @@
#pragma once
#include <glib.h>
#include <cassert>
#include <string>
#include <list>
#include <cstddef>
#include <functional>
#include <glib.h>
#include <list>
#include <string>
template <typename T, typename unref_res_t, void (*unref_res)(unref_res_t *)>
class ResourceWrapper {
class ResourceWrapper
{
public:
ResourceWrapper(T *p = nullptr) : p_(p) {}
~ResourceWrapper() { free_resource(); }
ResourceWrapper(const ResourceWrapper&) = delete;
ResourceWrapper& operator=(const ResourceWrapper&) = delete;
T *operator->() const { return p_; }
bool operator!() const { return p_ == nullptr; }
const T& operator[](size_t idx) const {
ResourceWrapper(T *p = nullptr)
: p_(p)
{
}
~ResourceWrapper() { free_resource(); }
ResourceWrapper(const ResourceWrapper &) = delete;
ResourceWrapper &operator=(const ResourceWrapper &) = delete;
T *operator->() const { return p_; }
bool operator!() const { return p_ == nullptr; }
const T &operator[](size_t idx) const
{
assert(p_ != nullptr);
return p_[idx];
}
void reset(T *newp) {
if (p_ != newp) {
free_resource();
p_ = newp;
}
}
void reset(T *newp)
{
if (p_ != newp) {
free_resource();
p_ = newp;
}
}
friend inline T *get_impl(const ResourceWrapper& rw) {
return rw.p_;
}
friend inline bool operator==(const ResourceWrapper &lhs, std::nullptr_t) noexcept
{
return !lhs.p_;
}
friend inline T **get_addr(ResourceWrapper& rw) {
return &rw.p_;
}
friend inline bool operator!=(const ResourceWrapper &lhs, std::nullptr_t) noexcept
{
return !!lhs.p_;
}
friend inline T *get_impl(const ResourceWrapper &rw)
{
return rw.p_;
}
friend inline T **get_addr(ResourceWrapper &rw)
{
return &rw.p_;
}
private:
T *p_;
T *p_;
void free_resource() { if (p_) unref_res(p_); }
// Helper for enabling 'if (sp)'
struct Tester {
Tester() {}
private:
void operator delete(void*);
};
public:
// enable 'if (sp)'
operator Tester*() const {
if (!*this)
return 0;
static Tester t;
return &t;
void free_resource()
{
if (p_)
unref_res(p_);
}
};
namespace glib {
typedef ResourceWrapper<gchar, void, g_free> CharStr;
typedef ResourceWrapper<GError, GError, g_error_free> Error;
namespace glib
{
typedef ResourceWrapper<gchar, void, g_free> CharStr;
typedef ResourceWrapper<GError, GError, g_error_free> Error;
}
extern std::string utf8_to_locale_ign_err(const std::string& utf8_str);
extern std::string utf8_to_locale_ign_err(const std::string &utf8_str);
extern void for_each_file(const std::list<std::string>& dirs_list, const std::string& suff,
const std::list<std::string>& order_list, const std::list<std::string>& disable_list,
const std::function<void (const std::string&, bool)>& f);
extern void for_each_file(const std::list<std::string> &dirs_list, const std::string &suff,
const std::list<std::string> &order_list, const std::list<std::string> &disable_list,
const std::function<void(const std::string &, bool)> &f);
extern std::string json_escape_string(const std::string &str);

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,7 @@
StarDict's dict ifo file
version=2.4.2
bookname=Test synonyms
wordcount=2
synwordcount=2
idxfilesize=32
sametypesequence=m

Binary file not shown.

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" ?>
<stardict xmlns:xi="http://www.w3.org/2003/XInclude">
<info>
<version>2.4.2</version>
<bookname>Test synonyms</bookname>
<author></author>
<email></email>
<website></website>
<description></description>
<date></date>
<dicttype></dicttype>
</info>
<article><key>test</key><synonym>foo</synonym><synonym>bar</synonym>
<definition type="m">
<![CDATA[result of test]]>
</definition>
</article>
<article><key>testawordy</key>
<definition type="m">
<![CDATA[word that ends in y to test with fuzzy search in -ied]]>
</definition>
</article>
</stardict>

24
tests/t_exact Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
set -e
SDCV="$1"
TEST_DIR="$2"
unset SDCV_PAGER
test_word() {
WORD=$1
EXPECTED=$2
TAG=$3
RES=$($SDCV -e -n --data-dir "$TEST_DIR" -u "Test synonyms" $WORD | grep "$TAG")
if [ "$EXPECTED" != "$RES" ]; then
echo "synonym for $WORD should be '$EXPECTED' but was '$RES'"
exit 1
fi
}
test_word testawordies "Nothing similar to testawordies, sorry :(" "Nothing similar"
test_word testawordy "word that ends in y to test with fuzzy search in -ied" "fuzzy"
exit 0

25
tests/t_json Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
set -e
SDCV="$1"
TEST_DIR="$2"
unset SDCV_PAGER
unset STARDICT_DATA_DIR
test_json() {
PARAMS="$1"
EXPECTED=$(echo "$2" | jq 'sort')
RESULT=$($SDCV $PARAMS | jq 'sort')
if [ "$EXPECTED" != "$RESULT"]; then
echo "expected $EXPECTED but got $RESULT"
exit 1
fi
}
test_json "-x -j -l -n --data-dir \"$TEST_DIR\"" "[{\"name\": \"Test synonyms\", \"wordcount\": \"1\"},{\"name\": \"Sample 1 test dictionary\", \"wordcount\": \"1\"},{\"name\": \"test_dict\", \"wordcount\": \"1\"}]"
test_json "-x -j -n --data-dir \"$TEST_DIR\" foo" "[{\"dict\": \"Test synonyms\",\"word\":\"test\",\"definition\":\"\nresult of test\"}]"
test_json "-x -j -n --data-dir \"$TEST_DIR\" foobarbaaz" "[]"
exit 0

19
tests/t_only_data_dir Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/sh
set -e
SDCV="$1"
TEST_DIR="$2"
unset SDCV_PAGER
unset STARDICT_DATA_DIR
DICTS=$($SDCV -x -n -l --data-dir "$TEST_DIR" | tail -n +2 | wc -l)
# the expected result:
ACTUAL_DICTS=$(find "$TEST_DIR" -name "*.ifo" | wc -l)
if [ $DICTS -ne $ACTUAL_DICTS ]; then
echo "number of dictionaries in $TEST_DIR should be $ACTUAL_DICTS but was $DICTS according to sdcv"
exit 1
fi
exit 0

22
tests/t_synonyms Executable file
View File

@@ -0,0 +1,22 @@
#!/bin/sh
set -e
SDCV="$1"
TEST_DIR="$2"
unset SDCV_PAGER
test_word() {
WORD=$1
RES=$($SDCV -n --data-dir "$TEST_DIR" -u "Test synonyms" $WORD | grep result)
if [ "result of test" != "$RES" ]; then
echo "synonym for $WORD should be 'result of test' but was '$RES'"
exit 1
fi
}
test_word foo
test_word bar
test_word test
exit 0