diff --git a/aegisub/frame_main.cpp b/aegisub/frame_main.cpp index 0fd79ae5a..fe1f7ee82 100644 --- a/aegisub/frame_main.cpp +++ b/aegisub/frame_main.cpp @@ -181,6 +181,8 @@ FrameMain::FrameMain (wxArrayString args) DialogVersionCheck *checker = new DialogVersionCheck (this,true); (void)checker; } + + //ShowFullScreen(true,wxFULLSCREEN_NOBORDER | wxFULLSCREEN_NOCAPTION); } diff --git a/aegisub/video_context.cpp b/aegisub/video_context.cpp index 6b32f89e1..39c443288 100644 --- a/aegisub/video_context.cpp +++ b/aegisub/video_context.cpp @@ -477,6 +477,13 @@ wxGLContext *VideoContext::GetGLContext(wxGLCanvas *canvas) { if (!glContext) glContext = new wxGLContext(canvas); #endif return glContext; + /* + if (!((VideoDisplay*)canvas)->freeSize) return glContext; + else { + static wxGLContext *test = NULL; + if (test = NULL) test = new wxGLContext(canvas,glContext); + return test; + }*/ } diff --git a/aegisub/video_display.cpp b/aegisub/video_display.cpp index 82cbb9698..0fb4b8caf 100644 --- a/aegisub/video_display.cpp +++ b/aegisub/video_display.cpp @@ -169,6 +169,7 @@ void VideoDisplay::ShowCursor(bool show) { void VideoDisplay::Render() { // Is shown? if (!IsShownOnScreen()) return; + if (!wxIsMainThread()) throw _T("Error: trying to render from non-primary thread"); // Get video context VideoContext *context = VideoContext::Get(); diff --git a/hunspell/ABOUT-NLS b/hunspell/ABOUT-NLS new file mode 100644 index 000000000..224f72c57 --- /dev/null +++ b/hunspell/ABOUT-NLS @@ -0,0 +1,405 @@ +Notes on the Free Translation Project +************************************* + + Free software is going international! The Free Translation Project +is a way to get maintainers of free software, translators, and users all +together, so that will gradually become able to speak many languages. +A few packages already provide translations for their messages. + + If you found this `ABOUT-NLS' file inside a distribution, you may +assume that the distributed package does use GNU `gettext' internally, +itself available at your nearest GNU archive site. But you do _not_ +need to install GNU `gettext' prior to configuring, installing or using +this package with messages translated. + + Installers will find here some useful hints. These notes also +explain how users should proceed for getting the programs to use the +available translations. They tell how people wanting to contribute and +work at translations should contact the appropriate team. + + When reporting bugs in the `intl/' directory or bugs which may be +related to internationalization, you should tell about the version of +`gettext' which is used. The information can be found in the +`intl/VERSION' file, in internationalized packages. + +Quick configuration advice +========================== + + If you want to exploit the full power of internationalization, you +should configure it using + + ./configure --with-included-gettext + +to force usage of internationalizing routines provided within this +package, despite the existence of internationalizing capabilities in the +operating system where this package is being installed. So far, only +the `gettext' implementation in the GNU C library version 2 provides as +many features (such as locale alias, message inheritance, automatic +charset conversion or plural form handling) as the implementation here. +It is also not possible to offer this additional functionality on top +of a `catgets' implementation. Future versions of GNU `gettext' will +very likely convey even more functionality. So it might be a good idea +to change to GNU `gettext' as soon as possible. + + So you need _not_ provide this option if you are using GNU libc 2 or +you have installed a recent copy of the GNU gettext package with the +included `libintl'. + +INSTALL Matters +=============== + + Some packages are "localizable" when properly installed; the +programs they contain can be made to speak your own native language. +Most such packages use GNU `gettext'. Other packages have their own +ways to internationalization, predating GNU `gettext'. + + By default, this package will be installed to allow translation of +messages. It will automatically detect whether the system already +provides the GNU `gettext' functions. If not, the GNU `gettext' own +library will be used. This library is wholly contained within this +package, usually in the `intl/' subdirectory, so prior installation of +the GNU `gettext' package is _not_ required. Installers may use +special options at configuration time for changing the default +behaviour. The commands: + + ./configure --with-included-gettext + ./configure --disable-nls + +will respectively bypass any pre-existing `gettext' to use the +internationalizing routines provided within this package, or else, +_totally_ disable translation of messages. + + When you already have GNU `gettext' installed on your system and run +configure without an option for your new package, `configure' will +probably detect the previously built and installed `libintl.a' file and +will decide to use this. This might be not what is desirable. You +should use the more recent version of the GNU `gettext' library. I.e. +if the file `intl/VERSION' shows that the library which comes with this +package is more recent, you should use + + ./configure --with-included-gettext + +to prevent auto-detection. + + The configuration process will not test for the `catgets' function +and therefore it will not be used. The reason is that even an +emulation of `gettext' on top of `catgets' could not provide all the +extensions of the GNU `gettext' library. + + Internationalized packages have usually many `po/LL.po' files, where +LL gives an ISO 639 two-letter code identifying the language. Unless +translations have been forbidden at `configure' time by using the +`--disable-nls' switch, all available translations are installed +together with the package. However, the environment variable `LINGUAS' +may be set, prior to configuration, to limit the installed set. +`LINGUAS' should then contain a space separated list of two-letter +codes, stating which languages are allowed. + +Using This Package +================== + + As a user, if your language has been installed for this package, you +only have to set the `LANG' environment variable to the appropriate +`LL_CC' combination. Here `LL' is an ISO 639 two-letter language code, +and `CC' is an ISO 3166 two-letter country code. For example, let's +suppose that you speak German and live in Germany. At the shell +prompt, merely execute `setenv LANG de_DE' (in `csh'), +`export LANG; LANG=de_DE' (in `sh') or `export LANG=de_DE' (in `bash'). +This can be done from your `.login' or `.profile' file, once and for +all. + + You might think that the country code specification is redundant. +But in fact, some languages have dialects in different countries. For +example, `de_AT' is used for Austria, and `pt_BR' for Brazil. The +country code serves to distinguish the dialects. + + The locale naming convention of `LL_CC', with `LL' denoting the +language and `CC' denoting the country, is the one use on systems based +on GNU libc. On other systems, some variations of this scheme are +used, such as `LL' or `LL_CC.ENCODING'. You can get the list of +locales supported by your system for your country by running the command +`locale -a | grep '^LL''. + + Not all programs have translations for all languages. By default, an +English message is shown in place of a nonexistent translation. If you +understand other languages, you can set up a priority list of languages. +This is done through a different environment variable, called +`LANGUAGE'. GNU `gettext' gives preference to `LANGUAGE' over `LANG' +for the purpose of message handling, but you still need to have `LANG' +set to the primary language; this is required by other parts of the +system libraries. For example, some Swedish users who would rather +read translations in German than English for when Swedish is not +available, set `LANGUAGE' to `sv:de' while leaving `LANG' to `sv_SE'. + + In the `LANGUAGE' environment variable, but not in the `LANG' +environment variable, `LL_CC' combinations can be abbreviated as `LL' +to denote the language's main dialect. For example, `de' is equivalent +to `de_DE' (German as spoken in Germany), and `pt' to `pt_PT' +(Portuguese as spoken in Portugal) in this context. + +Translating Teams +================= + + For the Free Translation Project to be a success, we need interested +people who like their own language and write it well, and who are also +able to synergize with other translators speaking the same language. +Each translation team has its own mailing list. The up-to-date list of +teams can be found at the Free Translation Project's homepage, +`http://www.iro.umontreal.ca/contrib/po/HTML/', in the "National teams" +area. + + If you'd like to volunteer to _work_ at translating messages, you +should become a member of the translating team for your own language. +The subscribing address is _not_ the same as the list itself, it has +`-request' appended. For example, speakers of Swedish can send a +message to `sv-request@li.org', having this message body: + + subscribe + + Keep in mind that team members are expected to participate +_actively_ in translations, or at solving translational difficulties, +rather than merely lurking around. If your team does not exist yet and +you want to start one, or if you are unsure about what to do or how to +get started, please write to `translation@iro.umontreal.ca' to reach the +coordinator for all translator teams. + + The English team is special. It works at improving and uniformizing +the terminology in use. Proven linguistic skill are praised more than +programming skill, here. + +Available Packages +================== + + Languages are not equally supported in all packages. The following +matrix shows the current state of internationalization, as of April +2002. The matrix shows, in regard of each package, for which languages +PO files have been submitted to translation coordination, with a +translation percentage of at least 50%. + + Ready PO files bg ca cs da de el en eo es et fi fr + +-------------------------------------+ + a2ps | [] [] [] [] | + bash | [] [] [] [] | + bfd | [] [] | + binutils | [] [] | + bison | [] [] [] [] | + clisp | [] [] [] [] | + cpio | [] [] [] [] | + diffutils | [] [] [] [] [] [] | + enscript | [] [] | + error | [] [] | + fetchmail | [] () [] [] [] () | + fileutils | [] [] [] [] [] | + findutils | [] [] [] [] [] | + flex | [] [] [] [] [] | + gas | [] [] | + gawk | [] [] [] | + gcal | [] [] | + gcc | [] [] | + gettext | [] [] [] [] [] | + gnupg | [] [] [] [] [] [] | + gprof | [] [] | + gpsdrive | () () () () () | + grep | [] [] [] [] [] [] [] | + gretl | | + hello | [] [] [] [] [] [] [] [] | + id-utils | [] [] [] | + indent | [] [] [] [] [] | + jpilot | () [] [] [] | + jwhois | [] [] | + kbd | [] [] | + ld | [] [] | + libc | [] [] [] [] [] [] [] | + lilypond | [] [] | + lynx | [] [] [] [] | + m4 | [] [] [] [] [] | + make | [] [] [] [] | + mysecretdiary | [] [] | + nano | [] () [] [] [] [] | + nano_1_0 | [] () [] [] [] [] | + opcodes | [] [] [] | + parted | [] [] [] [] [] | + ptx | [] [] [] [] [] | + python | | + recode | [] [] [] [] [] [] | + sed | [] [] [] [] [] [] [] [] | + sh-utils | [] [] [] [] [] [] [] [] | + sharutils | [] [] [] [] [] [] | + sketch | () [] () | + soundtracker | [] [] [] | + sp | [] | + tar | [] [] [] [] [] [] | + texinfo | [] [] [] [] [] | + textutils | [] [] [] [] [] | + util-linux | [] [] [] [] [] [] | + vorbis-tools | | + wastesedge | | + wdiff | [] [] [] [] [] [] | + wget | [] [] [] [] [] [] [] [] [] | + +-------------------------------------+ + bg ca cs da de el en eo es et fi fr + 2 14 11 31 40 10 1 8 41 16 1 50 + + gl he hr hu id it ja ko lv nb nl nn + +-------------------------------------+ + a2ps | () () [] | + bash | | + bfd | [] | + binutils | [] | + bison | [] [] | + clisp | [] | + cpio | [] [] [] | + diffutils | [] [] [] [] | + enscript | [] [] | + error | [] | + fetchmail | [] | + fileutils | [] [] [] | + findutils | [] [] [] [] [] [] [] | + flex | [] | + gas | | + gawk | [] | + gcal | | + gcc | | + gettext | [] [] | + gnupg | [] [] [] [] | + gprof | | + gpsdrive | () () | + grep | [] [] [] [] [] [] | + gretl | | + hello | [] [] [] [] [] [] [] [] [] [] [] [] | + id-utils | [] | + indent | [] [] [] | + jpilot | () () | + jwhois | [] | + kbd | | + ld | | + libc | [] [] [] [] | + lilypond | [] [] | + lynx | [] [] [] | + m4 | [] [] [] [] | + make | [] [] [] [] [] [] | + mysecretdiary | | + nano | [] [] [] () [] [] [] | + nano_1_0 | [] [] [] () [] [] | + opcodes | [] | + parted | [] [] [] | + ptx | [] [] [] [] | + python | | + recode | [] [] [] | + sed | [] [] [] [] [] [] [] | + sh-utils | [] [] [] [] [] | + sharutils | [] [] [] | + sketch | () | + soundtracker | [] | + sp | | + tar | [] [] [] [] [] | + texinfo | [] [] [] | + textutils | [] [] [] | + util-linux | () [] | + vorbis-tools | | + wastesedge | | + wdiff | [] [] | + wget | [] [] [] [] [] [] | + +-------------------------------------+ + gl he hr hu id it ja ko lv nb nl nn + 23 9 8 4 12 12 25 9 1 8 20 4 + + no pl pt pt_BR ru sk sl sv tr uk zh_TW + +----------------------------------------+ + a2ps | () () () [] [] [] [] () | 9 + bash | | 4 + bfd | [] [] | 5 + binutils | [] | 4 + bison | [] [] [] | 9 + clisp | | 5 + cpio | [] [] [] [] | 11 + diffutils | [] [] [] [] [] [] | 16 + enscript | [] [] [] | 7 + error | [] [] [] | 6 + fetchmail | () () [] | 6 + fileutils | [] [] [] [] [] | 13 + findutils | [] [] [] [] [] [] [] | 19 + flex | [] [] [] | 9 + gas | [] | 3 + gawk | [] [] | 6 + gcal | [] [] | 4 + gcc | [] | 3 + gettext | [] [] [] [] [] [] | 13 + gnupg | [] [] [] | 13 + gprof | [] [] | 4 + gpsdrive | () | 0 + grep | [] [] [] [] | 17 + gretl | | 0 + hello | [] [] [] [] [] [] [] | 27 + id-utils | [] [] | 6 + indent | [] [] [] [] | 12 + jpilot | () () [] | 4 + jwhois | () () [] [] | 5 + kbd | [] [] | 4 + ld | [] [] | 4 + libc | [] [] [] [] [] [] | 17 + lilypond | [] | 5 + lynx | [] [] [] | 10 + m4 | [] [] [] | 12 + make | [] [] [] [] | 14 + mysecretdiary | [] [] | 4 + nano | () [] [] [] [] | 15 + nano_1_0 | () [] [] [] [] | 14 + opcodes | [] [] | 6 + parted | [] [] [] | 11 + ptx | [] [] [] [] [] [] | 15 + python | | 0 + recode | [] [] [] [] | 13 + sed | [] [] [] [] [] [] | 21 + sh-utils | [] [] [] [] [] [] [] [] [] | 22 + sharutils | [] [] [] [] | 13 + sketch | [] () | 3 + soundtracker | [] | 5 + sp | | 1 + tar | [] [] [] [] [] [] [] | 18 + texinfo | [] [] | 10 + textutils | [] [] [] [] [] | 13 + util-linux | [] [] [] | 10 + vorbis-tools | [] | 1 + wastesedge | | 0 + wdiff | [] [] [] [] | 12 + wget | [] [] [] [] [] [] [] [] | 23 + +----------------------------------------+ + 35 teams no pl pt pt_BR ru sk sl sv tr uk zh_TW + 58 domains 5 16 2 14 27 11 11 41 36 4 9 536 + + Some counters in the preceding matrix are higher than the number of +visible blocks let us expect. This is because a few extra PO files are +used for implementing regional variants of languages, or language +dialects. + + For a PO file in the matrix above to be effective, the package to +which it applies should also have been internationalized and +distributed as such by its maintainer. There might be an observable +lag between the mere existence a PO file and its wide availability in a +distribution. + + If April 2002 seems to be old, you may fetch a more recent copy of +this `ABOUT-NLS' file on most GNU archive sites. The most up-to-date +matrix with full percentage details can be found at +`http://www.iro.umontreal.ca/contrib/po/HTML/matrix.html'. + +Using `gettext' in new packages +=============================== + + If you are writing a freely available program and want to +internationalize it you are welcome to use GNU `gettext' in your +package. Of course you have to respect the GNU Library General Public +License which covers the use of the GNU `gettext' library. This means +in particular that even non-free programs can use `libintl' as a shared +library, whereas only free software can use `libintl' as a static +library or use modified versions of `libintl'. + + Once the sources are changed appropriately and the setup can handle +to use of `gettext' the only thing missing are the translations. The +Free Translation Project is also available for packages which are not +developed inside the GNU project. Therefore the information given above +applies also for every other Free Software Project. Contact +`translation@iro.umontreal.ca' to make the `.pot' files available to +the translation teams. + diff --git a/hunspell/AUTHORS b/hunspell/AUTHORS new file mode 100644 index 000000000..3befa829f --- /dev/null +++ b/hunspell/AUTHORS @@ -0,0 +1,5 @@ +Author of Hunspell: +Németh László nemeth (at) OpenOffice.org + +Hunspell based on OpenOffice.org's Myspell. MySpell's author: +Kevin Hendricks kevin.hendricks (at) sympatico.ca diff --git a/hunspell/AUTHORS.myspell b/hunspell/AUTHORS.myspell new file mode 100644 index 000000000..7c7f980c9 --- /dev/null +++ b/hunspell/AUTHORS.myspell @@ -0,0 +1,67 @@ +Developer Credits: + +Special credit and thanks go to ispell's creator Geoff Kuenning. +Ispell affix compression code was used as the basis for the +affix code used in MySpell. Specifically Geoff's use of a +conds[] array that makes it easy to check if the conditions +required for a particular affix are present was very +ingenious! Kudos to Geoff. Very nicely done. +BTW: ispell is available under a BSD style license +from Geoff Kuennings ispell website: +http://www.cs.ucla.edu/ficus-members/geoff/ispell.html + + +Kevin Hendricks is the original +author and now maintainer of the MySpell codebase. Recent +additions include ngram support, and related character maps +to help improve and create suggestions for very poorly +spelled words. + +Please send any and all contributions or improvements +to him or to dev@lingucomponent.openoffice.org. + + +David Einstein (Deinst@world.std.com) developed an almost +complete rewrite of MySpell for use by the Mozilla project. +David and I are now working on parallel development tracks +to help our respective projects (Mozilla and OpenOffice.org) +and we will maintain full affix file and dictionary file +compatibility and work on merging our versions of MySpell +back into a single tree. David has been a significant help +in improving MySpell. + + +Nmeth Lszl is the author of +the Hungarian dictionary and he developed and contributed +extensive changes to MySpell including ... + * code to support compound words in MySpell + * fixed numerous problems with encoding case conversion tables. + * designed/developed replacement tables to improve suggestions + * changed affix file parsing to trees to greatly speed loading + * removed the need for malloc/free pairs in suffix_check which + speeds up spell checking in suffix rich languages by 20% + +Davide Prina , Giuseppe Modugno +, Gianluca Turconi +all from the it_IT OpenOffice.org team performed an +extremely detailed code review of MySpell and generated +fixes for bugs, leaks, and speedup improvements. + +Simon Brouwer for fixes and enhancements +that have greatly improved MySpell auggestions + * n-gram suggestions for an initcap word have an init. cap. + * fix for too many n-gram suggestions from specialized dictionary, + * fix for long suggestions rather than close ones in case of + dictionaries with many compound words (kompuuter) + * optionally disabling split-word suggestions (controlled + by NOSPLITSUGS line in affix file) + + +Special Thanks to all others who have either contributed ideas or +testing for MySpell + + +Thanks, + +Kevin Hendricks +kevin.hendricks@sympatico.ca diff --git a/hunspell/BUGS b/hunspell/BUGS new file mode 100644 index 000000000..b18d1352b --- /dev/null +++ b/hunspell/BUGS @@ -0,0 +1,9 @@ +* Problems with UTF-8 flag support on ARM platform (fail reputf and maputf test) + +* Interactive interface has some visualisation problem with UTF-8 characters + +* -U, -u options doesn't support Unicode. + +* Compound handling is not thread safe in Hungarian specific code + +* stemming is experimental and incomplete diff --git a/hunspell/COPYING b/hunspell/COPYING new file mode 100644 index 000000000..5bede4f5c --- /dev/null +++ b/hunspell/COPYING @@ -0,0 +1,12 @@ +GPL 2.0/LGPL 2.1/MPL 1.1 tri-license + +The contents of this software may be used under the terms of +the GNU General Public License Version 2 or later (the "GPL"), or +the GNU Lesser General Public License Version 2.1 or later (the "LGPL", +see COPYING.LGPL) or (excepting the LGPLed GNU gettext library in the +intl/ directory) the Mozilla Public License Version 1.1 or later +(the "MPL", see COPYING.MPL). + +Software distributed under these licenses is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the licences +for the specific language governing rights and limitations under the licenses. diff --git a/hunspell/COPYING.LGPL b/hunspell/COPYING.LGPL new file mode 100644 index 000000000..c4792dd27 --- /dev/null +++ b/hunspell/COPYING.LGPL @@ -0,0 +1,515 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 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. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. +^L + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. +^L + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. +^L + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. +^L + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. +^L + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. +^L + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. +^L + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS +^L + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper +mail. + +You should also get your employer (if you work as a programmer) or +your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James +Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/hunspell/COPYING.MPL b/hunspell/COPYING.MPL new file mode 100644 index 000000000..7714141d1 --- /dev/null +++ b/hunspell/COPYING.MPL @@ -0,0 +1,470 @@ + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A -Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + diff --git a/hunspell/ChangeLog b/hunspell/ChangeLog new file mode 100644 index 000000000..dc3c224d8 --- /dev/null +++ b/hunspell/ChangeLog @@ -0,0 +1,1107 @@ +2007-11-01 Németh László : + * hunspell/*: new feature: morphological generation, + also fix experimental morphological analysis and stemming. + - new API functions and improved API: + - analyze(word): (instead of morph()) morphological analysis + - stem(word): stemming + - stem(list): stemming based on the result of an analysis + - generate(word, word2): morphological generation + - generate(word, list): morphological generation + - add(word): add word to the run-time dictionary (renamed put_word()) + - add_with_affix(word, word2): (renamed put_word_pattern()): + add word to the run-time dictionary with affix flags of the + second parameter: all affixed forms of the user words will be + recognised by the spell checker. Especially useful for + agglutinative languages. + - remove(word): remove word from the run-time dictionary (not + implemented) + - see manual and hunspell/hunspell.hxx header and tests/morph.* + * tests/morph.*: test data, example for morphological analysis, + stemming and generation + + * tools/analyze, tools/chmorph: extended and new demo applications: + - analyze (originally hunmorph): analyses and stems input words, + generates word forms from input word pairs. + - chmorph: morphological transformation filter + + * configure.ac, hunspell/makefile.am: set library version number. + Bug reported by Rene Engelhard. + + * affentry.cxx, affixmgr.cxx: new pattern matching algorithm in + condition checking of affix rules instead of the Dömölki-algorithm: + - Unlimited condition length (instead of max. 8 characters). + - Less memory consumption, especially useful for affix rich languages: + 5,4 MB memory savings with hu_HU dictionary. + - Speed change depends from dictionaries and CPU caches: English spell + checking is 4% faster on Linux words with en_US dictionary, Hungarian + spell checking is 25% slower on most frequent words of Hungarian + Webcorpus. + + * tests/sug.*, sugutf.*: updated test data (use "a" and "lot" + dictionary items instead of "a lot".) + + * src/hunspell/hunspell.cxx: free(csconv) instead of delete csconv. + Report and patch by Sylvain Paschein in Mozilla Issue 398268. + + * suggestmgr.cxx, tools/hunspell.cxx: bad spelling of "misspelled". + Ubuntu Bug #134792, patch by Malcolm Parsons. + + * tests/base_utf.*: use Unicode apostrophe instead of 8-bit one. + + * hunspell.cxx, hashmgr.cxx: add(): use HashMgr::add() + +2007-10-25 Pavel Janík : + * hunspell/csutil.cxx: Fix type cast warnings on 64bit Linux in + printing of character positions in u8_u16(). OOo issue 82984. + +2007-09-05 Németh László : + * win_api/Hunspell.vproj, parsers/testparser.cxx,textparser.hxx: + warning fixes and removing unnecessary Windows project file. + Reported by Ingo H. De Boer. + + * hashmgr.*, {affixmgr,suggestmgr}.cxx: optimized data structure + for variable-count fields (only "ph" transliteration field in + this version, see next item). Also less memory consumption: + -13% (0.75 MB) with en_US dictionary, -6% (1 MB) with hu_HU. + + * suggestmgr.cxx: dictionary based phonetic suggestion for special + or foreign pronounciation (see also rule-based PHONE in manual). + Usage: tab separated field in dictionary lines, started with "ph:". + The field contains a phonetic transliteration of the word: + +Marseille ph:maarsayl + * tests/phone.*: test data for dictionary and rule based phonetic + suggestion. + + * hunspell.cxx: fix potential bad memory access in allcap word + capitalization in suggest() (bug of previous version). + + * hunspell.cxx, atypes.hxx: set correct limit for UTF-8 encoded + input words (256 byte). + + * suggestmgr.cxx: improved REP suggestions with spaces: it works + without dictionary modification. + OOo issue 80147, reported by Davide Prina. + * tests/rep.*: new test data: higher priority for "alot" -> "a lot", + and Italian suggestion "un'alunno" -> "un alunno". + + * affixmgr.cxx: fix Unicode ngram suggestions in expand_rootword(). + (Suggestions with bad affixes.) + Bug reported by Vitaly Piryatinksy . + * tests/ngram_utf_fix.*: test based on Vitaly Piryatinksy's data. + + * suggestmgr.cxx: fix twowords() for last UTF-8 multibyte character. + (conditional jump or move depended on uninitialised value). + +2007-08-29 Ingo H. De Boer : + * win_api/{hunspell,libhunspell, testparser}.vcproj: new project + files for the library and the executables. + + * Hunspell.rc, Hunspell.sln, config.h: updated versions. + Version number problem also reported by András Tímár. + +2007-08-27 Németh László : + * suggestmgr.hxx: put fixed version. Bug report by Ingo H. De Boer. + + * suggestmgr.cxx: remove variable-length local character array + reported by Ingo H. De Boer. + +2007-08-27 Németh László : + * suggestmgr.hxx: change bad time_t to clock_t in header, too. + Bug reports or patches by Ingo H. De Boer under SF.net + Bug ID 1781951, János Mohácsi and Gábor Zahemszky, András Tímár, + OMax3 at SF.net under SF.net Bug ID 1781592. + + * phonet.*: change variable-length local character array to + portable fixed size character array. Problem reported by + Ingo H. De Boer under SF.net Bug ID 1781951 and + Ryan VanderMeulen. + + * suggestmgr.cxx: remove debug message (also by + Ingo H. De Boer). + +2007-08-26 Ingo H. De Boer : + * win_api/Hunspell.vcproj: updated version (with phonet.*) + +2007-08-23 Németh László : + * phonet.{c,h}xx, suggestmgr.cxx: PHONE parameter: + pronounciation based suggestion using Björn Jacke's original Aspell + phonetic transcription algorithm (http://aspell.net), relicensed + under GPL/LGPL/MPL tri-license with the permission of the author. + Usage: see manual. + + * affixmgr,suggestmgr.cxx: add KEY parameter for keyboard and + input method error related suggestions. + Example: KEY qwertyuiop|asdfghjkl|zxcvbnm + + * man/hunspell.4: description about PHONE and KEY suggestion parameters. + + * suggestmgr.cxx: enhancements for better suggestions: + - Set ngram suggestions for badchar-type errors + and only two word and compound word suggestions, too. + - Separate not compound and compound word + suggestions for MAP suggestion, too. + - Double swap suggestions for short words. + For example: ahev -> have, hwihc -> which. + - Better time limits using clock() instead of time() + (tenths of a second resolution instead of second ones). + - leftcommonsubstring() weigth function. + + * htype.hxx, hashmgr.cxx: blen (byte length) and clen (character + length) fields instead of wlen + + * affixmgr.cxx: fix get_syllable() for bad Unicode inputs. + + * tests/suggestiontest/*: test environment for suggestions + +2007-08-07 Martijn Wargers: + * csutil.cxx: fix Mingw build error associated with ToUpper() call. + Report and patch in Mozilla Issue 391447. + +2007-08-07 Robert Longson: + * atypes.cxx: use empty inline function HUNSPELL_WARNING instead of + variadic macros to switch of Hunspell warnings. + Reported by Gavin Sharp in Mozilla Issue 391147. + +2007-08-05 Ginn Chen: + * hashmgr.cxx: Hunspell failed to compile on OpenSolaris (use stdio + instead of csdio). Report and patch in Mozilla Issue 391040. + +2007-07-25 Németh László : + * parsers/*.cxx: Hunspell executable recognises and accepts URLs, + e-mail addresses, directory paths, reported by Jeppe Bundsgaard. + * src/tools/hunspell.cxx: --check-url: new option of Hunspell program. + Use --check-url, if you want check URLs, e-mail addresses and paths. + + * parsers/textparser.cxx: strip colon at end of words for Finnish + and Swedish (colon may be in words in Finnish and Swedish). + Problem reported by Lars Aronsson. + * tests/colons_in_words.*: test data + + * tests/digits_in_words.*: example for using digits in words + (eg. 1-jährig, 112-jährig etc. in German), reported by Lars Aronsson. + + * hashmgr.cxx: Hunspell accepts allcaps forms of mixed case + words of personal dictionaries (+allcaps custom dictionary words with + allcaps affixes). + Sf.net Bug ID 1755272, reported by Ellis Miller. + + * hashmgr.cxx: fix small memory leaks with alias compressed + dictionaries (free flag vectors of affixed personal dictionary words + and flag vectors of hidden capitalized forms of mixed case and + allcaps words). + + * affixmgr.cxx: fix COMPOUNDRULE checking with affixed compounds. + Sf.net Bug ID 1706659, reported by Björn Jacke. Also fixing for + OOo Issue 76067 (crash-like deceleration for hexadecimal numbers + with long FFFFFF sequence using en_US dictionary). + + * tools/hunspell.cxx: add missing return to save_privdic(). + + * man/hunspell.4: add information about affixation of personal words: + "Personal dictionaries are simple word lists, but with optional + word patterns for affixation, separated by a slash: + + foo + Foo/Simpson + + In this example, "foo" and "Foo" are personal words, plus Foo + will be recognised with affixes of Simpson (Foo's etc.)." + +2007-07-18 Németh László : + * src/win_api/: add missing resource files, reported by Ingo H. De Boer. + +2007-07-16 Németh László : + * hunspell.cxx: fix dot removing from UTF-8 encoded words in cleanword2() + (Capitalised words with dots, as "Something." were not recognised + using Unicode encoded dictionaries.) + * tests/{base.*,base_utf.*}: extended and new test files for + dot removing and Unicode support. + + * tools/hunspell.cxx: fix Cygwin, OS X compatibility using platform + specifics iconv() header by ICONV_CONST macro of Autoconf. + Sf.net Bug ID 1746030, reported by Mike Tian-Jian Jiang. + Sf.net Bug ID 1753939, reported by Jean-Christophe Helary. + + * tools/hunspell.cxx: fix missing global path setting with -d option. + + * tests/test.sh: fix broken Valgrind checking (missing warnings + with VALGRIND=memcheck make check). + + * csutil.cxx: fix condition in u8_u16() to avoid invalid read + of not null-terminated character arrays (detected by Valgrind + in Hunspell executable: associated with 8-bit character table + conversion in tools/hunspell.cxx). + + * csutil.cxx: free_utf_tbl(): use utf_tbl_count-- instead of utf_tbl--. + Memory leak in Hunspell executable detected by Valgrind. + + * hashmgr.cxx: add missing free_utf_tbl(), memory leak in Hunspell + executable detected by Valgrind. + + * hashmgr.cxx: load_tables(): fix memory error in spec. capitalization. + Use sizeof(unsigned short) instead of bad sizeof(unsigned short*). + Invalid memory read detected by Valgrind. + + * hashmgr.cxx: add_word(): fix memory error in spec. capitalization. + Update also affix array length of capitalized homonyms. Invalid + memory read detected by Valgrind. + + * hunspell.cxx: suggest(): fix invalid memory write and leak. + Bad realloc() and missing free() detected by Valgrind associated + with suggestions for "something.The" type spelling errors. + + * {dictmgr,csutil,hashmgr,suggestmgr}.cxx: check memory allocation. + Sf.net Bug ID 1747507, based on the patch by Jose da Silva. + +2007-07-13 Ingo H. De Boer : + * atypes.cxx: fix Visual C compatibility: Using + "HUNSPELL_WARNING(a,b,...} {}" macro instead of empty "X(a,b...)". + + * hunspell.cxx: changes for Windows API. + * win_api/Hunspell.*: new resource files + * win_api/hunspelldll.*: set optional Hunspell and Borland spec. codes + Sf.net Bug ID 1753802, patch by Ingo H. de Boer. + See also Sf.net Bug ID 1751406, patch by Mike Tian-Jian Jiang. + +2007-07-09 Caolan McNamara : + * {hunspell,hashmgr,affentry}.cxx: fix warnings of Coverity program + analyzer. Sf.net Bug ID, 1750219. + +2007-07-06 Németh László : + * atypes.cxx: warning-free swallowing of conditional warning messages + and their parameters using empty HUNSPELL_WARNING(a,b...) macro. + * {affixmgr,atypes,csutil}.cxx: fix unused variable warnings + using WARNVAR macro for conditionally named variables. + * hashmgr.cxx: fix unused variable warning in add_word() by cond. name + * hunspell.cxx: fix shadowed declaration of captype var. in suggest() + +2006-06-29 Caolan McNamara : + * hunspell.cxx: patch to fix possible memory leak in analyze() of + experimental morphological analyzer code. Sf.net Bug ID 1745263. + +2007-06-29 Németh László : +improvements: + * src/hunspell/hunspell.cxx: check bad capitalisation of Dutch letter IJ. + - Sf.net Feature Request ID 1640985, reported by Frank Fesevur. + - Solution: FORBIDDENWORD for capitalised word forms (need + an improved Dutch dictionary with forbidden words: Ijs/*, etc.). + * tests/IJ.*: test data and example. + + * hashmgr.cxx, hunspell.cxx: check capitalization of special word forms + - words with mixed capitalisation: OpenOffice.org - OPENOFFICE.ORG + Sf.net Bug ID 1398550, reported by Dmitri Gabinski. + - allcap words and suffixes: UNICEF's - UNICEF'S + - prefixes with apostrophe and proper names: Sant'Elia - SANT'ELIA + For Catalan, French and Italian languages. + Reported by Davide Prina in OOo Issue 68568. + * tests/allcaps*: tests for OPENOFFICE.ORG, UNICEF'S capitalization. + * tests/i68568*: tests for SANT'ELIA capitalization. + + * hunspell/hunspell.cxx: suggestion for missing sentence spacing: + something.The -> something. The + + * tools/hunspell.cxx: multiple character encoding support + - -i option: custom input encoding + Sf.net Bug ID 1610866, reported by Thobias Schlemmer. + Sf.net Bug ID 1633413, reported by Dan Kenigsberg. + See also hunspell-1.1.5-encoding.patch of Fedora from Caolan Mc'Namara. + * tests/*.test: add input encodings + + * tools/hunspell.cxx: use locale data for default dictionary names. + Sf.net Bug ID 1731630, report and patch from Bernhard Rosenkraenzer, + See also hunspell-1.1.4-defaultdictfromlang.patch of Fedora Linux + from Caolan McNamara. + + * tools/hunspell.cxx: fix 8-bit tokenization (letters without + casing, like ß or Hebrew characters now are handled well) + + * tools/hunspell.cxx: dictionary search path + - DICPATH environmental variable + - -D option: show directory path of loaded dictionary + - automatic detection of OpenOffice.org directories + +fixes: + * affixmgr.cxx: fault-tolerant patch for REP and other affix + table data problems. Problem with Hunspell and en_GB dictionary + reported by Thomas Lange in OOo Issue 76098 and + Stephan Bergmann in OOo Issue 76100. + Sf.net Bug ID 1698240, reported by Ingo H. de Boer. + + * csutil.cxx: fix mkallcap_utf() for allcaps suggestion in UTF-8. + + * suggestmgr.cxx: fix bad movechar_utf() (missing strlen()). + + * hunspell.cxx: fix bad degree sign detection in Unicode + hu_HU environment. + + * hunspell/hunspell.cxx: free allocated memory of csconv in + ported Mozilla code. + - Mozilla Bugzilla Bug 383564, report and Mozilla MySpell patch + by Andrew Geul. Reported by Ryan VanderMeulen for Hunspell. + + * suggestmgr.cxx: fix minor difference in Unicode suggestion + (ngram suggestion of allcaps words in Unicode). + + * hashmgr.cxx: close file handle after errors. + Sf.net Bug ID 1736286, reported by John Nisly. + + * configure.ac: syntax error (shell variable with spaces). + Sf.net Bug ID 1731625, reported by Bernhard Rosenkraenzer. + + * hunspell.cxx: check_word(): fix bad usage of info pointer. + + * hashmgr.cxx: fix de_DE related bug (accept words with leading dash). + Sf.net Bug ID 1696134, reported by Björn Jacke. + + * suggestmgr.cxx, tests/1695964.*: fix NEEDAFFIX homonym suggestion. + Sf.net Bug ID 1695964, reported by Björn Jacke. + + * tests/1463589*: capitalized ngram suggestion test data for + Sf.net Bug ID 1463589, reported by Frederik Fouvry. + + * csutil.cxx, affixmgr.cxx: fix possible heap error with + multiple instances of utf_tbl. + Sf.net Bug ID 1693875, reported by Ingo H. de Boer. + + * affixmgr.cxx, suggestmgr.cxx, license.hunspell: convert to ASCII. + Locale dependent compiling problems. Sf.net Bug ID 1694379, reported + by Mike Tian-Jian Jiang. OOo Issue 78018 reported by Thomas Lange. + + * tests/test.sh: compatibility issues + - fix Valgrind support (check shared library instead of shell wrapper) + - remove deprecated "tail +2" syntax + - set 8-bit locale for testing (LC_ALL=C) + + * hunspell.hxx: remove license.* and config.h dependencies. + - hunspell-1.1.5-badheader.patch from Caolan McNamara + +2007-03-21 Németh László : + * tools/Makefile.am, munch.h, unmunch.h: add missing munch.h and unmunch.h + Reported by Björn Jacke and Khaled Hosny (sf.net Bug ID 1684144) + * hunspell/hunspell.cxx, hunspell.hxx: fix --with-ui compliling error (add get_csconv()) + Reported by Khaled Hosny (sf.net Bug ID 1685010) + +2007-03-19 Németh László : + * csutil.cxx, hunspell/hunspell.cxx: Unicode non BMP area (>65K character range) support + (except conditional patterns and strip characters of affix rules) + * tests/utf8_nonbmp*: test data + + * src/hunspell/*: add Mozilla patches from David Einstein + - run-time generated 8-bit character tables + - other Mozilla related changes (see Mozilla Bugzilla Bug 319778) + + * csutil.cxx, affixmgr.cxx, hashmgr.cxx: optimized version of IGNORE feature + - IGNORE works with affixes (except strip characters and affix conditions) + * tests/ignore*: test data with latin characters + * tests/ignoreutf*: Unicode test data with Arabic diacritics (Harakat) + + * src/hunspell/suggestmgr.cxx: new edit distance suggestion methods + - capitalization: nasa -> NASA + - long swap: permenant -> permanent + - long mov.: Ghandi -> Gandhi + - double two characters: vacacation -> vacation + * tests/sug.*: test data + + * src/hunspell/affixmgr.cxx: space in REP strings (alot -> a lot) + Note: Underline character signs the space in REP strings: REP alot a_lot, and + put the expression with space ("a lot") into the dic file (see tests/sug). + + * hashmgr.cxx, affixmgr.cxx: ignore Unicode byte order mark (BOM sequence) + * tests/utf8_bom*: test data + + * hunspell/*.cxx: OOo Issue 68903 - Make lingucomponent warning-free on wntmsci10 + - fix Hunspell related warning messages on Windows platform (except some assignment + within conditional expressions). Reported and started by Stephan Bergmann. + + * hunspell/affixmgr.cxx: fix OOo Issue 66683 - hunspell dmake debug=x fails + - Reported by Stephan Bergmann. + + * src/hunspell/hunspell.[ch]xx: thread safe API for Hunspell executable + (removing prev*() functions, new spell(word, info, root) function) + + * configure.ac, src/hunspell/*: HUNSPELL_EXPERIMENTAL code + --with-experimental configure option (conditional compiling of morphological analyser + and stemmer tools) + + * configure.ac, src/hunspell/*: conditional Hunspell warning messages + --with-warnings configure option + + * affixmgr.cxx: new, optimized parsing functions + + * affixmgr.cxx: fix homonym handling for German dictionary project, + reported by Björn Jacke (sf.net Bug ID 1592880). + * tests/1592880.*: test data by Björn Jacke + + * src/hunspell/affixmgr.cxx: fix CIRCUMFIX suggestion + Bug reported by Erdal Ronahi. + + * hunspell.cxx: reverse root word output (complex prefixes) + Bug reported by Munzir Taha. + + * tools/hunspell.cxx: fix Emacs compatibility, patch by marot at sf.net + - no % command in PIPE mode (SourceForge BugTracker 1595607) + - fix HUNSPELL_VERSION string + + * suggestmgr.[hc]xx: rename check() functions to checkword() (OOo Issue 68296) + adopt MySpell patch by Bryan Petty (tierra at ooo) for Hunspell source + + * csutil.cxx, munch.c, unmunch.c: adopt relevant parts of the MinGW patch + (OOo Issue 42504) by tonal at ooo + + * affigmgr.cxx: remove double candidate_check() call, reported by Bram Moolenaar + + * tests/test.sh: add LC_ALL="C" environment. Locale dependency of make check + reported by Gentoo project. + + * src/tools/hunspell.cxx: UTF-8 highlighting fix for console UI + (not solved: breaking long UTF-8 lines) + + * src/tools/unmunch.c: fix bad generation if strip is shorter than condition, + reported by Davide Prina + * src/tools/unmunch.h: increase 5000 -> 500000 + + * src/tools/hunspell.cxx: fix memory error in suggestion (uninitialized parameter), + Bug also reported by Björn Jacke in SourceForge Bug 1469957 + + * csutil.cxx, affixmgr.cxx: fix Caolan McNamara's patch for non OOo environment + +2006-11-11 Caolan McNamara : + * csutil.cxx, affixmgr.cxx: UTF-8 table patch (OOo Issue 71449) + Description: memory optimization (OOo doesn't use the large UTF-8 table). + + * Makefile.am: shared library patch (Sourceforge ID 1610756) + + * hunspell.h, hunspell.cxx: C API patch (Sourceforge ID 1616353) + + * hunspell.pc: pkgconfig patch (Sourceforge ID 1639128) + +2006-10-17 Ryan Jones : + * affixmgr.cxx: missing fclose(affixlst) calls + Reported by in OOo Issue 70408 + +2007-07-11 Taha Zerrouki : + * affixmgr.cxx, hunspell.cxx, hashmgr.cxx, csutil.cxx: IGNORE feature to remove + optional Arabic and other characters from input and dictionary words. + * src/hunspell/langnum.hxx: add Arabic language number, lang_ar=96 + * tests/ignore.*: test data + +2006-05-28 Miha Vrhovnik : + * src/win_api/*: C API for Windows DLLs + - also Delphi text editor example (see on Hunspell Sourceforge page) + +2006-05-18 Kevin F. Quinn : + * utf_info.cxx: struct -> static struct + Shared library patch also developed by Gentoo developers (Hanno Meyer-Thurow, + Diego Pettenò, Kevin F. Quinn) + +2006-02-02 Németh László : + * src/hunspell/hunspell.cxx: suggest(): replace "fooBar" -> "foo bar" suggestions + with "fooBar" ->"foo Bar" (missing spaces are typical OCR bugs). + Bug reported by stowrob at OOo in Issue 58202. + * src/hunspell/suggestmgr.cxx: twowords(): permit 1-character words. + (restore MySpell's original behavior). Here: "aNew" -> "a New". + * tests/i58202.*: test data + + * src/parsers/textparser.cxx: fix Unicode tokenization in is_wordchar() + (extra word characters (WORDCHARS) didn't work on big-endian platforms). + + * src/hunspell/{csutil,affixmgr}.cxx: inline isSubset(), isRevSubset(): + little speed optimalization for languages with rich morphology. + + * src/tools/hunspell.cxx: fix bad --with-ui and --with-readline compiling + when (N)curses is missing. Reported by Daniel Naber. + +2006-01-19 Tor Lillqvist + * src/hunspell/csutil.cxx: mystrsep(): fix locale-dependent isspace() tokenization + +2006-01-06 András Tímár + * src/hunspell/{hashmgr.hxx,hunspell.cxx}: fix Visual C++ compiling errors + +2006-01-05 Németh László : + * COPYING: set GPL/LGPL/MPL tri-license for Mozilla integration. + Rationale: Mozilla source code contains an old MySpell version + with GPL/LGPL/MPL tri-license. (MPL license is a copyleft license, similar + to the LGPL, but it acts on file level.) + * COPYING.LGPL: GNU Lesser General Public License 2.1 (LGPL) + * COPYING.MPL: Mozilla Public License 1.1 (MPL) + * license.hunspell, src/hunspell/license.hunspell: GPL/LGPL/MPL tri-license + + * src/hunspell/{affixmgr,hashmgr}.*: AF, AM alias definitions in affix file: + compression of flag sets and morphological descriptions (see manual, + and tests/alias* test files). + Rationale: Alias compression is also good for loading time and memory + efficiency, not only smaller resources. + * src/tools/makealias: alias compression utility + (usage: ./makealias file.dic file.aff) + * tests/alias{,2,3}: AF, AM tests + * man/hunspell.4: add AF, AM documentation + * src/hunspell/affentry.cxx, atypes.hxx: add new opts bits (aeALIASM, aeALIASF) + + * tools/hunspell, src/parser/*, src/hunspell/*: Hunspell program + tokenizes Unicode texts (only with UTF-8 encoded dictionaries). + Missing Unicode tokenization reported by Björn Jacke, Egmont Koblinger, + Jess Body and others. + Note: Curses interactive interface hasn't worked perfectly yet. + * tests/*.tests: remove -1 parameters of Hunspell + * tests/*.{good,wrong}: remove tabulators + + * src/hunspell/{hunspell,affixmgr}.cxx: BREAK option: break words at + specified break points and checking word parts separately (see manual). + Note: COMPOUNDRULE is better (or will be better) for handling dashes and + other compound joining characters or character strings. Use BREAK, if you + want check words with dashes or other joining characters and there is no time + or possibility to describe precise compound rules with COMPOUNDRULE. + * tests/break.*: BREAK example. + + * src/hunspell/{affixmgr,hunspell}.cxx: add CHECKSHARPS declaration instead + of LANG de_DE definitions to handle German sharp s in both spelling and + suggestion. + * src/hunspell/hunspell.cxx: With CHECKSHARPS, uppercase words are valid + with both lower sharp s (it's is optional for names in German legal texts) + and SS (MÜßIG, MÜSSIG). Missing lower sharp s form reported by Björn Jacke. + * src/hunspell/hunspell.cxx: KEEPCASE flag on a sharp s word has a special + meaning with CHECKSHARPS declaration: KEEPCASE permits capitalisation and SS upper + casing of a sharp s word (Müßig and MÜSSIG), but forbids the upper cased form + with lower sharp s character(s): *MÜßIG. + * tests/germancompounding*: add CHECKSHARPS, remove LANG + * tests/checksharps*: add CHECKSHARPS and KEEPCASE, remove LANG + + * src/hunspell/hunspell.cxx: improved suggestions: + - suggestions for pressed Caps Lock problems: macARONI -> macaroni + - suggestions for long shift problems: MAcaroni -> Macaroni, macaroni + - suggestions for KEEPCASE words: KG -> kg + * src/hunspell/csutil.cxx: fix mystrrep() function: + - suggestions for lower sharp s in uppercased words: MÜßIG -> MÜSSIG + * tests/checksharps{,utf}.sug: add tests for mystrrep() fix + + * src/hunspell/hashmgr.cxx: Now dictionary words can contain slashes + with the "\/" syntax. Problem reported by Frederik Fouvry. + + * src/hunspell/hunspell.cxx: fix bad duplicate filter in suggest(). + (Suggesting some capitalised compound words caused program crash + with Hungarian dictionary, OOo Issue 59055). + + * src/hunspell/affixmgr.cxx: fix bad defcpd_check() call in compound_check(). + (Overlapping new COMPOUNDRULE and old compounding methods caused program + crash at suggestion.) + + * src/hunspell/affixmgr.{cxx,hxx}: check affix flag duplication at affix classes. + Suggested by Daniel Naber. + + * src/hunspell/affentry.cxx: remove unused variable declarations (OOo i58338). + Compiler warnings reported by András Tímár and Martin Hollmichel. + + * src/hunspell/hunspell.cxx: morph(): not analyse bad mixed uppercased forms + (fix Arabic morphological analysis with Buckwalter's Arabic transliteration) + + * src/hunspell/affentry.{cxx,hxx}, atypes.hxx: little memory optimization + in affentry: + - using unsigned char fields instead of short (stripl, appndl, numconds) + - rename xpflg field to opts + - removing utf8 field, use aeUTF8 bit of opts field + + * configure.ac: set tests/maputf.test to XFAILED on ARM platform. + Fail reported by Rene Engelhard. + + * configure.ac: link Ncursesw library, if exists. + + * BUGS: add BUGS file + + * tests/complexprefixes2.*: test for morphological analysis with COMPLEXPREFIXES + + * src/hunspell/affixmgr.cxx: use "COMPOUNDRULE" instead of + "COMPOUND". The new name suggested by Bram Moolenaar. + * tests/compoundrule*: modified and renamed compound.* test files + + * man/hunspell.4: AF, AM, BREAK, CHECKSHARPS, COMPOUNDRULE, KEEPCASE. + - also new addition to the documentation: + Header of the dictionary file define approximate dictionary size: + ``A dictionary file (*.dic) contains a list of words, one per line. + The first line of the dictionaries (except personal dictionaries) + contains the _approximate_ word count (for optimal hash memory size).'' + Asked by Frederik Foudry. + + One-character replacements in REP definitions: ``It's very useful to + define replacements for the most typical one-character mistakes, too: + with REP you can add higher priority to a subset of the TRY suggestions + (suggestion list begins with the REP suggestions).'' + +2005-11-11 Németh László : + * src/hunspell/affixmgr.*: fix Unicode MAP errors (sorted only n-1 + characters instead of n ones in UTF-16 MAP character lists). + Bug reported by Rene Engelhard. + + * src/hunspell/affixmgr.*: fix infinite COMPOUND matching (default char + type is unsigned on PowerPC, s390 and ARM platforms and it will never + be negative). Bug reported by Rene Engelhard. + + * src/hunspell/{affixmgr,suggestmgr}.cxx: fix bad ONLYINCOMPOUND + word suggestions. + * tests/onlyincompound.sug: empty test file to check this fix. + Bug reported by Björn Jacke. + + * src/hunspell/affixmgr.cxx: fix backtracking in COMPOUND pattern matching. + * tests/compound6.*: test files to check this fix. + + * csutil.cxx: set bigger range types in flag_qsort() and flag_bsearch(). + + * affixmgr.hxx: set better type for cont_classes[] Boolean data (short -> char) + + * configure.ac, tests/automake.am: set platform specific XFAIL test + (flagutf8.test on ARM platform) + +2005-11-09 Németh László : +improvements: + * src/hunspell/affixmgr.*: new and improved affix file parameters: + + - COMPOUND definitions: compound patterns with regexp-like matching. + See manual and test files: tests/compound*.* + Suggested by Bram Moolenaar. + Also useful for simple word-level lexical scanning, for example + analysing numbers or words with numbers (OOo Issue #53643): + http://qa.openoffice.org/issues/show_bug.cgi?id=53643 + Examples: tests/compound{4,5}.*. + + - NOSUGGEST flag: words signed with NOSUGGEST flag are not suggested. + Proposed flag for vulgar and obscene words (OOo Issue #55498). + Example: tests/nosuggest.*. + Problem reported by bobharvey at OOo: + http://qa.openoffice.org/issues/show_bug.cgi?id=55498 + + - KEEPCASE flag: Forbid capitalized and uppercased forms of words + signed with KEEPCASE flags. Useful for special ortographies + (measurements and currency often keep their case in uppercased + texts) and other writing systems (eg. keeping lower case of IPA + characters). + + - CHECKCOMPOUNDCASE: Forbid upper case characters at word bound in compounds. + Examples: tests/checkcompoundcase* and tests/germancompounding.* + + - FLAG UTF-8: New flag type: Unicode character encoded with UTF-8. + Example: tests/flagutf8.*. + Rationale: Unicode character type can be more readable + (in a Unicode text editor) than `long' or `num' flag type. + +bug fixes: + * src/hunspell/hunspell.cxx: accept numbers and numbers with separators (i53643) + Bug reported by skelet at OOo: + http://qa.openoffice.org/issues/show_bug.cgi?id=53643 + + * src/hunspell/csutil.cxx: fix casing data in ISO 8859-13 character table. + + * src/hunspell/csutil.cxx: add ISO-8859-15 character encoding (i54980) + Rationale: ISO-8859-15 is the default encoding of the French OpenOffice.org + dictionary. ISO-8859-15 is a modified version of ISO-8859-1 + (latin-1) character encoding with French œ ligatures and euro + symbol. Problem reported by cbrunet at OOo in OOo Issue 54980: + http://qa.openoffice.org/issues/show_bug.cgi?id=54980 + + * src/hunspell/affixmgr.cxx: fix zero-byte malloc after a bad affix header. + Patch by Harri Pitkänen. + + * src/hunspell/suggestmgr.cxx: fix bad NEEDAFFIX word suggestion + in ngram suggestions. Reported by Daniel Naber and Friedel Wolff. + + * src/hunspell/hashmgr.cxx: fix bad white space checking in affix files. + src/hunspell/{csutil,affixmgr}.cxx: add other white space separators. + Problems with tabulators reported by Frederik Fouvry. + + * src/hunspell/*: replace system-dependent #include + parameters with quoted ones. Problem reported by Dafydd Jones. + + * src/hunspell/hunspell.cxx: fix missing morphological analysis of dot(s) + Reported by Trón Viktor. + +changes: + * src/hunspell/affixmgr.cxx: rename PSEUDOROOT to NEEDAFFIX. + Suggested by Bram Moolenaar. + + * src/hunspell/suggestmgr.hxx: Increase default maximum of + ngram suggestions (3->5). Suggested by Kevin Hendricks. + + * src/hunspell/htypes.hxx: Increase MAXDELEN for long affix flags. + + * src/hunspell/suggestmgr.cxx: modify (perhaps fix) Unicode map suggestion. + tests/maputf test fail on ARM platform reported by Rene Engelhard. + + * src/hunspell/{affentry.cxx,atypes.hxx}: remove [PREFIX] and + MISSING_DESCRIPTION messages from morphological analysis. + Problems reported by Trón Viktor. + + * tests/germancompounding.{aff,good}: Add "Computer-Arbeit" test word. + Suggested by Daniel Naber. + + * doc/man/hunspell.4: Proof-reading patch by Goldman Eleonóra. + + * doc/man/hunspell.4: Fix bad affix example (replace `move' with `work'). + Bug reported by Frederik Fouvry. + + * tests/*: new test files: + affixes.*: simple affix compression example from Hunspell 4 manual page + checkcompoundcase.*, checkcompoundcase2.*, checkcompoundcaseutf.* + compound.*, compound2.*, compound3.*, compound4.*, compound5.* + compoundflag.* (former compound.*) + flagutf8.*: test for FLAG UTF-8 + germancompounding.*: simplification with CHECKCOMPOUNDCASE. + germancompoundingold.* (former germancompounding.*) + i53643.*: check numbers with separators + i54980.*: ISO8859-15 test + keepcase.*: test for KEEPCASE + needaffix*.* (former pseudoroot*.* tests) + nosuggest.*: test for NOSUGGEST + +2005-09-19 Németh László : + * src/hunspell/suggestmgr.cxx: improved ngram suggestion: + - detect not neighboring swap characters (pernament -> permanent) + Rationale: ngram method has a significant error with not neighboring + swap characters, especially when swap is in the middle of the word. + - suggest uppercase forms (unesco -> UNESCO, siggraph's -> SIGGRAPH's) + - suggest only ngram swap character and uppercase form, if they exist. + Rationale: swap character and casing equivalence give mutch better + suggestions as any other (weighted) ngram suggestions. + - add uppercase suggestion (PERMENANT -> PERMANENT) + + * src/hunspell/*: complete comparison with MySpell 3.2 (in OOo beta 2): + - affixmgr.cxx: add missing numrep initialization + - hashmgr.cxx: add_word(): don't allocate temporary records + - hunspell.cxx: in suggest(): + - check capitalized words first (better sug. order for proper names), + - check pSMgr->suggest() return value + - set pSMgr->suggest() call to not optional in HUHCAP + - csutil.cxx: fix bad KOI8-U -> koi8r_tbl reference in enc_entry encds + - csutil.cxx: fix casing data in ISO 8859-2, Windows 1251 and KOI8-U + encoding tables. Bug reported by Dmitri Gabinski. + + * src/hunspell/affixmgr.*: improved compound word and other features + - generalize hu_HU specific compound word features with new affix file + parameters, suggested by Bram Moolenaar: + - CHECKCOMPOUNDDUP: forbid word duplication in compounds (eg. foo|foo) + - CHECKCOMPOUNDTRIPLE: forbid triple letters in compounds (eg. foo|obar) + - CHECKCOMPOUNDPATTERN: forbid patterns at word bounds in compounds + - CHECKCOMPOUNDREP: using REP replacement table, forbid presumably bad + compounds (useful for languages with unlimited number of compounds) + - ONLYINCOMPOUND flag works also with words (see tests/onlyincompound.*) + Suggested by Daniel Naber, Björn Jacke, Trón Viktor & Bram Moolenaar. + - PSEUDOROOT works also with prefixes and prefix + suffix combinations + (see tests/pseudoroot5.*). Suggested by Trón Viktor. + - man/hunspell.4: updated man page + + * src/hunspell/affixmgr.*: fix incomplete prefix handling with twofold + suffixes (delete unnecessary contclasses[] conditions in + prefix_check_twosfx() and prefix_check_twosfx_morph()). + Bug reported by Trón Viktor. + + * src/hunspell/affixmgr.*: complete also *_morph() functions with + conditions of new Hunspell features (circumfix, pseudoroot etc.). + + * src/hunspell/suggestmgr.cxx: + - fix missing suggestions for words with crossed prefix and suffix + - fix redundant non compound word checking + - fix losing suggestions problem. Bug reported by Dmitri Gabinski. + + * src/hunspell/dictmgr.*: + - add new dictionary manager for Hunspell UNO modul + Problems with eo_ANY Esperanto locale reported by Dmitri Gabinski. + + * src/hunspell/*: use precise constant sizes for 8-bit and 16-bit character + arrays with MAXWORDUTF8LEN and MAXSWUTF8L macros. + + * src/hunspell/affixmgr.cxx: fix bad MAXNGRAMSUGS parameter handling + + * src/hunspell/affixmgr.cxx, src/tools/{un}munch.*: fix GCC 4.0 warnings + on fgets(), reported by Dvornik László + + * po/hu.po: improved translation by Dvornik László + + * tests/test.sh: improved test environment + - add suggestion testing (see tests/*.sug) + - add memory debugging environment, based on the excellent Valgrind debugger. + Usage on Linux and experimental platforms of Valgrind: + VALGRIND=memcheck make check + - rename test_hunmorph to test.sh + + * tests/*: new tests: + - base.*: base example based on MySpell's checkme.lst. + - map{,utf}.*, rep{,utf}: MAP and REP suggestion examples + - tests on new CHECKCOMPOUND, ONLYINCOMPOUND and PSEUDOROOT features + - i54633.*: capitalized suggestion test for Issue 54633 from OOo's Issuezilla + - i35725.*: improved ngram suggestion test for Issue 35725 + +2005-08-26 Németh László : +improvements: + + * src/hunspell/suggestmgr.cxx: + Unicode support in related character map suggestion + + * src/hunspell/suggestmgr.cxx: Unicode support in ngram suggestion + + * src/hunspell/{suggestmgr,affixmgr,hunspell}.cxx: improve ngram suggestion. + Fix http://qa.openoffice.org/issues/show_bug.cgi?id=35725. See release + notes for examples. This problem reported by beccablain at OOo. + - ngram suggestions now are case insensitive (see `Permenant' bug in Issuezilla) + - weight ngram suggestions (with the longest common subsequent algorithm, + also considering lengths of bad word and suggestion, identical first + letters and almost completely identical character positions) + - set strict affix congruency in expand_rootword(). Now ngram suggestions + are good for languages with rich morphology and also better for English. + Rationale: affixed forms of the first ngram suggestion + very often suppress the second and subsequent root word suggestions. But + faults in affixes are more uncommon, and can be fix without suggestions. + We must prefer the more informative second and subsequent root word + suggestions instead of the suggestions for bad affixes. + - a better suggestion may not be substring of a less good suggestion + Rationale: Suggesting affixed forms of a root word is + unnecessary, when root word has got better weighted ngram value. + (Checking substrings is a good approximation for this refinement.) + - lesser ngram suggestions (default 3 maximum instead of 10) + Rationale: For users need a big extra effort to check a lot of bad ngram + suggestions, nine times out of ten unnecessarily. It is very + distracting, because ngram suggestions could be very different. + Usually Myspell and Hunspell suggest one or two suggestions with + the old suggestion algorithms (maximum is 15), with ngram algorithm + often gives maximum number suggestions. With strict affix congruency + and other refinements, the good suggestion there is usually among the + first three elements. + - new affix parameter: MAXNGRAMSUG + + * src/hunspell/*: support agglutinative languages with rich prefix + morphology or with right-to-left writing system (for example, Turkic + and Austronesian languages with (modified) Arabic scripts). + - new affix parameter: COMPLEXPREFIXES + Set twofold prefix stripping (but single suffix stripping) + * src/hunspell/affixmgr.cxx: + - speed up prefix loading with tree sorting algorithm. + * tests/complexprefixes.*, tests/complexprefixesutf.*: + Coptic example posted by Moheb Mekhaiel + + * src/hunspell/hashmgr.cxx: check size attribute in dic file + suggested by Daniel Naber + Rationale: With missing size attribute Hunspell allocates too small and + more slower hash memory, and Hunspell can lose first dictionary word. + + * src/hunspell/affixmgr.cxx: check stripping characters and condition + compatibility in affix rules (bugs detected in cs_CZ, es_ES, es_NEW, + es_MX, lt_LT, nn_NO, pt_PT, ro_RO and sk_SK dictionaries). See release + notes of Hunspell 1.0.9 in NEWS. + + * src/hunspell/affixmgr.cxx: check unnecessary fields in affix rules + (bugs detected in ro_RO and sv_SE dictionaries). See release notes. + + * src/hunspell/affixmgr.cxx: remove redundant condition checking + in affix rules with stripping characters (redundancy in OpenOffice.org + dictionaries reported by Eleonóra Goldman) + Rationale: this is a little optimization, but it was excellent for + detect the bad ngram affixation with bad or weak affix conditions. + + * tests/germancompounding.aff: improve compound definition + - use dash prefix instead of language specific tokenizer + Rationale: Using uniform approach is the right way to check and analyze + compound words. Language specific word breaking is deprecated, need + a sophisticated grammar checking for word-like word pairs + (for example in Hungarian there is a substandard, but accepted + syntax with dash for word pairs: cats, dogs -> kutyák-macskák (like + cats/dogs in English). + + * test Hunspell with 54 OpenOffice.org dictionaries: see release notes + +bug fixes: + + * src/hunspell/suggestmgr.*: add time limit to exponential + algorithm of the related character map suggestion + Rationale: a long word in agglutinative languages or a special pattern + (for example a horizontal rule) made of map characters can `crash' the + spell checker. + + * src/hunspell/affentry.cxx: add() functions: fix bad word generation + checking stripping characters (see similar bug in unmunch) + + * src/hunspell/affixmgr.cxx: parse_file(): fix unconditional getNext() + call for ~AffixMgr() when affix file is corrupt. + + * src/hunspell/affixmgr.*: AffixMgr(), parse_cpdsyllable(): fix missing + string duplications for ~AffixMgr() when affix file is corrupt. + + * src/hunspell/affixmgr.*: parse_affix(): fix fprintf() call when affix + file is corrupt. Bug reported by Daniel Naber. + + * suggestmgr.cxx: replace single usage of 'strdup' with 'mystrdup' + patch by Chris Halls (debian.org) + + * src/hunspell/makefile.mk: add makefile.mk for compiling in OpenOffice.org + See README in Hunspell UNO modul. + Problems with separated compiling reported by Rene Engelhard + + * src/hunspell/hunspell.cxx: fix pseudoroot support + - search a not pseudoroot homonym in check() + * tests/pseudoroot4.*: test this fix + + * src/tools/unmunch.c: fix bad word generation when conditions + are shorter or incompatible with stripping characters in affix rules + + * src/tools/unmunch.c: fix mychomp() for de_AT.dic and other dic files + without last new line character. + +other changes: + * src/hunspell/suggestmgr.*: erase ACCENT suggestion + Rationale: ACCENT suggestion was the same as Kevin Hendrick's map + suggestion algorithm, but with a less good interface in affix file. + + * src/hunspell/suggestmgr.*: combine cycle number limit + in badchar(), and forgotchar() with a time limit. + + * src/hunspell/affixmgr.*: remove NOMAPSUGS affix parameter + + * src/hunspell/{suggestmgr,hunspell}.*: strip periods from + suggestions (restore MySpell's original behaviour) + Rationale: OpenOffice.org has an automatic period handling mechanism + and suggestions look better without periods. + - new affix file parameter: SUGSWITHDOTS + Add period(s) to suggestions, if input word terminates in period(s). + (No need for OpenOffice.org dictionaries.) + + * tests/germancompounding.aff: improve bad german affix in affix example + (computeren->computern). Suggested by Daniel Naber. + + * src/tools/example.cxx: add Myspell's example + + * src/tools/munch.cxx: add Myspell's munch + + * man{,/hu}/hunspell.4: refresh manual pages + +2005-08-01 Németh László : + * add missing MySpell files and features: + - add MySpell license.readme, README and CONTRIBUTORS ({license,README,AUTHORS}.myspell) + - add MySpell unmunch program (src/tools/unmunch.c) + - add licenses to source (src/hunspell/license.{myspell,hunspell}) + - port MAP suggestion (with imperfect UTF-8 support) + - add NOSPLITSUGS affix parameter + - add NOMAPSUGS affix parameter + + * src/man/man.4: MAP, COMPOUNDPERMITFLAG, NOSPLITSUGS, NOMAPSUGS + + * src/hunspell/aff{entry,ixmgr}.cxx: + - improve compound word support + - new affix parameter: COMPOUNDPERMITFLAG (see manual) + * src/tests/compoundaffix{,2}.*: examples for COMPOUNDPERMITFLAG + * src/tests/germancompounding.*: new solution for German compounding + Problems with German compounding reported by Daniel Naber + + * src/hunspell/hunspell.cxx: fix German uppercase word spelling + with the spellsharps() recursive algorithm. + Default recursive depth is 5 (MAXSHARPS). + * src/tests/germansharps*: extended German sharp s tests + + * src/tools/hunspell.cxx: fix fatal memory bug in non-interactive + subshells without HOME environmental variable + Bug detected with PHP by András Izsók. + +2005-07-22 Németh László : + * src/hunspell/csutil.hxx: utf16_u8() + - fix 3-byte UTF-8 character conversion + +2005-07-21 Németh László : + * src/hunspell/csutil.hxx: hunspell_version() for OOo UNO modul + +2005-07-19 Németh László : + * renaming: + - src/morphbase -> src/hunspell + - src/hunspell, src/hunmorph -> src/tools + - src/huntokens -> src/parsers + + * src/tools/hunstem.cxx: add stemmer example + +2005-07-18 Németh László : + * configure.ac: --with-ui, --with-readline configure options + * src/hunspell/hunspell.cxx: fix conditional compiling + + * src/hunspell/hunspell.cxx: set HunSPELL.bak temporaly file + in the same dictionary with the checked file. + + * src/morphbase/morphbase.cxx: + + - handling German sharp s (ß) + + - fix (temporaly) analyize() + + * tests: a lot of new tests + + * po/, intl/, m4/: add gettext from GNU hello + + * po/hu.po: add Hungarian translation + + * doc/, man/: rename doc to man + +2005-07-04 Németh László : + * src/morphbase/hashmgr.cxx: set FLAG attributum instead of FLAG_NUM and FLAG_LONG + + * doc/hunspell.4: manual in English + +2005-06-30 Németh László : + * src/morphbase/csutil.cxx: add character tables from csutil.cxx of OOo 1.1.4 + + * src/morphbase/affentry.cxx: fix Unicode condition checking + + * tests/{,utf}compound.*: tests compounding + +2005-06-27 Németh László : + * src/morphbase/*: fix Unicode compound handling + +2005-06-23 Halácsy Péter: + * src/hunmorph/hunmorph.cxx: delete spelling error message and suggest_auto() call + +2005-06-21 Németh László : + * src/morphbase: Unicode support + * tests/utf8.*: SET UTF-8 test + + * src/morphbase: checking and fixing with Valgrind + Memory handling error reported by Ferenc Szidarovszky + +2005-05-26 Németh László : + * suggestmgr.cxx: fix stemming + * AUTHORS, COPYING, ChangeLog: set CC-LGPL free software license + +2004-05-25 Varga Dániel + * src/stemtool: new subproject + +2005-05-25 Halácsy Péter + * AUTHORS, COPYING: set CC Attribution license + +2004-05-23 Varga Dániel + * src: - modifications for compiling with Visual C++ + + * src/hunmorph/csutil.cxx: correcting header of flag_qsort(), + * src/hunmorph/*: correct csutil include + +2005-05-19 Németh László + * csutil.cxx: fix loop condition in lineuniq() + bug reported by Viktor Nagy (nagyv nyelvtud hu). + + * morphbase.cxx: handle PSEUDOROOT with zero affixes + bug reported by Viktor Nagy (nagyv nyelvtud hu). + * tests/zeroaffix.*: add zeroaffix tests + +2005-04-09 Németh László + * config.h.in: reset with autoheader + + * src/hunspell/hunspell.cxx: set version + +2005-04-06 Németh László + * tests: tests + + * src/morphbase: + New optional parameters in affix file: + - PSEUDOROOT: for forbidding root with not forbidden suffixed forms. + - COMPOUNDWORDMAX: max. words in compounds (default is no limit) + - COMPOUNDROOT: signs compounds in dictionary for handling special compound rules + - remove COMPOUNDWORD, ONLYROOT + +2005-03-21 Németh László + * src/morphbase/*: + - 2-byte flags, FLAG_NUM, FLAG_LONG + - CIRCUMFIX: signed suffixes and prefixes can only occur together + - ONLYINCOMPOUND for fogemorpheme (Swedish, Danish) or Flute-elements (German) + - COMPOUNDBEGIN: allow signed roots, and roots with signed suffix in begin of compounds + - COMPOUNDMIDDLE: like before, but middle of compounds + - COMPOUNDEND: like before, but end of compounds + - remove COMPOUNDFIRST, COMPOUNDLAST diff --git a/hunspell/ChangeLog.O b/hunspell/ChangeLog.O new file mode 100644 index 000000000..a2c712d73 --- /dev/null +++ b/hunspell/ChangeLog.O @@ -0,0 +1,524 @@ +Myspell has a lot of parallel development, that is not documented here. + +2005-01-11: Nmeth Lszl + * hunspell.cxx: + - interaktv javtsnl hinyz j sor karakterek ptlsa. + A hibt Gefferth Andrs s Khiraly jelezte. + * csutil.cxx: + - pontosvesszk trlse a GCC 3.4-es fordt ignyeinek megfelelen + A hibt Dvornik Lszl jelezte. + - i vltoz ismtelt deklarsnak trlse, ami helyenknt hibs + fordtst eredmnyez. + A hibt Ldoktor s Bencsth Boldizsr jelezte. + * OLVASS.EL: + - Windows alatti fordtsnl Langid.cxx mdostand. A hibt + Ldoktor jelezte. + +2004-12-15 Nmeth Lszl + * src/morphbase/*: + - handling K&R morphological encoding (remove plus signs from output) + - LEMMA_PRESENT: put only morphological description to output + - LANG parameter, langnum variable in source for writing language-dependent codes + - remove HU_KOTOHANGZO + - etc. + * doc/hunspell.4: + - adding some + +2004-09-29 Halcsy Pter + + * doc/ : bemsoltam a hunspell.1 hunspell.4 man oldalakat + * doc/hunspell.1: Kivettem a -s -m kapcsolkrl szl rszt + +2004-09-28 Halcsy Pter + + * src/hunspell/hunspell.cxx (indexing_interface): Ezt kiszedtem a + HunSpell-bol, mert nem ide valo. Ez egy kulon program lehet. + (main): a hunstem zemmdot is kidobtam, ez se ide val + (main): meg a hunmorph zemmdot is + + * src/morphbase/morphbase.cxx (MorphBase): tneveztem a MySpell + osztlyt MorphBase-re + (stems): tnevezten a suggest_stems metdust stem -re (mint to stem) + +2004-08-25 Nmeth Lszl + * src/hunbase/suggestmgr.cxx: tvezs visszalltsa, nem + mkdik mg az igektk hozztoldsa a thz, tovbb a + kivtelek kezelse (ehhez a 0.99.4-es sztr szksges mg). + * src/hunbase/myspell.cxx: -s vissza a tvezshez + * src/hunbase/atypes.hxx: HUNSTEM makr definilsa itt az + affixmgr.cxx feltteles kdjhoz + +2004-08-12 Halacsy Peter + * src/misc/lexfilter.cxx : uj program, ami a szotar szureshez hasznalhato + lecserelheti a mostani hunmorph, hunspell -G -1 funkciokat + + * src/hunbase/myspell.cxx (analyzer) : Uj metodust vettem fel, ami mar + karaktertombben adja vissza az elemzes eredmenyet + +2004-08-03 Halcsy Pter + + * src/hunspell/hunspell.cxx (HUNSPELL_VERSION): ttettem ide ennek definilst + +2004-07-31 Halcsy Pter + + * src/hunbase/suggestmgr.cxx (fixstems): A fixstems mirt itt van + s mirt gy hvjk. Ez mehetne egy kln osztlyba. + +2004-07-31 Halcsy Pter + + * src/huntoken/htmlparser.cxx: Egyebkent az include-ok kezelese + eleg zavaros. Peldaul itt minek a textparser.hxx includolasa? + + * src/huntoken/textparser.hxx (MAXLNLEN): thoztam ide a MAXLNLEN makrt + az atypes.hxx-bol, hogy a fuggoseget megszuntessem + + * src/hunbase/myspell.cxx (suggest): Kivettem azt a rszt, ami visszaadja a HUNSPELL_VERSION stringet + ha a VERSION_KEYWORD a bemeneti string. Csnya gnyolsnak tartottam + +2004-07-27 Halcsy Pter + + * src/hunbase/myspell.cxx (morph_with_correction): + + * src/hunbase/baseaffix.hxx (class AffEntry): Allandora felvettem a morphcode mezot (last htypes.hxx) + + * src/hunbase/affentry.hxx: Kivettem a hunmorph felteteleket (last htypes.hxx) + + * src/hunbase/htypes.hxx (struct hentry): Kivettem a HUNMORPH feltetelt a char* description korul. Ertem, + hogy hatekonyabb egy folosleges mutato nelkul, ha nincs morf info, de szerintem felesleges + + * src/hunbase/myspell.hxx: HUNSPELL_VERSION es VERSION_KEYWORD makrokat kivettem. Valamiert a + hunspellnek kell majd + + * src/hunbase/config.hxx (FLAG): config.hxx torolve, helyet atveszi a kozponti config.h; FLAG + definicioja az atypes.hxx-be ment + + * src/hunbase/atypes.hxx (FLAG): config.hxx megszuntetese erdekeben attettem ide a FLAG makro + definialasat, ami az EXT_CLASS-tol fugg + + config.hxx include kicserelve a configure altal kezelt config.h-ra + +2004-06-29: Nmeth Lszl + * affixmgr.cxx: + - csak utols tagknt megengedett szavak (compound3) toldalk + nlkli elfordulsnak engedlyezse (pl. macskapr) + - tbbszrsen sszetett szavak toldalkolt alakjainak morfolgiai + elemzse + * myspell.cxx: + - rvidtsek, szmok, ktjeles sszetett szavak s a + -e hatrozszt tartalmaz szavak morfolgiai elemzse + * suggestmgr.cxx: suggest_morph_for_spelling_error() optimalizlsa + (csak a felhasznlt egy javaslatot keresi meg, tbbet nem). + * csutil.cxx: kimenetben szerepl res sorok trlse + +2004-06-10: Nmeth Lszl + * suggestmgr.cxx: sszetett szavak elemzsnek korltozsa + - a tvezs mg nincs megvalstva a 0.9.9-es vltozatban + (helyette a Hunspell 0.9.7 hasznland a Magyar Ispell 0.99.4-es + vltozatval) + +2004-05-19: Nmeth Lszl + * 0.9.9f-alpha + + - morf. lers sztringkezelse jav. + - EXT_CLASS: config.cxx-ben + - nagybets alakok is elemezve (a hibt Tron Viktor jelezte) + - szebb kimenet + - rule119 trlve + - firstparser.cxx javtva + +2004-02-13: Nmeth Lszl + * 0.9.8a: + - MAXUSERWORD helyett USERWORD, nincs korlt + - description \t-vel dic fjlba + - homonimk kezelse + - aff formtumbvts + - konfixumok + - _morpho fggvnyek + - ketts szuffixum + - hunmorph + - lsd tests/hunmorph + +2004-01-29: Nmeth Lszl + * 0.9.7-sztaki: + - memriakezelsi hibk javtsa + +2003-12-17: Nmeth Lszl + * 0.9.7-es vltozat: + * affixmgr.cxx: + - suffix_check() javts (tmpword kivltsa isRevSubSet() + fggvnnyel + - betlts optimalizlsa, build_pfxlist() helyett: + - build_pfxtree() + - process_sfx_tree_to_list(), process_sfx_inorder() + + * csutil.cxx: + - isSubSet() gyorsabb vltozata + - isRevSubSet() + + * langid.cxx, hunp.cxx: + - nyelvfelismer osztly s program (l. man hunp) + * man/hunp.1: + - nyelvfelismer program lersa + + * firstparser.cxx: + - csak a tabultorjelet tartalmaz sorokbl a tabultorjel + eltti rszt adja vissza (l. man Hunspell, -1 kapcsol) + + * hunspell.cxx: + - -u, -U, -u2 kapcsolk: tipikus hibk kijelzse; + automatikus, illetve lektorlt javtsa. L. man hunspell. + + - -w kapcsol teljes sor vizsglathoz + + * hunspell.cxx: + - spell(): javts (Valgrind hibajelzs alapjn) + + * hunspell.cxx: sprintf()-ek el strlen() felttelvizsglat + + * suggestmgr.cxx: + - 0.99.4-es Hunspell sztrral bekerlt tvezsi hiba + javtsa (nem produktv ragozs, sszetett szbam szerepl + fneveknl lpett fel ez a problma). + + * OLVASS.EL: + - bvts + +2003-11-03: Nmeth Lszl + * SuggestMgr::permute_accent(): + - illeglis memriaolvassi hiba javtsa. + * example.cxx:: + - dupla free() a "" karakterlnc tvezse utn + + A hibkat Sarls Tams + fedezte fel a figyelemre mlt Valgrind nyomkvet + programmal (http://developer.kde.org/~sewardj/) + +2003-10-22: Bencsth Boldizsr + * affixmgr.[ch]xx, csutil.[ch]xx: Az eredeti + MySpell foltjainak alkalmazsa az OpenOffice.org 1.1 + kompatibilits rdekben. Itt karakterkezel + segdfggvnyek lettek thelyezve elrhetbb helyre. + + * dictmgr.[ch]xx: Itt etype paramter hozzadsa. + + * makefile.mk: Itt angol sztrak megjegyzsbe ttele. + +2003-10-04: Nmeth Lszl + * 0.9.6.3-as vltozat: + * myspell.cxx: suggest() fggvnyben hibs + memriafoglals javtsa. A hiba a pontra vgzd + helytelen szavakra adott javaslattevs sorn + jelentkezett. A hibs mkdst Khiraly + jelezte. + +2003-09-15: Nmeth Lszl + * 0.9.6.2-es vltozat: + * latexparser.cxx: TeX elemz javtsa: + - elemzsi hiba ({{}}}) + - verb+ +, \verb stb. kezelse + +2003-09-01: Nmeth Lszl + * 0.9.6-os vltozat: + + * affentry.cxx: check2 trlse, lehetsges + tvek trolsa + * suggestmgr.cxx, myspell.cxx: suggest_pos_stems() + az ismeretlen szavak nvszragjainak s + jeleinek levlasztsra. + + * affixmgr.cxx, suggestmgr.cxx: suggest_stems() + szlkezelshez mdostott s javtott fggvny + + * myspell.cxx: szmok tvezse (teszt: 5-nek) + + * myspell.cxx: egy karakter + sz javaslatok + trlse (pldul cpak->cpa k) + + * affixmgr.cxx, myspell.cxx, hunspell.cxx: sztr + verziszmnak kirsa + + * hunspell.cxx: \r karaktert tartalmaz sorok + helyes megjelentse + + * myspell.cxx, hunspell.cxx: rvidts vgi pontok + hozzadsa fggvnyknyvtr szinten + + * hunspell.cxx: pipe_interface(): standard bemenet + tvezsnl hinyz memriafelszabadts ptlsa + + * Makefile: install javtsa, tbb felttelvizsglat + deinstall szakasz + +2003-07-22: Nmeth Lszl + * 0.9.5-s vltozat + * suggestmgr.cxx: marhalevl->lelevl tvezs javtsa + * myspell.cxx: nagy kezdbets rvidtsek vizsglata (Bp., Btk.) + - pontot tartalmaz szmok helyesnek val elfogadsa, ha: + - az els pontot legalbb egy, + - de legfeljebb hrom szmjegy elzi meg, + - a pontok nem egyms mellett helyezkednek el, + - az utols pont utn legfeljebb kt szmjegy van. + Ezzel elfogadjuk az idpontokat (12.00-kor), a pontozsokat + (1.1.2-ben), de kizrjuk a szkz nlkli hibs dtummegadsokat + (2003.7.22.), valamint a tizedesvessz helyett ponttal rt + tizedestrteket (3.456, 4563.34). + - Javts a tiltott szavakra adott ktjeles javaslatoknl: + Straussal->Strauss-szal, s nem ,,Strauss szal''. + * hunspell.cxx: csak a -a kapcsol megadsval lnek a + csfelleti parancsok. Ezrt most mr nincsenek figyelmen + kvl hagyva pldul a ktjellel kezdd sorok, ha a -l + kapcsolval hibs szavakat keresnk egy llomnyban. + * man/hunspell.1: a -a kapcsol lersnak kiegsztse. + +2003-06-13: Nmeth Lszl + * 0.9.4-es vltozat + * bin/*: makedb, lookdb segdprogramok az indexelshez + * man/*: hunstem, makedb, lookdb + * hunspell.cxx: pipe_interface: nyomkvet kirs trlse + - LOG #ifdef-be + +2003-06-11: Nmeth Lszl + * 0.9.3-es vltozat + * suggestmgr.cxx: nagybets javaslat tulajdonneveknl + * hunspell.cxx: pipe_interface: hiba javtsa + +2003-06-05: Nmeth Lszl + * 0.9.2-es vltozat + * hunspell.cxx: -s kapcsol + * suggestmgr.cxx: suggest_stems() + Sztvek ellltsa + * example.cxx: plda a sztvek ellltsra + +2003-05-13: Nmeth Lszl + * 0.9.1-es vltozat + * hunspell.cxx: + - rl_escape(), stb.: a readline sorban ki lett kapcsolva + a fjlnv-kiegszts, s helyette a kt Escape lenyoms + megszaktja a szvegbevitelt. A Csere mveletnl is a + readline() hvs tallhat most mr. + - egy hibs sprintf() sor javtva lett + * Makefile.unix: + - belltsok elklntve az llomny elejn + - Makefile most mr szimblikus kts + * ooomagyarispellteszt.txt: tesztllomny + +2003-04-28: Nmeth Lszl + * affixmgr.cxx: + - y vg szavak kezelse: bvebb lers a + Magyar Ispell Changelog llomnyban. + + * *parser.cxx: + ISO-8859-1 HTML karakterentitsok kzl a betrtkek + (csak az ISO-8859-2-ben nem szereplk) felismerse + s kezelse. + +2003-04-21: Goldman Elenonra + * *.dll fggvnyknyvtr ellltsa Windows alatt: + - StdAfx.h + - libmyspell.def + - dlltest.cpp + +2003-04-16: Nmeth Lszl + * Hunspell.cxx, stb: a Mispell tnevezse Hunspell-l. + A nevet Kornai Andrs javasolta. + Knyvtrak: /usr/share/mispell -> /usr/share/myspell + (korbban is ez volt). + A /usr/share/hunmorph sztr a helye a specilis + morfolgiai informcikat tartalmaz Hunmorph (bvtett + Myspell sztrformtum) sztrllomnyoknak. + * Licenc: LGPL + * config.hxx: SZOSZABLYA_POSSIBLE_ROOTS + Ha a makrt bekapcsoljuk, akkor kirsra kerlnek + a lehetsges tvek is, az alkalmazott ragozsi szably + osztlynak betjelvel, illetve az alapszval egytt. + +2003-04-10: Nmeth Lszl : + * affixmgr.cxx: + - kthangzk helyes kezelse (hu_kotohangzo kapcsolval), + l. mg Magyar Ispell Changelog + +2003-03-24: Nmeth Lszl + * mispell.cxx: pipe_interface(): az adatfjl szrsnl fellp + memriaszivrgs megszntetse a kimaradt free(token) ptlsval + * affixmgr.cxx: prefix_check(): leg-, legesleg- confixum ellenrzs + - onlyroot kapcsol a csak tszt rint tiltshoz. L. Magyar Ispell + Az affixum llomnyban j kapcsolt adhatunk meg az + ONLYROOT paranccsal bevezetve. A kapcsol mdostja a tiltkapcsol + mkdst. L. man 4 mispell + * myspell.cxx: + - spell(): nagybets tulajdonnevek ellenrzse (pl. BALATON) + - onlyroot vizsglat forbiddenword mellett -> mangrove kezelse + +2003-03-17: Goldman Elenonra + * Windows port + * makefile.Windows: + +2003-03-04: Nmeth Lszl + * firstparser.[ch]xx: adatfjlok szrshez (l. -1 kapcsol) + * mispell.cxx: -L, -1, -G kapcsolk + * man/mispell.1: -L, -1, -G kapcsolk + +2003-03-03: Nmeth Lszl + * mispell.cxx: -l, -p, WORDLIST + * man/mispell.1: -l, -p, WORDLIST + +2003-02-26: Nmeth Lszl + * mispell.cxx: dialog_screen(): + TILTOTT! (FORBIDDEN!) megjelentse a tiltott szsszettelek + esetn. + * suggestmgr.cxx: + - check(): -, - kpzs igeneveket rint kd trlse + - check_forbidden(): a 6 sztagnl hosszabb, tiltott sztvekre + vonatkoz javaslatok nem ktjellel, hanem szkzzel elvlasztva + tartalmazzk a szavakat, ehhez szksges a check_forbidden(). + * man/*: j kziknyv oldal az llomnyok formtumrl (mispell(4)), + a mispell(1) bvtse. + * Makefile, mispell.mo: Br rpd javtsai + +2003-02-18: Nmeth Lszl + * mispell.cxx: interactive_interface() + - nem nyeli el a MAXLNLEN-t meghalad mret sorokban a MAXLNLEN + mret rszek hatrn lv karaktereket, s a nem jsor karakterre + vgzd llomnyok utols karaktert. (Hibt viszont mg mindig + jelez, ha a MAXLNLEN hatr feldarabol egy amgy helyes szt.) + A MAXLNLEN 8192 karakter jelenleg. + - readline fggvnyknyvtr hasznlata a bevitelnl + - tfelvtelnl egy lehetsges t ellltsa, s a beviteli + sorban val feltntetse. Az gy megjelen sz javthat. + - --help kapcsol + * Makefile: Javtsok az install szakaszban. + A hibkat Br rpd jelezte. + +2003-02-07: Nmeth Lszl + * mispell.cxx: put_dots_to_suggestions() + - realloc() cserje malloc()-ra ismeretlen eredet lefagys miatt. + - lehetsges az Ispellhez hasonlan a kapcsolkat kzzel megadni a + sajt sztrban a szavak utn egy perjelet kveten: pldul a + valamicsnyasz/w + sor megadsa utn a valamicsnyasz s toldalkolt vltozatai hibsak + lesznek az ellenrzs alatt. (Tovbbi kapcsolk lersrt lsd a + Magyar Ispell forrsban az aff/aff.fej llomnyt.) + * affixmgr.cxx: compound_check() + - repl_chars() hvsa a megfelel helyre lett tve, ezzel a + javaslattevs sebessge ktszeresre ntt. + - A dinamikus memriakezels lecserelse veremmemrira nem jrt + lnyeges sebessgnvekedssel, de a kzeljvben ezzel elkerlhet + az a memriaszivrgs, ami pldul itt a tiltott szavak kezelsnl + volt az elz vltozatban (javtva). + * affentry.cxx, affixmgr.cxx: szt-elllt kd megalapozsa: + get_possible_root() metdus az utols toldalk-levlaszts + eredmnyvel tr vissza. + +2003-02-05: Nmeth Lszl + * mispell.cxx: put_dots_to_suggestions(): amennyiben + a felismert sz pontra, vagy pontokra vgzdik, a + javaslatokat is bvti ezzel. + - @, valamint 1-nl tbb pontot magba foglal (de nem arra vgzd) + szavak ellenrzsnek tiltsa (e-mail, fjlnevek, mg nem opcionlis). + - Hossz sorok helyes megjelentse. + - Tabultorjelet tartalmaz sorok helyes megjelentse. + - Mozaikszavak tfelvtelnl ktjeles alak automatikus rgztse + Pl.: BKV//URH mellett BKV-//URH- is bekerl a sajt sztrba + (a ragozott mozaikszavak felismerse teht automatikus lesz, kivve a + nem trivilis -val/-vel toldalkos alakok, amit kln kell felvenni.) + - PuT trlse (helyette MySpell::put_word(), put_word_suffix(), + put_word_pattern() eljrsok a sajt sztr bvtsre) + - dupla szavak ellenrzsnek trlse a MySpell kdbl (thelyezs majd a + Mispell felletbe), hogy a MySpell meghvhat maradjon prhuzamosan + fut szlakbl. + +2002-12-30: Nmeth Lszl + * *parser.cxx, *parser.hxx: elemz osztlyok a rgi s csnya kd helyett + +2002-12-10: Nmeth Lszl + * myspell.cxx: 35-os, 20%-kal kezelse + * man/mispell.1: kziknyv + +2002-12-04: Noll Jnos + * spdaemon/: kiszolgl fellet, ld. README.spdaemon + +2002-12-04: Nmeth Lszl + * mispell.cxx: Emacs kompatibilitshoz hibk javtsa (pl. tbbszrs -d) + * mispell.cxx: CURSES makrval kikapcsolhat az interaktv fellet + locale + (Windows, Macintosh) + +2002-11-30: Nmeth Lszl + * affixmgr.cxx: get_checkdoublewords() + +2002-11-25: Nmeth Lszl + * affixmgr.cxx: mozgszably (hu_mov_rule) + * myspell.cxx: mozgszably + * affixmgr.cxx: kitljnekmacskt (affix is sszetettben, ha prefix) + +2002-11-08 Nmeth Lszl + * myspell.cxx: balatonnak->Balatonnak, balatoninak + +2002-11-07 Nmeth Lszl + * myspell: 0.6-os vltozat + +2002-10-31 Nmeth Lszl + * Egyszerbb nv: Magyar MySpell 0.5 utn -> MIspell 0.6 + * mispell.cxx: tbbnyelv interaktv fellet (ncurses, locale) + * Makefile: make install + +2002-09-22 Nmeth Lszl + * affixmgr.cxx: compound_check() macskaugom->macskaugrom, stb. javtsa + * affixmgr.cxx: compound_check() szismtls (pl. macskamacska) tiltsa + * myspell.cxx: szismtlds tiltsa (pl. kutya kutya) msodik rossz + * suggestmgr.cxx: macskarat->macska rat mellett ->macskairat + +2002-07-29 Nmeth Lszl + * mispell Windowsra, teszt Emacs-szel (vagy Emacs-csal) + * tiltott szavakat nem javasol, s sszetett szban sem fogad el + * fonev_morfo, fonev_morfo2 lsztvek elutastsa (hzakmacska) + * ktjeles szavak kezelse + * szmok kezelse, ktjeles alakjaikkal egytt, CHECKNUM kapcsol + +2002-07-17 Nmeth Lszl + * mispell.cxx: MySpell Ispell cs interfsz + +2002-07-04 Nmeth Lszl + * mispell.cxx: MySpell Ispell cs interfsz + * affxmgr.cxx: szszer kiszrse, + * j funkcik: + COMPOUNDFIRST: sz szerepelhet els tagknt a szszettelekben + COMPOUNDLAST: sz szerepelhet utols tagknt a szszettelekben + FORBIDDENWORD: tiltott szavak kapcsolja (ut, uta, stb.) + +2002-06-25 Nmeth Lszl + * myspell.cxx, suggestmgr.cxx: get_compound() char* helyett char + * affxmgr.cxx: check_repl() a helyesnek tn, de hibs sszetett + szavak kiszrsre (pl. tejles, szervz) + A szsszettel elfogadsa eltt mg megnzzk, hogy a sz + nem-e a cseretblzatban felvett hibt tartalmaz, + ha igen, akkor a sz hibsnak minsl, hiba helyes szsszettel. + * affxmgr.cxx, suggestmgr.xx: accent: kezetest. + Lers: README.accent + Tovbbi optimalizci: az kezet nlkli bet kezetes + vltozatai szmnak fggvnyben + +2002-06-05 Noll Jnos + * myspell.cxx, suggestmgr.cxx: mem. szivrgs javtsa + (a get_compound() felszabadts nlkl lett meghva). + A hiba a GNU mtrace segtsgvel lett detektlva. + +2002-06-03 Nmeth Lszl + * Licenc: GPL + * Lsd MYSPELL.HU + * compound_check: 6-3 szably, stb. + +MySpell: + +2002-xx-xx Kevin Hendricks + * REP: ismtlsek kiszrse a javaslatokbl + * COMPOUNDMIN + +2002-xx-xx Nmeth Lszl + * REP cseretblzat + * COMPOUND, szsszettelkpzs + +2002-xx-xx David Einstein + * optimalizlt MySpell algoritmus + +2001-xx-xx Kevin Hendricks + * Mkd ellenrz, Ispell toldalktmrtsi algoritmussal diff --git a/hunspell/INSTALL b/hunspell/INSTALL new file mode 100644 index 000000000..54caf7c19 --- /dev/null +++ b/hunspell/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/hunspell/NEWS b/hunspell/NEWS new file mode 100644 index 000000000..befdaa09b --- /dev/null +++ b/hunspell/NEWS @@ -0,0 +1,502 @@ +2007-11-01: Hunspell 1.2.1 release: + - new memory efficient condition checking algorithm for affix rules + + - new morphological functions: + - stem() for stemming + - analyze() for morphological analysis + - generate() for morphological generation + + - new demos: + - analyze: stemming, morphological analysis and generation + - chmorph: morphological conversion of texts + +2007-09-05: Hunspell 1.1.12 release: + - dictionary based phonetic suggestion for words with + special or foreign pronounciation or alternative (bad) transliteration + (see Changelog, tests/phone.* and manual). + + - improved data structure and memory optimization for dictionaries + with variable count fields + + - bug fixes for Unicode encoding dictionaries and ngram suggestions + + - improved REP suggestions with space: it works without dictionary + modification + + - updated and new project files for Windows API + +2007-08-27: Hunspell 1.1.11 release: + - portability fixes + +2007-08-23: Hunspell 1.1.10 release: + - pronounciation based suggestion using Bjrn Jacke's original Aspell + phonetic transcription algorithm (http://aspell.net), relicensed under + GPL/LGPL/MPL tri-license with the permission of the author + + - keyboard base suggestion by KEY (see manual) + + - better time limits for suggestion search + + - test environment for suggestion based on Wikipedia data + + - bug fixes for non standard Mozilla platforms etc. + +2007-07-25: Hunspell 1.1.9 release: + - better tokenization: + - for URLs, mail addresses and directory paths (default: skip these tokens) + - for colons in words (for Finnish and Swedish) + + - new examples: + - affixation of personal dictionary words + - digits in words + + - bug fixes (see ChangeLog) + +2007-07-16: Hunspell 1.1.8 release: + - better Mac OS X/Cygwin and Windows compatibility + + - fix Hunspell's Valgrind environment and memory handling errors + detected by Valgrind + + - other bug fixes (see ChangeLog) + +2007-07-06: Hunspell 1.1.7 release: + - fix warning messages of OpenOffice.org build + +2007-06-29: Hunspell 1.1.6 release: + - check capitalization of the following word forms + - words with mixed capitalisation: OpenOffice.org - OPENOFFICE.ORG + - allcap words and suffixes: UNICEF's - UNICEF'S + - prefixes with apostrophe and proper names: Sant'Elia - SANT'ELIA + + - suggestion for missing sentence spacing: something.The -> something. The + + - Hunspell executable: improved locale support + - -i option: custom input encoding + - use locale data for default dictionary names. + - tools/hunspell.cxx: fix 8-bit tokenization (letters without + casing, like ß or Hebrew characters now are handled well) + - dictionary search path (automatic detection of OpenOffice.org directories) + - DICPATH environmental variable + - -D option: show directory path of loaded dictionary + + - patches and bug fixes for Mozilla, OpenOffice.org. + +2007-03-19: Hunspell 1.1.5 release: + - optimizations: 10-100% speed up, smaller code size and memory footprint + (conditional experimental code and warning messages) + + - extended Unicode support: + - non BMP Unicode characters in dictionary words and affixes (except + affix rules and conditions) + - support BOM sequence in aff and dic files + + - IGNORE feature for Arabic diacritics and other optional characters + + - New edit distance suggestion methods: + - capitalisation: nasa -> NASA + - long swap: permenant -> permanent + - long move: Ghandi -> Gandhi, greatful -> grateful + - double two characters: vacacation -> vacation + - spaces in REP sug.: REP alot a_lot (NOTE: "a lot" must be a dictionary word) + + - patches and bug fixes for Mozilla, OpenOffice.org, Emacs, MinGW, Aqua, + German and Arabic language, etc. + +2006-02-01: Hunspell 1.1.4 release: + - Improved suggestion for typical OCR bugs (missing spaces between + capitalized words). For example: "aNew" -> "a New". + http://qa.openoffice.org/issues/show_bug.cgi?id=58202 + + - tokenization fixes (fix incomplete tokenization of input texts on big-endian + platforms, and locale-dependent tokenization of dictionary entries) + +2006-01-06: Hunspell 1.1.3.2 release: + - fix Visual C++ compiling errors + +2006-01-05: Hunspell 1.1.3 release: + - GPL/LGPL/MPL tri-license for Mozilla integration + + - Alias compression of flag sets and morphological descriptions. + (For example, 16 MB Arabic dic file can be compressed to 1 MB.) + + - Improved suggestion. + + - Improved, language independent German sharp s casing with CHECKSHARPS + declaration. + + - Unicode tokenization in Hunspell program. + + - Bug fixes (at new and old compound word handling methods), etc. + +2005-11-11: Hunspell 1.1.2 release: + + - Bug fixes (MAP Unicode, COMPOUND pattern matching, ONLYINCOMPOUND + suggestions) + + - Checked with 51 regression tests in Valgrind debugging environment, + and tested with 52 OOo dictionaries on i686-pc-linux platform. + +2005-11-09: Hunspell 1.1.1 release: + + - Compound word patterns for complex compound word handling and + simple word-level lexical scanning. Ideal for checking + Arabic and Roman numbers, ordinal numbers in English, affixed + numbers in agglutinative languages, etc. + http://qa.openoffice.org/issues/show_bug.cgi?id=53643 + + - Support ISO-8859-15 encoding for French (French oe ligatures are + missing from the latin-1 encoding). + http://qa.openoffice.org/issues/show_bug.cgi?id=54980 + + - Implemented a flag to forbid obscene word suggestion: + http://qa.openoffice.org/issues/show_bug.cgi?id=55498 + + - Checked with 50 regression tests in Valgrind debugging environment, + and tested with 52 OOo dictionaries. + + - other improvements and bug fixes (see ChangeLog) + +2005-09-19: Hunspell 1.1.0 release + +* complete comparison with MySpell 3.2 (from OpenOffice.org 2 beta) + +* improved ngram suggestion with swap character detection and + case insensitivity + +------ examples for ngram improvement (input word and suggestions) ----- + +1. pernament (instead of permanent) + +MySpell 3.2: tournaments, tournament, ornaments, ornament's, ornamenting, ornamented, + ornament, ornamentals, ornamental, ornamentally + +Hunspell 1.0.9: ornamental, ornament, tournament + +Hunspell 1.1.0: permanent + +Note: swap character detection + + +2. PERNAMENT (instead of PERMANENT) + +MySpell 3.2: - + +Hunspell 1.0.9: - + +Hunspell 1.1.0: PERMANENT + + +3. Unesco (instead of UNESCO) + +MySpell 3.2: Genesco, Ionesco, Genesco's, Ionesco's, Frescoing, Fresco's, + Frescoed, Fresco, Escorts, Escorting + +Hunspell 1.0.9: Genesco, Ionesco, Fresco + +Hunspell 1.1.0: UNESCO + + +4. siggraph's (instead of SIGGRAPH's) + +MySpell 3.2: serigraph's, photograph's, serigraphs, physiography's, + physiography, digraphs, serigraph, stratigraphy's, stratigraphy + epigraphs + +Hunspell 1.0.9: serigraph's, epigraph's, digraph's + +Hunspell 1.1.0: SIGGRAPH's + +--------------- end of examples -------------------- + +* improved testing environment with suggestion checking and memory debugging + + memory debugging of all tests with a simple command: + + VALGRIND=memcheck make check + +* lots of other improvements and bug fixes (see ChangeLog) + + +2005-08-26: Hunspell 1.0.9 release + +* improved related character map suggestion + +* improved ngram suggestion + +------ examples for ngram improvement (O=old, N = new ngram suggestions) -- + +1. Permenant (instead of Permanent) + +O: Endangerment, Ferment, Fermented, Deferment's, Empowerment, + Ferment's, Ferments, Fermenting, Countermen, Weathermen + +N: Permanent, Supermen, Preferment + +Note: Ngram suggestions was case sensitive. + +2. permenant (instead of permanent) + +O: supermen, newspapermen, empowerment, endangerment, preferments, + preferment, permanent, preferment's, permanently, impermanent + +N: permanent, supermen, preferment + +Note: new suggestions are also weighted with longest common subsequence, +first letter and common character positions + +3. pernemant (instead of permanent) + +O: pimpernel's, pimpernel, pimpernels, permanently, permanents, permanent, + supernatant, impermanent, semipermanent, impermanently + +N: permanent, supernatant, pimpernel + +Note: new method also prefers root word instead of not +relevant affixes ('s, s and ly) + + +4. pernament (instead of permanent) + +O: tournaments, tournament, ornaments, ornament's, ornamenting, ornamented, + ornament, ornamentals, ornamental, ornamentally + +N: ornamental, ornament, tournament + +Note: Both ngram methods misses here. + + +5. obvus (instad of obvious): + +O: obvious, Corvus, obverse, obviously, Jacobus, obtuser, obtuse, + obviates, obviate, Travus + +N: obvious, obtuse, obverse + +Note: new method also prefers common first letters. + + +6. unambigus (instead of unambiguous) + +O: unambiguous, unambiguity, unambiguously, ambiguously, ambiguous, + unambitious, ambiguities, ambiguousness + +N: unambiguous, unambiguity, unambitious + + + +7. consecvence (instead of consequence) + +O: consecutive, consecutively, consecutiveness, nonconsecutive, consequence, + consecutiveness's, convenience's, consistences, consistence + +N: consequence, consecutive, consecrates + + +An example in a language with rich morphology: + +8. Misisipiben (instead of Mississippiben [`in Mississippi' in Hungarian]): + +O: Misikdiben, Pisisediben, Misikiiben, Pisisekiben, Misikiben, + Misikidiben, Misikkiben, Misikikiben, Misikimiben, Mississippiiben + +N: Mississippiben, Mississippiiben, Misiiben + +Note: Suggesting not relevant affixes was the biggest fault in ngram + suggestion for languages with a lot of affixes. + +--------------- end of examples -------------------- + +* support twofold prefix cutting + +* lots of other improvements and bug fixes (see ChangeLog) + +* test Hunspell with 54 OpenOffice.org dictionaries: + +source: ftp://ftp.services.openoffice.org/pub/OpenOffice.org/contrib/dictionaries + +testing shell script: +------------------------------------------------------- +for i in `ls *zip | grep '^[a-z]*_[A-Z]*[.]'` +do + dic=`basename $i .zip` + mkdir $dic + echo unzip $dic + unzip -d $dic $i 2>/dev/null + cd $dic + echo unmunch and test $dic + unmunch $dic.dic $dic.aff 2>/dev/null | awk '{print$0"\t"}' | + hunspell -d $dic -l -1 >$dic.result 2>$dic.err || rm -f $dic.result + cd .. +done +-------------------------------------------------------- + +test result (0 size is o.k.): + +$ for i in *_*/*.result; do wc -c $i; done +0 af_ZA/af_ZA.result +0 bg_BG/bg_BG.result +0 ca_ES/ca_ES.result +0 cy_GB/cy_GB.result +0 cs_CZ/cs_CZ.result +0 da_DK/da_DK.result +0 de_AT/de_AT.result +0 de_CH/de_CH.result +0 de_DE/de_DE.result +0 el_GR/el_GR.result +6 en_AU/en_AU.result +0 en_CA/en_CA.result +0 en_GB/en_GB.result +0 en_NZ/en_NZ.result +0 en_US/en_US.result +0 eo_EO/eo_EO.result +0 es_ES/es_ES.result +0 es_MX/es_MX.result +0 es_NEW/es_NEW.result +0 fo_FO/fo_FO.result +0 fr_FR/fr_FR.result +0 ga_IE/ga_IE.result +0 gd_GB/gd_GB.result +0 gl_ES/gl_ES.result +0 he_IL/he_IL.result +0 hr_HR/hr_HR.result +200694989 hu_HU/hu_HU.result +0 id_ID/id_ID.result +0 it_IT/it_IT.result +0 ku_TR/ku_TR.result +0 lt_LT/lt_LT.result +0 lv_LV/lv_LV.result +0 mg_MG/mg_MG.result +0 mi_NZ/mi_NZ.result +0 ms_MY/ms_MY.result +0 nb_NO/nb_NO.result +0 nl_NL/nl_NL.result +0 nn_NO/nn_NO.result +0 ny_MW/ny_MW.result +0 pl_PL/pl_PL.result +0 pt_BR/pt_BR.result +0 pt_PT/pt_PT.result +0 ro_RO/ro_RO.result +0 ru_RU/ru_RU.result +0 rw_RW/rw_RW.result +0 sk_SK/sk_SK.result +0 sl_SI/sl_SI.result +0 sv_SE/sv_SE.result +0 sw_KE/sw_KE.result +0 tet_ID/tet_ID.result +0 tl_PH/tl_PH.result +0 tn_ZA/tn_ZA.result +0 uk_UA/uk_UA.result +0 zu_ZA/zu_ZA.result + +In en_AU dictionary, there is an abbrevation with two dots (`eqn..'), but +`eqn.' is missing. Presumably it is a dictionary bug. Myspell also +haven't accepted it. + +Hungarian dictionary contains pseudoroots and forbidden words. +Unmunch haven't supported these features yet, and generates bad words, too. + +* check affix rules and OOo dictionaries. Detected bugs in cs_CZ, +es_ES, es_NEW, es_MX, lt_LT, nn_NO, pt_PT, ro_RO, sk_SK and sv_SE dictionaries). + +Details: +-------------------------------------------------------- +cs_CZ +warning - incompatible stripping characters and condition: +SFX D us ech [^ighk]os +SFX D us y [^i]os +SFX Q os ech [^ghk]es +SFX M o ech [^ghkei]a +SFX J m ej m +SFX J m ejme m +SFX J m ejte m +SFX A ouit up oupit +SFX A ouit upme oupit +SFX A ouit upte oupit +SFX A nout l [aeiouyr][^aeiouyrl][^aeiouy +SFX A nout l [aeiouyr][^aeiouyrl][^aeiouy + +es_ES +warning - incompatible stripping characters and condition: +SFX W umar se [ae]husar +SFX W emir iis eir + +es_NEW +warning - incompatible stripping characters and condition: +SFX I unan nen unar + +es_MX +warning - incompatible stripping characters and condition: +SFX A a ote e +SFX W umar se [ae]husar +SFX W emir iis eir + +lt_LT +warning - incompatible stripping characters and condition: +SFX U ti siuosi tis +SFX U ti siuosi tis +SFX U ti siesi tis +SFX U ti siesi tis +SFX U ti sis tis +SFX U ti sis tis +SFX U ti sims tis +SFX U ti sims tis +SFX U ti sits tis +SFX U ti sits tis + +nn_NO +warning - incompatible stripping characters and condition: +SFX D ar rar [^fmk]er +SFX U re orde ere +SFX U re ort ere + +pt_PT +warning - incompatible stripping characters and condition: +SFX g os oas o +SFX g os oas o + +ro_RO +warning - bad field number: +SFX L 0 le [^cg] i +SFX L 0 i [cg] i +SFX U 0 i [^i] ii +warning - incompatible stripping characters and condition: +SFX P l i l [<- there is an unnecessary tabulator here) +SFX I a ii [gc] a +warning - bad field number: +SFX I a ii [gc] a +SFX I a ei [^cg] a + +sk_SK +warning - incompatible stripping characters and condition: +SFX T a ol kla +SFX T a olc kla +SFX T sa l sla +SFX T sa lc sla +SFX R c liem c +SFX R is tie mias +SFX R iez iem [^i]ez +SFX R iez ie [^i]ez +SFX R iez ie [^i]ez +SFX R iez eme [^i]ez +SFX R iez ete [^i]ez +SFX R iez [^i]ez +SFX R iez c [^i]ez +SFX R iez z [^i]ez +SFX R iez me [^i]ez +SFX R iez te [^i]ez + +sv_SE +warning - bad field number: +SFX C 0 net nets [^e]n +-------------------------------------------------------- + +2005-08-01: Hunspell 1.0.8 release + +- improved compound word support +- fix German S handling +- port MySpell files and MAP feature + +2005-07-22: Hunspell 1.0.7 release + +2005-07-21: new home page: http://hunspell.sourceforge.net diff --git a/hunspell/README b/hunspell/README new file mode 100644 index 000000000..a71850173 --- /dev/null +++ b/hunspell/README @@ -0,0 +1,132 @@ +About Hunspell +-------------- + +Hunspell is a spell checker and morphological analyzer library and program +designed for languages with rich morphology and complex word compounding or +character encoding. Hunspell interfaces: Ispell-like terminal interface +using Curses library, Ispell pipe interface, OpenOffice.org UNO module. + +Hunspell's code base comes from the OpenOffice.org MySpell +(http://lingucomponent.openoffice.org/MySpell-3.zip). See README.MYSPELL, +AUTHORS.MYSPELL and license.myspell files. +Hunspell is designed to eventually replace Myspell in OpenOffice.org. + +Main features of Hunspell spell checker and morphological analyzer: + +- Unicode support (affix rules work only with the first 65535 Unicode characters) + +- Morphological analysis (in custom item and arrangement style) + +- Max. 65535 affix classes and twofold affix stripping (for agglutinative + languages, like Azeri, Basque, Estonian, Finnish, Hungarian, Turkish, etc.) + +- Support complex compoundings (for example, Hungarian and German) + +- Support language specific features (for example, special casing of + Azeri and Turkish dotted i, or German sharp s) + +- Handle conditional affixes, circumfixes, fogemorphemes, + forbidden words, pseudoroots and homonyms. + +- Free software (LGPL, GPL, MPL tri-license) + +Compiling +--------- + +./configure +make +make install + +For dictionary development, use the --with-warnings option of configure. + +For compiling morphological analyser and stemmer code and tools, use the +--with-experimental option of configure. + +For interactive user interface of Hunspell executable, use the --with-ui option. + +The developer packages you need to compile Hunspell's interface: + +glibc-devel + +optional developer packages: + +ncurses (need for --with-ui) +readline (for fancy input line editing, + configure parameter: --with-readline) +locale and gettext (but you can also use the + --with-included-gettext configure parameter) + +Hunspell distribution uses new Autoconf (2.59) and Automake (1.9). + +Testing +------- + +Testing Hunspell (see tests in tests/ subdirectory): + +make check + +or with Valgrind debugger: + +make check +VALGRIND=[Valgrind_tool] make check + +For example: + +make check +VALGRIND=memcheck make check + +Documentation +------------- + +features and dictionary format: +man 4 hunspell + +man hunspell +hunspell -h +http://hunspell.sourceforge.net + +Usage +----- + +The src/tools dictionary contains three executables. +A spell checker with Ispell-like curses interface and Ispell +compatible pipe interface (hunspell) and two small example +program (hunmorph and hunstem). + +After compiling and installing (see INSTALL) you can +run the Hunspell spell checker (compiled with user interface) +with a Hunspell or Myspell dictionary: + +hunspell -d en_UK text.txt + +or without interface: + +hunspell -d en_UK -l + +Linking with Hunspell static library: +g++ -lhunspell example.cxx + +Dictionaries +------------ + +Myspell dictionaries: +http://lingucomponent.openoffice.org/spell_dic.html + +Aspell dictionaries (need some conversion): +ftp://ftp.gnu.org/gnu/aspell/dict +Conversion steps: see relevant feature request at http://hunspell.sf.net. + +Németh László +nemeth at OOo diff --git a/hunspell/README.myspell b/hunspell/README.myspell new file mode 100644 index 000000000..25934eec0 --- /dev/null +++ b/hunspell/README.myspell @@ -0,0 +1,69 @@ +MySpell is a simple spell checker that uses affix +compression and is modelled after the spell checker +ispell. + +MySpell was written to explore how affix compression +can be implemented. + +The Main features of MySpell are: + +1. written in C++ to make it easier to interface with + Pspell, OpenOffice, AbiWord, etc + +2. it is stateless, uses no static variables and + should be completely reentrant with almost no + ifdefs + +3. it tries to be as compatible with ispell to + the extent it can. It can read slightly modified + versions of munched ispell dictionaries (and it + comes with a munched english wordlist borrowed from + Kevin Atkinson's excellent Aspell. + +4. it uses a heavily modified aff file format that + can be derived from ispell aff files but uses + the iso-8859-X character sets only + +5. it is simple with *lots* of comments that + describes how the affixes are stored + and tested for (based on the approach used by + ispell). + +6. it supports improved suggestions with replacement + tables and ngram-scoring based mechanisms in addition + to the main suggestion mechanisms + +7. like ispell it has a BSD license (and no + advertising clause) + +But ... it has *no* support for adding words +to a personal dictionary, *no* support for converting +between various text encodings, and *no* command line +interface (it is purely meant to be a library). + +It can not (in any way) replace all of the functionality +of ispell or aspell/pspell. It is meant as a learning +tool for understanding affix compression and for +being used by front ends like OpenOffice, Abiword, etc. + +MySpell has been tested under Linux and Solaris +and has the world's simplest Makefile and no +configure support. + +It does come with a simple example program that +spell checks some words and returns suggestions. + +To build a static library and an example +program under Linux simply type: + +tar -zxvf myspell.tar.gz +cd myspell2 +make + +To run the example program: +./example ./en_US.aff ./en_US.dic checkme.lst + +Please play around with it and let me know +what you think. + +Please see the file CONTRIBUTORS for more info. diff --git a/hunspell/THANKS b/hunspell/THANKS new file mode 100644 index 000000000..5d5387a13 --- /dev/null +++ b/hunspell/THANKS @@ -0,0 +1,94 @@ +Many thanks to the following contributors and supporters: + +Lars Aronsson +Bencsáth Boldizsár +Bíró Árpád +Ingo H. de Boer +Simon Brouwer +Jeppe Bundsgaard +Ginn Chen +Dmitri Gabinski +Dvornik László +David Einstein +Rene Engelhard +Frederik Fouvry +Gavins at OOo +Gefferth András +Godó Ferenc +Goldman Eleonóra +Halácsy Péter +Chris Halls +Khaled Hosny +Izsók András +Björn Jacke +Mike Tian-Jian Jiang +Dafydd Jones +Ryan Jones +Jean-Christophe Helary +Kevin Hendricks +Martin Hollmichel +Pavel Janík +Kéménczy Kálmán +Dan Kenigsberg +Khiraly László +Koblinger Egmont +Kornai András +Tor Lillqvist +Robert Longson +Marot at SF dot net +Caolan McNamara +Michael Meeks +Moheb Mekhaiel +Ellis Miller +Giuseppe Modugno +János Mohácsi +Bram Moolenaar +Daniel Naber +Nagy Viktor +John Nisly +Noll János +Bryan Petty +Harri Pitkänen +Davide Prina +Kevin F. Quinn +Erdal Ronahi +Bernhard Rosenkraenzer +Sarlós Tamás +Thobias Schlemmer +Jose da Silva +Munzir Taha +Tímár András +Tonal at OOo +Trón Viktor +Gianluca Turconi +Ryan VanderMeulen +Varga Dániel +Miha Vrhovnik +Martijn Wargers +Friedel Wolff +Gábor Zahemszky +Taha Zerrouki +and others (see also AUTHORS.myspell) + +FSF.hu Foundation +http://www.fsf.hu + +MOKK Research Centre +Budapest University of Technology and Economics +Sociology and Communications Department +http://www.mokk.bme.hu + +Hungarian Ministry of Informatics and Telecommunications + +IMEDIA Ltd. +http://www.imedia.hu + +OpenOffice.org community +http://www.openoffice.org + +UHU-Linux Ltd. + +Thanks, + +Németh László +nemeth at OOo diff --git a/hunspell/TODO b/hunspell/TODO new file mode 100644 index 000000000..fb32e7ec8 --- /dev/null +++ b/hunspell/TODO @@ -0,0 +1,4 @@ +* shared dictionaries for multi-user environment +* improve compound handling +* Unicode unmunch (munch) +* forbiddenword and pseudoword support in unmunch diff --git a/hunspell/hunspell.pc.in b/hunspell/hunspell.pc.in new file mode 100644 index 000000000..2b856186b --- /dev/null +++ b/hunspell/hunspell.pc.in @@ -0,0 +1,10 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=${prefix}/lib +includedir=${prefix}/include + +Name: hunspell +Description: Hunpell spellchecking library +Version: @VERSION@ +Libs: -L${libdir} -lhunspell-@HUNSPELL_VERSION_MAJOR@.@HUNSPELL_VERSION_MINOR@ +Cflags: -I${includedir}/hunspell diff --git a/hunspell/license.hunspell b/hunspell/license.hunspell new file mode 100644 index 000000000..8f998bdc3 --- /dev/null +++ b/hunspell/license.hunspell @@ -0,0 +1,55 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Hunspell, based on MySpell. + * + * The Initial Developers of the Original Code are + * Kevin Hendricks (MySpell) and Németh László (Hunspell). + * Portions created by the Initial Developers are Copyright (C) 2002-2005 + * the Initial Developers. All Rights Reserved. + * + * Contributor(s): + * David Einstein + * Davide Prina + * Giuseppe Modugno + * Gianluca Turconi + * Simon Brouwer + * Noll János + * Bíró Árpád + * Goldman Eleonóra + * Sarlós Tamás + * Bencsáth Boldizsár + * Halácsy Péter + * Dvornik László + * Gefferth András + * Nagy Viktor + * Varga Dániel + * Chris Halls + * Rene Engelhard + * Bram Moolenaar + * Dafydd Jones + * Harri Pitkänen + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ diff --git a/hunspell/license.myspell b/hunspell/license.myspell new file mode 100644 index 000000000..2da533075 --- /dev/null +++ b/hunspell/license.myspell @@ -0,0 +1,61 @@ +/* + * Copyright 2002 Kevin B. Hendricks, Stratford, Ontario, Canada + * And Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All modifications to the source code must be clearly marked as + * such. Binary redistributions based on modified source code + * must be clearly marked as modified versions in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY KEVIN B. HENDRICKS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * KEVIN B. HENDRICKS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * NOTE: A special thanks and credit goes to Geoff Kuenning + * the creator of ispell. MySpell's affix algorithms were + * based on those of ispell which should be noted is + * copyright Geoff Kuenning et.al. and now available + * under a BSD style license. For more information on ispell + * and affix compression in general, please see: + * http://www.cs.ucla.edu/ficus-members/geoff/ispell.html + * (the home page for ispell) + * + * An almost complete rewrite of MySpell for use by + * the Mozilla project has been developed by David Einstein + * (Deinst@world.std.com). David and I are now + * working on parallel development tracks to help + * our respective projects (Mozilla and OpenOffice.org + * and we will maintain full affix file and dictionary + * file compatibility and work on merging our versions + * of MySpell back into a single tree. David has been + * a significant help in improving MySpell. + * + * Special thanks also go to La'szlo' Ne'meth + * who is the author of the + * Hungarian dictionary and who developed and contributed + * the code to support compound words in MySpell + * and fixed numerous problems with the encoding + * case conversion tables. + * + */ diff --git a/hunspell/missing b/hunspell/missing new file mode 100644 index 000000000..e7ef83a1c --- /dev/null +++ b/hunspell/missing @@ -0,0 +1,360 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2003-09-02.23 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/hunspell/src/Makefile.am b/hunspell/src/Makefile.am new file mode 100644 index 000000000..7570b3915 --- /dev/null +++ b/hunspell/src/Makefile.am @@ -0,0 +1 @@ +SUBDIRS=hunspell parsers tools win_api diff --git a/hunspell/src/Makefile.in b/hunspell/src/Makefile.in new file mode 100644 index 000000000..c00a088c3 --- /dev/null +++ b/hunspell/src/Makefile.in @@ -0,0 +1,505 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/isc-posix.m4 \ + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +SOURCES = +DIST_SOURCES = +RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ + html-recursive info-recursive install-data-recursive \ + install-exec-recursive install-info-recursive \ + install-recursive installcheck-recursive installdirs-recursive \ + pdf-recursive ps-recursive uninstall-info-recursive \ + uninstall-recursive +ETAGS = etags +CTAGS = ctags +DIST_SUBDIRS = $(SUBDIRS) +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSESLIB = @CURSESLIB@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GENCAT = @GENCAT@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +HUNSPELL_VERSION_MAJOR = @HUNSPELL_VERSION_MAJOR@ +HUNSPELL_VERSION_MINOR = @HUNSPELL_VERSION_MINOR@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +READLINELIB = @READLINELIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XFAILED = @XFAILED@ +XGETTEXT = @XGETTEXT@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +SUBDIRS = hunspell parsers tools win_api +all: all-recursive + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @failcom='exit 1'; \ + for f in x $$MAKEFLAGS; do \ + case $$f in \ + *=* | --[!k]*);; \ + *k*) failcom='fail=yes';; \ + esac; \ + done; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || eval $$failcom; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done +ctags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ + include_option=--etags-include; \ + empty_fix=.; \ + else \ + include_option=--include; \ + empty_fix=; \ + fi; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test ! -f $$subdir/TAGS || \ + tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d "$(distdir)/$$subdir" \ + || $(mkdir_p) "$(distdir)/$$subdir" \ + || exit 1; \ + distdir=`$(am__cd) $(distdir) && pwd`; \ + top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$$top_distdir" \ + distdir="$$distdir/$$subdir" \ + distdir) \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-recursive +all-am: Makefile +installdirs: installdirs-recursive +installdirs-am: +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f Makefile +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +html: html-recursive + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-recursive + +pdf-am: + +ps: ps-recursive + +ps-am: + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ + clean clean-generic clean-libtool clean-recursive ctags \ + ctags-recursive distclean distclean-generic distclean-libtool \ + distclean-recursive distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs installdirs-am maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive \ + mostlyclean mostlyclean-generic mostlyclean-libtool \ + mostlyclean-recursive pdf pdf-am ps ps-am tags tags-recursive \ + uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/hunspell/src/hunspell/Makefile.am b/hunspell/src/hunspell/Makefile.am new file mode 100644 index 000000000..cefd66bc4 --- /dev/null +++ b/hunspell/src/hunspell/Makefile.am @@ -0,0 +1,15 @@ +libhunspell_la_LDFLAGS = -version-info 1:1:0 + +lib_LTLIBRARIES = libhunspell.la +libhunspell_includedir = $(includedir)/hunspell +libhunspell_la_SOURCES=affentry.cxx affixmgr.cxx csutil.cxx \ + dictmgr.cxx hashmgr.cxx hunspell.cxx utf_info.cxx \ + suggestmgr.cxx license.myspell license.hunspell \ + phonet.cxx + +libhunspell_include_HEADERS=affentry.hxx htypes.hxx affixmgr.hxx \ + csutil.hxx hunspell.hxx atypes.hxx dictmgr.hxx hunspell.h \ + suggestmgr.hxx baseaffix.hxx hashmgr.hxx langnum.hxx \ + phonet.hxx + +EXTRA_DIST=hunspell.dsp makefile.mk README diff --git a/hunspell/src/hunspell/Makefile.in b/hunspell/src/hunspell/Makefile.in new file mode 100644 index 000000000..a700fd81d --- /dev/null +++ b/hunspell/src/hunspell/Makefile.in @@ -0,0 +1,533 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +subdir = src/hunspell +DIST_COMMON = README $(libhunspell_include_HEADERS) \ + $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/isc-posix.m4 \ + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(libhunspell_includedir)" +libLTLIBRARIES_INSTALL = $(INSTALL) +LTLIBRARIES = $(lib_LTLIBRARIES) +libhunspell_la_LIBADD = +am_libhunspell_la_OBJECTS = affentry.lo affixmgr.lo csutil.lo \ + dictmgr.lo hashmgr.lo hunspell.lo utf_info.lo suggestmgr.lo \ + phonet.lo +libhunspell_la_OBJECTS = $(am_libhunspell_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libhunspell_la_SOURCES) +DIST_SOURCES = $(libhunspell_la_SOURCES) +libhunspell_includeHEADERS_INSTALL = $(INSTALL_HEADER) +HEADERS = $(libhunspell_include_HEADERS) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSESLIB = @CURSESLIB@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GENCAT = @GENCAT@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +HUNSPELL_VERSION_MAJOR = @HUNSPELL_VERSION_MAJOR@ +HUNSPELL_VERSION_MINOR = @HUNSPELL_VERSION_MINOR@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +READLINELIB = @READLINELIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XFAILED = @XFAILED@ +XGETTEXT = @XGETTEXT@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +libhunspell_la_LDFLAGS = -version-info 1:1:0 +lib_LTLIBRARIES = libhunspell.la +libhunspell_includedir = $(includedir)/hunspell +libhunspell_la_SOURCES = affentry.cxx affixmgr.cxx csutil.cxx \ + dictmgr.cxx hashmgr.cxx hunspell.cxx utf_info.cxx \ + suggestmgr.cxx license.myspell license.hunspell \ + phonet.cxx + +libhunspell_include_HEADERS = affentry.hxx htypes.hxx affixmgr.hxx \ + csutil.hxx hunspell.hxx atypes.hxx dictmgr.hxx hunspell.h \ + suggestmgr.hxx baseaffix.hxx hashmgr.hxx langnum.hxx \ + phonet.hxx + +EXTRA_DIST = hunspell.dsp makefile.mk README +all: all-am + +.SUFFIXES: +.SUFFIXES: .cxx .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/hunspell/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/hunspell/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLTLIBRARIES: + -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) + @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libhunspell.la: $(libhunspell_la_OBJECTS) $(libhunspell_la_DEPENDENCIES) + $(CXXLINK) -rpath $(libdir) $(libhunspell_la_LDFLAGS) $(libhunspell_la_OBJECTS) $(libhunspell_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affentry.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/affixmgr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/csutil.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dictmgr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashmgr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hunspell.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/phonet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/suggestmgr.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/utf_info.Plo@am__quote@ + +.cxx.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cxx.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cxx.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +install-libhunspell_includeHEADERS: $(libhunspell_include_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(libhunspell_includedir)" || $(mkdir_p) "$(DESTDIR)$(libhunspell_includedir)" + @list='$(libhunspell_include_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f=$(am__strip_dir) \ + echo " $(libhunspell_includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(libhunspell_includedir)/$$f'"; \ + $(libhunspell_includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(libhunspell_includedir)/$$f"; \ + done + +uninstall-libhunspell_includeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(libhunspell_include_HEADERS)'; for p in $$list; do \ + f=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(libhunspell_includedir)/$$f'"; \ + rm -f "$(DESTDIR)$(libhunspell_includedir)/$$f"; \ + done + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) +installdirs: + for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(libhunspell_includedir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ + mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: install-libhunspell_includeHEADERS + +install-exec-am: install-libLTLIBRARIES + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES \ + uninstall-libhunspell_includeHEADERS + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLTLIBRARIES clean-libtool ctags distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am \ + install-libLTLIBRARIES install-libhunspell_includeHEADERS \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-info-am uninstall-libLTLIBRARIES \ + uninstall-libhunspell_includeHEADERS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/hunspell/src/hunspell/README b/hunspell/src/hunspell/README new file mode 100644 index 000000000..b45209628 --- /dev/null +++ b/hunspell/src/hunspell/README @@ -0,0 +1,21 @@ +Hunspell spell checker and morphological analyser library + +Documentation, tests, examples: http://hunspell.sourceforge.net + +Author of Hunspell: +László Németh (nemethl (at) gyorsposta.hu) + +Hunspell based on OpenOffice.org's Myspell. MySpell's author: +Kevin Hendricks (kevin.hendricks (at) sympatico.ca) + +License: GPL 2.0/LGPL 2.1/MPL 1.1 tri-license + +The contents of this library may be used under the terms of +the GNU General Public License Version 2 or later (the "GPL"), or +the GNU Lesser General Public License Version 2.1 or later (the "LGPL", +see http://gnu.org/copyleft/lesser.html) or the Mozilla Public License +Version 1.1 or later (the "MPL", see http://mozilla.org/MPL/MPL-1.1.html). + +Software distributed under these licenses is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the licences +for the specific language governing rights and limitations under the licenses. diff --git a/hunspell/src/hunspell/affentry.cxx b/hunspell/src/hunspell/affentry.cxx new file mode 100644 index 000000000..0ffe55725 --- /dev/null +++ b/hunspell/src/hunspell/affentry.cxx @@ -0,0 +1,941 @@ +#include "license.hunspell" +#include "license.myspell" + +#ifndef MOZILLA_CLIENT +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include "affentry.hxx" +#include "csutil.hxx" + +#ifndef MOZILLA_CLIENT +#ifndef W32 +using namespace std; +#endif +#endif + + +PfxEntry::PfxEntry(AffixMgr* pmgr, affentry* dp) +{ + // register affix manager + pmyMgr = pmgr; + + // set up its intial values + + aflag = dp->aflag; // flag + strip = dp->strip; // string to strip + appnd = dp->appnd; // string to append + stripl = dp->stripl; // length of strip string + appndl = dp->appndl; // length of append string + numconds = dp->numconds; // length of the condition + opts = dp->opts; // cross product flag + // then copy over all of the conditions + if (opts & aeLONGCOND) { + memcpy(c.conds, dp->c.l.conds1, MAXCONDLEN_1); + c.l.conds2 = dp->c.l.conds2; + } else memcpy(c.conds, dp->c.conds, MAXCONDLEN); + next = NULL; + nextne = NULL; + nexteq = NULL; + morphcode = dp->morphcode; + contclass = dp->contclass; + contclasslen = dp->contclasslen; +} + + +PfxEntry::~PfxEntry() +{ + aflag = 0; + if (appnd) free(appnd); + if (strip) free(strip); + pmyMgr = NULL; + appnd = NULL; + strip = NULL; + if (opts & aeLONGCOND) free(c.l.conds2); + if (morphcode && !(opts & aeALIASM)) free(morphcode); + if (contclass && !(opts & aeALIASF)) free(contclass); +} + +// add prefix to this word assuming conditions hold +char * PfxEntry::add(const char * word, int len) +{ + char tword[MAXWORDUTF8LEN + 4]; + + if ((len > stripl) && (len >= numconds) && test_condition(word) && + (!stripl || (strncmp(word, strip, stripl) == 0)) && + ((MAXWORDUTF8LEN + 4) > (len + appndl - stripl))) { + /* we have a match so add prefix */ + char * pp = tword; + if (appndl) { + strcpy(tword,appnd); + pp += appndl; + } + strcpy(pp, (word + stripl)); + return mystrdup(tword); + } + return NULL; +} + +inline char * PfxEntry::nextchar(char * p) { + if (p) { + p++; + if (opts & aeLONGCOND) { + // jump to the 2nd part of the condition + if (p == c.conds + MAXCONDLEN_1) return c.l.conds2; + // end of the MAXCONDLEN length condition + } else if (p == c.conds + MAXCONDLEN) return NULL; + } + return p; +} + +inline int PfxEntry::test_condition(const char * st) +{ + const char * pos = NULL; // group with pos input position + bool neg = false; // complementer + bool ingroup = false; // character in the group + if (numconds == 0) return 1; + char * p = c.conds; + while (1) { + switch (*p) { + case '\0': return 1; + case '[': { p = nextchar(p); pos = st; break; } + case '^': { p = nextchar(p); neg = true; break; } + case ']': { if ((neg && ingroup) || (!neg && !ingroup)) return 0; + pos = NULL; + neg = false; + ingroup = false; + p = nextchar(p); + st++; + if (*st == '\0' && p && *p != '\0') return 0; // word <= condition + break; + } + case '.': if (!pos) { // dots are not metacharacters in groups: [.] + p = nextchar(p); + // skip the next character + for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++); + if (*st == '\0') return 0; // word <= condition + break; + } + default: { + if (*st == *p) { + st++; + p = nextchar(p); + if ((opts & aeUTF8) && (*(st - 1) & 0x80)) { // multibyte + while (p && (*p & 0xc0) == 0x80) { // character + if (*p != *st) { + if (!pos) return 0; + st = pos; + break; + } + p = nextchar(p); + st++; + } + if (st != pos) ingroup = true; + } else if (pos) ingroup = true; + } else if (pos) { // group + p = nextchar(p); + } else return 0; + } + } + if (!p) return 1; + } +} + +// check if this prefix entry matches +struct hentry * PfxEntry::checkword(const char * word, int len, char in_compound, const FLAG needflag) +{ + int tmpl; // length of tmpword + struct hentry * he; // hash entry of root word or NULL + char tmpword[MAXWORDUTF8LEN + 4]; + + // on entry prefix is 0 length or already matches the beginning of the word. + // So if the remaining root word has positive length + // and if there are enough chars in root word and added back strip chars + // to meet the number of characters conditions, then test it + + tmpl = len - appndl; + +// if ((tmpl > 0) && (tmpl + stripl >= numconds)) { + if (tmpl > 0) { + + // generate new root word by removing prefix and adding + // back any characters that would have been stripped + + if (stripl) strcpy (tmpword, strip); + strcpy ((tmpword + stripl), (word + appndl)); + + // now make sure all of the conditions on characters + // are met. Please see the appendix at the end of + // this file for more info on exactly what is being + // tested + + // if all conditions are met then check if resulting + // root word in the dictionary + + if (test_condition(tmpword)) { + tmpl += stripl; + if ((he = pmyMgr->lookup(tmpword)) != NULL) { + do { + if (TESTAFF(he->astr, aflag, he->alen) && + // forbid single prefixes with needaffix flag + ! TESTAFF(contclass, pmyMgr->get_needaffix(), contclasslen) && + // needflag + ((!needflag) || TESTAFF(he->astr, needflag, he->alen) || + (contclass && TESTAFF(contclass, needflag, contclasslen)))) + return he; + he = he->next_homonym; // check homonyms + } while (he); + } + + // prefix matched but no root word was found + // if aeXPRODUCT is allowed, try again but now + // ross checked combined with a suffix + + //if ((opts & aeXPRODUCT) && in_compound) { + if ((opts & aeXPRODUCT)) { + he = pmyMgr->suffix_check(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, NULL, + 0, NULL, FLAG_NULL, needflag, in_compound); + if (he) return he; + } + } + } + return NULL; +} + +// check if this prefix entry matches +struct hentry * PfxEntry::check_twosfx(const char * word, int len, + char in_compound, const FLAG needflag) +{ + int tmpl; // length of tmpword + struct hentry * he; // hash entry of root word or NULL + char tmpword[MAXWORDUTF8LEN + 4]; + + // on entry prefix is 0 length or already matches the beginning of the word. + // So if the remaining root word has positive length + // and if there are enough chars in root word and added back strip chars + // to meet the number of characters conditions, then test it + + tmpl = len - appndl; + + if ((tmpl > 0) && (tmpl + stripl >= numconds)) { +// if (tmpl > 0) { + + // generate new root word by removing prefix and adding + // back any characters that would have been stripped + + if (stripl) strcpy (tmpword, strip); + strcpy ((tmpword + stripl), (word + appndl)); + + // now make sure all of the conditions on characters + // are met. Please see the appendix at the end of + // this file for more info on exactly what is being + // tested + + // if all conditions are met then check if resulting + // root word in the dictionary + + if (test_condition(tmpword)) { + tmpl += stripl; + + // prefix matched but no root word was found + // if aeXPRODUCT is allowed, try again but now + // cross checked combined with a suffix + + if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) { + he = pmyMgr->suffix_check_twosfx(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, needflag); + if (he) return he; + } + } + } + return NULL; +} + +// check if this prefix entry matches +char * PfxEntry::check_twosfx_morph(const char * word, int len, + char in_compound, const FLAG needflag) +{ + int tmpl; // length of tmpword + char tmpword[MAXWORDUTF8LEN + 4]; + + // on entry prefix is 0 length or already matches the beginning of the word. + // So if the remaining root word has positive length + // and if there are enough chars in root word and added back strip chars + // to meet the number of characters conditions, then test it + + tmpl = len - appndl; + + if ((tmpl > 0) && (tmpl + stripl >= numconds)) { +// if (tmpl > 0) { + + // generate new root word by removing prefix and adding + // back any characters that would have been stripped + + if (stripl) strcpy (tmpword, strip); + strcpy ((tmpword + stripl), (word + appndl)); + + // now make sure all of the conditions on characters + // are met. Please see the appendix at the end of + // this file for more info on exactly what is being + // tested + + // if all conditions are met then check if resulting + // root word in the dictionary + + if (test_condition(tmpword)) { + tmpl += stripl; + + // prefix matched but no root word was found + // if aeXPRODUCT is allowed, try again but now + // ross checked combined with a suffix + + if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) { + return pmyMgr->suffix_check_twosfx_morph(tmpword, tmpl, + aeXPRODUCT, (AffEntry *)this, needflag); + } + } + } + return NULL; +} + +// check if this prefix entry matches +char * PfxEntry::check_morph(const char * word, int len, char in_compound, const FLAG needflag) +{ + int tmpl; // length of tmpword + struct hentry * he; // hash entry of root word or NULL + char tmpword[MAXWORDUTF8LEN + 4]; + char result[MAXLNLEN]; + char * st; + + *result = '\0'; + + // on entry prefix is 0 length or already matches the beginning of the word. + // So if the remaining root word has positive length + // and if there are enough chars in root word and added back strip chars + // to meet the number of characters conditions, then test it + + tmpl = len - appndl; + + if ((tmpl > 0) && (tmpl + stripl >= numconds)) { +// if (tmpl > 0) { + + // generate new root word by removing prefix and adding + // back any characters that would have been stripped + + if (stripl) strcpy (tmpword, strip); + strcpy ((tmpword + stripl), (word + appndl)); + + // now make sure all of the conditions on characters + // are met. Please see the appendix at the end of + // this file for more info on exactly what is being + // tested + + // if all conditions are met then check if resulting + // root word in the dictionary + + if (test_condition(tmpword)) { + tmpl += stripl; + if ((he = pmyMgr->lookup(tmpword)) != NULL) { + do { + if (TESTAFF(he->astr, aflag, he->alen) && + // forbid single prefixes with needaffix flag + ! TESTAFF(contclass, pmyMgr->get_needaffix(), contclasslen) && + // needflag + ((!needflag) || TESTAFF(he->astr, needflag, he->alen) || + (contclass && TESTAFF(contclass, needflag, contclasslen)))) { + if (morphcode) { + strcat(result, " "); + strcat(result, morphcode); + } else strcat(result,getKey()); + if (!HENTRY_FIND(he, MORPH_STEM)) { + strcat(result, " "); + strcat(result, MORPH_STEM); + strcat(result,HENTRY_WORD(he)); + } + // store the pointer of the hash entry +// sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, he); + if (HENTRY_DATA(he)) { + strcat(result, " "); + strcat(result,HENTRY_DATA(he)); + } + strcat(result, "\n"); + } + he = he->next_homonym; + } while (he); + } + + // prefix matched but no root word was found + // if aeXPRODUCT is allowed, try again but now + // ross checked combined with a suffix + + if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) { + st = pmyMgr->suffix_check_morph(tmpword, tmpl, aeXPRODUCT, (AffEntry *)this, + FLAG_NULL, needflag); + if (st) { + strcat(result, st); + free(st); + } + } + } + } + + if (*result) return mystrdup(result); + return NULL; +} + +SfxEntry::SfxEntry(AffixMgr * pmgr, affentry* dp) +{ + // register affix manager + pmyMgr = pmgr; + + // set up its intial values + aflag = dp->aflag; // char flag + strip = dp->strip; // string to strip + appnd = dp->appnd; // string to append + stripl = dp->stripl; // length of strip string + appndl = dp->appndl; // length of append string + numconds = dp->numconds; // length of the condition + opts = dp->opts; // cross product flag + + // then copy over all of the conditions + if (opts & aeLONGCOND) { + memcpy(c.l.conds1, dp->c.l.conds1, MAXCONDLEN_1); + c.l.conds2 = dp->c.l.conds2; + } else memcpy(c.conds, dp->c.conds, MAXCONDLEN); + + rappnd = myrevstrdup(appnd); + morphcode = dp->morphcode; + contclass = dp->contclass; + contclasslen = dp->contclasslen; +} + + +SfxEntry::~SfxEntry() +{ + aflag = 0; + if (appnd) free(appnd); + if (rappnd) free(rappnd); + if (strip) free(strip); + pmyMgr = NULL; + appnd = NULL; + strip = NULL; + if (opts & aeLONGCOND) free(c.l.conds2); + if (morphcode && !(opts & aeALIASM)) free(morphcode); + if (contclass && !(opts & aeALIASF)) free(contclass); +} + +// add suffix to this word assuming conditions hold +char * SfxEntry::add(const char * word, int len) +{ + char tword[MAXWORDUTF8LEN + 4]; + + /* make sure all conditions match */ + if ((len > stripl) && (len >= numconds) && test_condition(word + len, word) && + (!stripl || (strcmp(word + len - stripl, strip) == 0)) && + ((MAXWORDUTF8LEN + 4) > (len + appndl - stripl))) { + /* we have a match so add suffix */ + strcpy(tword,word); + if (appndl) { + strcpy(tword + len - stripl, appnd); + } else { + *(tword + len - stripl) = '\0'; + } + return mystrdup(tword); + } + return NULL; +} + +inline char * SfxEntry::nextchar(char * p) { + p++; + if (opts & aeLONGCOND) { + // jump to the 2nd part of the condition + if (p == c.l.conds1 + MAXCONDLEN_1) return c.l.conds2; + // end of the MAXCONDLEN length condition + } else if (p == c.conds + MAXCONDLEN) return NULL; + return p; +} + +inline int SfxEntry::test_condition(const char * st, const char * beg) +{ + const char * pos = NULL; // group with pos input position + bool neg = false; // complementer + bool ingroup = false; // character in the group + if (numconds == 0) return 1; + char * p = c.conds; + st--; + int c = 1; + while (1) { + switch (*p) { + case '\0': return 1; + case '[': { p = nextchar(p); pos = st; break; } + case '^': { p = nextchar(p); neg = true; break; } + case ']': { if (!neg && !ingroup) return 0; + c++; + pos = NULL; + neg = false; + ingroup = false; + p = nextchar(p); + st--; + if (st < beg && p && *p != '\0') return 0; // word <= condition + break; + } + case '.': if (!pos) { // dots are not metacharacters in groups: [.] + p = nextchar(p); + // skip the next character + for (st--; (opts & aeUTF8) && (st >= beg) && (*st & 0xc0) == 0x80; st--); + if (st < beg) return 0; // word <= condition + if (*st & 0x80) { // head of the UTF-8 character + st--; + if (st < beg) return 0; // word <= condition + } + break; + } + default: { + if (*st == *p) { + p = nextchar(p); + if ((opts & aeUTF8) && (*st & 0x80)) { + st--; + while (p && (st >= beg)) { + if (*p != *st) { + if (!pos) return 0; + st = pos; + break; + } + // first byte of the UTF-8 multibyte character + if ((*p & 0xc0) != 0x80) break; + p = nextchar(p); + st--; + } + if (pos && st != pos) { + if (neg) return 0; + else if (c == numconds) return 1; + ingroup = true; + } + if (p && *p != '\0') p = nextchar(p); + } else if (pos) { + if (neg) return 0; + else if (c == numconds) return 1; + ingroup = true; + } + if (!pos) { + c++; + st--; + if (st < beg && p && *p != '\0') return 0; // word <= condition + } + } else if (pos) { // group + p = nextchar(p); + } else return 0; + } + } + if (!p) return 1; + } +} + +// see if this suffix is present in the word +struct hentry * SfxEntry::checkword(const char * word, int len, int optflags, + AffEntry* ppfx, char ** wlst, int maxSug, int * ns, const FLAG cclass, const FLAG needflag, + const FLAG badflag) +{ + int tmpl; // length of tmpword + struct hentry * he; // hash entry pointer + unsigned char * cp; + char tmpword[MAXWORDUTF8LEN + 4]; + PfxEntry* ep = (PfxEntry *) ppfx; + + // if this suffix is being cross checked with a prefix + // but it does not support cross products skip it + + if (((optflags & aeXPRODUCT) != 0) && ((opts & aeXPRODUCT) == 0)) + return NULL; + + // upon entry suffix is 0 length or already matches the end of the word. + // So if the remaining root word has positive length + // and if there are enough chars in root word and added back strip chars + // to meet the number of characters conditions, then test it + + tmpl = len - appndl; + // the second condition is not enough for UTF-8 strings + // it checked in test_condition() + + if ((tmpl > 0) && (tmpl + stripl >= numconds)) { +// if (tmpl > 0) { + + // generate new root word by removing suffix and adding + // back any characters that would have been stripped or + // or null terminating the shorter string + + strcpy (tmpword, word); + cp = (unsigned char *)(tmpword + tmpl); + if (stripl) { + strcpy ((char *)cp, strip); + tmpl += stripl; + cp = (unsigned char *)(tmpword + tmpl); + } else *cp = '\0'; + + // now make sure all of the conditions on characters + // are met. Please see the appendix at the end of + // this file for more info on exactly what is being + // tested + + // if all conditions are met then check if resulting + // root word in the dictionary + + if (test_condition((char *) cp, (char *) tmpword)) { + +#ifdef SZOSZABLYA_POSSIBLE_ROOTS + fprintf(stdout,"%s %s %c\n", word, tmpword, aflag); +#endif + if ((he = pmyMgr->lookup(tmpword)) != NULL) { + do { + // check conditional suffix (enabled by prefix) + if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() && + TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && + (((optflags & aeXPRODUCT) == 0) || + TESTAFF(he->astr, ep->getFlag(), he->alen) || + // enabled by prefix + ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) + ) && + // handle cont. class + ((!cclass) || + ((contclass) && TESTAFF(contclass, cclass, contclasslen)) + ) && + // check only in compound homonyms (bad flags) + (!badflag || !TESTAFF(he->astr, badflag, he->alen) + ) && + // handle required flag + ((!needflag) || + (TESTAFF(he->astr, needflag, he->alen) || + ((contclass) && TESTAFF(contclass, needflag, contclasslen))) + ) + ) return he; + he = he->next_homonym; // check homonyms + } while (he); + + // obsolote stemming code (used only by the + // experimental SuffixMgr:suggest_pos_stems) + // store resulting root in wlst + } else if (wlst && (*ns < maxSug)) { + int cwrd = 1; + for (int k=0; k < *ns; k++) + if (strcmp(tmpword, wlst[k]) == 0) cwrd = 0; + if (cwrd) { + wlst[*ns] = mystrdup(tmpword); + if (wlst[*ns] == NULL) { + for (int j=0; j<*ns; j++) free(wlst[j]); + *ns = -1; + return NULL; + } + (*ns)++; + } + } + } + } + return NULL; +} + +// see if two-level suffix is present in the word +struct hentry * SfxEntry::check_twosfx(const char * word, int len, int optflags, + AffEntry* ppfx, const FLAG needflag) +{ + int tmpl; // length of tmpword + struct hentry * he; // hash entry pointer + unsigned char * cp; + char tmpword[MAXWORDUTF8LEN + 4]; + PfxEntry* ep = (PfxEntry *) ppfx; + + + // if this suffix is being cross checked with a prefix + // but it does not support cross products skip it + + if ((optflags & aeXPRODUCT) != 0 && (opts & aeXPRODUCT) == 0) + return NULL; + + // upon entry suffix is 0 length or already matches the end of the word. + // So if the remaining root word has positive length + // and if there are enough chars in root word and added back strip chars + // to meet the number of characters conditions, then test it + + tmpl = len - appndl; + + if ((tmpl > 0) && (tmpl + stripl >= numconds)) { +// if (tmpl > 0) { + + // generate new root word by removing suffix and adding + // back any characters that would have been stripped or + // or null terminating the shorter string + + strcpy (tmpword, word); + cp = (unsigned char *)(tmpword + tmpl); + if (stripl) { + strcpy ((char *)cp, strip); + tmpl += stripl; + cp = (unsigned char *)(tmpword + tmpl); + } else *cp = '\0'; + + // now make sure all of the conditions on characters + // are met. Please see the appendix at the end of + // this file for more info on exactly what is being + // tested + + // if all conditions are met then recall suffix_check + + if (test_condition((char *) cp, (char *) tmpword)) { + if (ppfx) { + // handle conditional suffix + if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) + he = pmyMgr->suffix_check(tmpword, tmpl, 0, NULL, NULL, 0, NULL, (FLAG) aflag, needflag); + else + he = pmyMgr->suffix_check(tmpword, tmpl, optflags, ppfx, NULL, 0, NULL, (FLAG) aflag, needflag); + } else { + he = pmyMgr->suffix_check(tmpword, tmpl, 0, NULL, NULL, 0, NULL, (FLAG) aflag, needflag); + } + if (he) return he; + } + } + return NULL; +} + +// see if two-level suffix is present in the word +char * SfxEntry::check_twosfx_morph(const char * word, int len, int optflags, + AffEntry* ppfx, const FLAG needflag) +{ + int tmpl; // length of tmpword + unsigned char * cp; + char tmpword[MAXWORDUTF8LEN + 4]; + PfxEntry* ep = (PfxEntry *) ppfx; + char * st; + + char result[MAXLNLEN]; + + *result = '\0'; + + // if this suffix is being cross checked with a prefix + // but it does not support cross products skip it + + if ((optflags & aeXPRODUCT) != 0 && (opts & aeXPRODUCT) == 0) + return NULL; + + // upon entry suffix is 0 length or already matches the end of the word. + // So if the remaining root word has positive length + // and if there are enough chars in root word and added back strip chars + // to meet the number of characters conditions, then test it + + tmpl = len - appndl; + + if ((tmpl > 0) && (tmpl + stripl >= numconds)) { +// if (tmpl > 0) { + + // generate new root word by removing suffix and adding + // back any characters that would have been stripped or + // or null terminating the shorter string + + strcpy (tmpword, word); + cp = (unsigned char *)(tmpword + tmpl); + if (stripl) { + strcpy ((char *)cp, strip); + tmpl += stripl; + cp = (unsigned char *)(tmpword + tmpl); + } else *cp = '\0'; + + // now make sure all of the conditions on characters + // are met. Please see the appendix at the end of + // this file for more info on exactly what is being + // tested + + // if all conditions are met then recall suffix_check + + if (test_condition((char *) cp, (char *) tmpword)) { + if (ppfx) { + // handle conditional suffix + if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) { + st = pmyMgr->suffix_check_morph(tmpword, tmpl, 0, NULL, aflag, needflag); + if (st) { + if (((PfxEntry *) ppfx)->getMorph()) { + strcat(result, ((PfxEntry *) ppfx)->getMorph()); + strcat(result, " "); + } + strcat(result,st); + free(st); + mychomp(result); + } + } else { + st = pmyMgr->suffix_check_morph(tmpword, tmpl, optflags, ppfx, aflag, needflag); + if (st) { + strcat(result, st); + free(st); + mychomp(result); + } + } + } else { + st = pmyMgr->suffix_check_morph(tmpword, tmpl, 0, NULL, aflag, needflag); + if (st) { + strcat(result, st); + free(st); + mychomp(result); + } + } + if (*result) return mystrdup(result); + } + } + return NULL; +} + +// get next homonym with same affix +struct hentry * SfxEntry::get_next_homonym(struct hentry * he, int optflags, AffEntry* ppfx, + const FLAG cclass, const FLAG needflag) +{ + PfxEntry* ep = (PfxEntry *) ppfx; + FLAG eFlag = ep ? ep->getFlag() : FLAG_NULL; + + while (he->next_homonym) { + he = he->next_homonym; + if ((TESTAFF(he->astr, aflag, he->alen) || (ep && ep->getCont() && TESTAFF(ep->getCont(), aflag, ep->getContLen()))) && + ((optflags & aeXPRODUCT) == 0 || + TESTAFF(he->astr, eFlag, he->alen) || + // handle conditional suffix + ((contclass) && TESTAFF(contclass, eFlag, contclasslen)) + ) && + // handle cont. class + ((!cclass) || + ((contclass) && TESTAFF(contclass, cclass, contclasslen)) + ) && + // handle required flag + ((!needflag) || + (TESTAFF(he->astr, needflag, he->alen) || + ((contclass) && TESTAFF(contclass, needflag, contclasslen))) + ) + ) return he; + } + return NULL; +} + + +#if 0 + +Appendix: Understanding Affix Code + + +An affix is either a prefix or a suffix attached to root words to make +other words. + +Basically a Prefix or a Suffix is set of AffEntry objects +which store information about the prefix or suffix along +with supporting routines to check if a word has a particular +prefix or suffix or a combination. + +The structure affentry is defined as follows: + +struct affentry +{ + unsigned short aflag; // ID used to represent the affix + char * strip; // string to strip before adding affix + char * appnd; // the affix string to add + unsigned char stripl; // length of the strip string + unsigned char appndl; // length of the affix string + char numconds; // the number of conditions that must be met + char opts; // flag: aeXPRODUCT- combine both prefix and suffix + char conds[SETSIZE]; // array which encodes the conditions to be met +}; + + +Here is a suffix borrowed from the en_US.aff file. This file +is whitespace delimited. + +SFX D Y 4 +SFX D 0 e d +SFX D y ied [^aeiou]y +SFX D 0 ed [^ey] +SFX D 0 ed [aeiou]y + +This information can be interpreted as follows: + +In the first line has 4 fields + +Field +----- +1 SFX - indicates this is a suffix +2 D - is the name of the character flag which represents this suffix +3 Y - indicates it can be combined with prefixes (cross product) +4 4 - indicates that sequence of 4 affentry structures are needed to + properly store the affix information + +The remaining lines describe the unique information for the 4 SfxEntry +objects that make up this affix. Each line can be interpreted +as follows: (note fields 1 and 2 are as a check against line 1 info) + +Field +----- +1 SFX - indicates this is a suffix +2 D - is the name of the character flag for this affix +3 y - the string of chars to strip off before adding affix + (a 0 here indicates the NULL string) +4 ied - the string of affix characters to add +5 [^aeiou]y - the conditions which must be met before the affix + can be applied + +Field 5 is interesting. Since this is a suffix, field 5 tells us that +there are 2 conditions that must be met. The first condition is that +the next to the last character in the word must *NOT* be any of the +following "a", "e", "i", "o" or "u". The second condition is that +the last character of the word must end in "y". + +So how can we encode this information concisely and be able to +test for both conditions in a fast manner? The answer is found +but studying the wonderful ispell code of Geoff Kuenning, et.al. +(now available under a normal BSD license). + +If we set up a conds array of 256 bytes indexed (0 to 255) and access it +using a character (cast to an unsigned char) of a string, we have 8 bits +of information we can store about that character. Specifically we +could use each bit to say if that character is allowed in any of the +last (or first for prefixes) 8 characters of the word. + +Basically, each character at one end of the word (up to the number +of conditions) is used to index into the conds array and the resulting +value found there says whether the that character is valid for a +specific character position in the word. + +For prefixes, it does this by setting bit 0 if that char is valid +in the first position, bit 1 if valid in the second position, and so on. + +If a bit is not set, then that char is not valid for that postion in the +word. + +If working with suffixes bit 0 is used for the character closest +to the front, bit 1 for the next character towards the end, ..., +with bit numconds-1 representing the last char at the end of the string. + +Note: since entries in the conds[] are 8 bits, only 8 conditions +(read that only 8 character positions) can be examined at one +end of a word (the beginning for prefixes and the end for suffixes. + +So to make this clearer, lets encode the conds array values for the +first two affentries for the suffix D described earlier. + + + For the first affentry: + numconds = 1 (only examine the last character) + + conds['e'] = (1 << 0) (the word must end in an E) + all others are all 0 + + For the second affentry: + numconds = 2 (only examine the last two characters) + + conds[X] = conds[X] | (1 << 0) (aeiou are not allowed) + where X is all characters *but* a, e, i, o, or u + + + conds['y'] = (1 << 1) (the last char must be a y) + all other bits for all other entries in the conds array are zero + + +#endif + diff --git a/hunspell/src/hunspell/affentry.hxx b/hunspell/src/hunspell/affentry.hxx new file mode 100644 index 000000000..ef1f86d34 --- /dev/null +++ b/hunspell/src/hunspell/affentry.hxx @@ -0,0 +1,134 @@ +#ifndef _AFFIX_HXX_ +#define _AFFIX_HXX_ + +#include "atypes.hxx" +#include "baseaffix.hxx" +#include "affixmgr.hxx" + +/* A Prefix Entry */ + +class PfxEntry : public AffEntry +{ + AffixMgr* pmyMgr; + + PfxEntry * next; + PfxEntry * nexteq; + PfxEntry * nextne; + PfxEntry * flgnxt; + +public: + + PfxEntry(AffixMgr* pmgr, affentry* dp ); + ~PfxEntry(); + + inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); } + struct hentry * checkword(const char * word, int len, char in_compound, + const FLAG needflag = FLAG_NULL); + + struct hentry * check_twosfx(const char * word, int len, char in_compound, const FLAG needflag = NULL); + + char * check_morph(const char * word, int len, char in_compound, + const FLAG needflag = FLAG_NULL); + + char * check_twosfx_morph(const char * word, int len, + char in_compound, const FLAG needflag = FLAG_NULL); + + inline FLAG getFlag() { return aflag; } + inline const char * getKey() { return appnd; } + char * add(const char * word, int len); + + inline short getKeyLen() { return appndl; } + + inline const char * getMorph() { return morphcode; } + + inline const unsigned short * getCont() { return contclass; } + inline short getContLen() { return contclasslen; } + + inline PfxEntry * getNext() { return next; } + inline PfxEntry * getNextNE() { return nextne; } + inline PfxEntry * getNextEQ() { return nexteq; } + inline PfxEntry * getFlgNxt() { return flgnxt; } + + inline void setNext(PfxEntry * ptr) { next = ptr; } + inline void setNextNE(PfxEntry * ptr) { nextne = ptr; } + inline void setNextEQ(PfxEntry * ptr) { nexteq = ptr; } + inline void setFlgNxt(PfxEntry * ptr) { flgnxt = ptr; } + + inline char * nextchar(char * p); + inline int test_condition(const char * st); +}; + + + + +/* A Suffix Entry */ + +class SfxEntry : public AffEntry +{ + AffixMgr* pmyMgr; + char * rappnd; + + SfxEntry * next; + SfxEntry * nexteq; + SfxEntry * nextne; + SfxEntry * flgnxt; + + SfxEntry * l_morph; + SfxEntry * r_morph; + SfxEntry * eq_morph; + +public: + + SfxEntry(AffixMgr* pmgr, affentry* dp ); + ~SfxEntry(); + + inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); } + struct hentry * checkword(const char * word, int len, int optflags, + AffEntry* ppfx, char ** wlst, int maxSug, int * ns, +// const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, char in_compound=IN_CPD_NOT); + const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, const FLAG badflag = 0); + + struct hentry * check_twosfx(const char * word, int len, int optflags, AffEntry* ppfx, const FLAG needflag = NULL); + + char * check_twosfx_morph(const char * word, int len, int optflags, + AffEntry* ppfx, const FLAG needflag = FLAG_NULL); + struct hentry * get_next_homonym(struct hentry * he); + struct hentry * get_next_homonym(struct hentry * word, int optflags, AffEntry* ppfx, + const FLAG cclass, const FLAG needflag); + + + inline FLAG getFlag() { return aflag; } + inline const char * getKey() { return rappnd; } + char * add(const char * word, int len); + + + inline const char * getMorph() { return morphcode; } + + inline const unsigned short * getCont() { return contclass; } + inline short getContLen() { return contclasslen; } + inline const char * getAffix() { return appnd; } + + inline short getKeyLen() { return appndl; } + + inline SfxEntry * getNext() { return next; } + inline SfxEntry * getNextNE() { return nextne; } + inline SfxEntry * getNextEQ() { return nexteq; } + + inline SfxEntry * getLM() { return l_morph; } + inline SfxEntry * getRM() { return r_morph; } + inline SfxEntry * getEQM() { return eq_morph; } + inline SfxEntry * getFlgNxt() { return flgnxt; } + + inline void setNext(SfxEntry * ptr) { next = ptr; } + inline void setNextNE(SfxEntry * ptr) { nextne = ptr; } + inline void setNextEQ(SfxEntry * ptr) { nexteq = ptr; } + inline void setFlgNxt(SfxEntry * ptr) { flgnxt = ptr; } + + inline char * nextchar(char * p); + inline int test_condition(const char * st, const char * begin); + +}; + +#endif + + diff --git a/hunspell/src/hunspell/affixmgr.cxx b/hunspell/src/hunspell/affixmgr.cxx new file mode 100644 index 000000000..d3e36be35 --- /dev/null +++ b/hunspell/src/hunspell/affixmgr.cxx @@ -0,0 +1,4082 @@ +#include "license.hunspell" +#include "license.myspell" + +#ifndef MOZILLA_CLIENT +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include "affixmgr.hxx" +#include "affentry.hxx" +#include "langnum.hxx" + +#include "csutil.hxx" + +#ifndef MOZILLA_CLIENT +#ifndef W32 +using namespace std; +#endif +#endif + +AffixMgr::AffixMgr(const char * affpath, HashMgr* ptr) +{ + // register hash manager and load affix data from aff file + pHMgr = ptr; + keystring = NULL; + trystring = NULL; + encoding=NULL; + utf8 = 0; + complexprefixes = 0; + maptable = NULL; + nummap = 0; + breaktable = NULL; + numbreak = 0; + reptable = NULL; + numrep = 0; + checkcpdtable = NULL; + numcheckcpd = 0; + defcpdtable = NULL; + numdefcpd = 0; + phone = NULL; + compoundflag = FLAG_NULL; // permits word in compound forms + compoundbegin = FLAG_NULL; // may be first word in compound forms + compoundmiddle = FLAG_NULL; // may be middle word in compound forms + compoundend = FLAG_NULL; // may be last word in compound forms + compoundroot = FLAG_NULL; // compound word signing flag + compoundpermitflag = FLAG_NULL; // compound permitting flag for suffixed word + compoundforbidflag = FLAG_NULL; // compound fordidden flag for suffixed word + checkcompounddup = 0; // forbid double words in compounds + checkcompoundrep = 0; // forbid bad compounds (may be non compound word with a REP substitution) + checkcompoundcase = 0; // forbid upper and lowercase combinations at word bounds + checkcompoundtriple = 0; // forbid compounds with triple letters + forbiddenword = FORBIDDENWORD; // forbidden word signing flag + nosuggest = FLAG_NULL; // don't suggest words signed with NOSUGGEST flag + lang = NULL; // language + langnum = 0; // language code (see http://l10n.openoffice.org/languages.html) + needaffix = FLAG_NULL; // forbidden root, allowed only with suffixes + cpdwordmax = -1; // default: unlimited wordcount in compound words + cpdmin = -1; // undefined + cpdmaxsyllable = 0; // default: unlimited syllablecount in compound words + cpdvowels=NULL; // vowels (for calculating of Hungarian compounding limit, O(n) search! XXX) + cpdvowels_utf16=NULL; // vowels for UTF-8 encoding (bsearch instead of O(n) search) + cpdvowels_utf16_len=0; // vowels + pfxappnd=NULL; // previous prefix for counting the syllables of prefix BUG + sfxappnd=NULL; // previous suffix for counting a special syllables BUG + cpdsyllablenum=NULL; // syllable count incrementing flag + checknum=0; // checking numbers, and word with numbers + wordchars=NULL; // letters + spec. word characters + wordchars_utf16=NULL; // letters + spec. word characters + wordchars_utf16_len=0; // letters + spec. word characters + ignorechars=NULL; // letters + spec. word characters + ignorechars_utf16=NULL; // letters + spec. word characters + ignorechars_utf16_len=0; // letters + spec. word characters + version=NULL; // affix and dictionary file version string + havecontclass=0; // flags of possible continuing classes (double affix) + // LEMMA_PRESENT: not put root into the morphological output. Lemma presents + // in morhological description in dictionary file. It's often combined with PSEUDOROOT. + lemma_present = FLAG_NULL; + circumfix = FLAG_NULL; + onlyincompound = FLAG_NULL; + flag_mode = FLAG_CHAR; // default one-character flags in affix and dic file + maxngramsugs = -1; // undefined + nosplitsugs = 0; + sugswithdots = 0; + keepcase = 0; + checksharps = 0; + substandard = FLAG_NULL; + + derived = NULL; // XXX not threadsafe variable for experimental stemming + sfx = NULL; + pfx = NULL; + + for (int i=0; i < SETSIZE; i++) { + pStart[i] = NULL; + sStart[i] = NULL; + pFlag[i] = NULL; + sFlag[i] = NULL; + } + + for (int j=0; j < CONTSIZE; j++) { + contclasses[j] = 0; + } + + if (parse_file(affpath)) { + HUNSPELL_WARNING(stderr, "Failure loading aff file %s\n",affpath); + } + + if (cpdmin == -1) cpdmin = MINCPDLEN; + +} + + +AffixMgr::~AffixMgr() +{ + + // pass through linked prefix entries and clean up + for (int i=0; i < SETSIZE ;i++) { + pFlag[i] = NULL; + PfxEntry * ptr = (PfxEntry *)pStart[i]; + PfxEntry * nptr = NULL; + while (ptr) { + nptr = ptr->getNext(); + delete(ptr); + ptr = nptr; + nptr = NULL; + } + } + + // pass through linked suffix entries and clean up + for (int j=0; j < SETSIZE ; j++) { + sFlag[j] = NULL; + SfxEntry * ptr = (SfxEntry *)sStart[j]; + SfxEntry * nptr = NULL; + while (ptr) { + nptr = ptr->getNext(); + delete(ptr); + ptr = nptr; + nptr = NULL; + } + sStart[j] = NULL; + } + + if (keystring) free(keystring); + keystring=NULL; + if (trystring) free(trystring); + trystring=NULL; + if (encoding) free(encoding); + encoding=NULL; + if (maptable) { + for (int j=0; j < nummap; j++) { + if (maptable[j].set) free(maptable[j].set); + if (maptable[j].set_utf16) free(maptable[j].set_utf16); + maptable[j].set = NULL; + maptable[j].len = 0; + } + free(maptable); + maptable = NULL; + } + nummap = 0; + if (breaktable) { + for (int j=0; j < numbreak; j++) { + if (breaktable[j]) free(breaktable[j]); + breaktable[j] = NULL; + } + free(breaktable); + breaktable = NULL; + } + numbreak = 0; + if (reptable) { + for (int j=0; j < numrep; j++) { + free(reptable[j].pattern); + free(reptable[j].pattern2); + } + free(reptable); + reptable = NULL; + } + if (phone && phone->rules) { + for (int j=0; j < phone->num + 1; j++) { + free(phone->rules[j * 2]); + free(phone->rules[j * 2 + 1]); + } + free(phone->rules); + free(phone); + phone = NULL; + } + + if (defcpdtable) { + for (int j=0; j < numdefcpd; j++) { + free(defcpdtable[j].def); + defcpdtable[j].def = NULL; + } + free(defcpdtable); + defcpdtable = NULL; + } + numrep = 0; + if (checkcpdtable) { + for (int j=0; j < numcheckcpd; j++) { + free(checkcpdtable[j].pattern); + free(checkcpdtable[j].pattern2); + checkcpdtable[j].pattern = NULL; + checkcpdtable[j].pattern2 = NULL; + } + free(checkcpdtable); + checkcpdtable = NULL; + } + numcheckcpd = 0; + FREE_FLAG(compoundflag); + FREE_FLAG(compoundbegin); + FREE_FLAG(compoundmiddle); + FREE_FLAG(compoundend); + FREE_FLAG(compoundpermitflag); + FREE_FLAG(compoundforbidflag); + FREE_FLAG(compoundroot); + FREE_FLAG(forbiddenword); + FREE_FLAG(nosuggest); + FREE_FLAG(needaffix); + FREE_FLAG(lemma_present); + FREE_FLAG(circumfix); + FREE_FLAG(onlyincompound); + + cpdwordmax = 0; + pHMgr = NULL; + cpdmin = 0; + cpdmaxsyllable = 0; + if (cpdvowels) free(cpdvowels); + if (cpdvowels_utf16) free(cpdvowels_utf16); + if (cpdsyllablenum) free(cpdsyllablenum); + free_utf_tbl(); + if (lang) free(lang); + if (wordchars) free(wordchars); + if (wordchars_utf16) free(wordchars_utf16); + if (ignorechars) free(ignorechars); + if (ignorechars_utf16) free(ignorechars_utf16); + if (version) free(version); + if (derived) free(derived); + checknum=0; +} + + +// read in aff file and build up prefix and suffix entry objects +int AffixMgr::parse_file(const char * affpath) +{ + + // io buffers + char line[MAXLNLEN+1]; + + // affix type + char ft; + + // checking flag duplication + char dupflags[CONTSIZE]; + char dupflags_ini = 1; + + // first line indicator for removing byte order mark + int firstline = 1; + + // open the affix file + FILE * afflst; + afflst = fopen(affpath,"r"); + if (!afflst) { + HUNSPELL_WARNING(stderr, "error: could not open affix description file %s\n",affpath); + return 1; + } + + // step one is to parse the affix file building up the internal + // affix data structures + + + // read in each line ignoring any that do not + // start with a known line type indicator + while (fgets(line,MAXLNLEN,afflst)) { + mychomp(line); + + /* remove byte order mark */ + if (firstline) { + firstline = 0; + if (strncmp(line,"\xEF\xBB\xBF",3) == 0) { + memmove(line, line+3, strlen(line+3)+1); + HUNSPELL_WARNING(stderr, "warning: affix file begins with byte order mark: possible incompatibility with old Hunspell versions\n"); + } + } + + /* parse in the keyboard string */ + if (strncmp(line,"KEY",3) == 0) { + if (parse_string(line, &keystring, "KEY")) { + fclose(afflst); + return 1; + } + } + + /* parse in the try string */ + if (strncmp(line,"TRY",3) == 0) { + if (parse_string(line, &trystring, "TRY")) { + fclose(afflst); + return 1; + } + } + + /* parse in the name of the character set used by the .dict and .aff */ + if (strncmp(line,"SET",3) == 0) { + if (parse_string(line, &encoding, "SET")) { + fclose(afflst); + return 1; + } + if (strcmp(encoding, "UTF-8") == 0) { + utf8 = 1; +#ifndef OPENOFFICEORG +#ifndef MOZILLA_CLIENT + if (initialize_utf_tbl()) return 1; +#endif +#endif + } + } + + /* parse COMPLEXPREFIXES for agglutinative languages with right-to-left writing system */ + if (strncmp(line,"COMPLEXPREFIXES",15) == 0) + complexprefixes = 1; + + /* parse in the flag used by the controlled compound words */ + if (strncmp(line,"COMPOUNDFLAG",12) == 0) { + if (parse_flag(line, &compoundflag, "COMPOUNDFLAG")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by compound words */ + if (strncmp(line,"COMPOUNDBEGIN",13) == 0) { + if (complexprefixes) { + if (parse_flag(line, &compoundend, "COMPOUNDBEGIN")) { + fclose(afflst); + return 1; + } + } else { + if (parse_flag(line, &compoundbegin, "COMPOUNDBEGIN")) { + fclose(afflst); + return 1; + } + } + } + + /* parse in the flag used by compound words */ + if (strncmp(line,"COMPOUNDMIDDLE",14) == 0) { + if (parse_flag(line, &compoundmiddle, "COMPOUNDMIDDLE")) { + fclose(afflst); + return 1; + } + } + /* parse in the flag used by compound words */ + if (strncmp(line,"COMPOUNDEND",11) == 0) { + if (complexprefixes) { + if (parse_flag(line, &compoundbegin, "COMPOUNDEND")) { + fclose(afflst); + return 1; + } + } else { + if (parse_flag(line, &compoundend, "COMPOUNDEND")) { + fclose(afflst); + return 1; + } + } + } + + /* parse in the data used by compound_check() method */ + if (strncmp(line,"COMPOUNDWORDMAX",15) == 0) { + if (parse_num(line, &cpdwordmax, "COMPOUNDWORDMAX")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag sign compounds in dictionary */ + if (strncmp(line,"COMPOUNDROOT",12) == 0) { + if (parse_flag(line, &compoundroot, "COMPOUNDROOT")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by compound_check() method */ + if (strncmp(line,"COMPOUNDPERMITFLAG",18) == 0) { + if (parse_flag(line, &compoundpermitflag, "COMPOUNDPERMITFLAG")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by compound_check() method */ + if (strncmp(line,"COMPOUNDFORBIDFLAG",18) == 0) { + if (parse_flag(line, &compoundforbidflag, "COMPOUNDFORBIDFLAG")) { + fclose(afflst); + return 1; + } + } + + if (strncmp(line,"CHECKCOMPOUNDDUP",16) == 0) { + checkcompounddup = 1; + } + + if (strncmp(line,"CHECKCOMPOUNDREP",16) == 0) { + checkcompoundrep = 1; + } + + if (strncmp(line,"CHECKCOMPOUNDTRIPLE",19) == 0) { + checkcompoundtriple = 1; + } + + if (strncmp(line,"CHECKCOMPOUNDCASE",17) == 0) { + checkcompoundcase = 1; + } + + if (strncmp(line,"NOSUGGEST",9) == 0) { + if (parse_flag(line, &nosuggest, "NOSUGGEST")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by forbidden words */ + if (strncmp(line,"FORBIDDENWORD",13) == 0) { + if (parse_flag(line, &forbiddenword, "FORBIDDENWORD")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by forbidden words */ + if (strncmp(line,"LEMMA_PRESENT",13) == 0) { + if (parse_flag(line, &lemma_present, "LEMMA_PRESENT")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by circumfixes */ + if (strncmp(line,"CIRCUMFIX",9) == 0) { + if (parse_flag(line, &circumfix, "CIRCUMFIX")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by fogemorphemes */ + if (strncmp(line,"ONLYINCOMPOUND",14) == 0) { + if (parse_flag(line, &onlyincompound, "ONLYINCOMPOUND")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by `needaffixs' */ + if (strncmp(line,"PSEUDOROOT",10) == 0) { + if (parse_flag(line, &needaffix, "PSEUDOROOT")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by `needaffixs' */ + if (strncmp(line,"NEEDAFFIX",9) == 0) { + if (parse_flag(line, &needaffix, "NEEDAFFIX")) { + fclose(afflst); + return 1; + } + } + + /* parse in the minimal length for words in compounds */ + if (strncmp(line,"COMPOUNDMIN",11) == 0) { + if (parse_num(line, &cpdmin, "COMPOUNDMIN")) { + fclose(afflst); + return 1; + } + if (cpdmin < 1) cpdmin = 1; + } + + /* parse in the max. words and syllables in compounds */ + if (strncmp(line,"COMPOUNDSYLLABLE",16) == 0) { + if (parse_cpdsyllable(line)) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by compound_check() method */ + if (strncmp(line,"SYLLABLENUM",11) == 0) { + if (parse_string(line, &cpdsyllablenum, "SYLLABLENUM")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by the controlled compound words */ + if (strncmp(line,"CHECKNUM",8) == 0) { + checknum=1; + } + + /* parse in the extra word characters */ + if (strncmp(line,"WORDCHARS",9) == 0) { + if (parse_array(line, &wordchars, &wordchars_utf16, &wordchars_utf16_len, "WORDCHARS", utf8)) { + fclose(afflst); + return 1; + } + } + + /* parse in the ignored characters (for example, Arabic optional diacretics charachters */ + if (strncmp(line,"IGNORE",6) == 0) { + if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) { + fclose(afflst); + return 1; + } + } + + /* parse in the typical fault correcting table */ + if (strncmp(line,"REP",3) == 0) { + if (parse_reptable(line, afflst)) { + fclose(afflst); + return 1; + } + } + + /* parse in the phonetic translation table */ + if (strncmp(line,"PHONE",5) == 0) { + if (parse_phonetable(line, afflst)) { + fclose(afflst); + return 1; + } + } + + /* parse in the checkcompoundpattern table */ + if (strncmp(line,"CHECKCOMPOUNDPATTERN",20) == 0) { + if (parse_checkcpdtable(line, afflst)) { + fclose(afflst); + return 1; + } + } + + /* parse in the defcompound table */ + if (strncmp(line,"COMPOUNDRULE",12) == 0) { + if (parse_defcpdtable(line, afflst)) { + fclose(afflst); + return 1; + } + } + + /* parse in the related character map table */ + if (strncmp(line,"MAP",3) == 0) { + if (parse_maptable(line, afflst)) { + fclose(afflst); + return 1; + } + } + + /* parse in the word breakpoints table */ + if (strncmp(line,"BREAK",5) == 0) { + if (parse_breaktable(line, afflst)) { + fclose(afflst); + return 1; + } + } + + /* parse in the language for language specific codes */ + if (strncmp(line,"LANG",4) == 0) { + if (parse_string(line, &lang, "LANG")) { + fclose(afflst); + return 1; + } + langnum = get_lang_num(lang); + } + + if (strncmp(line,"VERSION",7) == 0) { + if (parse_string(line, &version, "VERSION")) { + fclose(afflst); + return 1; + } + } + + if (strncmp(line,"MAXNGRAMSUGS",12) == 0) { + if (parse_num(line, &maxngramsugs, "MAXNGRAMSUGS")) { + fclose(afflst); + return 1; + } + } + + if (strncmp(line,"NOSPLITSUGS",11) == 0) { + nosplitsugs=1; + } + + if (strncmp(line,"SUGSWITHDOTS",12) == 0) { + sugswithdots=1; + } + + /* parse in the flag used by forbidden words */ + if (strncmp(line,"KEEPCASE",8) == 0) { + if (parse_flag(line, &keepcase, "KEEPCASE")) { + fclose(afflst); + return 1; + } + } + + /* parse in the flag used by the affix generator */ + if (strncmp(line,"SUBSTANDARD",11) == 0) { + if (parse_flag(line, &substandard, "SUBSTANDARD")) { + fclose(afflst); + return 1; + } + } + + if (strncmp(line,"CHECKSHARPS",11) == 0) { + checksharps=1; + } + + /* parse this affix: P - prefix, S - suffix */ + ft = ' '; + if (strncmp(line,"PFX",3) == 0) ft = complexprefixes ? 'S' : 'P'; + if (strncmp(line,"SFX",3) == 0) ft = complexprefixes ? 'P' : 'S'; + if (ft != ' ') { + if (dupflags_ini) { + for (int i = 0; i < CONTSIZE; i++) dupflags[i] = 0; + dupflags_ini = 0; + } + if (parse_affix(line, ft, afflst, dupflags)) { + fclose(afflst); + process_pfx_tree_to_list(); + process_sfx_tree_to_list(); + return 1; + } + } + + } + fclose(afflst); + + // convert affix trees to sorted list + process_pfx_tree_to_list(); + process_sfx_tree_to_list(); + + // now we can speed up performance greatly taking advantage of the + // relationship between the affixes and the idea of "subsets". + + // View each prefix as a potential leading subset of another and view + // each suffix (reversed) as a potential trailing subset of another. + + // To illustrate this relationship if we know the prefix "ab" is found in the + // word to examine, only prefixes that "ab" is a leading subset of need be examined. + // Furthermore is "ab" is not present then none of the prefixes that "ab" is + // is a subset need be examined. + // The same argument goes for suffix string that are reversed. + + // Then to top this off why not examine the first char of the word to quickly + // limit the set of prefixes to examine (i.e. the prefixes to examine must + // be leading supersets of the first character of the word (if they exist) + + // To take advantage of this "subset" relationship, we need to add two links + // from entry. One to take next if the current prefix is found (call it nexteq) + // and one to take next if the current prefix is not found (call it nextne). + + // Since we have built ordered lists, all that remains is to properly intialize + // the nextne and nexteq pointers that relate them + + process_pfx_order(); + process_sfx_order(); + + /* get encoding for CHECKCOMPOUNDCASE */ + char * enc = get_encoding(); + csconv = get_current_cs(enc); + free(enc); + enc = NULL; + + // temporary BREAK definition for German dash handling (OOo issue 64400) + if ((langnum == LANG_de) && (!breaktable)) { + breaktable = (char **) malloc(sizeof(char *)); + if (!breaktable) return 1; + breaktable[0] = mystrdup("-"); + numbreak = 1; + } + return 0; +} + + +// we want to be able to quickly access prefix information +// both by prefix flag, and sorted by prefix string itself +// so we need to set up two indexes + +int AffixMgr::build_pfxtree(AffEntry* pfxptr) +{ + PfxEntry * ptr; + PfxEntry * pptr; + PfxEntry * ep = (PfxEntry*) pfxptr; + + // get the right starting points + const char * key = ep->getKey(); + const unsigned char flg = (unsigned char) (ep->getFlag() & 0x00FF); + + // first index by flag which must exist + ptr = (PfxEntry*)pFlag[flg]; + ep->setFlgNxt(ptr); + pFlag[flg] = (AffEntry *) ep; + + + // handle the special case of null affix string + if (strlen(key) == 0) { + // always inset them at head of list at element 0 + ptr = (PfxEntry*)pStart[0]; + ep->setNext(ptr); + pStart[0] = (AffEntry*)ep; + return 0; + } + + // now handle the normal case + ep->setNextEQ(NULL); + ep->setNextNE(NULL); + + unsigned char sp = *((const unsigned char *)key); + ptr = (PfxEntry*)pStart[sp]; + + // handle the first insert + if (!ptr) { + pStart[sp] = (AffEntry*)ep; + return 0; + } + + + // otherwise use binary tree insertion so that a sorted + // list can easily be generated later + pptr = NULL; + for (;;) { + pptr = ptr; + if (strcmp(ep->getKey(), ptr->getKey() ) <= 0) { + ptr = ptr->getNextEQ(); + if (!ptr) { + pptr->setNextEQ(ep); + break; + } + } else { + ptr = ptr->getNextNE(); + if (!ptr) { + pptr->setNextNE(ep); + break; + } + } + } + return 0; +} + +// we want to be able to quickly access suffix information +// both by suffix flag, and sorted by the reverse of the +// suffix string itself; so we need to set up two indexes +int AffixMgr::build_sfxtree(AffEntry* sfxptr) +{ + SfxEntry * ptr; + SfxEntry * pptr; + SfxEntry * ep = (SfxEntry *) sfxptr; + + /* get the right starting point */ + const char * key = ep->getKey(); + const unsigned char flg = (unsigned char) (ep->getFlag() & 0x00FF); + + // first index by flag which must exist + ptr = (SfxEntry*)sFlag[flg]; + ep->setFlgNxt(ptr); + sFlag[flg] = (AffEntry *) ep; + + // next index by affix string + + // handle the special case of null affix string + if (strlen(key) == 0) { + // always inset them at head of list at element 0 + ptr = (SfxEntry*)sStart[0]; + ep->setNext(ptr); + sStart[0] = (AffEntry*)ep; + return 0; + } + + // now handle the normal case + ep->setNextEQ(NULL); + ep->setNextNE(NULL); + + unsigned char sp = *((const unsigned char *)key); + ptr = (SfxEntry*)sStart[sp]; + + // handle the first insert + if (!ptr) { + sStart[sp] = (AffEntry*)ep; + return 0; + } + + // otherwise use binary tree insertion so that a sorted + // list can easily be generated later + pptr = NULL; + for (;;) { + pptr = ptr; + if (strcmp(ep->getKey(), ptr->getKey() ) <= 0) { + ptr = ptr->getNextEQ(); + if (!ptr) { + pptr->setNextEQ(ep); + break; + } + } else { + ptr = ptr->getNextNE(); + if (!ptr) { + pptr->setNextNE(ep); + break; + } + } + } + return 0; +} + +// convert from binary tree to sorted list +int AffixMgr::process_pfx_tree_to_list() +{ + for (int i=1; i< SETSIZE; i++) { + pStart[i] = process_pfx_in_order(pStart[i],NULL); + } + return 0; +} + + +AffEntry* AffixMgr::process_pfx_in_order(AffEntry* ptr, AffEntry* nptr) +{ + if (ptr) { + nptr = process_pfx_in_order(((PfxEntry*) ptr)->getNextNE(), nptr); + ((PfxEntry*) ptr)->setNext((PfxEntry*) nptr); + nptr = process_pfx_in_order(((PfxEntry*) ptr)->getNextEQ(), ptr); + } + return nptr; +} + + +// convert from binary tree to sorted list +int AffixMgr:: process_sfx_tree_to_list() +{ + for (int i=1; i< SETSIZE; i++) { + sStart[i] = process_sfx_in_order(sStart[i],NULL); + } + return 0; +} + +AffEntry* AffixMgr::process_sfx_in_order(AffEntry* ptr, AffEntry* nptr) +{ + if (ptr) { + nptr = process_sfx_in_order(((SfxEntry*) ptr)->getNextNE(), nptr); + ((SfxEntry*) ptr)->setNext((SfxEntry*) nptr); + nptr = process_sfx_in_order(((SfxEntry*) ptr)->getNextEQ(), ptr); + } + return nptr; +} + + +// reinitialize the PfxEntry links NextEQ and NextNE to speed searching +// using the idea of leading subsets this time +int AffixMgr::process_pfx_order() +{ + PfxEntry* ptr; + + // loop through each prefix list starting point + for (int i=1; i < SETSIZE; i++) { + + ptr = (PfxEntry*)pStart[i]; + + // look through the remainder of the list + // and find next entry with affix that + // the current one is not a subset of + // mark that as destination for NextNE + // use next in list that you are a subset + // of as NextEQ + + for (; ptr != NULL; ptr = ptr->getNext()) { + + PfxEntry * nptr = ptr->getNext(); + for (; nptr != NULL; nptr = nptr->getNext()) { + if (! isSubset( ptr->getKey() , nptr->getKey() )) break; + } + ptr->setNextNE(nptr); + ptr->setNextEQ(NULL); + if ((ptr->getNext()) && isSubset(ptr->getKey() , (ptr->getNext())->getKey())) + ptr->setNextEQ(ptr->getNext()); + } + + // now clean up by adding smart search termination strings: + // if you are already a superset of the previous prefix + // but not a subset of the next, search can end here + // so set NextNE properly + + ptr = (PfxEntry *) pStart[i]; + for (; ptr != NULL; ptr = ptr->getNext()) { + PfxEntry * nptr = ptr->getNext(); + PfxEntry * mptr = NULL; + for (; nptr != NULL; nptr = nptr->getNext()) { + if (! isSubset(ptr->getKey(),nptr->getKey())) break; + mptr = nptr; + } + if (mptr) mptr->setNextNE(NULL); + } + } + return 0; +} + +// initialize the SfxEntry links NextEQ and NextNE to speed searching +// using the idea of leading subsets this time +int AffixMgr::process_sfx_order() +{ + SfxEntry* ptr; + + // loop through each prefix list starting point + for (int i=1; i < SETSIZE; i++) { + + ptr = (SfxEntry *) sStart[i]; + + // look through the remainder of the list + // and find next entry with affix that + // the current one is not a subset of + // mark that as destination for NextNE + // use next in list that you are a subset + // of as NextEQ + + for (; ptr != NULL; ptr = ptr->getNext()) { + SfxEntry * nptr = ptr->getNext(); + for (; nptr != NULL; nptr = nptr->getNext()) { + if (! isSubset(ptr->getKey(),nptr->getKey())) break; + } + ptr->setNextNE(nptr); + ptr->setNextEQ(NULL); + if ((ptr->getNext()) && isSubset(ptr->getKey(),(ptr->getNext())->getKey())) + ptr->setNextEQ(ptr->getNext()); + } + + + // now clean up by adding smart search termination strings: + // if you are already a superset of the previous suffix + // but not a subset of the next, search can end here + // so set NextNE properly + + ptr = (SfxEntry *) sStart[i]; + for (; ptr != NULL; ptr = ptr->getNext()) { + SfxEntry * nptr = ptr->getNext(); + SfxEntry * mptr = NULL; + for (; nptr != NULL; nptr = nptr->getNext()) { + if (! isSubset(ptr->getKey(),nptr->getKey())) break; + mptr = nptr; + } + if (mptr) mptr->setNextNE(NULL); + } + } + return 0; +} + +// calculate the character length of the condition +int AffixMgr::condlen(char * st) +{ + int l = 0; + bool group = false; + for(; *st; st++) { + if (*st == '[') { + group = true; + l++; + } else if (*st == ']') group = false; + else if (!group && (!utf8 || + (!(*st & 0x80) || ((*st & 0xc0) == 0x80)))) l++; + } + return l; +} + +int AffixMgr::encodeit(struct affentry * ptr, char * cs) +{ + if (strcmp(cs,".") != 0) { + ptr->numconds = condlen(cs); + strncpy(ptr->c.conds, cs, MAXCONDLEN); + // long condition (end of conds padded by strncpy) + if (ptr->c.conds[MAXCONDLEN - 1] && cs[MAXCONDLEN]) { + ptr->opts += aeLONGCOND; + ptr->c.l.conds2 = mystrdup(cs + MAXCONDLEN_1); + } + } else { + ptr->numconds = 0; + ptr->c.conds[0] = '\0'; + } + return 0; +} + +// return 1 if s1 is a leading subset of s2 (dots are for infixes) +inline int AffixMgr::isSubset(const char * s1, const char * s2) + { + while (((*s1 == *s2) || (*s1 == '.')) && (*s1 != '\0')) { + s1++; + s2++; + } + return (*s1 == '\0'); + } + + +// check word for prefixes +struct hentry * AffixMgr::prefix_check(const char * word, int len, char in_compound, + const FLAG needflag) +{ + struct hentry * rv= NULL; + + pfx = NULL; + pfxappnd = NULL; + sfxappnd = NULL; + + // first handle the special case of 0 length prefixes + PfxEntry * pe = (PfxEntry *) pStart[0]; + while (pe) { + if ( + // fogemorpheme + ((in_compound != IN_CPD_NOT) || !(pe->getCont() && + (TESTAFF(pe->getCont(), onlyincompound, pe->getContLen())))) && + // permit prefixes in compounds + ((in_compound != IN_CPD_END) || (pe->getCont() && + (TESTAFF(pe->getCont(), compoundpermitflag, pe->getContLen())))) + ) { + // check prefix + rv = pe->checkword(word, len, in_compound, needflag); + if (rv) { + pfx=(AffEntry *)pe; // BUG: pfx not stateless + return rv; + } + } + pe = pe->getNext(); + } + + // now handle the general case + unsigned char sp = *((const unsigned char *)word); + PfxEntry * pptr = (PfxEntry *)pStart[sp]; + + while (pptr) { + if (isSubset(pptr->getKey(),word)) { + if ( + // fogemorpheme + ((in_compound != IN_CPD_NOT) || !(pptr->getCont() && + (TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen())))) && + // permit prefixes in compounds + ((in_compound != IN_CPD_END) || (pptr->getCont() && + (TESTAFF(pptr->getCont(), compoundpermitflag, pptr->getContLen())))) + ) { + // check prefix + rv = pptr->checkword(word, len, in_compound, needflag); + if (rv) { + pfx=(AffEntry *)pptr; // BUG: pfx not stateless + return rv; + } + } + pptr = pptr->getNextEQ(); + } else { + pptr = pptr->getNextNE(); + } + } + + return NULL; +} + +// check word for prefixes +struct hentry * AffixMgr::prefix_check_twosfx(const char * word, int len, + char in_compound, const FLAG needflag) +{ + struct hentry * rv= NULL; + + pfx = NULL; + sfxappnd = NULL; + + // first handle the special case of 0 length prefixes + PfxEntry * pe = (PfxEntry *) pStart[0]; + + while (pe) { + rv = pe->check_twosfx(word, len, in_compound, needflag); + if (rv) return rv; + pe = pe->getNext(); + } + + // now handle the general case + unsigned char sp = *((const unsigned char *)word); + PfxEntry * pptr = (PfxEntry *)pStart[sp]; + + while (pptr) { + if (isSubset(pptr->getKey(),word)) { + rv = pptr->check_twosfx(word, len, in_compound, needflag); + if (rv) { + pfx = (AffEntry *)pptr; + return rv; + } + pptr = pptr->getNextEQ(); + } else { + pptr = pptr->getNextNE(); + } + } + + return NULL; +} + +// check word for prefixes +char * AffixMgr::prefix_check_morph(const char * word, int len, char in_compound, + const FLAG needflag) +{ + char * st; + + char result[MAXLNLEN]; + result[0] = '\0'; + + pfx = NULL; + sfxappnd = NULL; + + // first handle the special case of 0 length prefixes + PfxEntry * pe = (PfxEntry *) pStart[0]; + while (pe) { + st = pe->check_morph(word,len,in_compound, needflag); + if (st) { + strcat(result, st); + free(st); + } + // if (rv) return rv; + pe = pe->getNext(); + } + + // now handle the general case + unsigned char sp = *((const unsigned char *)word); + PfxEntry * pptr = (PfxEntry *)pStart[sp]; + + while (pptr) { + if (isSubset(pptr->getKey(),word)) { + st = pptr->check_morph(word,len,in_compound, needflag); + if (st) { + // fogemorpheme + if ((in_compound != IN_CPD_NOT) || !((pptr->getCont() && + (TESTAFF(pptr->getCont(), onlyincompound, pptr->getContLen()))))) { + strcat(result, st); + pfx = (AffEntry *)pptr; + } + free(st); + } + pptr = pptr->getNextEQ(); + } else { + pptr = pptr->getNextNE(); + } + } + + if (*result) return mystrdup(result); + return NULL; +} + + +// check word for prefixes +char * AffixMgr::prefix_check_twosfx_morph(const char * word, int len, + char in_compound, const FLAG needflag) +{ + char * st; + + char result[MAXLNLEN]; + result[0] = '\0'; + + pfx = NULL; + sfxappnd = NULL; + + // first handle the special case of 0 length prefixes + PfxEntry * pe = (PfxEntry *) pStart[0]; + while (pe) { + st = pe->check_twosfx_morph(word,len,in_compound, needflag); + if (st) { + strcat(result, st); + free(st); + } + pe = pe->getNext(); + } + + // now handle the general case + unsigned char sp = *((const unsigned char *)word); + PfxEntry * pptr = (PfxEntry *)pStart[sp]; + + while (pptr) { + if (isSubset(pptr->getKey(),word)) { + st = pptr->check_twosfx_morph(word, len, in_compound, needflag); + if (st) { + strcat(result, st); + free(st); + pfx = (AffEntry *)pptr; + } + pptr = pptr->getNextEQ(); + } else { + pptr = pptr->getNextNE(); + } + } + + if (*result) return mystrdup(result); + return NULL; +} + +// Is word a non compound with a REP substitution (see checkcompoundrep)? +int AffixMgr::cpdrep_check(const char * word, int wl) +{ + char candidate[MAXLNLEN]; + const char * r; + int lenr, lenp; + + if ((wl < 2) || !numrep) return 0; + + for (int i=0; i < numrep; i++ ) { + r = word; + lenr = strlen(reptable[i].pattern2); + lenp = strlen(reptable[i].pattern); + // search every occurence of the pattern in the word + while ((r=strstr(r, reptable[i].pattern)) != NULL) { + strcpy(candidate, word); + if (r-word + lenr + strlen(r+lenp) >= MAXLNLEN) break; + strcpy(candidate+(r-word),reptable[i].pattern2); + strcpy(candidate+(r-word)+lenr, r+lenp); + if (candidate_check(candidate,strlen(candidate))) return 1; + r++; // search for the next letter + } + } + return 0; +} + +// forbid compoundings when there are special patterns at word bound +int AffixMgr::cpdpat_check(const char * word, int pos) +{ + int len; + for (int i = 0; i < numcheckcpd; i++) { + if (isSubset(checkcpdtable[i].pattern2, word + pos) && + (len = strlen(checkcpdtable[i].pattern)) && (pos > len) && + (strncmp(word + pos - len, checkcpdtable[i].pattern, len) == 0)) return 1; + } + return 0; +} + +// forbid compounding with neighbouring upper and lower case characters at word bounds +int AffixMgr::cpdcase_check(const char * word, int pos) +{ + if (utf8) { + w_char u, w; + const char * p; + u8_u16(&u, 1, word + pos); + for (p = word + pos - 1; (*p & 0xc0) == 0x80; p--); + u8_u16(&w, 1, p); + unsigned short a = (u.h << 8) + u.l; + unsigned short b = (w.h << 8) + w.l; + if (((unicodetoupper(a, langnum) == a) || (unicodetoupper(b, langnum) == b))) return 1; + } else { + unsigned char a = *(word + pos - 1); + unsigned char b = *(word + pos); + if ((csconv[a].ccase || csconv[b].ccase) && (a != '-') && (b != '-')) return 1; + } + return 0; +} + +// check compound patterns +int AffixMgr::defcpd_check(hentry *** words, short wnum, hentry * rv, hentry ** def, char all) +{ + signed short btpp[MAXWORDLEN]; // metacharacter (*, ?) positions for backtracking + signed short btwp[MAXWORDLEN]; // word positions for metacharacters + int btnum[MAXWORDLEN]; // number of matched characters in metacharacter positions + short bt = 0; + int i; + int ok; + int w = 0; + if (!*words) { + w = 1; + *words = def; + } + (*words)[wnum] = rv; + + for (i = 0; i < numdefcpd; i++) { + signed short pp = 0; // pattern position + signed short wp = 0; // "words" position + int ok2; + ok = 1; + ok2 = 1; + do { + while ((pp < defcpdtable[i].len) && (wp <= wnum)) { + if (((pp+1) < defcpdtable[i].len) && + ((defcpdtable[i].def[pp+1] == '*') || (defcpdtable[i].def[pp+1] == '?'))) { + int wend = (defcpdtable[i].def[pp+1] == '?') ? wp : wnum; + ok2 = 1; + pp+=2; + btpp[bt] = pp; + btwp[bt] = wp; + while (wp <= wend) { + if (!(*words)[wp]->alen || + !TESTAFF((*words)[wp]->astr, defcpdtable[i].def[pp-2], (*words)[wp]->alen)) { + ok2 = 0; + break; + } + wp++; + } + if (wp <= wnum) ok2 = 0; + btnum[bt] = wp - btwp[bt]; + if (btnum[bt] > 0) bt++; + if (ok2) break; + } else { + ok2 = 1; + if (!(*words)[wp] || !(*words)[wp]->alen || + !TESTAFF((*words)[wp]->astr, defcpdtable[i].def[pp], (*words)[wp]->alen)) { + ok = 0; + break; + } + pp++; + wp++; + if ((defcpdtable[i].len == pp) && !(wp > wnum)) ok = 0; + } + } + if (ok && ok2) { + int r = pp; + while ((defcpdtable[i].len > r) && ((r+1) < defcpdtable[i].len) && + ((defcpdtable[i].def[r+1] == '*') || (defcpdtable[i].def[r+1] == '?'))) r+=2; + if (defcpdtable[i].len <= r) return 1; + } + // backtrack + if (bt) do { + ok = 1; + btnum[bt - 1]--; + pp = btpp[bt - 1]; + wp = btwp[bt - 1] + btnum[bt - 1]; + } while ((btnum[bt - 1] < 0) && --bt); + } while (bt); + + if (ok && ok2 && (!all || (defcpdtable[i].len <= pp))) return 1; + // check zero ending + while (ok && ok2 && (defcpdtable[i].len > pp) && ((pp+1) < defcpdtable[i].len) && + ((defcpdtable[i].def[pp+1] == '*') || (defcpdtable[i].def[pp+1] == '?'))) pp+=2; + if (ok && ok2 && (defcpdtable[i].len <= pp)) return 1; + } + (*words)[wnum] = NULL; + if (w) *words = NULL; + return 0; +} + +inline int AffixMgr::candidate_check(const char * word, int len) +{ + struct hentry * rv=NULL; + + rv = lookup(word); + if (rv) return 1; + +// rv = prefix_check(word,len,1); +// if (rv) return 1; + + rv = affix_check(word,len); + if (rv) return 1; + return 0; +} + +// calculate number of syllable for compound-checking +short AffixMgr::get_syllable(const char * word, int wlen) +{ + if (cpdmaxsyllable==0) return 0; + + short num=0; + + if (!utf8) { + for (int i=0; i 0; i--) { + if (flag_bsearch((unsigned short *) cpdvowels_utf16, + ((unsigned short *) w)[i - 1], cpdvowels_utf16_len)) num++; + } + } + return num; +} + +// check if compound word is correctly spelled +// hu_mov_rule = spec. Hungarian rule (XXX) +struct hentry * AffixMgr::compound_check(const char * word, int len, + short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words = NULL, + char hu_mov_rule = 0, int * cmpdstemnum = NULL, int * cmpdstem = NULL, char is_sug = 0) +{ + int i; + short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2; + int oldcmpdstemnum = 0; + struct hentry * rv = NULL; + struct hentry * rv_first; + struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking + char st [MAXWORDUTF8LEN + 4]; + char ch; + int cmin; + int cmax; + + int checked_prefix; + +#ifdef HUNSTEM + if (cmpdstemnum) { + if (wordnum == 0) { + *cmpdstemnum = 1; + } else { + (*cmpdstemnum)++; + } + } +#endif + if (utf8) { + for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) { + cmin++; + for (; (word[cmin] & 0xc0) == 0x80; cmin++); + } + for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) { + cmax--; + for (; (word[cmax] & 0xc0) == 0x80; cmax--); + } + } else { + cmin = cpdmin; + cmax = len - cpdmin + 1; + } + + strcpy(st, word); + + for (i = cmin; i < cmax; i++) { + + oldnumsyllable = numsyllable; + oldwordnum = wordnum; + checked_prefix = 0; + + // go to end of the UTF-8 character + if (utf8) { + for (; (st[i] & 0xc0) == 0x80; i++); + if (i >= cmax) return NULL; + } + + + ch = st[i]; + st[i] = '\0'; + + sfx = NULL; + pfx = NULL; + + // FIRST WORD + + rv = lookup(st); // perhaps without prefix + + // search homonym with compound flag + while ((rv) && !hu_mov_rule && + ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || + !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || + (compoundbegin && !wordnum && + TESTAFF(rv->astr, compoundbegin, rv->alen)) || + (compoundmiddle && wordnum && !words && + TESTAFF(rv->astr, compoundmiddle, rv->alen)) || + (numdefcpd && + ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) || + (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)))) + ))) { + rv = rv->next_homonym; + } + + if (!rv) { + if (compoundflag && + !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) { + if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, + FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule && + ((SfxEntry*)sfx)->getCont() && + ((compoundforbidflag && TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, + ((SfxEntry*)sfx)->getContLen())) || (compoundend && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, + ((SfxEntry*)sfx)->getContLen())))) { + rv = NULL; + } + } + if (rv || + (((wordnum == 0) && compoundbegin && + ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || + (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) || + ((wordnum > 0) && compoundmiddle && + ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || + (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle))))) + ) checked_prefix = 1; + // else check forbiddenwords and needaffix + } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + TESTAFF(rv->astr, needaffix, rv->alen) || + (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)) + )) { + st[i] = ch; + continue; + } + + // check non_compound flag in suffix and prefix + if ((rv) && !hu_mov_rule && + ((pfx && ((PfxEntry*)pfx)->getCont() && + TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, + ((PfxEntry*)pfx)->getContLen())) || + (sfx && ((SfxEntry*)sfx)->getCont() && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, + ((SfxEntry*)sfx)->getContLen())))) { + rv = NULL; + } + + // check compoundend flag in suffix and prefix + if ((rv) && !checked_prefix && compoundend && !hu_mov_rule && + ((pfx && ((PfxEntry*)pfx)->getCont() && + TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, + ((PfxEntry*)pfx)->getContLen())) || + (sfx && ((SfxEntry*)sfx)->getCont() && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, + ((SfxEntry*)sfx)->getContLen())))) { + rv = NULL; + } + + // check compoundmiddle flag in suffix and prefix + if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule && + ((pfx && ((PfxEntry*)pfx)->getCont() && + TESTAFF(((PfxEntry*)pfx)->getCont(), compoundmiddle, + ((PfxEntry*)pfx)->getContLen())) || + (sfx && ((SfxEntry*)sfx)->getCont() && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, + ((SfxEntry*)sfx)->getContLen())))) { + rv = NULL; + } + + // check forbiddenwords + if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) { + return NULL; + } + + // increment word number, if the second root has a compoundroot flag + if ((rv) && compoundroot && + (TESTAFF(rv->astr, compoundroot, rv->alen))) { + wordnum++; + } + + // first word is acceptable in compound words? + if (((rv) && + ( checked_prefix || (words && words[wnum]) || + (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) || + ((oldwordnum == 0) && compoundbegin && TESTAFF(rv->astr, compoundbegin, rv->alen)) || + ((oldwordnum > 0) && compoundmiddle && TESTAFF(rv->astr, compoundmiddle, rv->alen))// || +// (numdefcpd && ) + +// LANG_hu section: spec. Hungarian rule + || ((langnum == LANG_hu) && hu_mov_rule && ( + TESTAFF(rv->astr, 'F', rv->alen) || // XXX hardwired Hungarian dictionary codes + TESTAFF(rv->astr, 'G', rv->alen) || + TESTAFF(rv->astr, 'H', rv->alen) + ) + ) +// END of LANG_hu section + ) + && ! (( checkcompoundtriple && // test triple letters + (word[i-1]==word[i]) && ( + ((i>1) && (word[i-1]==word[i-2])) || + ((word[i-1]==word[i+1])) // may be word[i+1] == '\0' + ) + ) || + ( + // test CHECKCOMPOUNDPATTERN + numcheckcpd && cpdpat_check(word, i) + ) || + ( + checkcompoundcase && cpdcase_check(word, i) + )) + ) +// LANG_hu section: spec. Hungarian rule + || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) && + (sfx && ((SfxEntry*)sfx)->getCont() && ( // XXX hardwired Hungarian dic. codes + TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) || + TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen()) + ) + ) + ) +// END of LANG_hu section + ) { + +// LANG_hu section: spec. Hungarian rule + if (langnum == LANG_hu) { + // calculate syllable number of the word + numsyllable += get_syllable(st, i); + + // + 1 word, if syllable number of the prefix > 1 (hungarian convention) + if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; + } +// END of LANG_hu section + +#ifdef HUNSTEM + if (cmpdstem) cmpdstem[*cmpdstemnum - 1] = i; +#endif + + // NEXT WORD(S) + rv_first = rv; + rv = lookup((word+i)); // perhaps without prefix + + // search homonym with compound flag + while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || + !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || + (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) || + (numdefcpd && words && defcpd_check(&words, wnum + 1, rv, NULL,1))))) { + rv = rv->next_homonym; + } + + if (rv && words && words[wnum + 1]) return rv; + + oldnumsyllable2 = numsyllable; + oldwordnum2 = wordnum; + +// LANG_hu section: spec. Hungarian rule, XXX hardwired dictionary code + if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) { + numsyllable--; + } +// END of LANG_hu section + + // increment word number, if the second root has a compoundroot flag + if ((rv) && (compoundroot) && + (TESTAFF(rv->astr, compoundroot, rv->alen))) { + wordnum++; + } + + // check forbiddenwords + if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL; + + // second word is acceptable, as a root? + // hungarian conventions: compounding is acceptable, + // when compound forms consist of 2 words, or if more, + // then the syllable number of root words must be 6, or lesser. + + if ((rv) && ( + (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) || + (compoundend && TESTAFF(rv->astr, compoundend, rv->alen)) + ) + && ( + ((cpdwordmax==-1) || (wordnum+1clen)<=cpdmaxsyllable)) + ) + && ( + (!checkcompounddup || (rv != rv_first)) + ) + ) + { + // forbid compound word, if it is a non compound word with typical fault + if (checkcompoundrep && cpdrep_check(word,len)) return NULL; + return rv; + } + + numsyllable = oldnumsyllable2 ; + wordnum = oldwordnum2; + + // perhaps second word has prefix or/and suffix + sfx = NULL; + sfxflag = FLAG_NULL; + rv = (compoundflag) ? affix_check((word+i),strlen(word+i), compoundflag, IN_CPD_END) : NULL; + if (!rv && compoundend) { + sfx = NULL; + pfx = NULL; + rv = affix_check((word+i),strlen(word+i), compoundend, IN_CPD_END); + } + + if (!rv && numdefcpd && words) { + rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END); + if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv; + rv = NULL; + } + + // check non_compound flag in suffix and prefix + if ((rv) && + ((pfx && ((PfxEntry*)pfx)->getCont() && + TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, + ((PfxEntry*)pfx)->getContLen())) || + (sfx && ((SfxEntry*)sfx)->getCont() && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, + ((SfxEntry*)sfx)->getContLen())))) { + rv = NULL; + } + + // check forbiddenwords + if ((rv) && (rv->astr) && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + (is_sug && nosuggest && TESTAFF(rv->astr, nosuggest, rv->alen)))) return NULL; + + // pfxappnd = prefix of word+i, or NULL + // calculate syllable number of prefix. + // hungarian convention: when syllable number of prefix is more, + // than 1, the prefix+word counts as two words. + + if (langnum == LANG_hu) { + // calculate syllable number of the word + numsyllable += get_syllable(word + i, strlen(word + i)); + + // - affix syllable num. + // XXX only second suffix (inflections, not derivations) + if (sfxappnd) { + char * tmp = myrevstrdup(sfxappnd); + numsyllable -= get_syllable(tmp, strlen(tmp)); + free(tmp); + } + + // + 1 word, if syllable number of the prefix > 1 (hungarian convention) + if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; + + // increment syllable num, if last word has a SYLLABLENUM flag + // and the suffix is beginning `s' + + if (cpdsyllablenum) { + switch (sfxflag) { + case 'c': { numsyllable+=2; break; } + case 'J': { numsyllable += 1; break; } + case 'I': { if (TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; } + } + } + } + + // increment word number, if the second word has a compoundroot flag + if ((rv) && (compoundroot) && + (TESTAFF(rv->astr, compoundroot, rv->alen))) { + wordnum++; + } + + // second word is acceptable, as a word with prefix or/and suffix? + // hungarian conventions: compounding is acceptable, + // when compound forms consist 2 word, otherwise + // the syllable number of root words is 6, or lesser. + if ((rv) && + ( + ((cpdwordmax == -1) || (wordnum + 1 < cpdwordmax)) || + ((cpdmaxsyllable == 0) || + (numsyllable <= cpdmaxsyllable)) + ) + && ( + (!checkcompounddup || (rv != rv_first)) + )) { + // forbid compound word, if it is a non compound word with typical fault + if (checkcompoundrep && cpdrep_check(word, len)) return NULL; + return rv; + } + + numsyllable = oldnumsyllable2; + wordnum = oldwordnum2; +#ifdef HUNSTEM + if (cmpdstemnum) oldcmpdstemnum = *cmpdstemnum; +#endif + // perhaps second word is a compound word (recursive call) + if (wordnum < maxwordnum) { + rv = compound_check((word+i),strlen(word+i), wordnum+1, + numsyllable, maxwordnum, wnum + 1, words, + 0, cmpdstemnum, cmpdstem, is_sug); + } else { + rv=NULL; + } + if (rv) { + // forbid compound word, if it is a non compound word with typical fault + if (checkcompoundrep && cpdrep_check(word, len)) return NULL; + return rv; + } else { +#ifdef HUNSTEM + if (cmpdstemnum) *cmpdstemnum = oldcmpdstemnum; +#endif + } + } + st[i] = ch; + wordnum = oldwordnum; + numsyllable = oldnumsyllable; + } + + return NULL; +} + +// check if compound word is correctly spelled +// hu_mov_rule = spec. Hungarian rule (XXX) +int AffixMgr::compound_check_morph(const char * word, int len, + short wordnum, short numsyllable, short maxwordnum, short wnum, hentry ** words, + char hu_mov_rule = 0, char ** result = NULL, char * partresult = NULL) +{ + int i; + short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2; + int ok = 0; + + struct hentry * rv = NULL; + struct hentry * rv_first; + struct hentry * rwords[MAXWORDLEN]; // buffer for COMPOUND pattern checking + char st [MAXWORDUTF8LEN + 4]; + char ch; + + int checked_prefix; + char presult[MAXLNLEN]; + + int cmin; + int cmax; + + if (utf8) { + for (cmin = 0, i = 0; (i < cpdmin) && word[cmin]; i++) { + cmin++; + for (; (word[cmin] & 0xc0) == 0x80; cmin++); + } + for (cmax = len, i = 0; (i < (cpdmin - 1)) && cmax; i++) { + cmax--; + for (; (word[cmax] & 0xc0) == 0x80; cmax--); + } + } else { + cmin = cpdmin; + cmax = len - cpdmin + 1; + } + + strcpy(st, word); + + for (i = cmin; i < cmax; i++) { + oldnumsyllable = numsyllable; + oldwordnum = wordnum; + checked_prefix = 0; + + // go to end of the UTF-8 character + if (utf8) { + for (; (st[i] & 0xc0) == 0x80; i++); + if (i >= cmax) return 0; + } + + ch = st[i]; + st[i] = '\0'; + sfx = NULL; + + // FIRST WORD + *presult = '\0'; + if (partresult) strcat(presult, partresult); + + rv = lookup(st); // perhaps without prefix + + // search homonym with compound flag + while ((rv) && !hu_mov_rule && + ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || + !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || + (compoundbegin && !wordnum && + TESTAFF(rv->astr, compoundbegin, rv->alen)) || + (compoundmiddle && wordnum && !words && + TESTAFF(rv->astr, compoundmiddle, rv->alen)) || + (numdefcpd && + ((!words && !wordnum && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)) || + (words && defcpd_check(&words, wnum, rv, (hentry **) &rwords, 0)))) + ))) { + rv = rv->next_homonym; + } + + if (rv) { + sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_PART, st); + if (!HENTRY_FIND(rv, MORPH_STEM)) { + sprintf(presult + strlen(presult), "%c%s%s", MSEP_FLD, MORPH_STEM, st); + } + // store the pointer of the hash entry +// sprintf(presult + strlen(presult), "%c%s%p", MSEP_FLD, MORPH_HENTRY, rv); + if (HENTRY_DATA(rv)) { + sprintf(presult + strlen(presult), "%c%s", MSEP_FLD, HENTRY_DATA(rv)); + } + } + if (!rv) { + if (compoundflag && + !(rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundflag))) { + if ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, + FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) && !hu_mov_rule && + ((SfxEntry*)sfx)->getCont() && + ((compoundforbidflag && TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, + ((SfxEntry*)sfx)->getContLen())) || (compoundend && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, + ((SfxEntry*)sfx)->getContLen())))) { + rv = NULL; + } + } + + if (rv || + (((wordnum == 0) && compoundbegin && + ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundbegin, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || + (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundbegin)))) || + ((wordnum > 0) && compoundmiddle && + ((rv = suffix_check(st, i, 0, NULL, NULL, 0, NULL, FLAG_NULL, compoundmiddle, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || + (rv = prefix_check(st, i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, compoundmiddle))))) + ) { + // char * p = prefix_check_morph(st, i, 0, compound); + char * p = NULL; + if (compoundflag) p = affix_check_morph(st, i, compoundflag); + if (!p || (*p == '\0')) { + if (p) free(p); + p = NULL; + if ((wordnum == 0) && compoundbegin) { + p = affix_check_morph(st, i, compoundbegin); + } else if ((wordnum > 0) && compoundmiddle) { + p = affix_check_morph(st, i, compoundmiddle); + } + } + if (p && (*p != '\0')) { + sprintf(presult + strlen(presult), "%c%s%s%s", MSEP_FLD, + MORPH_PART, st, line_uniq_app(&p, MSEP_REC)); + } + if (p) free(p); + checked_prefix = 1; + } + // else check forbiddenwords + } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) || + TESTAFF(rv->astr, needaffix, rv->alen))) { + st[i] = ch; + continue; + } + + // check non_compound flag in suffix and prefix + if ((rv) && !hu_mov_rule && + ((pfx && ((PfxEntry*)pfx)->getCont() && + TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, + ((PfxEntry*)pfx)->getContLen())) || + (sfx && ((SfxEntry*)sfx)->getCont() && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, + ((SfxEntry*)sfx)->getContLen())))) { + continue; + } + + // check compoundend flag in suffix and prefix + if ((rv) && !checked_prefix && compoundend && !hu_mov_rule && + ((pfx && ((PfxEntry*)pfx)->getCont() && + TESTAFF(((PfxEntry*)pfx)->getCont(), compoundend, + ((PfxEntry*)pfx)->getContLen())) || + (sfx && ((SfxEntry*)sfx)->getCont() && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundend, + ((SfxEntry*)sfx)->getContLen())))) { + continue; + } + + // check compoundmiddle flag in suffix and prefix + if ((rv) && !checked_prefix && (wordnum==0) && compoundmiddle && !hu_mov_rule && + ((pfx && ((PfxEntry*)pfx)->getCont() && + TESTAFF(((PfxEntry*)pfx)->getCont(), compoundmiddle, + ((PfxEntry*)pfx)->getContLen())) || + (sfx && ((SfxEntry*)sfx)->getCont() && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundmiddle, + ((SfxEntry*)sfx)->getContLen())))) { + rv = NULL; + } + + // check forbiddenwords + if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) continue; + + // increment word number, if the second root has a compoundroot flag + if ((rv) && (compoundroot) && + (TESTAFF(rv->astr, compoundroot, rv->alen))) { + wordnum++; + } + + // first word is acceptable in compound words? + if (((rv) && + ( checked_prefix || (words && words[wnum]) || + (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) || + ((oldwordnum == 0) && compoundbegin && TESTAFF(rv->astr, compoundbegin, rv->alen)) || + ((oldwordnum > 0) && compoundmiddle && TESTAFF(rv->astr, compoundmiddle, rv->alen)) +// LANG_hu section: spec. Hungarian rule + || ((langnum == LANG_hu) && // hu_mov_rule + hu_mov_rule && ( + TESTAFF(rv->astr, 'F', rv->alen) || + TESTAFF(rv->astr, 'G', rv->alen) || + TESTAFF(rv->astr, 'H', rv->alen) + ) + ) +// END of LANG_hu section + ) + && ! (( checkcompoundtriple && // test triple letters + (word[i-1]==word[i]) && ( + ((i>1) && (word[i-1]==word[i-2])) || + ((word[i-1]==word[i+1])) // may be word[i+1] == '\0' + ) + ) || + ( + // test CHECKCOMPOUNDPATTERN + numcheckcpd && cpdpat_check(word, i) + ) || + ( + checkcompoundcase && cpdcase_check(word, i) + )) + ) +// LANG_hu section: spec. Hungarian rule + || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && (rv = affix_check(st,i)) && + (sfx && ((SfxEntry*)sfx)->getCont() && ( + TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) 'x', ((SfxEntry*)sfx)->getContLen()) || + TESTAFF(((SfxEntry*)sfx)->getCont(), (unsigned short) '%', ((SfxEntry*)sfx)->getContLen()) + ) + ) + ) +// END of LANG_hu section + ) { + +// LANG_hu section: spec. Hungarian rule + if (langnum == LANG_hu) { + // calculate syllable number of the word + numsyllable += get_syllable(st, i); + + // + 1 word, if syllable number of the prefix > 1 (hungarian convention) + if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; + } +// END of LANG_hu section + + // NEXT WORD(S) + rv_first = rv; + rv = lookup((word+i)); // perhaps without prefix + + // search homonym with compound flag + while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || + !((compoundflag && !words && TESTAFF(rv->astr, compoundflag, rv->alen)) || + (compoundend && !words && TESTAFF(rv->astr, compoundend, rv->alen)) || + (numdefcpd && defcpd_check(&words, wnum + 1, rv, NULL,1))))) { + rv = rv->next_homonym; + } + + if (rv && words && words[wnum + 1]) { + strcat(*result, presult); + strcat(*result, " "); + strcat(*result, MORPH_PART); + strcat(*result, word+i); + if (complexprefixes && HENTRY_DATA(rv)) strcat(*result, HENTRY_DATA(rv)); + if (!HENTRY_FIND(rv, MORPH_STEM)) { + strcat(*result, " "); + strcat(*result, MORPH_STEM); + strcat(*result, HENTRY_WORD(rv)); + } + // store the pointer of the hash entry +// sprintf(*result + strlen(*result), " %s%p", MORPH_HENTRY, rv); + if (!complexprefixes && HENTRY_DATA(rv)) { + strcat(*result, " "); + strcat(*result, HENTRY_DATA(rv)); + } + strcat(*result, "\n"); + ok = 1; + return 0; + } + + oldnumsyllable2 = numsyllable; + oldwordnum2 = wordnum; + +// LANG_hu section: spec. Hungarian rule + if ((rv) && (langnum == LANG_hu) && (TESTAFF(rv->astr, 'I', rv->alen)) && !(TESTAFF(rv->astr, 'J', rv->alen))) { + numsyllable--; + } +// END of LANG_hu section + // increment word number, if the second root has a compoundroot flag + if ((rv) && (compoundroot) && + (TESTAFF(rv->astr, compoundroot, rv->alen))) { + wordnum++; + } + + // check forbiddenwords + if ((rv) && (rv->astr) && TESTAFF(rv->astr, forbiddenword, rv->alen)) { + st[i] = ch; + continue; + } + + // second word is acceptable, as a root? + // hungarian conventions: compounding is acceptable, + // when compound forms consist of 2 words, or if more, + // then the syllable number of root words must be 6, or lesser. + if ((rv) && ( + (compoundflag && TESTAFF(rv->astr, compoundflag, rv->alen)) || + (compoundend && TESTAFF(rv->astr, compoundend, rv->alen)) + ) + && ( + ((cpdwordmax==-1) || (wordnum+1blen)<=cpdmaxsyllable)) + ) + && ( + (!checkcompounddup || (rv != rv_first)) + ) + ) + { + // bad compound word + strcat(*result, presult); + strcat(*result, " "); + strcat(*result, MORPH_PART); + strcat(*result, word+i); + + if (HENTRY_DATA(rv)) { + if (complexprefixes) strcat(*result, HENTRY_DATA(rv)); + if (! HENTRY_FIND(rv, MORPH_STEM)) { + strcat(*result, " "); + strcat(*result, MORPH_STEM); + strcat(*result, HENTRY_WORD(rv)); + } + // store the pointer of the hash entry +// sprintf(*result + strlen(*result), " %s%p", MORPH_HENTRY, rv); + if (!complexprefixes) { + strcat(*result, " "); + strcat(*result, HENTRY_DATA(rv)); + } + } + strcat(*result, "\n"); + ok = 1; + } + + numsyllable = oldnumsyllable2 ; + wordnum = oldwordnum2; + + // perhaps second word has prefix or/and suffix + sfx = NULL; + sfxflag = FLAG_NULL; + + if (compoundflag) rv = affix_check((word+i),strlen(word+i), compoundflag); else rv = NULL; + + if (!rv && compoundend) { + sfx = NULL; + pfx = NULL; + rv = affix_check((word+i),strlen(word+i), compoundend); + } + + if (!rv && numdefcpd && words) { + rv = affix_check((word+i),strlen(word+i), 0, IN_CPD_END); + if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) { + char * m = NULL; + if (compoundflag) m = affix_check_morph((word+i),strlen(word+i), compoundflag); + if ((!m || *m == '\0') && compoundend) { + if (m) free(m); + m = affix_check_morph((word+i),strlen(word+i), compoundend); + } + strcat(*result, presult); + if (m || (*m != '\0')) { + sprintf(*result + strlen(*result), "%c%s%s%s", MSEP_FLD, + MORPH_PART, word + i, line_uniq_app(&m, MSEP_REC)); + } + if (m) free(m); + strcat(*result, "\n"); + ok = 1; + } + } + + // check non_compound flag in suffix and prefix + if ((rv) && + ((pfx && ((PfxEntry*)pfx)->getCont() && + TESTAFF(((PfxEntry*)pfx)->getCont(), compoundforbidflag, + ((PfxEntry*)pfx)->getContLen())) || + (sfx && ((SfxEntry*)sfx)->getCont() && + TESTAFF(((SfxEntry*)sfx)->getCont(), compoundforbidflag, + ((SfxEntry*)sfx)->getContLen())))) { + rv = NULL; + } + + // check forbiddenwords + if ((rv) && (rv->astr) && (TESTAFF(rv->astr,forbiddenword,rv->alen)) + && (! TESTAFF(rv->astr, needaffix, rv->alen))) { + st[i] = ch; + continue; + } + + if (langnum == LANG_hu) { + // calculate syllable number of the word + numsyllable += get_syllable(word + i, strlen(word + i)); + + // - affix syllable num. + // XXX only second suffix (inflections, not derivations) + if (sfxappnd) { + char * tmp = myrevstrdup(sfxappnd); + numsyllable -= get_syllable(tmp, strlen(tmp)); + free(tmp); + } + + // + 1 word, if syllable number of the prefix > 1 (hungarian convention) + if (pfx && (get_syllable(((PfxEntry *)pfx)->getKey(),strlen(((PfxEntry *)pfx)->getKey())) > 1)) wordnum++; + + // increment syllable num, if last word has a SYLLABLENUM flag + // and the suffix is beginning `s' + + if (cpdsyllablenum) { + switch (sfxflag) { + case 'c': { numsyllable+=2; break; } + case 'J': { numsyllable += 1; break; } + case 'I': { if (rv && TESTAFF(rv->astr, 'J', rv->alen)) numsyllable += 1; break; } + } + } + } + + // increment word number, if the second word has a compoundroot flag + if ((rv) && (compoundroot) && + (TESTAFF(rv->astr, compoundroot, rv->alen))) { + wordnum++; + } + // second word is acceptable, as a word with prefix or/and suffix? + // hungarian conventions: compounding is acceptable, + // when compound forms consist 2 word, otherwise + // the syllable number of root words is 6, or lesser. + if ((rv) && + ( + ((cpdwordmax==-1) || (wordnum+1 0) && *s1 && (*s1 == *end_of_s2)) { + s1++; + end_of_s2--; + len--; + } + return (*s1 == '\0'); + } + */ + +inline int AffixMgr::isRevSubset(const char * s1, const char * end_of_s2, int len) + { + while ((len > 0) && (*s1 != '\0') && ((*s1 == *end_of_s2) || (*s1 == '.'))) { + s1++; + end_of_s2--; + len--; + } + return (*s1 == '\0'); + } + +// check word for suffixes + +struct hentry * AffixMgr::suffix_check (const char * word, int len, + int sfxopts, AffEntry * ppfx, char ** wlst, int maxSug, int * ns, + const FLAG cclass, const FLAG needflag, char in_compound) +{ + struct hentry * rv = NULL; + char result[MAXLNLEN]; + + PfxEntry* ep = (PfxEntry *) ppfx; + + // first handle the special case of 0 length suffixes + SfxEntry * se = (SfxEntry *) sStart[0]; + + while (se) { + if (!cclass || se->getCont()) { + // suffixes are not allowed in beginning of compounds + if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass + // except when signed with compoundpermitflag flag + (se->getCont() && compoundpermitflag && + TESTAFF(se->getCont(),compoundpermitflag,se->getContLen()))) && (!circumfix || + // no circumfix flag in prefix and suffix + ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(), + circumfix, ep->getContLen())) && + (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) || + // circumfix flag in prefix AND suffix + ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(), + circumfix, ep->getContLen())) && + (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen()))))) && + // fogemorpheme + (in_compound || + !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) && + // needaffix on prefix or first suffix + (cclass || + !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) || + (ppfx && !((ep->getCont()) && + TESTAFF(ep->getCont(), needaffix, + ep->getContLen()))) + ) + ) { + rv = se->checkword(word,len, sfxopts, ppfx, wlst, maxSug, ns, (FLAG) cclass, + needflag, (in_compound ? 0 : onlyincompound)); + if (rv) { + sfx=(AffEntry *)se; // BUG: sfx not stateless + return rv; + } + } + } + se = se->getNext(); + } + + // now handle the general case + unsigned char sp = *((const unsigned char *)(word + len - 1)); + SfxEntry * sptr = (SfxEntry *) sStart[sp]; + + while (sptr) { + if (isRevSubset(sptr->getKey(), word + len - 1, len) + ) { + // suffixes are not allowed in beginning of compounds + if ((((in_compound != IN_CPD_BEGIN)) || // && !cclass + // except when signed with compoundpermitflag flag + (sptr->getCont() && compoundpermitflag && + TESTAFF(sptr->getCont(),compoundpermitflag,sptr->getContLen()))) && (!circumfix || + // no circumfix flag in prefix and suffix + ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(), + circumfix, ep->getContLen())) && + (!sptr->getCont() || !(TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))) || + // circumfix flag in prefix AND suffix + ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(), + circumfix, ep->getContLen())) && + (sptr->getCont() && (TESTAFF(sptr->getCont(),circumfix,sptr->getContLen()))))) && + // fogemorpheme + (in_compound || + !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) && + // needaffix on prefix or first suffix + (cclass || + !(sptr->getCont() && TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) || + (ppfx && !((ep->getCont()) && + TESTAFF(ep->getCont(), needaffix, + ep->getContLen()))) + ) + ) { + rv = sptr->checkword(word,len, sfxopts, ppfx, wlst, + maxSug, ns, cclass, needflag, (in_compound ? 0 : onlyincompound)); + if (rv) { + sfx=(AffEntry *)sptr; // BUG: sfx not stateless + sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless + if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless + if (cclass || sptr->getCont()) { + if (!derived) { + derived = mystrdup(word); + } else { + strcat(result, " "); + strcpy(result, MORPH_STEM); + strcpy(result, derived); // XXX check size + strcat(result, "\n"); + strcat(result, " "); + strcat(result, MORPH_STEM); + strcat(result, word); + // store the pointer of the hash entry +// sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, rv); + free(derived); + derived = mystrdup(result); + } + } + return rv; + } + } + sptr = sptr->getNextEQ(); + } else { + sptr = sptr->getNextNE(); + } + } + + return NULL; +} + +// check word for two-level suffixes + +struct hentry * AffixMgr::suffix_check_twosfx(const char * word, int len, + int sfxopts, AffEntry * ppfx, const FLAG needflag) +{ + struct hentry * rv = NULL; + + // first handle the special case of 0 length suffixes + SfxEntry * se = (SfxEntry *) sStart[0]; + while (se) { + if (contclasses[se->getFlag()]) + { + rv = se->check_twosfx(word,len, sfxopts, ppfx, needflag); + if (rv) return rv; + } + se = se->getNext(); + } + + // now handle the general case + unsigned char sp = *((const unsigned char *)(word + len - 1)); + SfxEntry * sptr = (SfxEntry *) sStart[sp]; + + while (sptr) { + if (isRevSubset(sptr->getKey(), word + len - 1, len)) { + if (contclasses[sptr->getFlag()]) + { + rv = sptr->check_twosfx(word,len, sfxopts, ppfx, needflag); + if (rv) { + sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless + if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless + return rv; + } + } + sptr = sptr->getNextEQ(); + } else { + sptr = sptr->getNextNE(); + } + } + + return NULL; +} + +char * AffixMgr::suffix_check_twosfx_morph(const char * word, int len, + int sfxopts, AffEntry * ppfx, const FLAG needflag) +{ + char result[MAXLNLEN]; + char result2[MAXLNLEN]; + char result3[MAXLNLEN]; + + char * st; + + result[0] = '\0'; + result2[0] = '\0'; + result3[0] = '\0'; + + // first handle the special case of 0 length suffixes + SfxEntry * se = (SfxEntry *) sStart[0]; + while (se) { + if (contclasses[se->getFlag()]) + { + st = se->check_twosfx_morph(word,len, sfxopts, ppfx, needflag); + if (st) { + if (ppfx) { + if (((PfxEntry *) ppfx)->getMorph()) { + strcat(result, ((PfxEntry *) ppfx)->getMorph()); + strcat(result, " "); + } + } + strcat(result, st); + free(st); + if (se->getMorph()) { + strcat(result, " "); + strcat(result, se->getMorph()); + } + strcat(result, "\n"); + } + } + se = se->getNext(); + } + + // now handle the general case + unsigned char sp = *((const unsigned char *)(word + len - 1)); + SfxEntry * sptr = (SfxEntry *) sStart[sp]; + + while (sptr) { + if (isRevSubset(sptr->getKey(), word + len - 1, len)) { + if (contclasses[sptr->getFlag()]) + { + st = sptr->check_twosfx_morph(word,len, sfxopts, ppfx, needflag); + if (st) { + sfxflag = sptr->getFlag(); // BUG: sfxflag not stateless + if (!sptr->getCont()) sfxappnd=sptr->getKey(); // BUG: sfxappnd not stateless + strcpy(result2, st); + free(st); + + result3[0] = '\0'; +#ifdef DEBUG + unsigned short flag = sptr->getFlag(); + if (flag_mode == FLAG_NUM) { + sprintf(result3, "<%d>", sptr->getKey()); + } else if (flag_mode == FLAG_LONG) { + sprintf(result3, "<%c%c>", flag >> 8, (flag << 8) >>8); + } else sprintf(result3, "<%c>", flag); + strcat(result3, ":"); +#endif + if (sptr->getMorph()) { + strcat(result3, " "); + strcat(result3, sptr->getMorph()); + } + strlinecat(result2, result3); + strcat(result2, "\n"); + strcat(result, result2); + } + } + sptr = sptr->getNextEQ(); + } else { + sptr = sptr->getNextNE(); + } + } + if (result) return mystrdup(result); + return NULL; +} + +char * AffixMgr::suffix_check_morph(const char * word, int len, + int sfxopts, AffEntry * ppfx, const FLAG cclass, const FLAG needflag, char in_compound) +{ + char result[MAXLNLEN]; + + struct hentry * rv = NULL; + + result[0] = '\0'; + + PfxEntry* ep = (PfxEntry *) ppfx; + + // first handle the special case of 0 length suffixes + SfxEntry * se = (SfxEntry *) sStart[0]; + while (se) { + if (!cclass || se->getCont()) { + // suffixes are not allowed in beginning of compounds + if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass + // except when signed with compoundpermitflag flag + (se->getCont() && compoundpermitflag && + TESTAFF(se->getCont(),compoundpermitflag,se->getContLen()))) && (!circumfix || + // no circumfix flag in prefix and suffix + ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(), + circumfix, ep->getContLen())) && + (!se->getCont() || !(TESTAFF(se->getCont(),circumfix,se->getContLen())))) || + // circumfix flag in prefix AND suffix + ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(), + circumfix, ep->getContLen())) && + (se->getCont() && (TESTAFF(se->getCont(),circumfix,se->getContLen()))))) && + // fogemorpheme + (in_compound || + !((se->getCont() && (TESTAFF(se->getCont(), onlyincompound, se->getContLen()))))) && + // needaffix on prefix or first suffix + (cclass || + !(se->getCont() && TESTAFF(se->getCont(), needaffix, se->getContLen())) || + (ppfx && !((ep->getCont()) && + TESTAFF(ep->getCont(), needaffix, + ep->getContLen()))) + ) + )) + rv = se->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag); + while (rv) { + if (ppfx) { + if (((PfxEntry *) ppfx)->getMorph()) { + strcat(result, ((PfxEntry *) ppfx)->getMorph()); + strcat(result, " "); + } + } + if (complexprefixes && HENTRY_DATA(rv)) strcat(result, HENTRY_DATA(rv)); + if (! HENTRY_FIND(rv, MORPH_STEM)) { + strcat(result, " "); + strcat(result, MORPH_STEM); + strcat(result, HENTRY_WORD(rv)); + } + // store the pointer of the hash entry +// sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, rv); + + if (!complexprefixes && HENTRY_DATA(rv)) { + strcat(result, " "); + strcat(result, HENTRY_DATA(rv)); + } + if (se->getMorph()) { + strcat(result, " "); + strcat(result, se->getMorph()); + } + strcat(result, "\n"); + rv = se->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag); + } + } + se = se->getNext(); + } + + // now handle the general case + unsigned char sp = *((const unsigned char *)(word + len - 1)); + SfxEntry * sptr = (SfxEntry *) sStart[sp]; + + while (sptr) { + if (isRevSubset(sptr->getKey(), word + len - 1, len) + ) { + // suffixes are not allowed in beginning of compounds + if (((((in_compound != IN_CPD_BEGIN)) || // && !cclass + // except when signed with compoundpermitflag flag + (sptr->getCont() && compoundpermitflag && + TESTAFF(sptr->getCont(),compoundpermitflag,sptr->getContLen()))) && (!circumfix || + // no circumfix flag in prefix and suffix + ((!ppfx || !(ep->getCont()) || !TESTAFF(ep->getCont(), + circumfix, ep->getContLen())) && + (!sptr->getCont() || !(TESTAFF(sptr->getCont(),circumfix,sptr->getContLen())))) || + // circumfix flag in prefix AND suffix + ((ppfx && (ep->getCont()) && TESTAFF(ep->getCont(), + circumfix, ep->getContLen())) && + (sptr->getCont() && (TESTAFF(sptr->getCont(),circumfix,sptr->getContLen()))))) && + // fogemorpheme + (in_compound || + !((sptr->getCont() && (TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen()))))) && + // needaffix on first suffix + (cclass || !(sptr->getCont() && + TESTAFF(sptr->getCont(), needaffix, sptr->getContLen()))) + )) rv = sptr->checkword(word,len, sfxopts, ppfx, NULL, 0, 0, cclass, needflag); + while (rv) { + if (ppfx) { + if (((PfxEntry *) ppfx)->getMorph()) { + strcat(result, ((PfxEntry *) ppfx)->getMorph()); + strcat(result, " "); + } + } + if (complexprefixes && HENTRY_DATA(rv)) strcat(result, HENTRY_DATA(rv)); + if (! HENTRY_FIND(rv, MORPH_STEM)) { + strcat(result, " "); + strcat(result, MORPH_STEM); + strcat(result, HENTRY_WORD(rv)); + } + // store the pointer of the hash entry +// sprintf(result + strlen(result), " %s%p", MORPH_HENTRY, rv); + + if (!complexprefixes && HENTRY_DATA(rv)) { + strcat(result, " "); + strcat(result, HENTRY_DATA(rv)); + } +#ifdef DEBUG + unsigned short flag = sptr->getFlag(); + if (flag_mode == FLAG_NUM) { + sprintf(result, "<%d>", sptr->getKey()); + } else if (flag_mode == FLAG_LONG) { + sprintf(result, "<%c%c>", flag >> 8, (flag << 8) >>8); + } else sprintf(result, "<%c>", flag); + strcat(result, ":"); +#endif + + if (sptr->getMorph()) { + strcat(result, " "); + strcat(result, sptr->getMorph()); + } + strcat(result, "\n"); + rv = sptr->get_next_homonym(rv, sfxopts, ppfx, cclass, needflag); + } + sptr = sptr->getNextEQ(); + } else { + sptr = sptr->getNextNE(); + } + } + + if (*result) return mystrdup(result); + return NULL; +} + +// check if word with affixes is correctly spelled +struct hentry * AffixMgr::affix_check (const char * word, int len, const FLAG needflag, char in_compound) +{ + struct hentry * rv= NULL; + if (derived) free(derived); + derived = NULL; + + // check all prefixes (also crossed with suffixes if allowed) + rv = prefix_check(word, len, in_compound, needflag); + if (rv) return rv; + + // if still not found check all suffixes + rv = suffix_check(word, len, 0, NULL, NULL, 0, NULL, FLAG_NULL, needflag, in_compound); + + if (havecontclass) { + sfx = NULL; + pfx = NULL; + if (rv) return rv; + // if still not found check all two-level suffixes + rv = suffix_check_twosfx(word, len, 0, NULL, needflag); + if (rv) return rv; + // if still not found check all two-level suffixes + rv = prefix_check_twosfx(word, len, IN_CPD_NOT, needflag); + } + return rv; +} + +// check if word with affixes is correctly spelled +char * AffixMgr::affix_check_morph(const char * word, int len, const FLAG needflag, char in_compound) +{ + char result[MAXLNLEN]; + char * st = NULL; + + *result = '\0'; + + // check all prefixes (also crossed with suffixes if allowed) + st = prefix_check_morph(word, len, in_compound); + if (st) { + strcat(result, st); + free(st); + } + + // if still not found check all suffixes + st = suffix_check_morph(word, len, 0, NULL, '\0', needflag, in_compound); + if (st) { + strcat(result, st); + free(st); + } + + if (havecontclass) { + sfx = NULL; + pfx = NULL; + // if still not found check all two-level suffixes + st = suffix_check_twosfx_morph(word, len, 0, NULL, needflag); + if (st) { + strcat(result, st); + free(st); + } + + // if still not found check all two-level suffixes + st = prefix_check_twosfx_morph(word, len, IN_CPD_NOT, needflag); + if (st) { + strcat(result, st); + free(st); + } + } + + return mystrdup(result); +} + +char * AffixMgr::morphgen(char * ts, int wl, const unsigned short * ap, + unsigned short al, char * morph, char * targetmorph, int level) +{ + // handle suffixes + char * stemmorph; + char * stemmorphcatpos; + char mymorph[MAXLNLEN]; + + if (!morph && !targetmorph) return NULL; + + // check substandard flag + if (TESTAFF(ap, substandard, al)) return NULL; + + if (morphcmp(morph, targetmorph) == 0) return mystrdup(ts); + +// int targetcount = get_sfxcount(targetmorph); + + // use input suffix fields, if exist + if (strstr(morph, MORPH_INFL_SFX) || strstr(morph, MORPH_DERI_SFX)) { + stemmorph = mymorph; + strcpy(stemmorph, morph); + strcat(stemmorph, " "); + stemmorphcatpos = stemmorph + strlen(stemmorph); + } else { + stemmorph = morph; + stemmorphcatpos = NULL; + } + + for (int i = 0; i < al; i++) { + const unsigned char c = (unsigned char) (ap[i] & 0x00FF); + SfxEntry * sptr = (SfxEntry *)sFlag[c]; + while (sptr) { + if (sptr->getFlag() == ap[i] && ((sptr->getContLen() == 0) || + // don't generate forms with substandard affixes + !TESTAFF(sptr->getCont(), substandard, sptr->getContLen()))) { + + if (stemmorphcatpos) strcpy(stemmorphcatpos, sptr->getMorph()); + else stemmorph = (char *) sptr->getMorph(); + + int cmp = morphcmp(stemmorph, targetmorph); + + if (cmp == 0) { + char * newword = sptr->add(ts, wl); + if (newword) { + hentry * check = pHMgr->lookup(newword); + if (!check || !check->astr || + !TESTAFF(check->astr, forbiddenword, check->alen)) { + return newword; + } + free(newword); + } + } + + // recursive call for secondary suffixes + if ((level == 0) && (cmp == 1) && (sptr->getContLen() > 0) && +// (get_sfxcount(stemmorph) < targetcount) && + !TESTAFF(sptr->getCont(), substandard, sptr->getContLen())) { + char * newword = sptr->add(ts, wl); + if (newword) { + char * newword2 = morphgen(newword, strlen(newword), sptr->getCont(), + sptr->getContLen(), stemmorph, targetmorph, 1); + + if (newword2) { + free(newword); + return newword2; + } + free(newword); + newword = NULL; + } + } + } + sptr = (SfxEntry *)sptr ->getFlgNxt(); + } + } + return NULL; +} + + +int AffixMgr::expand_rootword(struct guessword * wlst, int maxn, const char * ts, + int wl, const unsigned short * ap, unsigned short al, char * bad, int badl, + char * phone) +{ + int nh=0; + // first add root word to list + if ((nh < maxn) && !(al && ((needaffix && TESTAFF(ap, needaffix, al)) || + (onlyincompound && TESTAFF(ap, onlyincompound, al))))) { + wlst[nh].word = mystrdup(ts); + wlst[nh].allow = (1 == 0); + wlst[nh].orig = NULL; + nh++; + // add special phonetic version + if (phone && (nh < maxn)) { + wlst[nh].word = mystrdup(phone); + wlst[nh].allow = (1 == 0); + wlst[nh].orig = mystrdup(ts); + nh++; + } + } + + // handle suffixes + for (int i = 0; i < al; i++) { + const unsigned char c = (unsigned char) (ap[i] & 0x00FF); + SfxEntry * sptr = (SfxEntry *)sFlag[c]; + while (sptr) { + if ((sptr->getFlag() == ap[i]) && (!sptr->getKeyLen() || ((badl > sptr->getKeyLen()) && + (strcmp(sptr->getAffix(), bad + badl - sptr->getKeyLen()) == 0))) && + // check needaffix flag + !(sptr->getCont() && ((needaffix && + TESTAFF(sptr->getCont(), needaffix, sptr->getContLen())) || + (circumfix && + TESTAFF(sptr->getCont(), circumfix, sptr->getContLen())) || + (onlyincompound && + TESTAFF(sptr->getCont(), onlyincompound, sptr->getContLen())))) + ) { + char * newword = sptr->add(ts, wl); + if (newword) { + if (nh < maxn) { + wlst[nh].word = newword; + wlst[nh].allow = sptr->allowCross(); + wlst[nh].orig = NULL; + nh++; + // add special phonetic version + if (phone && (nh < maxn)) { + char st[MAXWORDUTF8LEN]; + strcpy(st, phone); + strcat(st, sptr->getKey()); + reverseword(st + strlen(phone)); + wlst[nh].word = mystrdup(st); + wlst[nh].allow = (1 == 0); + wlst[nh].orig = mystrdup(newword); + nh++; + } + } else { + free(newword); + } + } + } + sptr = (SfxEntry *)sptr ->getFlgNxt(); + } + } + + int n = nh; + + // handle cross products of prefixes and suffixes + for (int j=1;jgetFlag() == ap[k]) && cptr->allowCross() && (!cptr->getKeyLen() || ((badl > cptr->getKeyLen()) && + (strncmp(cptr->getKey(), bad, cptr->getKeyLen()) == 0)))) { + int l1 = strlen(wlst[j].word); + char * newword = cptr->add(wlst[j].word, l1); + if (newword) { + if (nh < maxn) { + wlst[nh].word = newword; + wlst[nh].allow = cptr->allowCross(); + wlst[nh].orig = NULL; + nh++; + } else { + free(newword); + } + } + } + cptr = (PfxEntry *)cptr ->getFlgNxt(); + } + } + } + + + // now handle pure prefixes + for (int m = 0; m < al; m ++) { + const unsigned char c = (unsigned char) (ap[m] & 0x00FF); + PfxEntry * ptr = (PfxEntry *) pFlag[c]; + while (ptr) { + if ((ptr->getFlag() == ap[m]) && (!ptr->getKeyLen() || ((badl > ptr->getKeyLen()) && + (strncmp(ptr->getKey(), bad, ptr->getKeyLen()) == 0))) && + // check needaffix flag + !(ptr->getCont() && ((needaffix && + TESTAFF(ptr->getCont(), needaffix, ptr->getContLen())) || + (circumfix && + TESTAFF(ptr->getCont(), circumfix, ptr->getContLen())) || + (onlyincompound && + TESTAFF(ptr->getCont(), onlyincompound, ptr->getContLen())))) + ) { + char * newword = ptr->add(ts, wl); + if (newword) { + if (nh < maxn) { + wlst[nh].word = newword; + wlst[nh].allow = ptr->allowCross(); + wlst[nh].orig = NULL; + nh++; + } else { + free(newword); + } + } + } + ptr = (PfxEntry *)ptr ->getFlgNxt(); + } + } + + return nh; +} + +// return length of replacing table +int AffixMgr::get_numrep() +{ + return numrep; +} + +// return replacing table +struct replentry * AffixMgr::get_reptable() +{ + if (! reptable ) return NULL; + return reptable; +} + +// return replacing table +struct phonetable * AffixMgr::get_phonetable() +{ + if (! phone ) return NULL; + return phone; +} + +// return length of character map table +int AffixMgr::get_nummap() +{ + return nummap; +} + +// return character map table +struct mapentry * AffixMgr::get_maptable() +{ + if (! maptable ) return NULL; + return maptable; +} + +// return length of word break table +int AffixMgr::get_numbreak() +{ + return numbreak; +} + +// return character map table +char ** AffixMgr::get_breaktable() +{ + if (! breaktable ) return NULL; + return breaktable; +} + +// return text encoding of dictionary +char * AffixMgr::get_encoding() +{ + if (! encoding ) { + encoding = mystrdup("ISO8859-1"); + } + return mystrdup(encoding); +} + +// return text encoding of dictionary +int AffixMgr::get_langnum() +{ + return langnum; +} + +// return double prefix option +int AffixMgr::get_complexprefixes() +{ + return complexprefixes; +} + +FLAG AffixMgr::get_keepcase() +{ + return keepcase; +} + +int AffixMgr::get_checksharps() +{ + return checksharps; +} + +// return the preferred ignore string for suggestions +char * AffixMgr::get_ignore() +{ + if (!ignorechars) return NULL; + return ignorechars; +} + +// return the preferred ignore string for suggestions +unsigned short * AffixMgr::get_ignore_utf16(int * len) +{ + *len = ignorechars_utf16_len; + return ignorechars_utf16; +} + +// return the keyboard string for suggestions +char * AffixMgr::get_key_string() +{ + if (! keystring ) return NULL; + return mystrdup(keystring); +} + +// return the preferred try string for suggestions +char * AffixMgr::get_try_string() +{ + if (! trystring ) return NULL; + return mystrdup(trystring); +} + +// return the preferred try string for suggestions +const char * AffixMgr::get_wordchars() +{ + return wordchars; +} + +unsigned short * AffixMgr::get_wordchars_utf16(int * len) +{ + *len = wordchars_utf16_len; + return wordchars_utf16; +} + +// is there compounding? +int AffixMgr::get_compound() +{ + return compoundflag || compoundbegin || numdefcpd; +} + +// return the compound words control flag +FLAG AffixMgr::get_compoundflag() +{ + return compoundflag; +} + +// return the forbidden words control flag +FLAG AffixMgr::get_forbiddenword() +{ + return forbiddenword; +} + +// return the forbidden words control flag +FLAG AffixMgr::get_nosuggest() +{ + return nosuggest; +} + +// return the forbidden words flag modify flag +FLAG AffixMgr::get_needaffix() +{ + return needaffix; +} + +// return the onlyincompound flag +FLAG AffixMgr::get_onlyincompound() +{ + return onlyincompound; +} + +// return the compound word signal flag +FLAG AffixMgr::get_compoundroot() +{ + return compoundroot; +} + +// return the compound begin signal flag +FLAG AffixMgr::get_compoundbegin() +{ + return compoundbegin; +} + +// return the value of checknum +int AffixMgr::get_checknum() +{ + return checknum; +} + +// return the value of prefix +const char * AffixMgr::get_prefix() +{ + if (pfx) return ((PfxEntry *)pfx)->getKey(); + return NULL; +} + +// return the value of suffix +const char * AffixMgr::get_suffix() +{ + return sfxappnd; +} + +// return the value of derived form (base word with first suffix). +const char * AffixMgr::get_derived() +{ + return derived; +} + +// return the value of suffix +const char * AffixMgr::get_version() +{ + return version; +} + +// return lemma_present flag +FLAG AffixMgr::get_lemma_present() +{ + return lemma_present; +} + +// utility method to look up root words in hash table +struct hentry * AffixMgr::lookup(const char * word) +{ + if (! pHMgr) return NULL; + return pHMgr->lookup(word); +} + +// return the value of suffix +const int AffixMgr::have_contclass() +{ + return havecontclass; +} + +// return utf8 +int AffixMgr::get_utf8() +{ + return utf8; +} + +// return nosplitsugs +int AffixMgr::get_maxngramsugs(void) +{ + return maxngramsugs; +} + +// return nosplitsugs +int AffixMgr::get_nosplitsugs(void) +{ + return nosplitsugs; +} + +// return sugswithdots +int AffixMgr::get_sugswithdots(void) +{ + return sugswithdots; +} + +/* parse flag */ +int AffixMgr::parse_flag(char * line, unsigned short * out, const char * name) { + char * s = NULL; + if (*out != FLAG_NULL && !(*out >= DEFAULTFLAGS)) { + HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name); + return 1; + } + if (parse_string(line, &s, name)) return 1; + *out = pHMgr->decode_flag(s); + free(s); + return 0; +} + +/* parse num */ +int AffixMgr::parse_num(char * line, int * out, const char * name) { + char * s = NULL; + if (*out != -1) { + HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", name); + return 1; + } + if (parse_string(line, &s, name)) return 1; + *out = atoi(s); + free(s); + return 0; +} + +/* parse in the max syllablecount of compound words and */ +int AffixMgr::parse_cpdsyllable(char * line) +{ + char * tp = line; + char * piece; + int i = 0; + int np = 0; + w_char w[MAXWORDLEN]; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { cpdmaxsyllable = atoi(piece); np++; break; } + case 2: { + if (!utf8) { + cpdvowels = mystrdup(piece); + } else { + int n = u8_u16(w, MAXWORDLEN, piece); + if (n > 0) { + flag_qsort((unsigned short *) w, 0, n); + cpdvowels_utf16 = (w_char *) malloc(n * sizeof(w_char)); + if (!cpdvowels_utf16) return 1; + memcpy(cpdvowels_utf16, w, n * sizeof(w_char)); + } + cpdvowels_utf16_len = n; + } + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np < 2) { + HUNSPELL_WARNING(stderr, "error: missing compoundsyllable information\n"); + return 1; + } + if (np == 2) cpdvowels = mystrdup("aeiouAEIOU"); + return 0; +} + +/* parse in the typical fault correcting table */ +int AffixMgr::parse_reptable(char * line, FILE * af) +{ + if (numrep != 0) { + HUNSPELL_WARNING(stderr, "error: duplicate REP tables used\n"); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + numrep = atoi(piece); + if (numrep < 1) { + HUNSPELL_WARNING(stderr, "incorrect number of entries in replacement table\n"); + // free(piece); + return 1; + } + reptable = (replentry *) malloc(numrep * sizeof(struct replentry)); + if (!reptable) return 1; + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: missing replacement table information\n"); + return 1; + } + + /* now parse the numrep lines to read in the remainder of the table */ + char * nl = line; + for (int j=0; j < numrep; j++) { + if (!fgets(nl,MAXLNLEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + reptable[j].pattern = NULL; + reptable[j].pattern2 = NULL; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece,"REP",3) != 0) { + HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n"); + numrep = 0; + // free(piece); + return 1; + } + break; + } + case 1: { reptable[j].pattern = mystrrep(mystrdup(piece),"_"," "); break; } + case 2: { reptable[j].pattern2 = mystrrep(mystrdup(piece),"_"," "); break; } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if ((!(reptable[j].pattern)) || (!(reptable[j].pattern2))) { + HUNSPELL_WARNING(stderr, "error: replacement table is corrupt\n"); + numrep = 0; + return 1; + } + } + return 0; +} + +/* parse in the typical fault correcting table */ +int AffixMgr::parse_phonetable(char * line, FILE * af) +{ + if (phone) { + HUNSPELL_WARNING(stderr, "error: duplicate PHONE tables used\n"); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + phone = (phonetable *) malloc(sizeof(struct phonetable)); + phone->num = atoi(piece); + phone->rules = NULL; + phone->utf8 = utf8; + if (!phone) return 1; + if (phone->num < 1) { + HUNSPELL_WARNING(stderr, "incorrect number of entries in phonelacement table\n"); + // free(piece); + return 1; + } + phone->rules = (char * *) malloc(2 * (phone->num + 1) * sizeof(char *)); + if (!phone->rules) return 1; + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: missing PHONE table information\n"); + return 1; + } + + /* now parse the phone->num lines to read in the remainder of the table */ + char * nl = line; + for (int j=0; j < phone->num; j++) { + if (!fgets(nl,MAXLNLEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + phone->rules[j * 2] = NULL; + phone->rules[j * 2 + 1] = NULL; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece,"PHONE",5) != 0) { + HUNSPELL_WARNING(stderr, "error: PHONE table is corrupt\n"); + phone->num = 0; + // free(piece); + return 1; + } + break; + } + case 1: { phone->rules[j * 2] = mystrrep(mystrdup(piece),"_",""); break; } + case 2: { phone->rules[j * 2 + 1] = mystrrep(mystrdup(piece),"_",""); break; } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if ((!(phone->rules[j * 2])) || (!(phone->rules[j * 2 + 1]))) { + HUNSPELL_WARNING(stderr, "error: PHONE table is corrupt\n"); + phone->num = 0; + return 1; + } + } + phone->rules[phone->num * 2] = mystrdup(""); + phone->rules[phone->num * 2 + 1] = mystrdup(""); + init_phonet_hash(*phone); + return 0; +} + +/* parse in the checkcompoundpattern table */ +int AffixMgr::parse_checkcpdtable(char * line, FILE * af) +{ + if (numcheckcpd != 0) { + HUNSPELL_WARNING(stderr, "error: duplicate compound pattern tables used\n"); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + numcheckcpd = atoi(piece); + if (numcheckcpd < 1) { + HUNSPELL_WARNING(stderr, "incorrect number of entries in compound pattern table\n"); + // free(piece); + return 1; + } + checkcpdtable = (replentry *) malloc(numcheckcpd * sizeof(struct replentry)); + if (!checkcpdtable) return 1; + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: missing compound pattern table information\n"); + return 1; + } + + /* now parse the numcheckcpd lines to read in the remainder of the table */ + char * nl = line; + for (int j=0; j < numcheckcpd; j++) { + if (!fgets(nl,MAXLNLEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + checkcpdtable[j].pattern = NULL; + checkcpdtable[j].pattern2 = NULL; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece,"CHECKCOMPOUNDPATTERN",20) != 0) { + HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n"); + numcheckcpd = 0; + // free(piece); + return 1; + } + break; + } + case 1: { checkcpdtable[j].pattern = mystrdup(piece); break; } + case 2: { checkcpdtable[j].pattern2 = mystrdup(piece); break; } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if ((!(checkcpdtable[j].pattern)) || (!(checkcpdtable[j].pattern2))) { + HUNSPELL_WARNING(stderr, "error: compound pattern table is corrupt\n"); + numcheckcpd = 0; + return 1; + } + } + return 0; +} + +/* parse in the compound rule table */ +int AffixMgr::parse_defcpdtable(char * line, FILE * af) +{ + if (numdefcpd != 0) { + HUNSPELL_WARNING(stderr, "error: duplicate compound rule tables used\n"); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + numdefcpd = atoi(piece); + if (numdefcpd < 1) { + HUNSPELL_WARNING(stderr, "incorrect number of entries in compound rule table\n"); + // free(piece); + return 1; + } + defcpdtable = (flagentry *) malloc(numdefcpd * sizeof(flagentry)); + if (!defcpdtable) return 1; + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: missing compound rule table information\n"); + return 1; + } + + /* now parse the numdefcpd lines to read in the remainder of the table */ + char * nl = line; + for (int j=0; j < numdefcpd; j++) { + if (!fgets(nl,MAXLNLEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + defcpdtable[j].def = NULL; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece, "COMPOUNDRULE", 12) != 0) { + HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n"); + // free(piece); + numdefcpd = 0; + return 1; + } + break; + } + case 1: { + defcpdtable[j].len = + pHMgr->decode_flags(&(defcpdtable[j].def), piece); + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (!defcpdtable[j].len) { + HUNSPELL_WARNING(stderr, "error: compound rule table is corrupt\n"); + numdefcpd = 0; + return 1; + } + } + return 0; +} + + +/* parse in the character map table */ +int AffixMgr::parse_maptable(char * line, FILE * af) +{ + if (nummap != 0) { + HUNSPELL_WARNING(stderr, "error: duplicate MAP tables used\n"); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + nummap = atoi(piece); + if (nummap < 1) { + HUNSPELL_WARNING(stderr, "incorrect number of entries in map table\n"); + // free(piece); + return 1; + } + maptable = (mapentry *) malloc(nummap * sizeof(struct mapentry)); + if (!maptable) return 1; + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: missing map table information\n"); + return 1; + } + + /* now parse the nummap lines to read in the remainder of the table */ + char * nl = line; + for (int j=0; j < nummap; j++) { + if (!fgets(nl,MAXLNLEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + maptable[j].set = NULL; + maptable[j].len = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece,"MAP",3) != 0) { + HUNSPELL_WARNING(stderr, "error: map table is corrupt\n"); + nummap = 0; + // free(piece); + return 1; + } + break; + } + case 1: { + maptable[j].len = 0; + maptable[j].set = NULL; + maptable[j].set_utf16 = NULL; + if (!utf8) { + maptable[j].set = mystrdup(piece); + maptable[j].len = strlen(maptable[j].set); + } else { + w_char w[MAXWORDLEN]; + int n = u8_u16(w, MAXWORDLEN, piece); + if (n > 0) { + flag_qsort((unsigned short *) w, 0, n); + maptable[j].set_utf16 = (w_char *) malloc(n * sizeof(w_char)); + if (!maptable[j].set_utf16) return 1; + memcpy(maptable[j].set_utf16, w, n * sizeof(w_char)); + } + maptable[j].len = n; + } + break; } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if ((!(maptable[j].set || maptable[j].set_utf16)) || (!(maptable[j].len))) { + HUNSPELL_WARNING(stderr, "error: map table is corrupt\n"); + nummap = 0; + return 1; + } + } + return 0; +} + +/* parse in the word breakpoint table */ +int AffixMgr::parse_breaktable(char * line, FILE * af) +{ + if (numbreak != 0) { + HUNSPELL_WARNING(stderr, "error: duplicate word breakpoint tables used\n"); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + numbreak = atoi(piece); + if (numbreak < 1) { + HUNSPELL_WARNING(stderr, "incorrect number of entries in BREAK table\n"); + // free(piece); + return 1; + } + breaktable = (char **) malloc(numbreak * sizeof(char *)); + if (!breaktable) return 1; + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: missing word breakpoint table information\n"); + return 1; + } + + /* now parse the numbreak lines to read in the remainder of the table */ + char * nl = line; + for (int j=0; j < numbreak; j++) { + if (!fgets(nl,MAXLNLEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece,"BREAK",5) != 0) { + HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n"); + // free(piece); + numbreak = 0; + return 1; + } + break; + } + case 1: { + breaktable[j] = mystrdup(piece); + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (!breaktable) { + HUNSPELL_WARNING(stderr, "error: BREAK table is corrupt\n"); + numbreak = 0; + return 1; + } + } + return 0; +} + +void AffixMgr::reverse_condition(char * piece) { + int neg = 0; + for (char * k = piece + strlen(piece) - 1; k >= piece; k--) { + switch(*k) { + case '[': { + if (neg) *(k+1) = '['; else *k = ']'; + break; + } + case ']': { + *k = '['; + if (neg) *(k+1) = '^'; + neg = 0; + break; + } + case '^': { + if (*(k+1) == ']') neg = 1; else *(k+1) = *k; + break; + } + default: { + if (neg) *(k+1) = *k; + } + } + } +} + +int AffixMgr::parse_affix(char * line, const char at, FILE * af, char * dupflags) +{ + int numents = 0; // number of affentry structures to parse + + unsigned short aflag = 0; // affix char identifier + + char ff=0; + struct affentry * ptr= NULL; + struct affentry * nptr= NULL; + + char * tp = line; + char * nl = line; + char * piece; + int i = 0; + + // checking lines with bad syntax +#ifdef DEBUG + int basefieldnum = 0; +#endif + + // split affix header line into pieces + + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + // piece 1 - is type of affix + case 0: { np++; break; } + + // piece 2 - is affix char + case 1: { + np++; + aflag = pHMgr->decode_flag(piece); + if (((at == 'S') && (dupflags[aflag] & dupSFX)) || + ((at == 'P') && (dupflags[aflag] & dupPFX))) { + HUNSPELL_WARNING(stderr, "error: duplicate affix flag %s in line %s\n", piece, nl); + // return 1; XXX permissive mode for bad dictionaries + } + dupflags[aflag] += ((at == 'S') ? dupSFX : dupPFX); + break; + } + // piece 3 - is cross product indicator + case 2: { np++; if (*piece == 'Y') ff = aeXPRODUCT; break; } + + // piece 4 - is number of affentries + case 3: { + np++; + numents = atoi(piece); + if (numents == 0) { + char * err = pHMgr->encode_flag(aflag); + HUNSPELL_WARNING(stderr, "error: affix %s header has incorrect entry count in line %s\n", + err, nl); + free(err); + return 1; + } + ptr = (struct affentry *) malloc(numents * sizeof(struct affentry)); + if (!ptr) return 1; + ptr->opts = ff; + if (utf8) ptr->opts += aeUTF8; + if (pHMgr->is_aliasf()) ptr->opts += aeALIASF; + if (pHMgr->is_aliasm()) ptr->opts += aeALIASM; + ptr->aflag = aflag; + } + + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + // check to make sure we parsed enough pieces + if (np != 4) { + char * err = pHMgr->encode_flag(aflag); + HUNSPELL_WARNING(stderr, "error: affix %s header has insufficient data in line %s\n", err, nl); + free(err); + free(ptr); + return 1; + } + + // store away ptr to first affentry + nptr = ptr; + + // now parse numents affentries for this affix + for (int j=0; j < numents; j++) { + if (!fgets(nl,MAXLNLEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + np = 0; + + // split line into pieces + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + // piece 1 - is type + case 0: { + np++; + if (nptr != ptr) nptr->opts = ptr->opts & + (aeXPRODUCT + aeUTF8 + aeALIASF + aeALIASM); + break; + } + + // piece 2 - is affix char + case 1: { + np++; + if (pHMgr->decode_flag(piece) != aflag) { + char * err = pHMgr->encode_flag(aflag); + HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl); + HUNSPELL_WARNING(stderr, "error: possible incorrect count\n"); + free(err); + // free(piece); + return 1; + } + + if (nptr != ptr) nptr->aflag = ptr->aflag; + break; + } + + // piece 3 - is string to strip or 0 for null + case 2: { + np++; + if (complexprefixes) { + if (utf8) reverseword_utf(piece); else reverseword(piece); + } + nptr->strip = mystrdup(piece); + nptr->stripl = (unsigned char) strlen(nptr->strip); + if (strcmp(nptr->strip,"0") == 0) { + free(nptr->strip); + nptr->strip=mystrdup(""); + nptr->stripl = 0; + } + break; + } + + // piece 4 - is affix string or 0 for null + case 3: { + char * dash; + nptr->morphcode = NULL; + nptr->contclass = NULL; + nptr->contclasslen = 0; + np++; + dash = strchr(piece, '/'); + if (dash) { + *dash = '\0'; + + if (ignorechars) { + if (utf8) { + remove_ignored_chars_utf(piece, ignorechars_utf16, ignorechars_utf16_len); + } else { + remove_ignored_chars(piece,ignorechars); + } + } + + if (complexprefixes) { + if (utf8) reverseword_utf(piece); else reverseword(piece); + } + nptr->appnd = mystrdup(piece); + + if (pHMgr->is_aliasf()) { + int index = atoi(dash + 1); + nptr->contclasslen = (unsigned short) pHMgr->get_aliasf(index, &(nptr->contclass)); + } else { + nptr->contclasslen = (unsigned short) pHMgr->decode_flags(&(nptr->contclass), dash + 1); + flag_qsort(nptr->contclass, 0, nptr->contclasslen); + } + *dash = '/'; + + havecontclass = 1; + for (unsigned short _i = 0; _i < nptr->contclasslen; _i++) { + contclasses[(nptr->contclass)[_i]] = 1; + } + } else { + if (ignorechars) { + if (utf8) { + remove_ignored_chars_utf(piece, ignorechars_utf16, ignorechars_utf16_len); + } else { + remove_ignored_chars(piece,ignorechars); + } + } + + if (complexprefixes) { + if (utf8) reverseword_utf(piece); else reverseword(piece); + } + nptr->appnd = mystrdup(piece); + } + + nptr->appndl = (unsigned char) strlen(nptr->appnd); + if (strcmp(nptr->appnd,"0") == 0) { + free(nptr->appnd); + nptr->appnd=mystrdup(""); + nptr->appndl = 0; + } + break; + } + + // piece 5 - is the conditions descriptions + case 4: { + np++; + if (complexprefixes) { + if (utf8) reverseword_utf(piece); else reverseword(piece); + reverse_condition(piece); + } + if (nptr->stripl && (strcmp(piece, ".") != 0) && + redundant_condition(at, nptr->strip, nptr->stripl, piece, nl)) + strcpy(piece, "."); + if (at == 'S') { + reverseword(piece); + reverse_condition(piece); + } + if (encodeit(nptr, piece)) return 1; + break; + } + + case 5: { + np++; + if (pHMgr->is_aliasm()) { + int index = atoi(piece); + nptr->morphcode = pHMgr->get_aliasm(index); + } else { + if (complexprefixes) { // XXX - fix me for morph. gen. + if (utf8) reverseword_utf(piece); else reverseword(piece); + } + // add the remaining of the line + if (*tp) { + *(tp - 1) = ' '; + tp = tp + strlen(tp); + } + nptr->morphcode = (char *) malloc(strlen(piece)+1); + strcpy(nptr->morphcode, piece); + } + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + // check to make sure we parsed enough pieces + if (np < 4) { + char * err = pHMgr->encode_flag(aflag); + HUNSPELL_WARNING(stderr, "error: affix %s is corrupt near line %s\n", err, nl); + free(err); + free(ptr); + return 1; + } + +#ifdef DEBUG + // detect unnecessary fields, excepting comments + if (basefieldnum) { + int fieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6); + if (fieldnum != basefieldnum) + HUNSPELL_WARNING(stderr, "warning: bad field number:\n%s\n", nl); + } else { + basefieldnum = !(nptr->morphcode) ? 5 : ((*(nptr->morphcode)=='#') ? 5 : 6); + } +#endif + nptr++; + } + + // now create SfxEntry or PfxEntry objects and use links to + // build an ordered (sorted by affix string) list + nptr = ptr; + for (int k = 0; k < numents; k++) { + if (at == 'P') { + PfxEntry * pfxptr = new PfxEntry(this,nptr); + build_pfxtree((AffEntry *)pfxptr); + } else { + SfxEntry * sfxptr = new SfxEntry(this,nptr); + build_sfxtree((AffEntry *)sfxptr); + } + nptr++; + } + free(ptr); + return 0; +} + +int AffixMgr::redundant_condition(char ft, char * strip, int stripl, const char * cond, char * warnvar) { + int condl = strlen(cond); + int i; + int j; + int neg; + int in; + if (ft == 'P') { // prefix + if (strncmp(strip, cond, condl) == 0) return 1; + if (utf8) { + } else { + for (i = 0, j = 0; (i < stripl) && (j < condl); i++, j++) { + if (cond[j] != '[') { + if (cond[j] != strip[i]) { + HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar); + } + } else { + neg = (cond[j+1] == '^') ? 1 : 0; + in = 0; + do { + j++; + if (strip[i] == cond[j]) in = 1; + } while ((j < (condl - 1)) && (cond[j] != ']')); + if (j == (condl - 1) && (cond[j] != ']')) { + HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", warnvar); + return 0; + } + if ((!neg && !in) || (neg && in)) { + HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar); + return 0; + } + } + } + if (j >= condl) return 1; + } + } else { // suffix + if ((stripl >= condl) && strcmp(strip + stripl - condl, cond) == 0) return 1; + if (utf8) { + } else { + for (i = stripl - 1, j = condl - 1; (i >= 0) && (j >= 0); i--, j--) { + if (cond[j] != ']') { + if (cond[j] != strip[i]) { + HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar); + } + } else { + in = 0; + do { + j--; + if (strip[i] == cond[j]) in = 1; + } while ((j > 0) && (cond[j] != '[')); + if ((j == 0) && (cond[j] != '[')) { + HUNSPELL_WARNING(stderr, "error: missing ] in condition:\n%s\n", warnvar); + return 0; + } + neg = (cond[j+1] == '^') ? 1 : 0; + if ((!neg && !in) || (neg && in)) { + HUNSPELL_WARNING(stderr, "warning: incompatible stripping characters and condition:\n%s\n", warnvar); + return 0; + } + } + } + if (j < 0) return 1; + } + } + return 0; +} diff --git a/hunspell/src/hunspell/affixmgr.hxx b/hunspell/src/hunspell/affixmgr.hxx new file mode 100644 index 000000000..644d2c99b --- /dev/null +++ b/hunspell/src/hunspell/affixmgr.hxx @@ -0,0 +1,224 @@ +#ifndef _AFFIXMGR_HXX_ +#define _AFFIXMGR_HXX_ + +#ifdef MOZILLA_CLIENT +#ifdef __SUNPRO_CC // for SunONE Studio compiler +using namespace std; +#endif +#include +#else +#include +#endif + +#include "atypes.hxx" +#include "baseaffix.hxx" +#include "hashmgr.hxx" +#include "phonet.hxx" + +// check flag duplication +#define dupSFX (1 << 0) +#define dupPFX (1 << 1) + +class AffixMgr +{ + + AffEntry * pStart[SETSIZE]; + AffEntry * sStart[SETSIZE]; + AffEntry * pFlag[CONTSIZE]; + AffEntry * sFlag[CONTSIZE]; + HashMgr * pHMgr; + char * keystring; + char * trystring; + char * encoding; + struct cs_info * csconv; + int utf8; + int complexprefixes; + FLAG compoundflag; + FLAG compoundbegin; + FLAG compoundmiddle; + FLAG compoundend; + FLAG compoundroot; + FLAG compoundforbidflag; + FLAG compoundpermitflag; + int checkcompounddup; + int checkcompoundrep; + int checkcompoundcase; + int checkcompoundtriple; + FLAG forbiddenword; + FLAG nosuggest; + FLAG needaffix; + int cpdmin; + int numrep; + replentry * reptable; + int nummap; + mapentry * maptable; + int numbreak; + char ** breaktable; + int numcheckcpd; + replentry * checkcpdtable; + int numdefcpd; + flagentry * defcpdtable; + phonetable * phone; + int maxngramsugs; + int nosplitsugs; + int sugswithdots; + int cpdwordmax; + int cpdmaxsyllable; + char * cpdvowels; + w_char * cpdvowels_utf16; + int cpdvowels_utf16_len; + char * cpdsyllablenum; + const char * pfxappnd; // BUG: not stateless + const char * sfxappnd; // BUG: not stateless + FLAG sfxflag; // BUG: not stateless + char * derived; // BUG: not stateless + AffEntry * sfx; // BUG: not stateless + AffEntry * pfx; // BUG: not stateless + int checknum; + char * wordchars; + unsigned short * wordchars_utf16; + int wordchars_utf16_len; + char * ignorechars; + unsigned short * ignorechars_utf16; + int ignorechars_utf16_len; + char * version; + char * lang; + int langnum; + FLAG lemma_present; + FLAG circumfix; + FLAG onlyincompound; + FLAG keepcase; + FLAG substandard; + int checksharps; + + int havecontclass; // boolean variable + char contclasses[CONTSIZE]; // flags of possible continuing classes (twofold affix) + flag flag_mode; + +public: + + AffixMgr(const char * affpath, HashMgr * ptr); + ~AffixMgr(); + struct hentry * affix_check(const char * word, int len, + const unsigned short needflag = (unsigned short) 0, + char in_compound = IN_CPD_NOT); + struct hentry * prefix_check(const char * word, int len, + char in_compound, const FLAG needflag = FLAG_NULL); + inline int isSubset(const char * s1, const char * s2); + struct hentry * prefix_check_twosfx(const char * word, int len, + char in_compound, const FLAG needflag = FLAG_NULL); + inline int isRevSubset(const char * s1, const char * end_of_s2, int len); + struct hentry * suffix_check(const char * word, int len, int sfxopts, + AffEntry* ppfx, char ** wlst, int maxSug, int * ns, + const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, + char in_compound = IN_CPD_NOT); + struct hentry * suffix_check_twosfx(const char * word, int len, + int sfxopts, AffEntry* ppfx, const FLAG needflag = FLAG_NULL); + + char * affix_check_morph(const char * word, int len, + const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT); + char * prefix_check_morph(const char * word, int len, + char in_compound, const FLAG needflag = FLAG_NULL); + char * suffix_check_morph (const char * word, int len, int sfxopts, + AffEntry * ppfx, const FLAG cclass = FLAG_NULL, + const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT); + + char * prefix_check_twosfx_morph(const char * word, int len, + char in_compound, const FLAG needflag = FLAG_NULL); + char * suffix_check_twosfx_morph(const char * word, int len, + int sfxopts, AffEntry * ppfx, const FLAG needflag = FLAG_NULL); + + char * morphgen(char * ts, int wl, const unsigned short * ap, + unsigned short al, char * morph, char * targetmorph, int level); + + int expand_rootword(struct guessword * wlst, int maxn, const char * ts, + int wl, const unsigned short * ap, unsigned short al, char * bad, + int, char *); + + short get_syllable (const char * word, int wlen); + int cpdrep_check(const char * word, int len); + int cpdpat_check(const char * word, int len); + int defcpd_check(hentry *** words, short wnum, hentry * rv, + hentry ** rwords, char all); + int cpdcase_check(const char * word, int len); + inline int candidate_check(const char * word, int len); + struct hentry * compound_check(const char * word, int len, short wordnum, + short numsyllable, short maxwordnum, short wnum, hentry ** words, + char hu_mov_rule, int * cmpdstemnum, int * cmpdstem, char is_sug); + + int compound_check_morph(const char * word, int len, short wordnum, + short numsyllable, short maxwordnum, short wnum, hentry ** words, + char hu_mov_rule, char ** result, char * partresult); + + struct hentry * lookup(const char * word); + int get_numrep(); + struct replentry * get_reptable(); + struct phonetable * get_phonetable(); + int get_nummap(); + struct mapentry * get_maptable(); + int get_numbreak(); + char ** get_breaktable(); + char * get_encoding(); + int get_langnum(); + char * get_key_string(); + char * get_try_string(); + const char * get_wordchars(); + unsigned short * get_wordchars_utf16(int * len); + char * get_ignore(); + unsigned short * get_ignore_utf16(int * len); + int get_compound(); + FLAG get_compoundflag(); + FLAG get_compoundbegin(); + FLAG get_forbiddenword(); + FLAG get_nosuggest(); +// FLAG get_circumfix(); + FLAG get_needaffix(); + FLAG get_onlyincompound(); + FLAG get_compoundroot(); + FLAG get_lemma_present(); + int get_checknum(); + char * get_possible_root(); + const char * get_prefix(); + const char * get_suffix(); + const char * get_derived(); + const char * get_version(); + const int have_contclass(); + int get_utf8(); + int get_complexprefixes(); + char * get_suffixed(char ); + int get_maxngramsugs(); + int get_nosplitsugs(); + int get_sugswithdots(void); + FLAG get_keepcase(void); + int get_checksharps(void); + +private: + int parse_file(const char * affpath); + int parse_flag(char * line, unsigned short * out, const char * name); + int parse_num(char * line, int * out, const char * name); + int parse_cpdsyllable(char * line); + int parse_reptable(char * line, FILE * af); + int parse_phonetable(char * line, FILE * af); + int parse_maptable(char * line, FILE * af); + int parse_breaktable(char * line, FILE * af); + int parse_checkcpdtable(char * line, FILE * af); + int parse_defcpdtable(char * line, FILE * af); + int parse_affix(char * line, const char at, FILE * af, char * dupflags); + + void reverse_condition(char *); + int condlen(char *); + int encodeit(struct affentry * ptr, char * cs); + int build_pfxtree(AffEntry* pfxptr); + int build_sfxtree(AffEntry* sfxptr); + int process_pfx_order(); + int process_sfx_order(); + AffEntry * process_pfx_in_order(AffEntry * ptr, AffEntry * nptr); + AffEntry * process_sfx_in_order(AffEntry * ptr, AffEntry * nptr); + int process_pfx_tree_to_list(); + int process_sfx_tree_to_list(); + int redundant_condition(char, char * strip, int stripl, + const char * cond, char *); +}; + +#endif + diff --git a/hunspell/src/hunspell/atypes.hxx b/hunspell/src/hunspell/atypes.hxx new file mode 100644 index 000000000..0afb3451f --- /dev/null +++ b/hunspell/src/hunspell/atypes.hxx @@ -0,0 +1,90 @@ +#ifndef _ATYPES_HXX_ +#define _ATYPES_HXX_ + +#ifndef HUNSPELL_WARNING +#ifdef HUNSPELL_WARNING_ON +#define HUNSPELL_WARNING fprintf +#else +// empty inline function to switch off warnings (instead of the C99 standard variadic macros) +static inline void HUNSPELL_WARNING(FILE *, const char *, ...) {} +#endif +#endif + +// HUNSTEM def. +#define HUNSTEM + +#include "csutil.hxx" +#include "hashmgr.hxx" + +#define SETSIZE 256 +#define CONTSIZE 65536 +#define MAXWORDLEN 100 +#define MAXWORDUTF8LEN 256 + +// affentry options +#define aeXPRODUCT (1 << 0) +#define aeUTF8 (1 << 1) +#define aeALIASF (1 << 2) +#define aeALIASM (1 << 3) +#define aeLONGCOND (1 << 4) + +// compound options +#define IN_CPD_NOT 0 +#define IN_CPD_BEGIN 1 +#define IN_CPD_END 2 +#define IN_CPD_OTHER 3 + +#define MAXLNLEN 8192 + +#define MINCPDLEN 3 +#define MAXCOMPOUND 10 +#define MAXCONDLEN 20 +#define MAXCONDLEN_1 (MAXCONDLEN - sizeof(char *)) + +#define MAXACC 1000 + +#define FLAG unsigned short +#define FLAG_NULL 0x00 +#define FREE_FLAG(a) a = 0 + +#define TESTAFF( a, b , c ) flag_bsearch((unsigned short *) a, (unsigned short) b, c) + +struct affentry +{ + char * strip; + char * appnd; + unsigned char stripl; + unsigned char appndl; + char numconds; + char opts; + unsigned short aflag; + unsigned short * contclass; + short contclasslen; + union { + char conds[MAXCONDLEN]; + struct { + char conds1[MAXCONDLEN_1]; + char * conds2; + } l; + } c; + char * morphcode; +}; + +struct mapentry { + char * set; + w_char * set_utf16; + int len; +}; + +struct flagentry { + FLAG * def; + int len; +}; + +struct guessword { + char * word; + bool allow; + char * orig; +}; + +#endif diff --git a/hunspell/src/hunspell/baseaffix.hxx b/hunspell/src/hunspell/baseaffix.hxx new file mode 100644 index 000000000..03a876d9e --- /dev/null +++ b/hunspell/src/hunspell/baseaffix.hxx @@ -0,0 +1,28 @@ +#ifndef _BASEAFF_HXX_ +#define _BASEAFF_HXX_ + +class AffEntry +{ +public: + +protected: + char * appnd; + char * strip; + unsigned char appndl; + unsigned char stripl; + char numconds; + char opts; + unsigned short aflag; + union { + char conds[MAXCONDLEN]; + struct { + char conds1[MAXCONDLEN_1]; + char * conds2; + } l; + } c; + char * morphcode; + unsigned short * contclass; + short contclasslen; +}; + +#endif diff --git a/hunspell/src/hunspell/csutil.cxx b/hunspell/src/hunspell/csutil.cxx new file mode 100644 index 000000000..da9ff9fe8 --- /dev/null +++ b/hunspell/src/hunspell/csutil.cxx @@ -0,0 +1,5499 @@ +#include "license.hunspell" +#include "license.myspell" + +#ifndef MOZILLA_CLIENT +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include "csutil.hxx" +#include "atypes.hxx" +#include "langnum.hxx" + +#ifdef OPENOFFICEORG +# include +#else +# ifndef MOZILLA_CLIENT +# include "utf_info.cxx" +# define UTF_LST_LEN (sizeof(utf_lst) / (sizeof(unicode_info))) +# endif +#endif + +#ifdef MOZILLA_CLIENT +#include "nsCOMPtr.h" +#include "nsServiceManagerUtils.h" +#include "nsIUnicodeEncoder.h" +#include "nsIUnicodeDecoder.h" +#include "nsICaseConversion.h" +#include "nsICharsetConverterManager.h" +#include "nsUnicharUtilCIID.h" +#include "nsUnicharUtils.h" + +static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID); +static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID); +#endif + +#ifdef MOZILLA_CLIENT +#ifdef __SUNPRO_CC // for SunONE Studio compiler +using namespace std; +#endif +#else +#ifndef W32 +using namespace std; +#endif +#endif + +static struct unicode_info2 * utf_tbl = NULL; +static int utf_tbl_count = 0; // utf_tbl can be used by multiple Hunspell instances + +/* only UTF-16 (BMP) implementation */ +char * u16_u8(char * dest, int size, const w_char * src, int srclen) { + char * u8 = dest; + char * u8_max = u8 + size; + const w_char * u2 = src; + const w_char * u2_max = src + srclen; + while ((u2 < u2_max) && (u8 < u8_max)) { + if (u2->h) { // > 0xFF + // XXX 4-byte haven't implemented yet. + if (u2->h >= 0x08) { // >= 0x800 (3-byte UTF-8 character) + *u8 = 0xe0 + (u2->h >> 4); + u8++; + if (u8 < u8_max) { + *u8 = 0x80 + ((u2->h & 0xf) << 2) + (u2->l >> 6); + u8++; + if (u8 < u8_max) { + *u8 = 0x80 + (u2->l & 0x3f); + u8++; + } + } + } else { // < 0x800 (2-byte UTF-8 character) + *u8 = 0xc0 + (u2->h << 2) + (u2->l >> 6); + u8++; + if (u8 < u8_max) { + *u8 = 0x80 + (u2->l & 0x3f); + u8++; + } + } + } else { // <= 0xFF + if (u2->l & 0x80) { // >0x80 (2-byte UTF-8 character) + *u8 = 0xc0 + (u2->l >> 6); + u8++; + if (u8 < u8_max) { + *u8 = 0x80 + (u2->l & 0x3f); + u8++; + } + } else { // < 0x80 (1-byte UTF-8 character) + *u8 = u2->l; + u8++; + } + } + u2++; + } + *u8 = '\0'; + return dest; +} + + +/* only UTF-16 (BMP) implementation */ +int u8_u16(w_char * dest, int size, const char * src) { + const char * u8 = src; + w_char * u2 = dest; + w_char * u2_max = u2 + size; + + while ((u2 < u2_max) && *u8) { + switch ((*u8) & 0xf0) { + case 0x00: + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: { + u2->h = 0; + u2->l = *u8; + break; + } + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: { + HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Unexpected continuation bytes in %ld. character position\n%s\n", static_cast(u8 - src), src); + u2->h = 0xff; + u2->l = 0xfd; + break; + } + case 0xc0: + case 0xd0: { // 2-byte UTF-8 codes + if ((*(u8+1) & 0xc0) == 0x80) { + u2->h = (*u8 & 0x1f) >> 2; + u2->l = (*u8 << 6) + (*(u8+1) & 0x3f); + u8++; + } else { + HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %ld. character position:\n%s\n", static_cast(u8 - src), src); + u2->h = 0xff; + u2->l = 0xfd; + } + break; + } + case 0xe0: { // 3-byte UTF-8 codes + if ((*(u8+1) & 0xc0) == 0x80) { + u2->h = ((*u8 & 0x0f) << 4) + ((*(u8+1) & 0x3f) >> 2); + u8++; + if ((*(u8+1) & 0xc0) == 0x80) { + u2->l = (*u8 << 6) + (*(u8+1) & 0x3f); + u8++; + } else { + HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %ld. character position:\n%s\n", static_cast(u8 - src), src); + u2->h = 0xff; + u2->l = 0xfd; + } + } else { + HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %ld. character position:\n%s\n", static_cast(u8 - src), src); + u2->h = 0xff; + u2->l = 0xfd; + } + break; + } + case 0xf0: { // 4 or more byte UTF-8 codes + HUNSPELL_WARNING(stderr, "This UTF-8 encoding can't convert to UTF-16:\n%s\n", src); + u2->h = 0xff; + u2->l = 0xfd; + return -1; + } + } + u8++; + u2++; + } + return u2 - dest; +} + +void flag_qsort(unsigned short flags[], int begin, int end) { + unsigned short reg; + if (end > begin) { + unsigned short pivot = flags[begin]; + int l = begin + 1; + int r = end; + while(l < r) { + if (flags[l] <= pivot) { + l++; + } else { + r--; + reg = flags[l]; + flags[l] = flags[r]; + flags[r] = reg; + } + } + l--; + reg = flags[begin]; + flags[begin] = flags[l]; + flags[l] = reg; + + flag_qsort(flags, begin, l); + flag_qsort(flags, r, end); + } + } + +int flag_bsearch(unsigned short flags[], unsigned short flag, int length) { + int mid; + int left = 0; + int right = length - 1; + while (left <= right) { + mid = (left + right) / 2; + if (flags[mid] == flag) return 1; + if (flag < flags[mid]) right = mid - 1; + else left = mid + 1; + } + return 0; +} + + // strip strings into token based on single char delimiter + // acts like strsep() but only uses a delim char and not + // a delim string + // default delimiter: white space characters + + char * mystrsep(char ** stringp, const char delim) + { + char * mp = *stringp; + if (*mp != '\0') { + char * dp; + if (delim) { + dp = strchr(mp, delim); + } else { + // don't use isspace() here, the string can be in some random charset + // that's way different than the locale's + for (dp = mp; (*dp && *dp != ' ' && *dp != '\t'); dp++); + if (!*dp) dp = NULL; + } + if (dp) { + *stringp = dp+1; + int nc = (int)((unsigned long)dp - (unsigned long)mp); + *(mp+nc) = '\0'; + return mp; + } else { + *stringp = mp + strlen(mp); + return mp; + } + } + return NULL; + } + + + // replaces strdup with ansi version + char * mystrdup(const char * s) + { + char * d = NULL; + if (s) { + int sl = strlen(s); + d = (char *) malloc(((sl+1) * sizeof(char))); + if (d) memcpy(d,s,((sl+1)*sizeof(char))); + } + return d; + } + + + // remove cross-platform text line end characters + void mychomp(char * s) + { + int k = strlen(s); + if ((k > 0) && ((*(s+k-1)=='\r') || (*(s+k-1)=='\n'))) *(s+k-1) = '\0'; + if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0'; + } + + + // does an ansi strdup of the reverse of a string + char * myrevstrdup(const char * s) + { + char * d = NULL; + if (s) { + int sl = strlen(s); + d = (char *) malloc((sl+1) * sizeof(char)); + if (d) { + const char * p = s + sl - 1; + char * q = d; + while (p >= s) *q++ = *p--; + *q = '\0'; + } + } + return d; + } + +// break text to lines +// return number of lines +int line_tok(const char * text, char *** lines, char breakchar) { + int linenum = 0; + char * dup = mystrdup(text); + char * p = strchr(dup, breakchar); + while (p) { + linenum++; + *p = '\0'; + p++; + p = strchr(p, breakchar); + } + linenum++; + *lines = (char **) malloc(linenum * sizeof(char *)); + if (!(*lines)) { + free(dup); + return 0; + } + + p = dup; + int l = 0; + for (int i = 0; i < linenum; i++) { + if (*p != '\0') { + (*lines)[l] = mystrdup(p); + l++; + } + p += strlen(p) + 1; + } + free(dup); + if (!l) free(*lines); + return l; +} + +// uniq line in place +char * line_uniq(char * text, char breakchar) { + char ** lines; + int linenum = line_tok(text, &lines, breakchar); + int i; + strcpy(text, lines[0]); + for ( i = 1; i < linenum; i++ ) { + int dup = 0; + for (int j = 0; j < i; j++) { + if (strcmp(lines[i], lines[j]) == 0) dup = 1; + } + if (!dup) { + if ((i > 1) || (*(lines[0]) != '\0')) { + sprintf(text + strlen(text), "%c", breakchar); + } + strcat(text, lines[i]); + } + } + for ( i = 0; i < linenum; i++ ) { + if (lines[i]) free(lines[i]); + } + if (lines) free(lines); + return text; +} + +// uniq and boundary for compound analysis: "1\n\2\n\1" -> " ( \1 | \2 ) " +char * line_uniq_app(char ** text, char breakchar) { + if (!strchr(*text, breakchar)) { + return *text; + } + + char ** lines; + int linenum = line_tok(*text, &lines, breakchar); + int dup = 0; + for (int i = 0; i < linenum; i++) { + for (int j = 0; j < (i - 1); j++) { + if (strcmp(lines[i], lines[j]) == 0) { + *(lines[i]) = '\0'; + dup++; + break; + } + } + } + if ((linenum - dup) == 1) { + strcpy(*text, lines[0]); + freelist(&lines, linenum); + return *text; + } + char * newtext = (char *) malloc(strlen(*text) + 2 * linenum + 3 + 1); + if (newtext) { + free(*text); + *text = newtext; + } else { + freelist(&lines, linenum); + return *text; + } + strcpy(*text," ( "); + for (int i = 0; i < linenum; i++) if (*(lines[i])) { + sprintf(*text + strlen(*text), "%s%s", lines[i], " | "); + } + (*text)[strlen(*text) - 2] = ')'; // " ) " + freelist(&lines, linenum); + return *text; +} + + // append s to ends of every lines in text + void strlinecat(char * dest, const char * s) + { + char * dup = mystrdup(dest); + char * source = dup; + int len = strlen(s); + while (*source) { + if (*source == '\n') { + strncpy(dest, s, len); + dest += len; + } + *dest = *source; + source++; dest++; + } + strcpy(dest, s); + free(dup); + } + +// change \n to char c +char * tr(char * text, char oldc, char newc) { + char * p; + for (p = text; *p; p++) if (*p == oldc) *p = newc; + return text; +} + +// morphcmp(): compare MORPH_DERI_SFX, MORPH_INFL_SFX and MORPH_TERM_SFX fields +// in the first line of the inputs +// return 0, if inputs equal +// return 1, if inputs may equal with a secondary suffix +// otherwise return -1 +int morphcmp(const char * s, const char * t) +{ + int se; + int te; + const char * sl; + const char * tl; + const char * olds; + const char * oldt; + if (!s || !t) return 1; + olds = s; + sl = strchr(s, '\n'); + s = strstr(s, MORPH_DERI_SFX); + if (!s || (sl && sl < s)) s = strstr(olds, MORPH_INFL_SFX); + if (!s || (sl && sl < s)) { + s= strstr(olds, MORPH_TERM_SFX); + olds = NULL; + } + oldt = t; + tl = strchr(t, '\n'); + t = strstr(t, MORPH_DERI_SFX); + if (!t || (tl && tl < t)) t = strstr(oldt, MORPH_INFL_SFX); + if (!t || (tl && tl < t)) { + t = strstr(oldt, MORPH_TERM_SFX); + oldt = NULL; + } + while (s && t && (!sl || sl > s) && (!tl || tl > t)) { + s += MORPH_TAG_LEN; + t += MORPH_TAG_LEN; + se = 0; + te = 0; + while ((*s == *t) && !se && !te) { + s++; + t++; + switch(*s) { + case ' ': + case '\n': + case '\t': + case '\0': se = 1; + } + switch(*t) { + case ' ': + case '\n': + case '\t': + case '\0': te = 1; + } + } + if (!se || !te) { + // not terminal suffix difference + if (olds) return -1; + return 1; + } + olds = s; + s = strstr(s, MORPH_DERI_SFX); + if (!s || (sl && sl < s)) s = strstr(olds, MORPH_INFL_SFX); + if (!s || (sl && sl < s)) { + s = strstr(olds, MORPH_TERM_SFX); + olds = NULL; + } + oldt = t; + t = strstr(t, MORPH_DERI_SFX); + if (!t || (tl && tl < t)) t = strstr(oldt, MORPH_INFL_SFX); + if (!t || (tl && tl < t)) { + t = strstr(oldt, MORPH_TERM_SFX); + oldt = NULL; + } + } + if (!s && !t && se && te) return 0; + return 1; +} + +int get_sfxcount(const char * morph) +{ + if (!morph || !*morph) return 0; + int n = 0; + const char * old = morph; + morph = strstr(morph, MORPH_DERI_SFX); + if (!morph) morph = strstr(old, MORPH_INFL_SFX); + if (!morph) morph = strstr(old, MORPH_TERM_SFX); + while (morph) { + n++; + old = morph; + morph = strstr(morph + 1, MORPH_DERI_SFX); + if (!morph) morph = strstr(old + 1, MORPH_INFL_SFX); + if (!morph) morph = strstr(old + 1, MORPH_TERM_SFX); + } + return n; +} + + +int fieldlen(const char * r) +{ + int n = 0; + while (r && *r != '\t' && *r != '\0' && *r != '\n' && *r != ' ') { + r++; + n++; + } + return n; +} + +char * copy_field(char * dest, const char * morph, const char * var) +{ + if (!morph) return NULL; + const char * beg = strstr(morph, var); + if (beg) { + char * d = dest; + for (beg += MORPH_TAG_LEN; *beg != ' ' && *beg != '\t' && + *beg != '\n' && *beg != '\0'; d++, beg++) { + *d = *beg; + } + *d = '\0'; + return dest; + } + return NULL; +} + +char * mystrrep(char * word, const char * pat, const char * rep) { + char * pos = strstr(word, pat); + if (pos) { + int replen = strlen(rep); + int patlen = strlen(pat); + if (replen < patlen) { + char * end = word + strlen(word); + char * next = pos + replen; + char * prev = pos + strlen(pat); + for (; prev < end; *next = *prev, prev++, next++); + *next = '\0'; + } else if (replen > patlen) { + char * end = pos + patlen; + char * next = word + strlen(word) + replen - patlen; + char * prev = next - replen + patlen; + for (; prev >= end; *next = *prev, prev--, next--); + } + strncpy(pos, rep, replen); + } + return word; +} + + // reverse word + int reverseword(char * word) { + char r; + for (char * dest = word + strlen(word) - 1; word < dest; word++, dest--) { + r=*word; + *word = *dest; + *dest = r; + } + return 0; + } + + // reverse word (error: 1) + int reverseword_utf(char * word) { + w_char w[MAXWORDLEN]; + w_char * p; + w_char r; + int l = u8_u16(w, MAXWORDLEN, word); + if (l == -1) return 1; + p = w; + for (w_char * dest = w + l - 1; p < dest; p++, dest--) { + r=*p; + *p = *dest; + *dest = r; + } + u16_u8(word, MAXWORDUTF8LEN, w, l); + return 0; + } + + int uniqlist(char ** list, int n) { + if (n < 2) return n; + for (int i = 0; i < n; i++) { + for (int j = 0; j < i; j++) { + if (list[j] && list[i] && (strcmp(list[j], list[i]) == 0)) { + free(list[i]); + list[i] = NULL; + break; + } + } + } + int m = 1; + for (int i = 1; i < n; i++) if (list[i]) { + list[m] = list[i]; + m++; + } + return m; + } + + void freelist(char *** list, int n) { + if (list && (n > 0)) { + for (int i = 0; i < n; i++) if ((*list)[i]) free((*list)[i]); + free(*list); + *list = NULL; + } + } + + // convert null terminated string to all caps + void mkallcap(char * p, const struct cs_info * csconv) + { + while (*p != '\0') { + *p = csconv[((unsigned char) *p)].cupper; + p++; + } + } + + // convert null terminated string to all little + void mkallsmall(char * p, const struct cs_info * csconv) + { + while (*p != '\0') { + *p = csconv[((unsigned char) *p)].clower; + p++; + } + } + +void mkallsmall_utf(w_char * u, int nc, int langnum) { + for (int i = 0; i < nc; i++) { + unsigned short idx = (u[i].h << 8) + u[i].l; + if (idx != unicodetolower(idx, langnum)) { + u[i].h = (unsigned char) (unicodetolower(idx, langnum) >> 8); + u[i].l = (unsigned char) (unicodetolower(idx, langnum) & 0x00FF); + } + } +} + +void mkallcap_utf(w_char * u, int nc, int langnum) { + for (int i = 0; i < nc; i++) { + unsigned short idx = (u[i].h << 8) + u[i].l; + if (idx != unicodetoupper(idx, langnum)) { + u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8); + u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF); + } + } +} + + // convert null terminated string to have intial capital + void mkinitcap(char * p, const struct cs_info * csconv) + { + if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper; + } + +#ifndef MOZILLA_CLIENT + // convert null terminated string to all caps using encoding + void enmkallcap(char * d, const char * p, const char * encoding) + + { + struct cs_info * csconv = get_current_cs(encoding); + while (*p != '\0') { + *d++ = csconv[((unsigned char) *p)].cupper; + p++; + } + *d = '\0'; + } + + // convert null terminated string to all little using encoding + void enmkallsmall(char * d, const char * p, const char * encoding) + { + struct cs_info * csconv = get_current_cs(encoding); + while (*p != '\0') { + *d++ = csconv[((unsigned char) *p)].clower; + p++; + } + *d = '\0'; + } + + // convert null terminated string to have intial capital using encoding + void enmkinitcap(char * d, const char * p, const char * encoding) + { + struct cs_info * csconv = get_current_cs(encoding); + memcpy(d,p,(strlen(p)+1)); + if (*p != '\0') *d= csconv[((unsigned char)*p)].cupper; + } + +// these are simple character mappings for the +// encodings supported +// supplying isupper, tolower, and toupper + +struct cs_info iso1_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x01, 0xf0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x01, 0xf2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x01, 0xfc, 0xdc }, +{ 0x01, 0xfd, 0xdd }, +{ 0x01, 0xfe, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xd0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd2 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xdc }, +{ 0x00, 0xfd, 0xdd }, +{ 0x00, 0xfe, 0xde }, +{ 0x00, 0xff, 0xff }, +}; + + +struct cs_info iso2_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x01, 0xb1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x01, 0xb3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x01, 0xb5, 0xa5 }, +{ 0x01, 0xb6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x01, 0xb9, 0xa9 }, +{ 0x01, 0xba, 0xaa }, +{ 0x01, 0xbb, 0xab }, +{ 0x01, 0xbc, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x01, 0xbe, 0xae }, +{ 0x01, 0xbf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xa1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xa3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xa5 }, +{ 0x00, 0xb6, 0xa6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xa9 }, +{ 0x00, 0xba, 0xaa }, +{ 0x00, 0xbb, 0xab }, +{ 0x00, 0xbc, 0xac }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xae }, +{ 0x00, 0xbf, 0xaf }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x01, 0xf0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x01, 0xf2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x01, 0xfc, 0xdc }, +{ 0x01, 0xfd, 0xdd }, +{ 0x01, 0xfe, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xd0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd2 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xdc }, +{ 0x00, 0xfd, 0xdd }, +{ 0x00, 0xfe, 0xde }, +{ 0x00, 0xff, 0xff }, +}; + + +struct cs_info iso3_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x01, 0xb1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x01, 0xb6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x01, 0x69, 0xa9 }, +{ 0x01, 0xba, 0xaa }, +{ 0x01, 0xbb, 0xab }, +{ 0x01, 0xbc, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x01, 0xbf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xa1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xa6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0x49 }, +{ 0x00, 0xba, 0xaa }, +{ 0x00, 0xbb, 0xab }, +{ 0x00, 0xbc, 0xac }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xaf }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x00, 0xc3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x00, 0xd0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x01, 0xf2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x01, 0xfc, 0xdc }, +{ 0x01, 0xfd, 0xdd }, +{ 0x01, 0xfe, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xe3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xf0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd2 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xdc }, +{ 0x00, 0xfd, 0xdd }, +{ 0x00, 0xfe, 0xde }, +{ 0x00, 0xff, 0xff }, +}; + +struct cs_info iso4_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x01, 0xb1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x01, 0xb3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x01, 0xb5, 0xa5 }, +{ 0x01, 0xb6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x01, 0xb9, 0xa9 }, +{ 0x01, 0xba, 0xaa }, +{ 0x01, 0xbb, 0xab }, +{ 0x01, 0xbc, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x01, 0xbe, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xa1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xa3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xa5 }, +{ 0x00, 0xb6, 0xa6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xa9 }, +{ 0x00, 0xba, 0xaa }, +{ 0x00, 0xbb, 0xab }, +{ 0x00, 0xbc, 0xac }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xae }, +{ 0x00, 0xbf, 0xbf }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x01, 0xf0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x01, 0xf2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x01, 0xfc, 0xdc }, +{ 0x01, 0xfd, 0xdd }, +{ 0x01, 0xfe, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xd0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd2 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xdc }, +{ 0x00, 0xfd, 0xdd }, +{ 0x00, 0xfe, 0xde }, +{ 0x00, 0xff, 0xff }, +}; + +struct cs_info iso5_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x01, 0xf1, 0xa1 }, +{ 0x01, 0xf2, 0xa2 }, +{ 0x01, 0xf3, 0xa3 }, +{ 0x01, 0xf4, 0xa4 }, +{ 0x01, 0xf5, 0xa5 }, +{ 0x01, 0xf6, 0xa6 }, +{ 0x01, 0xf7, 0xa7 }, +{ 0x01, 0xf8, 0xa8 }, +{ 0x01, 0xf9, 0xa9 }, +{ 0x01, 0xfa, 0xaa }, +{ 0x01, 0xfb, 0xab }, +{ 0x01, 0xfc, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x01, 0xfe, 0xae }, +{ 0x01, 0xff, 0xaf }, +{ 0x01, 0xd0, 0xb0 }, +{ 0x01, 0xd1, 0xb1 }, +{ 0x01, 0xd2, 0xb2 }, +{ 0x01, 0xd3, 0xb3 }, +{ 0x01, 0xd4, 0xb4 }, +{ 0x01, 0xd5, 0xb5 }, +{ 0x01, 0xd6, 0xb6 }, +{ 0x01, 0xd7, 0xb7 }, +{ 0x01, 0xd8, 0xb8 }, +{ 0x01, 0xd9, 0xb9 }, +{ 0x01, 0xda, 0xba }, +{ 0x01, 0xdb, 0xbb }, +{ 0x01, 0xdc, 0xbc }, +{ 0x01, 0xdd, 0xbd }, +{ 0x01, 0xde, 0xbe }, +{ 0x01, 0xdf, 0xbf }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x00, 0xd0, 0xb0 }, +{ 0x00, 0xd1, 0xb1 }, +{ 0x00, 0xd2, 0xb2 }, +{ 0x00, 0xd3, 0xb3 }, +{ 0x00, 0xd4, 0xb4 }, +{ 0x00, 0xd5, 0xb5 }, +{ 0x00, 0xd6, 0xb6 }, +{ 0x00, 0xd7, 0xb7 }, +{ 0x00, 0xd8, 0xb8 }, +{ 0x00, 0xd9, 0xb9 }, +{ 0x00, 0xda, 0xba }, +{ 0x00, 0xdb, 0xbb }, +{ 0x00, 0xdc, 0xbc }, +{ 0x00, 0xdd, 0xbd }, +{ 0x00, 0xde, 0xbe }, +{ 0x00, 0xdf, 0xbf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xf0 }, +{ 0x00, 0xf1, 0xa1 }, +{ 0x00, 0xf2, 0xa2 }, +{ 0x00, 0xf3, 0xa3 }, +{ 0x00, 0xf4, 0xa4 }, +{ 0x00, 0xf5, 0xa5 }, +{ 0x00, 0xf6, 0xa6 }, +{ 0x00, 0xf7, 0xa7 }, +{ 0x00, 0xf8, 0xa8 }, +{ 0x00, 0xf9, 0xa9 }, +{ 0x00, 0xfa, 0xaa }, +{ 0x00, 0xfb, 0xab }, +{ 0x00, 0xfc, 0xac }, +{ 0x00, 0xfd, 0xfd }, +{ 0x00, 0xfe, 0xae }, +{ 0x00, 0xff, 0xaf }, +}; + +struct cs_info iso6_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x00, 0xc0, 0xc0 }, +{ 0x00, 0xc1, 0xc1 }, +{ 0x00, 0xc2, 0xc2 }, +{ 0x00, 0xc3, 0xc3 }, +{ 0x00, 0xc4, 0xc4 }, +{ 0x00, 0xc5, 0xc5 }, +{ 0x00, 0xc6, 0xc6 }, +{ 0x00, 0xc7, 0xc7 }, +{ 0x00, 0xc8, 0xc8 }, +{ 0x00, 0xc9, 0xc9 }, +{ 0x00, 0xca, 0xca }, +{ 0x00, 0xcb, 0xcb }, +{ 0x00, 0xcc, 0xcc }, +{ 0x00, 0xcd, 0xcd }, +{ 0x00, 0xce, 0xce }, +{ 0x00, 0xcf, 0xcf }, +{ 0x00, 0xd0, 0xd0 }, +{ 0x00, 0xd1, 0xd1 }, +{ 0x00, 0xd2, 0xd2 }, +{ 0x00, 0xd3, 0xd3 }, +{ 0x00, 0xd4, 0xd4 }, +{ 0x00, 0xd5, 0xd5 }, +{ 0x00, 0xd6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x00, 0xd8, 0xd8 }, +{ 0x00, 0xd9, 0xd9 }, +{ 0x00, 0xda, 0xda }, +{ 0x00, 0xdb, 0xdb }, +{ 0x00, 0xdc, 0xdc }, +{ 0x00, 0xdd, 0xdd }, +{ 0x00, 0xde, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xe0 }, +{ 0x00, 0xe1, 0xe1 }, +{ 0x00, 0xe2, 0xe2 }, +{ 0x00, 0xe3, 0xe3 }, +{ 0x00, 0xe4, 0xe4 }, +{ 0x00, 0xe5, 0xe5 }, +{ 0x00, 0xe6, 0xe6 }, +{ 0x00, 0xe7, 0xe7 }, +{ 0x00, 0xe8, 0xe8 }, +{ 0x00, 0xe9, 0xe9 }, +{ 0x00, 0xea, 0xea }, +{ 0x00, 0xeb, 0xeb }, +{ 0x00, 0xec, 0xec }, +{ 0x00, 0xed, 0xed }, +{ 0x00, 0xee, 0xee }, +{ 0x00, 0xef, 0xef }, +{ 0x00, 0xf0, 0xf0 }, +{ 0x00, 0xf1, 0xf1 }, +{ 0x00, 0xf2, 0xf2 }, +{ 0x00, 0xf3, 0xf3 }, +{ 0x00, 0xf4, 0xf4 }, +{ 0x00, 0xf5, 0xf5 }, +{ 0x00, 0xf6, 0xf6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xf8 }, +{ 0x00, 0xf9, 0xf9 }, +{ 0x00, 0xfa, 0xfa }, +{ 0x00, 0xfb, 0xfb }, +{ 0x00, 0xfc, 0xfc }, +{ 0x00, 0xfd, 0xfd }, +{ 0x00, 0xfe, 0xfe }, +{ 0x00, 0xff, 0xff }, +}; + +struct cs_info iso7_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x01, 0xdc, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x01, 0xdd, 0xb8 }, +{ 0x01, 0xde, 0xb9 }, +{ 0x01, 0xdf, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x01, 0xfc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x01, 0xfd, 0xbe }, +{ 0x01, 0xfe, 0xbf }, +{ 0x00, 0xc0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x01, 0xf0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x00, 0xd2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x01, 0xf7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x00, 0xdc, 0xb6 }, +{ 0x00, 0xdd, 0xb8 }, +{ 0x00, 0xde, 0xb9 }, +{ 0x00, 0xdf, 0xba }, +{ 0x00, 0xe0, 0xe0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xd0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd3 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xd7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xbc }, +{ 0x00, 0xfd, 0xbe }, +{ 0x00, 0xfe, 0xbf }, +{ 0x00, 0xff, 0xff }, +}; + +struct cs_info iso8_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x00, 0xc0, 0xc0 }, +{ 0x00, 0xc1, 0xc1 }, +{ 0x00, 0xc2, 0xc2 }, +{ 0x00, 0xc3, 0xc3 }, +{ 0x00, 0xc4, 0xc4 }, +{ 0x00, 0xc5, 0xc5 }, +{ 0x00, 0xc6, 0xc6 }, +{ 0x00, 0xc7, 0xc7 }, +{ 0x00, 0xc8, 0xc8 }, +{ 0x00, 0xc9, 0xc9 }, +{ 0x00, 0xca, 0xca }, +{ 0x00, 0xcb, 0xcb }, +{ 0x00, 0xcc, 0xcc }, +{ 0x00, 0xcd, 0xcd }, +{ 0x00, 0xce, 0xce }, +{ 0x00, 0xcf, 0xcf }, +{ 0x00, 0xd0, 0xd0 }, +{ 0x00, 0xd1, 0xd1 }, +{ 0x00, 0xd2, 0xd2 }, +{ 0x00, 0xd3, 0xd3 }, +{ 0x00, 0xd4, 0xd4 }, +{ 0x00, 0xd5, 0xd5 }, +{ 0x00, 0xd6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x00, 0xd8, 0xd8 }, +{ 0x00, 0xd9, 0xd9 }, +{ 0x00, 0xda, 0xda }, +{ 0x00, 0xdb, 0xdb }, +{ 0x00, 0xdc, 0xdc }, +{ 0x00, 0xdd, 0xdd }, +{ 0x00, 0xde, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xe0 }, +{ 0x00, 0xe1, 0xe1 }, +{ 0x00, 0xe2, 0xe2 }, +{ 0x00, 0xe3, 0xe3 }, +{ 0x00, 0xe4, 0xe4 }, +{ 0x00, 0xe5, 0xe5 }, +{ 0x00, 0xe6, 0xe6 }, +{ 0x00, 0xe7, 0xe7 }, +{ 0x00, 0xe8, 0xe8 }, +{ 0x00, 0xe9, 0xe9 }, +{ 0x00, 0xea, 0xea }, +{ 0x00, 0xeb, 0xeb }, +{ 0x00, 0xec, 0xec }, +{ 0x00, 0xed, 0xed }, +{ 0x00, 0xee, 0xee }, +{ 0x00, 0xef, 0xef }, +{ 0x00, 0xf0, 0xf0 }, +{ 0x00, 0xf1, 0xf1 }, +{ 0x00, 0xf2, 0xf2 }, +{ 0x00, 0xf3, 0xf3 }, +{ 0x00, 0xf4, 0xf4 }, +{ 0x00, 0xf5, 0xf5 }, +{ 0x00, 0xf6, 0xf6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xf8 }, +{ 0x00, 0xf9, 0xf9 }, +{ 0x00, 0xfa, 0xfa }, +{ 0x00, 0xfb, 0xfb }, +{ 0x00, 0xfc, 0xfc }, +{ 0x00, 0xfd, 0xfd }, +{ 0x00, 0xfe, 0xfe }, +{ 0x00, 0xff, 0xff }, +}; + +struct cs_info iso9_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0xfd, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0xdd }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x01, 0xf0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x01, 0xf2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x01, 0xfc, 0xdc }, +{ 0x01, 0x69, 0xdd }, +{ 0x01, 0xfe, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xd0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd2 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xdc }, +{ 0x00, 0xfd, 0x49 }, +{ 0x00, 0xfe, 0xde }, +{ 0x00, 0xff, 0xff }, +}; + +struct cs_info iso10_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x00, 0xc0, 0xc0 }, +{ 0x00, 0xc1, 0xc1 }, +{ 0x00, 0xc2, 0xc2 }, +{ 0x00, 0xc3, 0xc3 }, +{ 0x00, 0xc4, 0xc4 }, +{ 0x00, 0xc5, 0xc5 }, +{ 0x00, 0xc6, 0xc6 }, +{ 0x00, 0xc7, 0xc7 }, +{ 0x00, 0xc8, 0xc8 }, +{ 0x00, 0xc9, 0xc9 }, +{ 0x00, 0xca, 0xca }, +{ 0x00, 0xcb, 0xcb }, +{ 0x00, 0xcc, 0xcc }, +{ 0x00, 0xcd, 0xcd }, +{ 0x00, 0xce, 0xce }, +{ 0x00, 0xcf, 0xcf }, +{ 0x00, 0xd0, 0xd0 }, +{ 0x00, 0xd1, 0xd1 }, +{ 0x00, 0xd2, 0xd2 }, +{ 0x00, 0xd3, 0xd3 }, +{ 0x00, 0xd4, 0xd4 }, +{ 0x00, 0xd5, 0xd5 }, +{ 0x00, 0xd6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x00, 0xd8, 0xd8 }, +{ 0x00, 0xd9, 0xd9 }, +{ 0x00, 0xda, 0xda }, +{ 0x00, 0xdb, 0xdb }, +{ 0x00, 0xdc, 0xdc }, +{ 0x00, 0xdd, 0xdd }, +{ 0x00, 0xde, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xe0 }, +{ 0x00, 0xe1, 0xe1 }, +{ 0x00, 0xe2, 0xe2 }, +{ 0x00, 0xe3, 0xe3 }, +{ 0x00, 0xe4, 0xe4 }, +{ 0x00, 0xe5, 0xe5 }, +{ 0x00, 0xe6, 0xe6 }, +{ 0x00, 0xe7, 0xe7 }, +{ 0x00, 0xe8, 0xe8 }, +{ 0x00, 0xe9, 0xe9 }, +{ 0x00, 0xea, 0xea }, +{ 0x00, 0xeb, 0xeb }, +{ 0x00, 0xec, 0xec }, +{ 0x00, 0xed, 0xed }, +{ 0x00, 0xee, 0xee }, +{ 0x00, 0xef, 0xef }, +{ 0x00, 0xf0, 0xf0 }, +{ 0x00, 0xf1, 0xf1 }, +{ 0x00, 0xf2, 0xf2 }, +{ 0x00, 0xf3, 0xf3 }, +{ 0x00, 0xf4, 0xf4 }, +{ 0x00, 0xf5, 0xf5 }, +{ 0x00, 0xf6, 0xf6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xf8 }, +{ 0x00, 0xf9, 0xf9 }, +{ 0x00, 0xfa, 0xfa }, +{ 0x00, 0xfb, 0xfb }, +{ 0x00, 0xfc, 0xfc }, +{ 0x00, 0xfd, 0xfd }, +{ 0x00, 0xfe, 0xfe }, +{ 0x00, 0xff, 0xff }, +}; + +struct cs_info koi8r_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xb3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x01, 0xa3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x00, 0xc0, 0xe0 }, +{ 0x00, 0xc1, 0xe1 }, +{ 0x00, 0xc2, 0xe2 }, +{ 0x00, 0xc3, 0xe3 }, +{ 0x00, 0xc4, 0xe4 }, +{ 0x00, 0xc5, 0xe5 }, +{ 0x00, 0xc6, 0xe6 }, +{ 0x00, 0xc7, 0xe7 }, +{ 0x00, 0xc8, 0xe8 }, +{ 0x00, 0xc9, 0xe9 }, +{ 0x00, 0xca, 0xea }, +{ 0x00, 0xcb, 0xeb }, +{ 0x00, 0xcc, 0xec }, +{ 0x00, 0xcd, 0xed }, +{ 0x00, 0xce, 0xee }, +{ 0x00, 0xcf, 0xef }, +{ 0x00, 0xd0, 0xf0 }, +{ 0x00, 0xd1, 0xf1 }, +{ 0x00, 0xd2, 0xf2 }, +{ 0x00, 0xd3, 0xf3 }, +{ 0x00, 0xd4, 0xf4 }, +{ 0x00, 0xd5, 0xf5 }, +{ 0x00, 0xd6, 0xf6 }, +{ 0x00, 0xd7, 0xf7 }, +{ 0x00, 0xd8, 0xf8 }, +{ 0x00, 0xd9, 0xf9 }, +{ 0x00, 0xda, 0xfa }, +{ 0x00, 0xdb, 0xfb }, +{ 0x00, 0xdc, 0xfc }, +{ 0x00, 0xdd, 0xfd }, +{ 0x00, 0xde, 0xfe }, +{ 0x00, 0xdf, 0xff }, +{ 0x01, 0xc0, 0xe0 }, +{ 0x01, 0xc1, 0xe1 }, +{ 0x01, 0xc2, 0xe2 }, +{ 0x01, 0xc3, 0xe3 }, +{ 0x01, 0xc4, 0xe4 }, +{ 0x01, 0xc5, 0xe5 }, +{ 0x01, 0xc6, 0xe6 }, +{ 0x01, 0xc7, 0xe7 }, +{ 0x01, 0xc8, 0xe8 }, +{ 0x01, 0xc9, 0xe9 }, +{ 0x01, 0xca, 0xea }, +{ 0x01, 0xcb, 0xeb }, +{ 0x01, 0xcc, 0xec }, +{ 0x01, 0xcd, 0xed }, +{ 0x01, 0xce, 0xee }, +{ 0x01, 0xcf, 0xef }, +{ 0x01, 0xd0, 0xf0 }, +{ 0x01, 0xd1, 0xf1 }, +{ 0x01, 0xd2, 0xf2 }, +{ 0x01, 0xd3, 0xf3 }, +{ 0x01, 0xd4, 0xf4 }, +{ 0x01, 0xd5, 0xf5 }, +{ 0x01, 0xd6, 0xf6 }, +{ 0x01, 0xd7, 0xf7 }, +{ 0x01, 0xd8, 0xf8 }, +{ 0x01, 0xd9, 0xf9 }, +{ 0x01, 0xda, 0xfa }, +{ 0x01, 0xdb, 0xfb }, +{ 0x01, 0xdc, 0xfc }, +{ 0x01, 0xdd, 0xfd }, +{ 0x01, 0xde, 0xfe }, +{ 0x01, 0xdf, 0xff }, +}; + +struct cs_info koi8u_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xb3 }, +{ 0x00, 0xa4, 0xb4 }, /* ie */ +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xb6 }, /* i */ +{ 0x00, 0xa7, 0xb7 }, /* ii */ +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xbd }, /* g'' */ +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x01, 0xa3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, /* IE */ +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, /* I */ +{ 0x00, 0xb7, 0xb7 }, /* II */ +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x00, 0xc0, 0xe0 }, +{ 0x00, 0xc1, 0xe1 }, +{ 0x00, 0xc2, 0xe2 }, +{ 0x00, 0xc3, 0xe3 }, +{ 0x00, 0xc4, 0xe4 }, +{ 0x00, 0xc5, 0xe5 }, +{ 0x00, 0xc6, 0xe6 }, +{ 0x00, 0xc7, 0xe7 }, +{ 0x00, 0xc8, 0xe8 }, +{ 0x00, 0xc9, 0xe9 }, +{ 0x00, 0xca, 0xea }, +{ 0x00, 0xcb, 0xeb }, +{ 0x00, 0xcc, 0xec }, +{ 0x00, 0xcd, 0xed }, +{ 0x00, 0xce, 0xee }, +{ 0x00, 0xcf, 0xef }, +{ 0x00, 0xd0, 0xf0 }, +{ 0x00, 0xd1, 0xf1 }, +{ 0x00, 0xd2, 0xf2 }, +{ 0x00, 0xd3, 0xf3 }, +{ 0x00, 0xd4, 0xf4 }, +{ 0x00, 0xd5, 0xf5 }, +{ 0x00, 0xd6, 0xf6 }, +{ 0x00, 0xd7, 0xf7 }, +{ 0x00, 0xd8, 0xf8 }, +{ 0x00, 0xd9, 0xf9 }, +{ 0x00, 0xda, 0xfa }, +{ 0x00, 0xdb, 0xfb }, +{ 0x00, 0xdc, 0xfc }, +{ 0x00, 0xdd, 0xfd }, +{ 0x00, 0xde, 0xfe }, +{ 0x00, 0xdf, 0xff }, +{ 0x01, 0xc0, 0xe0 }, +{ 0x01, 0xc1, 0xe1 }, +{ 0x01, 0xc2, 0xe2 }, +{ 0x01, 0xc3, 0xe3 }, +{ 0x01, 0xc4, 0xe4 }, +{ 0x01, 0xc5, 0xe5 }, +{ 0x01, 0xc6, 0xe6 }, +{ 0x01, 0xc7, 0xe7 }, +{ 0x01, 0xc8, 0xe8 }, +{ 0x01, 0xc9, 0xe9 }, +{ 0x01, 0xca, 0xea }, +{ 0x01, 0xcb, 0xeb }, +{ 0x01, 0xcc, 0xec }, +{ 0x01, 0xcd, 0xed }, +{ 0x01, 0xce, 0xee }, +{ 0x01, 0xcf, 0xef }, +{ 0x01, 0xd0, 0xf0 }, +{ 0x01, 0xd1, 0xf1 }, +{ 0x01, 0xd2, 0xf2 }, +{ 0x01, 0xd3, 0xf3 }, +{ 0x01, 0xd4, 0xf4 }, +{ 0x01, 0xd5, 0xf5 }, +{ 0x01, 0xd6, 0xf6 }, +{ 0x01, 0xd7, 0xf7 }, +{ 0x01, 0xd8, 0xf8 }, +{ 0x01, 0xd9, 0xf9 }, +{ 0x01, 0xda, 0xfa }, +{ 0x01, 0xdb, 0xfb }, +{ 0x01, 0xdc, 0xfc }, +{ 0x01, 0xdd, 0xfd }, +{ 0x01, 0xde, 0xfe }, +{ 0x01, 0xdf, 0xff }, +}; + +struct cs_info cp1251_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x01, 0x90, 0x80 }, +{ 0x01, 0x83, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x81 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x01, 0x9a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x01, 0x9c, 0x8c }, +{ 0x01, 0x9d, 0x8d }, +{ 0x01, 0x9e, 0x8e }, +{ 0x01, 0x9f, 0x8f }, +{ 0x00, 0x90, 0x80 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x8a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x8c }, +{ 0x00, 0x9d, 0x8d }, +{ 0x00, 0x9e, 0x8e }, +{ 0x00, 0x9f, 0x8f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x01, 0xa2, 0xa1 }, +{ 0x00, 0xa2, 0xa1 }, +{ 0x01, 0xbc, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x01, 0xb4, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x01, 0xb8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x01, 0xba, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x01, 0xbf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x01, 0xb3, 0xb2 }, +{ 0x00, 0xb3, 0xb2 }, +{ 0x00, 0xb4, 0xa5 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xa8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xaa }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xa3 }, +{ 0x01, 0xbe, 0xbd }, +{ 0x00, 0xbe, 0xbd }, +{ 0x00, 0xbf, 0xaf }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x01, 0xf0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x01, 0xf2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x01, 0xf7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x01, 0xfc, 0xdc }, +{ 0x01, 0xfd, 0xdd }, +{ 0x01, 0xfe, 0xde }, +{ 0x01, 0xff, 0xdf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xd0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd2 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xd7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xdc }, +{ 0x00, 0xfd, 0xdd }, +{ 0x00, 0xfe, 0xde }, +{ 0x00, 0xff, 0xdf }, +}; + +struct cs_info iso13_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0A, 0x0A }, +{ 0x00, 0x0B, 0x0B }, +{ 0x00, 0x0C, 0x0C }, +{ 0x00, 0x0D, 0x0D }, +{ 0x00, 0x0E, 0x0E }, +{ 0x00, 0x0F, 0x0F }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1A, 0x1A }, +{ 0x00, 0x1B, 0x1B }, +{ 0x00, 0x1C, 0x1C }, +{ 0x00, 0x1D, 0x1D }, +{ 0x00, 0x1E, 0x1E }, +{ 0x00, 0x1F, 0x1F }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2A, 0x2A }, +{ 0x00, 0x2B, 0x2B }, +{ 0x00, 0x2C, 0x2C }, +{ 0x00, 0x2D, 0x2D }, +{ 0x00, 0x2E, 0x2E }, +{ 0x00, 0x2F, 0x2F }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3A, 0x3A }, +{ 0x00, 0x3B, 0x3B }, +{ 0x00, 0x3C, 0x3C }, +{ 0x00, 0x3D, 0x3D }, +{ 0x00, 0x3E, 0x3E }, +{ 0x00, 0x3F, 0x3F }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6A, 0x4A }, +{ 0x01, 0x6B, 0x4B }, +{ 0x01, 0x6C, 0x4C }, +{ 0x01, 0x6D, 0x4D }, +{ 0x01, 0x6E, 0x4E }, +{ 0x01, 0x6F, 0x4F }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7A, 0x5A }, +{ 0x00, 0x5B, 0x5B }, +{ 0x00, 0x5C, 0x5C }, +{ 0x00, 0x5D, 0x5D }, +{ 0x00, 0x5E, 0x5E }, +{ 0x00, 0x5F, 0x5F }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6A, 0x4A }, +{ 0x00, 0x6B, 0x4B }, +{ 0x00, 0x6C, 0x4C }, +{ 0x00, 0x6D, 0x4D }, +{ 0x00, 0x6E, 0x4E }, +{ 0x00, 0x6F, 0x4F }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7A, 0x5A }, +{ 0x00, 0x7B, 0x7B }, +{ 0x00, 0x7C, 0x7C }, +{ 0x00, 0x7D, 0x7D }, +{ 0x00, 0x7E, 0x7E }, +{ 0x00, 0x7F, 0x7F }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8A, 0x8A }, +{ 0x00, 0x8B, 0x8B }, +{ 0x00, 0x8C, 0x8C }, +{ 0x00, 0x8D, 0x8D }, +{ 0x00, 0x8E, 0x8E }, +{ 0x00, 0x8F, 0x8F }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9A, 0x9A }, +{ 0x00, 0x9B, 0x9B }, +{ 0x00, 0x9C, 0x9C }, +{ 0x00, 0x9D, 0x9D }, +{ 0x00, 0x9E, 0x9E }, +{ 0x00, 0x9F, 0x9F }, +{ 0x00, 0xA0, 0xA0 }, +{ 0x00, 0xA1, 0xA1 }, +{ 0x00, 0xA2, 0xA2 }, +{ 0x00, 0xA3, 0xA3 }, +{ 0x00, 0xA4, 0xA4 }, +{ 0x00, 0xA5, 0xA5 }, +{ 0x00, 0xA6, 0xA6 }, +{ 0x00, 0xA7, 0xA7 }, +{ 0x01, 0xB8, 0xA8 }, +{ 0x00, 0xA9, 0xA9 }, +{ 0x01, 0xBA, 0xAA }, +{ 0x00, 0xAB, 0xAB }, +{ 0x00, 0xAC, 0xAC }, +{ 0x00, 0xAD, 0xAD }, +{ 0x00, 0xAE, 0xAE }, +{ 0x01, 0xBF, 0xAF }, +{ 0x00, 0xB0, 0xB0 }, +{ 0x00, 0xB1, 0xB1 }, +{ 0x00, 0xB2, 0xB2 }, +{ 0x00, 0xB3, 0xB3 }, +{ 0x00, 0xB4, 0xB4 }, +{ 0x00, 0xB5, 0xB5 }, +{ 0x00, 0xB6, 0xB6 }, +{ 0x00, 0xB7, 0xB7 }, +{ 0x00, 0xB8, 0xA8 }, +{ 0x00, 0xB9, 0xB9 }, +{ 0x00, 0xBA, 0xAA }, +{ 0x00, 0xBB, 0xBB }, +{ 0x00, 0xBC, 0xBC }, +{ 0x00, 0xBD, 0xBD }, +{ 0x00, 0xBE, 0xBE }, +{ 0x00, 0xBF, 0xAF }, +{ 0x01, 0xE0, 0xC0 }, +{ 0x01, 0xE1, 0xC1 }, +{ 0x01, 0xE2, 0xC2 }, +{ 0x01, 0xE3, 0xC3 }, +{ 0x01, 0xE4, 0xC4 }, +{ 0x01, 0xE5, 0xC5 }, +{ 0x01, 0xE6, 0xC6 }, +{ 0x01, 0xE7, 0xC7 }, +{ 0x01, 0xE8, 0xC8 }, +{ 0x01, 0xE9, 0xC9 }, +{ 0x01, 0xEA, 0xCA }, +{ 0x01, 0xEB, 0xCB }, +{ 0x01, 0xEC, 0xCC }, +{ 0x01, 0xED, 0xCD }, +{ 0x01, 0xEE, 0xCE }, +{ 0x01, 0xEF, 0xCF }, +{ 0x01, 0xF0, 0xD0 }, +{ 0x01, 0xF1, 0xD1 }, +{ 0x01, 0xF2, 0xD2 }, +{ 0x01, 0xF3, 0xD3 }, +{ 0x01, 0xF4, 0xD4 }, +{ 0x01, 0xF5, 0xD5 }, +{ 0x01, 0xF6, 0xD6 }, +{ 0x00, 0xD7, 0xD7 }, +{ 0x01, 0xF8, 0xD8 }, +{ 0x01, 0xF9, 0xD9 }, +{ 0x01, 0xFA, 0xDA }, +{ 0x01, 0xFB, 0xDB }, +{ 0x01, 0xFC, 0xDC }, +{ 0x01, 0xFD, 0xDD }, +{ 0x01, 0xFE, 0xDE }, +{ 0x00, 0xDF, 0xDF }, +{ 0x00, 0xE0, 0xC0 }, +{ 0x00, 0xE1, 0xC1 }, +{ 0x00, 0xE2, 0xC2 }, +{ 0x00, 0xE3, 0xC3 }, +{ 0x00, 0xE4, 0xC4 }, +{ 0x00, 0xE5, 0xC5 }, +{ 0x00, 0xE6, 0xC6 }, +{ 0x00, 0xE7, 0xC7 }, +{ 0x00, 0xE8, 0xC8 }, +{ 0x00, 0xE9, 0xC9 }, +{ 0x00, 0xEA, 0xCA }, +{ 0x00, 0xEB, 0xCB }, +{ 0x00, 0xEC, 0xCC }, +{ 0x00, 0xED, 0xCD }, +{ 0x00, 0xEE, 0xCE }, +{ 0x00, 0xEF, 0xCF }, +{ 0x00, 0xF0, 0xD0 }, +{ 0x00, 0xF1, 0xD1 }, +{ 0x00, 0xF2, 0xD2 }, +{ 0x00, 0xF3, 0xD3 }, +{ 0x00, 0xF4, 0xD4 }, +{ 0x00, 0xF5, 0xD5 }, +{ 0x00, 0xF6, 0xD6 }, +{ 0x00, 0xF7, 0xF7 }, +{ 0x00, 0xF8, 0xD8 }, +{ 0x00, 0xF9, 0xD9 }, +{ 0x00, 0xFA, 0xDA }, +{ 0x00, 0xFB, 0xDB }, +{ 0x00, 0xFC, 0xDC }, +{ 0x00, 0xFD, 0xDD }, +{ 0x00, 0xFE, 0xDE }, +{ 0x00, 0xFF, 0xFF }, +}; + + +struct cs_info iso14_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x01, 0xa2, 0xa1 }, +{ 0x00, 0xa2, 0xa1 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x01, 0xa5, 0xa4 }, +{ 0x00, 0xa5, 0xa4 }, +{ 0x01, 0xa6, 0xab }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x01, 0xb8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x01, 0xba, 0xaa }, +{ 0x00, 0xab, 0xa6 }, +{ 0x01, 0xbc, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x01, 0xff, 0xaf }, +{ 0x01, 0xb1, 0xb0 }, +{ 0x00, 0xb1, 0xb0 }, +{ 0x01, 0xb3, 0xb2 }, +{ 0x00, 0xb3, 0xb2 }, +{ 0x01, 0xb5, 0xb4 }, +{ 0x00, 0xb5, 0xb4 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x01, 0xb9, 0xb7 }, +{ 0x00, 0xb8, 0xa8 }, +{ 0x00, 0xb9, 0xb6 }, +{ 0x00, 0xba, 0xaa }, +{ 0x01, 0xbf, 0xbb }, +{ 0x00, 0xbc, 0xac }, +{ 0x01, 0xbe, 0xbd }, +{ 0x00, 0xbe, 0xbd }, +{ 0x00, 0xbf, 0xbb }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x01, 0xf0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x01, 0xf2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x01, 0xf7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x01, 0xfc, 0xdc }, +{ 0x01, 0xfd, 0xdd }, +{ 0x01, 0xfe, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xd0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd2 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xd7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xdc }, +{ 0x00, 0xfd, 0xdd }, +{ 0x00, 0xfe, 0xde }, +{ 0x00, 0xff, 0xff }, +}; + +struct cs_info iso15_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x01, 0xa8, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa6 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x01, 0xb8, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb4 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x01, 0xbd, 0xbc }, +{ 0x00, 0xbd, 0xbc }, +{ 0x01, 0xff, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x01, 0xe0, 0xc0 }, +{ 0x01, 0xe1, 0xc1 }, +{ 0x01, 0xe2, 0xc2 }, +{ 0x01, 0xe3, 0xc3 }, +{ 0x01, 0xe4, 0xc4 }, +{ 0x01, 0xe5, 0xc5 }, +{ 0x01, 0xe6, 0xc6 }, +{ 0x01, 0xe7, 0xc7 }, +{ 0x01, 0xe8, 0xc8 }, +{ 0x01, 0xe9, 0xc9 }, +{ 0x01, 0xea, 0xca }, +{ 0x01, 0xeb, 0xcb }, +{ 0x01, 0xec, 0xcc }, +{ 0x01, 0xed, 0xcd }, +{ 0x01, 0xee, 0xce }, +{ 0x01, 0xef, 0xcf }, +{ 0x01, 0xf0, 0xd0 }, +{ 0x01, 0xf1, 0xd1 }, +{ 0x01, 0xf2, 0xd2 }, +{ 0x01, 0xf3, 0xd3 }, +{ 0x01, 0xf4, 0xd4 }, +{ 0x01, 0xf5, 0xd5 }, +{ 0x01, 0xf6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x01, 0xf8, 0xd8 }, +{ 0x01, 0xf9, 0xd9 }, +{ 0x01, 0xfa, 0xda }, +{ 0x01, 0xfb, 0xdb }, +{ 0x01, 0xfc, 0xdc }, +{ 0x01, 0xfd, 0xdd }, +{ 0x01, 0xfe, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xc0 }, +{ 0x00, 0xe1, 0xc1 }, +{ 0x00, 0xe2, 0xc2 }, +{ 0x00, 0xe3, 0xc3 }, +{ 0x00, 0xe4, 0xc4 }, +{ 0x00, 0xe5, 0xc5 }, +{ 0x00, 0xe6, 0xc6 }, +{ 0x00, 0xe7, 0xc7 }, +{ 0x00, 0xe8, 0xc8 }, +{ 0x00, 0xe9, 0xc9 }, +{ 0x00, 0xea, 0xca }, +{ 0x00, 0xeb, 0xcb }, +{ 0x00, 0xec, 0xcc }, +{ 0x00, 0xed, 0xcd }, +{ 0x00, 0xee, 0xce }, +{ 0x00, 0xef, 0xcf }, +{ 0x00, 0xf0, 0xd0 }, +{ 0x00, 0xf1, 0xd1 }, +{ 0x00, 0xf2, 0xd2 }, +{ 0x00, 0xf3, 0xd3 }, +{ 0x00, 0xf4, 0xd4 }, +{ 0x00, 0xf5, 0xd5 }, +{ 0x00, 0xf6, 0xd6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xd8 }, +{ 0x00, 0xf9, 0xd9 }, +{ 0x00, 0xfa, 0xda }, +{ 0x00, 0xfb, 0xdb }, +{ 0x00, 0xfc, 0xdc }, +{ 0x00, 0xfd, 0xdd }, +{ 0x00, 0xfe, 0xde }, +{ 0x00, 0xff, 0xbe }, +}; + +struct cs_info iscii_devanagari_tbl[] = { +{ 0x00, 0x00, 0x00 }, +{ 0x00, 0x01, 0x01 }, +{ 0x00, 0x02, 0x02 }, +{ 0x00, 0x03, 0x03 }, +{ 0x00, 0x04, 0x04 }, +{ 0x00, 0x05, 0x05 }, +{ 0x00, 0x06, 0x06 }, +{ 0x00, 0x07, 0x07 }, +{ 0x00, 0x08, 0x08 }, +{ 0x00, 0x09, 0x09 }, +{ 0x00, 0x0a, 0x0a }, +{ 0x00, 0x0b, 0x0b }, +{ 0x00, 0x0c, 0x0c }, +{ 0x00, 0x0d, 0x0d }, +{ 0x00, 0x0e, 0x0e }, +{ 0x00, 0x0f, 0x0f }, +{ 0x00, 0x10, 0x10 }, +{ 0x00, 0x11, 0x11 }, +{ 0x00, 0x12, 0x12 }, +{ 0x00, 0x13, 0x13 }, +{ 0x00, 0x14, 0x14 }, +{ 0x00, 0x15, 0x15 }, +{ 0x00, 0x16, 0x16 }, +{ 0x00, 0x17, 0x17 }, +{ 0x00, 0x18, 0x18 }, +{ 0x00, 0x19, 0x19 }, +{ 0x00, 0x1a, 0x1a }, +{ 0x00, 0x1b, 0x1b }, +{ 0x00, 0x1c, 0x1c }, +{ 0x00, 0x1d, 0x1d }, +{ 0x00, 0x1e, 0x1e }, +{ 0x00, 0x1f, 0x1f }, +{ 0x00, 0x20, 0x20 }, +{ 0x00, 0x21, 0x21 }, +{ 0x00, 0x22, 0x22 }, +{ 0x00, 0x23, 0x23 }, +{ 0x00, 0x24, 0x24 }, +{ 0x00, 0x25, 0x25 }, +{ 0x00, 0x26, 0x26 }, +{ 0x00, 0x27, 0x27 }, +{ 0x00, 0x28, 0x28 }, +{ 0x00, 0x29, 0x29 }, +{ 0x00, 0x2a, 0x2a }, +{ 0x00, 0x2b, 0x2b }, +{ 0x00, 0x2c, 0x2c }, +{ 0x00, 0x2d, 0x2d }, +{ 0x00, 0x2e, 0x2e }, +{ 0x00, 0x2f, 0x2f }, +{ 0x00, 0x30, 0x30 }, +{ 0x00, 0x31, 0x31 }, +{ 0x00, 0x32, 0x32 }, +{ 0x00, 0x33, 0x33 }, +{ 0x00, 0x34, 0x34 }, +{ 0x00, 0x35, 0x35 }, +{ 0x00, 0x36, 0x36 }, +{ 0x00, 0x37, 0x37 }, +{ 0x00, 0x38, 0x38 }, +{ 0x00, 0x39, 0x39 }, +{ 0x00, 0x3a, 0x3a }, +{ 0x00, 0x3b, 0x3b }, +{ 0x00, 0x3c, 0x3c }, +{ 0x00, 0x3d, 0x3d }, +{ 0x00, 0x3e, 0x3e }, +{ 0x00, 0x3f, 0x3f }, +{ 0x00, 0x40, 0x40 }, +{ 0x01, 0x61, 0x41 }, +{ 0x01, 0x62, 0x42 }, +{ 0x01, 0x63, 0x43 }, +{ 0x01, 0x64, 0x44 }, +{ 0x01, 0x65, 0x45 }, +{ 0x01, 0x66, 0x46 }, +{ 0x01, 0x67, 0x47 }, +{ 0x01, 0x68, 0x48 }, +{ 0x01, 0x69, 0x49 }, +{ 0x01, 0x6a, 0x4a }, +{ 0x01, 0x6b, 0x4b }, +{ 0x01, 0x6c, 0x4c }, +{ 0x01, 0x6d, 0x4d }, +{ 0x01, 0x6e, 0x4e }, +{ 0x01, 0x6f, 0x4f }, +{ 0x01, 0x70, 0x50 }, +{ 0x01, 0x71, 0x51 }, +{ 0x01, 0x72, 0x52 }, +{ 0x01, 0x73, 0x53 }, +{ 0x01, 0x74, 0x54 }, +{ 0x01, 0x75, 0x55 }, +{ 0x01, 0x76, 0x56 }, +{ 0x01, 0x77, 0x57 }, +{ 0x01, 0x78, 0x58 }, +{ 0x01, 0x79, 0x59 }, +{ 0x01, 0x7a, 0x5a }, +{ 0x00, 0x5b, 0x5b }, +{ 0x00, 0x5c, 0x5c }, +{ 0x00, 0x5d, 0x5d }, +{ 0x00, 0x5e, 0x5e }, +{ 0x00, 0x5f, 0x5f }, +{ 0x00, 0x60, 0x60 }, +{ 0x00, 0x61, 0x41 }, +{ 0x00, 0x62, 0x42 }, +{ 0x00, 0x63, 0x43 }, +{ 0x00, 0x64, 0x44 }, +{ 0x00, 0x65, 0x45 }, +{ 0x00, 0x66, 0x46 }, +{ 0x00, 0x67, 0x47 }, +{ 0x00, 0x68, 0x48 }, +{ 0x00, 0x69, 0x49 }, +{ 0x00, 0x6a, 0x4a }, +{ 0x00, 0x6b, 0x4b }, +{ 0x00, 0x6c, 0x4c }, +{ 0x00, 0x6d, 0x4d }, +{ 0x00, 0x6e, 0x4e }, +{ 0x00, 0x6f, 0x4f }, +{ 0x00, 0x70, 0x50 }, +{ 0x00, 0x71, 0x51 }, +{ 0x00, 0x72, 0x52 }, +{ 0x00, 0x73, 0x53 }, +{ 0x00, 0x74, 0x54 }, +{ 0x00, 0x75, 0x55 }, +{ 0x00, 0x76, 0x56 }, +{ 0x00, 0x77, 0x57 }, +{ 0x00, 0x78, 0x58 }, +{ 0x00, 0x79, 0x59 }, +{ 0x00, 0x7a, 0x5a }, +{ 0x00, 0x7b, 0x7b }, +{ 0x00, 0x7c, 0x7c }, +{ 0x00, 0x7d, 0x7d }, +{ 0x00, 0x7e, 0x7e }, +{ 0x00, 0x7f, 0x7f }, +{ 0x00, 0x80, 0x80 }, +{ 0x00, 0x81, 0x81 }, +{ 0x00, 0x82, 0x82 }, +{ 0x00, 0x83, 0x83 }, +{ 0x00, 0x84, 0x84 }, +{ 0x00, 0x85, 0x85 }, +{ 0x00, 0x86, 0x86 }, +{ 0x00, 0x87, 0x87 }, +{ 0x00, 0x88, 0x88 }, +{ 0x00, 0x89, 0x89 }, +{ 0x00, 0x8a, 0x8a }, +{ 0x00, 0x8b, 0x8b }, +{ 0x00, 0x8c, 0x8c }, +{ 0x00, 0x8d, 0x8d }, +{ 0x00, 0x8e, 0x8e }, +{ 0x00, 0x8f, 0x8f }, +{ 0x00, 0x90, 0x90 }, +{ 0x00, 0x91, 0x91 }, +{ 0x00, 0x92, 0x92 }, +{ 0x00, 0x93, 0x93 }, +{ 0x00, 0x94, 0x94 }, +{ 0x00, 0x95, 0x95 }, +{ 0x00, 0x96, 0x96 }, +{ 0x00, 0x97, 0x97 }, +{ 0x00, 0x98, 0x98 }, +{ 0x00, 0x99, 0x99 }, +{ 0x00, 0x9a, 0x9a }, +{ 0x00, 0x9b, 0x9b }, +{ 0x00, 0x9c, 0x9c }, +{ 0x00, 0x9d, 0x9d }, +{ 0x00, 0x9e, 0x9e }, +{ 0x00, 0x9f, 0x9f }, +{ 0x00, 0xa0, 0xa0 }, +{ 0x00, 0xa1, 0xa1 }, +{ 0x00, 0xa2, 0xa2 }, +{ 0x00, 0xa3, 0xa3 }, +{ 0x00, 0xa4, 0xa4 }, +{ 0x00, 0xa5, 0xa5 }, +{ 0x00, 0xa6, 0xa6 }, +{ 0x00, 0xa7, 0xa7 }, +{ 0x00, 0xa8, 0xa8 }, +{ 0x00, 0xa9, 0xa9 }, +{ 0x00, 0xaa, 0xaa }, +{ 0x00, 0xab, 0xab }, +{ 0x00, 0xac, 0xac }, +{ 0x00, 0xad, 0xad }, +{ 0x00, 0xae, 0xae }, +{ 0x00, 0xaf, 0xaf }, +{ 0x00, 0xb0, 0xb0 }, +{ 0x00, 0xb1, 0xb1 }, +{ 0x00, 0xb2, 0xb2 }, +{ 0x00, 0xb3, 0xb3 }, +{ 0x00, 0xb4, 0xb4 }, +{ 0x00, 0xb5, 0xb5 }, +{ 0x00, 0xb6, 0xb6 }, +{ 0x00, 0xb7, 0xb7 }, +{ 0x00, 0xb8, 0xb8 }, +{ 0x00, 0xb9, 0xb9 }, +{ 0x00, 0xba, 0xba }, +{ 0x00, 0xbb, 0xbb }, +{ 0x00, 0xbc, 0xbc }, +{ 0x00, 0xbd, 0xbd }, +{ 0x00, 0xbe, 0xbe }, +{ 0x00, 0xbf, 0xbf }, +{ 0x00, 0xc0, 0xc0 }, +{ 0x00, 0xc1, 0xc1 }, +{ 0x00, 0xc2, 0xc2 }, +{ 0x00, 0xc3, 0xc3 }, +{ 0x00, 0xc4, 0xc4 }, +{ 0x00, 0xc5, 0xc5 }, +{ 0x00, 0xc6, 0xc6 }, +{ 0x00, 0xc7, 0xc7 }, +{ 0x00, 0xc8, 0xc8 }, +{ 0x00, 0xc9, 0xc9 }, +{ 0x00, 0xca, 0xca }, +{ 0x00, 0xcb, 0xcb }, +{ 0x00, 0xcc, 0xcc }, +{ 0x00, 0xcd, 0xcd }, +{ 0x00, 0xce, 0xce }, +{ 0x00, 0xcf, 0xcf }, +{ 0x00, 0xd0, 0xd0 }, +{ 0x00, 0xd1, 0xd1 }, +{ 0x00, 0xd2, 0xd2 }, +{ 0x00, 0xd3, 0xd3 }, +{ 0x00, 0xd4, 0xd4 }, +{ 0x00, 0xd5, 0xd5 }, +{ 0x00, 0xd6, 0xd6 }, +{ 0x00, 0xd7, 0xd7 }, +{ 0x00, 0xd8, 0xd8 }, +{ 0x00, 0xd9, 0xd9 }, +{ 0x00, 0xda, 0xda }, +{ 0x00, 0xdb, 0xdb }, +{ 0x00, 0xdc, 0xdc }, +{ 0x00, 0xdd, 0xdd }, +{ 0x00, 0xde, 0xde }, +{ 0x00, 0xdf, 0xdf }, +{ 0x00, 0xe0, 0xe0 }, +{ 0x00, 0xe1, 0xe1 }, +{ 0x00, 0xe2, 0xe2 }, +{ 0x00, 0xe3, 0xe3 }, +{ 0x00, 0xe4, 0xe4 }, +{ 0x00, 0xe5, 0xe5 }, +{ 0x00, 0xe6, 0xe6 }, +{ 0x00, 0xe7, 0xe7 }, +{ 0x00, 0xe8, 0xe8 }, +{ 0x00, 0xe9, 0xe9 }, +{ 0x00, 0xea, 0xea }, +{ 0x00, 0xeb, 0xeb }, +{ 0x00, 0xec, 0xec }, +{ 0x00, 0xed, 0xed }, +{ 0x00, 0xee, 0xee }, +{ 0x00, 0xef, 0xef }, +{ 0x00, 0xf0, 0xf0 }, +{ 0x00, 0xf1, 0xf1 }, +{ 0x00, 0xf2, 0xf2 }, +{ 0x00, 0xf3, 0xf3 }, +{ 0x00, 0xf4, 0xf4 }, +{ 0x00, 0xf5, 0xf5 }, +{ 0x00, 0xf6, 0xf6 }, +{ 0x00, 0xf7, 0xf7 }, +{ 0x00, 0xf8, 0xf8 }, +{ 0x00, 0xf9, 0xf9 }, +{ 0x00, 0xfa, 0xfa }, +{ 0x00, 0xfb, 0xfb }, +{ 0x00, 0xfc, 0xfc }, +{ 0x00, 0xfd, 0xfd }, +{ 0x00, 0xfe, 0xfe }, +{ 0x00, 0xff, 0xff }, +}; + +struct enc_entry encds[] = { +{"ISO8859-1",iso1_tbl}, +{"ISO8859-2",iso2_tbl}, +{"ISO8859-3",iso3_tbl}, +{"ISO8859-4",iso4_tbl}, +{"ISO8859-5",iso5_tbl}, +{"ISO8859-6",iso6_tbl}, +{"ISO8859-7",iso7_tbl}, +{"ISO8859-8",iso8_tbl}, +{"ISO8859-9",iso9_tbl}, +{"ISO8859-10",iso10_tbl}, +{"KOI8-R",koi8r_tbl}, +{"KOI8-U",koi8u_tbl}, +{"microsoft-cp1251",cp1251_tbl}, +{"ISO8859-13", iso13_tbl}, +{"ISO8859-14", iso14_tbl}, +{"ISO8859-15", iso15_tbl}, +{"ISCII-DEVANAGARI", iscii_devanagari_tbl}, +}; + +struct cs_info * get_current_cs(const char * es) { + struct cs_info * ccs = encds[0].cs_table; + int n = sizeof(encds) / sizeof(encds[0]); + for (int i = 0; i < n; i++) { + if (strcmp(es,encds[i].enc_name) == 0) { + ccs = encds[i].cs_table; + } + } + return ccs; +} +#else +// XXX This function was rewritten for mozilla. Instead of storing the +// conversion tables static in this file, create them when needed +// with help the mozilla backend. +struct cs_info * get_current_cs(const char * es) { + struct cs_info *ccs; + + nsCOMPtr encoder; + nsCOMPtr decoder; + nsCOMPtr caseConv; + + nsresult rv; + nsCOMPtr ccm = do_GetService(kCharsetConverterManagerCID, &rv); + if (NS_FAILED(rv)) + return nsnull; + + rv = ccm->GetUnicodeEncoder(es, getter_AddRefs(encoder)); + if (encoder && NS_SUCCEEDED(rv)) + encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?'); + if (NS_FAILED(rv)) + return nsnull; + rv = ccm->GetUnicodeDecoder(es, getter_AddRefs(decoder)); + + caseConv = do_GetService(kUnicharUtilCID, &rv); + if (NS_FAILED(rv)) + return nsnull; + + ccs = (struct cs_info *) malloc(256 * sizeof(cs_info)); + + PRInt32 charLength = 256; + PRInt32 uniLength = 512; + char *source = (char *)malloc(charLength * sizeof(char)); + PRUnichar *uni = (PRUnichar *)malloc(uniLength * sizeof(PRUnichar)); + char *lower = (char *)malloc(charLength * sizeof(char)); + char *upper = (char *)malloc(charLength * sizeof(char)); + + // Create a long string of all chars. + unsigned int i; + for (i = 0x00; i <= 0xff ; ++i) { + source[i] = i; + } + + // Convert this long string to unicode + rv = decoder->Convert(source, &charLength, uni, &uniLength); + + // Do case conversion stuff, and convert back. + caseConv->ToUpper(uni, uni, uniLength); + encoder->Convert(uni, &uniLength, upper, &charLength); + + uniLength = 512; + charLength = 256; + rv = decoder->Convert(source, &charLength, uni, &uniLength); + caseConv->ToLower(uni, uni, uniLength); + encoder->Convert(uni, &uniLength, lower, &charLength); + + // Store + for (i = 0x00; i <= 0xff ; ++i) { + ccs[i].cupper = upper[i]; + ccs[i].clower = lower[i]; + + if (ccs[i].clower != (unsigned char)i) + ccs[i].ccase = true; + else + ccs[i].ccase = false; + + } + + free(source); + free(uni); + free(lower); + free(upper); + + return ccs; +} +#endif + +// primitive isalpha() replacement for tokenization +char * get_casechars(const char * enc) { + struct cs_info * csconv = get_current_cs(enc); + char expw[MAXLNLEN]; + char * p = expw; + for (int i = 0; i <= 255; i++) { + if ((csconv[i].cupper != csconv[i].clower)) { + *p = (char) i; + p++; + } + } + *p = '\0'; +#ifdef MOZILLA_CLIENT + delete csconv; +#endif + return mystrdup(expw); +} + + + +struct lang_map lang2enc[] = { +{"ar", "UTF-8", LANG_ar}, +{"az", "UTF-8", LANG_az}, +{"bg", "microsoft-cp1251", LANG_bg}, +{"ca", "ISO8859-1", LANG_ca}, +{"cs", "ISO8859-2", LANG_cs}, +{"da", "ISO8859-1", LANG_da}, +{"de", "ISO8859-1", LANG_de}, +{"el", "ISO8859-7", LANG_el}, +{"en", "ISO8859-1", LANG_en}, +{"es", "ISO8859-1", LANG_es}, +{"eu", "ISO8859-1", LANG_eu}, +{"gl", "ISO8859-1", LANG_gl}, +{"fr", "ISO8859-15", LANG_fr}, +{"hr", "ISO8859-2", LANG_hr}, +{"hu", "ISO8859-2", LANG_hu}, +{"it", "ISO8859-1", LANG_it}, +{"la", "ISO8859-1", LANG_la}, +{"lv", "ISO8859-13", LANG_lv}, +{"nl", "ISO8859-1", LANG_nl}, +{"pl", "ISO8859-2", LANG_pl}, +{"pt", "ISO8859-1", LANG_pt}, +{"sv", "ISO8859-1", LANG_sv}, +{"tr", "UTF-8", LANG_tr}, +{"ru", "KOI8-R", LANG_ru}, +{"uk", "KOI8-U", LANG_uk} +}; + + +const char * get_default_enc(const char * lang) { + int n = sizeof(lang2enc) / sizeof(lang2enc[0]); + for (int i = 0; i < n; i++) { + if (strcmp(lang,lang2enc[i].lang) == 0) { + return lang2enc[i].def_enc; + } + } + return NULL; +} + +int get_lang_num(const char * lang) { + int n = sizeof(lang2enc) / sizeof(lang2enc[0]); + for (int i = 0; i < n; i++) { + if (strncmp(lang,lang2enc[i].lang,2) == 0) { + return lang2enc[i].num; + } + } + return LANG_xx; +} + +#ifndef OPENOFFICEORG +#ifndef MOZILLA_CLIENT +int initialize_utf_tbl() { + utf_tbl_count++; + if (utf_tbl) return 0; + utf_tbl = (unicode_info2 *) malloc(CONTSIZE * sizeof(unicode_info2)); + if (utf_tbl) { + int j; + for (j = 0; j < CONTSIZE; j++) { + utf_tbl[j].cletter = 0; + utf_tbl[j].clower = (unsigned short) j; + utf_tbl[j].cupper = (unsigned short) j; + } + for (j = 0; j < UTF_LST_LEN; j++) { + utf_tbl[utf_lst[j].c].cletter = 1; + utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower; + utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper; + } + } else return 1; + return 0; +} +#endif +#endif + +void free_utf_tbl() { + if (utf_tbl_count > 0) utf_tbl_count--; + if (utf_tbl && (utf_tbl_count == 0)) { + free(utf_tbl); + utf_tbl = NULL; + } +} + +#ifdef MOZILLA_CLIENT +static nsCOMPtr& getcaseConv() +{ + nsresult rv; + static nsCOMPtr caseConv = do_GetService(kUnicharUtilCID, &rv); + return caseConv; +} +#endif + +unsigned short unicodetoupper(unsigned short c, int langnum) +{ + // In Azeri and Turkish, I and i dictinct letters: + // There are a dotless lower case i pair of upper `I', + // and an upper I with dot pair of lower `i'. + if (c == 0x0069 && ((langnum == LANG_az) || (langnum == LANG_tr))) + return 0x0130; +#ifdef OPENOFFICEORG + return u_toupper(c); +#else +#ifdef MOZILLA_CLIENT + PRUnichar ch2; + getcaseConv()->ToUpper((PRUnichar) c, &ch2); + return ch2; +#else + return (utf_tbl) ? utf_tbl[c].cupper : c; +#endif +#endif +} + +unsigned short unicodetolower(unsigned short c, int langnum) +{ + // In Azeri and Turkish, I and i dictinct letters: + // There are a dotless lower case i pair of upper `I', + // and an upper I with dot pair of lower `i'. + if (c == 0x0049 && ((langnum == LANG_az) || (langnum == LANG_tr))) + return 0x0131; +#ifdef OPENOFFICEORG + return u_tolower(c); +#else +#ifdef MOZILLA_CLIENT + PRUnichar ch2; + getcaseConv()->ToLower((PRUnichar) c, &ch2); + return ch2; +#else + return (utf_tbl) ? utf_tbl[c].clower : c; +#endif +#endif +} + +int unicodeisalpha(unsigned short c) +{ +#ifdef OPENOFFICEORG + return u_isalpha(c); +#else + return (utf_tbl) ? utf_tbl[c].cletter : 0; +#endif +} + +/* get type of capitalization */ +int get_captype(char * word, int nl, cs_info * csconv) { + // now determine the capitalization type of the first nl letters + int ncap = 0; + int nneutral = 0; + int firstcap = 0; + + for (char * q = word; *q != '\0'; q++) { + if (csconv[*((unsigned char *)q)].ccase) ncap++; + if (csconv[*((unsigned char *)q)].cupper == csconv[*((unsigned char *)q)].clower) nneutral++; + } + if (ncap) { + firstcap = csconv[*((unsigned char *) word)].ccase; + } + + // now finally set the captype + if (ncap == 0) { + return NOCAP; + } else if ((ncap == 1) && firstcap) { + return INITCAP; + } else if ((ncap == nl) || ((ncap + nneutral) == nl)) { + return ALLCAP; + } else if ((ncap > 1) && firstcap) { + return HUHINITCAP; + } + return HUHCAP; +} + +int get_captype_utf8(w_char * word, int nl, int langnum) { + // now determine the capitalization type of the first nl letters + int ncap = 0; + int nneutral = 0; + int firstcap = 0; + unsigned short idx; + // don't check too long words + if (nl >= MAXWORDLEN) return 0; + // big Unicode character (non BMP area) + if (nl == -1) return NOCAP; + for (int i = 0; i < nl; i++) { + idx = (word[i].h << 8) + word[i].l; + if (idx != unicodetolower(idx, langnum)) ncap++; + if (unicodetoupper(idx, langnum) == unicodetolower(idx, langnum)) nneutral++; + } + if (ncap) { + idx = (word[0].h << 8) + word[0].l; + firstcap = (idx != unicodetolower(idx, langnum)); + } + + // now finally set the captype + if (ncap == 0) { + return NOCAP; + } else if ((ncap == 1) && firstcap) { + return INITCAP; + } else if ((ncap == nl) || ((ncap + nneutral) == nl)) { + return ALLCAP; + } else if ((ncap > 1) && firstcap) { + return HUHINITCAP; + } + return HUHCAP; +} + + +// strip all ignored characters in the string +void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len) +{ + w_char w[MAXWORDLEN]; + w_char w2[MAXWORDLEN]; + int i; + int j; + int len = u8_u16(w, MAXWORDLEN, word); + for (i = 0, j = 0; i < len; i++) { + if (!flag_bsearch(ignored_chars, ((unsigned short *) w)[i], ignored_len)) { + w2[j] = w[i]; + j++; + } + } + if (j < i) u16_u8(word, MAXWORDUTF8LEN, w2, j); +} + +// strip all ignored characters in the string +void remove_ignored_chars(char * word, char * ignored_chars) +{ + for (char * p = word; *p != '\0'; p++) { + if (!strchr(ignored_chars, *p)) { + *word = *p; + word++; + } + } + *word = '\0'; +} + +int parse_string(char * line, char ** out, const char * warnvar) +{ + char * tp = line; + char * piece; + int i = 0; + int np = 0; + if (*out) { + HUNSPELL_WARNING(stderr, "error: duplicate %s line\n", warnvar); + return 1; + } + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + *out = mystrdup(piece); + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + HUNSPELL_WARNING(stderr, "error: missing %s information\n", warnvar); + return 1; + } + return 0; +} + +int parse_array(char * line, char ** out, + unsigned short ** out_utf16, int * out_utf16_len, const char * name, int utf8) { + if (parse_string(line, out, name)) return 1; + if (utf8) { + w_char w[MAXWORDLEN]; + int n = u8_u16(w, MAXWORDLEN, *out); + if (n > 0) { + flag_qsort((unsigned short *) w, 0, n); + *out_utf16 = (unsigned short *) malloc(n * sizeof(unsigned short)); + if (!*out_utf16) return 1; + memcpy(*out_utf16, w, n * sizeof(unsigned short)); + } + *out_utf16_len = n; + } + return 0; +} diff --git a/hunspell/src/hunspell/csutil.hxx b/hunspell/src/hunspell/csutil.hxx new file mode 100644 index 000000000..df7979b68 --- /dev/null +++ b/hunspell/src/hunspell/csutil.hxx @@ -0,0 +1,203 @@ +#ifndef __CSUTILHXX__ +#define __CSUTILHXX__ + +// First some base level utility routines + +#define NOCAP 0 +#define INITCAP 1 +#define ALLCAP 2 +#define HUHCAP 3 +#define HUHINITCAP 4 + +#define MORPH_STEM "st:" +#define MORPH_ALLOMORPH "al:" +#define MORPH_POS "po:" +#define MORPH_DERI_PFX "dp:" +#define MORPH_INFL_PFX "ip:" +#define MORPH_TERM_PFX "tp:" +#define MORPH_DERI_SFX "ds:" +#define MORPH_INFL_SFX "is:" +#define MORPH_TERM_SFX "ts:" +#define MORPH_SURF_PFX "sp:" +#define MORPH_FREQ "fr:" +#define MORPH_PHON "ph:" +#define MORPH_HYPH "hy:" +#define MORPH_PART "pa:" +#define MORPH_HENTRY "_H:" +#define MORPH_TAG_LEN strlen(MORPH_STEM) + +#define MSEP_FLD ' ' +#define MSEP_REC '\n' +#define MSEP_ALT '\v' + + +// default flags +#define DEFAULTFLAGS 65510 +#define FORBIDDENWORD 65510 +#define ONLYUPCASEFLAG 65511 + +typedef struct { + unsigned char l; + unsigned char h; +} w_char; + +#define w_char_eq(a,b) (((a).l == (b).l) && ((a).h == (b).h)) + +// convert UTF-16 characters to UTF-8 +char * u16_u8(char * dest, int size, const w_char * src, int srclen); + +// convert UTF-8 characters to UTF-16 +int u8_u16(w_char * dest, int size, const char * src); + +// sort 2-byte vector +void flag_qsort(unsigned short flags[], int begin, int end); + +// binary search in 2-byte vector +int flag_bsearch(unsigned short flags[], unsigned short flag, int right); + +// remove end of line char(s) +void mychomp(char * s); + +// duplicate string +char * mystrdup(const char * s); + +// duplicate reverse of string +char * myrevstrdup(const char * s); + +// parse into tokens with char delimiter +char * mystrsep(char ** sptr, const char delim); +// parse into tokens with char delimiter +char * mystrsep2(char ** sptr, const char delim); + +// parse into tokens with char delimiter +char * mystrrep(char *, const char *, const char *); + +// append s to ends of every lines in text +void strlinecat(char * lines, const char * s); + +// tokenize into lines with new line + int line_tok(const char * text, char *** lines, char breakchar); + +// tokenize into lines with new line and uniq in place + char * line_uniq(char * text, char breakchar); + char * line_uniq_app(char ** text, char breakchar); + +// change oldchar to newchar in place + char * tr(char * text, char oldc, char newc); + +// reverse word + int reverseword(char *); + +// reverse word + int reverseword_utf(char *); + +// remove duplicates + int uniqlist(char ** list, int n); + +// free character array list + void freelist(char *** list, int n); + +// character encoding information +struct cs_info { + unsigned char ccase; + unsigned char clower; + unsigned char cupper; +}; + +// two character arrays +struct replentry { + char * pattern; + char * pattern2; +}; + +// Unicode character encoding information +struct unicode_info { + unsigned short c; + unsigned short cupper; + unsigned short clower; +}; + +struct unicode_info2 { + char cletter; + unsigned short cupper; + unsigned short clower; +}; + +int initialize_utf_tbl(); +void free_utf_tbl(); +unsigned short unicodetoupper(unsigned short c, int langnum); +unsigned short unicodetolower(unsigned short c, int langnum); +int unicodeisalpha(unsigned short c); + +struct enc_entry { + const char * enc_name; + struct cs_info * cs_table; +}; + +// language to encoding default map + +struct lang_map { + const char * lang; + const char * def_enc; + int num; +}; + +struct cs_info * get_current_cs(const char * es); + +const char * get_default_enc(const char * lang); + +// get language identifiers of language codes +int get_lang_num(const char * lang); + +// get characters of the given 8bit encoding with lower- and uppercase forms +char * get_casechars(const char * enc); + +// convert null terminated string to all caps using encoding +void enmkallcap(char * d, const char * p, const char * encoding); + +// convert null terminated string to all little using encoding +void enmkallsmall(char * d, const char * p, const char * encoding); + +// convert null terminated string to have intial capital using encoding +void enmkinitcap(char * d, const char * p, const char * encoding); + +// convert null terminated string to all caps +void mkallcap(char * p, const struct cs_info * csconv); + +// convert null terminated string to all little +void mkallsmall(char * p, const struct cs_info * csconv); + +// convert null terminated string to have intial capital +void mkinitcap(char * p, const struct cs_info * csconv); + +// convert first nc characters of UTF-8 string to little +void mkallsmall_utf(w_char * u, int nc, int langnum); + +// convert first nc characters of UTF-8 string to capital +void mkallcap_utf(w_char * u, int nc, int langnum); + +// get type of capitalization +int get_captype(char * q, int nl, cs_info *); + +// get type of capitalization (UTF-8) +int get_captype_utf8(w_char * q, int nl, int langnum); + +// strip all ignored characters in the string +void remove_ignored_chars_utf(char * word, unsigned short ignored_chars[], int ignored_len); + +// strip all ignored characters in the string +void remove_ignored_chars(char * word, char * ignored_chars); + +int parse_string(char * line, char ** out, const char * name); + +int parse_array(char * line, char ** out, + unsigned short ** out_utf16, int * out_utf16_len, const char * name, int utf8); + +int fieldlen(const char * r); +char * copy_field(char * dest, const char * morph, const char * var); + +int morphcmp(const char * s, const char * t); + +int get_sfxcount(const char * morph); + +#endif diff --git a/hunspell/src/hunspell/dictmgr.cxx b/hunspell/src/hunspell/dictmgr.cxx new file mode 100644 index 000000000..55945822e --- /dev/null +++ b/hunspell/src/hunspell/dictmgr.cxx @@ -0,0 +1,177 @@ + +#include +#include +#include +#include + +#include "dictmgr.hxx" + +using namespace std; + +DictMgr::DictMgr(const char * dictpath, const char * etype) +{ + // load list of etype entries + numdict = 0; + pdentry = (dictentry *)malloc(MAXDICTIONARIES*sizeof(struct dictentry)); + if (pdentry) { + if (parse_file(dictpath, etype)) { + numdict = 0; + // no dictionary.lst found is okay + } + } else { + numdict = 0; + } +} + + +DictMgr::~DictMgr() +{ + dictentry * pdict = NULL; + if (pdentry) { + pdict = pdentry; + for (int i=0;ilang) { + free(pdict->lang); + pdict->lang = NULL; + } + if (pdict->region) { + free(pdict->region); + pdict->region=NULL; + } + if (pdict->filename) { + free(pdict->filename); + pdict->filename = NULL; + } + pdict++; + } + free(pdentry); + pdentry = NULL; + pdict = NULL; + } + numdict = 0; +} + + +// read in list of etype entries and build up structure to describe them +int DictMgr::parse_file(const char * dictpath, const char * etype) +{ + + int i; + char line[MAXDICTENTRYLEN+1]; + dictentry * pdict = pdentry; + + // open the dictionary list file + FILE * dictlst; + dictlst = fopen(dictpath,"r"); + if (!dictlst) { + return 1; + } + + // step one is to parse the dictionary list building up the + // descriptive structures + + // read in each line ignoring any that dont start with etype + while (fgets(line,MAXDICTENTRYLEN,dictlst)) { + mychomp(line); + + /* parse in a dictionary entry */ + if (strncmp(line,etype,4) == 0) { + if (numdict < MAXDICTIONARIES) { + char * tp = line; + char * piece; + i = 0; + while ((piece=mystrsep(&tp,' '))) { + if (*piece != '\0') { + switch(i) { + case 0: break; + case 1: pdict->lang = mystrdup(piece); break; + case 2: if (strcmp (piece, "ANY") == 0) + pdict->region = mystrdup(""); + else + pdict->region = mystrdup(piece); + break; + case 3: pdict->filename = mystrdup(piece); break; + default: break; + } + i++; + } + free(piece); + } + if (i == 4) { + numdict++; + pdict++; + } else { + fprintf(stderr,"dictionary list corruption in line \"%s\"\n",line); + fflush(stderr); + } + } + } + } + fclose(dictlst); + return 0; +} + +// return text encoding of dictionary +int DictMgr::get_list(dictentry ** ppentry) +{ + *ppentry = pdentry; + return numdict; +} + + + +// strip strings into token based on single char delimiter +// acts like strsep() but only uses a delim char and not +// a delim string + +char * DictMgr::mystrsep(char ** stringp, const char delim) +{ + char * rv = NULL; + char * mp = *stringp; + int n = strlen(mp); + if (n > 0) { + char * dp = (char *)memchr(mp,(int)((unsigned char)delim),n); + if (dp) { + *stringp = dp+1; + int nc = (int)((unsigned long)dp - (unsigned long)mp); + rv = (char *) malloc(nc+1); + if (rv) { + memcpy(rv,mp,nc); + *(rv+nc) = '\0'; + return rv; + } + } else { + rv = (char *) malloc(n+1); + if (rv) { + memcpy(rv, mp, n); + *(rv+n) = '\0'; + *stringp = mp + n; + return rv; + } + } + } + return NULL; +} + + +// replaces strdup with ansi version +char * DictMgr::mystrdup(const char * s) +{ + char * d = NULL; + if (s) { + int sl = strlen(s); + d = (char *) malloc(((sl+1) * sizeof(char))); + if (d) memcpy(d,s,((sl+1)*sizeof(char))); + } + return d; +} + + +// remove cross-platform text line end characters +void DictMgr:: mychomp(char * s) +{ + int k = strlen(s); + if ((k > 0) && ((*(s+k-1)=='\r') || (*(s+k-1)=='\n'))) *(s+k-1) = '\0'; + if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0'; +} + diff --git a/hunspell/src/hunspell/dictmgr.hxx b/hunspell/src/hunspell/dictmgr.hxx new file mode 100644 index 000000000..88eeb7d61 --- /dev/null +++ b/hunspell/src/hunspell/dictmgr.hxx @@ -0,0 +1,34 @@ +#ifndef _DICTMGR_HXX_ +#define _DICTMGR_HXX_ + +#define MAXDICTIONARIES 100 +#define MAXDICTENTRYLEN 1024 + +struct dictentry { + char * filename; + char * lang; + char * region; +}; + + +class DictMgr +{ + + int numdict; + dictentry * pdentry; + +public: + + DictMgr(const char * dictpath, const char * etype); + ~DictMgr(); + int get_list(dictentry** ppentry); + +private: + int parse_file(const char * dictpath, const char * etype); + char * mystrsep(char ** stringp, const char delim); + char * mystrdup(const char * s); + void mychomp(char * s); + +}; + +#endif diff --git a/hunspell/src/hunspell/hashmgr.cxx b/hunspell/src/hunspell/hashmgr.cxx new file mode 100644 index 000000000..08e061c25 --- /dev/null +++ b/hunspell/src/hunspell/hashmgr.cxx @@ -0,0 +1,897 @@ +#include "license.hunspell" +#include "license.myspell" + +#ifndef MOZILLA_CLIENT +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include "hashmgr.hxx" +#include "csutil.hxx" +#include "atypes.hxx" + +#ifdef MOZILLA_CLIENT +#ifdef __SUNPRO_CC // for SunONE Studio compiler +using namespace std; +#endif +#else +#ifndef W32 +using namespace std; +#endif +#endif + +// build a hash table from a munched word list + +HashMgr::HashMgr(const char * tpath, const char * apath) +{ + tablesize = 0; + tableptr = NULL; + flag_mode = FLAG_CHAR; + complexprefixes = 0; + utf8 = 0; + langnum = 0; + lang = NULL; + enc = NULL; + csconv = 0; + ignorechars = NULL; + ignorechars_utf16 = NULL; + ignorechars_utf16_len = 0; + numaliasf = 0; + aliasf = NULL; + numaliasm = 0; + aliasm = NULL; + forbiddenword = FORBIDDENWORD; // forbidden word signing flag + load_config(apath); + int ec = load_tables(tpath); + if (ec) { + /* error condition - what should we do here */ + HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n",ec); + if (tableptr) { + free(tableptr); + tableptr = NULL; + } + tablesize = 0; + } +} + + +HashMgr::~HashMgr() +{ + if (tableptr) { + // now pass through hash table freeing up everything + // go through column by column of the table + for (int i=0; i < tablesize; i++) { + struct hentry * pt = tableptr[i]; + struct hentry * nt = NULL; + while(pt) { + nt = pt->next; + if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr); + free(pt); + pt = nt; + } + } + free(tableptr); + } + tablesize = 0; + + if (aliasf) { + for (int j = 0; j < (numaliasf); j++) free(aliasf[j]); + free(aliasf); + aliasf = NULL; + if (aliasflen) { + free(aliasflen); + aliasflen = NULL; + } + } + if (aliasm) { + for (int j = 0; j < (numaliasm); j++) free(aliasm[j]); + free(aliasm); + aliasm = NULL; + } + +#ifndef OPENOFFICEORG +#ifndef MOZILLA_CLIENT + if (utf8) free_utf_tbl(); +#endif +#endif + + if (enc) free(enc); + if (lang) free(lang); + + if (ignorechars) free(ignorechars); + if (ignorechars_utf16) free(ignorechars_utf16); +} + +// lookup a root word in the hashtable + +struct hentry * HashMgr::lookup(const char *word) const +{ + struct hentry * dp; + if (tableptr) { + dp = tableptr[hash(word)]; + if (!dp) return NULL; + for ( ; dp != NULL; dp = dp->next) { + if (strcmp(word,&(dp->word)) == 0) return dp; + } + } + return NULL; +} + +// add a word to the hash table (private) +int HashMgr::add_word(const char * word, int wbl, int wcl, unsigned short * aff, + int al, const char * desc, bool onlyupcase) +{ + bool upcasehomonym = false; + int descl = desc ? (aliasm ? sizeof(char *) : strlen(desc) + 1) : 0; + // variable-length hash record with word and optional fields + struct hentry* hp = + (struct hentry *) malloc (sizeof(struct hentry) + wbl + descl); + if (!hp) return 1; + char * hpw = &(hp->word); + strcpy(hpw, word); + if (ignorechars != NULL) { + if (utf8) { + remove_ignored_chars_utf(hpw, ignorechars_utf16, ignorechars_utf16_len); + } else { + remove_ignored_chars(hpw, ignorechars); + } + } + if (complexprefixes) { + if (utf8) reverseword_utf(hpw); else reverseword(hpw); + } + + int i = hash(hpw); + + hp->blen = (unsigned char) wbl; + hp->clen = (unsigned char) wcl; + hp->alen = (short) al; + hp->astr = aff; + hp->next = NULL; + hp->next_homonym = NULL; + + // store the description string or its pointer + if (desc) { + hp->var = H_OPT; + if (aliasm) { + hp->var += H_OPT_ALIASM; + *((char **) (hpw + wbl + 1)) = get_aliasm(atoi(desc)); + } else { + strcpy(hpw + wbl + 1, desc); + if (complexprefixes) { + if (utf8) reverseword_utf(HENTRY_DATA(hp)); + else reverseword(HENTRY_DATA(hp)); + } + } + if (strstr(HENTRY_DATA(hp), MORPH_PHON)) hp->var += H_OPT_PHON; + } else hp->var = 0; + + struct hentry * dp = tableptr[i]; + if (!dp) { + tableptr[i] = hp; + return 0; + } + while (dp->next != NULL) { + if ((!dp->next_homonym) && (strcmp(&(hp->word), &(dp->word)) == 0)) { + // remove hidden onlyupcase homonym + if (!onlyupcase) { + if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) { + free(dp->astr); + dp->astr = hp->astr; + dp->alen = hp->alen; + free(hp); + return 0; + } else { + dp->next_homonym = hp; + } + } else { + upcasehomonym = true; + } + } + dp=dp->next; + } + if (strcmp(&(hp->word), &(dp->word)) == 0) { + // remove hidden onlyupcase homonym + if (!onlyupcase) { + if ((dp->astr) && TESTAFF(dp->astr, ONLYUPCASEFLAG, dp->alen)) { + free(dp->astr); + dp->astr = hp->astr; + dp->alen = hp->alen; + free(hp); + return 0; + } else { + dp->next_homonym = hp; + } + } else { + upcasehomonym = true; + } + } + if (!upcasehomonym) { + dp->next = hp; + } else { + // remove hidden onlyupcase homonym + if (hp->astr) free(hp->astr); + free(hp); + } + return 0; +} + +int HashMgr::add_hidden_capitalized_word(char * word, int wbl, int wcl, + unsigned short * flags, int al, char * dp, int captype) +{ + // add inner capitalized forms to handle the following allcap forms: + // Mixed caps: OpenOffice.org -> OPENOFFICE.ORG + // Allcaps with suffixes: CIA's -> CIA'S + if (((captype == HUHCAP) || (captype == HUHINITCAP) || + ((captype == ALLCAP) && (flags != NULL))) && + !((flags != NULL) && TESTAFF(flags, forbiddenword, al))) { + unsigned short * flags2 = (unsigned short *) malloc (sizeof(unsigned short) * (al+1)); + if (!flags2) return 1; + if (al) memcpy(flags2, flags, al * sizeof(unsigned short)); + flags2[al] = ONLYUPCASEFLAG; + if (utf8) { + char st[MAXDELEN]; + w_char w[MAXDELEN]; + int wlen = u8_u16(w, MAXDELEN, word); + mkallsmall_utf(w, wlen, langnum); + mkallcap_utf(w, 1, langnum); + u16_u8(st, MAXDELEN, w, wlen); + return add_word(st,wbl,wcl,flags2,al+1,dp, true); + } else { + mkallsmall(word, csconv); + mkinitcap(word, csconv); + return add_word(word,wbl,wcl,flags2,al+1,dp, true); + } + } + return 0; +} + +// detect captype and modify word length for UTF-8 encoding +int HashMgr::get_clen_and_captype(const char * word, int wbl, int * captype) { + int len; + if (utf8) { + w_char dest_utf[MAXDELEN]; + len = u8_u16(dest_utf, MAXDELEN, word); + *captype = get_captype_utf8(dest_utf, len, langnum); + } else { + len = wbl; + *captype = get_captype((char *) word, len, csconv); + } + return len; +} + +// remove word with FORBIDDENWORD flag (not implemented) +int HashMgr::remove(const char * word) +{ + struct hentry * dp = lookup(word); +/* + if (!word || (!dp->astr || !TESTAFF(dp->astr, forbiddenword, pt->alen))) { + int wbl = strlen(word); + int wcl = get_clen_and_captype(word, wbl, &captype); + if (aliasf) { + add_word(word, wbl, wcl, dp->astr, dp->alen, NULL, false); + } else { + unsigned short * flags = (unsigned short *) malloc (dp->alen * sizeof(short)); + if (flags) { + memcpy((void *) flags, (void *) dp->astr, dp->alen * sizeof(short)); + add_word(word, wbl, wcl, flags, dp->alen, NULL, false); + } else return 1; + } + return add_hidden_capitalized_word((char *) word, wbl, wcl, dp->astr, dp->alen, NULL, captype); + } +*/ + return 1; +} + +// add a custom dic. word to the hash table (public) +int HashMgr::add(const char * word, char * aff) +{ + unsigned short * flags; + int al = 0; + if (aff) { + al = decode_flags(&flags, aff); + flag_qsort(flags, 0, al); + } else { + flags = NULL; + } + + int captype; + int wbl = strlen(word); + int wcl = get_clen_and_captype(word, wbl, &captype); + add_word(word, wbl, wcl, flags, al, NULL, false); + return add_hidden_capitalized_word((char *) word, wbl, wcl, flags, al, NULL, captype); +} + +int HashMgr::add_with_affix(const char * word, const char * example) +{ + // detect captype and modify word length for UTF-8 encoding + struct hentry * dp = lookup(example); + if (dp && dp->astr) { + int captype; + int wbl = strlen(word); + int wcl = get_clen_and_captype(word, wbl, &captype); + if (aliasf) { + add_word(word, wbl, wcl, dp->astr, dp->alen, NULL, false); + } else { + unsigned short * flags = (unsigned short *) malloc (dp->alen * sizeof(short)); + if (flags) { + memcpy((void *) flags, (void *) dp->astr, dp->alen * sizeof(short)); + add_word(word, wbl, wcl, flags, dp->alen, NULL, false); + } else return 1; + } + return add_hidden_capitalized_word((char *) word, wbl, wcl, dp->astr, dp->alen, NULL, captype); + } + return 1; +} + +// walk the hash table entry by entry - null at end +// initialize: col=-1; hp = NULL; hp = walk_hashtable(&col, hp); +struct hentry * HashMgr::walk_hashtable(int &col, struct hentry * hp) const +{ + if (hp && hp->next != NULL) return hp->next; + for (col++; col < tablesize; col++) { + if (tableptr[col]) return tableptr[col]; + } + // null at end and reset to start + col = -1; + return NULL; +} + +// load a munched word list and build a hash table on the fly +int HashMgr::load_tables(const char * tpath) +{ + int al; + char * ap; + char * dp; + unsigned short * flags; + + // raw dictionary - munched file + FILE * rawdict = fopen(tpath, "r"); + if (rawdict == NULL) return 1; + + // first read the first line of file to get hash table size */ + char ts[MAXDELEN]; + if (! fgets(ts, MAXDELEN-1,rawdict)) { + HUNSPELL_WARNING(stderr, "error: empty dic file\n"); + fclose(rawdict); + return 2; + } + mychomp(ts); + + /* remove byte order mark */ + if (strncmp(ts,"\xEF\xBB\xBF",3) == 0) { + memmove(ts, ts+3, strlen(ts+3)+1); + HUNSPELL_WARNING(stderr, "warning: dic file begins with byte order mark: possible incompatibility with old Hunspell versions\n"); + } + + if ((*ts < '1') || (*ts > '9')) HUNSPELL_WARNING(stderr, "error - missing word count in dictionary file\n"); + tablesize = atoi(ts); + if (!tablesize) { + fclose(rawdict); + return 4; + } + tablesize = tablesize + 5 + USERWORD; + if ((tablesize %2) == 0) tablesize++; + + // allocate the hash table + tableptr = (struct hentry **) malloc(tablesize * sizeof(struct hentry *)); + if (! tableptr) { + fclose(rawdict); + return 3; + } + for (int i=0; i 1x 2y Zz) + len = strlen(flags); + if (len%2 == 1) HUNSPELL_WARNING(stderr, "error: length of FLAG_LONG flagvector is odd: %s\n", flags); + len /= 2; + *result = (unsigned short *) malloc(len * sizeof(short)); + if (!*result) return -1; + for (int i = 0; i < len; i++) { + (*result)[i] = (((unsigned short) flags[i * 2]) << 8) + (unsigned short) flags[i * 2 + 1]; + } + break; + } + case FLAG_NUM: { // decimal numbers separated by comma (4521,23,233 -> 4521 23 233) + len = 1; + char * src = flags; + unsigned short * dest; + char * p; + for (p = flags; *p; p++) { + if (*p == ',') len++; + } + *result = (unsigned short *) malloc(len * sizeof(short)); + if (!*result) return -1; + dest = *result; + for (p = flags; *p; p++) { + if (*p == ',') { + *dest = (unsigned short) atoi(src); + if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n"); + src = p + 1; + dest++; + } + } + *dest = (unsigned short) atoi(src); + if (*dest == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n"); + break; + } + case FLAG_UNI: { // UTF-8 characters + w_char w[MAXDELEN/2]; + len = u8_u16(w, MAXDELEN/2, flags); + *result = (unsigned short *) malloc(len * sizeof(short)); + if (!*result) return -1; + memcpy(*result, w, len * sizeof(short)); + break; + } + default: { // Ispell's one-character flags (erfg -> e r f g) + unsigned short * dest; + len = strlen(flags); + *result = (unsigned short *) malloc(len * sizeof(short)); + if (!*result) return -1; + dest = *result; + for (unsigned char * p = (unsigned char *) flags; *p; p++) { + *dest = (unsigned short) *p; + dest++; + } + } + } + return len; +} + +unsigned short HashMgr::decode_flag(const char * f) { + unsigned short s = 0; + switch (flag_mode) { + case FLAG_LONG: + s = ((unsigned short) f[0] << 8) + (unsigned short) f[1]; + break; + case FLAG_NUM: + s = (unsigned short) atoi(f); + break; + case FLAG_UNI: + u8_u16((w_char *) &s, 1, f); + break; + default: + s = (unsigned short) *((unsigned char *)f); + } + if (!s) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n"); + return s; +} + +char * HashMgr::encode_flag(unsigned short f) { + unsigned char ch[10]; + if (f==0) return mystrdup("(NULL)"); + if (flag_mode == FLAG_LONG) { + ch[0] = (unsigned char) (f >> 8); + ch[1] = (unsigned char) (f - ((f >> 8) << 8)); + ch[2] = '\0'; + } else if (flag_mode == FLAG_NUM) { + sprintf((char *) ch, "%d", f); + } else if (flag_mode == FLAG_UNI) { + u16_u8((char *) &ch, 10, (w_char *) &f, 1); + } else { + ch[0] = (unsigned char) (f); + ch[1] = '\0'; + } + return mystrdup((char *) ch); +} + +// read in aff file and set flag mode +int HashMgr::load_config(const char * affpath) +{ + int firstline = 1; + + // io buffers + char line[MAXDELEN+1]; + + // open the affix file + FILE * afflst; + afflst = fopen(affpath,"r"); + if (!afflst) { + HUNSPELL_WARNING(stderr, "Error - could not open affix description file %s\n",affpath); + return 1; + } + + // read in each line ignoring any that do not + // start with a known line type indicator + + while (fgets(line,MAXDELEN,afflst)) { + mychomp(line); + + /* remove byte order mark */ + if (firstline) { + firstline = 0; + if (strncmp(line,"\xEF\xBB\xBF",3) == 0) memmove(line, line+3, strlen(line+3)+1); + } + + /* parse in the try string */ + if ((strncmp(line,"FLAG",4) == 0) && isspace(line[4])) { + if (flag_mode != FLAG_CHAR) { + HUNSPELL_WARNING(stderr, "error: duplicate FLAG parameter\n"); + } + if (strstr(line, "long")) flag_mode = FLAG_LONG; + if (strstr(line, "num")) flag_mode = FLAG_NUM; + if (strstr(line, "UTF-8")) flag_mode = FLAG_UNI; + if (flag_mode == FLAG_CHAR) { + HUNSPELL_WARNING(stderr, "error: FLAG need `num', `long' or `UTF-8' parameter: %s\n", line); + } + } + if (strncmp(line,"FORBIDDENWORD",13) == 0) { + char * st = NULL; + if (parse_string(line, &st, "FORBIDDENWORD")) { + fclose(afflst); + return 1; + } + forbiddenword = decode_flag(st); + free(st); + } + if (strncmp(line, "SET", 3) == 0) { + if (parse_string(line, &enc, "SET")) { + fclose(afflst); + return 1; + } + if (strcmp(enc, "UTF-8") == 0) { + utf8 = 1; +#ifndef OPENOFFICEORG +#ifndef MOZILLA_CLIENT + initialize_utf_tbl(); +#endif +#endif + } else csconv = get_current_cs(enc); + } + if (strncmp(line, "LANG", 4) == 0) { + if (parse_string(line, &lang, "LANG")) { + fclose(afflst); + return 1; + } + langnum = get_lang_num(lang); + } + + /* parse in the ignored characters (for example, Arabic optional diacritics characters */ + if (strncmp(line,"IGNORE",6) == 0) { + if (parse_array(line, &ignorechars, &ignorechars_utf16, &ignorechars_utf16_len, "IGNORE", utf8)) { + fclose(afflst); + return 1; + } + } + + if ((strncmp(line,"AF",2) == 0) && isspace(line[2])) { + if (parse_aliasf(line, afflst)) { + fclose(afflst); + return 1; + } + } + + if ((strncmp(line,"AM",2) == 0) && isspace(line[2])) { + if (parse_aliasm(line, afflst)) { + fclose(afflst); + return 1; + } + } + + if (strncmp(line,"COMPLEXPREFIXES",15) == 0) complexprefixes = 1; + if (((strncmp(line,"SFX",3) == 0) || (strncmp(line,"PFX",3) == 0)) && isspace(line[3])) break; + } + if (csconv == NULL) csconv = get_current_cs("ISO8859-1"); + fclose(afflst); + return 0; +} + +/* parse in the ALIAS table */ +int HashMgr::parse_aliasf(char * line, FILE * af) +{ + if (numaliasf != 0) { + HUNSPELL_WARNING(stderr, "error: duplicate AF (alias for flag vector) tables used\n"); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + numaliasf = atoi(piece); + if (numaliasf < 1) { + numaliasf = 0; + aliasf = NULL; + aliasflen = NULL; + HUNSPELL_WARNING(stderr, "incorrect number of entries in AF table\n"); + // free(piece); + return 1; + } + aliasf = (unsigned short **) malloc(numaliasf * sizeof(unsigned short *)); + aliasflen = (unsigned short *) malloc(numaliasf * sizeof(short)); + if (!aliasf || !aliasflen) { + numaliasf = 0; + if (aliasf) free(aliasf); + if (aliasflen) free(aliasflen); + aliasf = NULL; + aliasflen = NULL; + return 1; + } + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + numaliasf = 0; + free(aliasf); + free(aliasflen); + aliasf = NULL; + aliasflen = NULL; + HUNSPELL_WARNING(stderr, "error: missing AF table information\n"); + return 1; + } + + /* now parse the numaliasf lines to read in the remainder of the table */ + char * nl = line; + for (int j=0; j < numaliasf; j++) { + if (!fgets(nl,MAXDELEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + aliasf[j] = NULL; + aliasflen[j] = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece,"AF",2) != 0) { + numaliasf = 0; + free(aliasf); + free(aliasflen); + aliasf = NULL; + aliasflen = NULL; + HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n"); + // free(piece); + return 1; + } + break; + } + case 1: { + aliasflen[j] = (unsigned short) decode_flags(&(aliasf[j]), piece); + flag_qsort(aliasf[j], 0, aliasflen[j]); + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (!aliasf[j]) { + free(aliasf); + free(aliasflen); + aliasf = NULL; + aliasflen = NULL; + numaliasf = 0; + HUNSPELL_WARNING(stderr, "error: AF table is corrupt\n"); + return 1; + } + } + return 0; +} + +int HashMgr::is_aliasf() { + return (aliasf != NULL); +} + +int HashMgr::get_aliasf(int index, unsigned short ** fvec) { + if ((index > 0) && (index <= numaliasf)) { + *fvec = aliasf[index - 1]; + return aliasflen[index - 1]; + } + HUNSPELL_WARNING(stderr, "error: bad flag alias index: %d\n", index); + *fvec = NULL; + return 0; +} + +/* parse morph alias definitions */ +int HashMgr::parse_aliasm(char * line, FILE * af) +{ + if (numaliasm != 0) { + HUNSPELL_WARNING(stderr, "error: duplicate AM (aliases for morphological descriptions) tables used\n"); + return 1; + } + char * tp = line; + char * piece; + int i = 0; + int np = 0; + piece = mystrsep(&tp, 0); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { np++; break; } + case 1: { + numaliasm = atoi(piece); + if (numaliasm < 1) { + HUNSPELL_WARNING(stderr, "incorrect number of entries in AM table\n"); + // free(piece); + return 1; + } + aliasm = (char **) malloc(numaliasm * sizeof(char *)); + if (!aliasm) { + numaliasm = 0; + return 1; + } + np++; + break; + } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, 0); + } + if (np != 2) { + numaliasm = 0; + free(aliasm); + aliasm = NULL; + HUNSPELL_WARNING(stderr, "error: missing AM alias information\n"); + return 1; + } + + /* now parse the numaliasm lines to read in the remainder of the table */ + char * nl = line; + for (int j=0; j < numaliasm; j++) { + if (!fgets(nl,MAXDELEN,af)) return 1; + mychomp(nl); + tp = nl; + i = 0; + aliasm[j] = NULL; + piece = mystrsep(&tp, ' '); + while (piece) { + if (*piece != '\0') { + switch(i) { + case 0: { + if (strncmp(piece,"AM",2) != 0) { + HUNSPELL_WARNING(stderr, "error: AM table is corrupt\n"); + // free(piece); + numaliasm = 0; + free(aliasm); + aliasm = NULL; + return 1; + } + break; + } + case 1: { + // add the remaining of the line + if (*tp) { + *(tp - 1) = ' '; + tp = tp + strlen(tp); + } + if (complexprefixes) { + if (utf8) reverseword_utf(piece); + else reverseword(piece); + } + aliasm[j] = mystrdup(piece); + break; } + default: break; + } + i++; + } + // free(piece); + piece = mystrsep(&tp, ' '); + } + if (!aliasm[j]) { + numaliasm = 0; + free(aliasm); + aliasm = NULL; + HUNSPELL_WARNING(stderr, "error: map table is corrupt\n"); + return 1; + } + } + return 0; +} + +int HashMgr::is_aliasm() { + return (aliasm != NULL); +} + +char * HashMgr::get_aliasm(int index) { + if ((index > 0) && (index <= numaliasm)) return aliasm[index - 1]; + HUNSPELL_WARNING(stderr, "error: bad morph. alias index: %d\n", index); + return NULL; +} diff --git a/hunspell/src/hunspell/hashmgr.hxx b/hunspell/src/hunspell/hashmgr.hxx new file mode 100644 index 000000000..d88de48d4 --- /dev/null +++ b/hunspell/src/hunspell/hashmgr.hxx @@ -0,0 +1,69 @@ +#ifndef _HASHMGR_HXX_ +#define _HASHMGR_HXX_ + +#ifndef MOZILLA_CLIENT +#include +#else +#include +#endif + +#include "htypes.hxx" + +enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI }; + +class HashMgr +{ + int tablesize; + struct hentry ** tableptr; + int userword; + flag flag_mode; + int complexprefixes; + int utf8; + unsigned short forbiddenword; + int langnum; + char * enc; + char * lang; + struct cs_info * csconv; + char * ignorechars; + unsigned short * ignorechars_utf16; + int ignorechars_utf16_len; + int numaliasf; // flag vector `compression' with aliases + unsigned short ** aliasf; + unsigned short * aliasflen; + int numaliasm; // morphological desciption `compression' with aliases + char ** aliasm; + + +public: + HashMgr(const char * tpath, const char * apath); + ~HashMgr(); + + struct hentry * lookup(const char *) const; + int hash(const char *) const; + struct hentry * walk_hashtable(int & col, struct hentry * hp) const; + + int add(const char * word, char * aff); + int add_with_affix(const char * word, const char * pattern); + int remove(const char * word); + int decode_flags(unsigned short ** result, char * flags); + unsigned short decode_flag(const char * flag); + char * encode_flag(unsigned short flag); + int is_aliasf(); + int get_aliasf(int index, unsigned short ** fvec); + int is_aliasm(); + char * get_aliasm(int index); + +private: + int get_clen_and_captype(const char * word, int wbl, int * captype); + int load_tables(const char * tpath); + int add_word(const char * word, int wbl, int wcl, unsigned short * ap, + int al, const char * desc, bool onlyupcase); + int load_config(const char * affpath); + int parse_aliasf(char * line, FILE * af); + int add_hidden_capitalized_word(char * word, int wbl, int wcl, + unsigned short * flags, int al, char * dp, int captype); + int parse_aliasm(char * line, FILE * af); + +}; + +#endif diff --git a/hunspell/src/hunspell/htypes.hxx b/hunspell/src/hunspell/htypes.hxx new file mode 100644 index 000000000..bc078c345 --- /dev/null +++ b/hunspell/src/hunspell/htypes.hxx @@ -0,0 +1,36 @@ +#ifndef _HTYPES_HXX_ +#define _HTYPES_HXX_ + +#define MAXDELEN 8192 + +#define ROTATE_LEN 5 + +#define ROTATE(v,q) \ + (v) = ((v) << (q)) | (((v) >> (32 - q)) & ((1 << (q))-1)); + +// hentry options +#define H_OPT (1 << 0) +#define H_OPT_ALIASM (1 << 1) +#define H_OPT_PHON (1 << 2) + +#define HENTRY_WORD(h) &(h->word) +#define HENTRY_DATA(h) (h->var ? ((h->var & H_OPT_ALIASM) ? \ + *((char **) (&(h->word) + h->blen + 1)) : &(h->word) + h->blen + 1) : NULL) +#define HENTRY_FIND(h,p) (HENTRY_DATA(h) ? strstr(HENTRY_DATA(h), p) : NULL) + +// approx. number of user defined words +#define USERWORD 1000 + +struct hentry +{ + unsigned char blen; // word length in bytes + unsigned char clen; // word length in characters (different for UTF-8 enc.) + short alen; // length of affix flag vector + unsigned short * astr; // affix flag vector + struct hentry * next; // next word with same hash code + struct hentry * next_homonym; // next homonym word (with same hash code) + char var; // variable fields (only for special pronounciation yet) + char word; // variable-length word (8-bit or UTF-8 encoding) +}; + +#endif diff --git a/hunspell/src/hunspell/hunspell.cxx b/hunspell/src/hunspell/hunspell.cxx new file mode 100644 index 000000000..0578606d4 --- /dev/null +++ b/hunspell/src/hunspell/hunspell.cxx @@ -0,0 +1,1754 @@ +#include "license.hunspell" +#include "license.myspell" + +#ifndef MOZILLA_CLIENT +#include +#include +#include +#else +#include +#include +#include +#endif + +#include "hunspell.hxx" +#include "hunspell.h" +#include "config.h" + +#ifndef MOZILLA_CLIENT +#ifndef W32 +using namespace std; +#endif +#endif + +Hunspell::Hunspell(const char * affpath, const char * dpath) +{ + encoding = NULL; + csconv = NULL; + utf8 = 0; + complexprefixes = 0; + + /* first set up the hash manager */ + pHMgr = new HashMgr(dpath, affpath); + + /* next set up the affix manager */ + /* it needs access to the hash manager lookup methods */ + pAMgr = new AffixMgr(affpath,pHMgr); + + /* get the preferred try string and the dictionary */ + /* encoding from the Affix Manager for that dictionary */ + char * try_string = pAMgr->get_try_string(); + encoding = pAMgr->get_encoding(); + csconv = get_current_cs(encoding); + langnum = pAMgr->get_langnum(); + utf8 = pAMgr->get_utf8(); + complexprefixes = pAMgr->get_complexprefixes(); + wordbreak = pAMgr->get_breaktable(); + + /* and finally set up the suggestion manager */ + pSMgr = new SuggestMgr(try_string, MAXSUGGESTION, pAMgr); + if (try_string) free(try_string); + +} + +Hunspell::~Hunspell() +{ + if (pSMgr) delete pSMgr; + if (pAMgr) delete pAMgr; + if (pHMgr) delete pHMgr; + pSMgr = NULL; + pAMgr = NULL; + pHMgr = NULL; +#ifdef MOZILLA_CLIENT + free(csconv); +#endif + csconv= NULL; + if (encoding) free(encoding); + encoding = NULL; +} + + +// make a copy of src at destination while removing all leading +// blanks and removing any trailing periods after recording +// their presence with the abbreviation flag +// also since already going through character by character, +// set the capitalization type +// return the length of the "cleaned" (and UTF-8 encoded) word + +int Hunspell::cleanword2(char * dest, const char * src, + w_char * dest_utf, int * nc, int * pcaptype, int * pabbrev) +{ + unsigned char * p = (unsigned char *) dest; + const unsigned char * q = (const unsigned char * ) src; + + // first skip over any leading blanks + while ((*q != '\0') && (*q == ' ')) q++; + + // now strip off any trailing periods (recording their presence) + *pabbrev = 0; + int nl = strlen((const char *)q); + while ((nl > 0) && (*(q+nl-1)=='.')) { + nl--; + (*pabbrev)++; + } + + // if no characters are left it can't be capitalized + if (nl <= 0) { + *pcaptype = NOCAP; + *p = '\0'; + return 0; + } + + strncpy(dest, (char *) q, nl); + *(dest + nl) = '\0'; + nl = strlen(dest); + if (utf8) { + *nc = u8_u16(dest_utf, MAXWORDLEN, dest); + // don't check too long words + if (*nc >= MAXWORDLEN) return 0; + if (*nc == -1) { // big Unicode character (non BMP area) + *pcaptype = NOCAP; + return nl; + } + *pcaptype = get_captype_utf8(dest_utf, *nc, langnum); + } else { + *pcaptype = get_captype(dest, nl, csconv); + *nc = nl; + } + return nl; +} + +int Hunspell::cleanword(char * dest, const char * src, + int * pcaptype, int * pabbrev) +{ + unsigned char * p = (unsigned char *) dest; + const unsigned char * q = (const unsigned char * ) src; + int firstcap = 0; + + // first skip over any leading blanks + while ((*q != '\0') && (*q == ' ')) q++; + + // now strip off any trailing periods (recording their presence) + *pabbrev = 0; + int nl = strlen((const char *)q); + while ((nl > 0) && (*(q+nl-1)=='.')) { + nl--; + (*pabbrev)++; + } + + // if no characters are left it can't be capitalized + if (nl <= 0) { + *pcaptype = NOCAP; + *p = '\0'; + return 0; + } + + // now determine the capitalization type of the first nl letters + int ncap = 0; + int nneutral = 0; + int nc = 0; + + if (!utf8) { + while (nl > 0) { + nc++; + if (csconv[(*q)].ccase) ncap++; + if (csconv[(*q)].cupper == csconv[(*q)].clower) nneutral++; + *p++ = *q++; + nl--; + } + // remember to terminate the destination string + *p = '\0'; + firstcap = csconv[(unsigned char)(*dest)].ccase; + } else { + unsigned short idx; + w_char t[MAXWORDLEN]; + nc = u8_u16(t, MAXWORDLEN, src); + for (int i = 0; i < nc; i++) { + idx = (t[i].h << 8) + t[i].l; + unsigned short low = unicodetolower(idx, langnum); + if (idx != low) ncap++; + if (unicodetoupper(idx, langnum) == low) nneutral++; + } + u16_u8(dest, MAXWORDUTF8LEN, t, nc); + if (ncap) { + idx = (t[0].h << 8) + t[0].l; + firstcap = (idx != unicodetolower(idx, langnum)); + } + } + + // now finally set the captype + if (ncap == 0) { + *pcaptype = NOCAP; + } else if ((ncap == 1) && firstcap) { + *pcaptype = INITCAP; + } else if ((ncap == nc) || ((ncap + nneutral) == nc)){ + *pcaptype = ALLCAP; + } else if ((ncap > 1) && firstcap) { + *pcaptype = HUHINITCAP; + } else { + *pcaptype = HUHCAP; + } + return strlen(dest); +} + +void Hunspell::mkallcap(char * p) +{ + if (utf8) { + w_char u[MAXWORDLEN]; + int nc = u8_u16(u, MAXWORDLEN, p); + unsigned short idx; + for (int i = 0; i < nc; i++) { + idx = (u[i].h << 8) + u[i].l; + if (idx != unicodetoupper(idx, langnum)) { + u[i].h = (unsigned char) (unicodetoupper(idx, langnum) >> 8); + u[i].l = (unsigned char) (unicodetoupper(idx, langnum) & 0x00FF); + } + } + u16_u8(p, MAXWORDUTF8LEN, u, nc); + } else { + while (*p != '\0') { + *p = csconv[((unsigned char) *p)].cupper; + p++; + } + } +} + +int Hunspell::mkallcap2(char * p, w_char * u, int nc) +{ + if (utf8) { + unsigned short idx; + for (int i = 0; i < nc; i++) { + idx = (u[i].h << 8) + u[i].l; + unsigned short up = unicodetoupper(idx, langnum); + if (idx != up) { + u[i].h = (unsigned char) (up >> 8); + u[i].l = (unsigned char) (up & 0x00FF); + } + } + u16_u8(p, MAXWORDUTF8LEN, u, nc); + return strlen(p); + } else { + while (*p != '\0') { + *p = csconv[((unsigned char) *p)].cupper; + p++; + } + } + return nc; +} + + +void Hunspell::mkallsmall(char * p) +{ + while (*p != '\0') { + *p = csconv[((unsigned char) *p)].clower; + p++; + } +} + +int Hunspell::mkallsmall2(char * p, w_char * u, int nc) +{ + if (utf8) { + unsigned short idx; + for (int i = 0; i < nc; i++) { + idx = (u[i].h << 8) + u[i].l; + unsigned short low = unicodetolower(idx, langnum); + if (idx != low) { + u[i].h = (unsigned char) (low >> 8); + u[i].l = (unsigned char) (low & 0x00FF); + } + } + u16_u8(p, MAXWORDUTF8LEN, u, nc); + return strlen(p); + } else { + while (*p != '\0') { + *p = csconv[((unsigned char) *p)].clower; + p++; + } + } + return nc; +} + +// convert UTF-8 sharp S codes to latin 1 +char * Hunspell::sharps_u8_l1(char * dest, char * source) { + char * p = dest; + *p = *source; + for (p++, source++; *(source - 1); p++, source++) { + *p = *source; + if (*source == '\x9F') *--p = '\xDF'; + } + return dest; +} + +// recursive search for right ss - sharp s permutations +hentry * Hunspell::spellsharps(char * base, char * pos, int n, + int repnum, char * tmp, int * info, char **root) { + pos = strstr(pos, "ss"); + if (pos && (n < MAXSHARPS)) { + *pos = '\xC3'; + *(pos + 1) = '\x9F'; + hentry * h = spellsharps(base, pos + 2, n + 1, repnum + 1, tmp, info, root); + if (h) return h; + *pos = 's'; + *(pos + 1) = 's'; + h = spellsharps(base, pos + 2, n + 1, repnum, tmp, info, root); + if (h) return h; + } else if (repnum > 0) { + if (utf8) return checkword(base, info, root); + return checkword(sharps_u8_l1(tmp, base), info, root); + } + return NULL; +} + +int Hunspell::is_keepcase(const hentry * rv) { + return pAMgr && rv->astr && pAMgr->get_keepcase() && + TESTAFF(rv->astr, pAMgr->get_keepcase(), rv->alen); +} + +/* insert a word to beginning of the suggestion array and return ns */ +int Hunspell::insert_sug(char ***slst, char * word, int ns) { + if (ns == MAXSUGGESTION) { + ns--; + free((*slst)[ns]); + } + for (int k = ns; k > 0; k--) (*slst)[k] = (*slst)[k - 1]; + (*slst)[0] = mystrdup(word); + return ns + 1; +} + +int Hunspell::spell(const char * word, int * info, char ** root) +{ + struct hentry * rv=NULL; + // need larger vector. For example, Turkish capital letter I converted a + // 2-byte UTF-8 character (dotless i) by mkallsmall. + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + w_char unicw[MAXWORDLEN]; + int nc = strlen(word); + int wl2 = 0; + if (utf8) { + if (nc >= MAXWORDUTF8LEN) return 0; + } else { + if (nc >= MAXWORDLEN) return 0; + } + int captype = 0; + int abbv = 0; + int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv); + int info2 = 0; + if (wl == 0) return 1; + if (root) *root = NULL; + + // allow numbers with dots and commas (but forbid double separators: "..", ",," etc.) + enum { NBEGIN, NNUM, NSEP }; + int nstate = NBEGIN; + int i; + + for (i = 0; (i < wl); i++) { + if ((cw[i] <= '9') && (cw[i] >= '0')) { + nstate = NNUM; + } else if ((cw[i] == ',') || (cw[i] == '.') || (cw[i] == '-')) { + if ((nstate == NSEP) || (i == 0)) break; + nstate = NSEP; + } else break; + } + if ((i == wl) && (nstate == NNUM)) return 1; + if (!info) info = &info2; else *info = 0; + + // LANG_hu section: number(s) + (percent or degree) with suffixes + if (langnum == LANG_hu) { + if ((nstate == NNUM) && ((cw[i] == '%') || ((!utf8 && (cw[i] == '\xB0')) || + (utf8 && (strncmp(cw + i, "\xC2\xB0", 2)==0)))) + && checkword(cw + i, info, root)) return 1; + } + // END of LANG_hu section + + switch(captype) { + case HUHCAP: + case HUHINITCAP: + case NOCAP: { + rv = checkword(cw, info, root); + if ((abbv) && !(rv)) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + rv = checkword(wspace, info, root); + } + break; + } + case ALLCAP: { + rv = checkword(cw, info, root); + if (rv) break; + if (abbv) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + rv = checkword(wspace, info, root); + if (rv) break; + } + // Spec. prefix handling for Catalan, French, Italian: + // prefixes separated by apostrophe (SANT'ELIA -> Sant'+Elia). + if (pAMgr && strchr(cw, '\'')) { + wl = mkallsmall2(cw, unicw, nc); + char * apostrophe = strchr(cw, '\''); + if (utf8) { + w_char tmpword[MAXWORDLEN]; + *apostrophe = '\0'; + wl2 = u8_u16(tmpword, MAXWORDLEN, cw); + *apostrophe = '\''; + if (wl2 < nc) { + mkinitcap2(apostrophe + 1, unicw + wl2 + 1, nc - wl2 - 1); + rv = checkword(cw, info, root); + if (rv) break; + } + } else { + mkinitcap2(apostrophe + 1, unicw, nc); + rv = checkword(cw, info, root); + if (rv) break; + } + mkinitcap2(cw, unicw, nc); + rv = checkword(cw, info, root); + if (rv) break; + } + if (pAMgr && pAMgr->get_checksharps() && strstr(cw, "SS")) { + char tmpword[MAXWORDUTF8LEN]; + wl = mkallsmall2(cw, unicw, nc); + memcpy(wspace,cw,(wl+1)); + rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); + if (!rv) { + wl2 = mkinitcap2(cw, unicw, nc); + rv = spellsharps(cw, cw, 0, 0, tmpword, info, root); + } + if ((abbv) && !(rv)) { + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); + if (!rv) { + memcpy(wspace, cw, wl2); + *(wspace+wl2) = '.'; + *(wspace+wl2+1) = '\0'; + rv = spellsharps(wspace, wspace, 0, 0, tmpword, info, root); + } + } + if (rv) break; + } + } + case INITCAP: { + wl = mkallsmall2(cw, unicw, nc); + memcpy(wspace,cw,(wl+1)); + wl2 = mkinitcap2(cw, unicw, nc); + if (captype == INITCAP) *info += SPELL_INITCAP; + rv = checkword(cw, info, root); + if (captype == INITCAP) *info -= SPELL_INITCAP; + // forbid bad capitalization + // (for example, ijs -> Ijs instead of IJs in Dutch) + // use explicit forms in dic: Ijs/F (F = FORBIDDENWORD flag) + if (*info & SPELL_FORBIDDEN) { + rv = NULL; + break; + } + if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL; + if (rv) break; + + rv = checkword(wspace, info, root); + if (abbv && !rv) { + + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + rv = checkword(wspace, info, root); + if (!rv) { + memcpy(wspace, cw, wl2); + *(wspace+wl2) = '.'; + *(wspace+wl2+1) = '\0'; + if (captype == INITCAP) *info += SPELL_INITCAP; + rv = checkword(wspace, info, root); + if (captype == INITCAP) *info -= SPELL_INITCAP; + if (rv && is_keepcase(rv) && (captype == ALLCAP)) rv = NULL; + break; + } + } + if (rv && is_keepcase(rv) && + ((captype == ALLCAP) || + // if CHECKSHARPS: KEEPCASE words with \xDF are allowed + // in INITCAP form, too. + !(pAMgr->get_checksharps() && + ((utf8 && strstr(wspace, "\xC3\x9F")) || + (!utf8 && strchr(wspace, '\xDF')))))) rv = NULL; + break; + } + } + + if (rv) return 1; + + // recursive breaking at break points (not good for morphological analysis) + if (wordbreak) { + char * s; + char r; + int corr = 0; + // German words beginning with "-" are not accepted + if (langnum == LANG_de) corr = 1; + int numbreak = pAMgr ? pAMgr->get_numbreak() : 0; + for (int j = 0; j < numbreak; j++) { + s=(char *) strstr(cw + corr, wordbreak[j]); + if (s) { + r = *s; + *s = '\0'; + // examine 2 sides of the break point + if (spell(cw) && spell(s + strlen(wordbreak[j]))) { + *s = r; + return 1; + } + *s = r; + } + } + } + + // LANG_hu: compoundings with dashes and n-dashes XXX deprecated! + if (langnum == LANG_hu) { + int n; + // compound word with dash (HU) I18n + char * dash; + int result = 0; + // n-dash + dash = (char *) strstr(cw,"\xE2\x80\x93"); + if (dash && !wordbreak) { + *dash = '\0'; + // examine 2 sides of the dash + if (spell(cw) && spell(dash + 3)) { + *dash = '\xE2'; + return 1; + } + *dash = '\xE2'; + } + dash = (char *) strchr(cw,'-'); + if (dash) { + *dash='\0'; + // examine 2 sides of the dash + if (dash[1] == '\0') { // base word ending with dash + if (spell(cw)) return 1; + } else { + // first word ending with dash: word- + char r2 = *(dash + 1); + dash[0]='-'; + dash[1]='\0'; + result = spell(cw); + dash[1] = r2; + dash[0]='\0'; + if (result && spell(dash+1) && ((strlen(dash+1) > 1) || (dash[1] == 'e') || + ((dash[1] > '0') && (dash[1] < '9')))) return 1; + } + // affixed number in correct word + if (result && (dash > cw) && (((*(dash-1)<='9') && (*(dash-1)>='0')) || (*(dash-1)>='.'))) { + *dash='-'; + n = 1; + if (*(dash - n) == '.') n++; + // search first not a number character to left from dash + while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) { + n++; + } + if ((dash - n) < cw) n--; + // numbers: deprecated + for(; n >= 1; n--) { + if ((*(dash - n) >= '0') && (*(dash - n) <= '9') && + checkword(dash - n, info, root)) return 1; + } + } + } + } + return 0; +} + +struct hentry * Hunspell::checkword(const char * w, int * info, char ** root) +{ + struct hentry * he = NULL; + int len; + char w2[MAXWORDUTF8LEN]; + const char * word; + + char * ignoredchars = pAMgr->get_ignore(); + if (ignoredchars != NULL) { + strcpy(w2, w); + if (utf8) { + int ignoredchars_utf16_len; + unsigned short * ignoredchars_utf16 = pAMgr->get_ignore_utf16(&ignoredchars_utf16_len); + remove_ignored_chars_utf(w2, ignoredchars_utf16, ignoredchars_utf16_len); + } else { + remove_ignored_chars(w2,ignoredchars); + } + word = w2; + } else word = w; + + // word reversing wrapper for complex prefixes + if (complexprefixes) { + if (word != w2) { + strcpy(w2, word); + word = w2; + } + if (utf8) reverseword_utf(w2); else reverseword(w2); + } + + // look word in hash table + if (pHMgr) he = pHMgr->lookup(word); + + // check forbidden and onlyincompound words + if ((he) && (he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) { + if (info) *info += SPELL_FORBIDDEN; + // LANG_hu section: set dash information for suggestions + if (langnum == LANG_hu) { + if (pAMgr->get_compoundflag() && + TESTAFF(he->astr, pAMgr->get_compoundflag(), he->alen)) { + if (info) *info += SPELL_COMPOUND; + } + } + return NULL; + } + + // he = next not needaffix, onlyincompound homonym or onlyupcase word + while (he && (he->astr) && + ((pAMgr->get_needaffix() && TESTAFF(he->astr, pAMgr->get_needaffix(), he->alen)) || + (pAMgr->get_onlyincompound() && TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) || + (info && (*info & SPELL_INITCAP) && TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)) + )) he = he->next_homonym; + + // check with affixes + if (!he && pAMgr) { + // try stripping off affixes */ + len = strlen(word); + he = pAMgr->affix_check(word, len, 0); + + // check compound restriction and onlyupcase + if (he && he->astr && ( + (pAMgr->get_onlyincompound() && + TESTAFF(he->astr, pAMgr->get_onlyincompound(), he->alen)) || + (info && (*info & SPELL_INITCAP) && + TESTAFF(he->astr, ONLYUPCASEFLAG, he->alen)))) { + he = NULL; + } + + if (he) { + if ((he->astr) && (pAMgr) && TESTAFF(he->astr, pAMgr->get_forbiddenword(), he->alen)) { + if (info) *info += SPELL_FORBIDDEN; + return NULL; + } + if (root) { + *root = mystrdup(&(he->word)); + if (complexprefixes) { + if (utf8) reverseword_utf(*root); else reverseword(*root); + } + } + // try check compound word + } else if (pAMgr->get_compound()) { + he = pAMgr->compound_check(word, len, + 0,0,100,0,NULL,0,NULL,NULL,0); + // LANG_hu section: `moving rule' with last dash + if ((!he) && (langnum == LANG_hu) && (word[len-1]=='-')) { + char * dup = mystrdup(word); + dup[len-1] = '\0'; + he = pAMgr->compound_check(dup, len-1, + -5,0,100,0,NULL,1,NULL,NULL,0); + free(dup); + } + // end of LANG speficic region + if (he) { + if (root) { + *root = mystrdup(&(he->word)); + if (complexprefixes) { + if (utf8) reverseword_utf(*root); else reverseword(*root); + } + } + if (info) *info += SPELL_COMPOUND; + } + } + + } + + return he; +} + +int Hunspell::suggest(char*** slst, const char * word) +{ + int onlycmpdsug = 0; + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (! pSMgr) return 0; + w_char unicw[MAXWORDLEN]; + int nc = strlen(word); + if (utf8) { + if (nc >= MAXWORDUTF8LEN) return 0; + } else { + if (nc >= MAXWORDLEN) return 0; + } + int captype = 0; + int abbv = 0; + int wl = cleanword2(cw, word, unicw, &nc, &captype, &abbv); + if (wl == 0) return 0; + int ns = 0; + *slst = NULL; + int capwords = 0; + + switch(captype) { + case NOCAP: { + ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug); + break; + } + + case INITCAP: { + capwords = 1; + ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug); + if (ns == -1) break; + memcpy(wspace,cw,(wl+1)); + mkallsmall2(wspace, unicw, nc); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); + break; + } + case HUHINITCAP: + capwords = 1; + case HUHCAP: { + ns = pSMgr->suggest(slst, cw, ns, &onlycmpdsug); + if (ns != -1) { + int prevns; + // something.The -> something. The + char * dot = strchr(cw, '.'); + if (dot && (dot > cw)) { + int captype_; + if (utf8) { + w_char w_[MAXWORDLEN]; + int wl_ = u8_u16(w_, MAXWORDLEN, dot + 1); + captype_ = get_captype_utf8(w_, wl_, langnum); + } else captype_ = get_captype(dot+1, strlen(dot+1), csconv); + if (captype_ == INITCAP) { + char * st = mystrdup(cw); + st = (char *) realloc(st, wl + 2); + if (st) { + st[(dot - cw) + 1] = ' '; + strcpy(st + (dot - cw) + 2, dot + 1); + ns = insert_sug(slst, st, ns); + free(st); + } + } + } + if (captype == HUHINITCAP) { + // TheOpenOffice.org -> The OpenOffice.org + memcpy(wspace,cw,(wl+1)); + mkinitsmall2(wspace, unicw, nc); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); + } + memcpy(wspace,cw,(wl+1)); + mkallsmall2(wspace, unicw, nc); + if (spell(wspace)) ns = insert_sug(slst, wspace, ns); + prevns = ns; + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); + if (captype == HUHINITCAP) { + mkinitcap2(wspace, unicw, nc); + if (spell(wspace)) ns = insert_sug(slst, wspace, ns); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); + } + // aNew -> "a New" (instead of "a new") + for (int j = prevns; j < ns; j++) { + char * space = strchr((*slst)[j],' '); + if (space) { + int slen = strlen(space + 1); + // different case after space (need capitalisation) + if ((slen < wl) && strcmp(cw + wl - slen, space + 1)) { + w_char w[MAXWORDLEN]; + int wc = 0; + char * r = (*slst)[j]; + if (utf8) wc = u8_u16(w, MAXWORDLEN, space + 1); + mkinitcap2(space + 1, w, wc); + // set as first suggestion + for (int k = j; k > 0; k--) (*slst)[k] = (*slst)[k - 1]; + (*slst)[0] = r; + } + } + } + } + break; + } + + case ALLCAP: { + memcpy(wspace, cw, (wl+1)); + mkallsmall2(wspace, unicw, nc); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); + if (ns == -1) break; + if (pAMgr && pAMgr->get_keepcase() && spell(wspace)) + ns = insert_sug(slst, wspace, ns); + mkinitcap2(wspace, unicw, nc); + ns = pSMgr->suggest(slst, wspace, ns, &onlycmpdsug); + for (int j=0; j < ns; j++) { + mkallcap((*slst)[j]); + if (pAMgr && pAMgr->get_checksharps()) { + char * pos; + if (utf8) { + pos = strstr((*slst)[j], "\xC3\x9F"); + while (pos) { + *pos = 'S'; + *(pos+1) = 'S'; + pos = strstr(pos+2, "\xC3\x9F"); + } + } else { + pos = strchr((*slst)[j], '\xDF'); + while (pos) { + (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 2); + mystrrep((*slst)[j], "\xDF", "SS"); + pos = strchr((*slst)[j], '\xDF'); + } + } + } + } + break; + } + } + + // LANG_hu section: replace '-' with ' ' in Hungarian + if (langnum == LANG_hu) { + for (int j=0; j < ns; j++) { + char * pos = strchr((*slst)[j],'-'); + if (pos) { + int info; + char w[MAXWORDUTF8LEN]; + *pos = '\0'; + strcpy(w, (*slst)[j]); + strcat(w, pos + 1); + spell(w, &info, NULL); + if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) { + *pos = ' '; + } else *pos = '-'; + } + } + } + // END OF LANG_hu section + + // try ngram approach since found nothing + if ((ns == 0 || onlycmpdsug) && pAMgr && (pAMgr->get_maxngramsugs() != 0)) { + switch(captype) { + case NOCAP: { + ns = pSMgr->ngsuggest(*slst, cw, ns, pHMgr); + break; + } + case HUHCAP: { + memcpy(wspace,cw,(wl+1)); + mkallsmall2(wspace, unicw, nc); + ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr); + break; + } + case INITCAP: { + capwords = 1; + memcpy(wspace,cw,(wl+1)); + mkallsmall2(wspace, unicw, nc); + ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr); + break; + } + case ALLCAP: { + memcpy(wspace,cw,(wl+1)); + mkallsmall2(wspace, unicw, nc); + int oldns = ns; + ns = pSMgr->ngsuggest(*slst, wspace, ns, pHMgr); + for (int j = oldns; j < ns; j++) + mkallcap((*slst)[j]); + break; + } + } + } + + // word reversing wrapper for complex prefixes + if (complexprefixes) { + for (int j = 0; j < ns; j++) { + if (utf8) reverseword_utf((*slst)[j]); else reverseword((*slst)[j]); + } + } + + // capitalize + if (capwords) for (int j=0; j < ns; j++) { + mkinitcap((*slst)[j]); + } + + // expand suggestions with dot(s) + if (abbv && pAMgr && pAMgr->get_sugswithdots()) { + for (int j = 0; j < ns; j++) { + (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv); + strcat((*slst)[j], word + strlen(word) - abbv); + } + } + + // remove bad capitalized and forbidden forms + if (pAMgr && (pAMgr->get_keepcase() || pAMgr->get_forbiddenword())) { + switch (captype) { + case INITCAP: + case ALLCAP: { + int l = 0; + for (int j=0; j < ns; j++) { + if (!strchr((*slst)[j],' ') && !spell((*slst)[j])) { + char s[MAXSWUTF8L]; + w_char w[MAXSWL]; + int len; + if (utf8) { + len = u8_u16(w, MAXSWL, (*slst)[j]); + } else { + strcpy(s, (*slst)[j]); + len = strlen(s); + } + mkallsmall2(s, w, len); + free((*slst)[j]); + if (spell(s)) { + (*slst)[l] = mystrdup(s); + l++; + } else { + mkinitcap2(s, w, len); + if (spell(s)) { + (*slst)[l] = mystrdup(s); + l++; + } + } + } else { + (*slst)[l] = (*slst)[j]; + l++; + } + } + ns = l; + } + } + } + + // remove duplications + int l = 0; + for (int j = 0; j < ns; j++) { + (*slst)[l] = (*slst)[j]; + for (int k = 0; k < l; k++) { + if (strcmp((*slst)[k], (*slst)[j]) == 0) { + free((*slst)[j]); + l--; + } + } + l++; + } + return l; +} + +char * Hunspell::get_dic_encoding() +{ + return encoding; +} + +#ifdef HUNSPELL_EXPERIMENTAL +// XXX need UTF-8 support +int Hunspell::suggest_auto(char*** slst, const char * word) +{ + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (! pSMgr) return 0; + int wl = strlen(word); + if (utf8) { + if (wl >= MAXWORDUTF8LEN) return 0; + } else { + if (wl >= MAXWORDLEN) return 0; + } + int captype = 0; + int abbv = 0; + wl = cleanword(cw, word, &captype, &abbv); + if (wl == 0) return 0; + int ns = 0; + *slst = NULL; // HU, nsug in pSMgr->suggest + + switch(captype) { + case NOCAP: { + ns = pSMgr->suggest_auto(slst, cw, ns); + if (ns>0) break; + break; + } + + case INITCAP: { + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + ns = pSMgr->suggest_auto(slst, wspace, ns); + for (int j=0; j < ns; j++) + mkinitcap((*slst)[j]); + ns = pSMgr->suggest_auto(slst, cw, ns); + break; + + } + + case HUHCAP: { + ns = pSMgr->suggest_auto(slst, cw, ns); + if (ns == 0) { + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + ns = pSMgr->suggest_auto(slst, wspace, ns); + } + break; + } + + case ALLCAP: { + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + ns = pSMgr->suggest_auto(slst, wspace, ns); + + mkinitcap(wspace); + ns = pSMgr->suggest_auto(slst, wspace, ns); + + for (int j=0; j < ns; j++) + mkallcap((*slst)[j]); + break; + } + } + + // word reversing wrapper for complex prefixes + if (complexprefixes) { + for (int j = 0; j < ns; j++) { + if (utf8) reverseword_utf((*slst)[j]); else reverseword((*slst)[j]); + } + } + + // expand suggestions with dot(s) + if (abbv && pAMgr && pAMgr->get_sugswithdots()) { + for (int j = 0; j < ns; j++) { + (*slst)[j] = (char *) realloc((*slst)[j], strlen((*slst)[j]) + 1 + abbv); + strcat((*slst)[j], word + strlen(word) - abbv); + } + } + + // LANG_hu section: replace '-' with ' ' in Hungarian + if (langnum == LANG_hu) { + for (int j=0; j < ns; j++) { + char * pos = strchr((*slst)[j],'-'); + if (pos) { + int info; + char w[MAXWORDUTF8LEN]; + *pos = '\0'; + strcpy(w, (*slst)[j]); + strcat(w, pos + 1); + spell(w, &info, NULL); + if ((info & SPELL_COMPOUND) && (info & SPELL_FORBIDDEN)) { + *pos = ' '; + } else *pos = '-'; + } + } + } + // END OF LANG_hu section + return ns; +} +#endif + +int Hunspell::stem(char*** slst, char ** desc, int n) +{ + char result[MAXLNLEN]; + char result2[MAXLNLEN]; + if (n == 0) return 0; + *result2 = '\0'; + for (int i = 0; i < n; i++) { + *result = '\0'; + // add compound word parts (except the last one) + char * s = (char *) desc[i]; + char * part = strstr(s, MORPH_PART); + if (part) { + char * nextpart = strstr(part + 1, MORPH_PART); + while (nextpart) { + copy_field(result + strlen(result), part, MORPH_PART); + part = nextpart; + nextpart = strstr(part + 1, MORPH_PART); + } + s = part; + } + + char **pl; + char tok[MAXLNLEN]; + strcpy(tok, s); + char * alt = strstr(tok, " | "); + while (alt) { + alt[1] = MSEP_ALT; + alt = strstr(alt, " | "); + } + int pln = line_tok(tok, &pl, MSEP_ALT); + for (int i = 0; i < pln; i++) { + // add derivational suffixes + if (strstr(pl[i], MORPH_DERI_SFX)) { + // remove inflectional suffixes + char * is = strstr(pl[i], MORPH_INFL_SFX); + if (is) *is = '\0'; + char * sg = pSMgr->suggest_gen(&(pl[i]), 1, pl[i]); + if (sg) { + char ** gen; + int genl = line_tok(sg, &gen, MSEP_REC); + free(sg); + for (int j = 0; j < genl; j++) { + sprintf(result2 + strlen(result2), "%c%s%s", + MSEP_REC, result, gen[j]); + } + freelist(&gen, genl); + } + } else { + sprintf(result2 + strlen(result2), "%c%s", MSEP_REC, result); + if (strstr(pl[i], MORPH_SURF_PFX)) { + copy_field(result2 + strlen(result2), pl[i], MORPH_SURF_PFX); + } + copy_field(result2 + strlen(result2), pl[i], MORPH_STEM); + } + } + freelist(&pl, pln); + } + return uniqlist(*slst, line_tok(result2, slst, MSEP_REC)); +} + +int Hunspell::stem(char*** slst, const char * word) +{ + char ** pl; + int pln = analyze(&pl, word); + int pln2 = stem(slst, pl, pln); + freelist(&pl, pln); + return pln2; +} + +#ifdef HUNSPELL_EXPERIMENTAL +int Hunspell::suggest_pos_stems(char*** slst, const char * word) +{ + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (! pSMgr) return 0; + int wl = strlen(word); + if (utf8) { + if (wl >= MAXWORDUTF8LEN) return 0; + } else { + if (wl >= MAXWORDLEN) return 0; + } + int captype = 0; + int abbv = 0; + wl = cleanword(cw, word, &captype, &abbv); + if (wl == 0) return 0; + + int ns = 0; // ns=0 = normalized input + + *slst = NULL; // HU, nsug in pSMgr->suggest + + switch(captype) { + case HUHCAP: + case NOCAP: { + ns = pSMgr->suggest_pos_stems(slst, cw, ns); + + if ((abbv) && (ns == 0)) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + ns = pSMgr->suggest_pos_stems(slst, wspace, ns); + } + + break; + } + + case INITCAP: { + + ns = pSMgr->suggest_pos_stems(slst, cw, ns); + + if (ns == 0 || ((*slst)[0][0] == '#')) { + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + ns = pSMgr->suggest_pos_stems(slst, wspace, ns); + } + + break; + + } + + case ALLCAP: { + ns = pSMgr->suggest_pos_stems(slst, cw, ns); + if (ns != 0) break; + + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + ns = pSMgr->suggest_pos_stems(slst, wspace, ns); + + if (ns == 0) { + mkinitcap(wspace); + ns = pSMgr->suggest_pos_stems(slst, wspace, ns); + } + break; + } + } + + return ns; +} +#endif // END OF HUNSPELL_EXPERIMENTAL CODE + +const char * Hunspell::get_wordchars() +{ + return pAMgr->get_wordchars(); +} + +unsigned short * Hunspell::get_wordchars_utf16(int * len) +{ + return pAMgr->get_wordchars_utf16(len); +} + +void Hunspell::mkinitcap(char * p) +{ + if (!utf8) { + if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper; + } else { + int len; + w_char u[MAXWORDLEN]; + len = u8_u16(u, MAXWORDLEN, p); + unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum); + u[0].h = (unsigned char) (i >> 8); + u[0].l = (unsigned char) (i & 0x00FF); + u16_u8(p, MAXWORDUTF8LEN, u, len); + } +} + +int Hunspell::mkinitcap2(char * p, w_char * u, int nc) +{ + if (!utf8) { + if (*p != '\0') *p = csconv[((unsigned char)*p)].cupper; + } else if (nc > 0) { + unsigned short i = unicodetoupper((u[0].h << 8) + u[0].l, langnum); + u[0].h = (unsigned char) (i >> 8); + u[0].l = (unsigned char) (i & 0x00FF); + u16_u8(p, MAXWORDUTF8LEN, u, nc); + return strlen(p); + } + return nc; +} + +int Hunspell::mkinitsmall2(char * p, w_char * u, int nc) +{ + if (!utf8) { + if (*p != '\0') *p = csconv[((unsigned char)*p)].clower; + } else if (nc > 0) { + unsigned short i = unicodetolower((u[0].h << 8) + u[0].l, langnum); + u[0].h = (unsigned char) (i >> 8); + u[0].l = (unsigned char) (i & 0x00FF); + u16_u8(p, MAXWORDUTF8LEN, u, nc); + return strlen(p); + } + return nc; +} + +int Hunspell::add(const char * word) +{ + if (pHMgr) return pHMgr->add(word, NULL); + return 0; +} + +int Hunspell::add_with_affix(const char * word, const char * example) +{ + if (pHMgr) return pHMgr->add_with_affix(word, example); + return 0; +} + +/* XXX not implemented yet */ + +int Hunspell::remove(const char * word) +{ + if (pHMgr) return pHMgr->remove(word); + return 0; +} + +const char * Hunspell::get_version() +{ + return pAMgr->get_version(); +} + +struct cs_info * Hunspell::get_csconv() +{ + return csconv; +} + +char * Hunspell::cat_result(char * result, char * st) +{ + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + return result; +} + +int Hunspell::analyze(char*** slst, const char * word) +{ + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (! pSMgr) return 0; + int wl = strlen(word); + if (utf8) { + if (wl >= MAXWORDUTF8LEN) return 0; + } else { + if (wl >= MAXWORDLEN) return 0; + } + int captype = 0; + int abbv = 0; + wl = cleanword(cw, word, &captype, &abbv); + if (wl == 0) { + if (abbv) { + for (wl = 0; wl < abbv; wl++) cw[wl] = '.'; + cw[wl] = '\0'; + abbv = 0; + } else return 0; + } + + char result[MAXLNLEN]; + char * st = NULL; + + *result = '\0'; + + int n = 0; + int n2 = 0; + int n3 = 0; + + // test numbers + // LANG_hu section: set dash information for suggestions + if (langnum == LANG_hu) { + while ((n < wl) && + (((cw[n] <= '9') && (cw[n] >= '0')) || (((cw[n] == '.') || (cw[n] == ',')) && (n > 0)))) { + n++; + if ((cw[n] == '.') || (cw[n] == ',')) { + if (((n2 == 0) && (n > 3)) || + ((n2 > 0) && ((cw[n-1] == '.') || (cw[n-1] == ',')))) break; + n2++; + n3 = n; + } + } + + if ((n == wl) && (n3 > 0) && (n - n3 > 3)) return 0; + if ((n == wl) || ((n>0) && ((cw[n]=='%') || (cw[n]=='\xB0')) && checkword(cw+n, NULL, NULL))) { + strcat(result, cw); + result[n - 1] = '\0'; + if (n == wl) cat_result(result, pSMgr->suggest_morph(cw + n - 1)); + else { + char sign = cw[n]; + cw[n] = '\0'; + cat_result(result, pSMgr->suggest_morph(cw + n - 1)); + strcat(result, "+"); // XXX SPEC. MORPHCODE + cw[n] = sign; + cat_result(result, pSMgr->suggest_morph(cw + n)); + } + return line_tok(result, slst, MSEP_REC); + } + } + // END OF LANG_hu section + + switch(captype) { + case NOCAP: { + cat_result(result, pSMgr->suggest_morph(cw)); + if (abbv) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + cat_result(result, pSMgr->suggest_morph(wspace)); + } + break; + } + case INITCAP: { + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + cat_result(result, pSMgr->suggest_morph(wspace)); + cat_result(result, pSMgr->suggest_morph(cw)); + if (abbv) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + mkallsmall(wspace); + cat_result(result, pSMgr->suggest_morph(wspace)); + mkinitcap(wspace); + cat_result(result, pSMgr->suggest_morph(wspace)); + } + break; + } + case HUHCAP: { + cat_result(result, pSMgr->suggest_morph(cw)); +#if 0 + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + cat_result(result, pSMgr->suggest_morph(wspace)); +#endif + break; + } + case ALLCAP: { + memcpy(wspace,cw,(wl+1)); + cat_result(result, pSMgr->suggest_morph(wspace)); + mkallsmall(wspace); + cat_result(result, pSMgr->suggest_morph(wspace)); + mkinitcap(wspace); + cat_result(result, pSMgr->suggest_morph(wspace)); + if (abbv) { + memcpy(wspace,cw,(wl+1)); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + cat_result(result, pSMgr->suggest_morph(wspace)); + mkallsmall(wspace); + cat_result(result, pSMgr->suggest_morph(wspace)); + mkinitcap(wspace); + cat_result(result, pSMgr->suggest_morph(wspace)); + } + break; + } + } + + if (result && (*result)) { + // word reversing wrapper for complex prefixes + if (complexprefixes) { + if (utf8) reverseword_utf(result); else reverseword(result); + } + return line_tok(result, slst, MSEP_REC); + + } + + // compound word with dash (HU) I18n + char * dash = NULL; + int nresult = 0; + // LANG_hu section: set dash information for suggestions + if (langnum == LANG_hu) dash = (char *) strchr(cw,'-'); + if ((langnum == LANG_hu) && dash) { + *dash='\0'; + // examine 2 sides of the dash + if (dash[1] == '\0') { // base word ending with dash + if (spell(cw)) return line_tok(pSMgr->suggest_morph(cw), slst, MSEP_REC); + } else if ((dash[1] == 'e') && (dash[2] == '\0')) { // XXX (HU) -e hat. + if (spell(cw) && (spell("-e"))) { + st = pSMgr->suggest_morph(cw); + if (st) { + strcat(result, st); + free(st); + } + strcat(result,"+"); // XXX spec. separator in MORPHCODE + st = pSMgr->suggest_morph("-e"); + if (st) { + strcat(result, st); + free(st); + } + return line_tok(result, slst, MSEP_REC); + } + } else { + // first word ending with dash: word- XXX ??? + char r2 = *(dash + 1); + dash[0]='-'; + dash[1]='\0'; + nresult = spell(cw); + dash[1] = r2; + dash[0]='\0'; + if (nresult && spell(dash+1) && ((strlen(dash+1) > 1) || + ((dash[1] > '0') && (dash[1] < '9')))) { + st = pSMgr->suggest_morph(cw); + if (st) { + strcat(result, st); + free(st); + strcat(result,"+"); // XXX spec. separator in MORPHCODE + } + st = pSMgr->suggest_morph(dash+1); + if (st) { + strcat(result, st); + free(st); + } + return line_tok(result, slst, MSEP_REC); + } + } + // affixed number in correct word + if (nresult && (dash > cw) && (((*(dash-1)<='9') && + (*(dash-1)>='0')) || (*(dash-1)=='.'))) { + *dash='-'; + n = 1; + if (*(dash - n) == '.') n++; + // search first not a number character to left from dash + while (((dash - n)>=cw) && ((*(dash - n)=='0') || (n < 3)) && (n < 6)) { + n++; + } + if ((dash - n) < cw) n--; + // numbers: valami1000000-hoz + // examine 100000-hoz, 10000-hoz 1000-hoz, 10-hoz, + // 56-hoz, 6-hoz + for(; n >= 1; n--) { + if ((*(dash - n) >= '0') && (*(dash - n) <= '9') && checkword(dash - n, NULL, NULL)) { + strcat(result, cw); + result[dash - cw - n] = '\0'; + st = pSMgr->suggest_morph(dash - n); + if (st) { + strcat(result, st); + free(st); + } + return line_tok(result, slst, MSEP_REC); + } + } + } + } + return 0; +} + +int Hunspell::generate(char*** slst, const char * word, char ** pl, int pln) +{ + if (!pSMgr || !pln) return 0; + char **pl2; + char pl2n = analyze(&pl2, word); + int captype = 0; + int abbv = 0; + char cw[MAXWORDUTF8LEN]; + cleanword(cw, word, &captype, &abbv); + char result[MAXLNLEN]; + *result = '\0'; + + for (int i = 0; i < pln; i++) { + cat_result(result, pSMgr->suggest_gen(pl2, pl2n, pl[i])); + } + freelist(&pl2, pl2n); + + if (*result) { + // allcap + if (captype == ALLCAP) mkallcap(result); + + // line split + int linenum = line_tok(result, slst, MSEP_REC); + + // capitalize + if (captype == INITCAP || captype == HUHINITCAP) { + for (int j=0; j < linenum; j++) mkinitcap((*slst)[j]); + } + + // temporary filtering of prefix related errors (eg. + // generate("undrinkable", "eats") --> "undrinkables" and "*undrinks") + + int r = 0; + for (int j=0; j < linenum; j++) { + if (!spell((*slst)[j])) { + free((*slst)[j]); + (*slst)[j] = NULL; + } else { + if (r < j) (*slst)[r] = (*slst)[j]; + r++; + } + } + if (r > 0) return r; + free(*slst); + *slst = NULL; + } + return 0; +} + +int Hunspell::generate(char*** slst, const char * word, const char * pattern) +{ + char **pl; + char pln = analyze(&pl, pattern); + int n = generate(slst, word, pl, pln); + freelist(&pl, pln); + return uniqlist(*slst, n); +} + +#ifdef HUNSPELL_EXPERIMENTAL +// XXX need UTF-8 support +char * Hunspell::morph_with_correction(const char * word) +{ + char cw[MAXWORDUTF8LEN]; + char wspace[MAXWORDUTF8LEN]; + if (! pSMgr) return NULL; + int wl = strlen(word); + if (utf8) { + if (wl >= MAXWORDUTF8LEN) return NULL; + } else { + if (wl >= MAXWORDLEN) return NULL; + } + int captype = 0; + int abbv = 0; + wl = cleanword(cw, word, &captype, &abbv); + if (wl == 0) return NULL; + + char result[MAXLNLEN]; + char * st = NULL; + + *result = '\0'; + + + switch(captype) { + case NOCAP: { + st = pSMgr->suggest_morph_for_spelling_error(cw); + if (st) { + strcat(result, st); + free(st); + } + if (abbv) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + } + break; + } + case INITCAP: { + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + strcat(result, st); + free(st); + } + st = pSMgr->suggest_morph_for_spelling_error(cw); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + if (abbv) { + memcpy(wspace,cw,wl); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + mkallsmall(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + mkinitcap(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + } + break; + } + case HUHCAP: { + st = pSMgr->suggest_morph_for_spelling_error(cw); + if (st) { + strcat(result, st); + free(st); + } + memcpy(wspace,cw,(wl+1)); + mkallsmall(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + break; + } + case ALLCAP: { + memcpy(wspace,cw,(wl+1)); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + strcat(result, st); + free(st); + } + mkallsmall(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + mkinitcap(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + if (abbv) { + memcpy(wspace,cw,(wl+1)); + *(wspace+wl) = '.'; + *(wspace+wl+1) = '\0'; + if (*result) strcat(result, "\n"); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + strcat(result, st); + free(st); + } + mkallsmall(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + mkinitcap(wspace); + st = pSMgr->suggest_morph_for_spelling_error(wspace); + if (st) { + if (*result) strcat(result, "\n"); + strcat(result, st); + free(st); + } + } + break; + } + } + + if (result) return mystrdup(result); + return NULL; +} + +#endif // END OF HUNSPELL_EXPERIMENTAL CODE + +Hunhandle *Hunspell_create(const char * affpath, const char * dpath) +{ + return (Hunhandle*)(new Hunspell(affpath, dpath)); +} + +void Hunspell_destroy(Hunhandle *pHunspell) +{ + delete (Hunspell*)(pHunspell); +} + +int Hunspell_spell(Hunhandle *pHunspell, const char *word) +{ + return ((Hunspell*)pHunspell)->spell(word); +} + +char *Hunspell_get_dic_encoding(Hunhandle *pHunspell) +{ + return ((Hunspell*)pHunspell)->get_dic_encoding(); +} + +int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word) +{ + return ((Hunspell*)pHunspell)->suggest(slst, word); +} + +int Hunspell_analyze(Hunhandle *pHunspell, char*** slst, const char * word) +{ + return ((Hunspell*)pHunspell)->analyze(slst, word); +} + +int Hunspell_stem(Hunhandle *pHunspell, char*** slst, const char * word) +{ + return ((Hunspell*)pHunspell)->stem(slst, word); +} + +int Hunspell_stem(Hunhandle *pHunspell, char*** slst, char** desc, int n) +{ + return ((Hunspell*)pHunspell)->stem(slst, desc, n); +} + +int Hunspell_generate(Hunhandle *pHunspell, char*** slst, const char * word, + const char * word2) +{ + return ((Hunspell*)pHunspell)->generate(slst, word, word2); +} + +int Hunspell_generate(Hunhandle *pHunspell, char*** slst, const char * word, + char** desc, int n) +{ + return ((Hunspell*)pHunspell)->generate(slst, word, desc, n); +} + + /* functions for run-time modification of the dictionary */ + + /* add word to the run-time dictionary */ + +int Hunspell_add(Hunhandle *pHunspell, const char * word) { + return ((Hunspell*)pHunspell)->add(word); +} + + /* add word to the run-time dictionary with affix flags of + * the example (a dictionary word): Hunspell will recognize + * affixed forms of the new word, too. + */ + +int Hunspell_add_with_affix(Hunhandle *pHunspell, const char * word, + const char * example) { + return ((Hunspell*)pHunspell)->add_with_affix(word, example); +} + + /* remove word from the run-time dictionary */ + /* NOTE: not implemented yet */ + +int Hunspell_remove(Hunhandle *pHunspell, const char * word) { + return ((Hunspell*)pHunspell)->remove(word); +} diff --git a/hunspell/src/hunspell/hunspell.h b/hunspell/src/hunspell/hunspell.h new file mode 100644 index 000000000..452599c6a --- /dev/null +++ b/hunspell/src/hunspell/hunspell.h @@ -0,0 +1,87 @@ +#ifndef _MYSPELLMGR_H_ +#define _MYSPELLMGR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct Hunhandle Hunhandle; + +Hunhandle *Hunspell_create(const char * affpath, const char * dpath); +void Hunspell_destroy(Hunhandle *pHunspell); + +/* spell(word) - spellcheck word + * output: 0 = bad word, not 0 = good word + */ +int Hunspell_spell(Hunhandle *pHunspell, const char *); + +char *Hunspell_get_dic_encoding(Hunhandle *pHunspell); + +/* suggest(suggestions, word) - search suggestions + * input: pointer to an array of strings pointer and the (bad) word + * array of strings pointer (here *slst) may not be initialized + * output: number of suggestions in string array, and suggestions in + * a newly allocated array of strings (*slts will be NULL when number + * of suggestion equals 0.) + */ +int Hunspell_suggest(Hunhandle *pHunspell, char*** slst, const char * word); + + /* morphological functions */ + + /* analyze(result, word) - morphological analysis of the word */ + +int Hunspell_analyze(Hunhandle *pHunspell, char*** slst, const char * word); + + /* stem(result, word) - stemmer function */ + +int Hunspell_stem(Hunhandle *pHunspell, char*** slst, const char * word); + + /* stem(result, analysis, n) - get stems from a morph. analysis + * example: + * char ** result, result2; + * int n1 = Hunspell_analyze(result, "words"); + * int n2 = Hunspell_stem2(result2, result, n1); + */ + +int Hunspell_stem2(Hunhandle *pHunspell, char*** slst, char** desc, int n); + + /* generate(result, word, word2) - morphological generation by example(s) */ + +int Hunspell_generate(Hunhandle *pHunspell, char*** slst, const char * word, + const char * word2); + + /* generate(result, word, desc, n) - generation by morph. description(s) + * example: + * char ** result; + * char * affix = "is:plural"; // description depends from dictionaries, too + * int n = Hunspell_generate2(result, "word", &affix, 1); + * for (int i = 0; i < n; i++) printf("%s\n", result[i]); + */ + +int Hunspell_generate2(Hunhandle *pHunspell, char*** slst, const char * word, + char** desc, int n); + + /* functions for run-time modification of the dictionary */ + + /* add word to the run-time dictionary */ + +int Hunspell_add(const char * word); + + /* add word to the run-time dictionary with affix flags of + * the example (a dictionary word): Hunspell will recognize + * affixed forms of the new word, too. + */ + +int Hunspell_add_with_affix(const char * word, const char * example); + + /* remove word from the run-time dictionary */ + /* NOTE: not implemented yet */ + +int Hunspell_remove(const char * word); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hunspell/src/hunspell/hunspell.hxx b/hunspell/src/hunspell/hunspell.hxx new file mode 100644 index 000000000..38c141e44 --- /dev/null +++ b/hunspell/src/hunspell/hunspell.hxx @@ -0,0 +1,172 @@ +#include "hashmgr.hxx" +#include "affixmgr.hxx" +#include "suggestmgr.hxx" +#include "csutil.hxx" +#include "langnum.hxx" + +#define SPELL_COMPOUND (1 << 0) +#define SPELL_FORBIDDEN (1 << 1) +#define SPELL_ALLCAP (1 << 2) +#define SPELL_NOCAP (1 << 3) +#define SPELL_INITCAP (1 << 4) + +#define MAXSUGGESTION 15 +#define MAXSHARPS 5 + +#ifndef _MYSPELLMGR_HXX_ +#define _MYSPELLMGR_HXX_ + +#ifdef HUNSPELL_STATIC + #define DLLEXPORT +#else + #ifdef HUNSPELL_EXPORTS + #define DLLEXPORT __declspec( dllexport ) + #else + #define DLLEXPORT __declspec( dllimport ) + #endif +#endif + +#ifdef W32 +class DLLEXPORT Hunspell +#else +class Hunspell +#endif +{ + AffixMgr* pAMgr; + HashMgr* pHMgr; + SuggestMgr* pSMgr; + char * encoding; + struct cs_info * csconv; + int langnum; + int utf8; + int complexprefixes; + char** wordbreak; + +public: + + /* Hunspell(aff, dic) - constructor of Hunspell class + * input: path of affix file and dictionary file + */ + + Hunspell(const char * affpath, const char * dpath); + + ~Hunspell(); + + /* spell(word) - spellcheck word + * output: 0 = bad word, not 0 = good word + * + * plus output: + * info: information bit array, fields: + * SPELL_COMPOUND = a compound word + * SPELL_FORBIDDEN = an explicit forbidden word + * root: root (stem), when input is a word with affix(es) + */ + + int spell(const char * word, int * info = NULL, char ** root = NULL); + + /* suggest(suggestions, word) - search suggestions + * input: pointer to an array of strings pointer and the (bad) word + * array of strings pointer (here *slst) may not be initialized + * output: number of suggestions in string array, and suggestions in + * a newly allocated array of strings (*slts will be NULL when number + * of suggestion equals 0.) + */ + + int suggest(char*** slst, const char * word); + + char * get_dic_encoding(); + + /* morphological functions */ + + /* analyze(result, word) - morphological analysis of the word */ + + int analyze(char*** slst, const char * word); + + /* stem(result, word) - stemmer function */ + + int stem(char*** slst, const char * word); + + /* stem(result, analysis, n) - get stems from a morph. analysis + * example: + * char ** result, result2; + * int n1 = analyze(result, "words"); + * int n2 = stem(result2, result, n1); + */ + + int stem(char*** slst, char ** morph, int n); + + /* generate(result, word, word2) - morphological generation by example(s) */ + + int generate(char*** slst, const char * word, const char * word2); + + /* generate(result, word, desc, n) - generation by morph. description(s) + * example: + * char ** result; + * char * affix = "is:plural"; // description depends from dictionaries, too + * int n = generate(result, "word", &affix, 1); + * for (int i = 0; i < n; i++) printf("%s\n", result[i]); + */ + + int generate(char*** slst, const char * word, char ** desc, int n); + + /* functions for run-time modification of the dictionary */ + + /* add word to the run-time dictionary */ + + int add(const char * word); + + /* add word to the run-time dictionary with affix flags of + * the example (a dictionary word): Hunspell will recognize + * affixed forms of the new word, too. + */ + + int add_with_affix(const char * word, const char * example); + + /* remove word from the run-time dictionary */ + /* NOTE: not implemented yet */ + + int remove(const char * word); + + /* other */ + + /* get extra word characters definied in affix file for tokenization */ + const char * get_wordchars(); + unsigned short * get_wordchars_utf16(int * len); + + struct cs_info * get_csconv(); + const char * get_version(); + + /* experimental and deprecated functions */ + +#ifdef HUNSPELL_EXPERIMENTAL + /* suffix is an affix flag string, similarly in dictionary files */ + int put_word_suffix(const char * word, const char * suffix); + char * morph_with_correction(const char * word); + + /* spec. suggestions */ + int suggest_auto(char*** slst, const char * word); + int suggest_pos_stems(char*** slst, const char * word); + char * get_possible_root(); +#endif + +private: + int cleanword(char *, const char *, int * pcaptype, int * pabbrev); + int cleanword2(char *, const char *, w_char *, int * w_len, int * pcaptype, int * pabbrev); + void mkinitcap(char *); + int mkinitcap2(char * p, w_char * u, int nc); + int mkinitsmall2(char * p, w_char * u, int nc); + void mkallcap(char *); + int mkallcap2(char * p, w_char * u, int nc); + void mkallsmall(char *); + int mkallsmall2(char * p, w_char * u, int nc); + struct hentry * checkword(const char *, int * info, char **root); + char * sharps_u8_l1(char * dest, char * source); + hentry * spellsharps(char * base, char *, int, int, char * tmp, int * info, char **root); + int is_keepcase(const hentry * rv); + int insert_sug(char ***slst, char * word, int ns); + char * cat_result(char * result, char * st); + char * stem_description(const char * desc); + +}; + +#endif diff --git a/hunspell/src/hunspell/langnum.hxx b/hunspell/src/hunspell/langnum.hxx new file mode 100644 index 000000000..1d140a701 --- /dev/null +++ b/hunspell/src/hunspell/langnum.hxx @@ -0,0 +1,38 @@ +#ifndef _LANGNUM_HXX_ +#define _LANGNUM_HXX_ + +/* + language numbers for language specific codes + see http://l10n.openoffice.org/languages.html +*/ + +enum { +LANG_ar=96, +LANG_az=100, // custom number +LANG_bg=41, +LANG_ca=37, +LANG_cs=42, +LANG_da=45, +LANG_de=49, +LANG_el=30, +LANG_en=01, +LANG_es=34, +LANG_eu=10, +LANG_fr=02, +LANG_gl=38, +LANG_hr=78, +LANG_hu=36, +LANG_it=39, +LANG_la=99, // custom number +LANG_lv=101, // custom number +LANG_nl=31, +LANG_pl=48, +LANG_pt=03, +LANG_ru=07, +LANG_sv=50, +LANG_tr=90, +LANG_uk=80, +LANG_xx=999 +}; + +#endif diff --git a/hunspell/src/hunspell/license.hunspell b/hunspell/src/hunspell/license.hunspell new file mode 100644 index 000000000..490e440c7 --- /dev/null +++ b/hunspell/src/hunspell/license.hunspell @@ -0,0 +1,59 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Hunspell, based on MySpell. + * + * The Initial Developers of the Original Code are + * Kevin Hendricks (MySpell) and Laszlo Nemeth (Hunspell). + * Portions created by the Initial Developers are Copyright (C) 2002-2005 + * the Initial Developers. All Rights Reserved. + * + * Contributor(s): + * David Einstein + * Davide Prina + * Giuseppe Modugno + * Gianluca Turconi + * Simon Brouwer + * Noll Janos + * Biro Arpad + * Goldman Eleonora + * Sarlos Tamas + * Bencsath Boldizsar + * Halacsy Peter + * Dvornik Laszlo + * Gefferth Andras + * Nagy Viktor + * Varga Daniel + * Chris Halls + * Rene Engelhard + * Bram Moolenaar + * Dafydd Jones + * Harri Pitkanen + * Andras Timar + * Tor Lillqvist + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "config.h" diff --git a/hunspell/src/hunspell/license.myspell b/hunspell/src/hunspell/license.myspell new file mode 100644 index 000000000..2da533075 --- /dev/null +++ b/hunspell/src/hunspell/license.myspell @@ -0,0 +1,61 @@ +/* + * Copyright 2002 Kevin B. Hendricks, Stratford, Ontario, Canada + * And Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All modifications to the source code must be clearly marked as + * such. Binary redistributions based on modified source code + * must be clearly marked as modified versions in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY KEVIN B. HENDRICKS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * KEVIN B. HENDRICKS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * NOTE: A special thanks and credit goes to Geoff Kuenning + * the creator of ispell. MySpell's affix algorithms were + * based on those of ispell which should be noted is + * copyright Geoff Kuenning et.al. and now available + * under a BSD style license. For more information on ispell + * and affix compression in general, please see: + * http://www.cs.ucla.edu/ficus-members/geoff/ispell.html + * (the home page for ispell) + * + * An almost complete rewrite of MySpell for use by + * the Mozilla project has been developed by David Einstein + * (Deinst@world.std.com). David and I are now + * working on parallel development tracks to help + * our respective projects (Mozilla and OpenOffice.org + * and we will maintain full affix file and dictionary + * file compatibility and work on merging our versions + * of MySpell back into a single tree. David has been + * a significant help in improving MySpell. + * + * Special thanks also go to La'szlo' Ne'meth + * who is the author of the + * Hungarian dictionary and who developed and contributed + * the code to support compound words in MySpell + * and fixed numerous problems with the encoding + * case conversion tables. + * + */ diff --git a/hunspell/src/hunspell/makefile.mk b/hunspell/src/hunspell/makefile.mk new file mode 100644 index 000000000..8eeaebec6 --- /dev/null +++ b/hunspell/src/hunspell/makefile.mk @@ -0,0 +1,113 @@ +#************************************************************************* +# +# $RCSfile: makefile.mk,v $ +# +# $Revision: 1.7 $ +# +# last change: $Author: vg $ $Date: 2003/06/12 10:38:24 $ +# +# The Contents of this file are made available subject to the terms of +# either of the following licenses +# +# - GNU Lesser General Public License Version 2.1 +# - Sun Industry Standards Source License Version 1.1 +# +# Sun Microsystems Inc., October, 2000 +# +# GNU Lesser General Public License Version 2.1 +# ============================================= +# Copyright 2000 by Sun Microsystems, Inc. +# 901 San Antonio Road, Palo Alto, CA 94303, USA +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1, as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# +# +# Sun Industry Standards Source License Version 1.1 +# ================================================= +# The contents of this file are subject to the Sun Industry Standards +# Source License Version 1.1 (the "License"); You may not use this file +# except in compliance with the License. You may obtain a copy of the +# License at http://www.openoffice.org/license.html. +# +# Software provided under this License is provided on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, +# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. +# See the License for the specific provisions governing your rights and +# obligations concerning the Software. +# +# The Initial Developer of the Original Code is: Sun Microsystems, Inc. +# +# Copyright: 2000 by Sun Microsystems, Inc. +# +# All Rights Reserved. +# +# Contributor(s): _______________________________________ +# +# +# +#************************************************************************* + +PRJ = .. + +PRJNAME = hunspell +TARGET = hunspell +LIBTARGET=NO + +#----- Settings --------------------------------------------------------- + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +# all_target: ALLTAR DICTIONARY +all_target: ALLTAR + +##CXXFLAGS += -I..$/..$/lingutil +##CFLAGSCXX += -I..$/..$/lingutil +##CFLAGSCC += -I..$/..$/lingutil + +CDEFS+=-DOPENOFFICEORG + +SLOFILES= \ + $(SLO)$/affentry.obj \ + $(SLO)$/affixmgr.obj \ + $(SLO)$/dictmgr.obj \ + $(SLO)$/csutil.obj \ + $(SLO)$/utf_info.obj \ + $(SLO)$/hashmgr.obj \ + $(SLO)$/suggestmgr.obj \ + $(SLO)$/hunspell.obj + +LIB1TARGET= $(SLB)$/lib$(TARGET).lib +LIB1ARCHIV= $(LB)/lib$(TARGET).a +LIB1OBJFILES= $(SLOFILES) + +# DIC2BIN= \ +# en_US.aff \ +# en_US.dic +# +# de_DE.aff \ +# de_DE.dic + + +# DICTIONARY : +# +$(COPY) $(foreach,i,$(DIC2BIN) $i) $(BIN) + + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/hunspell/src/hunspell/phonet.cxx b/hunspell/src/hunspell/phonet.cxx new file mode 100644 index 000000000..e4ad5a022 --- /dev/null +++ b/hunspell/src/hunspell/phonet.cxx @@ -0,0 +1,294 @@ +/* phonetic.c - generic replacement aglogithms for phonetic transformation + Copyright (C) 2000 Bjoern Jacke + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation; + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; If not, see + . + + Changelog: + + 2000-01-05 Bjoern Jacke + Initial Release insprired by the article about phonetic + transformations out of c't 25/1999 + + 2007-07-26 Bjoern Jacke + Released under MPL/GPL/LGPL tri-license for Hunspell + + 2007-08-23 Laszlo Nemeth + Porting from Aspell to Hunspell using C-like structs +*/ + +#ifndef MOZILLA_CLIENT +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include "csutil.hxx" +#include "phonet.hxx" + +void init_phonet_hash(phonetable & parms) + { + int i, k; + + for (i = 0; i < parms.hash_size; i++) { + parms.hash[i] = -1; + } + + for (i = 0; parms.rules[i][0] != '\0'; i += 2) { + /** set hash value **/ + k = (unsigned char) parms.rules[i][0]; + + if (parms.hash[k] < 0) { + parms.hash[k] = i; + } + } + } + + // like strcpy but safe if the strings overlap + // but only if dest < src + static inline void strmove(char * dest, char * src) { + while (*src) + *dest++ = *src++; + *dest = '\0'; + } + +/* phonetic transcription algorithm */ +/* see: http://aspell.net/man-html/Phonetic-Code.html */ +/* convert string to uppercase before this call */ +int phonet (const char * inword, char * target, + int len, + phonetable & parms) + { + /** Do phonetic transformation. **/ + /** "len" = length of "inword" incl. '\0'. **/ + + /** result: >= 0: length of "target" **/ + /** otherwise: error **/ + + int i,j,k=0,n,p,z; + int k0,n0,p0=-333,z0; + char c, c0; + const char * s; + typedef unsigned char uchar; + char word[MAXPHONETUTF8LEN + 1]; + if (len == -1) len = strlen(inword); + if (len > MAXPHONETUTF8LEN) return 0; + strcpy(word, inword); + + /** check word **/ + i = j = z = 0; + while ((c = word[i]) != '\0') { + n = parms.hash[(uchar) c]; + z0 = 0; + + if (n >= 0) { + /** check all rules for the same letter **/ + while (parms.rules[n][0] == c) { + + /** check whole string **/ + k = 1; /** number of found letters **/ + p = 5; /** default priority **/ + s = parms.rules[n]; + s++; /** important for (see below) "*(s-1)" **/ + + while (*s != '\0' && word[i+k] == *s + && !isdigit (*s) && strchr ("(-<^$", *s) == NULL) { + k++; + s++; + } + if (*s == '(') { + /** check letters in "(..)" **/ + if (isalpha(word[i+k]) // ...could be implied? + && strchr(s+1, word[i+k]) != NULL) { + k++; + while (*s != ')') + s++; + s++; + } + } + p0 = (int) *s; + k0 = k; + while (*s == '-' && k > 1) { + k--; + s++; + } + if (*s == '<') + s++; + if (isdigit (*s)) { + /** determine priority **/ + p = *s - '0'; + s++; + } + if (*s == '^' && *(s+1) == '^') + s++; + + if (*s == '\0' + || (*s == '^' + && (i == 0 || ! isalpha(word[i-1])) + && (*(s+1) != '$' + || (! isalpha(word[i+k0]) ))) + || (*s == '$' && i > 0 + && isalpha(word[i-1]) + && (! isalpha(word[i+k0]) ))) + { + /** search for followup rules, if: **/ + /** parms.followup and k > 1 and NO '-' in searchstring **/ + c0 = word[i+k-1]; + n0 = parms.hash[(uchar) c0]; + +// if (parms.followup && k > 1 && n0 >= 0 + if (k > 1 && n0 >= 0 + && p0 != (int) '-' && word[i+k] != '\0') { + /** test follow-up rule for "word[i+k]" **/ + while (parms.rules[n0][0] == c0) { + + /** check whole string **/ + k0 = k; + p0 = 5; + s = parms.rules[n0]; + s++; + while (*s != '\0' && word[i+k0] == *s + && ! isdigit(*s) && strchr("(-<^$",*s) == NULL) { + k0++; + s++; + } + if (*s == '(') { + /** check letters **/ + if (isalpha(word[i+k0]) + && strchr (s+1, word[i+k0]) != NULL) { + k0++; + while (*s != ')' && *s != '\0') + s++; + if (*s == ')') + s++; + } + } + while (*s == '-') { + /** "k0" gets NOT reduced **/ + /** because "if (k0 == k)" **/ + s++; + } + if (*s == '<') + s++; + if (isdigit (*s)) { + p0 = *s - '0'; + s++; + } + + if (*s == '\0' + /** *s == '^' cuts **/ + || (*s == '$' && ! isalpha(word[i+k0]))) + { + if (k0 == k) { + /** this is just a piece of the string **/ + n0 += 2; + continue; + } + + if (p0 < p) { + /** priority too low **/ + n0 += 2; + continue; + } + /** rule fits; stop search **/ + break; + } + n0 += 2; + } /** End of "while (parms.rules[n0][0] == c0)" **/ + + if (p0 >= p && parms.rules[n0][0] == c0) { + n += 2; + continue; + } + } /** end of follow-up stuff **/ + + /** replace string **/ + s = parms.rules[n+1]; + p0 = (parms.rules[n][0] != '\0' + && strchr (parms.rules[n]+1,'<') != NULL) ? 1:0; + if (p0 == 1 && z == 0) { + /** rule with '<' is used **/ + if (j > 0 && *s != '\0' + && (target[j-1] == c || target[j-1] == *s)) { + j--; + } + z0 = 1; + z = 1; + k0 = 0; + while (*s != '\0' && word[i+k0] != '\0') { + word[i+k0] = *s; + k0++; + s++; + } + if (k > k0) + strmove (&word[0]+i+k0, &word[0]+i+k); + + /** new "actual letter" **/ + c = word[i]; + } + else { /** no '<' rule used **/ + i += k - 1; + z = 0; + while (*s != '\0' + && *(s+1) != '\0' && j < len) { + if (j == 0 || target[j-1] != *s) { + target[j] = *s; + j++; + } + s++; + } + /** new "actual letter" **/ + c = *s; + if (parms.rules[n][0] != '\0' + && strstr (parms.rules[n]+1, "^^") != NULL) { + if (c != '\0') { + target[j] = c; + j++; + } + strmove (&word[0], &word[0]+i+1); + i = 0; + z0 = 1; + } + } + break; + } /** end of follow-up stuff **/ + n += 2; + } /** end of while (parms.rules[n][0] == c) **/ + } /** end of if (n >= 0) **/ + if (z0 == 0) { +// if (k && (assert(p0!=-333),!p0) && j < len && c != '\0' +// && (!parms.collapse_result || j == 0 || target[j-1] != c)){ + if (k && !p0 && j < len && c != '\0' + && (1 || j == 0 || target[j-1] != c)){ + /** condense only double letters **/ + target[j] = c; + ///printf("\n setting \n"); + j++; + } + + i++; + z = 0; + k=0; + } + } /** end of while ((c = word[i]) != '\0') **/ + + target[j] = '\0'; + return (j); + + } /** end of function "phonet" **/ diff --git a/hunspell/src/hunspell/phonet.hxx b/hunspell/src/hunspell/phonet.hxx new file mode 100644 index 000000000..471ff8417 --- /dev/null +++ b/hunspell/src/hunspell/phonet.hxx @@ -0,0 +1,50 @@ +/* phonetic.c - generic replacement aglogithms for phonetic transformation + Copyright (C) 2000 Bjoern Jacke + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation; + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; If not, see + . + + Changelog: + + 2000-01-05 Bjoern Jacke + Initial Release insprired by the article about phonetic + transformations out of c't 25/1999 + + 2007-07-26 Bjoern Jacke + Released under MPL/GPL/LGPL tri-license for Hunspell + + 2007-08-23 Laszlo Nemeth + Porting from Aspell to Hunspell using C-like structs +*/ + +#ifndef __PHONETHXX__ +#define __PHONETHXX__ + +#define MAXPHONETLEN 256 +#define MAXPHONETUTF8LEN (MAXPHONETLEN * 4) + +struct phonetable { + char utf8; + cs_info * lang; + int num; + char * * rules; + static const int hash_size = 256; + int hash[hash_size]; +}; + +void init_phonet_hash(phonetable & parms); + +int phonet (const char * inword, char * target, + int len, phonetable & phone); + +#endif diff --git a/hunspell/src/hunspell/suggestmgr.cxx b/hunspell/src/hunspell/suggestmgr.cxx new file mode 100644 index 000000000..b1a58f357 --- /dev/null +++ b/hunspell/src/hunspell/suggestmgr.cxx @@ -0,0 +1,1960 @@ +#include "license.hunspell" +#include "license.myspell" + +#ifndef MOZILLA_CLIENT +#include +#include +#include +#include +#else +#include +#include +#include +#include +#endif + +#include "suggestmgr.hxx" +#include "htypes.hxx" + +#ifndef MOZILLA_CLIENT +#ifndef W32 +using namespace std; +#endif +#endif + +const w_char W_VLINE = { '\0', '|' }; + +SuggestMgr::SuggestMgr(const char * tryme, int maxn, + AffixMgr * aptr) +{ + + // register affix manager and check in string of chars to + // try when building candidate suggestions + pAMgr = aptr; + + ckeyl = 0; + ckey = NULL; + ckey_utf = NULL; + + ctryl = 0; + ctry = NULL; + ctry_utf = NULL; + + utf8 = 0; + langnum = 0; + complexprefixes = 0; + + maxSug = maxn; + nosplitsugs = 0; + maxngramsugs = MAXNGRAMSUGS; + + if (pAMgr) { + char * enc = pAMgr->get_encoding(); + csconv = get_current_cs(enc); + free(enc); + langnum = pAMgr->get_langnum(); + ckey = pAMgr->get_key_string(); + nosplitsugs = pAMgr->get_nosplitsugs(); + if (pAMgr->get_maxngramsugs() >= 0) maxngramsugs = pAMgr->get_maxngramsugs(); + utf8 = pAMgr->get_utf8(); + complexprefixes = pAMgr->get_complexprefixes(); + } + + if (ckey) { + if (utf8) { + w_char t[MAXSWL]; + ckeyl = u8_u16(t, MAXSWL, ckey); + ckey_utf = (w_char *) malloc(ckeyl * sizeof(w_char)); + if (ckey_utf) memcpy(ckey_utf, t, ckeyl * sizeof(w_char)); + } else { + ckeyl = strlen(ckey); + } + } + + if (tryme) { + if (utf8) { + w_char t[MAXSWL]; + ctryl = u8_u16(t, MAXSWL, tryme); + ctry_utf = (w_char *) malloc(ctryl * sizeof(w_char)); + if (ctry_utf) memcpy(ctry_utf, t, ctryl * sizeof(w_char)); + } else { + ctry = mystrdup(tryme); + ctryl = strlen(ctry); + } + } +} + + +SuggestMgr::~SuggestMgr() +{ + pAMgr = NULL; + if (ckey) free(ckey); + ckey = NULL; + if (ckey_utf) free(ckey_utf); + ckey_utf = NULL; + ckeyl = 0; + if (ctry) free(ctry); + ctry = NULL; + if (ctry_utf) free(ctry_utf); + ctry_utf = NULL; + ctryl = 0; + maxSug = 0; +} + +int SuggestMgr::testsug(char** wlst, const char * candidate, int wl, int ns, int cpdsuggest, + int * timer, clock_t * timelimit) { + int cwrd = 1; + if (ns == maxSug) return maxSug; + for (int k=0; k < ns; k++) { + if (strcmp(candidate,wlst[k]) == 0) cwrd = 0; + } + if ((cwrd) && checkword(candidate, wl, cpdsuggest, timer, timelimit)) { + wlst[ns] = mystrdup(candidate); + if (wlst[ns] == NULL) { + for (int j=0; j HTML) + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? capchars_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + capchars(wlst, word, nsug, cpdsuggest); + } + + // perhaps we made a typical fault of spelling + if ((nsug < maxSug) && (nsug > -1)) + nsug = replchars(wlst, word, nsug, cpdsuggest); + + // perhaps we made chose the wrong char from a related set + if ((nsug < maxSug) && (nsug > -1)) { + nsug = mapchars(wlst, word, nsug, cpdsuggest); + } + + // did we swap the order of chars by mistake + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? swapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + swapchar(wlst, word, nsug, cpdsuggest); + } + + // did we swap the order of non adjacent chars by mistake + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? longswapchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + longswapchar(wlst, word, nsug, cpdsuggest); + } + + // did we just hit the wrong key in place of a good char (case and keyboard) + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? badcharkey_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + badcharkey(wlst, word, nsug, cpdsuggest); + } + + // did we add a char that should not be there + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? extrachar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + extrachar(wlst, word, nsug, cpdsuggest); + } + + // only suggest compound words when no other suggestion + if ((cpdsuggest == 0) && (nsug > 0)) nocompoundtwowords=1; + + // did we forgot a char + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? forgotchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + forgotchar(wlst, word, nsug, cpdsuggest); + } + + // did we move a char + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? movechar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + movechar(wlst, word, nsug, cpdsuggest); + } + + // did we just hit the wrong key in place of a good char + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? badchar_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + badchar(wlst, word, nsug, cpdsuggest); + } + + // did we double two characters + if ((nsug < maxSug) && (nsug > -1)) { + nsug = (utf8) ? doubletwochars_utf(wlst, word_utf, wl, nsug, cpdsuggest) : + doubletwochars(wlst, word, nsug, cpdsuggest); + } + + // perhaps we forgot to hit space and two words ran together + if ((!nosplitsugs) && (nsug < maxSug) && (nsug > -1)) { + nsug = twowords(wlst, word, nsug, cpdsuggest); + } + + } // repeating ``for'' statement compounding support + + if (nsug < 0) { + // we ran out of memory - we should free up as much as possible + for (int i = 0; i < maxSug; i++) + if (wlst[i] != NULL) free(wlst[i]); + free(wlst); + wlst = NULL; + } + + if (!nocompoundtwowords && (nsug > 0) && onlycompoundsug) *onlycompoundsug = 1; + + *slst = wlst; + return nsug; +} + +// generate suggestions for a word with typical mistake +// pass in address of array of char * pointers +#ifdef HUNSPELL_EXPERIMENTAL +int SuggestMgr::suggest_auto(char*** slst, const char * w, int nsug) +{ + int nocompoundtwowords = 0; + char ** wlst; + + char w2[MAXWORDUTF8LEN]; + const char * word = w; + + // word reversing wrapper for complex prefixes + if (complexprefixes) { + strcpy(w2, w); + if (utf8) reverseword_utf(w2); else reverseword(w2); + word = w2; + } + + if (*slst) { + wlst = *slst; + } else { + wlst = (char **) malloc(maxSug * sizeof(char *)); + if (wlst == NULL) return -1; + } + + for (int cpdsuggest=0; (cpdsuggest<2) && (nocompoundtwowords==0); cpdsuggest++) { + + // perhaps we made a typical fault of spelling + if ((nsug < maxSug) && (nsug > -1)) + nsug = replchars(wlst, word, nsug, cpdsuggest); + + // perhaps we made chose the wrong char from a related set + if ((nsug < maxSug) && (nsug > -1)) + nsug = mapchars(wlst, word, nsug, cpdsuggest); + + if ((cpdsuggest==0) && (nsug>0)) nocompoundtwowords=1; + + // perhaps we forgot to hit space and two words ran together + + if ((nsug < maxSug) && (nsug > -1) && check_forbidden(word, strlen(word))) { + nsug = twowords(wlst, word, nsug, cpdsuggest); + } + + } // repeating ``for'' statement compounding support + + if (nsug < 0) { + for (int i=0;i HTML) +int SuggestMgr::capchars_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + w_char candidate_utf[MAXSWL]; + memcpy(candidate_utf, word, wl * sizeof(w_char)); + mkallcap_utf(candidate_utf, wl, langnum); + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + return testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); +} + +// suggestions for an uppercase word (html -> HTML) +int SuggestMgr::capchars(char** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + strcpy(candidate, word); + mkallcap(candidate, csconv); + return testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); +} + +// suggestions for when chose the wrong char out of a related set +int SuggestMgr::mapchars(char** wlst, const char * word, int ns, int cpdsuggest) +{ + clock_t timelimit; + int timer; + + int wl = strlen(word); + if (wl < 2 || ! pAMgr) return ns; + + int nummap = pAMgr->get_nummap(); + struct mapentry* maptable = pAMgr->get_maptable(); + if (maptable==NULL) return ns; + + timelimit = clock(); + timer = MINTIMER; + if (utf8) { + w_char w[MAXSWL]; + int len = u8_u16(w, MAXSWL, word); + ns = map_related_utf(w, len, 0, cpdsuggest, wlst, ns, maptable, nummap, &timer, &timelimit); + } else ns = map_related(word, 0, wlst, cpdsuggest, ns, maptable, nummap, &timer, &timelimit); + return ns; +} + +int SuggestMgr::map_related(const char * word, int i, char** wlst, + int cpdsuggest, int ns, + const mapentry* maptable, int nummap, int * timer, clock_t * timelimit) +{ + char c = *(word + i); + if (c == 0) { + int cwrd = 1; + int wl = strlen(word); + for (int m=0; m < ns; m++) + if (strcmp(word,wlst[m]) == 0) cwrd = 0; + if ((cwrd) && checkword(word, wl, cpdsuggest, timer, timelimit)) { + if (ns < maxSug) { + wlst[ns] = mystrdup(word); + if (wlst[ns] == NULL) return -1; + ns++; + } + } + return ns; + } + int in_map = 0; + for (int j = 0; j < nummap; j++) { + if (strchr(maptable[j].set,c) != 0) { + in_map = 1; + char * newword = mystrdup(word); + for (int k = 0; k < maptable[j].len; k++) { + *(newword + i) = *(maptable[j].set + k); + ns = map_related(newword, (i+1), wlst, cpdsuggest, + ns, maptable, nummap, timer, timelimit); + if (!(*timer)) return ns; + } + free(newword); + } + } + if (!in_map) { + i++; + ns = map_related(word, i, wlst, cpdsuggest, + ns, maptable, nummap, timer, timelimit); + } + return ns; +} + +int SuggestMgr::map_related_utf(w_char * word, int len, int i, int cpdsuggest, + char** wlst, int ns, const mapentry* maptable, int nummap, + int * timer, clock_t * timelimit) +{ + if (i == len) { + int cwrd = 1; + int wl; + char s[MAXSWUTF8L]; + u16_u8(s, MAXSWUTF8L, word, len); + wl = strlen(s); + for (int m=0; m < ns; m++) + if (strcmp(s,wlst[m]) == 0) cwrd = 0; + if ((cwrd) && checkword(s, wl, cpdsuggest, timer, timelimit)) { + if (ns < maxSug) { + wlst[ns] = mystrdup(s); + if (wlst[ns] == NULL) return -1; + ns++; + } + } + return ns; + } + int in_map = 0; + unsigned short c = *((unsigned short *) word + i); + for (int j = 0; j < nummap; j++) { + if (flag_bsearch((unsigned short *) maptable[j].set_utf16, c, maptable[j].len)) { + in_map = 1; + for (int k = 0; k < maptable[j].len; k++) { + *(word + i) = *(maptable[j].set_utf16 + k); + ns = map_related_utf(word, len, i + 1, cpdsuggest, + wlst, ns, maptable, nummap, timer, timelimit); + if (!(*timer)) return ns; + } + *((unsigned short *) word + i) = c; + } + } + if (!in_map) { + i++; + ns = map_related_utf(word, len, i, cpdsuggest, + wlst, ns, maptable, nummap, timer, timelimit); + } + return ns; +} + + + +// suggestions for a typical fault of spelling, that +// differs with more, than 1 letter from the right form. +int SuggestMgr::replchars(char** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + const char * r; + int lenr, lenp; + int wl = strlen(word); + if (wl < 2 || ! pAMgr) return ns; + int numrep = pAMgr->get_numrep(); + struct replentry* reptable = pAMgr->get_reptable(); + if (reptable==NULL) return ns; + for (int i=0; i < numrep; i++ ) { + r = word; + lenr = strlen(reptable[i].pattern2); + lenp = strlen(reptable[i].pattern); + // search every occurence of the pattern in the word + while ((r=strstr(r, reptable[i].pattern)) != NULL) { + strcpy(candidate, word); + if (r-word + lenr + strlen(r+lenp) >= MAXSWUTF8L) break; + strcpy(candidate+(r-word),reptable[i].pattern2); + strcpy(candidate+(r-word)+lenr, r+lenp); + ns = testsug(wlst, candidate, wl-lenp+lenr, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + // check REP suggestions with space + char * sp = strchr(candidate, ' '); + if (sp) { + *sp = '\0'; + if (checkword(candidate, strlen(candidate), 0, NULL, NULL)) { + int oldns = ns; + *sp = ' '; + ns = testsug(wlst, sp + 1, strlen(sp + 1), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + if (oldns < ns) { + free(wlst[ns - 1]); + wlst[ns - 1] = mystrdup(candidate); + } + } + *sp = ' '; + } + r++; // search for the next letter + } + } + return ns; +} + +// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation) +int SuggestMgr::doubletwochars(char** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + int state=0; + int wl = strlen(word); + if (wl < 5 || ! pAMgr) return ns; + for (int i=2; i < wl; i++ ) { + if (word[i]==word[i-2]) { + state++; + if (state==3) { + strcpy(candidate,word); + strcpy(candidate+i-1,word+i+1); + ns = testsug(wlst, candidate, wl-2, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + state=0; + } + } else { + state=0; + } + } + return ns; +} + +// perhaps we doubled two characters (pattern aba -> ababa, for example vacation -> vacacation) +int SuggestMgr::doubletwochars_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + w_char candidate_utf[MAXSWL]; + char candidate[MAXSWUTF8L]; + int state=0; + if (wl < 5 || ! pAMgr) return ns; + for (int i=2; i < wl; i++) { + if (w_char_eq(word[i], word[i-2])) { + state++; + if (state==3) { + memcpy(candidate_utf, word, (i - 1) * sizeof(w_char)); + memcpy(candidate_utf+i-1, word+i+1, (wl-i-1) * sizeof(w_char)); + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl-2); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + state=0; + } + } else { + state=0; + } + } + return ns; +} + +// error is wrong char in place of correct one (case and keyboard related version) +int SuggestMgr::badcharkey(char ** wlst, const char * word, int ns, int cpdsuggest) +{ + char tmpc; + char candidate[MAXSWUTF8L]; + int wl = strlen(word); + strcpy(candidate, word); + // swap out each char one by one and try uppercase and neighbor + // keyboard chars in its place to see if that makes a good word + + for (int i=0; i < wl; i++) { + tmpc = candidate[i]; + // check with uppercase letters + candidate[i] = csconv[((unsigned char)tmpc)].cupper; + if (tmpc != candidate[i]) { + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + candidate[i] = tmpc; + } + // check neighbor characters in keyboard string + if (!ckey) continue; + char * loc = strchr(ckey, tmpc); + while (loc) { + if ((loc > ckey) && (*(loc - 1) != '|')) { + candidate[i] = *(loc - 1); + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + if ((*(loc + 1) != '|') && (*(loc + 1) != '\0')) { + candidate[i] = *(loc + 1); + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + loc = strchr(loc + 1, tmpc); + } + candidate[i] = tmpc; + } + return ns; +} + +// error is wrong char in place of correct one (case and keyboard related version) +int SuggestMgr::badcharkey_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + w_char tmpc; + w_char candidate_utf[MAXSWL]; + char candidate[MAXSWUTF8L]; + memcpy(candidate_utf, word, wl * sizeof(w_char)); + // swap out each char one by one and try all the tryme + // chars in its place to see if that makes a good word + for (int i=0; i < wl; i++) { + tmpc = candidate_utf[i]; + // check with uppercase letters + mkallcap_utf(candidate_utf + i, 1, langnum); + if (!w_char_eq(tmpc, candidate_utf[i])) { + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + candidate_utf[i] = tmpc; + } + // check neighbor characters in keyboard string + if (!ckey) continue; + w_char * loc = ckey_utf; + while ((loc < (ckey_utf + ckeyl)) && !w_char_eq(*loc, tmpc)) loc++; + while (loc < (ckey_utf + ckeyl)) { + if ((loc > ckey_utf) && !w_char_eq(*(loc - 1), W_VLINE)) { + candidate_utf[i] = *(loc - 1); + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + if (((loc + 1) < (ckey_utf + ckeyl)) && !w_char_eq(*(loc + 1), W_VLINE)) { + candidate_utf[i] = *(loc + 1); + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + do { loc++; } while ((loc < (ckey_utf + ckeyl)) && !w_char_eq(*loc, tmpc)); + } + candidate_utf[i] = tmpc; + } + return ns; +} + +// error is wrong char in place of correct one +int SuggestMgr::badchar(char ** wlst, const char * word, int ns, int cpdsuggest) +{ + char tmpc; + char candidate[MAXSWUTF8L]; + clock_t timelimit = clock(); + int timer = MINTIMER; + int wl = strlen(word); + strcpy(candidate, word); + // swap out each char one by one and try all the tryme + // chars in its place to see if that makes a good word + for (int i=0; i < wl; i++) { + tmpc = candidate[i]; + for (int j=0; j < ctryl; j++) { + if (ctry[j] == tmpc) continue; + candidate[i] = ctry[j]; + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, &timer, &timelimit); + if (ns == -1) return -1; + if (!timer) return ns; + candidate[i] = tmpc; + } + } + return ns; +} + +// error is wrong char in place of correct one +int SuggestMgr::badchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + w_char tmpc; + w_char candidate_utf[MAXSWL]; + char candidate[MAXSWUTF8L]; + clock_t timelimit = clock(); + int timer = MINTIMER; + memcpy(candidate_utf, word, wl * sizeof(w_char)); + // swap out each char one by one and try all the tryme + // chars in its place to see if that makes a good word + for (int i=0; i < wl; i++) { + tmpc = candidate_utf[i]; + for (int j=0; j < ctryl; j++) { + if (w_char_eq(tmpc, ctry_utf[j])) continue; + candidate_utf[i] = ctry_utf[j]; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, &timer, &timelimit); + if (ns == -1) return -1; + if (!timer) return ns; + candidate_utf[i] = tmpc; + } + } + return ns; +} + +// error is word has an extra letter it does not need +int SuggestMgr::extrachar_utf(char** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + w_char candidate_utf[MAXSWL]; + const w_char * p; + w_char * r; + if (wl < 2) return ns; + // try omitting one char of word at a time + memcpy(candidate_utf, word + 1, (wl - 1) * sizeof(w_char)); + for (p = word, r = candidate_utf; p < word + wl; ) { + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl - 1); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + *r++ = *p++; + } + return ns; +} + +// error is word has an extra letter it does not need +int SuggestMgr::extrachar(char** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + const char * p; + char * r; + int wl = strlen(word); + if (wl < 2) return ns; + // try omitting one char of word at a time + strcpy (candidate, word + 1); + for (p = word, r = candidate; *p != 0; ) { + ns = testsug(wlst, candidate, wl-1, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + *r++ = *p++; + } + return ns; +} + + +// error is missing a letter it needs +int SuggestMgr::forgotchar(char ** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + const char * p; + char * q; + clock_t timelimit = clock(); + int timer = MINTIMER; + int wl = strlen(word); + // try inserting a tryme character before every letter + strcpy(candidate + 1, word); + for (p = word, q = candidate; *p != 0; ) { + for (int i = 0; i < ctryl; i++) { + *q = ctry[i]; + ns = testsug(wlst, candidate, wl+1, ns, cpdsuggest, &timer, &timelimit); + if (ns == -1) return -1; + if (!timer) return ns; + } + *q++ = *p++; + } + // now try adding one to end */ + for (int i = 0; i < ctryl; i++) { + *q = ctry[i]; + ns = testsug(wlst, candidate, wl+1, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + return ns; +} + +// error is missing a letter it needs +int SuggestMgr::forgotchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + w_char candidate_utf[MAXSWL]; + char candidate[MAXSWUTF8L]; + const w_char * p; + w_char * q; + int cwrd; + clock_t timelimit = clock(); + int timer = MINTIMER; + // try inserting a tryme character before every letter + memcpy (candidate_utf + 1, word, wl * sizeof(w_char)); + for (p = word, q = candidate_utf; p < (word + wl); ) { + for (int i = 0; i < ctryl; i++) { + *q = ctry_utf[i]; + cwrd = 1; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl + 1); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, &timer, &timelimit); + if (ns == -1) return -1; + if (!timer) return ns; + } + *q++ = *p++; + } + // now try adding one to end */ + for (int i = 0; i < ctryl; i++) { + *q = ctry_utf[i]; + cwrd = 1; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl + 1); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + return ns; +} + + +/* error is should have been two words */ +int SuggestMgr::twowords(char ** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + char * p; + int c1, c2; + int forbidden = 0; + int cwrd; + + int wl=strlen(word); + if (wl < 3) return ns; + + if (langnum == LANG_hu) forbidden = check_forbidden(word, wl); + + strcpy(candidate + 1, word); + // split the string into two pieces after every char + // if both pieces are good words make them a suggestion + for (p = candidate + 1; p[1] != '\0'; p++) { + p[-1] = *p; + // go to end of the UTF-8 character + while (utf8 && ((p[1] & 0xc0) == 0x80)) { + *p = p[1]; + p++; + } + if (utf8 && p[1] == '\0') break; // last UTF-8 character + *p = '\0'; + c1 = checkword(candidate,strlen(candidate), cpdsuggest, NULL, NULL); + if (c1) { + c2 = checkword((p+1),strlen(p+1), cpdsuggest, NULL, NULL); + if (c2) { + *p = ' '; + + // spec. Hungarian code (need a better compound word support) + if ((langnum == LANG_hu) && !forbidden && + // if 3 repeating letter, use - instead of space + (((p[-1] == p[1]) && (((p>candidate+1) && (p[-1] == p[-2])) || (p[-1] == p[2]))) || + // or multiple compounding, with more, than 6 syllables + ((c1 == 3) && (c2 >= 2)))) *p = '-'; + + cwrd = 1; + for (int k=0; k < ns; k++) + if (strcmp(candidate,wlst[k]) == 0) cwrd = 0; + if (ns < maxSug) { + if (cwrd) { + wlst[ns] = mystrdup(candidate); + if (wlst[ns] == NULL) return -1; + ns++; + } + } else return ns; + } + } + } + return ns; +} + + +// error is adjacent letter were swapped +int SuggestMgr::swapchar(char ** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + char * p; + char tmpc; + int wl=strlen(word); + // try swapping adjacent chars one by one + strcpy(candidate, word); + for (p = candidate; p[1] != 0; p++) { + tmpc = *p; + *p = p[1]; + p[1] = tmpc; + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + p[1] = *p; + *p = tmpc; + } + // try double swaps for short words + // ahev -> have, owudl -> would + if (wl == 4 || wl == 5) { + candidate[0] = word[1]; + candidate[1] = word[0]; + candidate[2] = word[2]; + candidate[wl - 2] = word[wl - 1]; + candidate[wl - 1] = word[wl - 2]; + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + if (wl == 5) { + candidate[0] = word[0]; + candidate[1] = word[2]; + candidate[2] = word[1]; + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + } + return ns; +} + +// error is adjacent letter were swapped +int SuggestMgr::swapchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + w_char candidate_utf[MAXSWL]; + char candidate[MAXSWUTF8L]; + w_char * p; + w_char tmpc; + int len = 0; + // try swapping adjacent chars one by one + memcpy (candidate_utf, word, wl * sizeof(w_char)); + for (p = candidate_utf; p < (candidate_utf + wl - 1); p++) { + tmpc = *p; + *p = p[1]; + p[1] = tmpc; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + if (len == 0) len = strlen(candidate); + ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + p[1] = *p; + *p = tmpc; + } + // try double swaps for short words + // ahev -> have, owudl -> would, suodn -> sound + if (wl == 4 || wl == 5) { + candidate_utf[0] = word[1]; + candidate_utf[1] = word[0]; + candidate_utf[2] = word[2]; + candidate_utf[wl - 2] = word[wl - 1]; + candidate_utf[wl - 1] = word[wl - 2]; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + if (wl == 5) { + candidate_utf[0] = word[0]; + candidate_utf[1] = word[2]; + candidate_utf[2] = word[1]; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, len, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + } + return ns; +} + +// error is not adjacent letter were swapped +int SuggestMgr::longswapchar(char ** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + char * p; + char * q; + char tmpc; + int wl=strlen(word); + // try swapping not adjacent chars one by one + strcpy(candidate, word); + for (p = candidate; *p != 0; p++) { + for (q = candidate; *q != 0; q++) { + if (abs(p-q) > 1) { + tmpc = *p; + *p = *q; + *q = tmpc; + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + *q = *p; + *p = tmpc; + } + } + } + return ns; +} + + +// error is adjacent letter were swapped +int SuggestMgr::longswapchar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + w_char candidate_utf[MAXSWL]; + char candidate[MAXSWUTF8L]; + w_char * p; + w_char * q; + w_char tmpc; + // try swapping not adjacent chars + memcpy (candidate_utf, word, wl * sizeof(w_char)); + for (p = candidate_utf; p < (candidate_utf + wl); p++) { + for (q = candidate_utf; q < (candidate_utf + wl); q++) { + if (abs(p-q) > 1) { + tmpc = *p; + *p = *q; + *q = tmpc; + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + *q = *p; + *p = tmpc; + } + } + } + return ns; +} + +// error is a letter was moved +int SuggestMgr::movechar(char ** wlst, const char * word, int ns, int cpdsuggest) +{ + char candidate[MAXSWUTF8L]; + char * p; + char * q; + char tmpc; + + int wl=strlen(word); + // try moving a char + strcpy(candidate, word); + for (p = candidate; *p != 0; p++) { + for (q = p + 1; (*q != 0) && ((q - p) < 10); q++) { + tmpc = *(q-1); + *(q-1) = *q; + *q = tmpc; + if ((q-p) < 2) continue; // omit swap char + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + strcpy(candidate, word); + } + for (p = candidate + wl - 1; p > candidate; p--) { + for (q = p - 1; (q >= candidate) && ((p - q) < 10); q--) { + tmpc = *(q+1); + *(q+1) = *q; + *q = tmpc; + if ((p-q) < 2) continue; // omit swap char + ns = testsug(wlst, candidate, wl, ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + strcpy(candidate, word); + } + return ns; +} + +// error is a letter was moved +int SuggestMgr::movechar_utf(char ** wlst, const w_char * word, int wl, int ns, int cpdsuggest) +{ + w_char candidate_utf[MAXSWL]; + char candidate[MAXSWUTF8L]; + w_char * p; + w_char * q; + w_char tmpc; + // try moving a char + memcpy (candidate_utf, word, wl * sizeof(w_char)); + for (p = candidate_utf; p < (candidate_utf + wl); p++) { + for (q = p + 1; (q < (candidate_utf + wl)) && ((q - p) < 10); q++) { + tmpc = *(q-1); + *(q-1) = *q; + *q = tmpc; + if ((q-p) < 2) continue; // omit swap char + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + memcpy (candidate_utf, word, wl * sizeof(w_char)); + } + for (p = candidate_utf + wl - 1; p > candidate_utf; p--) { + for (q = p - 1; (q >= candidate_utf) && ((p - q) < 10); q--) { + tmpc = *(q+1); + *(q+1) = *q; + *q = tmpc; + if ((p-q) < 2) continue; // omit swap char + u16_u8(candidate, MAXSWUTF8L, candidate_utf, wl); + ns = testsug(wlst, candidate, strlen(candidate), ns, cpdsuggest, NULL, NULL); + if (ns == -1) return -1; + } + memcpy (candidate_utf, word, wl * sizeof(w_char)); + } + return ns; +} + +// generate a set of suggestions for very poorly spelled words +int SuggestMgr::ngsuggest(char** wlst, char * w, int ns, HashMgr* pHMgr) +{ + + int i, j; + int lval; + int sc, scphon; + int lp, lpphon; + int nonbmp = 0; + + if (!pHMgr) return ns; + + // exhaustively search through all root words + // keeping track of the MAX_ROOTS most similar root words + struct hentry * roots[MAX_ROOTS]; + char * rootsphon[MAX_ROOTS]; + int scores[MAX_ROOTS]; + int scoresphon[MAX_ROOTS]; + for (i = 0; i < MAX_ROOTS; i++) { + roots[i] = NULL; + scores[i] = -100 * i; + rootsphon[i] = NULL; + scoresphon[i] = -100 * i; + } + lp = MAX_ROOTS - 1; + lpphon = MAX_ROOTS - 1; + scphon = scoresphon[MAX_ROOTS-1]; + + char w2[MAXWORDUTF8LEN]; + char f[MAXSWUTF8L]; + char * word = w; + + // word reversing wrapper for complex prefixes + if (complexprefixes) { + strcpy(w2, w); + if (utf8) reverseword_utf(w2); else reverseword(w2); + word = w2; + } + + char mw[MAXSWUTF8L]; + w_char u8[MAXSWL]; + int nc = strlen(word); + int n = (utf8) ? u8_u16(u8, MAXSWL, word) : nc; + + // set character based ngram suggestion for words with non-BMP Unicode characters + if (n == -1) { + utf8 = 0; + n = nc; + nonbmp = 1; + } + + struct hentry* hp = NULL; + int col = -1; + phonetable * ph = (pAMgr) ? pAMgr->get_phonetable() : NULL; + char target[MAXSWUTF8L]; + char candidate[MAXSWUTF8L]; + if (ph) { + strcpy(candidate, word); + mkallcap(candidate, csconv); + phonet(candidate, target, n, *ph); + } + + while ((hp = pHMgr->walk_hashtable(col, hp))) { + if ((hp->astr) && (pAMgr) && + (TESTAFF(hp->astr, pAMgr->get_forbiddenword(), hp->alen) || + TESTAFF(hp->astr, ONLYUPCASEFLAG, hp->alen) || + TESTAFF(hp->astr, pAMgr->get_nosuggest(), hp->alen) || + TESTAFF(hp->astr, pAMgr->get_onlyincompound(), hp->alen))) continue; + + sc = ngram(3, word, HENTRY_WORD(hp), NGRAM_LONGER_WORSE + NGRAM_LOWERING) + + leftcommonsubstring(word, HENTRY_WORD(hp)); + + // check special pronounciation + if ((hp->var & H_OPT_PHON) && copy_field(f, HENTRY_DATA(hp), MORPH_PHON)) { + int sc2 = ngram(3, word, f, NGRAM_LONGER_WORSE + NGRAM_LOWERING) + + leftcommonsubstring(word, f); + if (sc2 > sc) sc = sc2; + } + + if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) { + char target2[MAXSWUTF8L]; + strcpy(candidate, HENTRY_WORD(hp)); + mkallcap(candidate, csconv); + phonet(candidate, target2, -1, *ph); + scphon = 2 * ngram(3, target, target2, NGRAM_LONGER_WORSE); + } + + if (sc > scores[lp]) { + scores[lp] = sc; + roots[lp] = hp; + lval = sc; + for (j=0; j < MAX_ROOTS; j++) + if (scores[j] < lval) { + lp = j; + lval = scores[j]; + } + } + + if (scphon > scoresphon[lpphon]) { + scoresphon[lpphon] = scphon; + rootsphon[lpphon] = HENTRY_WORD(hp); + lval = scphon; + for (j=0; j < MAX_ROOTS; j++) + if (scoresphon[j] < lval) { + lpphon = j; + lval = scoresphon[j]; + } + } + } + + // find minimum threshhold for a passable suggestion + // mangle original word three differnt ways + // and score them to generate a minimum acceptable score + int thresh = 0; + for (int sp = 1; sp < 4; sp++) { + if (utf8) { + for (int k=sp; k < n; k+=4) *((unsigned short *) u8 + k) = '*'; + u16_u8(mw, MAXSWUTF8L, u8, n); + thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + NGRAM_LOWERING); + } else { + strcpy(mw, word); + for (int k=sp; k < n; k+=4) *(mw + k) = '*'; + thresh = thresh + ngram(n, word, mw, NGRAM_ANY_MISMATCH + NGRAM_LOWERING); + } + } + thresh = thresh / 3; + thresh--; + + // now expand affixes on each of these root words and + // and use length adjusted ngram scores to select + // possible suggestions + char * guess[MAX_GUESS]; + char * guessorig[MAX_GUESS]; + int gscore[MAX_GUESS]; + for(i=0;iexpand_rootword(glst, MAX_WORDS, HENTRY_WORD(rp), rp->blen, + rp->astr, rp->alen, word, nc, + ((rp->var & H_OPT_PHON) ? copy_field(f, HENTRY_DATA(rp), MORPH_PHON) : NULL)); + + for (int k = 0; k < nw ; k++) { + sc = ngram(n, word, glst[k].word, NGRAM_ANY_MISMATCH + NGRAM_LOWERING) + + leftcommonsubstring(word, glst[k].word); + + if ((sc > thresh)) { + if (sc > gscore[lp]) { + if (guess[lp]) { + free (guess[lp]); + if (guessorig[lp]) { + free(guessorig[lp]); + guessorig[lp] = NULL; + } + } + gscore[lp] = sc; + guess[lp] = glst[k].word; + guessorig[lp] = glst[k].orig; + lval = sc; + for (j=0; j < MAX_GUESS; j++) + if (gscore[j] < lval) { + lp = j; + lval = gscore[j]; + } + } else { + free(glst[k].word); + if (glst[k].orig) free(glst[k].orig); + } + } else { + free(glst[k].word); + if (glst[k].orig) free(glst[k].orig); + } + } + } + } + free(glst); + + // now we are done generating guesses + // sort in order of decreasing score + + + bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS); + if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS); + + // weight suggestions with a similarity index, based on + // the longest common subsequent algorithm and resort + + int is_swap; + for (i=0; i < MAX_GUESS; i++) { + if (guess[i]) { + // lowering guess[i] + char gl[MAXSWUTF8L]; + int len; + if (utf8) { + w_char _w[MAXSWL]; + len = u8_u16(_w, MAXSWL, guess[i]); + mkallsmall_utf(_w, len, langnum); + u16_u8(gl, MAXSWUTF8L, _w, len); + } else { + strcpy(gl, guess[i]); + mkallsmall(gl, csconv); + len = strlen(guess[i]); + } + + int _lcs = lcslen(word, gl); + + // same characters with different casing + if ((n == len) && (n == _lcs)) { + gscore[i] += 2000; + break; + } + + // heuristic weigthing of ngram scores + gscore[i] += + // length of longest common subsequent minus length difference + 2 * _lcs - abs((int) (n - len)) + + // weight length of the left common substring + leftcommonsubstring(word, gl) + + // weight equal character positions + ((_lcs == commoncharacterpositions(word, gl, &is_swap)) ? 1: 0) + + // swap character (not neighboring) + ((is_swap) ? 1000 : 0); + } + } + + bubblesort(&guess[0], &guessorig[0], &gscore[0], MAX_GUESS); + +// phonetic version + if (ph) for (i=0; i < MAX_ROOTS; i++) { + if (rootsphon[i]) { + // lowering rootphon[i] + char gl[MAXSWUTF8L]; + int len; + if (utf8) { + w_char _w[MAXSWL]; + len = u8_u16(_w, MAXSWL, rootsphon[i]); + mkallsmall_utf(_w, len, langnum); + u16_u8(gl, MAXSWUTF8L, _w, len); + } else { + strcpy(gl, rootsphon[i]); + mkallsmall(gl, csconv); + len = strlen(rootsphon[i]); + } + + // heuristic weigthing of ngram scores + scoresphon[i] += 2 * lcslen(word, gl) - abs((int) (n - len)) + + // weight length of the left common substring + leftcommonsubstring(word, gl); + } + } + + if (ph) bubblesort(&rootsphon[0], NULL, &scoresphon[0], MAX_ROOTS); + + // copy over + int oldns = ns; + + int same = 0; + for (i=0; i < MAX_GUESS; i++) { + if (guess[i]) { + if ((ns < oldns + maxngramsugs) && (ns < maxSug) && (!same || (gscore[i] > 1000))) { + int unique = 1; + // leave only excellent suggestions, if exists + if (gscore[i] > 1000) same = 1; + for (j = 0; j < ns; j++) { + // don't suggest previous suggestions or a previous suggestion with prefixes or affixes + if ((!guessorig[i] && strstr(guess[i], wlst[j])) || + (guessorig[i] && strstr(guessorig[i], wlst[j])) || + // check forbidden words + !checkword(guess[i], strlen(guess[i]), 0, NULL, NULL)) unique = 0; + } + if (unique) { + wlst[ns++] = guess[i]; + if (guessorig[i]) { + free(guess[i]); + wlst[ns-1] = guessorig[i]; + } + } else { + free(guess[i]); + if (guessorig[i]) free(guessorig[i]); + } + } else { + free(guess[i]); + if (guessorig[i]) free(guessorig[i]); + } + } + } + + oldns = ns; + if (ph) for (i=0; i < MAX_ROOTS; i++) { + if (rootsphon[i]) { + if ((ns < oldns + MAXPHONSUGS) && (ns < maxSug)) { + int unique = 1; + for (j = 0; j < ns; j++) { + // don't suggest previous suggestions or a previous suggestion with prefixes or affixes + if (strstr(rootsphon[i], wlst[j]) || + // check forbidden words + !checkword(rootsphon[i], strlen(rootsphon[i]), 0, NULL, NULL)) unique = 0; + } + if (unique) wlst[ns++] = mystrdup(rootsphon[i]); + } + } + } + + if (nonbmp) utf8 = 1; + return ns; +} + + +// see if a candidate suggestion is spelled correctly +// needs to check both root words and words with affixes + +// obsolote MySpell-HU modifications: +// return value 2 and 3 marks compounding with hyphen (-) +// `3' marks roots without suffix +int SuggestMgr::checkword(const char * word, int len, int cpdsuggest, int * timer, clock_t * timelimit) +{ + struct hentry * rv=NULL; + int nosuffix = 0; + + // check time limit + if (timer) { + (*timer)--; + if (!(*timer) && timelimit) { + if ((clock() - *timelimit) > TIMELIMIT) return 0; + *timer = MAXPLUSTIMER; + } + } + + if (pAMgr) { + if (cpdsuggest==1) { + if (pAMgr->get_compound()) { + rv = pAMgr->compound_check(word,len,0,0,0,0,NULL,0,NULL,NULL,1); + if (rv) return 3; // XXX obsolote categorisation + } + return 0; + } + + rv = pAMgr->lookup(word); + + if (rv) { + if ((rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen) + || TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen))) return 0; + while (rv) { + if (rv->astr && (TESTAFF(rv->astr,pAMgr->get_needaffix(),rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || + TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) { + rv = rv->next_homonym; + } else break; + } + } else rv = pAMgr->prefix_check(word, len, 0); // only prefix, and prefix + suffix XXX + + if (rv) { + nosuffix=1; + } else { + rv = pAMgr->suffix_check(word, len, 0, NULL, NULL, 0, NULL); // only suffix + } + + if (!rv && pAMgr->have_contclass()) { + rv = pAMgr->suffix_check_twosfx(word, len, 0, NULL, FLAG_NULL); + if (!rv) rv = pAMgr->prefix_check_twosfx(word, len, 1, FLAG_NULL); + } + + // check forbidden words + if ((rv) && (rv->astr) && (TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen) || + TESTAFF(rv->astr, ONLYUPCASEFLAG, rv->alen) || + TESTAFF(rv->astr,pAMgr->get_nosuggest(),rv->alen) || + TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) return 0; + + if (rv) { // XXX obsolote + if ((pAMgr->get_compoundflag()) && + TESTAFF(rv->astr, pAMgr->get_compoundflag(), rv->alen)) return 2 + nosuffix; + return 1; + } + } + return 0; +} + +int SuggestMgr::check_forbidden(const char * word, int len) +{ + struct hentry * rv = NULL; + + if (pAMgr) { + rv = pAMgr->lookup(word); + if (rv && rv->astr && (TESTAFF(rv->astr,pAMgr->get_needaffix(),rv->alen) || + TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) rv = NULL; + if (!(pAMgr->prefix_check(word,len,1))) + rv = pAMgr->suffix_check(word,len, 0, NULL, NULL, 0, NULL); // prefix+suffix, suffix + // check forbidden words + if ((rv) && (rv->astr) && TESTAFF(rv->astr,pAMgr->get_forbiddenword(),rv->alen)) return 1; + } + return 0; +} + +#ifdef HUNSPELL_EXPERIMENTAL +// suggest possible stems +int SuggestMgr::suggest_pos_stems(char*** slst, const char * w, int nsug) +{ + char ** wlst; + + struct hentry * rv = NULL; + + char w2[MAXSWUTF8L]; + const char * word = w; + + // word reversing wrapper for complex prefixes + if (complexprefixes) { + strcpy(w2, w); + if (utf8) reverseword_utf(w2); else reverseword(w2); + word = w2; + } + + int wl = strlen(word); + + + if (*slst) { + wlst = *slst; + } else { + wlst = (char **) calloc(maxSug, sizeof(char *)); + if (wlst == NULL) return -1; + } + + rv = pAMgr->suffix_check(word, wl, 0, NULL, wlst, maxSug, &nsug); + + // delete dash from end of word + if (nsug > 0) { + for (int j=0; j < nsug; j++) { + if (wlst[j][strlen(wlst[j]) - 1] == '-') wlst[j][strlen(wlst[j]) - 1] = '\0'; + } + } + + *slst = wlst; + return nsug; +} +#endif // END OF HUNSPELL_EXPERIMENTAL CODE + + +char * SuggestMgr::suggest_morph(const char * w) +{ + char result[MAXLNLEN]; + char * r = (char *) result; + char * st; + + struct hentry * rv = NULL; + + *result = '\0'; + + if (! pAMgr) return NULL; + + char w2[MAXSWUTF8L]; + const char * word = w; + + // word reversing wrapper for complex prefixes + if (complexprefixes) { + strcpy(w2, w); + if (utf8) reverseword_utf(w2); else reverseword(w2); + word = w2; + } + + rv = pAMgr->lookup(word); + + while (rv) { + if ((!rv->astr) || !(TESTAFF(rv->astr, pAMgr->get_forbiddenword(), rv->alen) || + TESTAFF(rv->astr, pAMgr->get_needaffix(), rv->alen) || + TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) { + if (!HENTRY_FIND(rv, MORPH_STEM)) { + strcat(result, " "); + strcat(result, MORPH_STEM); + strcat(result, word); + } + if (HENTRY_DATA(rv)) { + strcat(result, " "); + strcat(result, HENTRY_DATA(rv)); + } + strcat(result, "\n"); + } + rv = rv->next_homonym; + } + + st = pAMgr->affix_check_morph(word,strlen(word)); + if (st) { + strcat(result, st); + free(st); + } + + if (pAMgr->get_compound() && (*result == '\0')) + pAMgr->compound_check_morph(word, strlen(word), + 0, 0, 100, 0,NULL, 0, &r, NULL); + + return (*result) ? mystrdup(line_uniq(result, MSEP_REC)) : NULL; +} + +#ifdef HUNSPELL_EXPERIMENTAL +char * SuggestMgr::suggest_morph_for_spelling_error(const char * word) +{ + char * p = NULL; + char ** wlst = (char **) calloc(maxSug, sizeof(char *)); + if (!**wlst) return NULL; + // we will use only the first suggestion + for (int i = 0; i < maxSug - 1; i++) wlst[i] = ""; + int ns = suggest(&wlst, word, maxSug - 1, NULL); + if (ns == maxSug) { + p = suggest_morph(wlst[maxSug - 1]); + free(wlst[maxSug - 1]); + } + if (wlst) free(wlst); + return p; +} +#endif // END OF HUNSPELL_EXPERIMENTAL CODE + +/* affixation */ +char * SuggestMgr::suggest_hentry_gen(hentry * rv, char * pattern) +{ + char result[MAXLNLEN]; + *result = '\0'; + int sfxcount = get_sfxcount(pattern); + +// if (get_sfxcount(HENTRY_DATA(rv)) > sfxcount) return NULL; + + if (HENTRY_DATA(rv)) { + char * aff = pAMgr->morphgen(HENTRY_WORD(rv), rv->blen, rv->astr, rv->alen, + HENTRY_DATA(rv), pattern, 0); + if (aff) { + strcat(result, aff); + strcat(result, "\n"); + free(aff); + } + } + + // check all allomorphs + char allomorph[MAXLNLEN]; + char * p = NULL; + if (HENTRY_DATA(rv)) p = strstr(HENTRY_DATA(rv), MORPH_ALLOMORPH); + while (p) { + struct hentry * rv2 = NULL; + p += MORPH_TAG_LEN; + int plen = fieldlen(p); + strncpy(allomorph, p, plen); + allomorph[plen] = '\0'; + rv2 = pAMgr->lookup(allomorph); + while (rv2) { +// if (HENTRY_DATA(rv2) && get_sfxcount(HENTRY_DATA(rv2)) <= sfxcount) { + if (HENTRY_DATA(rv2)) { + char * st = strstr(HENTRY_DATA(rv2), MORPH_STEM); + if (st && (strncmp(st + MORPH_TAG_LEN, + HENTRY_WORD(rv), fieldlen(st + MORPH_TAG_LEN)) == 0)) { + char * aff = pAMgr->morphgen(HENTRY_WORD(rv2), rv2->blen, rv2->astr, rv2->alen, + HENTRY_DATA(rv2), pattern, 0); + if (aff) { + strcat(result, aff); + strcat(result, "\n"); + free(aff); + } + } + } + rv2 = rv2->next_homonym; + } + p = strstr(p + plen, MORPH_ALLOMORPH); + } + + return (*result) ? mystrdup(result) : NULL; +} + +char * SuggestMgr::suggest_gen(char ** desc, int n, char * pattern) { + char result[MAXLNLEN]; + char result2[MAXLNLEN]; + char newpattern[MAXLNLEN]; + *newpattern = '\0'; + if (n == 0) return 0; + *result2 = '\0'; + struct hentry * rv = NULL; + if (!pAMgr) return NULL; + +// search affixed forms with and without derivational suffixes + while(1) { + + for (int k = 0; k < n; k++) { + *result = '\0'; + // add compound word parts (except the last one) + char * s = (char *) desc[k]; + char * part = strstr(s, MORPH_PART); + if (part) { + char * nextpart = strstr(part + 1, MORPH_PART); + while (nextpart) { + copy_field(result + strlen(result), part, MORPH_PART); + part = nextpart; + nextpart = strstr(part + 1, MORPH_PART); + } + s = part; + } + + char **pl; + char tok[MAXLNLEN]; + strcpy(tok, s); + char * alt = strstr(tok, " | "); + while (alt) { + alt[1] = MSEP_ALT; + alt = strstr(alt, " | "); + } + int pln = line_tok(tok, &pl, MSEP_ALT); + for (int i = 0; i < pln; i++) { + // remove inflectional and terminal suffixes + char * is = strstr(pl[i], MORPH_INFL_SFX); + if (is) *is = '\0'; + char * ts = strstr(pl[i], MORPH_TERM_SFX); + while (ts) { + *ts = '_'; + ts = strstr(pl[i], MORPH_TERM_SFX); + } + char * st = strstr(s, MORPH_STEM); + if (st) { + copy_field(tok, st, MORPH_STEM); + rv = pAMgr->lookup(tok); + while (rv) { + char newpat[MAXLNLEN]; + strcpy(newpat, pl[i]); + strcat(newpat, pattern); + char * sg = suggest_hentry_gen(rv, newpat); + if (!sg) sg = suggest_hentry_gen(rv, pattern); + if (sg) { + char ** gen; + int genl = line_tok(sg, &gen, MSEP_REC); + free(sg); + sg = NULL; + for (int j = 0; j < genl; j++) { + if (strstr(pl[i], MORPH_SURF_PFX)) { + int r2l = strlen(result2); + result2[r2l] = MSEP_REC; + strcpy(result2 + r2l + 1, result); + copy_field(result2 + strlen(result2), pl[i], MORPH_SURF_PFX); + strcat(result2, gen[j]); + } else { + sprintf(result2 + strlen(result2), "%c%s%s", + MSEP_REC, result, gen[j]); + } + } + freelist(&gen, genl); + } + rv = rv->next_homonym; + } + } + } + freelist(&pl, pln); + } + + if (*result2 || !strstr(pattern, MORPH_DERI_SFX)) break; + strcpy(newpattern, pattern); + pattern = newpattern; + char * ds = strstr(pattern, MORPH_DERI_SFX); + while (ds) { + strncpy(ds, MORPH_TERM_SFX, MORPH_TAG_LEN); + ds = strstr(pattern, MORPH_DERI_SFX); + } + } + return (*result2 ? mystrdup(result2) : NULL); +} + + +// generate an n-gram score comparing s1 and s2 +int SuggestMgr::ngram(int n, char * s1, const char * s2, int opt) +{ + int nscore = 0; + int ns; + int l1; + int l2; + + if (utf8) { + w_char su1[MAXSWL]; + w_char su2[MAXSWL]; + l1 = u8_u16(su1, MAXSWL, s1); + l2 = u8_u16(su2, MAXSWL, s2); + if ((l2 <= 0) || (l1 == -1)) return 0; + // lowering dictionary word + if (opt & NGRAM_LOWERING) mkallsmall_utf(su2, l2, langnum); + for (int j = 1; j <= n; j++) { + ns = 0; + for (int i = 0; i <= (l1-j); i++) { + for (int l = 0; l <= (l2-j); l++) { + int k; + for (k = 0; (k < j); k++) { + w_char * c1 = su1 + i + k; + w_char * c2 = su2 + l + k; + if ((c1->l != c2->l) || (c1->h != c2->h)) break; + } + if (k == j) { + ns++; + break; + } + } + } + nscore = nscore + ns; + if (ns < 2) break; + } + } else { + char t[MAXSWUTF8L]; + l1 = strlen(s1); + l2 = strlen(s2); + if (l2 == 0) return 0; + strcpy(t, s2); + if (opt & NGRAM_LOWERING) mkallsmall(t, csconv); + for (int j = 1; j <= n; j++) { + ns = 0; + for (int i = 0; i <= (l1-j); i++) { + char c = *(s1 + i + j); + *(s1 + i + j) = '\0'; + if (strstr(t,(s1+i))) ns++; + *(s1 + i + j ) = c; + } + nscore = nscore + ns; + if (ns < 2) break; + } + } + + ns = 0; + if (opt & NGRAM_LONGER_WORSE) ns = (l2-l1)-2; + if (opt & NGRAM_ANY_MISMATCH) ns = abs(l2-l1)-2; + ns = (nscore - ((ns > 0) ? ns : 0)); + return ns; +} + +// length of the left common substring of s1 and (decapitalised) s2 +int SuggestMgr::leftcommonsubstring(char * s1, const char * s2) { + if (utf8) { + w_char su1[MAXSWL]; + w_char su2[MAXSWL]; + // decapitalize dictionary word + if (complexprefixes) { + int l1 = u8_u16(su1, MAXSWL, s1); + int l2 = u8_u16(su2, MAXSWL, s2); + if (*((short *)su1+l1-1) == *((short *)su2+l2-1)) return 1; + } else { + int i; + u8_u16(su1, 1, s1); + u8_u16(su2, 1, s2); + unsigned short idx = (su2->h << 8) + su2->l; + if (*((short *)su1) != *((short *)su2) && + (*((unsigned short *)su1) != unicodetolower(idx, langnum))) return 0; + int l1 = u8_u16(su1, MAXSWL, s1); + int l2 = u8_u16(su2, MAXSWL, s2); + for(i = 1; (i < l1) && (i < l2) && + (*((short *)(su1 + i)) == *((short *)(su2 + i))); i++); + return i; + } + } else { + if (complexprefixes) { + int l1 = strlen(s1); + int l2 = strlen(s2); + if (*(s2+l1-1) == *(s2+l2-1)) return 1; + } else { + char * olds = s1; + // decapitalise dictionary word + if ((*s1 != *s2) && (*s1 != csconv[((unsigned char)*s2)].clower)) return 0; + do { + s1++; s2++; + } while ((*s1 == *s2) && (*s1 != '\0')); + return s1 - olds; + } + } + return 0; +} + +int SuggestMgr::commoncharacterpositions(char * s1, const char * s2, int * is_swap) { + int num = 0; + int diff = 0; + int diffpos[2]; + *is_swap = 0; + if (utf8) { + w_char su1[MAXSWL]; + w_char su2[MAXSWL]; + int l1 = u8_u16(su1, MAXSWL, s1); + int l2 = u8_u16(su2, MAXSWL, s2); + // decapitalize dictionary word + if (complexprefixes) { + mkallsmall_utf(su2+l2-1, 1, langnum); + } else { + mkallsmall_utf(su2, 1, langnum); + } + for (int i = 0; (i < l1) && (i < l2); i++) { + if (((short *) su1)[i] == ((short *) su2)[i]) { + num++; + } else { + if (diff < 2) diffpos[diff] = i; + diff++; + } + } + if ((diff == 2) && (l1 == l2) && + (((short *) su1)[diffpos[0]] == ((short *) su2)[diffpos[1]]) && + (((short *) su1)[diffpos[1]] == ((short *) su2)[diffpos[0]])) *is_swap = 1; + } else { + int i; + char t[MAXSWUTF8L]; + strcpy(t, s2); + // decapitalize dictionary word + if (complexprefixes) { + int l2 = strlen(t); + *(t+l2-1) = csconv[((unsigned char)*(t+l2-1))].clower; + } else { + mkallsmall(t, csconv); + } + for (i = 0; (*(s1+i) != 0) && (*(t+i) != 0); i++) { + if (*(s1+i) == *(t+i)) { + num++; + } else { + if (diff < 2) diffpos[diff] = i; + diff++; + } + } + if ((diff == 2) && (*(s1+i) == 0) && (*(t+i) == 0) && + (*(s1+diffpos[0]) == *(t+diffpos[1])) && + (*(s1+diffpos[1]) == *(t+diffpos[0]))) *is_swap = 1; + } + return num; +} + +int SuggestMgr::mystrlen(const char * word) { + if (utf8) { + w_char w[MAXSWL]; + return u8_u16(w, MAXSWL, word); + } else return strlen(word); +} + +// sort in decreasing order of score +void SuggestMgr::bubblesort(char** rword, char** rword2, int* rsc, int n ) +{ + int m = 1; + while (m < n) { + int j = m; + while (j > 0) { + if (rsc[j-1] < rsc[j]) { + int sctmp = rsc[j-1]; + char * wdtmp = rword[j-1]; + rsc[j-1] = rsc[j]; + rword[j-1] = rword[j]; + rsc[j] = sctmp; + rword[j] = wdtmp; + if (rword2) { + wdtmp = rword2[j-1]; + rword2[j-1] = rword2[j]; + rword2[j] = wdtmp; + } + j--; + } else break; + } + m++; + } + return; +} + +// longest common subsequence +void SuggestMgr::lcs(const char * s, const char * s2, int * l1, int * l2, char ** result) { + int n, m; + w_char su[MAXSWL]; + w_char su2[MAXSWL]; + char * b; + char * c; + int i; + int j; + if (utf8) { + m = u8_u16(su, MAXSWL, s); + n = u8_u16(su2, MAXSWL, s2); + } else { + m = strlen(s); + n = strlen(s2); + } + c = (char *) malloc((m + 1) * (n + 1)); + b = (char *) malloc((m + 1) * (n + 1)); + if (!c || !b) { + if (c) free(c); + if (b) free(b); + *result = NULL; + return; + } + for (i = 1; i <= m; i++) c[i*(n+1)] = 0; + for (j = 0; j <= n; j++) c[j] = 0; + for (i = 1; i <= m; i++) { + for (j = 1; j <= n; j++) { + if ((utf8) && (*((short *) su+i-1) == *((short *)su2+j-1)) + || (!utf8) && ((*(s+i-1)) == (*(s2+j-1)))) { + c[i*(n+1) + j] = c[(i-1)*(n+1) + j-1]+1; + b[i*(n+1) + j] = LCS_UPLEFT; + } else if (c[(i-1)*(n+1) + j] >= c[i*(n+1) + j-1]) { + c[i*(n+1) + j] = c[(i-1)*(n+1) + j]; + b[i*(n+1) + j] = LCS_UP; + } else { + c[i*(n+1) + j] = c[i*(n+1) + j-1]; + b[i*(n+1) + j] = LCS_LEFT; + } + } + } + *result = b; + free(c); + *l1 = m; + *l2 = n; +} + +int SuggestMgr::lcslen(const char * s, const char* s2) { + int m; + int n; + int i; + int j; + char * result; + int len = 0; + lcs(s, s2, &m, &n, &result); + if (!result) return 0; + i = m; + j = n; + while ((i != 0) && (j != 0)) { + if (result[i*(n+1) + j] == LCS_UPLEFT) { + len++; + i--; + j--; + } else if (result[i*(n+1) + j] == LCS_UP) { + i--; + } else j--; + } + free(result); + return len; +} diff --git a/hunspell/src/hunspell/suggestmgr.hxx b/hunspell/src/hunspell/suggestmgr.hxx new file mode 100644 index 000000000..d22884f4a --- /dev/null +++ b/hunspell/src/hunspell/suggestmgr.hxx @@ -0,0 +1,107 @@ +#ifndef _SUGGESTMGR_HXX_ +#define _SUGGESTMGR_HXX_ + +#define MAXSWL 100 +#define MAXSWUTF8L (MAXSWL * 4) +#define MAX_ROOTS 100 +#define MAX_WORDS 100 +#define MAX_GUESS 200 +#define MAXNGRAMSUGS 4 +#define MAXPHONSUGS 2 + +// timelimit: max ~1/4 sec (process time on Linux) for a time consuming function +#define TIMELIMIT (CLOCKS_PER_SEC >> 2) +#define MINTIMER 100 +#define MAXPLUSTIMER 100 + +#define NGRAM_LONGER_WORSE (1 << 0) +#define NGRAM_ANY_MISMATCH (1 << 1) +#define NGRAM_LOWERING (1 << 2) + +#include "atypes.hxx" +#include "affixmgr.hxx" +#include "hashmgr.hxx" +#include "langnum.hxx" +#include + +enum { LCS_UP, LCS_LEFT, LCS_UPLEFT }; + +class SuggestMgr +{ + char * ckey; + int ckeyl; + w_char * ckey_utf; + + char * ctry; + int ctryl; + w_char * ctry_utf; + + AffixMgr* pAMgr; + int maxSug; + struct cs_info * csconv; + int utf8; + int langnum; + int nosplitsugs; + int maxngramsugs; + int complexprefixes; + + +public: + SuggestMgr(const char * tryme, int maxn, AffixMgr *aptr); + ~SuggestMgr(); + + int suggest(char*** slst, const char * word, int nsug, int * onlycmpdsug); + int ngsuggest(char ** wlst, char * word, int ns, HashMgr* pHMgr); + int suggest_auto(char*** slst, const char * word, int nsug); + int suggest_stems(char*** slst, const char * word, int nsug); + int suggest_pos_stems(char*** slst, const char * word, int nsug); + + char * suggest_morph(const char * word); + char * suggest_gen(char ** pl, int pln, char * pattern); + char * suggest_morph_for_spelling_error(const char * word); + +private: + int testsug(char** wlst, const char * candidate, int wl, int ns, int cpdsuggest, + int * timer, clock_t * timelimit); + int checkword(const char *, int, int, int *, clock_t *); + int check_forbidden(const char *, int); + + int capchars(char **, const char *, int, int); + int replchars(char**, const char *, int, int); + int doubletwochars(char**, const char *, int, int); + int forgotchar(char **, const char *, int, int); + int swapchar(char **, const char *, int, int); + int longswapchar(char **, const char *, int, int); + int movechar(char **, const char *, int, int); + int extrachar(char **, const char *, int, int); + int badcharkey(char **, const char *, int, int); + int badchar(char **, const char *, int, int); + int twowords(char **, const char *, int, int); + int fixstems(char **, const char *, int); + + int capchars_utf(char **, const w_char *, int wl, int, int); + int doubletwochars_utf(char**, const w_char *, int wl, int, int); + int forgotchar_utf(char**, const w_char *, int wl, int, int); + int extrachar_utf(char**, const w_char *, int wl, int, int); + int badcharkey_utf(char **, const w_char *, int wl, int, int); + int badchar_utf(char **, const w_char *, int wl, int, int); + int swapchar_utf(char **, const w_char *, int wl, int, int); + int longswapchar_utf(char **, const w_char *, int, int, int); + int movechar_utf(char **, const w_char *, int, int, int); + + int mapchars(char**, const char *, int, int); + int map_related(const char *, int, char ** wlst, int, int, const mapentry*, int, int *, clock_t *); + int map_related_utf(w_char *, int, int, int, char ** wlst, int, const mapentry*, int, int *, clock_t *); + int ngram(int n, char * s1, const char * s2, int opt); + int mystrlen(const char * word); + int leftcommonsubstring(char * s1, const char * s2); + int commoncharacterpositions(char * s1, const char * s2, int * is_swap); + void bubblesort( char ** rwd, char ** rwd2, int * rsc, int n); + void lcs(const char * s, const char * s2, int * l1, int * l2, char ** result); + int lcslen(const char * s, const char* s2); + char * suggest_hentry_gen(hentry * rv, char * pattern); + +}; + +#endif + diff --git a/hunspell/src/hunspell/utf_info.cxx b/hunspell/src/hunspell/utf_info.cxx new file mode 100644 index 000000000..0d86d2ad2 --- /dev/null +++ b/hunspell/src/hunspell/utf_info.cxx @@ -0,0 +1,8506 @@ +#include "csutil.hxx" +/* fields: Unicode letter, toupper, tolower */ +static struct unicode_info utf_lst[] = { +{ 0x0041, 0x0041, 0x0061 }, +{ 0x0042, 0x0042, 0x0062 }, +{ 0x0043, 0x0043, 0x0063 }, +{ 0x0044, 0x0044, 0x0064 }, +{ 0x0045, 0x0045, 0x0065 }, +{ 0x0046, 0x0046, 0x0066 }, +{ 0x0047, 0x0047, 0x0067 }, +{ 0x0048, 0x0048, 0x0068 }, +{ 0x0049, 0x0049, 0x0069 }, +{ 0x004A, 0x004A, 0x006A }, +{ 0x004B, 0x004B, 0x006B }, +{ 0x004C, 0x004C, 0x006C }, +{ 0x004D, 0x004D, 0x006D }, +{ 0x004E, 0x004E, 0x006E }, +{ 0x004F, 0x004F, 0x006F }, +{ 0x0050, 0x0050, 0x0070 }, +{ 0x0051, 0x0051, 0x0071 }, +{ 0x0052, 0x0052, 0x0072 }, +{ 0x0053, 0x0053, 0x0073 }, +{ 0x0054, 0x0054, 0x0074 }, +{ 0x0055, 0x0055, 0x0075 }, +{ 0x0056, 0x0056, 0x0076 }, +{ 0x0057, 0x0057, 0x0077 }, +{ 0x0058, 0x0058, 0x0078 }, +{ 0x0059, 0x0059, 0x0079 }, +{ 0x005A, 0x005A, 0x007A }, +{ 0x0061, 0x0041, 0x0061 }, +{ 0x0062, 0x0042, 0x0062 }, +{ 0x0063, 0x0043, 0x0063 }, +{ 0x0064, 0x0044, 0x0064 }, +{ 0x0065, 0x0045, 0x0065 }, +{ 0x0066, 0x0046, 0x0066 }, +{ 0x0067, 0x0047, 0x0067 }, +{ 0x0068, 0x0048, 0x0068 }, +{ 0x0069, 0x0049, 0x0069 }, +{ 0x006A, 0x004A, 0x006A }, +{ 0x006B, 0x004B, 0x006B }, +{ 0x006C, 0x004C, 0x006C }, +{ 0x006D, 0x004D, 0x006D }, +{ 0x006E, 0x004E, 0x006E }, +{ 0x006F, 0x004F, 0x006F }, +{ 0x0070, 0x0050, 0x0070 }, +{ 0x0071, 0x0051, 0x0071 }, +{ 0x0072, 0x0052, 0x0072 }, +{ 0x0073, 0x0053, 0x0073 }, +{ 0x0074, 0x0054, 0x0074 }, +{ 0x0075, 0x0055, 0x0075 }, +{ 0x0076, 0x0056, 0x0076 }, +{ 0x0077, 0x0057, 0x0077 }, +{ 0x0078, 0x0058, 0x0078 }, +{ 0x0079, 0x0059, 0x0079 }, +{ 0x007A, 0x005A, 0x007A }, +{ 0x00AA, 0x00AA, 0x00AA }, +{ 0x00B5, 0x039C, 0x00B5 }, +{ 0x00BA, 0x00BA, 0x00BA }, +{ 0x00C0, 0x00C0, 0x00E0 }, +{ 0x00C1, 0x00C1, 0x00E1 }, +{ 0x00C2, 0x00C2, 0x00E2 }, +{ 0x00C3, 0x00C3, 0x00E3 }, +{ 0x00C4, 0x00C4, 0x00E4 }, +{ 0x00C5, 0x00C5, 0x00E5 }, +{ 0x00C6, 0x00C6, 0x00E6 }, +{ 0x00C7, 0x00C7, 0x00E7 }, +{ 0x00C8, 0x00C8, 0x00E8 }, +{ 0x00C9, 0x00C9, 0x00E9 }, +{ 0x00CA, 0x00CA, 0x00EA }, +{ 0x00CB, 0x00CB, 0x00EB }, +{ 0x00CC, 0x00CC, 0x00EC }, +{ 0x00CD, 0x00CD, 0x00ED }, +{ 0x00CE, 0x00CE, 0x00EE }, +{ 0x00CF, 0x00CF, 0x00EF }, +{ 0x00D0, 0x00D0, 0x00F0 }, +{ 0x00D1, 0x00D1, 0x00F1 }, +{ 0x00D2, 0x00D2, 0x00F2 }, +{ 0x00D3, 0x00D3, 0x00F3 }, +{ 0x00D4, 0x00D4, 0x00F4 }, +{ 0x00D5, 0x00D5, 0x00F5 }, +{ 0x00D6, 0x00D6, 0x00F6 }, +{ 0x00D8, 0x00D8, 0x00F8 }, +{ 0x00D9, 0x00D9, 0x00F9 }, +{ 0x00DA, 0x00DA, 0x00FA }, +{ 0x00DB, 0x00DB, 0x00FB }, +{ 0x00DC, 0x00DC, 0x00FC }, +{ 0x00DD, 0x00DD, 0x00FD }, +{ 0x00DE, 0x00DE, 0x00FE }, +{ 0x00DF, 0x00DF, 0x00DF }, +{ 0x00E0, 0x00C0, 0x00E0 }, +{ 0x00E1, 0x00C1, 0x00E1 }, +{ 0x00E2, 0x00C2, 0x00E2 }, +{ 0x00E3, 0x00C3, 0x00E3 }, +{ 0x00E4, 0x00C4, 0x00E4 }, +{ 0x00E5, 0x00C5, 0x00E5 }, +{ 0x00E6, 0x00C6, 0x00E6 }, +{ 0x00E7, 0x00C7, 0x00E7 }, +{ 0x00E8, 0x00C8, 0x00E8 }, +{ 0x00E9, 0x00C9, 0x00E9 }, +{ 0x00EA, 0x00CA, 0x00EA }, +{ 0x00EB, 0x00CB, 0x00EB }, +{ 0x00EC, 0x00CC, 0x00EC }, +{ 0x00ED, 0x00CD, 0x00ED }, +{ 0x00EE, 0x00CE, 0x00EE }, +{ 0x00EF, 0x00CF, 0x00EF }, +{ 0x00F0, 0x00D0, 0x00F0 }, +{ 0x00F1, 0x00D1, 0x00F1 }, +{ 0x00F2, 0x00D2, 0x00F2 }, +{ 0x00F3, 0x00D3, 0x00F3 }, +{ 0x00F4, 0x00D4, 0x00F4 }, +{ 0x00F5, 0x00D5, 0x00F5 }, +{ 0x00F6, 0x00D6, 0x00F6 }, +{ 0x00F8, 0x00D8, 0x00F8 }, +{ 0x00F9, 0x00D9, 0x00F9 }, +{ 0x00FA, 0x00DA, 0x00FA }, +{ 0x00FB, 0x00DB, 0x00FB }, +{ 0x00FC, 0x00DC, 0x00FC }, +{ 0x00FD, 0x00DD, 0x00FD }, +{ 0x00FE, 0x00DE, 0x00FE }, +{ 0x00FF, 0x0178, 0x00FF }, +{ 0x0100, 0x0100, 0x0101 }, +{ 0x0101, 0x0100, 0x0101 }, +{ 0x0102, 0x0102, 0x0103 }, +{ 0x0103, 0x0102, 0x0103 }, +{ 0x0104, 0x0104, 0x0105 }, +{ 0x0105, 0x0104, 0x0105 }, +{ 0x0106, 0x0106, 0x0107 }, +{ 0x0107, 0x0106, 0x0107 }, +{ 0x0108, 0x0108, 0x0109 }, +{ 0x0109, 0x0108, 0x0109 }, +{ 0x010A, 0x010A, 0x010B }, +{ 0x010B, 0x010A, 0x010B }, +{ 0x010C, 0x010C, 0x010D }, +{ 0x010D, 0x010C, 0x010D }, +{ 0x010E, 0x010E, 0x010F }, +{ 0x010F, 0x010E, 0x010F }, +{ 0x0110, 0x0110, 0x0111 }, +{ 0x0111, 0x0110, 0x0111 }, +{ 0x0112, 0x0112, 0x0113 }, +{ 0x0113, 0x0112, 0x0113 }, +{ 0x0114, 0x0114, 0x0115 }, +{ 0x0115, 0x0114, 0x0115 }, +{ 0x0116, 0x0116, 0x0117 }, +{ 0x0117, 0x0116, 0x0117 }, +{ 0x0118, 0x0118, 0x0119 }, +{ 0x0119, 0x0118, 0x0119 }, +{ 0x011A, 0x011A, 0x011B }, +{ 0x011B, 0x011A, 0x011B }, +{ 0x011C, 0x011C, 0x011D }, +{ 0x011D, 0x011C, 0x011D }, +{ 0x011E, 0x011E, 0x011F }, +{ 0x011F, 0x011E, 0x011F }, +{ 0x0120, 0x0120, 0x0121 }, +{ 0x0121, 0x0120, 0x0121 }, +{ 0x0122, 0x0122, 0x0123 }, +{ 0x0123, 0x0122, 0x0123 }, +{ 0x0124, 0x0124, 0x0125 }, +{ 0x0125, 0x0124, 0x0125 }, +{ 0x0126, 0x0126, 0x0127 }, +{ 0x0127, 0x0126, 0x0127 }, +{ 0x0128, 0x0128, 0x0129 }, +{ 0x0129, 0x0128, 0x0129 }, +{ 0x012A, 0x012A, 0x012B }, +{ 0x012B, 0x012A, 0x012B }, +{ 0x012C, 0x012C, 0x012D }, +{ 0x012D, 0x012C, 0x012D }, +{ 0x012E, 0x012E, 0x012F }, +{ 0x012F, 0x012E, 0x012F }, +{ 0x0130, 0x0130, 0x0069 }, +{ 0x0131, 0x0049, 0x0131 }, +{ 0x0132, 0x0132, 0x0133 }, +{ 0x0133, 0x0132, 0x0133 }, +{ 0x0134, 0x0134, 0x0135 }, +{ 0x0135, 0x0134, 0x0135 }, +{ 0x0136, 0x0136, 0x0137 }, +{ 0x0137, 0x0136, 0x0137 }, +{ 0x0138, 0x0138, 0x0138 }, +{ 0x0139, 0x0139, 0x013A }, +{ 0x013A, 0x0139, 0x013A }, +{ 0x013B, 0x013B, 0x013C }, +{ 0x013C, 0x013B, 0x013C }, +{ 0x013D, 0x013D, 0x013E }, +{ 0x013E, 0x013D, 0x013E }, +{ 0x013F, 0x013F, 0x0140 }, +{ 0x0140, 0x013F, 0x0140 }, +{ 0x0141, 0x0141, 0x0142 }, +{ 0x0142, 0x0141, 0x0142 }, +{ 0x0143, 0x0143, 0x0144 }, +{ 0x0144, 0x0143, 0x0144 }, +{ 0x0145, 0x0145, 0x0146 }, +{ 0x0146, 0x0145, 0x0146 }, +{ 0x0147, 0x0147, 0x0148 }, +{ 0x0148, 0x0147, 0x0148 }, +{ 0x0149, 0x0149, 0x0149 }, +{ 0x014A, 0x014A, 0x014B }, +{ 0x014B, 0x014A, 0x014B }, +{ 0x014C, 0x014C, 0x014D }, +{ 0x014D, 0x014C, 0x014D }, +{ 0x014E, 0x014E, 0x014F }, +{ 0x014F, 0x014E, 0x014F }, +{ 0x0150, 0x0150, 0x0151 }, +{ 0x0151, 0x0150, 0x0151 }, +{ 0x0152, 0x0152, 0x0153 }, +{ 0x0153, 0x0152, 0x0153 }, +{ 0x0154, 0x0154, 0x0155 }, +{ 0x0155, 0x0154, 0x0155 }, +{ 0x0156, 0x0156, 0x0157 }, +{ 0x0157, 0x0156, 0x0157 }, +{ 0x0158, 0x0158, 0x0159 }, +{ 0x0159, 0x0158, 0x0159 }, +{ 0x015A, 0x015A, 0x015B }, +{ 0x015B, 0x015A, 0x015B }, +{ 0x015C, 0x015C, 0x015D }, +{ 0x015D, 0x015C, 0x015D }, +{ 0x015E, 0x015E, 0x015F }, +{ 0x015F, 0x015E, 0x015F }, +{ 0x0160, 0x0160, 0x0161 }, +{ 0x0161, 0x0160, 0x0161 }, +{ 0x0162, 0x0162, 0x0163 }, +{ 0x0163, 0x0162, 0x0163 }, +{ 0x0164, 0x0164, 0x0165 }, +{ 0x0165, 0x0164, 0x0165 }, +{ 0x0166, 0x0166, 0x0167 }, +{ 0x0167, 0x0166, 0x0167 }, +{ 0x0168, 0x0168, 0x0169 }, +{ 0x0169, 0x0168, 0x0169 }, +{ 0x016A, 0x016A, 0x016B }, +{ 0x016B, 0x016A, 0x016B }, +{ 0x016C, 0x016C, 0x016D }, +{ 0x016D, 0x016C, 0x016D }, +{ 0x016E, 0x016E, 0x016F }, +{ 0x016F, 0x016E, 0x016F }, +{ 0x0170, 0x0170, 0x0171 }, +{ 0x0171, 0x0170, 0x0171 }, +{ 0x0172, 0x0172, 0x0173 }, +{ 0x0173, 0x0172, 0x0173 }, +{ 0x0174, 0x0174, 0x0175 }, +{ 0x0175, 0x0174, 0x0175 }, +{ 0x0176, 0x0176, 0x0177 }, +{ 0x0177, 0x0176, 0x0177 }, +{ 0x0178, 0x0178, 0x00FF }, +{ 0x0179, 0x0179, 0x017A }, +{ 0x017A, 0x0179, 0x017A }, +{ 0x017B, 0x017B, 0x017C }, +{ 0x017C, 0x017B, 0x017C }, +{ 0x017D, 0x017D, 0x017E }, +{ 0x017E, 0x017D, 0x017E }, +{ 0x017F, 0x0053, 0x017F }, +{ 0x0180, 0x0180, 0x0180 }, +{ 0x0181, 0x0181, 0x0253 }, +{ 0x0182, 0x0182, 0x0183 }, +{ 0x0183, 0x0182, 0x0183 }, +{ 0x0184, 0x0184, 0x0185 }, +{ 0x0185, 0x0184, 0x0185 }, +{ 0x0186, 0x0186, 0x0254 }, +{ 0x0187, 0x0187, 0x0188 }, +{ 0x0188, 0x0187, 0x0188 }, +{ 0x0189, 0x0189, 0x0256 }, +{ 0x018A, 0x018A, 0x0257 }, +{ 0x018B, 0x018B, 0x018C }, +{ 0x018C, 0x018B, 0x018C }, +{ 0x018D, 0x018D, 0x018D }, +{ 0x018E, 0x018E, 0x01DD }, +{ 0x018F, 0x018F, 0x0259 }, +{ 0x0190, 0x0190, 0x025B }, +{ 0x0191, 0x0191, 0x0192 }, +{ 0x0192, 0x0191, 0x0192 }, +{ 0x0193, 0x0193, 0x0260 }, +{ 0x0194, 0x0194, 0x0263 }, +{ 0x0195, 0x01F6, 0x0195 }, +{ 0x0196, 0x0196, 0x0269 }, +{ 0x0197, 0x0197, 0x0268 }, +{ 0x0198, 0x0198, 0x0199 }, +{ 0x0199, 0x0198, 0x0199 }, +{ 0x019A, 0x023D, 0x019A }, +{ 0x019B, 0x019B, 0x019B }, +{ 0x019C, 0x019C, 0x026F }, +{ 0x019D, 0x019D, 0x0272 }, +{ 0x019E, 0x0220, 0x019E }, +{ 0x019F, 0x019F, 0x0275 }, +{ 0x01A0, 0x01A0, 0x01A1 }, +{ 0x01A1, 0x01A0, 0x01A1 }, +{ 0x01A2, 0x01A2, 0x01A3 }, +{ 0x01A3, 0x01A2, 0x01A3 }, +{ 0x01A4, 0x01A4, 0x01A5 }, +{ 0x01A5, 0x01A4, 0x01A5 }, +{ 0x01A6, 0x01A6, 0x0280 }, +{ 0x01A7, 0x01A7, 0x01A8 }, +{ 0x01A8, 0x01A7, 0x01A8 }, +{ 0x01A9, 0x01A9, 0x0283 }, +{ 0x01AA, 0x01AA, 0x01AA }, +{ 0x01AB, 0x01AB, 0x01AB }, +{ 0x01AC, 0x01AC, 0x01AD }, +{ 0x01AD, 0x01AC, 0x01AD }, +{ 0x01AE, 0x01AE, 0x0288 }, +{ 0x01AF, 0x01AF, 0x01B0 }, +{ 0x01B0, 0x01AF, 0x01B0 }, +{ 0x01B1, 0x01B1, 0x028A }, +{ 0x01B2, 0x01B2, 0x028B }, +{ 0x01B3, 0x01B3, 0x01B4 }, +{ 0x01B4, 0x01B3, 0x01B4 }, +{ 0x01B5, 0x01B5, 0x01B6 }, +{ 0x01B6, 0x01B5, 0x01B6 }, +{ 0x01B7, 0x01B7, 0x0292 }, +{ 0x01B8, 0x01B8, 0x01B9 }, +{ 0x01B9, 0x01B8, 0x01B9 }, +{ 0x01BA, 0x01BA, 0x01BA }, +{ 0x01BB, 0x01BB, 0x01BB }, +{ 0x01BC, 0x01BC, 0x01BD }, +{ 0x01BD, 0x01BC, 0x01BD }, +{ 0x01BE, 0x01BE, 0x01BE }, +{ 0x01BF, 0x01F7, 0x01BF }, +{ 0x01C0, 0x01C0, 0x01C0 }, +{ 0x01C1, 0x01C1, 0x01C1 }, +{ 0x01C2, 0x01C2, 0x01C2 }, +{ 0x01C3, 0x01C3, 0x01C3 }, +{ 0x01C4, 0x01C4, 0x01C6 }, +{ 0x01C5, 0x01C4, 0x01C6 }, +{ 0x01C6, 0x01C4, 0x01C6 }, +{ 0x01C7, 0x01C7, 0x01C9 }, +{ 0x01C8, 0x01C7, 0x01C9 }, +{ 0x01C9, 0x01C7, 0x01C9 }, +{ 0x01CA, 0x01CA, 0x01CC }, +{ 0x01CB, 0x01CA, 0x01CC }, +{ 0x01CC, 0x01CA, 0x01CC }, +{ 0x01CD, 0x01CD, 0x01CE }, +{ 0x01CE, 0x01CD, 0x01CE }, +{ 0x01CF, 0x01CF, 0x01D0 }, +{ 0x01D0, 0x01CF, 0x01D0 }, +{ 0x01D1, 0x01D1, 0x01D2 }, +{ 0x01D2, 0x01D1, 0x01D2 }, +{ 0x01D3, 0x01D3, 0x01D4 }, +{ 0x01D4, 0x01D3, 0x01D4 }, +{ 0x01D5, 0x01D5, 0x01D6 }, +{ 0x01D6, 0x01D5, 0x01D6 }, +{ 0x01D7, 0x01D7, 0x01D8 }, +{ 0x01D8, 0x01D7, 0x01D8 }, +{ 0x01D9, 0x01D9, 0x01DA }, +{ 0x01DA, 0x01D9, 0x01DA }, +{ 0x01DB, 0x01DB, 0x01DC }, +{ 0x01DC, 0x01DB, 0x01DC }, +{ 0x01DD, 0x018E, 0x01DD }, +{ 0x01DE, 0x01DE, 0x01DF }, +{ 0x01DF, 0x01DE, 0x01DF }, +{ 0x01E0, 0x01E0, 0x01E1 }, +{ 0x01E1, 0x01E0, 0x01E1 }, +{ 0x01E2, 0x01E2, 0x01E3 }, +{ 0x01E3, 0x01E2, 0x01E3 }, +{ 0x01E4, 0x01E4, 0x01E5 }, +{ 0x01E5, 0x01E4, 0x01E5 }, +{ 0x01E6, 0x01E6, 0x01E7 }, +{ 0x01E7, 0x01E6, 0x01E7 }, +{ 0x01E8, 0x01E8, 0x01E9 }, +{ 0x01E9, 0x01E8, 0x01E9 }, +{ 0x01EA, 0x01EA, 0x01EB }, +{ 0x01EB, 0x01EA, 0x01EB }, +{ 0x01EC, 0x01EC, 0x01ED }, +{ 0x01ED, 0x01EC, 0x01ED }, +{ 0x01EE, 0x01EE, 0x01EF }, +{ 0x01EF, 0x01EE, 0x01EF }, +{ 0x01F0, 0x01F0, 0x01F0 }, +{ 0x01F1, 0x01F1, 0x01F3 }, +{ 0x01F2, 0x01F1, 0x01F3 }, +{ 0x01F3, 0x01F1, 0x01F3 }, +{ 0x01F4, 0x01F4, 0x01F5 }, +{ 0x01F5, 0x01F4, 0x01F5 }, +{ 0x01F6, 0x01F6, 0x0195 }, +{ 0x01F7, 0x01F7, 0x01BF }, +{ 0x01F8, 0x01F8, 0x01F9 }, +{ 0x01F9, 0x01F8, 0x01F9 }, +{ 0x01FA, 0x01FA, 0x01FB }, +{ 0x01FB, 0x01FA, 0x01FB }, +{ 0x01FC, 0x01FC, 0x01FD }, +{ 0x01FD, 0x01FC, 0x01FD }, +{ 0x01FE, 0x01FE, 0x01FF }, +{ 0x01FF, 0x01FE, 0x01FF }, +{ 0x0200, 0x0200, 0x0201 }, +{ 0x0201, 0x0200, 0x0201 }, +{ 0x0202, 0x0202, 0x0203 }, +{ 0x0203, 0x0202, 0x0203 }, +{ 0x0204, 0x0204, 0x0205 }, +{ 0x0205, 0x0204, 0x0205 }, +{ 0x0206, 0x0206, 0x0207 }, +{ 0x0207, 0x0206, 0x0207 }, +{ 0x0208, 0x0208, 0x0209 }, +{ 0x0209, 0x0208, 0x0209 }, +{ 0x020A, 0x020A, 0x020B }, +{ 0x020B, 0x020A, 0x020B }, +{ 0x020C, 0x020C, 0x020D }, +{ 0x020D, 0x020C, 0x020D }, +{ 0x020E, 0x020E, 0x020F }, +{ 0x020F, 0x020E, 0x020F }, +{ 0x0210, 0x0210, 0x0211 }, +{ 0x0211, 0x0210, 0x0211 }, +{ 0x0212, 0x0212, 0x0213 }, +{ 0x0213, 0x0212, 0x0213 }, +{ 0x0214, 0x0214, 0x0215 }, +{ 0x0215, 0x0214, 0x0215 }, +{ 0x0216, 0x0216, 0x0217 }, +{ 0x0217, 0x0216, 0x0217 }, +{ 0x0218, 0x0218, 0x0219 }, +{ 0x0219, 0x0218, 0x0219 }, +{ 0x021A, 0x021A, 0x021B }, +{ 0x021B, 0x021A, 0x021B }, +{ 0x021C, 0x021C, 0x021D }, +{ 0x021D, 0x021C, 0x021D }, +{ 0x021E, 0x021E, 0x021F }, +{ 0x021F, 0x021E, 0x021F }, +{ 0x0220, 0x0220, 0x019E }, +{ 0x0221, 0x0221, 0x0221 }, +{ 0x0222, 0x0222, 0x0223 }, +{ 0x0223, 0x0222, 0x0223 }, +{ 0x0224, 0x0224, 0x0225 }, +{ 0x0225, 0x0224, 0x0225 }, +{ 0x0226, 0x0226, 0x0227 }, +{ 0x0227, 0x0226, 0x0227 }, +{ 0x0228, 0x0228, 0x0229 }, +{ 0x0229, 0x0228, 0x0229 }, +{ 0x022A, 0x022A, 0x022B }, +{ 0x022B, 0x022A, 0x022B }, +{ 0x022C, 0x022C, 0x022D }, +{ 0x022D, 0x022C, 0x022D }, +{ 0x022E, 0x022E, 0x022F }, +{ 0x022F, 0x022E, 0x022F }, +{ 0x0230, 0x0230, 0x0231 }, +{ 0x0231, 0x0230, 0x0231 }, +{ 0x0232, 0x0232, 0x0233 }, +{ 0x0233, 0x0232, 0x0233 }, +{ 0x0234, 0x0234, 0x0234 }, +{ 0x0235, 0x0235, 0x0235 }, +{ 0x0236, 0x0236, 0x0236 }, +{ 0x0237, 0x0237, 0x0237 }, +{ 0x0238, 0x0238, 0x0238 }, +{ 0x0239, 0x0239, 0x0239 }, +{ 0x023A, 0x023A, 0x023A }, +{ 0x023B, 0x023B, 0x023C }, +{ 0x023C, 0x023B, 0x023C }, +{ 0x023D, 0x023D, 0x019A }, +{ 0x023E, 0x023E, 0x023E }, +{ 0x023F, 0x023F, 0x023F }, +{ 0x0240, 0x0240, 0x0240 }, +{ 0x0241, 0x0241, 0x0294 }, +{ 0x0250, 0x0250, 0x0250 }, +{ 0x0251, 0x0251, 0x0251 }, +{ 0x0252, 0x0252, 0x0252 }, +{ 0x0253, 0x0181, 0x0253 }, +{ 0x0254, 0x0186, 0x0254 }, +{ 0x0255, 0x0255, 0x0255 }, +{ 0x0256, 0x0189, 0x0256 }, +{ 0x0257, 0x018A, 0x0257 }, +{ 0x0258, 0x0258, 0x0258 }, +{ 0x0259, 0x018F, 0x0259 }, +{ 0x025A, 0x025A, 0x025A }, +{ 0x025B, 0x0190, 0x025B }, +{ 0x025C, 0x025C, 0x025C }, +{ 0x025D, 0x025D, 0x025D }, +{ 0x025E, 0x025E, 0x025E }, +{ 0x025F, 0x025F, 0x025F }, +{ 0x0260, 0x0193, 0x0260 }, +{ 0x0261, 0x0261, 0x0261 }, +{ 0x0262, 0x0262, 0x0262 }, +{ 0x0263, 0x0194, 0x0263 }, +{ 0x0264, 0x0264, 0x0264 }, +{ 0x0265, 0x0265, 0x0265 }, +{ 0x0266, 0x0266, 0x0266 }, +{ 0x0267, 0x0267, 0x0267 }, +{ 0x0268, 0x0197, 0x0268 }, +{ 0x0269, 0x0196, 0x0269 }, +{ 0x026A, 0x026A, 0x026A }, +{ 0x026B, 0x026B, 0x026B }, +{ 0x026C, 0x026C, 0x026C }, +{ 0x026D, 0x026D, 0x026D }, +{ 0x026E, 0x026E, 0x026E }, +{ 0x026F, 0x019C, 0x026F }, +{ 0x0270, 0x0270, 0x0270 }, +{ 0x0271, 0x0271, 0x0271 }, +{ 0x0272, 0x019D, 0x0272 }, +{ 0x0273, 0x0273, 0x0273 }, +{ 0x0274, 0x0274, 0x0274 }, +{ 0x0275, 0x019F, 0x0275 }, +{ 0x0276, 0x0276, 0x0276 }, +{ 0x0277, 0x0277, 0x0277 }, +{ 0x0278, 0x0278, 0x0278 }, +{ 0x0279, 0x0279, 0x0279 }, +{ 0x027A, 0x027A, 0x027A }, +{ 0x027B, 0x027B, 0x027B }, +{ 0x027C, 0x027C, 0x027C }, +{ 0x027D, 0x027D, 0x027D }, +{ 0x027E, 0x027E, 0x027E }, +{ 0x027F, 0x027F, 0x027F }, +{ 0x0280, 0x01A6, 0x0280 }, +{ 0x0281, 0x0281, 0x0281 }, +{ 0x0282, 0x0282, 0x0282 }, +{ 0x0283, 0x01A9, 0x0283 }, +{ 0x0284, 0x0284, 0x0284 }, +{ 0x0285, 0x0285, 0x0285 }, +{ 0x0286, 0x0286, 0x0286 }, +{ 0x0287, 0x0287, 0x0287 }, +{ 0x0288, 0x01AE, 0x0288 }, +{ 0x0289, 0x0289, 0x0289 }, +{ 0x028A, 0x01B1, 0x028A }, +{ 0x028B, 0x01B2, 0x028B }, +{ 0x028C, 0x028C, 0x028C }, +{ 0x028D, 0x028D, 0x028D }, +{ 0x028E, 0x028E, 0x028E }, +{ 0x028F, 0x028F, 0x028F }, +{ 0x0290, 0x0290, 0x0290 }, +{ 0x0291, 0x0291, 0x0291 }, +{ 0x0292, 0x01B7, 0x0292 }, +{ 0x0293, 0x0293, 0x0293 }, +{ 0x0294, 0x0241, 0x0294 }, +{ 0x0295, 0x0295, 0x0295 }, +{ 0x0296, 0x0296, 0x0296 }, +{ 0x0297, 0x0297, 0x0297 }, +{ 0x0298, 0x0298, 0x0298 }, +{ 0x0299, 0x0299, 0x0299 }, +{ 0x029A, 0x029A, 0x029A }, +{ 0x029B, 0x029B, 0x029B }, +{ 0x029C, 0x029C, 0x029C }, +{ 0x029D, 0x029D, 0x029D }, +{ 0x029E, 0x029E, 0x029E }, +{ 0x029F, 0x029F, 0x029F }, +{ 0x02A0, 0x02A0, 0x02A0 }, +{ 0x02A1, 0x02A1, 0x02A1 }, +{ 0x02A2, 0x02A2, 0x02A2 }, +{ 0x02A3, 0x02A3, 0x02A3 }, +{ 0x02A4, 0x02A4, 0x02A4 }, +{ 0x02A5, 0x02A5, 0x02A5 }, +{ 0x02A6, 0x02A6, 0x02A6 }, +{ 0x02A7, 0x02A7, 0x02A7 }, +{ 0x02A8, 0x02A8, 0x02A8 }, +{ 0x02A9, 0x02A9, 0x02A9 }, +{ 0x02AA, 0x02AA, 0x02AA }, +{ 0x02AB, 0x02AB, 0x02AB }, +{ 0x02AC, 0x02AC, 0x02AC }, +{ 0x02AD, 0x02AD, 0x02AD }, +{ 0x02AE, 0x02AE, 0x02AE }, +{ 0x02AF, 0x02AF, 0x02AF }, +{ 0x02B0, 0x02B0, 0x02B0 }, +{ 0x02B1, 0x02B1, 0x02B1 }, +{ 0x02B2, 0x02B2, 0x02B2 }, +{ 0x02B3, 0x02B3, 0x02B3 }, +{ 0x02B4, 0x02B4, 0x02B4 }, +{ 0x02B5, 0x02B5, 0x02B5 }, +{ 0x02B6, 0x02B6, 0x02B6 }, +{ 0x02B7, 0x02B7, 0x02B7 }, +{ 0x02B8, 0x02B8, 0x02B8 }, +{ 0x02B9, 0x02B9, 0x02B9 }, +{ 0x02BA, 0x02BA, 0x02BA }, +{ 0x02BB, 0x02BB, 0x02BB }, +{ 0x02BC, 0x02BC, 0x02BC }, +{ 0x02BD, 0x02BD, 0x02BD }, +{ 0x02BE, 0x02BE, 0x02BE }, +{ 0x02BF, 0x02BF, 0x02BF }, +{ 0x02C0, 0x02C0, 0x02C0 }, +{ 0x02C1, 0x02C1, 0x02C1 }, +{ 0x02C6, 0x02C6, 0x02C6 }, +{ 0x02C7, 0x02C7, 0x02C7 }, +{ 0x02C8, 0x02C8, 0x02C8 }, +{ 0x02C9, 0x02C9, 0x02C9 }, +{ 0x02CA, 0x02CA, 0x02CA }, +{ 0x02CB, 0x02CB, 0x02CB }, +{ 0x02CC, 0x02CC, 0x02CC }, +{ 0x02CD, 0x02CD, 0x02CD }, +{ 0x02CE, 0x02CE, 0x02CE }, +{ 0x02CF, 0x02CF, 0x02CF }, +{ 0x02D0, 0x02D0, 0x02D0 }, +{ 0x02D1, 0x02D1, 0x02D1 }, +{ 0x02E0, 0x02E0, 0x02E0 }, +{ 0x02E1, 0x02E1, 0x02E1 }, +{ 0x02E2, 0x02E2, 0x02E2 }, +{ 0x02E3, 0x02E3, 0x02E3 }, +{ 0x02E4, 0x02E4, 0x02E4 }, +{ 0x02EE, 0x02EE, 0x02EE }, +{ 0x0300, 0x0300, 0x0300 }, +{ 0x0301, 0x0301, 0x0301 }, +{ 0x0302, 0x0302, 0x0302 }, +{ 0x0303, 0x0303, 0x0303 }, +{ 0x0304, 0x0304, 0x0304 }, +{ 0x0305, 0x0305, 0x0305 }, +{ 0x0306, 0x0306, 0x0306 }, +{ 0x0307, 0x0307, 0x0307 }, +{ 0x0308, 0x0308, 0x0308 }, +{ 0x0309, 0x0309, 0x0309 }, +{ 0x030A, 0x030A, 0x030A }, +{ 0x030B, 0x030B, 0x030B }, +{ 0x030C, 0x030C, 0x030C }, +{ 0x030D, 0x030D, 0x030D }, +{ 0x030E, 0x030E, 0x030E }, +{ 0x030F, 0x030F, 0x030F }, +{ 0x0310, 0x0310, 0x0310 }, +{ 0x0311, 0x0311, 0x0311 }, +{ 0x0312, 0x0312, 0x0312 }, +{ 0x0313, 0x0313, 0x0313 }, +{ 0x0314, 0x0314, 0x0314 }, +{ 0x0315, 0x0315, 0x0315 }, +{ 0x0316, 0x0316, 0x0316 }, +{ 0x0317, 0x0317, 0x0317 }, +{ 0x0318, 0x0318, 0x0318 }, +{ 0x0319, 0x0319, 0x0319 }, +{ 0x031A, 0x031A, 0x031A }, +{ 0x031B, 0x031B, 0x031B }, +{ 0x031C, 0x031C, 0x031C }, +{ 0x031D, 0x031D, 0x031D }, +{ 0x031E, 0x031E, 0x031E }, +{ 0x031F, 0x031F, 0x031F }, +{ 0x0320, 0x0320, 0x0320 }, +{ 0x0321, 0x0321, 0x0321 }, +{ 0x0322, 0x0322, 0x0322 }, +{ 0x0323, 0x0323, 0x0323 }, +{ 0x0324, 0x0324, 0x0324 }, +{ 0x0325, 0x0325, 0x0325 }, +{ 0x0326, 0x0326, 0x0326 }, +{ 0x0327, 0x0327, 0x0327 }, +{ 0x0328, 0x0328, 0x0328 }, +{ 0x0329, 0x0329, 0x0329 }, +{ 0x032A, 0x032A, 0x032A }, +{ 0x032B, 0x032B, 0x032B }, +{ 0x032C, 0x032C, 0x032C }, +{ 0x032D, 0x032D, 0x032D }, +{ 0x032E, 0x032E, 0x032E }, +{ 0x032F, 0x032F, 0x032F }, +{ 0x0330, 0x0330, 0x0330 }, +{ 0x0331, 0x0331, 0x0331 }, +{ 0x0332, 0x0332, 0x0332 }, +{ 0x0333, 0x0333, 0x0333 }, +{ 0x0334, 0x0334, 0x0334 }, +{ 0x0335, 0x0335, 0x0335 }, +{ 0x0336, 0x0336, 0x0336 }, +{ 0x0337, 0x0337, 0x0337 }, +{ 0x0338, 0x0338, 0x0338 }, +{ 0x0339, 0x0339, 0x0339 }, +{ 0x033A, 0x033A, 0x033A }, +{ 0x033B, 0x033B, 0x033B }, +{ 0x033C, 0x033C, 0x033C }, +{ 0x033D, 0x033D, 0x033D }, +{ 0x033E, 0x033E, 0x033E }, +{ 0x033F, 0x033F, 0x033F }, +{ 0x0340, 0x0340, 0x0340 }, +{ 0x0341, 0x0341, 0x0341 }, +{ 0x0342, 0x0342, 0x0342 }, +{ 0x0343, 0x0343, 0x0343 }, +{ 0x0344, 0x0344, 0x0344 }, +{ 0x0345, 0x0399, 0x0345 }, +{ 0x0346, 0x0346, 0x0346 }, +{ 0x0347, 0x0347, 0x0347 }, +{ 0x0348, 0x0348, 0x0348 }, +{ 0x0349, 0x0349, 0x0349 }, +{ 0x034A, 0x034A, 0x034A }, +{ 0x034B, 0x034B, 0x034B }, +{ 0x034C, 0x034C, 0x034C }, +{ 0x034D, 0x034D, 0x034D }, +{ 0x034E, 0x034E, 0x034E }, +{ 0x034F, 0x034F, 0x034F }, +{ 0x0350, 0x0350, 0x0350 }, +{ 0x0351, 0x0351, 0x0351 }, +{ 0x0352, 0x0352, 0x0352 }, +{ 0x0353, 0x0353, 0x0353 }, +{ 0x0354, 0x0354, 0x0354 }, +{ 0x0355, 0x0355, 0x0355 }, +{ 0x0356, 0x0356, 0x0356 }, +{ 0x0357, 0x0357, 0x0357 }, +{ 0x0358, 0x0358, 0x0358 }, +{ 0x0359, 0x0359, 0x0359 }, +{ 0x035A, 0x035A, 0x035A }, +{ 0x035B, 0x035B, 0x035B }, +{ 0x035C, 0x035C, 0x035C }, +{ 0x035D, 0x035D, 0x035D }, +{ 0x035E, 0x035E, 0x035E }, +{ 0x035F, 0x035F, 0x035F }, +{ 0x0360, 0x0360, 0x0360 }, +{ 0x0361, 0x0361, 0x0361 }, +{ 0x0362, 0x0362, 0x0362 }, +{ 0x0363, 0x0363, 0x0363 }, +{ 0x0364, 0x0364, 0x0364 }, +{ 0x0365, 0x0365, 0x0365 }, +{ 0x0366, 0x0366, 0x0366 }, +{ 0x0367, 0x0367, 0x0367 }, +{ 0x0368, 0x0368, 0x0368 }, +{ 0x0369, 0x0369, 0x0369 }, +{ 0x036A, 0x036A, 0x036A }, +{ 0x036B, 0x036B, 0x036B }, +{ 0x036C, 0x036C, 0x036C }, +{ 0x036D, 0x036D, 0x036D }, +{ 0x036E, 0x036E, 0x036E }, +{ 0x036F, 0x036F, 0x036F }, +{ 0x037A, 0x037A, 0x037A }, +{ 0x0386, 0x0386, 0x03AC }, +{ 0x0388, 0x0388, 0x03AD }, +{ 0x0389, 0x0389, 0x03AE }, +{ 0x038A, 0x038A, 0x03AF }, +{ 0x038C, 0x038C, 0x03CC }, +{ 0x038E, 0x038E, 0x03CD }, +{ 0x038F, 0x038F, 0x03CE }, +{ 0x0390, 0x0390, 0x0390 }, +{ 0x0391, 0x0391, 0x03B1 }, +{ 0x0392, 0x0392, 0x03B2 }, +{ 0x0393, 0x0393, 0x03B3 }, +{ 0x0394, 0x0394, 0x03B4 }, +{ 0x0395, 0x0395, 0x03B5 }, +{ 0x0396, 0x0396, 0x03B6 }, +{ 0x0397, 0x0397, 0x03B7 }, +{ 0x0398, 0x0398, 0x03B8 }, +{ 0x0399, 0x0399, 0x03B9 }, +{ 0x039A, 0x039A, 0x03BA }, +{ 0x039B, 0x039B, 0x03BB }, +{ 0x039C, 0x039C, 0x03BC }, +{ 0x039D, 0x039D, 0x03BD }, +{ 0x039E, 0x039E, 0x03BE }, +{ 0x039F, 0x039F, 0x03BF }, +{ 0x03A0, 0x03A0, 0x03C0 }, +{ 0x03A1, 0x03A1, 0x03C1 }, +{ 0x03A3, 0x03A3, 0x03C3 }, +{ 0x03A4, 0x03A4, 0x03C4 }, +{ 0x03A5, 0x03A5, 0x03C5 }, +{ 0x03A6, 0x03A6, 0x03C6 }, +{ 0x03A7, 0x03A7, 0x03C7 }, +{ 0x03A8, 0x03A8, 0x03C8 }, +{ 0x03A9, 0x03A9, 0x03C9 }, +{ 0x03AA, 0x03AA, 0x03CA }, +{ 0x03AB, 0x03AB, 0x03CB }, +{ 0x03AC, 0x0386, 0x03AC }, +{ 0x03AD, 0x0388, 0x03AD }, +{ 0x03AE, 0x0389, 0x03AE }, +{ 0x03AF, 0x038A, 0x03AF }, +{ 0x03B0, 0x03B0, 0x03B0 }, +{ 0x03B1, 0x0391, 0x03B1 }, +{ 0x03B2, 0x0392, 0x03B2 }, +{ 0x03B3, 0x0393, 0x03B3 }, +{ 0x03B4, 0x0394, 0x03B4 }, +{ 0x03B5, 0x0395, 0x03B5 }, +{ 0x03B6, 0x0396, 0x03B6 }, +{ 0x03B7, 0x0397, 0x03B7 }, +{ 0x03B8, 0x0398, 0x03B8 }, +{ 0x03B9, 0x0399, 0x03B9 }, +{ 0x03BA, 0x039A, 0x03BA }, +{ 0x03BB, 0x039B, 0x03BB }, +{ 0x03BC, 0x039C, 0x03BC }, +{ 0x03BD, 0x039D, 0x03BD }, +{ 0x03BE, 0x039E, 0x03BE }, +{ 0x03BF, 0x039F, 0x03BF }, +{ 0x03C0, 0x03A0, 0x03C0 }, +{ 0x03C1, 0x03A1, 0x03C1 }, +{ 0x03C2, 0x03A3, 0x03C2 }, +{ 0x03C3, 0x03A3, 0x03C3 }, +{ 0x03C4, 0x03A4, 0x03C4 }, +{ 0x03C5, 0x03A5, 0x03C5 }, +{ 0x03C6, 0x03A6, 0x03C6 }, +{ 0x03C7, 0x03A7, 0x03C7 }, +{ 0x03C8, 0x03A8, 0x03C8 }, +{ 0x03C9, 0x03A9, 0x03C9 }, +{ 0x03CA, 0x03AA, 0x03CA }, +{ 0x03CB, 0x03AB, 0x03CB }, +{ 0x03CC, 0x038C, 0x03CC }, +{ 0x03CD, 0x038E, 0x03CD }, +{ 0x03CE, 0x038F, 0x03CE }, +{ 0x03D0, 0x0392, 0x03D0 }, +{ 0x03D1, 0x0398, 0x03D1 }, +{ 0x03D2, 0x03D2, 0x03D2 }, +{ 0x03D3, 0x03D3, 0x03D3 }, +{ 0x03D4, 0x03D4, 0x03D4 }, +{ 0x03D5, 0x03A6, 0x03D5 }, +{ 0x03D6, 0x03A0, 0x03D6 }, +{ 0x03D7, 0x03D7, 0x03D7 }, +{ 0x03D8, 0x03D8, 0x03D9 }, +{ 0x03D9, 0x03D8, 0x03D9 }, +{ 0x03DA, 0x03DA, 0x03DB }, +{ 0x03DB, 0x03DA, 0x03DB }, +{ 0x03DC, 0x03DC, 0x03DD }, +{ 0x03DD, 0x03DC, 0x03DD }, +{ 0x03DE, 0x03DE, 0x03DF }, +{ 0x03DF, 0x03DE, 0x03DF }, +{ 0x03E0, 0x03E0, 0x03E1 }, +{ 0x03E1, 0x03E0, 0x03E1 }, +{ 0x03E2, 0x03E2, 0x03E3 }, +{ 0x03E3, 0x03E2, 0x03E3 }, +{ 0x03E4, 0x03E4, 0x03E5 }, +{ 0x03E5, 0x03E4, 0x03E5 }, +{ 0x03E6, 0x03E6, 0x03E7 }, +{ 0x03E7, 0x03E6, 0x03E7 }, +{ 0x03E8, 0x03E8, 0x03E9 }, +{ 0x03E9, 0x03E8, 0x03E9 }, +{ 0x03EA, 0x03EA, 0x03EB }, +{ 0x03EB, 0x03EA, 0x03EB }, +{ 0x03EC, 0x03EC, 0x03ED }, +{ 0x03ED, 0x03EC, 0x03ED }, +{ 0x03EE, 0x03EE, 0x03EF }, +{ 0x03EF, 0x03EE, 0x03EF }, +{ 0x03F0, 0x039A, 0x03F0 }, +{ 0x03F1, 0x03A1, 0x03F1 }, +{ 0x03F2, 0x03F9, 0x03F2 }, +{ 0x03F3, 0x03F3, 0x03F3 }, +{ 0x03F4, 0x03F4, 0x03B8 }, +{ 0x03F5, 0x0395, 0x03F5 }, +{ 0x03F7, 0x03F7, 0x03F8 }, +{ 0x03F8, 0x03F7, 0x03F8 }, +{ 0x03F9, 0x03F9, 0x03F2 }, +{ 0x03FA, 0x03FA, 0x03FB }, +{ 0x03FB, 0x03FA, 0x03FB }, +{ 0x03FC, 0x03FC, 0x03FC }, +{ 0x03FD, 0x03FD, 0x03FD }, +{ 0x03FE, 0x03FE, 0x03FE }, +{ 0x03FF, 0x03FF, 0x03FF }, +{ 0x0400, 0x0400, 0x0450 }, +{ 0x0401, 0x0401, 0x0451 }, +{ 0x0402, 0x0402, 0x0452 }, +{ 0x0403, 0x0403, 0x0453 }, +{ 0x0404, 0x0404, 0x0454 }, +{ 0x0405, 0x0405, 0x0455 }, +{ 0x0406, 0x0406, 0x0456 }, +{ 0x0407, 0x0407, 0x0457 }, +{ 0x0408, 0x0408, 0x0458 }, +{ 0x0409, 0x0409, 0x0459 }, +{ 0x040A, 0x040A, 0x045A }, +{ 0x040B, 0x040B, 0x045B }, +{ 0x040C, 0x040C, 0x045C }, +{ 0x040D, 0x040D, 0x045D }, +{ 0x040E, 0x040E, 0x045E }, +{ 0x040F, 0x040F, 0x045F }, +{ 0x0410, 0x0410, 0x0430 }, +{ 0x0411, 0x0411, 0x0431 }, +{ 0x0412, 0x0412, 0x0432 }, +{ 0x0413, 0x0413, 0x0433 }, +{ 0x0414, 0x0414, 0x0434 }, +{ 0x0415, 0x0415, 0x0435 }, +{ 0x0416, 0x0416, 0x0436 }, +{ 0x0417, 0x0417, 0x0437 }, +{ 0x0418, 0x0418, 0x0438 }, +{ 0x0419, 0x0419, 0x0439 }, +{ 0x041A, 0x041A, 0x043A }, +{ 0x041B, 0x041B, 0x043B }, +{ 0x041C, 0x041C, 0x043C }, +{ 0x041D, 0x041D, 0x043D }, +{ 0x041E, 0x041E, 0x043E }, +{ 0x041F, 0x041F, 0x043F }, +{ 0x0420, 0x0420, 0x0440 }, +{ 0x0421, 0x0421, 0x0441 }, +{ 0x0422, 0x0422, 0x0442 }, +{ 0x0423, 0x0423, 0x0443 }, +{ 0x0424, 0x0424, 0x0444 }, +{ 0x0425, 0x0425, 0x0445 }, +{ 0x0426, 0x0426, 0x0446 }, +{ 0x0427, 0x0427, 0x0447 }, +{ 0x0428, 0x0428, 0x0448 }, +{ 0x0429, 0x0429, 0x0449 }, +{ 0x042A, 0x042A, 0x044A }, +{ 0x042B, 0x042B, 0x044B }, +{ 0x042C, 0x042C, 0x044C }, +{ 0x042D, 0x042D, 0x044D }, +{ 0x042E, 0x042E, 0x044E }, +{ 0x042F, 0x042F, 0x044F }, +{ 0x0430, 0x0410, 0x0430 }, +{ 0x0431, 0x0411, 0x0431 }, +{ 0x0432, 0x0412, 0x0432 }, +{ 0x0433, 0x0413, 0x0433 }, +{ 0x0434, 0x0414, 0x0434 }, +{ 0x0435, 0x0415, 0x0435 }, +{ 0x0436, 0x0416, 0x0436 }, +{ 0x0437, 0x0417, 0x0437 }, +{ 0x0438, 0x0418, 0x0438 }, +{ 0x0439, 0x0419, 0x0439 }, +{ 0x043A, 0x041A, 0x043A }, +{ 0x043B, 0x041B, 0x043B }, +{ 0x043C, 0x041C, 0x043C }, +{ 0x043D, 0x041D, 0x043D }, +{ 0x043E, 0x041E, 0x043E }, +{ 0x043F, 0x041F, 0x043F }, +{ 0x0440, 0x0420, 0x0440 }, +{ 0x0441, 0x0421, 0x0441 }, +{ 0x0442, 0x0422, 0x0442 }, +{ 0x0443, 0x0423, 0x0443 }, +{ 0x0444, 0x0424, 0x0444 }, +{ 0x0445, 0x0425, 0x0445 }, +{ 0x0446, 0x0426, 0x0446 }, +{ 0x0447, 0x0427, 0x0447 }, +{ 0x0448, 0x0428, 0x0448 }, +{ 0x0449, 0x0429, 0x0449 }, +{ 0x044A, 0x042A, 0x044A }, +{ 0x044B, 0x042B, 0x044B }, +{ 0x044C, 0x042C, 0x044C }, +{ 0x044D, 0x042D, 0x044D }, +{ 0x044E, 0x042E, 0x044E }, +{ 0x044F, 0x042F, 0x044F }, +{ 0x0450, 0x0400, 0x0450 }, +{ 0x0451, 0x0401, 0x0451 }, +{ 0x0452, 0x0402, 0x0452 }, +{ 0x0453, 0x0403, 0x0453 }, +{ 0x0454, 0x0404, 0x0454 }, +{ 0x0455, 0x0405, 0x0455 }, +{ 0x0456, 0x0406, 0x0456 }, +{ 0x0457, 0x0407, 0x0457 }, +{ 0x0458, 0x0408, 0x0458 }, +{ 0x0459, 0x0409, 0x0459 }, +{ 0x045A, 0x040A, 0x045A }, +{ 0x045B, 0x040B, 0x045B }, +{ 0x045C, 0x040C, 0x045C }, +{ 0x045D, 0x040D, 0x045D }, +{ 0x045E, 0x040E, 0x045E }, +{ 0x045F, 0x040F, 0x045F }, +{ 0x0460, 0x0460, 0x0461 }, +{ 0x0461, 0x0460, 0x0461 }, +{ 0x0462, 0x0462, 0x0463 }, +{ 0x0463, 0x0462, 0x0463 }, +{ 0x0464, 0x0464, 0x0465 }, +{ 0x0465, 0x0464, 0x0465 }, +{ 0x0466, 0x0466, 0x0467 }, +{ 0x0467, 0x0466, 0x0467 }, +{ 0x0468, 0x0468, 0x0469 }, +{ 0x0469, 0x0468, 0x0469 }, +{ 0x046A, 0x046A, 0x046B }, +{ 0x046B, 0x046A, 0x046B }, +{ 0x046C, 0x046C, 0x046D }, +{ 0x046D, 0x046C, 0x046D }, +{ 0x046E, 0x046E, 0x046F }, +{ 0x046F, 0x046E, 0x046F }, +{ 0x0470, 0x0470, 0x0471 }, +{ 0x0471, 0x0470, 0x0471 }, +{ 0x0472, 0x0472, 0x0473 }, +{ 0x0473, 0x0472, 0x0473 }, +{ 0x0474, 0x0474, 0x0475 }, +{ 0x0475, 0x0474, 0x0475 }, +{ 0x0476, 0x0476, 0x0477 }, +{ 0x0477, 0x0476, 0x0477 }, +{ 0x0478, 0x0478, 0x0479 }, +{ 0x0479, 0x0478, 0x0479 }, +{ 0x047A, 0x047A, 0x047B }, +{ 0x047B, 0x047A, 0x047B }, +{ 0x047C, 0x047C, 0x047D }, +{ 0x047D, 0x047C, 0x047D }, +{ 0x047E, 0x047E, 0x047F }, +{ 0x047F, 0x047E, 0x047F }, +{ 0x0480, 0x0480, 0x0481 }, +{ 0x0481, 0x0480, 0x0481 }, +{ 0x0483, 0x0483, 0x0483 }, +{ 0x0484, 0x0484, 0x0484 }, +{ 0x0485, 0x0485, 0x0485 }, +{ 0x0486, 0x0486, 0x0486 }, +{ 0x048A, 0x048A, 0x048B }, +{ 0x048B, 0x048A, 0x048B }, +{ 0x048C, 0x048C, 0x048D }, +{ 0x048D, 0x048C, 0x048D }, +{ 0x048E, 0x048E, 0x048F }, +{ 0x048F, 0x048E, 0x048F }, +{ 0x0490, 0x0490, 0x0491 }, +{ 0x0491, 0x0490, 0x0491 }, +{ 0x0492, 0x0492, 0x0493 }, +{ 0x0493, 0x0492, 0x0493 }, +{ 0x0494, 0x0494, 0x0495 }, +{ 0x0495, 0x0494, 0x0495 }, +{ 0x0496, 0x0496, 0x0497 }, +{ 0x0497, 0x0496, 0x0497 }, +{ 0x0498, 0x0498, 0x0499 }, +{ 0x0499, 0x0498, 0x0499 }, +{ 0x049A, 0x049A, 0x049B }, +{ 0x049B, 0x049A, 0x049B }, +{ 0x049C, 0x049C, 0x049D }, +{ 0x049D, 0x049C, 0x049D }, +{ 0x049E, 0x049E, 0x049F }, +{ 0x049F, 0x049E, 0x049F }, +{ 0x04A0, 0x04A0, 0x04A1 }, +{ 0x04A1, 0x04A0, 0x04A1 }, +{ 0x04A2, 0x04A2, 0x04A3 }, +{ 0x04A3, 0x04A2, 0x04A3 }, +{ 0x04A4, 0x04A4, 0x04A5 }, +{ 0x04A5, 0x04A4, 0x04A5 }, +{ 0x04A6, 0x04A6, 0x04A7 }, +{ 0x04A7, 0x04A6, 0x04A7 }, +{ 0x04A8, 0x04A8, 0x04A9 }, +{ 0x04A9, 0x04A8, 0x04A9 }, +{ 0x04AA, 0x04AA, 0x04AB }, +{ 0x04AB, 0x04AA, 0x04AB }, +{ 0x04AC, 0x04AC, 0x04AD }, +{ 0x04AD, 0x04AC, 0x04AD }, +{ 0x04AE, 0x04AE, 0x04AF }, +{ 0x04AF, 0x04AE, 0x04AF }, +{ 0x04B0, 0x04B0, 0x04B1 }, +{ 0x04B1, 0x04B0, 0x04B1 }, +{ 0x04B2, 0x04B2, 0x04B3 }, +{ 0x04B3, 0x04B2, 0x04B3 }, +{ 0x04B4, 0x04B4, 0x04B5 }, +{ 0x04B5, 0x04B4, 0x04B5 }, +{ 0x04B6, 0x04B6, 0x04B7 }, +{ 0x04B7, 0x04B6, 0x04B7 }, +{ 0x04B8, 0x04B8, 0x04B9 }, +{ 0x04B9, 0x04B8, 0x04B9 }, +{ 0x04BA, 0x04BA, 0x04BB }, +{ 0x04BB, 0x04BA, 0x04BB }, +{ 0x04BC, 0x04BC, 0x04BD }, +{ 0x04BD, 0x04BC, 0x04BD }, +{ 0x04BE, 0x04BE, 0x04BF }, +{ 0x04BF, 0x04BE, 0x04BF }, +{ 0x04C0, 0x04C0, 0x04C0 }, +{ 0x04C1, 0x04C1, 0x04C2 }, +{ 0x04C2, 0x04C1, 0x04C2 }, +{ 0x04C3, 0x04C3, 0x04C4 }, +{ 0x04C4, 0x04C3, 0x04C4 }, +{ 0x04C5, 0x04C5, 0x04C6 }, +{ 0x04C6, 0x04C5, 0x04C6 }, +{ 0x04C7, 0x04C7, 0x04C8 }, +{ 0x04C8, 0x04C7, 0x04C8 }, +{ 0x04C9, 0x04C9, 0x04CA }, +{ 0x04CA, 0x04C9, 0x04CA }, +{ 0x04CB, 0x04CB, 0x04CC }, +{ 0x04CC, 0x04CB, 0x04CC }, +{ 0x04CD, 0x04CD, 0x04CE }, +{ 0x04CE, 0x04CD, 0x04CE }, +{ 0x04D0, 0x04D0, 0x04D1 }, +{ 0x04D1, 0x04D0, 0x04D1 }, +{ 0x04D2, 0x04D2, 0x04D3 }, +{ 0x04D3, 0x04D2, 0x04D3 }, +{ 0x04D4, 0x04D4, 0x04D5 }, +{ 0x04D5, 0x04D4, 0x04D5 }, +{ 0x04D6, 0x04D6, 0x04D7 }, +{ 0x04D7, 0x04D6, 0x04D7 }, +{ 0x04D8, 0x04D8, 0x04D9 }, +{ 0x04D9, 0x04D8, 0x04D9 }, +{ 0x04DA, 0x04DA, 0x04DB }, +{ 0x04DB, 0x04DA, 0x04DB }, +{ 0x04DC, 0x04DC, 0x04DD }, +{ 0x04DD, 0x04DC, 0x04DD }, +{ 0x04DE, 0x04DE, 0x04DF }, +{ 0x04DF, 0x04DE, 0x04DF }, +{ 0x04E0, 0x04E0, 0x04E1 }, +{ 0x04E1, 0x04E0, 0x04E1 }, +{ 0x04E2, 0x04E2, 0x04E3 }, +{ 0x04E3, 0x04E2, 0x04E3 }, +{ 0x04E4, 0x04E4, 0x04E5 }, +{ 0x04E5, 0x04E4, 0x04E5 }, +{ 0x04E6, 0x04E6, 0x04E7 }, +{ 0x04E7, 0x04E6, 0x04E7 }, +{ 0x04E8, 0x04E8, 0x04E9 }, +{ 0x04E9, 0x04E8, 0x04E9 }, +{ 0x04EA, 0x04EA, 0x04EB }, +{ 0x04EB, 0x04EA, 0x04EB }, +{ 0x04EC, 0x04EC, 0x04ED }, +{ 0x04ED, 0x04EC, 0x04ED }, +{ 0x04EE, 0x04EE, 0x04EF }, +{ 0x04EF, 0x04EE, 0x04EF }, +{ 0x04F0, 0x04F0, 0x04F1 }, +{ 0x04F1, 0x04F0, 0x04F1 }, +{ 0x04F2, 0x04F2, 0x04F3 }, +{ 0x04F3, 0x04F2, 0x04F3 }, +{ 0x04F4, 0x04F4, 0x04F5 }, +{ 0x04F5, 0x04F4, 0x04F5 }, +{ 0x04F6, 0x04F6, 0x04F7 }, +{ 0x04F7, 0x04F6, 0x04F7 }, +{ 0x04F8, 0x04F8, 0x04F9 }, +{ 0x04F9, 0x04F8, 0x04F9 }, +{ 0x0500, 0x0500, 0x0501 }, +{ 0x0501, 0x0500, 0x0501 }, +{ 0x0502, 0x0502, 0x0503 }, +{ 0x0503, 0x0502, 0x0503 }, +{ 0x0504, 0x0504, 0x0505 }, +{ 0x0505, 0x0504, 0x0505 }, +{ 0x0506, 0x0506, 0x0507 }, +{ 0x0507, 0x0506, 0x0507 }, +{ 0x0508, 0x0508, 0x0509 }, +{ 0x0509, 0x0508, 0x0509 }, +{ 0x050A, 0x050A, 0x050B }, +{ 0x050B, 0x050A, 0x050B }, +{ 0x050C, 0x050C, 0x050D }, +{ 0x050D, 0x050C, 0x050D }, +{ 0x050E, 0x050E, 0x050F }, +{ 0x050F, 0x050E, 0x050F }, +{ 0x0531, 0x0531, 0x0561 }, +{ 0x0532, 0x0532, 0x0562 }, +{ 0x0533, 0x0533, 0x0563 }, +{ 0x0534, 0x0534, 0x0564 }, +{ 0x0535, 0x0535, 0x0565 }, +{ 0x0536, 0x0536, 0x0566 }, +{ 0x0537, 0x0537, 0x0567 }, +{ 0x0538, 0x0538, 0x0568 }, +{ 0x0539, 0x0539, 0x0569 }, +{ 0x053A, 0x053A, 0x056A }, +{ 0x053B, 0x053B, 0x056B }, +{ 0x053C, 0x053C, 0x056C }, +{ 0x053D, 0x053D, 0x056D }, +{ 0x053E, 0x053E, 0x056E }, +{ 0x053F, 0x053F, 0x056F }, +{ 0x0540, 0x0540, 0x0570 }, +{ 0x0541, 0x0541, 0x0571 }, +{ 0x0542, 0x0542, 0x0572 }, +{ 0x0543, 0x0543, 0x0573 }, +{ 0x0544, 0x0544, 0x0574 }, +{ 0x0545, 0x0545, 0x0575 }, +{ 0x0546, 0x0546, 0x0576 }, +{ 0x0547, 0x0547, 0x0577 }, +{ 0x0548, 0x0548, 0x0578 }, +{ 0x0549, 0x0549, 0x0579 }, +{ 0x054A, 0x054A, 0x057A }, +{ 0x054B, 0x054B, 0x057B }, +{ 0x054C, 0x054C, 0x057C }, +{ 0x054D, 0x054D, 0x057D }, +{ 0x054E, 0x054E, 0x057E }, +{ 0x054F, 0x054F, 0x057F }, +{ 0x0550, 0x0550, 0x0580 }, +{ 0x0551, 0x0551, 0x0581 }, +{ 0x0552, 0x0552, 0x0582 }, +{ 0x0553, 0x0553, 0x0583 }, +{ 0x0554, 0x0554, 0x0584 }, +{ 0x0555, 0x0555, 0x0585 }, +{ 0x0556, 0x0556, 0x0586 }, +{ 0x0559, 0x0559, 0x0559 }, +{ 0x0561, 0x0531, 0x0561 }, +{ 0x0562, 0x0532, 0x0562 }, +{ 0x0563, 0x0533, 0x0563 }, +{ 0x0564, 0x0534, 0x0564 }, +{ 0x0565, 0x0535, 0x0565 }, +{ 0x0566, 0x0536, 0x0566 }, +{ 0x0567, 0x0537, 0x0567 }, +{ 0x0568, 0x0538, 0x0568 }, +{ 0x0569, 0x0539, 0x0569 }, +{ 0x056A, 0x053A, 0x056A }, +{ 0x056B, 0x053B, 0x056B }, +{ 0x056C, 0x053C, 0x056C }, +{ 0x056D, 0x053D, 0x056D }, +{ 0x056E, 0x053E, 0x056E }, +{ 0x056F, 0x053F, 0x056F }, +{ 0x0570, 0x0540, 0x0570 }, +{ 0x0571, 0x0541, 0x0571 }, +{ 0x0572, 0x0542, 0x0572 }, +{ 0x0573, 0x0543, 0x0573 }, +{ 0x0574, 0x0544, 0x0574 }, +{ 0x0575, 0x0545, 0x0575 }, +{ 0x0576, 0x0546, 0x0576 }, +{ 0x0577, 0x0547, 0x0577 }, +{ 0x0578, 0x0548, 0x0578 }, +{ 0x0579, 0x0549, 0x0579 }, +{ 0x057A, 0x054A, 0x057A }, +{ 0x057B, 0x054B, 0x057B }, +{ 0x057C, 0x054C, 0x057C }, +{ 0x057D, 0x054D, 0x057D }, +{ 0x057E, 0x054E, 0x057E }, +{ 0x057F, 0x054F, 0x057F }, +{ 0x0580, 0x0550, 0x0580 }, +{ 0x0581, 0x0551, 0x0581 }, +{ 0x0582, 0x0552, 0x0582 }, +{ 0x0583, 0x0553, 0x0583 }, +{ 0x0584, 0x0554, 0x0584 }, +{ 0x0585, 0x0555, 0x0585 }, +{ 0x0586, 0x0556, 0x0586 }, +{ 0x0587, 0x0587, 0x0587 }, +{ 0x0591, 0x0591, 0x0591 }, +{ 0x0592, 0x0592, 0x0592 }, +{ 0x0593, 0x0593, 0x0593 }, +{ 0x0594, 0x0594, 0x0594 }, +{ 0x0595, 0x0595, 0x0595 }, +{ 0x0596, 0x0596, 0x0596 }, +{ 0x0597, 0x0597, 0x0597 }, +{ 0x0598, 0x0598, 0x0598 }, +{ 0x0599, 0x0599, 0x0599 }, +{ 0x059A, 0x059A, 0x059A }, +{ 0x059B, 0x059B, 0x059B }, +{ 0x059C, 0x059C, 0x059C }, +{ 0x059D, 0x059D, 0x059D }, +{ 0x059E, 0x059E, 0x059E }, +{ 0x059F, 0x059F, 0x059F }, +{ 0x05A0, 0x05A0, 0x05A0 }, +{ 0x05A1, 0x05A1, 0x05A1 }, +{ 0x05A2, 0x05A2, 0x05A2 }, +{ 0x05A3, 0x05A3, 0x05A3 }, +{ 0x05A4, 0x05A4, 0x05A4 }, +{ 0x05A5, 0x05A5, 0x05A5 }, +{ 0x05A6, 0x05A6, 0x05A6 }, +{ 0x05A7, 0x05A7, 0x05A7 }, +{ 0x05A8, 0x05A8, 0x05A8 }, +{ 0x05A9, 0x05A9, 0x05A9 }, +{ 0x05AA, 0x05AA, 0x05AA }, +{ 0x05AB, 0x05AB, 0x05AB }, +{ 0x05AC, 0x05AC, 0x05AC }, +{ 0x05AD, 0x05AD, 0x05AD }, +{ 0x05AE, 0x05AE, 0x05AE }, +{ 0x05AF, 0x05AF, 0x05AF }, +{ 0x05B0, 0x05B0, 0x05B0 }, +{ 0x05B1, 0x05B1, 0x05B1 }, +{ 0x05B2, 0x05B2, 0x05B2 }, +{ 0x05B3, 0x05B3, 0x05B3 }, +{ 0x05B4, 0x05B4, 0x05B4 }, +{ 0x05B5, 0x05B5, 0x05B5 }, +{ 0x05B6, 0x05B6, 0x05B6 }, +{ 0x05B7, 0x05B7, 0x05B7 }, +{ 0x05B8, 0x05B8, 0x05B8 }, +{ 0x05B9, 0x05B9, 0x05B9 }, +{ 0x05BB, 0x05BB, 0x05BB }, +{ 0x05BC, 0x05BC, 0x05BC }, +{ 0x05BD, 0x05BD, 0x05BD }, +{ 0x05BF, 0x05BF, 0x05BF }, +{ 0x05C1, 0x05C1, 0x05C1 }, +{ 0x05C2, 0x05C2, 0x05C2 }, +{ 0x05C4, 0x05C4, 0x05C4 }, +{ 0x05C5, 0x05C5, 0x05C5 }, +{ 0x05C7, 0x05C7, 0x05C7 }, +{ 0x05D0, 0x05D0, 0x05D0 }, +{ 0x05D1, 0x05D1, 0x05D1 }, +{ 0x05D2, 0x05D2, 0x05D2 }, +{ 0x05D3, 0x05D3, 0x05D3 }, +{ 0x05D4, 0x05D4, 0x05D4 }, +{ 0x05D5, 0x05D5, 0x05D5 }, +{ 0x05D6, 0x05D6, 0x05D6 }, +{ 0x05D7, 0x05D7, 0x05D7 }, +{ 0x05D8, 0x05D8, 0x05D8 }, +{ 0x05D9, 0x05D9, 0x05D9 }, +{ 0x05DA, 0x05DA, 0x05DA }, +{ 0x05DB, 0x05DB, 0x05DB }, +{ 0x05DC, 0x05DC, 0x05DC }, +{ 0x05DD, 0x05DD, 0x05DD }, +{ 0x05DE, 0x05DE, 0x05DE }, +{ 0x05DF, 0x05DF, 0x05DF }, +{ 0x05E0, 0x05E0, 0x05E0 }, +{ 0x05E1, 0x05E1, 0x05E1 }, +{ 0x05E2, 0x05E2, 0x05E2 }, +{ 0x05E3, 0x05E3, 0x05E3 }, +{ 0x05E4, 0x05E4, 0x05E4 }, +{ 0x05E5, 0x05E5, 0x05E5 }, +{ 0x05E6, 0x05E6, 0x05E6 }, +{ 0x05E7, 0x05E7, 0x05E7 }, +{ 0x05E8, 0x05E8, 0x05E8 }, +{ 0x05E9, 0x05E9, 0x05E9 }, +{ 0x05EA, 0x05EA, 0x05EA }, +{ 0x05F0, 0x05F0, 0x05F0 }, +{ 0x05F1, 0x05F1, 0x05F1 }, +{ 0x05F2, 0x05F2, 0x05F2 }, +{ 0x0610, 0x0610, 0x0610 }, +{ 0x0611, 0x0611, 0x0611 }, +{ 0x0612, 0x0612, 0x0612 }, +{ 0x0613, 0x0613, 0x0613 }, +{ 0x0614, 0x0614, 0x0614 }, +{ 0x0615, 0x0615, 0x0615 }, +{ 0x0621, 0x0621, 0x0621 }, +{ 0x0622, 0x0622, 0x0622 }, +{ 0x0623, 0x0623, 0x0623 }, +{ 0x0624, 0x0624, 0x0624 }, +{ 0x0625, 0x0625, 0x0625 }, +{ 0x0626, 0x0626, 0x0626 }, +{ 0x0627, 0x0627, 0x0627 }, +{ 0x0628, 0x0628, 0x0628 }, +{ 0x0629, 0x0629, 0x0629 }, +{ 0x062A, 0x062A, 0x062A }, +{ 0x062B, 0x062B, 0x062B }, +{ 0x062C, 0x062C, 0x062C }, +{ 0x062D, 0x062D, 0x062D }, +{ 0x062E, 0x062E, 0x062E }, +{ 0x062F, 0x062F, 0x062F }, +{ 0x0630, 0x0630, 0x0630 }, +{ 0x0631, 0x0631, 0x0631 }, +{ 0x0632, 0x0632, 0x0632 }, +{ 0x0633, 0x0633, 0x0633 }, +{ 0x0634, 0x0634, 0x0634 }, +{ 0x0635, 0x0635, 0x0635 }, +{ 0x0636, 0x0636, 0x0636 }, +{ 0x0637, 0x0637, 0x0637 }, +{ 0x0638, 0x0638, 0x0638 }, +{ 0x0639, 0x0639, 0x0639 }, +{ 0x063A, 0x063A, 0x063A }, +{ 0x0640, 0x0640, 0x0640 }, +{ 0x0641, 0x0641, 0x0641 }, +{ 0x0642, 0x0642, 0x0642 }, +{ 0x0643, 0x0643, 0x0643 }, +{ 0x0644, 0x0644, 0x0644 }, +{ 0x0645, 0x0645, 0x0645 }, +{ 0x0646, 0x0646, 0x0646 }, +{ 0x0647, 0x0647, 0x0647 }, +{ 0x0648, 0x0648, 0x0648 }, +{ 0x0649, 0x0649, 0x0649 }, +{ 0x064A, 0x064A, 0x064A }, +{ 0x064B, 0x064B, 0x064B }, +{ 0x064C, 0x064C, 0x064C }, +{ 0x064D, 0x064D, 0x064D }, +{ 0x064E, 0x064E, 0x064E }, +{ 0x064F, 0x064F, 0x064F }, +{ 0x0650, 0x0650, 0x0650 }, +{ 0x0651, 0x0651, 0x0651 }, +{ 0x0652, 0x0652, 0x0652 }, +{ 0x0653, 0x0653, 0x0653 }, +{ 0x0654, 0x0654, 0x0654 }, +{ 0x0655, 0x0655, 0x0655 }, +{ 0x0656, 0x0656, 0x0656 }, +{ 0x0657, 0x0657, 0x0657 }, +{ 0x0658, 0x0658, 0x0658 }, +{ 0x0659, 0x0659, 0x0659 }, +{ 0x065A, 0x065A, 0x065A }, +{ 0x065B, 0x065B, 0x065B }, +{ 0x065C, 0x065C, 0x065C }, +{ 0x065D, 0x065D, 0x065D }, +{ 0x065E, 0x065E, 0x065E }, +{ 0x066E, 0x066E, 0x066E }, +{ 0x066F, 0x066F, 0x066F }, +{ 0x0670, 0x0670, 0x0670 }, +{ 0x0671, 0x0671, 0x0671 }, +{ 0x0672, 0x0672, 0x0672 }, +{ 0x0673, 0x0673, 0x0673 }, +{ 0x0674, 0x0674, 0x0674 }, +{ 0x0675, 0x0675, 0x0675 }, +{ 0x0676, 0x0676, 0x0676 }, +{ 0x0677, 0x0677, 0x0677 }, +{ 0x0678, 0x0678, 0x0678 }, +{ 0x0679, 0x0679, 0x0679 }, +{ 0x067A, 0x067A, 0x067A }, +{ 0x067B, 0x067B, 0x067B }, +{ 0x067C, 0x067C, 0x067C }, +{ 0x067D, 0x067D, 0x067D }, +{ 0x067E, 0x067E, 0x067E }, +{ 0x067F, 0x067F, 0x067F }, +{ 0x0680, 0x0680, 0x0680 }, +{ 0x0681, 0x0681, 0x0681 }, +{ 0x0682, 0x0682, 0x0682 }, +{ 0x0683, 0x0683, 0x0683 }, +{ 0x0684, 0x0684, 0x0684 }, +{ 0x0685, 0x0685, 0x0685 }, +{ 0x0686, 0x0686, 0x0686 }, +{ 0x0687, 0x0687, 0x0687 }, +{ 0x0688, 0x0688, 0x0688 }, +{ 0x0689, 0x0689, 0x0689 }, +{ 0x068A, 0x068A, 0x068A }, +{ 0x068B, 0x068B, 0x068B }, +{ 0x068C, 0x068C, 0x068C }, +{ 0x068D, 0x068D, 0x068D }, +{ 0x068E, 0x068E, 0x068E }, +{ 0x068F, 0x068F, 0x068F }, +{ 0x0690, 0x0690, 0x0690 }, +{ 0x0691, 0x0691, 0x0691 }, +{ 0x0692, 0x0692, 0x0692 }, +{ 0x0693, 0x0693, 0x0693 }, +{ 0x0694, 0x0694, 0x0694 }, +{ 0x0695, 0x0695, 0x0695 }, +{ 0x0696, 0x0696, 0x0696 }, +{ 0x0697, 0x0697, 0x0697 }, +{ 0x0698, 0x0698, 0x0698 }, +{ 0x0699, 0x0699, 0x0699 }, +{ 0x069A, 0x069A, 0x069A }, +{ 0x069B, 0x069B, 0x069B }, +{ 0x069C, 0x069C, 0x069C }, +{ 0x069D, 0x069D, 0x069D }, +{ 0x069E, 0x069E, 0x069E }, +{ 0x069F, 0x069F, 0x069F }, +{ 0x06A0, 0x06A0, 0x06A0 }, +{ 0x06A1, 0x06A1, 0x06A1 }, +{ 0x06A2, 0x06A2, 0x06A2 }, +{ 0x06A3, 0x06A3, 0x06A3 }, +{ 0x06A4, 0x06A4, 0x06A4 }, +{ 0x06A5, 0x06A5, 0x06A5 }, +{ 0x06A6, 0x06A6, 0x06A6 }, +{ 0x06A7, 0x06A7, 0x06A7 }, +{ 0x06A8, 0x06A8, 0x06A8 }, +{ 0x06A9, 0x06A9, 0x06A9 }, +{ 0x06AA, 0x06AA, 0x06AA }, +{ 0x06AB, 0x06AB, 0x06AB }, +{ 0x06AC, 0x06AC, 0x06AC }, +{ 0x06AD, 0x06AD, 0x06AD }, +{ 0x06AE, 0x06AE, 0x06AE }, +{ 0x06AF, 0x06AF, 0x06AF }, +{ 0x06B0, 0x06B0, 0x06B0 }, +{ 0x06B1, 0x06B1, 0x06B1 }, +{ 0x06B2, 0x06B2, 0x06B2 }, +{ 0x06B3, 0x06B3, 0x06B3 }, +{ 0x06B4, 0x06B4, 0x06B4 }, +{ 0x06B5, 0x06B5, 0x06B5 }, +{ 0x06B6, 0x06B6, 0x06B6 }, +{ 0x06B7, 0x06B7, 0x06B7 }, +{ 0x06B8, 0x06B8, 0x06B8 }, +{ 0x06B9, 0x06B9, 0x06B9 }, +{ 0x06BA, 0x06BA, 0x06BA }, +{ 0x06BB, 0x06BB, 0x06BB }, +{ 0x06BC, 0x06BC, 0x06BC }, +{ 0x06BD, 0x06BD, 0x06BD }, +{ 0x06BE, 0x06BE, 0x06BE }, +{ 0x06BF, 0x06BF, 0x06BF }, +{ 0x06C0, 0x06C0, 0x06C0 }, +{ 0x06C1, 0x06C1, 0x06C1 }, +{ 0x06C2, 0x06C2, 0x06C2 }, +{ 0x06C3, 0x06C3, 0x06C3 }, +{ 0x06C4, 0x06C4, 0x06C4 }, +{ 0x06C5, 0x06C5, 0x06C5 }, +{ 0x06C6, 0x06C6, 0x06C6 }, +{ 0x06C7, 0x06C7, 0x06C7 }, +{ 0x06C8, 0x06C8, 0x06C8 }, +{ 0x06C9, 0x06C9, 0x06C9 }, +{ 0x06CA, 0x06CA, 0x06CA }, +{ 0x06CB, 0x06CB, 0x06CB }, +{ 0x06CC, 0x06CC, 0x06CC }, +{ 0x06CD, 0x06CD, 0x06CD }, +{ 0x06CE, 0x06CE, 0x06CE }, +{ 0x06CF, 0x06CF, 0x06CF }, +{ 0x06D0, 0x06D0, 0x06D0 }, +{ 0x06D1, 0x06D1, 0x06D1 }, +{ 0x06D2, 0x06D2, 0x06D2 }, +{ 0x06D3, 0x06D3, 0x06D3 }, +{ 0x06D5, 0x06D5, 0x06D5 }, +{ 0x06D6, 0x06D6, 0x06D6 }, +{ 0x06D7, 0x06D7, 0x06D7 }, +{ 0x06D8, 0x06D8, 0x06D8 }, +{ 0x06D9, 0x06D9, 0x06D9 }, +{ 0x06DA, 0x06DA, 0x06DA }, +{ 0x06DB, 0x06DB, 0x06DB }, +{ 0x06DC, 0x06DC, 0x06DC }, +{ 0x06DF, 0x06DF, 0x06DF }, +{ 0x06E0, 0x06E0, 0x06E0 }, +{ 0x06E1, 0x06E1, 0x06E1 }, +{ 0x06E2, 0x06E2, 0x06E2 }, +{ 0x06E3, 0x06E3, 0x06E3 }, +{ 0x06E4, 0x06E4, 0x06E4 }, +{ 0x06E5, 0x06E5, 0x06E5 }, +{ 0x06E6, 0x06E6, 0x06E6 }, +{ 0x06E7, 0x06E7, 0x06E7 }, +{ 0x06E8, 0x06E8, 0x06E8 }, +{ 0x06EA, 0x06EA, 0x06EA }, +{ 0x06EB, 0x06EB, 0x06EB }, +{ 0x06EC, 0x06EC, 0x06EC }, +{ 0x06ED, 0x06ED, 0x06ED }, +{ 0x06EE, 0x06EE, 0x06EE }, +{ 0x06EF, 0x06EF, 0x06EF }, +{ 0x06FA, 0x06FA, 0x06FA }, +{ 0x06FB, 0x06FB, 0x06FB }, +{ 0x06FC, 0x06FC, 0x06FC }, +{ 0x06FF, 0x06FF, 0x06FF }, +{ 0x0710, 0x0710, 0x0710 }, +{ 0x0711, 0x0711, 0x0711 }, +{ 0x0712, 0x0712, 0x0712 }, +{ 0x0713, 0x0713, 0x0713 }, +{ 0x0714, 0x0714, 0x0714 }, +{ 0x0715, 0x0715, 0x0715 }, +{ 0x0716, 0x0716, 0x0716 }, +{ 0x0717, 0x0717, 0x0717 }, +{ 0x0718, 0x0718, 0x0718 }, +{ 0x0719, 0x0719, 0x0719 }, +{ 0x071A, 0x071A, 0x071A }, +{ 0x071B, 0x071B, 0x071B }, +{ 0x071C, 0x071C, 0x071C }, +{ 0x071D, 0x071D, 0x071D }, +{ 0x071E, 0x071E, 0x071E }, +{ 0x071F, 0x071F, 0x071F }, +{ 0x0720, 0x0720, 0x0720 }, +{ 0x0721, 0x0721, 0x0721 }, +{ 0x0722, 0x0722, 0x0722 }, +{ 0x0723, 0x0723, 0x0723 }, +{ 0x0724, 0x0724, 0x0724 }, +{ 0x0725, 0x0725, 0x0725 }, +{ 0x0726, 0x0726, 0x0726 }, +{ 0x0727, 0x0727, 0x0727 }, +{ 0x0728, 0x0728, 0x0728 }, +{ 0x0729, 0x0729, 0x0729 }, +{ 0x072A, 0x072A, 0x072A }, +{ 0x072B, 0x072B, 0x072B }, +{ 0x072C, 0x072C, 0x072C }, +{ 0x072D, 0x072D, 0x072D }, +{ 0x072E, 0x072E, 0x072E }, +{ 0x072F, 0x072F, 0x072F }, +{ 0x0730, 0x0730, 0x0730 }, +{ 0x0731, 0x0731, 0x0731 }, +{ 0x0732, 0x0732, 0x0732 }, +{ 0x0733, 0x0733, 0x0733 }, +{ 0x0734, 0x0734, 0x0734 }, +{ 0x0735, 0x0735, 0x0735 }, +{ 0x0736, 0x0736, 0x0736 }, +{ 0x0737, 0x0737, 0x0737 }, +{ 0x0738, 0x0738, 0x0738 }, +{ 0x0739, 0x0739, 0x0739 }, +{ 0x073A, 0x073A, 0x073A }, +{ 0x073B, 0x073B, 0x073B }, +{ 0x073C, 0x073C, 0x073C }, +{ 0x073D, 0x073D, 0x073D }, +{ 0x073E, 0x073E, 0x073E }, +{ 0x073F, 0x073F, 0x073F }, +{ 0x0740, 0x0740, 0x0740 }, +{ 0x0741, 0x0741, 0x0741 }, +{ 0x0742, 0x0742, 0x0742 }, +{ 0x0743, 0x0743, 0x0743 }, +{ 0x0744, 0x0744, 0x0744 }, +{ 0x0745, 0x0745, 0x0745 }, +{ 0x0746, 0x0746, 0x0746 }, +{ 0x0747, 0x0747, 0x0747 }, +{ 0x0748, 0x0748, 0x0748 }, +{ 0x0749, 0x0749, 0x0749 }, +{ 0x074A, 0x074A, 0x074A }, +{ 0x074D, 0x074D, 0x074D }, +{ 0x074E, 0x074E, 0x074E }, +{ 0x074F, 0x074F, 0x074F }, +{ 0x0750, 0x0750, 0x0750 }, +{ 0x0751, 0x0751, 0x0751 }, +{ 0x0752, 0x0752, 0x0752 }, +{ 0x0753, 0x0753, 0x0753 }, +{ 0x0754, 0x0754, 0x0754 }, +{ 0x0755, 0x0755, 0x0755 }, +{ 0x0756, 0x0756, 0x0756 }, +{ 0x0757, 0x0757, 0x0757 }, +{ 0x0758, 0x0758, 0x0758 }, +{ 0x0759, 0x0759, 0x0759 }, +{ 0x075A, 0x075A, 0x075A }, +{ 0x075B, 0x075B, 0x075B }, +{ 0x075C, 0x075C, 0x075C }, +{ 0x075D, 0x075D, 0x075D }, +{ 0x075E, 0x075E, 0x075E }, +{ 0x075F, 0x075F, 0x075F }, +{ 0x0760, 0x0760, 0x0760 }, +{ 0x0761, 0x0761, 0x0761 }, +{ 0x0762, 0x0762, 0x0762 }, +{ 0x0763, 0x0763, 0x0763 }, +{ 0x0764, 0x0764, 0x0764 }, +{ 0x0765, 0x0765, 0x0765 }, +{ 0x0766, 0x0766, 0x0766 }, +{ 0x0767, 0x0767, 0x0767 }, +{ 0x0768, 0x0768, 0x0768 }, +{ 0x0769, 0x0769, 0x0769 }, +{ 0x076A, 0x076A, 0x076A }, +{ 0x076B, 0x076B, 0x076B }, +{ 0x076C, 0x076C, 0x076C }, +{ 0x076D, 0x076D, 0x076D }, +{ 0x0780, 0x0780, 0x0780 }, +{ 0x0781, 0x0781, 0x0781 }, +{ 0x0782, 0x0782, 0x0782 }, +{ 0x0783, 0x0783, 0x0783 }, +{ 0x0784, 0x0784, 0x0784 }, +{ 0x0785, 0x0785, 0x0785 }, +{ 0x0786, 0x0786, 0x0786 }, +{ 0x0787, 0x0787, 0x0787 }, +{ 0x0788, 0x0788, 0x0788 }, +{ 0x0789, 0x0789, 0x0789 }, +{ 0x078A, 0x078A, 0x078A }, +{ 0x078B, 0x078B, 0x078B }, +{ 0x078C, 0x078C, 0x078C }, +{ 0x078D, 0x078D, 0x078D }, +{ 0x078E, 0x078E, 0x078E }, +{ 0x078F, 0x078F, 0x078F }, +{ 0x0790, 0x0790, 0x0790 }, +{ 0x0791, 0x0791, 0x0791 }, +{ 0x0792, 0x0792, 0x0792 }, +{ 0x0793, 0x0793, 0x0793 }, +{ 0x0794, 0x0794, 0x0794 }, +{ 0x0795, 0x0795, 0x0795 }, +{ 0x0796, 0x0796, 0x0796 }, +{ 0x0797, 0x0797, 0x0797 }, +{ 0x0798, 0x0798, 0x0798 }, +{ 0x0799, 0x0799, 0x0799 }, +{ 0x079A, 0x079A, 0x079A }, +{ 0x079B, 0x079B, 0x079B }, +{ 0x079C, 0x079C, 0x079C }, +{ 0x079D, 0x079D, 0x079D }, +{ 0x079E, 0x079E, 0x079E }, +{ 0x079F, 0x079F, 0x079F }, +{ 0x07A0, 0x07A0, 0x07A0 }, +{ 0x07A1, 0x07A1, 0x07A1 }, +{ 0x07A2, 0x07A2, 0x07A2 }, +{ 0x07A3, 0x07A3, 0x07A3 }, +{ 0x07A4, 0x07A4, 0x07A4 }, +{ 0x07A5, 0x07A5, 0x07A5 }, +{ 0x07A6, 0x07A6, 0x07A6 }, +{ 0x07A7, 0x07A7, 0x07A7 }, +{ 0x07A8, 0x07A8, 0x07A8 }, +{ 0x07A9, 0x07A9, 0x07A9 }, +{ 0x07AA, 0x07AA, 0x07AA }, +{ 0x07AB, 0x07AB, 0x07AB }, +{ 0x07AC, 0x07AC, 0x07AC }, +{ 0x07AD, 0x07AD, 0x07AD }, +{ 0x07AE, 0x07AE, 0x07AE }, +{ 0x07AF, 0x07AF, 0x07AF }, +{ 0x07B0, 0x07B0, 0x07B0 }, +{ 0x07B1, 0x07B1, 0x07B1 }, +{ 0x0901, 0x0901, 0x0901 }, +{ 0x0902, 0x0902, 0x0902 }, +{ 0x0904, 0x0904, 0x0904 }, +{ 0x0905, 0x0905, 0x0905 }, +{ 0x0906, 0x0906, 0x0906 }, +{ 0x0907, 0x0907, 0x0907 }, +{ 0x0908, 0x0908, 0x0908 }, +{ 0x0909, 0x0909, 0x0909 }, +{ 0x090A, 0x090A, 0x090A }, +{ 0x090B, 0x090B, 0x090B }, +{ 0x090C, 0x090C, 0x090C }, +{ 0x090D, 0x090D, 0x090D }, +{ 0x090E, 0x090E, 0x090E }, +{ 0x090F, 0x090F, 0x090F }, +{ 0x0910, 0x0910, 0x0910 }, +{ 0x0911, 0x0911, 0x0911 }, +{ 0x0912, 0x0912, 0x0912 }, +{ 0x0913, 0x0913, 0x0913 }, +{ 0x0914, 0x0914, 0x0914 }, +{ 0x0915, 0x0915, 0x0915 }, +{ 0x0916, 0x0916, 0x0916 }, +{ 0x0917, 0x0917, 0x0917 }, +{ 0x0918, 0x0918, 0x0918 }, +{ 0x0919, 0x0919, 0x0919 }, +{ 0x091A, 0x091A, 0x091A }, +{ 0x091B, 0x091B, 0x091B }, +{ 0x091C, 0x091C, 0x091C }, +{ 0x091D, 0x091D, 0x091D }, +{ 0x091E, 0x091E, 0x091E }, +{ 0x091F, 0x091F, 0x091F }, +{ 0x0920, 0x0920, 0x0920 }, +{ 0x0921, 0x0921, 0x0921 }, +{ 0x0922, 0x0922, 0x0922 }, +{ 0x0923, 0x0923, 0x0923 }, +{ 0x0924, 0x0924, 0x0924 }, +{ 0x0925, 0x0925, 0x0925 }, +{ 0x0926, 0x0926, 0x0926 }, +{ 0x0927, 0x0927, 0x0927 }, +{ 0x0928, 0x0928, 0x0928 }, +{ 0x0929, 0x0929, 0x0929 }, +{ 0x092A, 0x092A, 0x092A }, +{ 0x092B, 0x092B, 0x092B }, +{ 0x092C, 0x092C, 0x092C }, +{ 0x092D, 0x092D, 0x092D }, +{ 0x092E, 0x092E, 0x092E }, +{ 0x092F, 0x092F, 0x092F }, +{ 0x0930, 0x0930, 0x0930 }, +{ 0x0931, 0x0931, 0x0931 }, +{ 0x0932, 0x0932, 0x0932 }, +{ 0x0933, 0x0933, 0x0933 }, +{ 0x0934, 0x0934, 0x0934 }, +{ 0x0935, 0x0935, 0x0935 }, +{ 0x0936, 0x0936, 0x0936 }, +{ 0x0937, 0x0937, 0x0937 }, +{ 0x0938, 0x0938, 0x0938 }, +{ 0x0939, 0x0939, 0x0939 }, +{ 0x093C, 0x093C, 0x093C }, +{ 0x093D, 0x093D, 0x093D }, +{ 0x0941, 0x0941, 0x0941 }, +{ 0x0942, 0x0942, 0x0942 }, +{ 0x0943, 0x0943, 0x0943 }, +{ 0x0944, 0x0944, 0x0944 }, +{ 0x0945, 0x0945, 0x0945 }, +{ 0x0946, 0x0946, 0x0946 }, +{ 0x0947, 0x0947, 0x0947 }, +{ 0x0948, 0x0948, 0x0948 }, +{ 0x094D, 0x094D, 0x094D }, +{ 0x0950, 0x0950, 0x0950 }, +{ 0x0951, 0x0951, 0x0951 }, +{ 0x0952, 0x0952, 0x0952 }, +{ 0x0953, 0x0953, 0x0953 }, +{ 0x0954, 0x0954, 0x0954 }, +{ 0x0958, 0x0958, 0x0958 }, +{ 0x0959, 0x0959, 0x0959 }, +{ 0x095A, 0x095A, 0x095A }, +{ 0x095B, 0x095B, 0x095B }, +{ 0x095C, 0x095C, 0x095C }, +{ 0x095D, 0x095D, 0x095D }, +{ 0x095E, 0x095E, 0x095E }, +{ 0x095F, 0x095F, 0x095F }, +{ 0x0960, 0x0960, 0x0960 }, +{ 0x0961, 0x0961, 0x0961 }, +{ 0x0962, 0x0962, 0x0962 }, +{ 0x0963, 0x0963, 0x0963 }, +{ 0x097D, 0x097D, 0x097D }, +{ 0x0981, 0x0981, 0x0981 }, +{ 0x0985, 0x0985, 0x0985 }, +{ 0x0986, 0x0986, 0x0986 }, +{ 0x0987, 0x0987, 0x0987 }, +{ 0x0988, 0x0988, 0x0988 }, +{ 0x0989, 0x0989, 0x0989 }, +{ 0x098A, 0x098A, 0x098A }, +{ 0x098B, 0x098B, 0x098B }, +{ 0x098C, 0x098C, 0x098C }, +{ 0x098F, 0x098F, 0x098F }, +{ 0x0990, 0x0990, 0x0990 }, +{ 0x0993, 0x0993, 0x0993 }, +{ 0x0994, 0x0994, 0x0994 }, +{ 0x0995, 0x0995, 0x0995 }, +{ 0x0996, 0x0996, 0x0996 }, +{ 0x0997, 0x0997, 0x0997 }, +{ 0x0998, 0x0998, 0x0998 }, +{ 0x0999, 0x0999, 0x0999 }, +{ 0x099A, 0x099A, 0x099A }, +{ 0x099B, 0x099B, 0x099B }, +{ 0x099C, 0x099C, 0x099C }, +{ 0x099D, 0x099D, 0x099D }, +{ 0x099E, 0x099E, 0x099E }, +{ 0x099F, 0x099F, 0x099F }, +{ 0x09A0, 0x09A0, 0x09A0 }, +{ 0x09A1, 0x09A1, 0x09A1 }, +{ 0x09A2, 0x09A2, 0x09A2 }, +{ 0x09A3, 0x09A3, 0x09A3 }, +{ 0x09A4, 0x09A4, 0x09A4 }, +{ 0x09A5, 0x09A5, 0x09A5 }, +{ 0x09A6, 0x09A6, 0x09A6 }, +{ 0x09A7, 0x09A7, 0x09A7 }, +{ 0x09A8, 0x09A8, 0x09A8 }, +{ 0x09AA, 0x09AA, 0x09AA }, +{ 0x09AB, 0x09AB, 0x09AB }, +{ 0x09AC, 0x09AC, 0x09AC }, +{ 0x09AD, 0x09AD, 0x09AD }, +{ 0x09AE, 0x09AE, 0x09AE }, +{ 0x09AF, 0x09AF, 0x09AF }, +{ 0x09B0, 0x09B0, 0x09B0 }, +{ 0x09B2, 0x09B2, 0x09B2 }, +{ 0x09B6, 0x09B6, 0x09B6 }, +{ 0x09B7, 0x09B7, 0x09B7 }, +{ 0x09B8, 0x09B8, 0x09B8 }, +{ 0x09B9, 0x09B9, 0x09B9 }, +{ 0x09BC, 0x09BC, 0x09BC }, +{ 0x09BD, 0x09BD, 0x09BD }, +{ 0x09C1, 0x09C1, 0x09C1 }, +{ 0x09C2, 0x09C2, 0x09C2 }, +{ 0x09C3, 0x09C3, 0x09C3 }, +{ 0x09C4, 0x09C4, 0x09C4 }, +{ 0x09CD, 0x09CD, 0x09CD }, +{ 0x09CE, 0x09CE, 0x09CE }, +{ 0x09DC, 0x09DC, 0x09DC }, +{ 0x09DD, 0x09DD, 0x09DD }, +{ 0x09DF, 0x09DF, 0x09DF }, +{ 0x09E0, 0x09E0, 0x09E0 }, +{ 0x09E1, 0x09E1, 0x09E1 }, +{ 0x09E2, 0x09E2, 0x09E2 }, +{ 0x09E3, 0x09E3, 0x09E3 }, +{ 0x09F0, 0x09F0, 0x09F0 }, +{ 0x09F1, 0x09F1, 0x09F1 }, +{ 0x0A01, 0x0A01, 0x0A01 }, +{ 0x0A02, 0x0A02, 0x0A02 }, +{ 0x0A05, 0x0A05, 0x0A05 }, +{ 0x0A06, 0x0A06, 0x0A06 }, +{ 0x0A07, 0x0A07, 0x0A07 }, +{ 0x0A08, 0x0A08, 0x0A08 }, +{ 0x0A09, 0x0A09, 0x0A09 }, +{ 0x0A0A, 0x0A0A, 0x0A0A }, +{ 0x0A0F, 0x0A0F, 0x0A0F }, +{ 0x0A10, 0x0A10, 0x0A10 }, +{ 0x0A13, 0x0A13, 0x0A13 }, +{ 0x0A14, 0x0A14, 0x0A14 }, +{ 0x0A15, 0x0A15, 0x0A15 }, +{ 0x0A16, 0x0A16, 0x0A16 }, +{ 0x0A17, 0x0A17, 0x0A17 }, +{ 0x0A18, 0x0A18, 0x0A18 }, +{ 0x0A19, 0x0A19, 0x0A19 }, +{ 0x0A1A, 0x0A1A, 0x0A1A }, +{ 0x0A1B, 0x0A1B, 0x0A1B }, +{ 0x0A1C, 0x0A1C, 0x0A1C }, +{ 0x0A1D, 0x0A1D, 0x0A1D }, +{ 0x0A1E, 0x0A1E, 0x0A1E }, +{ 0x0A1F, 0x0A1F, 0x0A1F }, +{ 0x0A20, 0x0A20, 0x0A20 }, +{ 0x0A21, 0x0A21, 0x0A21 }, +{ 0x0A22, 0x0A22, 0x0A22 }, +{ 0x0A23, 0x0A23, 0x0A23 }, +{ 0x0A24, 0x0A24, 0x0A24 }, +{ 0x0A25, 0x0A25, 0x0A25 }, +{ 0x0A26, 0x0A26, 0x0A26 }, +{ 0x0A27, 0x0A27, 0x0A27 }, +{ 0x0A28, 0x0A28, 0x0A28 }, +{ 0x0A2A, 0x0A2A, 0x0A2A }, +{ 0x0A2B, 0x0A2B, 0x0A2B }, +{ 0x0A2C, 0x0A2C, 0x0A2C }, +{ 0x0A2D, 0x0A2D, 0x0A2D }, +{ 0x0A2E, 0x0A2E, 0x0A2E }, +{ 0x0A2F, 0x0A2F, 0x0A2F }, +{ 0x0A30, 0x0A30, 0x0A30 }, +{ 0x0A32, 0x0A32, 0x0A32 }, +{ 0x0A33, 0x0A33, 0x0A33 }, +{ 0x0A35, 0x0A35, 0x0A35 }, +{ 0x0A36, 0x0A36, 0x0A36 }, +{ 0x0A38, 0x0A38, 0x0A38 }, +{ 0x0A39, 0x0A39, 0x0A39 }, +{ 0x0A3C, 0x0A3C, 0x0A3C }, +{ 0x0A41, 0x0A41, 0x0A41 }, +{ 0x0A42, 0x0A42, 0x0A42 }, +{ 0x0A47, 0x0A47, 0x0A47 }, +{ 0x0A48, 0x0A48, 0x0A48 }, +{ 0x0A4B, 0x0A4B, 0x0A4B }, +{ 0x0A4C, 0x0A4C, 0x0A4C }, +{ 0x0A4D, 0x0A4D, 0x0A4D }, +{ 0x0A59, 0x0A59, 0x0A59 }, +{ 0x0A5A, 0x0A5A, 0x0A5A }, +{ 0x0A5B, 0x0A5B, 0x0A5B }, +{ 0x0A5C, 0x0A5C, 0x0A5C }, +{ 0x0A5E, 0x0A5E, 0x0A5E }, +{ 0x0A70, 0x0A70, 0x0A70 }, +{ 0x0A71, 0x0A71, 0x0A71 }, +{ 0x0A72, 0x0A72, 0x0A72 }, +{ 0x0A73, 0x0A73, 0x0A73 }, +{ 0x0A74, 0x0A74, 0x0A74 }, +{ 0x0A81, 0x0A81, 0x0A81 }, +{ 0x0A82, 0x0A82, 0x0A82 }, +{ 0x0A85, 0x0A85, 0x0A85 }, +{ 0x0A86, 0x0A86, 0x0A86 }, +{ 0x0A87, 0x0A87, 0x0A87 }, +{ 0x0A88, 0x0A88, 0x0A88 }, +{ 0x0A89, 0x0A89, 0x0A89 }, +{ 0x0A8A, 0x0A8A, 0x0A8A }, +{ 0x0A8B, 0x0A8B, 0x0A8B }, +{ 0x0A8C, 0x0A8C, 0x0A8C }, +{ 0x0A8D, 0x0A8D, 0x0A8D }, +{ 0x0A8F, 0x0A8F, 0x0A8F }, +{ 0x0A90, 0x0A90, 0x0A90 }, +{ 0x0A91, 0x0A91, 0x0A91 }, +{ 0x0A93, 0x0A93, 0x0A93 }, +{ 0x0A94, 0x0A94, 0x0A94 }, +{ 0x0A95, 0x0A95, 0x0A95 }, +{ 0x0A96, 0x0A96, 0x0A96 }, +{ 0x0A97, 0x0A97, 0x0A97 }, +{ 0x0A98, 0x0A98, 0x0A98 }, +{ 0x0A99, 0x0A99, 0x0A99 }, +{ 0x0A9A, 0x0A9A, 0x0A9A }, +{ 0x0A9B, 0x0A9B, 0x0A9B }, +{ 0x0A9C, 0x0A9C, 0x0A9C }, +{ 0x0A9D, 0x0A9D, 0x0A9D }, +{ 0x0A9E, 0x0A9E, 0x0A9E }, +{ 0x0A9F, 0x0A9F, 0x0A9F }, +{ 0x0AA0, 0x0AA0, 0x0AA0 }, +{ 0x0AA1, 0x0AA1, 0x0AA1 }, +{ 0x0AA2, 0x0AA2, 0x0AA2 }, +{ 0x0AA3, 0x0AA3, 0x0AA3 }, +{ 0x0AA4, 0x0AA4, 0x0AA4 }, +{ 0x0AA5, 0x0AA5, 0x0AA5 }, +{ 0x0AA6, 0x0AA6, 0x0AA6 }, +{ 0x0AA7, 0x0AA7, 0x0AA7 }, +{ 0x0AA8, 0x0AA8, 0x0AA8 }, +{ 0x0AAA, 0x0AAA, 0x0AAA }, +{ 0x0AAB, 0x0AAB, 0x0AAB }, +{ 0x0AAC, 0x0AAC, 0x0AAC }, +{ 0x0AAD, 0x0AAD, 0x0AAD }, +{ 0x0AAE, 0x0AAE, 0x0AAE }, +{ 0x0AAF, 0x0AAF, 0x0AAF }, +{ 0x0AB0, 0x0AB0, 0x0AB0 }, +{ 0x0AB2, 0x0AB2, 0x0AB2 }, +{ 0x0AB3, 0x0AB3, 0x0AB3 }, +{ 0x0AB5, 0x0AB5, 0x0AB5 }, +{ 0x0AB6, 0x0AB6, 0x0AB6 }, +{ 0x0AB7, 0x0AB7, 0x0AB7 }, +{ 0x0AB8, 0x0AB8, 0x0AB8 }, +{ 0x0AB9, 0x0AB9, 0x0AB9 }, +{ 0x0ABC, 0x0ABC, 0x0ABC }, +{ 0x0ABD, 0x0ABD, 0x0ABD }, +{ 0x0AC1, 0x0AC1, 0x0AC1 }, +{ 0x0AC2, 0x0AC2, 0x0AC2 }, +{ 0x0AC3, 0x0AC3, 0x0AC3 }, +{ 0x0AC4, 0x0AC4, 0x0AC4 }, +{ 0x0AC5, 0x0AC5, 0x0AC5 }, +{ 0x0AC7, 0x0AC7, 0x0AC7 }, +{ 0x0AC8, 0x0AC8, 0x0AC8 }, +{ 0x0ACD, 0x0ACD, 0x0ACD }, +{ 0x0AD0, 0x0AD0, 0x0AD0 }, +{ 0x0AE0, 0x0AE0, 0x0AE0 }, +{ 0x0AE1, 0x0AE1, 0x0AE1 }, +{ 0x0AE2, 0x0AE2, 0x0AE2 }, +{ 0x0AE3, 0x0AE3, 0x0AE3 }, +{ 0x0B01, 0x0B01, 0x0B01 }, +{ 0x0B05, 0x0B05, 0x0B05 }, +{ 0x0B06, 0x0B06, 0x0B06 }, +{ 0x0B07, 0x0B07, 0x0B07 }, +{ 0x0B08, 0x0B08, 0x0B08 }, +{ 0x0B09, 0x0B09, 0x0B09 }, +{ 0x0B0A, 0x0B0A, 0x0B0A }, +{ 0x0B0B, 0x0B0B, 0x0B0B }, +{ 0x0B0C, 0x0B0C, 0x0B0C }, +{ 0x0B0F, 0x0B0F, 0x0B0F }, +{ 0x0B10, 0x0B10, 0x0B10 }, +{ 0x0B13, 0x0B13, 0x0B13 }, +{ 0x0B14, 0x0B14, 0x0B14 }, +{ 0x0B15, 0x0B15, 0x0B15 }, +{ 0x0B16, 0x0B16, 0x0B16 }, +{ 0x0B17, 0x0B17, 0x0B17 }, +{ 0x0B18, 0x0B18, 0x0B18 }, +{ 0x0B19, 0x0B19, 0x0B19 }, +{ 0x0B1A, 0x0B1A, 0x0B1A }, +{ 0x0B1B, 0x0B1B, 0x0B1B }, +{ 0x0B1C, 0x0B1C, 0x0B1C }, +{ 0x0B1D, 0x0B1D, 0x0B1D }, +{ 0x0B1E, 0x0B1E, 0x0B1E }, +{ 0x0B1F, 0x0B1F, 0x0B1F }, +{ 0x0B20, 0x0B20, 0x0B20 }, +{ 0x0B21, 0x0B21, 0x0B21 }, +{ 0x0B22, 0x0B22, 0x0B22 }, +{ 0x0B23, 0x0B23, 0x0B23 }, +{ 0x0B24, 0x0B24, 0x0B24 }, +{ 0x0B25, 0x0B25, 0x0B25 }, +{ 0x0B26, 0x0B26, 0x0B26 }, +{ 0x0B27, 0x0B27, 0x0B27 }, +{ 0x0B28, 0x0B28, 0x0B28 }, +{ 0x0B2A, 0x0B2A, 0x0B2A }, +{ 0x0B2B, 0x0B2B, 0x0B2B }, +{ 0x0B2C, 0x0B2C, 0x0B2C }, +{ 0x0B2D, 0x0B2D, 0x0B2D }, +{ 0x0B2E, 0x0B2E, 0x0B2E }, +{ 0x0B2F, 0x0B2F, 0x0B2F }, +{ 0x0B30, 0x0B30, 0x0B30 }, +{ 0x0B32, 0x0B32, 0x0B32 }, +{ 0x0B33, 0x0B33, 0x0B33 }, +{ 0x0B35, 0x0B35, 0x0B35 }, +{ 0x0B36, 0x0B36, 0x0B36 }, +{ 0x0B37, 0x0B37, 0x0B37 }, +{ 0x0B38, 0x0B38, 0x0B38 }, +{ 0x0B39, 0x0B39, 0x0B39 }, +{ 0x0B3C, 0x0B3C, 0x0B3C }, +{ 0x0B3D, 0x0B3D, 0x0B3D }, +{ 0x0B3F, 0x0B3F, 0x0B3F }, +{ 0x0B41, 0x0B41, 0x0B41 }, +{ 0x0B42, 0x0B42, 0x0B42 }, +{ 0x0B43, 0x0B43, 0x0B43 }, +{ 0x0B4D, 0x0B4D, 0x0B4D }, +{ 0x0B56, 0x0B56, 0x0B56 }, +{ 0x0B5C, 0x0B5C, 0x0B5C }, +{ 0x0B5D, 0x0B5D, 0x0B5D }, +{ 0x0B5F, 0x0B5F, 0x0B5F }, +{ 0x0B60, 0x0B60, 0x0B60 }, +{ 0x0B61, 0x0B61, 0x0B61 }, +{ 0x0B71, 0x0B71, 0x0B71 }, +{ 0x0B82, 0x0B82, 0x0B82 }, +{ 0x0B83, 0x0B83, 0x0B83 }, +{ 0x0B85, 0x0B85, 0x0B85 }, +{ 0x0B86, 0x0B86, 0x0B86 }, +{ 0x0B87, 0x0B87, 0x0B87 }, +{ 0x0B88, 0x0B88, 0x0B88 }, +{ 0x0B89, 0x0B89, 0x0B89 }, +{ 0x0B8A, 0x0B8A, 0x0B8A }, +{ 0x0B8E, 0x0B8E, 0x0B8E }, +{ 0x0B8F, 0x0B8F, 0x0B8F }, +{ 0x0B90, 0x0B90, 0x0B90 }, +{ 0x0B92, 0x0B92, 0x0B92 }, +{ 0x0B93, 0x0B93, 0x0B93 }, +{ 0x0B94, 0x0B94, 0x0B94 }, +{ 0x0B95, 0x0B95, 0x0B95 }, +{ 0x0B99, 0x0B99, 0x0B99 }, +{ 0x0B9A, 0x0B9A, 0x0B9A }, +{ 0x0B9C, 0x0B9C, 0x0B9C }, +{ 0x0B9E, 0x0B9E, 0x0B9E }, +{ 0x0B9F, 0x0B9F, 0x0B9F }, +{ 0x0BA3, 0x0BA3, 0x0BA3 }, +{ 0x0BA4, 0x0BA4, 0x0BA4 }, +{ 0x0BA8, 0x0BA8, 0x0BA8 }, +{ 0x0BA9, 0x0BA9, 0x0BA9 }, +{ 0x0BAA, 0x0BAA, 0x0BAA }, +{ 0x0BAE, 0x0BAE, 0x0BAE }, +{ 0x0BAF, 0x0BAF, 0x0BAF }, +{ 0x0BB0, 0x0BB0, 0x0BB0 }, +{ 0x0BB1, 0x0BB1, 0x0BB1 }, +{ 0x0BB2, 0x0BB2, 0x0BB2 }, +{ 0x0BB3, 0x0BB3, 0x0BB3 }, +{ 0x0BB4, 0x0BB4, 0x0BB4 }, +{ 0x0BB5, 0x0BB5, 0x0BB5 }, +{ 0x0BB6, 0x0BB6, 0x0BB6 }, +{ 0x0BB7, 0x0BB7, 0x0BB7 }, +{ 0x0BB8, 0x0BB8, 0x0BB8 }, +{ 0x0BB9, 0x0BB9, 0x0BB9 }, +{ 0x0BC0, 0x0BC0, 0x0BC0 }, +{ 0x0BCD, 0x0BCD, 0x0BCD }, +{ 0x0C05, 0x0C05, 0x0C05 }, +{ 0x0C06, 0x0C06, 0x0C06 }, +{ 0x0C07, 0x0C07, 0x0C07 }, +{ 0x0C08, 0x0C08, 0x0C08 }, +{ 0x0C09, 0x0C09, 0x0C09 }, +{ 0x0C0A, 0x0C0A, 0x0C0A }, +{ 0x0C0B, 0x0C0B, 0x0C0B }, +{ 0x0C0C, 0x0C0C, 0x0C0C }, +{ 0x0C0E, 0x0C0E, 0x0C0E }, +{ 0x0C0F, 0x0C0F, 0x0C0F }, +{ 0x0C10, 0x0C10, 0x0C10 }, +{ 0x0C12, 0x0C12, 0x0C12 }, +{ 0x0C13, 0x0C13, 0x0C13 }, +{ 0x0C14, 0x0C14, 0x0C14 }, +{ 0x0C15, 0x0C15, 0x0C15 }, +{ 0x0C16, 0x0C16, 0x0C16 }, +{ 0x0C17, 0x0C17, 0x0C17 }, +{ 0x0C18, 0x0C18, 0x0C18 }, +{ 0x0C19, 0x0C19, 0x0C19 }, +{ 0x0C1A, 0x0C1A, 0x0C1A }, +{ 0x0C1B, 0x0C1B, 0x0C1B }, +{ 0x0C1C, 0x0C1C, 0x0C1C }, +{ 0x0C1D, 0x0C1D, 0x0C1D }, +{ 0x0C1E, 0x0C1E, 0x0C1E }, +{ 0x0C1F, 0x0C1F, 0x0C1F }, +{ 0x0C20, 0x0C20, 0x0C20 }, +{ 0x0C21, 0x0C21, 0x0C21 }, +{ 0x0C22, 0x0C22, 0x0C22 }, +{ 0x0C23, 0x0C23, 0x0C23 }, +{ 0x0C24, 0x0C24, 0x0C24 }, +{ 0x0C25, 0x0C25, 0x0C25 }, +{ 0x0C26, 0x0C26, 0x0C26 }, +{ 0x0C27, 0x0C27, 0x0C27 }, +{ 0x0C28, 0x0C28, 0x0C28 }, +{ 0x0C2A, 0x0C2A, 0x0C2A }, +{ 0x0C2B, 0x0C2B, 0x0C2B }, +{ 0x0C2C, 0x0C2C, 0x0C2C }, +{ 0x0C2D, 0x0C2D, 0x0C2D }, +{ 0x0C2E, 0x0C2E, 0x0C2E }, +{ 0x0C2F, 0x0C2F, 0x0C2F }, +{ 0x0C30, 0x0C30, 0x0C30 }, +{ 0x0C31, 0x0C31, 0x0C31 }, +{ 0x0C32, 0x0C32, 0x0C32 }, +{ 0x0C33, 0x0C33, 0x0C33 }, +{ 0x0C35, 0x0C35, 0x0C35 }, +{ 0x0C36, 0x0C36, 0x0C36 }, +{ 0x0C37, 0x0C37, 0x0C37 }, +{ 0x0C38, 0x0C38, 0x0C38 }, +{ 0x0C39, 0x0C39, 0x0C39 }, +{ 0x0C3E, 0x0C3E, 0x0C3E }, +{ 0x0C3F, 0x0C3F, 0x0C3F }, +{ 0x0C40, 0x0C40, 0x0C40 }, +{ 0x0C46, 0x0C46, 0x0C46 }, +{ 0x0C47, 0x0C47, 0x0C47 }, +{ 0x0C48, 0x0C48, 0x0C48 }, +{ 0x0C4A, 0x0C4A, 0x0C4A }, +{ 0x0C4B, 0x0C4B, 0x0C4B }, +{ 0x0C4C, 0x0C4C, 0x0C4C }, +{ 0x0C4D, 0x0C4D, 0x0C4D }, +{ 0x0C55, 0x0C55, 0x0C55 }, +{ 0x0C56, 0x0C56, 0x0C56 }, +{ 0x0C60, 0x0C60, 0x0C60 }, +{ 0x0C61, 0x0C61, 0x0C61 }, +{ 0x0C85, 0x0C85, 0x0C85 }, +{ 0x0C86, 0x0C86, 0x0C86 }, +{ 0x0C87, 0x0C87, 0x0C87 }, +{ 0x0C88, 0x0C88, 0x0C88 }, +{ 0x0C89, 0x0C89, 0x0C89 }, +{ 0x0C8A, 0x0C8A, 0x0C8A }, +{ 0x0C8B, 0x0C8B, 0x0C8B }, +{ 0x0C8C, 0x0C8C, 0x0C8C }, +{ 0x0C8E, 0x0C8E, 0x0C8E }, +{ 0x0C8F, 0x0C8F, 0x0C8F }, +{ 0x0C90, 0x0C90, 0x0C90 }, +{ 0x0C92, 0x0C92, 0x0C92 }, +{ 0x0C93, 0x0C93, 0x0C93 }, +{ 0x0C94, 0x0C94, 0x0C94 }, +{ 0x0C95, 0x0C95, 0x0C95 }, +{ 0x0C96, 0x0C96, 0x0C96 }, +{ 0x0C97, 0x0C97, 0x0C97 }, +{ 0x0C98, 0x0C98, 0x0C98 }, +{ 0x0C99, 0x0C99, 0x0C99 }, +{ 0x0C9A, 0x0C9A, 0x0C9A }, +{ 0x0C9B, 0x0C9B, 0x0C9B }, +{ 0x0C9C, 0x0C9C, 0x0C9C }, +{ 0x0C9D, 0x0C9D, 0x0C9D }, +{ 0x0C9E, 0x0C9E, 0x0C9E }, +{ 0x0C9F, 0x0C9F, 0x0C9F }, +{ 0x0CA0, 0x0CA0, 0x0CA0 }, +{ 0x0CA1, 0x0CA1, 0x0CA1 }, +{ 0x0CA2, 0x0CA2, 0x0CA2 }, +{ 0x0CA3, 0x0CA3, 0x0CA3 }, +{ 0x0CA4, 0x0CA4, 0x0CA4 }, +{ 0x0CA5, 0x0CA5, 0x0CA5 }, +{ 0x0CA6, 0x0CA6, 0x0CA6 }, +{ 0x0CA7, 0x0CA7, 0x0CA7 }, +{ 0x0CA8, 0x0CA8, 0x0CA8 }, +{ 0x0CAA, 0x0CAA, 0x0CAA }, +{ 0x0CAB, 0x0CAB, 0x0CAB }, +{ 0x0CAC, 0x0CAC, 0x0CAC }, +{ 0x0CAD, 0x0CAD, 0x0CAD }, +{ 0x0CAE, 0x0CAE, 0x0CAE }, +{ 0x0CAF, 0x0CAF, 0x0CAF }, +{ 0x0CB0, 0x0CB0, 0x0CB0 }, +{ 0x0CB1, 0x0CB1, 0x0CB1 }, +{ 0x0CB2, 0x0CB2, 0x0CB2 }, +{ 0x0CB3, 0x0CB3, 0x0CB3 }, +{ 0x0CB5, 0x0CB5, 0x0CB5 }, +{ 0x0CB6, 0x0CB6, 0x0CB6 }, +{ 0x0CB7, 0x0CB7, 0x0CB7 }, +{ 0x0CB8, 0x0CB8, 0x0CB8 }, +{ 0x0CB9, 0x0CB9, 0x0CB9 }, +{ 0x0CBC, 0x0CBC, 0x0CBC }, +{ 0x0CBD, 0x0CBD, 0x0CBD }, +{ 0x0CBF, 0x0CBF, 0x0CBF }, +{ 0x0CC6, 0x0CC6, 0x0CC6 }, +{ 0x0CCC, 0x0CCC, 0x0CCC }, +{ 0x0CCD, 0x0CCD, 0x0CCD }, +{ 0x0CDE, 0x0CDE, 0x0CDE }, +{ 0x0CE0, 0x0CE0, 0x0CE0 }, +{ 0x0CE1, 0x0CE1, 0x0CE1 }, +{ 0x0D05, 0x0D05, 0x0D05 }, +{ 0x0D06, 0x0D06, 0x0D06 }, +{ 0x0D07, 0x0D07, 0x0D07 }, +{ 0x0D08, 0x0D08, 0x0D08 }, +{ 0x0D09, 0x0D09, 0x0D09 }, +{ 0x0D0A, 0x0D0A, 0x0D0A }, +{ 0x0D0B, 0x0D0B, 0x0D0B }, +{ 0x0D0C, 0x0D0C, 0x0D0C }, +{ 0x0D0E, 0x0D0E, 0x0D0E }, +{ 0x0D0F, 0x0D0F, 0x0D0F }, +{ 0x0D10, 0x0D10, 0x0D10 }, +{ 0x0D12, 0x0D12, 0x0D12 }, +{ 0x0D13, 0x0D13, 0x0D13 }, +{ 0x0D14, 0x0D14, 0x0D14 }, +{ 0x0D15, 0x0D15, 0x0D15 }, +{ 0x0D16, 0x0D16, 0x0D16 }, +{ 0x0D17, 0x0D17, 0x0D17 }, +{ 0x0D18, 0x0D18, 0x0D18 }, +{ 0x0D19, 0x0D19, 0x0D19 }, +{ 0x0D1A, 0x0D1A, 0x0D1A }, +{ 0x0D1B, 0x0D1B, 0x0D1B }, +{ 0x0D1C, 0x0D1C, 0x0D1C }, +{ 0x0D1D, 0x0D1D, 0x0D1D }, +{ 0x0D1E, 0x0D1E, 0x0D1E }, +{ 0x0D1F, 0x0D1F, 0x0D1F }, +{ 0x0D20, 0x0D20, 0x0D20 }, +{ 0x0D21, 0x0D21, 0x0D21 }, +{ 0x0D22, 0x0D22, 0x0D22 }, +{ 0x0D23, 0x0D23, 0x0D23 }, +{ 0x0D24, 0x0D24, 0x0D24 }, +{ 0x0D25, 0x0D25, 0x0D25 }, +{ 0x0D26, 0x0D26, 0x0D26 }, +{ 0x0D27, 0x0D27, 0x0D27 }, +{ 0x0D28, 0x0D28, 0x0D28 }, +{ 0x0D2A, 0x0D2A, 0x0D2A }, +{ 0x0D2B, 0x0D2B, 0x0D2B }, +{ 0x0D2C, 0x0D2C, 0x0D2C }, +{ 0x0D2D, 0x0D2D, 0x0D2D }, +{ 0x0D2E, 0x0D2E, 0x0D2E }, +{ 0x0D2F, 0x0D2F, 0x0D2F }, +{ 0x0D30, 0x0D30, 0x0D30 }, +{ 0x0D31, 0x0D31, 0x0D31 }, +{ 0x0D32, 0x0D32, 0x0D32 }, +{ 0x0D33, 0x0D33, 0x0D33 }, +{ 0x0D34, 0x0D34, 0x0D34 }, +{ 0x0D35, 0x0D35, 0x0D35 }, +{ 0x0D36, 0x0D36, 0x0D36 }, +{ 0x0D37, 0x0D37, 0x0D37 }, +{ 0x0D38, 0x0D38, 0x0D38 }, +{ 0x0D39, 0x0D39, 0x0D39 }, +{ 0x0D41, 0x0D41, 0x0D41 }, +{ 0x0D42, 0x0D42, 0x0D42 }, +{ 0x0D43, 0x0D43, 0x0D43 }, +{ 0x0D4D, 0x0D4D, 0x0D4D }, +{ 0x0D60, 0x0D60, 0x0D60 }, +{ 0x0D61, 0x0D61, 0x0D61 }, +{ 0x0D85, 0x0D85, 0x0D85 }, +{ 0x0D86, 0x0D86, 0x0D86 }, +{ 0x0D87, 0x0D87, 0x0D87 }, +{ 0x0D88, 0x0D88, 0x0D88 }, +{ 0x0D89, 0x0D89, 0x0D89 }, +{ 0x0D8A, 0x0D8A, 0x0D8A }, +{ 0x0D8B, 0x0D8B, 0x0D8B }, +{ 0x0D8C, 0x0D8C, 0x0D8C }, +{ 0x0D8D, 0x0D8D, 0x0D8D }, +{ 0x0D8E, 0x0D8E, 0x0D8E }, +{ 0x0D8F, 0x0D8F, 0x0D8F }, +{ 0x0D90, 0x0D90, 0x0D90 }, +{ 0x0D91, 0x0D91, 0x0D91 }, +{ 0x0D92, 0x0D92, 0x0D92 }, +{ 0x0D93, 0x0D93, 0x0D93 }, +{ 0x0D94, 0x0D94, 0x0D94 }, +{ 0x0D95, 0x0D95, 0x0D95 }, +{ 0x0D96, 0x0D96, 0x0D96 }, +{ 0x0D9A, 0x0D9A, 0x0D9A }, +{ 0x0D9B, 0x0D9B, 0x0D9B }, +{ 0x0D9C, 0x0D9C, 0x0D9C }, +{ 0x0D9D, 0x0D9D, 0x0D9D }, +{ 0x0D9E, 0x0D9E, 0x0D9E }, +{ 0x0D9F, 0x0D9F, 0x0D9F }, +{ 0x0DA0, 0x0DA0, 0x0DA0 }, +{ 0x0DA1, 0x0DA1, 0x0DA1 }, +{ 0x0DA2, 0x0DA2, 0x0DA2 }, +{ 0x0DA3, 0x0DA3, 0x0DA3 }, +{ 0x0DA4, 0x0DA4, 0x0DA4 }, +{ 0x0DA5, 0x0DA5, 0x0DA5 }, +{ 0x0DA6, 0x0DA6, 0x0DA6 }, +{ 0x0DA7, 0x0DA7, 0x0DA7 }, +{ 0x0DA8, 0x0DA8, 0x0DA8 }, +{ 0x0DA9, 0x0DA9, 0x0DA9 }, +{ 0x0DAA, 0x0DAA, 0x0DAA }, +{ 0x0DAB, 0x0DAB, 0x0DAB }, +{ 0x0DAC, 0x0DAC, 0x0DAC }, +{ 0x0DAD, 0x0DAD, 0x0DAD }, +{ 0x0DAE, 0x0DAE, 0x0DAE }, +{ 0x0DAF, 0x0DAF, 0x0DAF }, +{ 0x0DB0, 0x0DB0, 0x0DB0 }, +{ 0x0DB1, 0x0DB1, 0x0DB1 }, +{ 0x0DB3, 0x0DB3, 0x0DB3 }, +{ 0x0DB4, 0x0DB4, 0x0DB4 }, +{ 0x0DB5, 0x0DB5, 0x0DB5 }, +{ 0x0DB6, 0x0DB6, 0x0DB6 }, +{ 0x0DB7, 0x0DB7, 0x0DB7 }, +{ 0x0DB8, 0x0DB8, 0x0DB8 }, +{ 0x0DB9, 0x0DB9, 0x0DB9 }, +{ 0x0DBA, 0x0DBA, 0x0DBA }, +{ 0x0DBB, 0x0DBB, 0x0DBB }, +{ 0x0DBD, 0x0DBD, 0x0DBD }, +{ 0x0DC0, 0x0DC0, 0x0DC0 }, +{ 0x0DC1, 0x0DC1, 0x0DC1 }, +{ 0x0DC2, 0x0DC2, 0x0DC2 }, +{ 0x0DC3, 0x0DC3, 0x0DC3 }, +{ 0x0DC4, 0x0DC4, 0x0DC4 }, +{ 0x0DC5, 0x0DC5, 0x0DC5 }, +{ 0x0DC6, 0x0DC6, 0x0DC6 }, +{ 0x0DCA, 0x0DCA, 0x0DCA }, +{ 0x0DD2, 0x0DD2, 0x0DD2 }, +{ 0x0DD3, 0x0DD3, 0x0DD3 }, +{ 0x0DD4, 0x0DD4, 0x0DD4 }, +{ 0x0DD6, 0x0DD6, 0x0DD6 }, +{ 0x0E01, 0x0E01, 0x0E01 }, +{ 0x0E02, 0x0E02, 0x0E02 }, +{ 0x0E03, 0x0E03, 0x0E03 }, +{ 0x0E04, 0x0E04, 0x0E04 }, +{ 0x0E05, 0x0E05, 0x0E05 }, +{ 0x0E06, 0x0E06, 0x0E06 }, +{ 0x0E07, 0x0E07, 0x0E07 }, +{ 0x0E08, 0x0E08, 0x0E08 }, +{ 0x0E09, 0x0E09, 0x0E09 }, +{ 0x0E0A, 0x0E0A, 0x0E0A }, +{ 0x0E0B, 0x0E0B, 0x0E0B }, +{ 0x0E0C, 0x0E0C, 0x0E0C }, +{ 0x0E0D, 0x0E0D, 0x0E0D }, +{ 0x0E0E, 0x0E0E, 0x0E0E }, +{ 0x0E0F, 0x0E0F, 0x0E0F }, +{ 0x0E10, 0x0E10, 0x0E10 }, +{ 0x0E11, 0x0E11, 0x0E11 }, +{ 0x0E12, 0x0E12, 0x0E12 }, +{ 0x0E13, 0x0E13, 0x0E13 }, +{ 0x0E14, 0x0E14, 0x0E14 }, +{ 0x0E15, 0x0E15, 0x0E15 }, +{ 0x0E16, 0x0E16, 0x0E16 }, +{ 0x0E17, 0x0E17, 0x0E17 }, +{ 0x0E18, 0x0E18, 0x0E18 }, +{ 0x0E19, 0x0E19, 0x0E19 }, +{ 0x0E1A, 0x0E1A, 0x0E1A }, +{ 0x0E1B, 0x0E1B, 0x0E1B }, +{ 0x0E1C, 0x0E1C, 0x0E1C }, +{ 0x0E1D, 0x0E1D, 0x0E1D }, +{ 0x0E1E, 0x0E1E, 0x0E1E }, +{ 0x0E1F, 0x0E1F, 0x0E1F }, +{ 0x0E20, 0x0E20, 0x0E20 }, +{ 0x0E21, 0x0E21, 0x0E21 }, +{ 0x0E22, 0x0E22, 0x0E22 }, +{ 0x0E23, 0x0E23, 0x0E23 }, +{ 0x0E24, 0x0E24, 0x0E24 }, +{ 0x0E25, 0x0E25, 0x0E25 }, +{ 0x0E26, 0x0E26, 0x0E26 }, +{ 0x0E27, 0x0E27, 0x0E27 }, +{ 0x0E28, 0x0E28, 0x0E28 }, +{ 0x0E29, 0x0E29, 0x0E29 }, +{ 0x0E2A, 0x0E2A, 0x0E2A }, +{ 0x0E2B, 0x0E2B, 0x0E2B }, +{ 0x0E2C, 0x0E2C, 0x0E2C }, +{ 0x0E2D, 0x0E2D, 0x0E2D }, +{ 0x0E2E, 0x0E2E, 0x0E2E }, +{ 0x0E2F, 0x0E2F, 0x0E2F }, +{ 0x0E30, 0x0E30, 0x0E30 }, +{ 0x0E31, 0x0E31, 0x0E31 }, +{ 0x0E32, 0x0E32, 0x0E32 }, +{ 0x0E33, 0x0E33, 0x0E33 }, +{ 0x0E34, 0x0E34, 0x0E34 }, +{ 0x0E35, 0x0E35, 0x0E35 }, +{ 0x0E36, 0x0E36, 0x0E36 }, +{ 0x0E37, 0x0E37, 0x0E37 }, +{ 0x0E38, 0x0E38, 0x0E38 }, +{ 0x0E39, 0x0E39, 0x0E39 }, +{ 0x0E3A, 0x0E3A, 0x0E3A }, +{ 0x0E40, 0x0E40, 0x0E40 }, +{ 0x0E41, 0x0E41, 0x0E41 }, +{ 0x0E42, 0x0E42, 0x0E42 }, +{ 0x0E43, 0x0E43, 0x0E43 }, +{ 0x0E44, 0x0E44, 0x0E44 }, +{ 0x0E45, 0x0E45, 0x0E45 }, +{ 0x0E46, 0x0E46, 0x0E46 }, +{ 0x0E47, 0x0E47, 0x0E47 }, +{ 0x0E48, 0x0E48, 0x0E48 }, +{ 0x0E49, 0x0E49, 0x0E49 }, +{ 0x0E4A, 0x0E4A, 0x0E4A }, +{ 0x0E4B, 0x0E4B, 0x0E4B }, +{ 0x0E4C, 0x0E4C, 0x0E4C }, +{ 0x0E4D, 0x0E4D, 0x0E4D }, +{ 0x0E4E, 0x0E4E, 0x0E4E }, +{ 0x0E81, 0x0E81, 0x0E81 }, +{ 0x0E82, 0x0E82, 0x0E82 }, +{ 0x0E84, 0x0E84, 0x0E84 }, +{ 0x0E87, 0x0E87, 0x0E87 }, +{ 0x0E88, 0x0E88, 0x0E88 }, +{ 0x0E8A, 0x0E8A, 0x0E8A }, +{ 0x0E8D, 0x0E8D, 0x0E8D }, +{ 0x0E94, 0x0E94, 0x0E94 }, +{ 0x0E95, 0x0E95, 0x0E95 }, +{ 0x0E96, 0x0E96, 0x0E96 }, +{ 0x0E97, 0x0E97, 0x0E97 }, +{ 0x0E99, 0x0E99, 0x0E99 }, +{ 0x0E9A, 0x0E9A, 0x0E9A }, +{ 0x0E9B, 0x0E9B, 0x0E9B }, +{ 0x0E9C, 0x0E9C, 0x0E9C }, +{ 0x0E9D, 0x0E9D, 0x0E9D }, +{ 0x0E9E, 0x0E9E, 0x0E9E }, +{ 0x0E9F, 0x0E9F, 0x0E9F }, +{ 0x0EA1, 0x0EA1, 0x0EA1 }, +{ 0x0EA2, 0x0EA2, 0x0EA2 }, +{ 0x0EA3, 0x0EA3, 0x0EA3 }, +{ 0x0EA5, 0x0EA5, 0x0EA5 }, +{ 0x0EA7, 0x0EA7, 0x0EA7 }, +{ 0x0EAA, 0x0EAA, 0x0EAA }, +{ 0x0EAB, 0x0EAB, 0x0EAB }, +{ 0x0EAD, 0x0EAD, 0x0EAD }, +{ 0x0EAE, 0x0EAE, 0x0EAE }, +{ 0x0EAF, 0x0EAF, 0x0EAF }, +{ 0x0EB0, 0x0EB0, 0x0EB0 }, +{ 0x0EB1, 0x0EB1, 0x0EB1 }, +{ 0x0EB2, 0x0EB2, 0x0EB2 }, +{ 0x0EB3, 0x0EB3, 0x0EB3 }, +{ 0x0EB4, 0x0EB4, 0x0EB4 }, +{ 0x0EB5, 0x0EB5, 0x0EB5 }, +{ 0x0EB6, 0x0EB6, 0x0EB6 }, +{ 0x0EB7, 0x0EB7, 0x0EB7 }, +{ 0x0EB8, 0x0EB8, 0x0EB8 }, +{ 0x0EB9, 0x0EB9, 0x0EB9 }, +{ 0x0EBB, 0x0EBB, 0x0EBB }, +{ 0x0EBC, 0x0EBC, 0x0EBC }, +{ 0x0EBD, 0x0EBD, 0x0EBD }, +{ 0x0EC0, 0x0EC0, 0x0EC0 }, +{ 0x0EC1, 0x0EC1, 0x0EC1 }, +{ 0x0EC2, 0x0EC2, 0x0EC2 }, +{ 0x0EC3, 0x0EC3, 0x0EC3 }, +{ 0x0EC4, 0x0EC4, 0x0EC4 }, +{ 0x0EC6, 0x0EC6, 0x0EC6 }, +{ 0x0EC8, 0x0EC8, 0x0EC8 }, +{ 0x0EC9, 0x0EC9, 0x0EC9 }, +{ 0x0ECA, 0x0ECA, 0x0ECA }, +{ 0x0ECB, 0x0ECB, 0x0ECB }, +{ 0x0ECC, 0x0ECC, 0x0ECC }, +{ 0x0ECD, 0x0ECD, 0x0ECD }, +{ 0x0EDC, 0x0EDC, 0x0EDC }, +{ 0x0EDD, 0x0EDD, 0x0EDD }, +{ 0x0F00, 0x0F00, 0x0F00 }, +{ 0x0F18, 0x0F18, 0x0F18 }, +{ 0x0F19, 0x0F19, 0x0F19 }, +{ 0x0F35, 0x0F35, 0x0F35 }, +{ 0x0F37, 0x0F37, 0x0F37 }, +{ 0x0F39, 0x0F39, 0x0F39 }, +{ 0x0F40, 0x0F40, 0x0F40 }, +{ 0x0F41, 0x0F41, 0x0F41 }, +{ 0x0F42, 0x0F42, 0x0F42 }, +{ 0x0F43, 0x0F43, 0x0F43 }, +{ 0x0F44, 0x0F44, 0x0F44 }, +{ 0x0F45, 0x0F45, 0x0F45 }, +{ 0x0F46, 0x0F46, 0x0F46 }, +{ 0x0F47, 0x0F47, 0x0F47 }, +{ 0x0F49, 0x0F49, 0x0F49 }, +{ 0x0F4A, 0x0F4A, 0x0F4A }, +{ 0x0F4B, 0x0F4B, 0x0F4B }, +{ 0x0F4C, 0x0F4C, 0x0F4C }, +{ 0x0F4D, 0x0F4D, 0x0F4D }, +{ 0x0F4E, 0x0F4E, 0x0F4E }, +{ 0x0F4F, 0x0F4F, 0x0F4F }, +{ 0x0F50, 0x0F50, 0x0F50 }, +{ 0x0F51, 0x0F51, 0x0F51 }, +{ 0x0F52, 0x0F52, 0x0F52 }, +{ 0x0F53, 0x0F53, 0x0F53 }, +{ 0x0F54, 0x0F54, 0x0F54 }, +{ 0x0F55, 0x0F55, 0x0F55 }, +{ 0x0F56, 0x0F56, 0x0F56 }, +{ 0x0F57, 0x0F57, 0x0F57 }, +{ 0x0F58, 0x0F58, 0x0F58 }, +{ 0x0F59, 0x0F59, 0x0F59 }, +{ 0x0F5A, 0x0F5A, 0x0F5A }, +{ 0x0F5B, 0x0F5B, 0x0F5B }, +{ 0x0F5C, 0x0F5C, 0x0F5C }, +{ 0x0F5D, 0x0F5D, 0x0F5D }, +{ 0x0F5E, 0x0F5E, 0x0F5E }, +{ 0x0F5F, 0x0F5F, 0x0F5F }, +{ 0x0F60, 0x0F60, 0x0F60 }, +{ 0x0F61, 0x0F61, 0x0F61 }, +{ 0x0F62, 0x0F62, 0x0F62 }, +{ 0x0F63, 0x0F63, 0x0F63 }, +{ 0x0F64, 0x0F64, 0x0F64 }, +{ 0x0F65, 0x0F65, 0x0F65 }, +{ 0x0F66, 0x0F66, 0x0F66 }, +{ 0x0F67, 0x0F67, 0x0F67 }, +{ 0x0F68, 0x0F68, 0x0F68 }, +{ 0x0F69, 0x0F69, 0x0F69 }, +{ 0x0F6A, 0x0F6A, 0x0F6A }, +{ 0x0F71, 0x0F71, 0x0F71 }, +{ 0x0F72, 0x0F72, 0x0F72 }, +{ 0x0F73, 0x0F73, 0x0F73 }, +{ 0x0F74, 0x0F74, 0x0F74 }, +{ 0x0F75, 0x0F75, 0x0F75 }, +{ 0x0F76, 0x0F76, 0x0F76 }, +{ 0x0F77, 0x0F77, 0x0F77 }, +{ 0x0F78, 0x0F78, 0x0F78 }, +{ 0x0F79, 0x0F79, 0x0F79 }, +{ 0x0F7A, 0x0F7A, 0x0F7A }, +{ 0x0F7B, 0x0F7B, 0x0F7B }, +{ 0x0F7C, 0x0F7C, 0x0F7C }, +{ 0x0F7D, 0x0F7D, 0x0F7D }, +{ 0x0F7E, 0x0F7E, 0x0F7E }, +{ 0x0F80, 0x0F80, 0x0F80 }, +{ 0x0F81, 0x0F81, 0x0F81 }, +{ 0x0F82, 0x0F82, 0x0F82 }, +{ 0x0F83, 0x0F83, 0x0F83 }, +{ 0x0F84, 0x0F84, 0x0F84 }, +{ 0x0F86, 0x0F86, 0x0F86 }, +{ 0x0F87, 0x0F87, 0x0F87 }, +{ 0x0F88, 0x0F88, 0x0F88 }, +{ 0x0F89, 0x0F89, 0x0F89 }, +{ 0x0F8A, 0x0F8A, 0x0F8A }, +{ 0x0F8B, 0x0F8B, 0x0F8B }, +{ 0x0F90, 0x0F90, 0x0F90 }, +{ 0x0F91, 0x0F91, 0x0F91 }, +{ 0x0F92, 0x0F92, 0x0F92 }, +{ 0x0F93, 0x0F93, 0x0F93 }, +{ 0x0F94, 0x0F94, 0x0F94 }, +{ 0x0F95, 0x0F95, 0x0F95 }, +{ 0x0F96, 0x0F96, 0x0F96 }, +{ 0x0F97, 0x0F97, 0x0F97 }, +{ 0x0F99, 0x0F99, 0x0F99 }, +{ 0x0F9A, 0x0F9A, 0x0F9A }, +{ 0x0F9B, 0x0F9B, 0x0F9B }, +{ 0x0F9C, 0x0F9C, 0x0F9C }, +{ 0x0F9D, 0x0F9D, 0x0F9D }, +{ 0x0F9E, 0x0F9E, 0x0F9E }, +{ 0x0F9F, 0x0F9F, 0x0F9F }, +{ 0x0FA0, 0x0FA0, 0x0FA0 }, +{ 0x0FA1, 0x0FA1, 0x0FA1 }, +{ 0x0FA2, 0x0FA2, 0x0FA2 }, +{ 0x0FA3, 0x0FA3, 0x0FA3 }, +{ 0x0FA4, 0x0FA4, 0x0FA4 }, +{ 0x0FA5, 0x0FA5, 0x0FA5 }, +{ 0x0FA6, 0x0FA6, 0x0FA6 }, +{ 0x0FA7, 0x0FA7, 0x0FA7 }, +{ 0x0FA8, 0x0FA8, 0x0FA8 }, +{ 0x0FA9, 0x0FA9, 0x0FA9 }, +{ 0x0FAA, 0x0FAA, 0x0FAA }, +{ 0x0FAB, 0x0FAB, 0x0FAB }, +{ 0x0FAC, 0x0FAC, 0x0FAC }, +{ 0x0FAD, 0x0FAD, 0x0FAD }, +{ 0x0FAE, 0x0FAE, 0x0FAE }, +{ 0x0FAF, 0x0FAF, 0x0FAF }, +{ 0x0FB0, 0x0FB0, 0x0FB0 }, +{ 0x0FB1, 0x0FB1, 0x0FB1 }, +{ 0x0FB2, 0x0FB2, 0x0FB2 }, +{ 0x0FB3, 0x0FB3, 0x0FB3 }, +{ 0x0FB4, 0x0FB4, 0x0FB4 }, +{ 0x0FB5, 0x0FB5, 0x0FB5 }, +{ 0x0FB6, 0x0FB6, 0x0FB6 }, +{ 0x0FB7, 0x0FB7, 0x0FB7 }, +{ 0x0FB8, 0x0FB8, 0x0FB8 }, +{ 0x0FB9, 0x0FB9, 0x0FB9 }, +{ 0x0FBA, 0x0FBA, 0x0FBA }, +{ 0x0FBB, 0x0FBB, 0x0FBB }, +{ 0x0FBC, 0x0FBC, 0x0FBC }, +{ 0x0FC6, 0x0FC6, 0x0FC6 }, +{ 0x1000, 0x1000, 0x1000 }, +{ 0x1001, 0x1001, 0x1001 }, +{ 0x1002, 0x1002, 0x1002 }, +{ 0x1003, 0x1003, 0x1003 }, +{ 0x1004, 0x1004, 0x1004 }, +{ 0x1005, 0x1005, 0x1005 }, +{ 0x1006, 0x1006, 0x1006 }, +{ 0x1007, 0x1007, 0x1007 }, +{ 0x1008, 0x1008, 0x1008 }, +{ 0x1009, 0x1009, 0x1009 }, +{ 0x100A, 0x100A, 0x100A }, +{ 0x100B, 0x100B, 0x100B }, +{ 0x100C, 0x100C, 0x100C }, +{ 0x100D, 0x100D, 0x100D }, +{ 0x100E, 0x100E, 0x100E }, +{ 0x100F, 0x100F, 0x100F }, +{ 0x1010, 0x1010, 0x1010 }, +{ 0x1011, 0x1011, 0x1011 }, +{ 0x1012, 0x1012, 0x1012 }, +{ 0x1013, 0x1013, 0x1013 }, +{ 0x1014, 0x1014, 0x1014 }, +{ 0x1015, 0x1015, 0x1015 }, +{ 0x1016, 0x1016, 0x1016 }, +{ 0x1017, 0x1017, 0x1017 }, +{ 0x1018, 0x1018, 0x1018 }, +{ 0x1019, 0x1019, 0x1019 }, +{ 0x101A, 0x101A, 0x101A }, +{ 0x101B, 0x101B, 0x101B }, +{ 0x101C, 0x101C, 0x101C }, +{ 0x101D, 0x101D, 0x101D }, +{ 0x101E, 0x101E, 0x101E }, +{ 0x101F, 0x101F, 0x101F }, +{ 0x1020, 0x1020, 0x1020 }, +{ 0x1021, 0x1021, 0x1021 }, +{ 0x1023, 0x1023, 0x1023 }, +{ 0x1024, 0x1024, 0x1024 }, +{ 0x1025, 0x1025, 0x1025 }, +{ 0x1026, 0x1026, 0x1026 }, +{ 0x1027, 0x1027, 0x1027 }, +{ 0x1029, 0x1029, 0x1029 }, +{ 0x102A, 0x102A, 0x102A }, +{ 0x102D, 0x102D, 0x102D }, +{ 0x102E, 0x102E, 0x102E }, +{ 0x102F, 0x102F, 0x102F }, +{ 0x1030, 0x1030, 0x1030 }, +{ 0x1032, 0x1032, 0x1032 }, +{ 0x1036, 0x1036, 0x1036 }, +{ 0x1037, 0x1037, 0x1037 }, +{ 0x1039, 0x1039, 0x1039 }, +{ 0x1050, 0x1050, 0x1050 }, +{ 0x1051, 0x1051, 0x1051 }, +{ 0x1052, 0x1052, 0x1052 }, +{ 0x1053, 0x1053, 0x1053 }, +{ 0x1054, 0x1054, 0x1054 }, +{ 0x1055, 0x1055, 0x1055 }, +{ 0x1058, 0x1058, 0x1058 }, +{ 0x1059, 0x1059, 0x1059 }, +{ 0x10A0, 0x10A0, 0x2D00 }, +{ 0x10A1, 0x10A1, 0x2D01 }, +{ 0x10A2, 0x10A2, 0x2D02 }, +{ 0x10A3, 0x10A3, 0x2D03 }, +{ 0x10A4, 0x10A4, 0x2D04 }, +{ 0x10A5, 0x10A5, 0x2D05 }, +{ 0x10A6, 0x10A6, 0x2D06 }, +{ 0x10A7, 0x10A7, 0x2D07 }, +{ 0x10A8, 0x10A8, 0x2D08 }, +{ 0x10A9, 0x10A9, 0x2D09 }, +{ 0x10AA, 0x10AA, 0x2D0A }, +{ 0x10AB, 0x10AB, 0x2D0B }, +{ 0x10AC, 0x10AC, 0x2D0C }, +{ 0x10AD, 0x10AD, 0x2D0D }, +{ 0x10AE, 0x10AE, 0x2D0E }, +{ 0x10AF, 0x10AF, 0x2D0F }, +{ 0x10B0, 0x10B0, 0x2D10 }, +{ 0x10B1, 0x10B1, 0x2D11 }, +{ 0x10B2, 0x10B2, 0x2D12 }, +{ 0x10B3, 0x10B3, 0x2D13 }, +{ 0x10B4, 0x10B4, 0x2D14 }, +{ 0x10B5, 0x10B5, 0x2D15 }, +{ 0x10B6, 0x10B6, 0x2D16 }, +{ 0x10B7, 0x10B7, 0x2D17 }, +{ 0x10B8, 0x10B8, 0x2D18 }, +{ 0x10B9, 0x10B9, 0x2D19 }, +{ 0x10BA, 0x10BA, 0x2D1A }, +{ 0x10BB, 0x10BB, 0x2D1B }, +{ 0x10BC, 0x10BC, 0x2D1C }, +{ 0x10BD, 0x10BD, 0x2D1D }, +{ 0x10BE, 0x10BE, 0x2D1E }, +{ 0x10BF, 0x10BF, 0x2D1F }, +{ 0x10C0, 0x10C0, 0x2D20 }, +{ 0x10C1, 0x10C1, 0x2D21 }, +{ 0x10C2, 0x10C2, 0x2D22 }, +{ 0x10C3, 0x10C3, 0x2D23 }, +{ 0x10C4, 0x10C4, 0x2D24 }, +{ 0x10C5, 0x10C5, 0x2D25 }, +{ 0x10D0, 0x10D0, 0x10D0 }, +{ 0x10D1, 0x10D1, 0x10D1 }, +{ 0x10D2, 0x10D2, 0x10D2 }, +{ 0x10D3, 0x10D3, 0x10D3 }, +{ 0x10D4, 0x10D4, 0x10D4 }, +{ 0x10D5, 0x10D5, 0x10D5 }, +{ 0x10D6, 0x10D6, 0x10D6 }, +{ 0x10D7, 0x10D7, 0x10D7 }, +{ 0x10D8, 0x10D8, 0x10D8 }, +{ 0x10D9, 0x10D9, 0x10D9 }, +{ 0x10DA, 0x10DA, 0x10DA }, +{ 0x10DB, 0x10DB, 0x10DB }, +{ 0x10DC, 0x10DC, 0x10DC }, +{ 0x10DD, 0x10DD, 0x10DD }, +{ 0x10DE, 0x10DE, 0x10DE }, +{ 0x10DF, 0x10DF, 0x10DF }, +{ 0x10E0, 0x10E0, 0x10E0 }, +{ 0x10E1, 0x10E1, 0x10E1 }, +{ 0x10E2, 0x10E2, 0x10E2 }, +{ 0x10E3, 0x10E3, 0x10E3 }, +{ 0x10E4, 0x10E4, 0x10E4 }, +{ 0x10E5, 0x10E5, 0x10E5 }, +{ 0x10E6, 0x10E6, 0x10E6 }, +{ 0x10E7, 0x10E7, 0x10E7 }, +{ 0x10E8, 0x10E8, 0x10E8 }, +{ 0x10E9, 0x10E9, 0x10E9 }, +{ 0x10EA, 0x10EA, 0x10EA }, +{ 0x10EB, 0x10EB, 0x10EB }, +{ 0x10EC, 0x10EC, 0x10EC }, +{ 0x10ED, 0x10ED, 0x10ED }, +{ 0x10EE, 0x10EE, 0x10EE }, +{ 0x10EF, 0x10EF, 0x10EF }, +{ 0x10F0, 0x10F0, 0x10F0 }, +{ 0x10F1, 0x10F1, 0x10F1 }, +{ 0x10F2, 0x10F2, 0x10F2 }, +{ 0x10F3, 0x10F3, 0x10F3 }, +{ 0x10F4, 0x10F4, 0x10F4 }, +{ 0x10F5, 0x10F5, 0x10F5 }, +{ 0x10F6, 0x10F6, 0x10F6 }, +{ 0x10F7, 0x10F7, 0x10F7 }, +{ 0x10F8, 0x10F8, 0x10F8 }, +{ 0x10F9, 0x10F9, 0x10F9 }, +{ 0x10FA, 0x10FA, 0x10FA }, +{ 0x10FC, 0x10FC, 0x10FC }, +{ 0x1100, 0x1100, 0x1100 }, +{ 0x1101, 0x1101, 0x1101 }, +{ 0x1102, 0x1102, 0x1102 }, +{ 0x1103, 0x1103, 0x1103 }, +{ 0x1104, 0x1104, 0x1104 }, +{ 0x1105, 0x1105, 0x1105 }, +{ 0x1106, 0x1106, 0x1106 }, +{ 0x1107, 0x1107, 0x1107 }, +{ 0x1108, 0x1108, 0x1108 }, +{ 0x1109, 0x1109, 0x1109 }, +{ 0x110A, 0x110A, 0x110A }, +{ 0x110B, 0x110B, 0x110B }, +{ 0x110C, 0x110C, 0x110C }, +{ 0x110D, 0x110D, 0x110D }, +{ 0x110E, 0x110E, 0x110E }, +{ 0x110F, 0x110F, 0x110F }, +{ 0x1110, 0x1110, 0x1110 }, +{ 0x1111, 0x1111, 0x1111 }, +{ 0x1112, 0x1112, 0x1112 }, +{ 0x1113, 0x1113, 0x1113 }, +{ 0x1114, 0x1114, 0x1114 }, +{ 0x1115, 0x1115, 0x1115 }, +{ 0x1116, 0x1116, 0x1116 }, +{ 0x1117, 0x1117, 0x1117 }, +{ 0x1118, 0x1118, 0x1118 }, +{ 0x1119, 0x1119, 0x1119 }, +{ 0x111A, 0x111A, 0x111A }, +{ 0x111B, 0x111B, 0x111B }, +{ 0x111C, 0x111C, 0x111C }, +{ 0x111D, 0x111D, 0x111D }, +{ 0x111E, 0x111E, 0x111E }, +{ 0x111F, 0x111F, 0x111F }, +{ 0x1120, 0x1120, 0x1120 }, +{ 0x1121, 0x1121, 0x1121 }, +{ 0x1122, 0x1122, 0x1122 }, +{ 0x1123, 0x1123, 0x1123 }, +{ 0x1124, 0x1124, 0x1124 }, +{ 0x1125, 0x1125, 0x1125 }, +{ 0x1126, 0x1126, 0x1126 }, +{ 0x1127, 0x1127, 0x1127 }, +{ 0x1128, 0x1128, 0x1128 }, +{ 0x1129, 0x1129, 0x1129 }, +{ 0x112A, 0x112A, 0x112A }, +{ 0x112B, 0x112B, 0x112B }, +{ 0x112C, 0x112C, 0x112C }, +{ 0x112D, 0x112D, 0x112D }, +{ 0x112E, 0x112E, 0x112E }, +{ 0x112F, 0x112F, 0x112F }, +{ 0x1130, 0x1130, 0x1130 }, +{ 0x1131, 0x1131, 0x1131 }, +{ 0x1132, 0x1132, 0x1132 }, +{ 0x1133, 0x1133, 0x1133 }, +{ 0x1134, 0x1134, 0x1134 }, +{ 0x1135, 0x1135, 0x1135 }, +{ 0x1136, 0x1136, 0x1136 }, +{ 0x1137, 0x1137, 0x1137 }, +{ 0x1138, 0x1138, 0x1138 }, +{ 0x1139, 0x1139, 0x1139 }, +{ 0x113A, 0x113A, 0x113A }, +{ 0x113B, 0x113B, 0x113B }, +{ 0x113C, 0x113C, 0x113C }, +{ 0x113D, 0x113D, 0x113D }, +{ 0x113E, 0x113E, 0x113E }, +{ 0x113F, 0x113F, 0x113F }, +{ 0x1140, 0x1140, 0x1140 }, +{ 0x1141, 0x1141, 0x1141 }, +{ 0x1142, 0x1142, 0x1142 }, +{ 0x1143, 0x1143, 0x1143 }, +{ 0x1144, 0x1144, 0x1144 }, +{ 0x1145, 0x1145, 0x1145 }, +{ 0x1146, 0x1146, 0x1146 }, +{ 0x1147, 0x1147, 0x1147 }, +{ 0x1148, 0x1148, 0x1148 }, +{ 0x1149, 0x1149, 0x1149 }, +{ 0x114A, 0x114A, 0x114A }, +{ 0x114B, 0x114B, 0x114B }, +{ 0x114C, 0x114C, 0x114C }, +{ 0x114D, 0x114D, 0x114D }, +{ 0x114E, 0x114E, 0x114E }, +{ 0x114F, 0x114F, 0x114F }, +{ 0x1150, 0x1150, 0x1150 }, +{ 0x1151, 0x1151, 0x1151 }, +{ 0x1152, 0x1152, 0x1152 }, +{ 0x1153, 0x1153, 0x1153 }, +{ 0x1154, 0x1154, 0x1154 }, +{ 0x1155, 0x1155, 0x1155 }, +{ 0x1156, 0x1156, 0x1156 }, +{ 0x1157, 0x1157, 0x1157 }, +{ 0x1158, 0x1158, 0x1158 }, +{ 0x1159, 0x1159, 0x1159 }, +{ 0x115F, 0x115F, 0x115F }, +{ 0x1160, 0x1160, 0x1160 }, +{ 0x1161, 0x1161, 0x1161 }, +{ 0x1162, 0x1162, 0x1162 }, +{ 0x1163, 0x1163, 0x1163 }, +{ 0x1164, 0x1164, 0x1164 }, +{ 0x1165, 0x1165, 0x1165 }, +{ 0x1166, 0x1166, 0x1166 }, +{ 0x1167, 0x1167, 0x1167 }, +{ 0x1168, 0x1168, 0x1168 }, +{ 0x1169, 0x1169, 0x1169 }, +{ 0x116A, 0x116A, 0x116A }, +{ 0x116B, 0x116B, 0x116B }, +{ 0x116C, 0x116C, 0x116C }, +{ 0x116D, 0x116D, 0x116D }, +{ 0x116E, 0x116E, 0x116E }, +{ 0x116F, 0x116F, 0x116F }, +{ 0x1170, 0x1170, 0x1170 }, +{ 0x1171, 0x1171, 0x1171 }, +{ 0x1172, 0x1172, 0x1172 }, +{ 0x1173, 0x1173, 0x1173 }, +{ 0x1174, 0x1174, 0x1174 }, +{ 0x1175, 0x1175, 0x1175 }, +{ 0x1176, 0x1176, 0x1176 }, +{ 0x1177, 0x1177, 0x1177 }, +{ 0x1178, 0x1178, 0x1178 }, +{ 0x1179, 0x1179, 0x1179 }, +{ 0x117A, 0x117A, 0x117A }, +{ 0x117B, 0x117B, 0x117B }, +{ 0x117C, 0x117C, 0x117C }, +{ 0x117D, 0x117D, 0x117D }, +{ 0x117E, 0x117E, 0x117E }, +{ 0x117F, 0x117F, 0x117F }, +{ 0x1180, 0x1180, 0x1180 }, +{ 0x1181, 0x1181, 0x1181 }, +{ 0x1182, 0x1182, 0x1182 }, +{ 0x1183, 0x1183, 0x1183 }, +{ 0x1184, 0x1184, 0x1184 }, +{ 0x1185, 0x1185, 0x1185 }, +{ 0x1186, 0x1186, 0x1186 }, +{ 0x1187, 0x1187, 0x1187 }, +{ 0x1188, 0x1188, 0x1188 }, +{ 0x1189, 0x1189, 0x1189 }, +{ 0x118A, 0x118A, 0x118A }, +{ 0x118B, 0x118B, 0x118B }, +{ 0x118C, 0x118C, 0x118C }, +{ 0x118D, 0x118D, 0x118D }, +{ 0x118E, 0x118E, 0x118E }, +{ 0x118F, 0x118F, 0x118F }, +{ 0x1190, 0x1190, 0x1190 }, +{ 0x1191, 0x1191, 0x1191 }, +{ 0x1192, 0x1192, 0x1192 }, +{ 0x1193, 0x1193, 0x1193 }, +{ 0x1194, 0x1194, 0x1194 }, +{ 0x1195, 0x1195, 0x1195 }, +{ 0x1196, 0x1196, 0x1196 }, +{ 0x1197, 0x1197, 0x1197 }, +{ 0x1198, 0x1198, 0x1198 }, +{ 0x1199, 0x1199, 0x1199 }, +{ 0x119A, 0x119A, 0x119A }, +{ 0x119B, 0x119B, 0x119B }, +{ 0x119C, 0x119C, 0x119C }, +{ 0x119D, 0x119D, 0x119D }, +{ 0x119E, 0x119E, 0x119E }, +{ 0x119F, 0x119F, 0x119F }, +{ 0x11A0, 0x11A0, 0x11A0 }, +{ 0x11A1, 0x11A1, 0x11A1 }, +{ 0x11A2, 0x11A2, 0x11A2 }, +{ 0x11A8, 0x11A8, 0x11A8 }, +{ 0x11A9, 0x11A9, 0x11A9 }, +{ 0x11AA, 0x11AA, 0x11AA }, +{ 0x11AB, 0x11AB, 0x11AB }, +{ 0x11AC, 0x11AC, 0x11AC }, +{ 0x11AD, 0x11AD, 0x11AD }, +{ 0x11AE, 0x11AE, 0x11AE }, +{ 0x11AF, 0x11AF, 0x11AF }, +{ 0x11B0, 0x11B0, 0x11B0 }, +{ 0x11B1, 0x11B1, 0x11B1 }, +{ 0x11B2, 0x11B2, 0x11B2 }, +{ 0x11B3, 0x11B3, 0x11B3 }, +{ 0x11B4, 0x11B4, 0x11B4 }, +{ 0x11B5, 0x11B5, 0x11B5 }, +{ 0x11B6, 0x11B6, 0x11B6 }, +{ 0x11B7, 0x11B7, 0x11B7 }, +{ 0x11B8, 0x11B8, 0x11B8 }, +{ 0x11B9, 0x11B9, 0x11B9 }, +{ 0x11BA, 0x11BA, 0x11BA }, +{ 0x11BB, 0x11BB, 0x11BB }, +{ 0x11BC, 0x11BC, 0x11BC }, +{ 0x11BD, 0x11BD, 0x11BD }, +{ 0x11BE, 0x11BE, 0x11BE }, +{ 0x11BF, 0x11BF, 0x11BF }, +{ 0x11C0, 0x11C0, 0x11C0 }, +{ 0x11C1, 0x11C1, 0x11C1 }, +{ 0x11C2, 0x11C2, 0x11C2 }, +{ 0x11C3, 0x11C3, 0x11C3 }, +{ 0x11C4, 0x11C4, 0x11C4 }, +{ 0x11C5, 0x11C5, 0x11C5 }, +{ 0x11C6, 0x11C6, 0x11C6 }, +{ 0x11C7, 0x11C7, 0x11C7 }, +{ 0x11C8, 0x11C8, 0x11C8 }, +{ 0x11C9, 0x11C9, 0x11C9 }, +{ 0x11CA, 0x11CA, 0x11CA }, +{ 0x11CB, 0x11CB, 0x11CB }, +{ 0x11CC, 0x11CC, 0x11CC }, +{ 0x11CD, 0x11CD, 0x11CD }, +{ 0x11CE, 0x11CE, 0x11CE }, +{ 0x11CF, 0x11CF, 0x11CF }, +{ 0x11D0, 0x11D0, 0x11D0 }, +{ 0x11D1, 0x11D1, 0x11D1 }, +{ 0x11D2, 0x11D2, 0x11D2 }, +{ 0x11D3, 0x11D3, 0x11D3 }, +{ 0x11D4, 0x11D4, 0x11D4 }, +{ 0x11D5, 0x11D5, 0x11D5 }, +{ 0x11D6, 0x11D6, 0x11D6 }, +{ 0x11D7, 0x11D7, 0x11D7 }, +{ 0x11D8, 0x11D8, 0x11D8 }, +{ 0x11D9, 0x11D9, 0x11D9 }, +{ 0x11DA, 0x11DA, 0x11DA }, +{ 0x11DB, 0x11DB, 0x11DB }, +{ 0x11DC, 0x11DC, 0x11DC }, +{ 0x11DD, 0x11DD, 0x11DD }, +{ 0x11DE, 0x11DE, 0x11DE }, +{ 0x11DF, 0x11DF, 0x11DF }, +{ 0x11E0, 0x11E0, 0x11E0 }, +{ 0x11E1, 0x11E1, 0x11E1 }, +{ 0x11E2, 0x11E2, 0x11E2 }, +{ 0x11E3, 0x11E3, 0x11E3 }, +{ 0x11E4, 0x11E4, 0x11E4 }, +{ 0x11E5, 0x11E5, 0x11E5 }, +{ 0x11E6, 0x11E6, 0x11E6 }, +{ 0x11E7, 0x11E7, 0x11E7 }, +{ 0x11E8, 0x11E8, 0x11E8 }, +{ 0x11E9, 0x11E9, 0x11E9 }, +{ 0x11EA, 0x11EA, 0x11EA }, +{ 0x11EB, 0x11EB, 0x11EB }, +{ 0x11EC, 0x11EC, 0x11EC }, +{ 0x11ED, 0x11ED, 0x11ED }, +{ 0x11EE, 0x11EE, 0x11EE }, +{ 0x11EF, 0x11EF, 0x11EF }, +{ 0x11F0, 0x11F0, 0x11F0 }, +{ 0x11F1, 0x11F1, 0x11F1 }, +{ 0x11F2, 0x11F2, 0x11F2 }, +{ 0x11F3, 0x11F3, 0x11F3 }, +{ 0x11F4, 0x11F4, 0x11F4 }, +{ 0x11F5, 0x11F5, 0x11F5 }, +{ 0x11F6, 0x11F6, 0x11F6 }, +{ 0x11F7, 0x11F7, 0x11F7 }, +{ 0x11F8, 0x11F8, 0x11F8 }, +{ 0x11F9, 0x11F9, 0x11F9 }, +{ 0x1200, 0x1200, 0x1200 }, +{ 0x1201, 0x1201, 0x1201 }, +{ 0x1202, 0x1202, 0x1202 }, +{ 0x1203, 0x1203, 0x1203 }, +{ 0x1204, 0x1204, 0x1204 }, +{ 0x1205, 0x1205, 0x1205 }, +{ 0x1206, 0x1206, 0x1206 }, +{ 0x1207, 0x1207, 0x1207 }, +{ 0x1208, 0x1208, 0x1208 }, +{ 0x1209, 0x1209, 0x1209 }, +{ 0x120A, 0x120A, 0x120A }, +{ 0x120B, 0x120B, 0x120B }, +{ 0x120C, 0x120C, 0x120C }, +{ 0x120D, 0x120D, 0x120D }, +{ 0x120E, 0x120E, 0x120E }, +{ 0x120F, 0x120F, 0x120F }, +{ 0x1210, 0x1210, 0x1210 }, +{ 0x1211, 0x1211, 0x1211 }, +{ 0x1212, 0x1212, 0x1212 }, +{ 0x1213, 0x1213, 0x1213 }, +{ 0x1214, 0x1214, 0x1214 }, +{ 0x1215, 0x1215, 0x1215 }, +{ 0x1216, 0x1216, 0x1216 }, +{ 0x1217, 0x1217, 0x1217 }, +{ 0x1218, 0x1218, 0x1218 }, +{ 0x1219, 0x1219, 0x1219 }, +{ 0x121A, 0x121A, 0x121A }, +{ 0x121B, 0x121B, 0x121B }, +{ 0x121C, 0x121C, 0x121C }, +{ 0x121D, 0x121D, 0x121D }, +{ 0x121E, 0x121E, 0x121E }, +{ 0x121F, 0x121F, 0x121F }, +{ 0x1220, 0x1220, 0x1220 }, +{ 0x1221, 0x1221, 0x1221 }, +{ 0x1222, 0x1222, 0x1222 }, +{ 0x1223, 0x1223, 0x1223 }, +{ 0x1224, 0x1224, 0x1224 }, +{ 0x1225, 0x1225, 0x1225 }, +{ 0x1226, 0x1226, 0x1226 }, +{ 0x1227, 0x1227, 0x1227 }, +{ 0x1228, 0x1228, 0x1228 }, +{ 0x1229, 0x1229, 0x1229 }, +{ 0x122A, 0x122A, 0x122A }, +{ 0x122B, 0x122B, 0x122B }, +{ 0x122C, 0x122C, 0x122C }, +{ 0x122D, 0x122D, 0x122D }, +{ 0x122E, 0x122E, 0x122E }, +{ 0x122F, 0x122F, 0x122F }, +{ 0x1230, 0x1230, 0x1230 }, +{ 0x1231, 0x1231, 0x1231 }, +{ 0x1232, 0x1232, 0x1232 }, +{ 0x1233, 0x1233, 0x1233 }, +{ 0x1234, 0x1234, 0x1234 }, +{ 0x1235, 0x1235, 0x1235 }, +{ 0x1236, 0x1236, 0x1236 }, +{ 0x1237, 0x1237, 0x1237 }, +{ 0x1238, 0x1238, 0x1238 }, +{ 0x1239, 0x1239, 0x1239 }, +{ 0x123A, 0x123A, 0x123A }, +{ 0x123B, 0x123B, 0x123B }, +{ 0x123C, 0x123C, 0x123C }, +{ 0x123D, 0x123D, 0x123D }, +{ 0x123E, 0x123E, 0x123E }, +{ 0x123F, 0x123F, 0x123F }, +{ 0x1240, 0x1240, 0x1240 }, +{ 0x1241, 0x1241, 0x1241 }, +{ 0x1242, 0x1242, 0x1242 }, +{ 0x1243, 0x1243, 0x1243 }, +{ 0x1244, 0x1244, 0x1244 }, +{ 0x1245, 0x1245, 0x1245 }, +{ 0x1246, 0x1246, 0x1246 }, +{ 0x1247, 0x1247, 0x1247 }, +{ 0x1248, 0x1248, 0x1248 }, +{ 0x124A, 0x124A, 0x124A }, +{ 0x124B, 0x124B, 0x124B }, +{ 0x124C, 0x124C, 0x124C }, +{ 0x124D, 0x124D, 0x124D }, +{ 0x1250, 0x1250, 0x1250 }, +{ 0x1251, 0x1251, 0x1251 }, +{ 0x1252, 0x1252, 0x1252 }, +{ 0x1253, 0x1253, 0x1253 }, +{ 0x1254, 0x1254, 0x1254 }, +{ 0x1255, 0x1255, 0x1255 }, +{ 0x1256, 0x1256, 0x1256 }, +{ 0x1258, 0x1258, 0x1258 }, +{ 0x125A, 0x125A, 0x125A }, +{ 0x125B, 0x125B, 0x125B }, +{ 0x125C, 0x125C, 0x125C }, +{ 0x125D, 0x125D, 0x125D }, +{ 0x1260, 0x1260, 0x1260 }, +{ 0x1261, 0x1261, 0x1261 }, +{ 0x1262, 0x1262, 0x1262 }, +{ 0x1263, 0x1263, 0x1263 }, +{ 0x1264, 0x1264, 0x1264 }, +{ 0x1265, 0x1265, 0x1265 }, +{ 0x1266, 0x1266, 0x1266 }, +{ 0x1267, 0x1267, 0x1267 }, +{ 0x1268, 0x1268, 0x1268 }, +{ 0x1269, 0x1269, 0x1269 }, +{ 0x126A, 0x126A, 0x126A }, +{ 0x126B, 0x126B, 0x126B }, +{ 0x126C, 0x126C, 0x126C }, +{ 0x126D, 0x126D, 0x126D }, +{ 0x126E, 0x126E, 0x126E }, +{ 0x126F, 0x126F, 0x126F }, +{ 0x1270, 0x1270, 0x1270 }, +{ 0x1271, 0x1271, 0x1271 }, +{ 0x1272, 0x1272, 0x1272 }, +{ 0x1273, 0x1273, 0x1273 }, +{ 0x1274, 0x1274, 0x1274 }, +{ 0x1275, 0x1275, 0x1275 }, +{ 0x1276, 0x1276, 0x1276 }, +{ 0x1277, 0x1277, 0x1277 }, +{ 0x1278, 0x1278, 0x1278 }, +{ 0x1279, 0x1279, 0x1279 }, +{ 0x127A, 0x127A, 0x127A }, +{ 0x127B, 0x127B, 0x127B }, +{ 0x127C, 0x127C, 0x127C }, +{ 0x127D, 0x127D, 0x127D }, +{ 0x127E, 0x127E, 0x127E }, +{ 0x127F, 0x127F, 0x127F }, +{ 0x1280, 0x1280, 0x1280 }, +{ 0x1281, 0x1281, 0x1281 }, +{ 0x1282, 0x1282, 0x1282 }, +{ 0x1283, 0x1283, 0x1283 }, +{ 0x1284, 0x1284, 0x1284 }, +{ 0x1285, 0x1285, 0x1285 }, +{ 0x1286, 0x1286, 0x1286 }, +{ 0x1287, 0x1287, 0x1287 }, +{ 0x1288, 0x1288, 0x1288 }, +{ 0x128A, 0x128A, 0x128A }, +{ 0x128B, 0x128B, 0x128B }, +{ 0x128C, 0x128C, 0x128C }, +{ 0x128D, 0x128D, 0x128D }, +{ 0x1290, 0x1290, 0x1290 }, +{ 0x1291, 0x1291, 0x1291 }, +{ 0x1292, 0x1292, 0x1292 }, +{ 0x1293, 0x1293, 0x1293 }, +{ 0x1294, 0x1294, 0x1294 }, +{ 0x1295, 0x1295, 0x1295 }, +{ 0x1296, 0x1296, 0x1296 }, +{ 0x1297, 0x1297, 0x1297 }, +{ 0x1298, 0x1298, 0x1298 }, +{ 0x1299, 0x1299, 0x1299 }, +{ 0x129A, 0x129A, 0x129A }, +{ 0x129B, 0x129B, 0x129B }, +{ 0x129C, 0x129C, 0x129C }, +{ 0x129D, 0x129D, 0x129D }, +{ 0x129E, 0x129E, 0x129E }, +{ 0x129F, 0x129F, 0x129F }, +{ 0x12A0, 0x12A0, 0x12A0 }, +{ 0x12A1, 0x12A1, 0x12A1 }, +{ 0x12A2, 0x12A2, 0x12A2 }, +{ 0x12A3, 0x12A3, 0x12A3 }, +{ 0x12A4, 0x12A4, 0x12A4 }, +{ 0x12A5, 0x12A5, 0x12A5 }, +{ 0x12A6, 0x12A6, 0x12A6 }, +{ 0x12A7, 0x12A7, 0x12A7 }, +{ 0x12A8, 0x12A8, 0x12A8 }, +{ 0x12A9, 0x12A9, 0x12A9 }, +{ 0x12AA, 0x12AA, 0x12AA }, +{ 0x12AB, 0x12AB, 0x12AB }, +{ 0x12AC, 0x12AC, 0x12AC }, +{ 0x12AD, 0x12AD, 0x12AD }, +{ 0x12AE, 0x12AE, 0x12AE }, +{ 0x12AF, 0x12AF, 0x12AF }, +{ 0x12B0, 0x12B0, 0x12B0 }, +{ 0x12B2, 0x12B2, 0x12B2 }, +{ 0x12B3, 0x12B3, 0x12B3 }, +{ 0x12B4, 0x12B4, 0x12B4 }, +{ 0x12B5, 0x12B5, 0x12B5 }, +{ 0x12B8, 0x12B8, 0x12B8 }, +{ 0x12B9, 0x12B9, 0x12B9 }, +{ 0x12BA, 0x12BA, 0x12BA }, +{ 0x12BB, 0x12BB, 0x12BB }, +{ 0x12BC, 0x12BC, 0x12BC }, +{ 0x12BD, 0x12BD, 0x12BD }, +{ 0x12BE, 0x12BE, 0x12BE }, +{ 0x12C0, 0x12C0, 0x12C0 }, +{ 0x12C2, 0x12C2, 0x12C2 }, +{ 0x12C3, 0x12C3, 0x12C3 }, +{ 0x12C4, 0x12C4, 0x12C4 }, +{ 0x12C5, 0x12C5, 0x12C5 }, +{ 0x12C8, 0x12C8, 0x12C8 }, +{ 0x12C9, 0x12C9, 0x12C9 }, +{ 0x12CA, 0x12CA, 0x12CA }, +{ 0x12CB, 0x12CB, 0x12CB }, +{ 0x12CC, 0x12CC, 0x12CC }, +{ 0x12CD, 0x12CD, 0x12CD }, +{ 0x12CE, 0x12CE, 0x12CE }, +{ 0x12CF, 0x12CF, 0x12CF }, +{ 0x12D0, 0x12D0, 0x12D0 }, +{ 0x12D1, 0x12D1, 0x12D1 }, +{ 0x12D2, 0x12D2, 0x12D2 }, +{ 0x12D3, 0x12D3, 0x12D3 }, +{ 0x12D4, 0x12D4, 0x12D4 }, +{ 0x12D5, 0x12D5, 0x12D5 }, +{ 0x12D6, 0x12D6, 0x12D6 }, +{ 0x12D8, 0x12D8, 0x12D8 }, +{ 0x12D9, 0x12D9, 0x12D9 }, +{ 0x12DA, 0x12DA, 0x12DA }, +{ 0x12DB, 0x12DB, 0x12DB }, +{ 0x12DC, 0x12DC, 0x12DC }, +{ 0x12DD, 0x12DD, 0x12DD }, +{ 0x12DE, 0x12DE, 0x12DE }, +{ 0x12DF, 0x12DF, 0x12DF }, +{ 0x12E0, 0x12E0, 0x12E0 }, +{ 0x12E1, 0x12E1, 0x12E1 }, +{ 0x12E2, 0x12E2, 0x12E2 }, +{ 0x12E3, 0x12E3, 0x12E3 }, +{ 0x12E4, 0x12E4, 0x12E4 }, +{ 0x12E5, 0x12E5, 0x12E5 }, +{ 0x12E6, 0x12E6, 0x12E6 }, +{ 0x12E7, 0x12E7, 0x12E7 }, +{ 0x12E8, 0x12E8, 0x12E8 }, +{ 0x12E9, 0x12E9, 0x12E9 }, +{ 0x12EA, 0x12EA, 0x12EA }, +{ 0x12EB, 0x12EB, 0x12EB }, +{ 0x12EC, 0x12EC, 0x12EC }, +{ 0x12ED, 0x12ED, 0x12ED }, +{ 0x12EE, 0x12EE, 0x12EE }, +{ 0x12EF, 0x12EF, 0x12EF }, +{ 0x12F0, 0x12F0, 0x12F0 }, +{ 0x12F1, 0x12F1, 0x12F1 }, +{ 0x12F2, 0x12F2, 0x12F2 }, +{ 0x12F3, 0x12F3, 0x12F3 }, +{ 0x12F4, 0x12F4, 0x12F4 }, +{ 0x12F5, 0x12F5, 0x12F5 }, +{ 0x12F6, 0x12F6, 0x12F6 }, +{ 0x12F7, 0x12F7, 0x12F7 }, +{ 0x12F8, 0x12F8, 0x12F8 }, +{ 0x12F9, 0x12F9, 0x12F9 }, +{ 0x12FA, 0x12FA, 0x12FA }, +{ 0x12FB, 0x12FB, 0x12FB }, +{ 0x12FC, 0x12FC, 0x12FC }, +{ 0x12FD, 0x12FD, 0x12FD }, +{ 0x12FE, 0x12FE, 0x12FE }, +{ 0x12FF, 0x12FF, 0x12FF }, +{ 0x1300, 0x1300, 0x1300 }, +{ 0x1301, 0x1301, 0x1301 }, +{ 0x1302, 0x1302, 0x1302 }, +{ 0x1303, 0x1303, 0x1303 }, +{ 0x1304, 0x1304, 0x1304 }, +{ 0x1305, 0x1305, 0x1305 }, +{ 0x1306, 0x1306, 0x1306 }, +{ 0x1307, 0x1307, 0x1307 }, +{ 0x1308, 0x1308, 0x1308 }, +{ 0x1309, 0x1309, 0x1309 }, +{ 0x130A, 0x130A, 0x130A }, +{ 0x130B, 0x130B, 0x130B }, +{ 0x130C, 0x130C, 0x130C }, +{ 0x130D, 0x130D, 0x130D }, +{ 0x130E, 0x130E, 0x130E }, +{ 0x130F, 0x130F, 0x130F }, +{ 0x1310, 0x1310, 0x1310 }, +{ 0x1312, 0x1312, 0x1312 }, +{ 0x1313, 0x1313, 0x1313 }, +{ 0x1314, 0x1314, 0x1314 }, +{ 0x1315, 0x1315, 0x1315 }, +{ 0x1318, 0x1318, 0x1318 }, +{ 0x1319, 0x1319, 0x1319 }, +{ 0x131A, 0x131A, 0x131A }, +{ 0x131B, 0x131B, 0x131B }, +{ 0x131C, 0x131C, 0x131C }, +{ 0x131D, 0x131D, 0x131D }, +{ 0x131E, 0x131E, 0x131E }, +{ 0x131F, 0x131F, 0x131F }, +{ 0x1320, 0x1320, 0x1320 }, +{ 0x1321, 0x1321, 0x1321 }, +{ 0x1322, 0x1322, 0x1322 }, +{ 0x1323, 0x1323, 0x1323 }, +{ 0x1324, 0x1324, 0x1324 }, +{ 0x1325, 0x1325, 0x1325 }, +{ 0x1326, 0x1326, 0x1326 }, +{ 0x1327, 0x1327, 0x1327 }, +{ 0x1328, 0x1328, 0x1328 }, +{ 0x1329, 0x1329, 0x1329 }, +{ 0x132A, 0x132A, 0x132A }, +{ 0x132B, 0x132B, 0x132B }, +{ 0x132C, 0x132C, 0x132C }, +{ 0x132D, 0x132D, 0x132D }, +{ 0x132E, 0x132E, 0x132E }, +{ 0x132F, 0x132F, 0x132F }, +{ 0x1330, 0x1330, 0x1330 }, +{ 0x1331, 0x1331, 0x1331 }, +{ 0x1332, 0x1332, 0x1332 }, +{ 0x1333, 0x1333, 0x1333 }, +{ 0x1334, 0x1334, 0x1334 }, +{ 0x1335, 0x1335, 0x1335 }, +{ 0x1336, 0x1336, 0x1336 }, +{ 0x1337, 0x1337, 0x1337 }, +{ 0x1338, 0x1338, 0x1338 }, +{ 0x1339, 0x1339, 0x1339 }, +{ 0x133A, 0x133A, 0x133A }, +{ 0x133B, 0x133B, 0x133B }, +{ 0x133C, 0x133C, 0x133C }, +{ 0x133D, 0x133D, 0x133D }, +{ 0x133E, 0x133E, 0x133E }, +{ 0x133F, 0x133F, 0x133F }, +{ 0x1340, 0x1340, 0x1340 }, +{ 0x1341, 0x1341, 0x1341 }, +{ 0x1342, 0x1342, 0x1342 }, +{ 0x1343, 0x1343, 0x1343 }, +{ 0x1344, 0x1344, 0x1344 }, +{ 0x1345, 0x1345, 0x1345 }, +{ 0x1346, 0x1346, 0x1346 }, +{ 0x1347, 0x1347, 0x1347 }, +{ 0x1348, 0x1348, 0x1348 }, +{ 0x1349, 0x1349, 0x1349 }, +{ 0x134A, 0x134A, 0x134A }, +{ 0x134B, 0x134B, 0x134B }, +{ 0x134C, 0x134C, 0x134C }, +{ 0x134D, 0x134D, 0x134D }, +{ 0x134E, 0x134E, 0x134E }, +{ 0x134F, 0x134F, 0x134F }, +{ 0x1350, 0x1350, 0x1350 }, +{ 0x1351, 0x1351, 0x1351 }, +{ 0x1352, 0x1352, 0x1352 }, +{ 0x1353, 0x1353, 0x1353 }, +{ 0x1354, 0x1354, 0x1354 }, +{ 0x1355, 0x1355, 0x1355 }, +{ 0x1356, 0x1356, 0x1356 }, +{ 0x1357, 0x1357, 0x1357 }, +{ 0x1358, 0x1358, 0x1358 }, +{ 0x1359, 0x1359, 0x1359 }, +{ 0x135A, 0x135A, 0x135A }, +{ 0x135F, 0x135F, 0x135F }, +{ 0x1380, 0x1380, 0x1380 }, +{ 0x1381, 0x1381, 0x1381 }, +{ 0x1382, 0x1382, 0x1382 }, +{ 0x1383, 0x1383, 0x1383 }, +{ 0x1384, 0x1384, 0x1384 }, +{ 0x1385, 0x1385, 0x1385 }, +{ 0x1386, 0x1386, 0x1386 }, +{ 0x1387, 0x1387, 0x1387 }, +{ 0x1388, 0x1388, 0x1388 }, +{ 0x1389, 0x1389, 0x1389 }, +{ 0x138A, 0x138A, 0x138A }, +{ 0x138B, 0x138B, 0x138B }, +{ 0x138C, 0x138C, 0x138C }, +{ 0x138D, 0x138D, 0x138D }, +{ 0x138E, 0x138E, 0x138E }, +{ 0x138F, 0x138F, 0x138F }, +{ 0x13A0, 0x13A0, 0x13A0 }, +{ 0x13A1, 0x13A1, 0x13A1 }, +{ 0x13A2, 0x13A2, 0x13A2 }, +{ 0x13A3, 0x13A3, 0x13A3 }, +{ 0x13A4, 0x13A4, 0x13A4 }, +{ 0x13A5, 0x13A5, 0x13A5 }, +{ 0x13A6, 0x13A6, 0x13A6 }, +{ 0x13A7, 0x13A7, 0x13A7 }, +{ 0x13A8, 0x13A8, 0x13A8 }, +{ 0x13A9, 0x13A9, 0x13A9 }, +{ 0x13AA, 0x13AA, 0x13AA }, +{ 0x13AB, 0x13AB, 0x13AB }, +{ 0x13AC, 0x13AC, 0x13AC }, +{ 0x13AD, 0x13AD, 0x13AD }, +{ 0x13AE, 0x13AE, 0x13AE }, +{ 0x13AF, 0x13AF, 0x13AF }, +{ 0x13B0, 0x13B0, 0x13B0 }, +{ 0x13B1, 0x13B1, 0x13B1 }, +{ 0x13B2, 0x13B2, 0x13B2 }, +{ 0x13B3, 0x13B3, 0x13B3 }, +{ 0x13B4, 0x13B4, 0x13B4 }, +{ 0x13B5, 0x13B5, 0x13B5 }, +{ 0x13B6, 0x13B6, 0x13B6 }, +{ 0x13B7, 0x13B7, 0x13B7 }, +{ 0x13B8, 0x13B8, 0x13B8 }, +{ 0x13B9, 0x13B9, 0x13B9 }, +{ 0x13BA, 0x13BA, 0x13BA }, +{ 0x13BB, 0x13BB, 0x13BB }, +{ 0x13BC, 0x13BC, 0x13BC }, +{ 0x13BD, 0x13BD, 0x13BD }, +{ 0x13BE, 0x13BE, 0x13BE }, +{ 0x13BF, 0x13BF, 0x13BF }, +{ 0x13C0, 0x13C0, 0x13C0 }, +{ 0x13C1, 0x13C1, 0x13C1 }, +{ 0x13C2, 0x13C2, 0x13C2 }, +{ 0x13C3, 0x13C3, 0x13C3 }, +{ 0x13C4, 0x13C4, 0x13C4 }, +{ 0x13C5, 0x13C5, 0x13C5 }, +{ 0x13C6, 0x13C6, 0x13C6 }, +{ 0x13C7, 0x13C7, 0x13C7 }, +{ 0x13C8, 0x13C8, 0x13C8 }, +{ 0x13C9, 0x13C9, 0x13C9 }, +{ 0x13CA, 0x13CA, 0x13CA }, +{ 0x13CB, 0x13CB, 0x13CB }, +{ 0x13CC, 0x13CC, 0x13CC }, +{ 0x13CD, 0x13CD, 0x13CD }, +{ 0x13CE, 0x13CE, 0x13CE }, +{ 0x13CF, 0x13CF, 0x13CF }, +{ 0x13D0, 0x13D0, 0x13D0 }, +{ 0x13D1, 0x13D1, 0x13D1 }, +{ 0x13D2, 0x13D2, 0x13D2 }, +{ 0x13D3, 0x13D3, 0x13D3 }, +{ 0x13D4, 0x13D4, 0x13D4 }, +{ 0x13D5, 0x13D5, 0x13D5 }, +{ 0x13D6, 0x13D6, 0x13D6 }, +{ 0x13D7, 0x13D7, 0x13D7 }, +{ 0x13D8, 0x13D8, 0x13D8 }, +{ 0x13D9, 0x13D9, 0x13D9 }, +{ 0x13DA, 0x13DA, 0x13DA }, +{ 0x13DB, 0x13DB, 0x13DB }, +{ 0x13DC, 0x13DC, 0x13DC }, +{ 0x13DD, 0x13DD, 0x13DD }, +{ 0x13DE, 0x13DE, 0x13DE }, +{ 0x13DF, 0x13DF, 0x13DF }, +{ 0x13E0, 0x13E0, 0x13E0 }, +{ 0x13E1, 0x13E1, 0x13E1 }, +{ 0x13E2, 0x13E2, 0x13E2 }, +{ 0x13E3, 0x13E3, 0x13E3 }, +{ 0x13E4, 0x13E4, 0x13E4 }, +{ 0x13E5, 0x13E5, 0x13E5 }, +{ 0x13E6, 0x13E6, 0x13E6 }, +{ 0x13E7, 0x13E7, 0x13E7 }, +{ 0x13E8, 0x13E8, 0x13E8 }, +{ 0x13E9, 0x13E9, 0x13E9 }, +{ 0x13EA, 0x13EA, 0x13EA }, +{ 0x13EB, 0x13EB, 0x13EB }, +{ 0x13EC, 0x13EC, 0x13EC }, +{ 0x13ED, 0x13ED, 0x13ED }, +{ 0x13EE, 0x13EE, 0x13EE }, +{ 0x13EF, 0x13EF, 0x13EF }, +{ 0x13F0, 0x13F0, 0x13F0 }, +{ 0x13F1, 0x13F1, 0x13F1 }, +{ 0x13F2, 0x13F2, 0x13F2 }, +{ 0x13F3, 0x13F3, 0x13F3 }, +{ 0x13F4, 0x13F4, 0x13F4 }, +{ 0x1401, 0x1401, 0x1401 }, +{ 0x1402, 0x1402, 0x1402 }, +{ 0x1403, 0x1403, 0x1403 }, +{ 0x1404, 0x1404, 0x1404 }, +{ 0x1405, 0x1405, 0x1405 }, +{ 0x1406, 0x1406, 0x1406 }, +{ 0x1407, 0x1407, 0x1407 }, +{ 0x1408, 0x1408, 0x1408 }, +{ 0x1409, 0x1409, 0x1409 }, +{ 0x140A, 0x140A, 0x140A }, +{ 0x140B, 0x140B, 0x140B }, +{ 0x140C, 0x140C, 0x140C }, +{ 0x140D, 0x140D, 0x140D }, +{ 0x140E, 0x140E, 0x140E }, +{ 0x140F, 0x140F, 0x140F }, +{ 0x1410, 0x1410, 0x1410 }, +{ 0x1411, 0x1411, 0x1411 }, +{ 0x1412, 0x1412, 0x1412 }, +{ 0x1413, 0x1413, 0x1413 }, +{ 0x1414, 0x1414, 0x1414 }, +{ 0x1415, 0x1415, 0x1415 }, +{ 0x1416, 0x1416, 0x1416 }, +{ 0x1417, 0x1417, 0x1417 }, +{ 0x1418, 0x1418, 0x1418 }, +{ 0x1419, 0x1419, 0x1419 }, +{ 0x141A, 0x141A, 0x141A }, +{ 0x141B, 0x141B, 0x141B }, +{ 0x141C, 0x141C, 0x141C }, +{ 0x141D, 0x141D, 0x141D }, +{ 0x141E, 0x141E, 0x141E }, +{ 0x141F, 0x141F, 0x141F }, +{ 0x1420, 0x1420, 0x1420 }, +{ 0x1421, 0x1421, 0x1421 }, +{ 0x1422, 0x1422, 0x1422 }, +{ 0x1423, 0x1423, 0x1423 }, +{ 0x1424, 0x1424, 0x1424 }, +{ 0x1425, 0x1425, 0x1425 }, +{ 0x1426, 0x1426, 0x1426 }, +{ 0x1427, 0x1427, 0x1427 }, +{ 0x1428, 0x1428, 0x1428 }, +{ 0x1429, 0x1429, 0x1429 }, +{ 0x142A, 0x142A, 0x142A }, +{ 0x142B, 0x142B, 0x142B }, +{ 0x142C, 0x142C, 0x142C }, +{ 0x142D, 0x142D, 0x142D }, +{ 0x142E, 0x142E, 0x142E }, +{ 0x142F, 0x142F, 0x142F }, +{ 0x1430, 0x1430, 0x1430 }, +{ 0x1431, 0x1431, 0x1431 }, +{ 0x1432, 0x1432, 0x1432 }, +{ 0x1433, 0x1433, 0x1433 }, +{ 0x1434, 0x1434, 0x1434 }, +{ 0x1435, 0x1435, 0x1435 }, +{ 0x1436, 0x1436, 0x1436 }, +{ 0x1437, 0x1437, 0x1437 }, +{ 0x1438, 0x1438, 0x1438 }, +{ 0x1439, 0x1439, 0x1439 }, +{ 0x143A, 0x143A, 0x143A }, +{ 0x143B, 0x143B, 0x143B }, +{ 0x143C, 0x143C, 0x143C }, +{ 0x143D, 0x143D, 0x143D }, +{ 0x143E, 0x143E, 0x143E }, +{ 0x143F, 0x143F, 0x143F }, +{ 0x1440, 0x1440, 0x1440 }, +{ 0x1441, 0x1441, 0x1441 }, +{ 0x1442, 0x1442, 0x1442 }, +{ 0x1443, 0x1443, 0x1443 }, +{ 0x1444, 0x1444, 0x1444 }, +{ 0x1445, 0x1445, 0x1445 }, +{ 0x1446, 0x1446, 0x1446 }, +{ 0x1447, 0x1447, 0x1447 }, +{ 0x1448, 0x1448, 0x1448 }, +{ 0x1449, 0x1449, 0x1449 }, +{ 0x144A, 0x144A, 0x144A }, +{ 0x144B, 0x144B, 0x144B }, +{ 0x144C, 0x144C, 0x144C }, +{ 0x144D, 0x144D, 0x144D }, +{ 0x144E, 0x144E, 0x144E }, +{ 0x144F, 0x144F, 0x144F }, +{ 0x1450, 0x1450, 0x1450 }, +{ 0x1451, 0x1451, 0x1451 }, +{ 0x1452, 0x1452, 0x1452 }, +{ 0x1453, 0x1453, 0x1453 }, +{ 0x1454, 0x1454, 0x1454 }, +{ 0x1455, 0x1455, 0x1455 }, +{ 0x1456, 0x1456, 0x1456 }, +{ 0x1457, 0x1457, 0x1457 }, +{ 0x1458, 0x1458, 0x1458 }, +{ 0x1459, 0x1459, 0x1459 }, +{ 0x145A, 0x145A, 0x145A }, +{ 0x145B, 0x145B, 0x145B }, +{ 0x145C, 0x145C, 0x145C }, +{ 0x145D, 0x145D, 0x145D }, +{ 0x145E, 0x145E, 0x145E }, +{ 0x145F, 0x145F, 0x145F }, +{ 0x1460, 0x1460, 0x1460 }, +{ 0x1461, 0x1461, 0x1461 }, +{ 0x1462, 0x1462, 0x1462 }, +{ 0x1463, 0x1463, 0x1463 }, +{ 0x1464, 0x1464, 0x1464 }, +{ 0x1465, 0x1465, 0x1465 }, +{ 0x1466, 0x1466, 0x1466 }, +{ 0x1467, 0x1467, 0x1467 }, +{ 0x1468, 0x1468, 0x1468 }, +{ 0x1469, 0x1469, 0x1469 }, +{ 0x146A, 0x146A, 0x146A }, +{ 0x146B, 0x146B, 0x146B }, +{ 0x146C, 0x146C, 0x146C }, +{ 0x146D, 0x146D, 0x146D }, +{ 0x146E, 0x146E, 0x146E }, +{ 0x146F, 0x146F, 0x146F }, +{ 0x1470, 0x1470, 0x1470 }, +{ 0x1471, 0x1471, 0x1471 }, +{ 0x1472, 0x1472, 0x1472 }, +{ 0x1473, 0x1473, 0x1473 }, +{ 0x1474, 0x1474, 0x1474 }, +{ 0x1475, 0x1475, 0x1475 }, +{ 0x1476, 0x1476, 0x1476 }, +{ 0x1477, 0x1477, 0x1477 }, +{ 0x1478, 0x1478, 0x1478 }, +{ 0x1479, 0x1479, 0x1479 }, +{ 0x147A, 0x147A, 0x147A }, +{ 0x147B, 0x147B, 0x147B }, +{ 0x147C, 0x147C, 0x147C }, +{ 0x147D, 0x147D, 0x147D }, +{ 0x147E, 0x147E, 0x147E }, +{ 0x147F, 0x147F, 0x147F }, +{ 0x1480, 0x1480, 0x1480 }, +{ 0x1481, 0x1481, 0x1481 }, +{ 0x1482, 0x1482, 0x1482 }, +{ 0x1483, 0x1483, 0x1483 }, +{ 0x1484, 0x1484, 0x1484 }, +{ 0x1485, 0x1485, 0x1485 }, +{ 0x1486, 0x1486, 0x1486 }, +{ 0x1487, 0x1487, 0x1487 }, +{ 0x1488, 0x1488, 0x1488 }, +{ 0x1489, 0x1489, 0x1489 }, +{ 0x148A, 0x148A, 0x148A }, +{ 0x148B, 0x148B, 0x148B }, +{ 0x148C, 0x148C, 0x148C }, +{ 0x148D, 0x148D, 0x148D }, +{ 0x148E, 0x148E, 0x148E }, +{ 0x148F, 0x148F, 0x148F }, +{ 0x1490, 0x1490, 0x1490 }, +{ 0x1491, 0x1491, 0x1491 }, +{ 0x1492, 0x1492, 0x1492 }, +{ 0x1493, 0x1493, 0x1493 }, +{ 0x1494, 0x1494, 0x1494 }, +{ 0x1495, 0x1495, 0x1495 }, +{ 0x1496, 0x1496, 0x1496 }, +{ 0x1497, 0x1497, 0x1497 }, +{ 0x1498, 0x1498, 0x1498 }, +{ 0x1499, 0x1499, 0x1499 }, +{ 0x149A, 0x149A, 0x149A }, +{ 0x149B, 0x149B, 0x149B }, +{ 0x149C, 0x149C, 0x149C }, +{ 0x149D, 0x149D, 0x149D }, +{ 0x149E, 0x149E, 0x149E }, +{ 0x149F, 0x149F, 0x149F }, +{ 0x14A0, 0x14A0, 0x14A0 }, +{ 0x14A1, 0x14A1, 0x14A1 }, +{ 0x14A2, 0x14A2, 0x14A2 }, +{ 0x14A3, 0x14A3, 0x14A3 }, +{ 0x14A4, 0x14A4, 0x14A4 }, +{ 0x14A5, 0x14A5, 0x14A5 }, +{ 0x14A6, 0x14A6, 0x14A6 }, +{ 0x14A7, 0x14A7, 0x14A7 }, +{ 0x14A8, 0x14A8, 0x14A8 }, +{ 0x14A9, 0x14A9, 0x14A9 }, +{ 0x14AA, 0x14AA, 0x14AA }, +{ 0x14AB, 0x14AB, 0x14AB }, +{ 0x14AC, 0x14AC, 0x14AC }, +{ 0x14AD, 0x14AD, 0x14AD }, +{ 0x14AE, 0x14AE, 0x14AE }, +{ 0x14AF, 0x14AF, 0x14AF }, +{ 0x14B0, 0x14B0, 0x14B0 }, +{ 0x14B1, 0x14B1, 0x14B1 }, +{ 0x14B2, 0x14B2, 0x14B2 }, +{ 0x14B3, 0x14B3, 0x14B3 }, +{ 0x14B4, 0x14B4, 0x14B4 }, +{ 0x14B5, 0x14B5, 0x14B5 }, +{ 0x14B6, 0x14B6, 0x14B6 }, +{ 0x14B7, 0x14B7, 0x14B7 }, +{ 0x14B8, 0x14B8, 0x14B8 }, +{ 0x14B9, 0x14B9, 0x14B9 }, +{ 0x14BA, 0x14BA, 0x14BA }, +{ 0x14BB, 0x14BB, 0x14BB }, +{ 0x14BC, 0x14BC, 0x14BC }, +{ 0x14BD, 0x14BD, 0x14BD }, +{ 0x14BE, 0x14BE, 0x14BE }, +{ 0x14BF, 0x14BF, 0x14BF }, +{ 0x14C0, 0x14C0, 0x14C0 }, +{ 0x14C1, 0x14C1, 0x14C1 }, +{ 0x14C2, 0x14C2, 0x14C2 }, +{ 0x14C3, 0x14C3, 0x14C3 }, +{ 0x14C4, 0x14C4, 0x14C4 }, +{ 0x14C5, 0x14C5, 0x14C5 }, +{ 0x14C6, 0x14C6, 0x14C6 }, +{ 0x14C7, 0x14C7, 0x14C7 }, +{ 0x14C8, 0x14C8, 0x14C8 }, +{ 0x14C9, 0x14C9, 0x14C9 }, +{ 0x14CA, 0x14CA, 0x14CA }, +{ 0x14CB, 0x14CB, 0x14CB }, +{ 0x14CC, 0x14CC, 0x14CC }, +{ 0x14CD, 0x14CD, 0x14CD }, +{ 0x14CE, 0x14CE, 0x14CE }, +{ 0x14CF, 0x14CF, 0x14CF }, +{ 0x14D0, 0x14D0, 0x14D0 }, +{ 0x14D1, 0x14D1, 0x14D1 }, +{ 0x14D2, 0x14D2, 0x14D2 }, +{ 0x14D3, 0x14D3, 0x14D3 }, +{ 0x14D4, 0x14D4, 0x14D4 }, +{ 0x14D5, 0x14D5, 0x14D5 }, +{ 0x14D6, 0x14D6, 0x14D6 }, +{ 0x14D7, 0x14D7, 0x14D7 }, +{ 0x14D8, 0x14D8, 0x14D8 }, +{ 0x14D9, 0x14D9, 0x14D9 }, +{ 0x14DA, 0x14DA, 0x14DA }, +{ 0x14DB, 0x14DB, 0x14DB }, +{ 0x14DC, 0x14DC, 0x14DC }, +{ 0x14DD, 0x14DD, 0x14DD }, +{ 0x14DE, 0x14DE, 0x14DE }, +{ 0x14DF, 0x14DF, 0x14DF }, +{ 0x14E0, 0x14E0, 0x14E0 }, +{ 0x14E1, 0x14E1, 0x14E1 }, +{ 0x14E2, 0x14E2, 0x14E2 }, +{ 0x14E3, 0x14E3, 0x14E3 }, +{ 0x14E4, 0x14E4, 0x14E4 }, +{ 0x14E5, 0x14E5, 0x14E5 }, +{ 0x14E6, 0x14E6, 0x14E6 }, +{ 0x14E7, 0x14E7, 0x14E7 }, +{ 0x14E8, 0x14E8, 0x14E8 }, +{ 0x14E9, 0x14E9, 0x14E9 }, +{ 0x14EA, 0x14EA, 0x14EA }, +{ 0x14EB, 0x14EB, 0x14EB }, +{ 0x14EC, 0x14EC, 0x14EC }, +{ 0x14ED, 0x14ED, 0x14ED }, +{ 0x14EE, 0x14EE, 0x14EE }, +{ 0x14EF, 0x14EF, 0x14EF }, +{ 0x14F0, 0x14F0, 0x14F0 }, +{ 0x14F1, 0x14F1, 0x14F1 }, +{ 0x14F2, 0x14F2, 0x14F2 }, +{ 0x14F3, 0x14F3, 0x14F3 }, +{ 0x14F4, 0x14F4, 0x14F4 }, +{ 0x14F5, 0x14F5, 0x14F5 }, +{ 0x14F6, 0x14F6, 0x14F6 }, +{ 0x14F7, 0x14F7, 0x14F7 }, +{ 0x14F8, 0x14F8, 0x14F8 }, +{ 0x14F9, 0x14F9, 0x14F9 }, +{ 0x14FA, 0x14FA, 0x14FA }, +{ 0x14FB, 0x14FB, 0x14FB }, +{ 0x14FC, 0x14FC, 0x14FC }, +{ 0x14FD, 0x14FD, 0x14FD }, +{ 0x14FE, 0x14FE, 0x14FE }, +{ 0x14FF, 0x14FF, 0x14FF }, +{ 0x1500, 0x1500, 0x1500 }, +{ 0x1501, 0x1501, 0x1501 }, +{ 0x1502, 0x1502, 0x1502 }, +{ 0x1503, 0x1503, 0x1503 }, +{ 0x1504, 0x1504, 0x1504 }, +{ 0x1505, 0x1505, 0x1505 }, +{ 0x1506, 0x1506, 0x1506 }, +{ 0x1507, 0x1507, 0x1507 }, +{ 0x1508, 0x1508, 0x1508 }, +{ 0x1509, 0x1509, 0x1509 }, +{ 0x150A, 0x150A, 0x150A }, +{ 0x150B, 0x150B, 0x150B }, +{ 0x150C, 0x150C, 0x150C }, +{ 0x150D, 0x150D, 0x150D }, +{ 0x150E, 0x150E, 0x150E }, +{ 0x150F, 0x150F, 0x150F }, +{ 0x1510, 0x1510, 0x1510 }, +{ 0x1511, 0x1511, 0x1511 }, +{ 0x1512, 0x1512, 0x1512 }, +{ 0x1513, 0x1513, 0x1513 }, +{ 0x1514, 0x1514, 0x1514 }, +{ 0x1515, 0x1515, 0x1515 }, +{ 0x1516, 0x1516, 0x1516 }, +{ 0x1517, 0x1517, 0x1517 }, +{ 0x1518, 0x1518, 0x1518 }, +{ 0x1519, 0x1519, 0x1519 }, +{ 0x151A, 0x151A, 0x151A }, +{ 0x151B, 0x151B, 0x151B }, +{ 0x151C, 0x151C, 0x151C }, +{ 0x151D, 0x151D, 0x151D }, +{ 0x151E, 0x151E, 0x151E }, +{ 0x151F, 0x151F, 0x151F }, +{ 0x1520, 0x1520, 0x1520 }, +{ 0x1521, 0x1521, 0x1521 }, +{ 0x1522, 0x1522, 0x1522 }, +{ 0x1523, 0x1523, 0x1523 }, +{ 0x1524, 0x1524, 0x1524 }, +{ 0x1525, 0x1525, 0x1525 }, +{ 0x1526, 0x1526, 0x1526 }, +{ 0x1527, 0x1527, 0x1527 }, +{ 0x1528, 0x1528, 0x1528 }, +{ 0x1529, 0x1529, 0x1529 }, +{ 0x152A, 0x152A, 0x152A }, +{ 0x152B, 0x152B, 0x152B }, +{ 0x152C, 0x152C, 0x152C }, +{ 0x152D, 0x152D, 0x152D }, +{ 0x152E, 0x152E, 0x152E }, +{ 0x152F, 0x152F, 0x152F }, +{ 0x1530, 0x1530, 0x1530 }, +{ 0x1531, 0x1531, 0x1531 }, +{ 0x1532, 0x1532, 0x1532 }, +{ 0x1533, 0x1533, 0x1533 }, +{ 0x1534, 0x1534, 0x1534 }, +{ 0x1535, 0x1535, 0x1535 }, +{ 0x1536, 0x1536, 0x1536 }, +{ 0x1537, 0x1537, 0x1537 }, +{ 0x1538, 0x1538, 0x1538 }, +{ 0x1539, 0x1539, 0x1539 }, +{ 0x153A, 0x153A, 0x153A }, +{ 0x153B, 0x153B, 0x153B }, +{ 0x153C, 0x153C, 0x153C }, +{ 0x153D, 0x153D, 0x153D }, +{ 0x153E, 0x153E, 0x153E }, +{ 0x153F, 0x153F, 0x153F }, +{ 0x1540, 0x1540, 0x1540 }, +{ 0x1541, 0x1541, 0x1541 }, +{ 0x1542, 0x1542, 0x1542 }, +{ 0x1543, 0x1543, 0x1543 }, +{ 0x1544, 0x1544, 0x1544 }, +{ 0x1545, 0x1545, 0x1545 }, +{ 0x1546, 0x1546, 0x1546 }, +{ 0x1547, 0x1547, 0x1547 }, +{ 0x1548, 0x1548, 0x1548 }, +{ 0x1549, 0x1549, 0x1549 }, +{ 0x154A, 0x154A, 0x154A }, +{ 0x154B, 0x154B, 0x154B }, +{ 0x154C, 0x154C, 0x154C }, +{ 0x154D, 0x154D, 0x154D }, +{ 0x154E, 0x154E, 0x154E }, +{ 0x154F, 0x154F, 0x154F }, +{ 0x1550, 0x1550, 0x1550 }, +{ 0x1551, 0x1551, 0x1551 }, +{ 0x1552, 0x1552, 0x1552 }, +{ 0x1553, 0x1553, 0x1553 }, +{ 0x1554, 0x1554, 0x1554 }, +{ 0x1555, 0x1555, 0x1555 }, +{ 0x1556, 0x1556, 0x1556 }, +{ 0x1557, 0x1557, 0x1557 }, +{ 0x1558, 0x1558, 0x1558 }, +{ 0x1559, 0x1559, 0x1559 }, +{ 0x155A, 0x155A, 0x155A }, +{ 0x155B, 0x155B, 0x155B }, +{ 0x155C, 0x155C, 0x155C }, +{ 0x155D, 0x155D, 0x155D }, +{ 0x155E, 0x155E, 0x155E }, +{ 0x155F, 0x155F, 0x155F }, +{ 0x1560, 0x1560, 0x1560 }, +{ 0x1561, 0x1561, 0x1561 }, +{ 0x1562, 0x1562, 0x1562 }, +{ 0x1563, 0x1563, 0x1563 }, +{ 0x1564, 0x1564, 0x1564 }, +{ 0x1565, 0x1565, 0x1565 }, +{ 0x1566, 0x1566, 0x1566 }, +{ 0x1567, 0x1567, 0x1567 }, +{ 0x1568, 0x1568, 0x1568 }, +{ 0x1569, 0x1569, 0x1569 }, +{ 0x156A, 0x156A, 0x156A }, +{ 0x156B, 0x156B, 0x156B }, +{ 0x156C, 0x156C, 0x156C }, +{ 0x156D, 0x156D, 0x156D }, +{ 0x156E, 0x156E, 0x156E }, +{ 0x156F, 0x156F, 0x156F }, +{ 0x1570, 0x1570, 0x1570 }, +{ 0x1571, 0x1571, 0x1571 }, +{ 0x1572, 0x1572, 0x1572 }, +{ 0x1573, 0x1573, 0x1573 }, +{ 0x1574, 0x1574, 0x1574 }, +{ 0x1575, 0x1575, 0x1575 }, +{ 0x1576, 0x1576, 0x1576 }, +{ 0x1577, 0x1577, 0x1577 }, +{ 0x1578, 0x1578, 0x1578 }, +{ 0x1579, 0x1579, 0x1579 }, +{ 0x157A, 0x157A, 0x157A }, +{ 0x157B, 0x157B, 0x157B }, +{ 0x157C, 0x157C, 0x157C }, +{ 0x157D, 0x157D, 0x157D }, +{ 0x157E, 0x157E, 0x157E }, +{ 0x157F, 0x157F, 0x157F }, +{ 0x1580, 0x1580, 0x1580 }, +{ 0x1581, 0x1581, 0x1581 }, +{ 0x1582, 0x1582, 0x1582 }, +{ 0x1583, 0x1583, 0x1583 }, +{ 0x1584, 0x1584, 0x1584 }, +{ 0x1585, 0x1585, 0x1585 }, +{ 0x1586, 0x1586, 0x1586 }, +{ 0x1587, 0x1587, 0x1587 }, +{ 0x1588, 0x1588, 0x1588 }, +{ 0x1589, 0x1589, 0x1589 }, +{ 0x158A, 0x158A, 0x158A }, +{ 0x158B, 0x158B, 0x158B }, +{ 0x158C, 0x158C, 0x158C }, +{ 0x158D, 0x158D, 0x158D }, +{ 0x158E, 0x158E, 0x158E }, +{ 0x158F, 0x158F, 0x158F }, +{ 0x1590, 0x1590, 0x1590 }, +{ 0x1591, 0x1591, 0x1591 }, +{ 0x1592, 0x1592, 0x1592 }, +{ 0x1593, 0x1593, 0x1593 }, +{ 0x1594, 0x1594, 0x1594 }, +{ 0x1595, 0x1595, 0x1595 }, +{ 0x1596, 0x1596, 0x1596 }, +{ 0x1597, 0x1597, 0x1597 }, +{ 0x1598, 0x1598, 0x1598 }, +{ 0x1599, 0x1599, 0x1599 }, +{ 0x159A, 0x159A, 0x159A }, +{ 0x159B, 0x159B, 0x159B }, +{ 0x159C, 0x159C, 0x159C }, +{ 0x159D, 0x159D, 0x159D }, +{ 0x159E, 0x159E, 0x159E }, +{ 0x159F, 0x159F, 0x159F }, +{ 0x15A0, 0x15A0, 0x15A0 }, +{ 0x15A1, 0x15A1, 0x15A1 }, +{ 0x15A2, 0x15A2, 0x15A2 }, +{ 0x15A3, 0x15A3, 0x15A3 }, +{ 0x15A4, 0x15A4, 0x15A4 }, +{ 0x15A5, 0x15A5, 0x15A5 }, +{ 0x15A6, 0x15A6, 0x15A6 }, +{ 0x15A7, 0x15A7, 0x15A7 }, +{ 0x15A8, 0x15A8, 0x15A8 }, +{ 0x15A9, 0x15A9, 0x15A9 }, +{ 0x15AA, 0x15AA, 0x15AA }, +{ 0x15AB, 0x15AB, 0x15AB }, +{ 0x15AC, 0x15AC, 0x15AC }, +{ 0x15AD, 0x15AD, 0x15AD }, +{ 0x15AE, 0x15AE, 0x15AE }, +{ 0x15AF, 0x15AF, 0x15AF }, +{ 0x15B0, 0x15B0, 0x15B0 }, +{ 0x15B1, 0x15B1, 0x15B1 }, +{ 0x15B2, 0x15B2, 0x15B2 }, +{ 0x15B3, 0x15B3, 0x15B3 }, +{ 0x15B4, 0x15B4, 0x15B4 }, +{ 0x15B5, 0x15B5, 0x15B5 }, +{ 0x15B6, 0x15B6, 0x15B6 }, +{ 0x15B7, 0x15B7, 0x15B7 }, +{ 0x15B8, 0x15B8, 0x15B8 }, +{ 0x15B9, 0x15B9, 0x15B9 }, +{ 0x15BA, 0x15BA, 0x15BA }, +{ 0x15BB, 0x15BB, 0x15BB }, +{ 0x15BC, 0x15BC, 0x15BC }, +{ 0x15BD, 0x15BD, 0x15BD }, +{ 0x15BE, 0x15BE, 0x15BE }, +{ 0x15BF, 0x15BF, 0x15BF }, +{ 0x15C0, 0x15C0, 0x15C0 }, +{ 0x15C1, 0x15C1, 0x15C1 }, +{ 0x15C2, 0x15C2, 0x15C2 }, +{ 0x15C3, 0x15C3, 0x15C3 }, +{ 0x15C4, 0x15C4, 0x15C4 }, +{ 0x15C5, 0x15C5, 0x15C5 }, +{ 0x15C6, 0x15C6, 0x15C6 }, +{ 0x15C7, 0x15C7, 0x15C7 }, +{ 0x15C8, 0x15C8, 0x15C8 }, +{ 0x15C9, 0x15C9, 0x15C9 }, +{ 0x15CA, 0x15CA, 0x15CA }, +{ 0x15CB, 0x15CB, 0x15CB }, +{ 0x15CC, 0x15CC, 0x15CC }, +{ 0x15CD, 0x15CD, 0x15CD }, +{ 0x15CE, 0x15CE, 0x15CE }, +{ 0x15CF, 0x15CF, 0x15CF }, +{ 0x15D0, 0x15D0, 0x15D0 }, +{ 0x15D1, 0x15D1, 0x15D1 }, +{ 0x15D2, 0x15D2, 0x15D2 }, +{ 0x15D3, 0x15D3, 0x15D3 }, +{ 0x15D4, 0x15D4, 0x15D4 }, +{ 0x15D5, 0x15D5, 0x15D5 }, +{ 0x15D6, 0x15D6, 0x15D6 }, +{ 0x15D7, 0x15D7, 0x15D7 }, +{ 0x15D8, 0x15D8, 0x15D8 }, +{ 0x15D9, 0x15D9, 0x15D9 }, +{ 0x15DA, 0x15DA, 0x15DA }, +{ 0x15DB, 0x15DB, 0x15DB }, +{ 0x15DC, 0x15DC, 0x15DC }, +{ 0x15DD, 0x15DD, 0x15DD }, +{ 0x15DE, 0x15DE, 0x15DE }, +{ 0x15DF, 0x15DF, 0x15DF }, +{ 0x15E0, 0x15E0, 0x15E0 }, +{ 0x15E1, 0x15E1, 0x15E1 }, +{ 0x15E2, 0x15E2, 0x15E2 }, +{ 0x15E3, 0x15E3, 0x15E3 }, +{ 0x15E4, 0x15E4, 0x15E4 }, +{ 0x15E5, 0x15E5, 0x15E5 }, +{ 0x15E6, 0x15E6, 0x15E6 }, +{ 0x15E7, 0x15E7, 0x15E7 }, +{ 0x15E8, 0x15E8, 0x15E8 }, +{ 0x15E9, 0x15E9, 0x15E9 }, +{ 0x15EA, 0x15EA, 0x15EA }, +{ 0x15EB, 0x15EB, 0x15EB }, +{ 0x15EC, 0x15EC, 0x15EC }, +{ 0x15ED, 0x15ED, 0x15ED }, +{ 0x15EE, 0x15EE, 0x15EE }, +{ 0x15EF, 0x15EF, 0x15EF }, +{ 0x15F0, 0x15F0, 0x15F0 }, +{ 0x15F1, 0x15F1, 0x15F1 }, +{ 0x15F2, 0x15F2, 0x15F2 }, +{ 0x15F3, 0x15F3, 0x15F3 }, +{ 0x15F4, 0x15F4, 0x15F4 }, +{ 0x15F5, 0x15F5, 0x15F5 }, +{ 0x15F6, 0x15F6, 0x15F6 }, +{ 0x15F7, 0x15F7, 0x15F7 }, +{ 0x15F8, 0x15F8, 0x15F8 }, +{ 0x15F9, 0x15F9, 0x15F9 }, +{ 0x15FA, 0x15FA, 0x15FA }, +{ 0x15FB, 0x15FB, 0x15FB }, +{ 0x15FC, 0x15FC, 0x15FC }, +{ 0x15FD, 0x15FD, 0x15FD }, +{ 0x15FE, 0x15FE, 0x15FE }, +{ 0x15FF, 0x15FF, 0x15FF }, +{ 0x1600, 0x1600, 0x1600 }, +{ 0x1601, 0x1601, 0x1601 }, +{ 0x1602, 0x1602, 0x1602 }, +{ 0x1603, 0x1603, 0x1603 }, +{ 0x1604, 0x1604, 0x1604 }, +{ 0x1605, 0x1605, 0x1605 }, +{ 0x1606, 0x1606, 0x1606 }, +{ 0x1607, 0x1607, 0x1607 }, +{ 0x1608, 0x1608, 0x1608 }, +{ 0x1609, 0x1609, 0x1609 }, +{ 0x160A, 0x160A, 0x160A }, +{ 0x160B, 0x160B, 0x160B }, +{ 0x160C, 0x160C, 0x160C }, +{ 0x160D, 0x160D, 0x160D }, +{ 0x160E, 0x160E, 0x160E }, +{ 0x160F, 0x160F, 0x160F }, +{ 0x1610, 0x1610, 0x1610 }, +{ 0x1611, 0x1611, 0x1611 }, +{ 0x1612, 0x1612, 0x1612 }, +{ 0x1613, 0x1613, 0x1613 }, +{ 0x1614, 0x1614, 0x1614 }, +{ 0x1615, 0x1615, 0x1615 }, +{ 0x1616, 0x1616, 0x1616 }, +{ 0x1617, 0x1617, 0x1617 }, +{ 0x1618, 0x1618, 0x1618 }, +{ 0x1619, 0x1619, 0x1619 }, +{ 0x161A, 0x161A, 0x161A }, +{ 0x161B, 0x161B, 0x161B }, +{ 0x161C, 0x161C, 0x161C }, +{ 0x161D, 0x161D, 0x161D }, +{ 0x161E, 0x161E, 0x161E }, +{ 0x161F, 0x161F, 0x161F }, +{ 0x1620, 0x1620, 0x1620 }, +{ 0x1621, 0x1621, 0x1621 }, +{ 0x1622, 0x1622, 0x1622 }, +{ 0x1623, 0x1623, 0x1623 }, +{ 0x1624, 0x1624, 0x1624 }, +{ 0x1625, 0x1625, 0x1625 }, +{ 0x1626, 0x1626, 0x1626 }, +{ 0x1627, 0x1627, 0x1627 }, +{ 0x1628, 0x1628, 0x1628 }, +{ 0x1629, 0x1629, 0x1629 }, +{ 0x162A, 0x162A, 0x162A }, +{ 0x162B, 0x162B, 0x162B }, +{ 0x162C, 0x162C, 0x162C }, +{ 0x162D, 0x162D, 0x162D }, +{ 0x162E, 0x162E, 0x162E }, +{ 0x162F, 0x162F, 0x162F }, +{ 0x1630, 0x1630, 0x1630 }, +{ 0x1631, 0x1631, 0x1631 }, +{ 0x1632, 0x1632, 0x1632 }, +{ 0x1633, 0x1633, 0x1633 }, +{ 0x1634, 0x1634, 0x1634 }, +{ 0x1635, 0x1635, 0x1635 }, +{ 0x1636, 0x1636, 0x1636 }, +{ 0x1637, 0x1637, 0x1637 }, +{ 0x1638, 0x1638, 0x1638 }, +{ 0x1639, 0x1639, 0x1639 }, +{ 0x163A, 0x163A, 0x163A }, +{ 0x163B, 0x163B, 0x163B }, +{ 0x163C, 0x163C, 0x163C }, +{ 0x163D, 0x163D, 0x163D }, +{ 0x163E, 0x163E, 0x163E }, +{ 0x163F, 0x163F, 0x163F }, +{ 0x1640, 0x1640, 0x1640 }, +{ 0x1641, 0x1641, 0x1641 }, +{ 0x1642, 0x1642, 0x1642 }, +{ 0x1643, 0x1643, 0x1643 }, +{ 0x1644, 0x1644, 0x1644 }, +{ 0x1645, 0x1645, 0x1645 }, +{ 0x1646, 0x1646, 0x1646 }, +{ 0x1647, 0x1647, 0x1647 }, +{ 0x1648, 0x1648, 0x1648 }, +{ 0x1649, 0x1649, 0x1649 }, +{ 0x164A, 0x164A, 0x164A }, +{ 0x164B, 0x164B, 0x164B }, +{ 0x164C, 0x164C, 0x164C }, +{ 0x164D, 0x164D, 0x164D }, +{ 0x164E, 0x164E, 0x164E }, +{ 0x164F, 0x164F, 0x164F }, +{ 0x1650, 0x1650, 0x1650 }, +{ 0x1651, 0x1651, 0x1651 }, +{ 0x1652, 0x1652, 0x1652 }, +{ 0x1653, 0x1653, 0x1653 }, +{ 0x1654, 0x1654, 0x1654 }, +{ 0x1655, 0x1655, 0x1655 }, +{ 0x1656, 0x1656, 0x1656 }, +{ 0x1657, 0x1657, 0x1657 }, +{ 0x1658, 0x1658, 0x1658 }, +{ 0x1659, 0x1659, 0x1659 }, +{ 0x165A, 0x165A, 0x165A }, +{ 0x165B, 0x165B, 0x165B }, +{ 0x165C, 0x165C, 0x165C }, +{ 0x165D, 0x165D, 0x165D }, +{ 0x165E, 0x165E, 0x165E }, +{ 0x165F, 0x165F, 0x165F }, +{ 0x1660, 0x1660, 0x1660 }, +{ 0x1661, 0x1661, 0x1661 }, +{ 0x1662, 0x1662, 0x1662 }, +{ 0x1663, 0x1663, 0x1663 }, +{ 0x1664, 0x1664, 0x1664 }, +{ 0x1665, 0x1665, 0x1665 }, +{ 0x1666, 0x1666, 0x1666 }, +{ 0x1667, 0x1667, 0x1667 }, +{ 0x1668, 0x1668, 0x1668 }, +{ 0x1669, 0x1669, 0x1669 }, +{ 0x166A, 0x166A, 0x166A }, +{ 0x166B, 0x166B, 0x166B }, +{ 0x166C, 0x166C, 0x166C }, +{ 0x166F, 0x166F, 0x166F }, +{ 0x1670, 0x1670, 0x1670 }, +{ 0x1671, 0x1671, 0x1671 }, +{ 0x1672, 0x1672, 0x1672 }, +{ 0x1673, 0x1673, 0x1673 }, +{ 0x1674, 0x1674, 0x1674 }, +{ 0x1675, 0x1675, 0x1675 }, +{ 0x1676, 0x1676, 0x1676 }, +{ 0x1681, 0x1681, 0x1681 }, +{ 0x1682, 0x1682, 0x1682 }, +{ 0x1683, 0x1683, 0x1683 }, +{ 0x1684, 0x1684, 0x1684 }, +{ 0x1685, 0x1685, 0x1685 }, +{ 0x1686, 0x1686, 0x1686 }, +{ 0x1687, 0x1687, 0x1687 }, +{ 0x1688, 0x1688, 0x1688 }, +{ 0x1689, 0x1689, 0x1689 }, +{ 0x168A, 0x168A, 0x168A }, +{ 0x168B, 0x168B, 0x168B }, +{ 0x168C, 0x168C, 0x168C }, +{ 0x168D, 0x168D, 0x168D }, +{ 0x168E, 0x168E, 0x168E }, +{ 0x168F, 0x168F, 0x168F }, +{ 0x1690, 0x1690, 0x1690 }, +{ 0x1691, 0x1691, 0x1691 }, +{ 0x1692, 0x1692, 0x1692 }, +{ 0x1693, 0x1693, 0x1693 }, +{ 0x1694, 0x1694, 0x1694 }, +{ 0x1695, 0x1695, 0x1695 }, +{ 0x1696, 0x1696, 0x1696 }, +{ 0x1697, 0x1697, 0x1697 }, +{ 0x1698, 0x1698, 0x1698 }, +{ 0x1699, 0x1699, 0x1699 }, +{ 0x169A, 0x169A, 0x169A }, +{ 0x16A0, 0x16A0, 0x16A0 }, +{ 0x16A1, 0x16A1, 0x16A1 }, +{ 0x16A2, 0x16A2, 0x16A2 }, +{ 0x16A3, 0x16A3, 0x16A3 }, +{ 0x16A4, 0x16A4, 0x16A4 }, +{ 0x16A5, 0x16A5, 0x16A5 }, +{ 0x16A6, 0x16A6, 0x16A6 }, +{ 0x16A7, 0x16A7, 0x16A7 }, +{ 0x16A8, 0x16A8, 0x16A8 }, +{ 0x16A9, 0x16A9, 0x16A9 }, +{ 0x16AA, 0x16AA, 0x16AA }, +{ 0x16AB, 0x16AB, 0x16AB }, +{ 0x16AC, 0x16AC, 0x16AC }, +{ 0x16AD, 0x16AD, 0x16AD }, +{ 0x16AE, 0x16AE, 0x16AE }, +{ 0x16AF, 0x16AF, 0x16AF }, +{ 0x16B0, 0x16B0, 0x16B0 }, +{ 0x16B1, 0x16B1, 0x16B1 }, +{ 0x16B2, 0x16B2, 0x16B2 }, +{ 0x16B3, 0x16B3, 0x16B3 }, +{ 0x16B4, 0x16B4, 0x16B4 }, +{ 0x16B5, 0x16B5, 0x16B5 }, +{ 0x16B6, 0x16B6, 0x16B6 }, +{ 0x16B7, 0x16B7, 0x16B7 }, +{ 0x16B8, 0x16B8, 0x16B8 }, +{ 0x16B9, 0x16B9, 0x16B9 }, +{ 0x16BA, 0x16BA, 0x16BA }, +{ 0x16BB, 0x16BB, 0x16BB }, +{ 0x16BC, 0x16BC, 0x16BC }, +{ 0x16BD, 0x16BD, 0x16BD }, +{ 0x16BE, 0x16BE, 0x16BE }, +{ 0x16BF, 0x16BF, 0x16BF }, +{ 0x16C0, 0x16C0, 0x16C0 }, +{ 0x16C1, 0x16C1, 0x16C1 }, +{ 0x16C2, 0x16C2, 0x16C2 }, +{ 0x16C3, 0x16C3, 0x16C3 }, +{ 0x16C4, 0x16C4, 0x16C4 }, +{ 0x16C5, 0x16C5, 0x16C5 }, +{ 0x16C6, 0x16C6, 0x16C6 }, +{ 0x16C7, 0x16C7, 0x16C7 }, +{ 0x16C8, 0x16C8, 0x16C8 }, +{ 0x16C9, 0x16C9, 0x16C9 }, +{ 0x16CA, 0x16CA, 0x16CA }, +{ 0x16CB, 0x16CB, 0x16CB }, +{ 0x16CC, 0x16CC, 0x16CC }, +{ 0x16CD, 0x16CD, 0x16CD }, +{ 0x16CE, 0x16CE, 0x16CE }, +{ 0x16CF, 0x16CF, 0x16CF }, +{ 0x16D0, 0x16D0, 0x16D0 }, +{ 0x16D1, 0x16D1, 0x16D1 }, +{ 0x16D2, 0x16D2, 0x16D2 }, +{ 0x16D3, 0x16D3, 0x16D3 }, +{ 0x16D4, 0x16D4, 0x16D4 }, +{ 0x16D5, 0x16D5, 0x16D5 }, +{ 0x16D6, 0x16D6, 0x16D6 }, +{ 0x16D7, 0x16D7, 0x16D7 }, +{ 0x16D8, 0x16D8, 0x16D8 }, +{ 0x16D9, 0x16D9, 0x16D9 }, +{ 0x16DA, 0x16DA, 0x16DA }, +{ 0x16DB, 0x16DB, 0x16DB }, +{ 0x16DC, 0x16DC, 0x16DC }, +{ 0x16DD, 0x16DD, 0x16DD }, +{ 0x16DE, 0x16DE, 0x16DE }, +{ 0x16DF, 0x16DF, 0x16DF }, +{ 0x16E0, 0x16E0, 0x16E0 }, +{ 0x16E1, 0x16E1, 0x16E1 }, +{ 0x16E2, 0x16E2, 0x16E2 }, +{ 0x16E3, 0x16E3, 0x16E3 }, +{ 0x16E4, 0x16E4, 0x16E4 }, +{ 0x16E5, 0x16E5, 0x16E5 }, +{ 0x16E6, 0x16E6, 0x16E6 }, +{ 0x16E7, 0x16E7, 0x16E7 }, +{ 0x16E8, 0x16E8, 0x16E8 }, +{ 0x16E9, 0x16E9, 0x16E9 }, +{ 0x16EA, 0x16EA, 0x16EA }, +{ 0x1700, 0x1700, 0x1700 }, +{ 0x1701, 0x1701, 0x1701 }, +{ 0x1702, 0x1702, 0x1702 }, +{ 0x1703, 0x1703, 0x1703 }, +{ 0x1704, 0x1704, 0x1704 }, +{ 0x1705, 0x1705, 0x1705 }, +{ 0x1706, 0x1706, 0x1706 }, +{ 0x1707, 0x1707, 0x1707 }, +{ 0x1708, 0x1708, 0x1708 }, +{ 0x1709, 0x1709, 0x1709 }, +{ 0x170A, 0x170A, 0x170A }, +{ 0x170B, 0x170B, 0x170B }, +{ 0x170C, 0x170C, 0x170C }, +{ 0x170E, 0x170E, 0x170E }, +{ 0x170F, 0x170F, 0x170F }, +{ 0x1710, 0x1710, 0x1710 }, +{ 0x1711, 0x1711, 0x1711 }, +{ 0x1712, 0x1712, 0x1712 }, +{ 0x1713, 0x1713, 0x1713 }, +{ 0x1714, 0x1714, 0x1714 }, +{ 0x1720, 0x1720, 0x1720 }, +{ 0x1721, 0x1721, 0x1721 }, +{ 0x1722, 0x1722, 0x1722 }, +{ 0x1723, 0x1723, 0x1723 }, +{ 0x1724, 0x1724, 0x1724 }, +{ 0x1725, 0x1725, 0x1725 }, +{ 0x1726, 0x1726, 0x1726 }, +{ 0x1727, 0x1727, 0x1727 }, +{ 0x1728, 0x1728, 0x1728 }, +{ 0x1729, 0x1729, 0x1729 }, +{ 0x172A, 0x172A, 0x172A }, +{ 0x172B, 0x172B, 0x172B }, +{ 0x172C, 0x172C, 0x172C }, +{ 0x172D, 0x172D, 0x172D }, +{ 0x172E, 0x172E, 0x172E }, +{ 0x172F, 0x172F, 0x172F }, +{ 0x1730, 0x1730, 0x1730 }, +{ 0x1731, 0x1731, 0x1731 }, +{ 0x1732, 0x1732, 0x1732 }, +{ 0x1733, 0x1733, 0x1733 }, +{ 0x1734, 0x1734, 0x1734 }, +{ 0x1740, 0x1740, 0x1740 }, +{ 0x1741, 0x1741, 0x1741 }, +{ 0x1742, 0x1742, 0x1742 }, +{ 0x1743, 0x1743, 0x1743 }, +{ 0x1744, 0x1744, 0x1744 }, +{ 0x1745, 0x1745, 0x1745 }, +{ 0x1746, 0x1746, 0x1746 }, +{ 0x1747, 0x1747, 0x1747 }, +{ 0x1748, 0x1748, 0x1748 }, +{ 0x1749, 0x1749, 0x1749 }, +{ 0x174A, 0x174A, 0x174A }, +{ 0x174B, 0x174B, 0x174B }, +{ 0x174C, 0x174C, 0x174C }, +{ 0x174D, 0x174D, 0x174D }, +{ 0x174E, 0x174E, 0x174E }, +{ 0x174F, 0x174F, 0x174F }, +{ 0x1750, 0x1750, 0x1750 }, +{ 0x1751, 0x1751, 0x1751 }, +{ 0x1752, 0x1752, 0x1752 }, +{ 0x1753, 0x1753, 0x1753 }, +{ 0x1760, 0x1760, 0x1760 }, +{ 0x1761, 0x1761, 0x1761 }, +{ 0x1762, 0x1762, 0x1762 }, +{ 0x1763, 0x1763, 0x1763 }, +{ 0x1764, 0x1764, 0x1764 }, +{ 0x1765, 0x1765, 0x1765 }, +{ 0x1766, 0x1766, 0x1766 }, +{ 0x1767, 0x1767, 0x1767 }, +{ 0x1768, 0x1768, 0x1768 }, +{ 0x1769, 0x1769, 0x1769 }, +{ 0x176A, 0x176A, 0x176A }, +{ 0x176B, 0x176B, 0x176B }, +{ 0x176C, 0x176C, 0x176C }, +{ 0x176E, 0x176E, 0x176E }, +{ 0x176F, 0x176F, 0x176F }, +{ 0x1770, 0x1770, 0x1770 }, +{ 0x1772, 0x1772, 0x1772 }, +{ 0x1773, 0x1773, 0x1773 }, +{ 0x1780, 0x1780, 0x1780 }, +{ 0x1781, 0x1781, 0x1781 }, +{ 0x1782, 0x1782, 0x1782 }, +{ 0x1783, 0x1783, 0x1783 }, +{ 0x1784, 0x1784, 0x1784 }, +{ 0x1785, 0x1785, 0x1785 }, +{ 0x1786, 0x1786, 0x1786 }, +{ 0x1787, 0x1787, 0x1787 }, +{ 0x1788, 0x1788, 0x1788 }, +{ 0x1789, 0x1789, 0x1789 }, +{ 0x178A, 0x178A, 0x178A }, +{ 0x178B, 0x178B, 0x178B }, +{ 0x178C, 0x178C, 0x178C }, +{ 0x178D, 0x178D, 0x178D }, +{ 0x178E, 0x178E, 0x178E }, +{ 0x178F, 0x178F, 0x178F }, +{ 0x1790, 0x1790, 0x1790 }, +{ 0x1791, 0x1791, 0x1791 }, +{ 0x1792, 0x1792, 0x1792 }, +{ 0x1793, 0x1793, 0x1793 }, +{ 0x1794, 0x1794, 0x1794 }, +{ 0x1795, 0x1795, 0x1795 }, +{ 0x1796, 0x1796, 0x1796 }, +{ 0x1797, 0x1797, 0x1797 }, +{ 0x1798, 0x1798, 0x1798 }, +{ 0x1799, 0x1799, 0x1799 }, +{ 0x179A, 0x179A, 0x179A }, +{ 0x179B, 0x179B, 0x179B }, +{ 0x179C, 0x179C, 0x179C }, +{ 0x179D, 0x179D, 0x179D }, +{ 0x179E, 0x179E, 0x179E }, +{ 0x179F, 0x179F, 0x179F }, +{ 0x17A0, 0x17A0, 0x17A0 }, +{ 0x17A1, 0x17A1, 0x17A1 }, +{ 0x17A2, 0x17A2, 0x17A2 }, +{ 0x17A3, 0x17A3, 0x17A3 }, +{ 0x17A4, 0x17A4, 0x17A4 }, +{ 0x17A5, 0x17A5, 0x17A5 }, +{ 0x17A6, 0x17A6, 0x17A6 }, +{ 0x17A7, 0x17A7, 0x17A7 }, +{ 0x17A8, 0x17A8, 0x17A8 }, +{ 0x17A9, 0x17A9, 0x17A9 }, +{ 0x17AA, 0x17AA, 0x17AA }, +{ 0x17AB, 0x17AB, 0x17AB }, +{ 0x17AC, 0x17AC, 0x17AC }, +{ 0x17AD, 0x17AD, 0x17AD }, +{ 0x17AE, 0x17AE, 0x17AE }, +{ 0x17AF, 0x17AF, 0x17AF }, +{ 0x17B0, 0x17B0, 0x17B0 }, +{ 0x17B1, 0x17B1, 0x17B1 }, +{ 0x17B2, 0x17B2, 0x17B2 }, +{ 0x17B3, 0x17B3, 0x17B3 }, +{ 0x17B7, 0x17B7, 0x17B7 }, +{ 0x17B8, 0x17B8, 0x17B8 }, +{ 0x17B9, 0x17B9, 0x17B9 }, +{ 0x17BA, 0x17BA, 0x17BA }, +{ 0x17BB, 0x17BB, 0x17BB }, +{ 0x17BC, 0x17BC, 0x17BC }, +{ 0x17BD, 0x17BD, 0x17BD }, +{ 0x17C6, 0x17C6, 0x17C6 }, +{ 0x17C9, 0x17C9, 0x17C9 }, +{ 0x17CA, 0x17CA, 0x17CA }, +{ 0x17CB, 0x17CB, 0x17CB }, +{ 0x17CC, 0x17CC, 0x17CC }, +{ 0x17CD, 0x17CD, 0x17CD }, +{ 0x17CE, 0x17CE, 0x17CE }, +{ 0x17CF, 0x17CF, 0x17CF }, +{ 0x17D0, 0x17D0, 0x17D0 }, +{ 0x17D1, 0x17D1, 0x17D1 }, +{ 0x17D2, 0x17D2, 0x17D2 }, +{ 0x17D3, 0x17D3, 0x17D3 }, +{ 0x17D7, 0x17D7, 0x17D7 }, +{ 0x17DC, 0x17DC, 0x17DC }, +{ 0x17DD, 0x17DD, 0x17DD }, +{ 0x180B, 0x180B, 0x180B }, +{ 0x180C, 0x180C, 0x180C }, +{ 0x180D, 0x180D, 0x180D }, +{ 0x1820, 0x1820, 0x1820 }, +{ 0x1821, 0x1821, 0x1821 }, +{ 0x1822, 0x1822, 0x1822 }, +{ 0x1823, 0x1823, 0x1823 }, +{ 0x1824, 0x1824, 0x1824 }, +{ 0x1825, 0x1825, 0x1825 }, +{ 0x1826, 0x1826, 0x1826 }, +{ 0x1827, 0x1827, 0x1827 }, +{ 0x1828, 0x1828, 0x1828 }, +{ 0x1829, 0x1829, 0x1829 }, +{ 0x182A, 0x182A, 0x182A }, +{ 0x182B, 0x182B, 0x182B }, +{ 0x182C, 0x182C, 0x182C }, +{ 0x182D, 0x182D, 0x182D }, +{ 0x182E, 0x182E, 0x182E }, +{ 0x182F, 0x182F, 0x182F }, +{ 0x1830, 0x1830, 0x1830 }, +{ 0x1831, 0x1831, 0x1831 }, +{ 0x1832, 0x1832, 0x1832 }, +{ 0x1833, 0x1833, 0x1833 }, +{ 0x1834, 0x1834, 0x1834 }, +{ 0x1835, 0x1835, 0x1835 }, +{ 0x1836, 0x1836, 0x1836 }, +{ 0x1837, 0x1837, 0x1837 }, +{ 0x1838, 0x1838, 0x1838 }, +{ 0x1839, 0x1839, 0x1839 }, +{ 0x183A, 0x183A, 0x183A }, +{ 0x183B, 0x183B, 0x183B }, +{ 0x183C, 0x183C, 0x183C }, +{ 0x183D, 0x183D, 0x183D }, +{ 0x183E, 0x183E, 0x183E }, +{ 0x183F, 0x183F, 0x183F }, +{ 0x1840, 0x1840, 0x1840 }, +{ 0x1841, 0x1841, 0x1841 }, +{ 0x1842, 0x1842, 0x1842 }, +{ 0x1843, 0x1843, 0x1843 }, +{ 0x1844, 0x1844, 0x1844 }, +{ 0x1845, 0x1845, 0x1845 }, +{ 0x1846, 0x1846, 0x1846 }, +{ 0x1847, 0x1847, 0x1847 }, +{ 0x1848, 0x1848, 0x1848 }, +{ 0x1849, 0x1849, 0x1849 }, +{ 0x184A, 0x184A, 0x184A }, +{ 0x184B, 0x184B, 0x184B }, +{ 0x184C, 0x184C, 0x184C }, +{ 0x184D, 0x184D, 0x184D }, +{ 0x184E, 0x184E, 0x184E }, +{ 0x184F, 0x184F, 0x184F }, +{ 0x1850, 0x1850, 0x1850 }, +{ 0x1851, 0x1851, 0x1851 }, +{ 0x1852, 0x1852, 0x1852 }, +{ 0x1853, 0x1853, 0x1853 }, +{ 0x1854, 0x1854, 0x1854 }, +{ 0x1855, 0x1855, 0x1855 }, +{ 0x1856, 0x1856, 0x1856 }, +{ 0x1857, 0x1857, 0x1857 }, +{ 0x1858, 0x1858, 0x1858 }, +{ 0x1859, 0x1859, 0x1859 }, +{ 0x185A, 0x185A, 0x185A }, +{ 0x185B, 0x185B, 0x185B }, +{ 0x185C, 0x185C, 0x185C }, +{ 0x185D, 0x185D, 0x185D }, +{ 0x185E, 0x185E, 0x185E }, +{ 0x185F, 0x185F, 0x185F }, +{ 0x1860, 0x1860, 0x1860 }, +{ 0x1861, 0x1861, 0x1861 }, +{ 0x1862, 0x1862, 0x1862 }, +{ 0x1863, 0x1863, 0x1863 }, +{ 0x1864, 0x1864, 0x1864 }, +{ 0x1865, 0x1865, 0x1865 }, +{ 0x1866, 0x1866, 0x1866 }, +{ 0x1867, 0x1867, 0x1867 }, +{ 0x1868, 0x1868, 0x1868 }, +{ 0x1869, 0x1869, 0x1869 }, +{ 0x186A, 0x186A, 0x186A }, +{ 0x186B, 0x186B, 0x186B }, +{ 0x186C, 0x186C, 0x186C }, +{ 0x186D, 0x186D, 0x186D }, +{ 0x186E, 0x186E, 0x186E }, +{ 0x186F, 0x186F, 0x186F }, +{ 0x1870, 0x1870, 0x1870 }, +{ 0x1871, 0x1871, 0x1871 }, +{ 0x1872, 0x1872, 0x1872 }, +{ 0x1873, 0x1873, 0x1873 }, +{ 0x1874, 0x1874, 0x1874 }, +{ 0x1875, 0x1875, 0x1875 }, +{ 0x1876, 0x1876, 0x1876 }, +{ 0x1877, 0x1877, 0x1877 }, +{ 0x1880, 0x1880, 0x1880 }, +{ 0x1881, 0x1881, 0x1881 }, +{ 0x1882, 0x1882, 0x1882 }, +{ 0x1883, 0x1883, 0x1883 }, +{ 0x1884, 0x1884, 0x1884 }, +{ 0x1885, 0x1885, 0x1885 }, +{ 0x1886, 0x1886, 0x1886 }, +{ 0x1887, 0x1887, 0x1887 }, +{ 0x1888, 0x1888, 0x1888 }, +{ 0x1889, 0x1889, 0x1889 }, +{ 0x188A, 0x188A, 0x188A }, +{ 0x188B, 0x188B, 0x188B }, +{ 0x188C, 0x188C, 0x188C }, +{ 0x188D, 0x188D, 0x188D }, +{ 0x188E, 0x188E, 0x188E }, +{ 0x188F, 0x188F, 0x188F }, +{ 0x1890, 0x1890, 0x1890 }, +{ 0x1891, 0x1891, 0x1891 }, +{ 0x1892, 0x1892, 0x1892 }, +{ 0x1893, 0x1893, 0x1893 }, +{ 0x1894, 0x1894, 0x1894 }, +{ 0x1895, 0x1895, 0x1895 }, +{ 0x1896, 0x1896, 0x1896 }, +{ 0x1897, 0x1897, 0x1897 }, +{ 0x1898, 0x1898, 0x1898 }, +{ 0x1899, 0x1899, 0x1899 }, +{ 0x189A, 0x189A, 0x189A }, +{ 0x189B, 0x189B, 0x189B }, +{ 0x189C, 0x189C, 0x189C }, +{ 0x189D, 0x189D, 0x189D }, +{ 0x189E, 0x189E, 0x189E }, +{ 0x189F, 0x189F, 0x189F }, +{ 0x18A0, 0x18A0, 0x18A0 }, +{ 0x18A1, 0x18A1, 0x18A1 }, +{ 0x18A2, 0x18A2, 0x18A2 }, +{ 0x18A3, 0x18A3, 0x18A3 }, +{ 0x18A4, 0x18A4, 0x18A4 }, +{ 0x18A5, 0x18A5, 0x18A5 }, +{ 0x18A6, 0x18A6, 0x18A6 }, +{ 0x18A7, 0x18A7, 0x18A7 }, +{ 0x18A8, 0x18A8, 0x18A8 }, +{ 0x18A9, 0x18A9, 0x18A9 }, +{ 0x1900, 0x1900, 0x1900 }, +{ 0x1901, 0x1901, 0x1901 }, +{ 0x1902, 0x1902, 0x1902 }, +{ 0x1903, 0x1903, 0x1903 }, +{ 0x1904, 0x1904, 0x1904 }, +{ 0x1905, 0x1905, 0x1905 }, +{ 0x1906, 0x1906, 0x1906 }, +{ 0x1907, 0x1907, 0x1907 }, +{ 0x1908, 0x1908, 0x1908 }, +{ 0x1909, 0x1909, 0x1909 }, +{ 0x190A, 0x190A, 0x190A }, +{ 0x190B, 0x190B, 0x190B }, +{ 0x190C, 0x190C, 0x190C }, +{ 0x190D, 0x190D, 0x190D }, +{ 0x190E, 0x190E, 0x190E }, +{ 0x190F, 0x190F, 0x190F }, +{ 0x1910, 0x1910, 0x1910 }, +{ 0x1911, 0x1911, 0x1911 }, +{ 0x1912, 0x1912, 0x1912 }, +{ 0x1913, 0x1913, 0x1913 }, +{ 0x1914, 0x1914, 0x1914 }, +{ 0x1915, 0x1915, 0x1915 }, +{ 0x1916, 0x1916, 0x1916 }, +{ 0x1917, 0x1917, 0x1917 }, +{ 0x1918, 0x1918, 0x1918 }, +{ 0x1919, 0x1919, 0x1919 }, +{ 0x191A, 0x191A, 0x191A }, +{ 0x191B, 0x191B, 0x191B }, +{ 0x191C, 0x191C, 0x191C }, +{ 0x1920, 0x1920, 0x1920 }, +{ 0x1921, 0x1921, 0x1921 }, +{ 0x1922, 0x1922, 0x1922 }, +{ 0x1927, 0x1927, 0x1927 }, +{ 0x1928, 0x1928, 0x1928 }, +{ 0x1932, 0x1932, 0x1932 }, +{ 0x1939, 0x1939, 0x1939 }, +{ 0x193A, 0x193A, 0x193A }, +{ 0x193B, 0x193B, 0x193B }, +{ 0x1950, 0x1950, 0x1950 }, +{ 0x1951, 0x1951, 0x1951 }, +{ 0x1952, 0x1952, 0x1952 }, +{ 0x1953, 0x1953, 0x1953 }, +{ 0x1954, 0x1954, 0x1954 }, +{ 0x1955, 0x1955, 0x1955 }, +{ 0x1956, 0x1956, 0x1956 }, +{ 0x1957, 0x1957, 0x1957 }, +{ 0x1958, 0x1958, 0x1958 }, +{ 0x1959, 0x1959, 0x1959 }, +{ 0x195A, 0x195A, 0x195A }, +{ 0x195B, 0x195B, 0x195B }, +{ 0x195C, 0x195C, 0x195C }, +{ 0x195D, 0x195D, 0x195D }, +{ 0x195E, 0x195E, 0x195E }, +{ 0x195F, 0x195F, 0x195F }, +{ 0x1960, 0x1960, 0x1960 }, +{ 0x1961, 0x1961, 0x1961 }, +{ 0x1962, 0x1962, 0x1962 }, +{ 0x1963, 0x1963, 0x1963 }, +{ 0x1964, 0x1964, 0x1964 }, +{ 0x1965, 0x1965, 0x1965 }, +{ 0x1966, 0x1966, 0x1966 }, +{ 0x1967, 0x1967, 0x1967 }, +{ 0x1968, 0x1968, 0x1968 }, +{ 0x1969, 0x1969, 0x1969 }, +{ 0x196A, 0x196A, 0x196A }, +{ 0x196B, 0x196B, 0x196B }, +{ 0x196C, 0x196C, 0x196C }, +{ 0x196D, 0x196D, 0x196D }, +{ 0x1970, 0x1970, 0x1970 }, +{ 0x1971, 0x1971, 0x1971 }, +{ 0x1972, 0x1972, 0x1972 }, +{ 0x1973, 0x1973, 0x1973 }, +{ 0x1974, 0x1974, 0x1974 }, +{ 0x1980, 0x1980, 0x1980 }, +{ 0x1981, 0x1981, 0x1981 }, +{ 0x1982, 0x1982, 0x1982 }, +{ 0x1983, 0x1983, 0x1983 }, +{ 0x1984, 0x1984, 0x1984 }, +{ 0x1985, 0x1985, 0x1985 }, +{ 0x1986, 0x1986, 0x1986 }, +{ 0x1987, 0x1987, 0x1987 }, +{ 0x1988, 0x1988, 0x1988 }, +{ 0x1989, 0x1989, 0x1989 }, +{ 0x198A, 0x198A, 0x198A }, +{ 0x198B, 0x198B, 0x198B }, +{ 0x198C, 0x198C, 0x198C }, +{ 0x198D, 0x198D, 0x198D }, +{ 0x198E, 0x198E, 0x198E }, +{ 0x198F, 0x198F, 0x198F }, +{ 0x1990, 0x1990, 0x1990 }, +{ 0x1991, 0x1991, 0x1991 }, +{ 0x1992, 0x1992, 0x1992 }, +{ 0x1993, 0x1993, 0x1993 }, +{ 0x1994, 0x1994, 0x1994 }, +{ 0x1995, 0x1995, 0x1995 }, +{ 0x1996, 0x1996, 0x1996 }, +{ 0x1997, 0x1997, 0x1997 }, +{ 0x1998, 0x1998, 0x1998 }, +{ 0x1999, 0x1999, 0x1999 }, +{ 0x199A, 0x199A, 0x199A }, +{ 0x199B, 0x199B, 0x199B }, +{ 0x199C, 0x199C, 0x199C }, +{ 0x199D, 0x199D, 0x199D }, +{ 0x199E, 0x199E, 0x199E }, +{ 0x199F, 0x199F, 0x199F }, +{ 0x19A0, 0x19A0, 0x19A0 }, +{ 0x19A1, 0x19A1, 0x19A1 }, +{ 0x19A2, 0x19A2, 0x19A2 }, +{ 0x19A3, 0x19A3, 0x19A3 }, +{ 0x19A4, 0x19A4, 0x19A4 }, +{ 0x19A5, 0x19A5, 0x19A5 }, +{ 0x19A6, 0x19A6, 0x19A6 }, +{ 0x19A7, 0x19A7, 0x19A7 }, +{ 0x19A8, 0x19A8, 0x19A8 }, +{ 0x19A9, 0x19A9, 0x19A9 }, +{ 0x19C1, 0x19C1, 0x19C1 }, +{ 0x19C2, 0x19C2, 0x19C2 }, +{ 0x19C3, 0x19C3, 0x19C3 }, +{ 0x19C4, 0x19C4, 0x19C4 }, +{ 0x19C5, 0x19C5, 0x19C5 }, +{ 0x19C6, 0x19C6, 0x19C6 }, +{ 0x19C7, 0x19C7, 0x19C7 }, +{ 0x1A00, 0x1A00, 0x1A00 }, +{ 0x1A01, 0x1A01, 0x1A01 }, +{ 0x1A02, 0x1A02, 0x1A02 }, +{ 0x1A03, 0x1A03, 0x1A03 }, +{ 0x1A04, 0x1A04, 0x1A04 }, +{ 0x1A05, 0x1A05, 0x1A05 }, +{ 0x1A06, 0x1A06, 0x1A06 }, +{ 0x1A07, 0x1A07, 0x1A07 }, +{ 0x1A08, 0x1A08, 0x1A08 }, +{ 0x1A09, 0x1A09, 0x1A09 }, +{ 0x1A0A, 0x1A0A, 0x1A0A }, +{ 0x1A0B, 0x1A0B, 0x1A0B }, +{ 0x1A0C, 0x1A0C, 0x1A0C }, +{ 0x1A0D, 0x1A0D, 0x1A0D }, +{ 0x1A0E, 0x1A0E, 0x1A0E }, +{ 0x1A0F, 0x1A0F, 0x1A0F }, +{ 0x1A10, 0x1A10, 0x1A10 }, +{ 0x1A11, 0x1A11, 0x1A11 }, +{ 0x1A12, 0x1A12, 0x1A12 }, +{ 0x1A13, 0x1A13, 0x1A13 }, +{ 0x1A14, 0x1A14, 0x1A14 }, +{ 0x1A15, 0x1A15, 0x1A15 }, +{ 0x1A16, 0x1A16, 0x1A16 }, +{ 0x1A17, 0x1A17, 0x1A17 }, +{ 0x1A18, 0x1A18, 0x1A18 }, +{ 0x1D00, 0x1D00, 0x1D00 }, +{ 0x1D01, 0x1D01, 0x1D01 }, +{ 0x1D02, 0x1D02, 0x1D02 }, +{ 0x1D03, 0x1D03, 0x1D03 }, +{ 0x1D04, 0x1D04, 0x1D04 }, +{ 0x1D05, 0x1D05, 0x1D05 }, +{ 0x1D06, 0x1D06, 0x1D06 }, +{ 0x1D07, 0x1D07, 0x1D07 }, +{ 0x1D08, 0x1D08, 0x1D08 }, +{ 0x1D09, 0x1D09, 0x1D09 }, +{ 0x1D0A, 0x1D0A, 0x1D0A }, +{ 0x1D0B, 0x1D0B, 0x1D0B }, +{ 0x1D0C, 0x1D0C, 0x1D0C }, +{ 0x1D0D, 0x1D0D, 0x1D0D }, +{ 0x1D0E, 0x1D0E, 0x1D0E }, +{ 0x1D0F, 0x1D0F, 0x1D0F }, +{ 0x1D10, 0x1D10, 0x1D10 }, +{ 0x1D11, 0x1D11, 0x1D11 }, +{ 0x1D12, 0x1D12, 0x1D12 }, +{ 0x1D13, 0x1D13, 0x1D13 }, +{ 0x1D14, 0x1D14, 0x1D14 }, +{ 0x1D15, 0x1D15, 0x1D15 }, +{ 0x1D16, 0x1D16, 0x1D16 }, +{ 0x1D17, 0x1D17, 0x1D17 }, +{ 0x1D18, 0x1D18, 0x1D18 }, +{ 0x1D19, 0x1D19, 0x1D19 }, +{ 0x1D1A, 0x1D1A, 0x1D1A }, +{ 0x1D1B, 0x1D1B, 0x1D1B }, +{ 0x1D1C, 0x1D1C, 0x1D1C }, +{ 0x1D1D, 0x1D1D, 0x1D1D }, +{ 0x1D1E, 0x1D1E, 0x1D1E }, +{ 0x1D1F, 0x1D1F, 0x1D1F }, +{ 0x1D20, 0x1D20, 0x1D20 }, +{ 0x1D21, 0x1D21, 0x1D21 }, +{ 0x1D22, 0x1D22, 0x1D22 }, +{ 0x1D23, 0x1D23, 0x1D23 }, +{ 0x1D24, 0x1D24, 0x1D24 }, +{ 0x1D25, 0x1D25, 0x1D25 }, +{ 0x1D26, 0x1D26, 0x1D26 }, +{ 0x1D27, 0x1D27, 0x1D27 }, +{ 0x1D28, 0x1D28, 0x1D28 }, +{ 0x1D29, 0x1D29, 0x1D29 }, +{ 0x1D2A, 0x1D2A, 0x1D2A }, +{ 0x1D2B, 0x1D2B, 0x1D2B }, +{ 0x1D2C, 0x1D2C, 0x1D2C }, +{ 0x1D2D, 0x1D2D, 0x1D2D }, +{ 0x1D2E, 0x1D2E, 0x1D2E }, +{ 0x1D2F, 0x1D2F, 0x1D2F }, +{ 0x1D30, 0x1D30, 0x1D30 }, +{ 0x1D31, 0x1D31, 0x1D31 }, +{ 0x1D32, 0x1D32, 0x1D32 }, +{ 0x1D33, 0x1D33, 0x1D33 }, +{ 0x1D34, 0x1D34, 0x1D34 }, +{ 0x1D35, 0x1D35, 0x1D35 }, +{ 0x1D36, 0x1D36, 0x1D36 }, +{ 0x1D37, 0x1D37, 0x1D37 }, +{ 0x1D38, 0x1D38, 0x1D38 }, +{ 0x1D39, 0x1D39, 0x1D39 }, +{ 0x1D3A, 0x1D3A, 0x1D3A }, +{ 0x1D3B, 0x1D3B, 0x1D3B }, +{ 0x1D3C, 0x1D3C, 0x1D3C }, +{ 0x1D3D, 0x1D3D, 0x1D3D }, +{ 0x1D3E, 0x1D3E, 0x1D3E }, +{ 0x1D3F, 0x1D3F, 0x1D3F }, +{ 0x1D40, 0x1D40, 0x1D40 }, +{ 0x1D41, 0x1D41, 0x1D41 }, +{ 0x1D42, 0x1D42, 0x1D42 }, +{ 0x1D43, 0x1D43, 0x1D43 }, +{ 0x1D44, 0x1D44, 0x1D44 }, +{ 0x1D45, 0x1D45, 0x1D45 }, +{ 0x1D46, 0x1D46, 0x1D46 }, +{ 0x1D47, 0x1D47, 0x1D47 }, +{ 0x1D48, 0x1D48, 0x1D48 }, +{ 0x1D49, 0x1D49, 0x1D49 }, +{ 0x1D4A, 0x1D4A, 0x1D4A }, +{ 0x1D4B, 0x1D4B, 0x1D4B }, +{ 0x1D4C, 0x1D4C, 0x1D4C }, +{ 0x1D4D, 0x1D4D, 0x1D4D }, +{ 0x1D4E, 0x1D4E, 0x1D4E }, +{ 0x1D4F, 0x1D4F, 0x1D4F }, +{ 0x1D50, 0x1D50, 0x1D50 }, +{ 0x1D51, 0x1D51, 0x1D51 }, +{ 0x1D52, 0x1D52, 0x1D52 }, +{ 0x1D53, 0x1D53, 0x1D53 }, +{ 0x1D54, 0x1D54, 0x1D54 }, +{ 0x1D55, 0x1D55, 0x1D55 }, +{ 0x1D56, 0x1D56, 0x1D56 }, +{ 0x1D57, 0x1D57, 0x1D57 }, +{ 0x1D58, 0x1D58, 0x1D58 }, +{ 0x1D59, 0x1D59, 0x1D59 }, +{ 0x1D5A, 0x1D5A, 0x1D5A }, +{ 0x1D5B, 0x1D5B, 0x1D5B }, +{ 0x1D5C, 0x1D5C, 0x1D5C }, +{ 0x1D5D, 0x1D5D, 0x1D5D }, +{ 0x1D5E, 0x1D5E, 0x1D5E }, +{ 0x1D5F, 0x1D5F, 0x1D5F }, +{ 0x1D60, 0x1D60, 0x1D60 }, +{ 0x1D61, 0x1D61, 0x1D61 }, +{ 0x1D62, 0x1D62, 0x1D62 }, +{ 0x1D63, 0x1D63, 0x1D63 }, +{ 0x1D64, 0x1D64, 0x1D64 }, +{ 0x1D65, 0x1D65, 0x1D65 }, +{ 0x1D66, 0x1D66, 0x1D66 }, +{ 0x1D67, 0x1D67, 0x1D67 }, +{ 0x1D68, 0x1D68, 0x1D68 }, +{ 0x1D69, 0x1D69, 0x1D69 }, +{ 0x1D6A, 0x1D6A, 0x1D6A }, +{ 0x1D6B, 0x1D6B, 0x1D6B }, +{ 0x1D6C, 0x1D6C, 0x1D6C }, +{ 0x1D6D, 0x1D6D, 0x1D6D }, +{ 0x1D6E, 0x1D6E, 0x1D6E }, +{ 0x1D6F, 0x1D6F, 0x1D6F }, +{ 0x1D70, 0x1D70, 0x1D70 }, +{ 0x1D71, 0x1D71, 0x1D71 }, +{ 0x1D72, 0x1D72, 0x1D72 }, +{ 0x1D73, 0x1D73, 0x1D73 }, +{ 0x1D74, 0x1D74, 0x1D74 }, +{ 0x1D75, 0x1D75, 0x1D75 }, +{ 0x1D76, 0x1D76, 0x1D76 }, +{ 0x1D77, 0x1D77, 0x1D77 }, +{ 0x1D78, 0x1D78, 0x1D78 }, +{ 0x1D79, 0x1D79, 0x1D79 }, +{ 0x1D7A, 0x1D7A, 0x1D7A }, +{ 0x1D7B, 0x1D7B, 0x1D7B }, +{ 0x1D7C, 0x1D7C, 0x1D7C }, +{ 0x1D7D, 0x1D7D, 0x1D7D }, +{ 0x1D7E, 0x1D7E, 0x1D7E }, +{ 0x1D7F, 0x1D7F, 0x1D7F }, +{ 0x1D80, 0x1D80, 0x1D80 }, +{ 0x1D81, 0x1D81, 0x1D81 }, +{ 0x1D82, 0x1D82, 0x1D82 }, +{ 0x1D83, 0x1D83, 0x1D83 }, +{ 0x1D84, 0x1D84, 0x1D84 }, +{ 0x1D85, 0x1D85, 0x1D85 }, +{ 0x1D86, 0x1D86, 0x1D86 }, +{ 0x1D87, 0x1D87, 0x1D87 }, +{ 0x1D88, 0x1D88, 0x1D88 }, +{ 0x1D89, 0x1D89, 0x1D89 }, +{ 0x1D8A, 0x1D8A, 0x1D8A }, +{ 0x1D8B, 0x1D8B, 0x1D8B }, +{ 0x1D8C, 0x1D8C, 0x1D8C }, +{ 0x1D8D, 0x1D8D, 0x1D8D }, +{ 0x1D8E, 0x1D8E, 0x1D8E }, +{ 0x1D8F, 0x1D8F, 0x1D8F }, +{ 0x1D90, 0x1D90, 0x1D90 }, +{ 0x1D91, 0x1D91, 0x1D91 }, +{ 0x1D92, 0x1D92, 0x1D92 }, +{ 0x1D93, 0x1D93, 0x1D93 }, +{ 0x1D94, 0x1D94, 0x1D94 }, +{ 0x1D95, 0x1D95, 0x1D95 }, +{ 0x1D96, 0x1D96, 0x1D96 }, +{ 0x1D97, 0x1D97, 0x1D97 }, +{ 0x1D98, 0x1D98, 0x1D98 }, +{ 0x1D99, 0x1D99, 0x1D99 }, +{ 0x1D9A, 0x1D9A, 0x1D9A }, +{ 0x1D9B, 0x1D9B, 0x1D9B }, +{ 0x1D9C, 0x1D9C, 0x1D9C }, +{ 0x1D9D, 0x1D9D, 0x1D9D }, +{ 0x1D9E, 0x1D9E, 0x1D9E }, +{ 0x1D9F, 0x1D9F, 0x1D9F }, +{ 0x1DA0, 0x1DA0, 0x1DA0 }, +{ 0x1DA1, 0x1DA1, 0x1DA1 }, +{ 0x1DA2, 0x1DA2, 0x1DA2 }, +{ 0x1DA3, 0x1DA3, 0x1DA3 }, +{ 0x1DA4, 0x1DA4, 0x1DA4 }, +{ 0x1DA5, 0x1DA5, 0x1DA5 }, +{ 0x1DA6, 0x1DA6, 0x1DA6 }, +{ 0x1DA7, 0x1DA7, 0x1DA7 }, +{ 0x1DA8, 0x1DA8, 0x1DA8 }, +{ 0x1DA9, 0x1DA9, 0x1DA9 }, +{ 0x1DAA, 0x1DAA, 0x1DAA }, +{ 0x1DAB, 0x1DAB, 0x1DAB }, +{ 0x1DAC, 0x1DAC, 0x1DAC }, +{ 0x1DAD, 0x1DAD, 0x1DAD }, +{ 0x1DAE, 0x1DAE, 0x1DAE }, +{ 0x1DAF, 0x1DAF, 0x1DAF }, +{ 0x1DB0, 0x1DB0, 0x1DB0 }, +{ 0x1DB1, 0x1DB1, 0x1DB1 }, +{ 0x1DB2, 0x1DB2, 0x1DB2 }, +{ 0x1DB3, 0x1DB3, 0x1DB3 }, +{ 0x1DB4, 0x1DB4, 0x1DB4 }, +{ 0x1DB5, 0x1DB5, 0x1DB5 }, +{ 0x1DB6, 0x1DB6, 0x1DB6 }, +{ 0x1DB7, 0x1DB7, 0x1DB7 }, +{ 0x1DB8, 0x1DB8, 0x1DB8 }, +{ 0x1DB9, 0x1DB9, 0x1DB9 }, +{ 0x1DBA, 0x1DBA, 0x1DBA }, +{ 0x1DBB, 0x1DBB, 0x1DBB }, +{ 0x1DBC, 0x1DBC, 0x1DBC }, +{ 0x1DBD, 0x1DBD, 0x1DBD }, +{ 0x1DBE, 0x1DBE, 0x1DBE }, +{ 0x1DBF, 0x1DBF, 0x1DBF }, +{ 0x1DC0, 0x1DC0, 0x1DC0 }, +{ 0x1DC1, 0x1DC1, 0x1DC1 }, +{ 0x1DC2, 0x1DC2, 0x1DC2 }, +{ 0x1DC3, 0x1DC3, 0x1DC3 }, +{ 0x1E00, 0x1E00, 0x1E01 }, +{ 0x1E01, 0x1E00, 0x1E01 }, +{ 0x1E02, 0x1E02, 0x1E03 }, +{ 0x1E03, 0x1E02, 0x1E03 }, +{ 0x1E04, 0x1E04, 0x1E05 }, +{ 0x1E05, 0x1E04, 0x1E05 }, +{ 0x1E06, 0x1E06, 0x1E07 }, +{ 0x1E07, 0x1E06, 0x1E07 }, +{ 0x1E08, 0x1E08, 0x1E09 }, +{ 0x1E09, 0x1E08, 0x1E09 }, +{ 0x1E0A, 0x1E0A, 0x1E0B }, +{ 0x1E0B, 0x1E0A, 0x1E0B }, +{ 0x1E0C, 0x1E0C, 0x1E0D }, +{ 0x1E0D, 0x1E0C, 0x1E0D }, +{ 0x1E0E, 0x1E0E, 0x1E0F }, +{ 0x1E0F, 0x1E0E, 0x1E0F }, +{ 0x1E10, 0x1E10, 0x1E11 }, +{ 0x1E11, 0x1E10, 0x1E11 }, +{ 0x1E12, 0x1E12, 0x1E13 }, +{ 0x1E13, 0x1E12, 0x1E13 }, +{ 0x1E14, 0x1E14, 0x1E15 }, +{ 0x1E15, 0x1E14, 0x1E15 }, +{ 0x1E16, 0x1E16, 0x1E17 }, +{ 0x1E17, 0x1E16, 0x1E17 }, +{ 0x1E18, 0x1E18, 0x1E19 }, +{ 0x1E19, 0x1E18, 0x1E19 }, +{ 0x1E1A, 0x1E1A, 0x1E1B }, +{ 0x1E1B, 0x1E1A, 0x1E1B }, +{ 0x1E1C, 0x1E1C, 0x1E1D }, +{ 0x1E1D, 0x1E1C, 0x1E1D }, +{ 0x1E1E, 0x1E1E, 0x1E1F }, +{ 0x1E1F, 0x1E1E, 0x1E1F }, +{ 0x1E20, 0x1E20, 0x1E21 }, +{ 0x1E21, 0x1E20, 0x1E21 }, +{ 0x1E22, 0x1E22, 0x1E23 }, +{ 0x1E23, 0x1E22, 0x1E23 }, +{ 0x1E24, 0x1E24, 0x1E25 }, +{ 0x1E25, 0x1E24, 0x1E25 }, +{ 0x1E26, 0x1E26, 0x1E27 }, +{ 0x1E27, 0x1E26, 0x1E27 }, +{ 0x1E28, 0x1E28, 0x1E29 }, +{ 0x1E29, 0x1E28, 0x1E29 }, +{ 0x1E2A, 0x1E2A, 0x1E2B }, +{ 0x1E2B, 0x1E2A, 0x1E2B }, +{ 0x1E2C, 0x1E2C, 0x1E2D }, +{ 0x1E2D, 0x1E2C, 0x1E2D }, +{ 0x1E2E, 0x1E2E, 0x1E2F }, +{ 0x1E2F, 0x1E2E, 0x1E2F }, +{ 0x1E30, 0x1E30, 0x1E31 }, +{ 0x1E31, 0x1E30, 0x1E31 }, +{ 0x1E32, 0x1E32, 0x1E33 }, +{ 0x1E33, 0x1E32, 0x1E33 }, +{ 0x1E34, 0x1E34, 0x1E35 }, +{ 0x1E35, 0x1E34, 0x1E35 }, +{ 0x1E36, 0x1E36, 0x1E37 }, +{ 0x1E37, 0x1E36, 0x1E37 }, +{ 0x1E38, 0x1E38, 0x1E39 }, +{ 0x1E39, 0x1E38, 0x1E39 }, +{ 0x1E3A, 0x1E3A, 0x1E3B }, +{ 0x1E3B, 0x1E3A, 0x1E3B }, +{ 0x1E3C, 0x1E3C, 0x1E3D }, +{ 0x1E3D, 0x1E3C, 0x1E3D }, +{ 0x1E3E, 0x1E3E, 0x1E3F }, +{ 0x1E3F, 0x1E3E, 0x1E3F }, +{ 0x1E40, 0x1E40, 0x1E41 }, +{ 0x1E41, 0x1E40, 0x1E41 }, +{ 0x1E42, 0x1E42, 0x1E43 }, +{ 0x1E43, 0x1E42, 0x1E43 }, +{ 0x1E44, 0x1E44, 0x1E45 }, +{ 0x1E45, 0x1E44, 0x1E45 }, +{ 0x1E46, 0x1E46, 0x1E47 }, +{ 0x1E47, 0x1E46, 0x1E47 }, +{ 0x1E48, 0x1E48, 0x1E49 }, +{ 0x1E49, 0x1E48, 0x1E49 }, +{ 0x1E4A, 0x1E4A, 0x1E4B }, +{ 0x1E4B, 0x1E4A, 0x1E4B }, +{ 0x1E4C, 0x1E4C, 0x1E4D }, +{ 0x1E4D, 0x1E4C, 0x1E4D }, +{ 0x1E4E, 0x1E4E, 0x1E4F }, +{ 0x1E4F, 0x1E4E, 0x1E4F }, +{ 0x1E50, 0x1E50, 0x1E51 }, +{ 0x1E51, 0x1E50, 0x1E51 }, +{ 0x1E52, 0x1E52, 0x1E53 }, +{ 0x1E53, 0x1E52, 0x1E53 }, +{ 0x1E54, 0x1E54, 0x1E55 }, +{ 0x1E55, 0x1E54, 0x1E55 }, +{ 0x1E56, 0x1E56, 0x1E57 }, +{ 0x1E57, 0x1E56, 0x1E57 }, +{ 0x1E58, 0x1E58, 0x1E59 }, +{ 0x1E59, 0x1E58, 0x1E59 }, +{ 0x1E5A, 0x1E5A, 0x1E5B }, +{ 0x1E5B, 0x1E5A, 0x1E5B }, +{ 0x1E5C, 0x1E5C, 0x1E5D }, +{ 0x1E5D, 0x1E5C, 0x1E5D }, +{ 0x1E5E, 0x1E5E, 0x1E5F }, +{ 0x1E5F, 0x1E5E, 0x1E5F }, +{ 0x1E60, 0x1E60, 0x1E61 }, +{ 0x1E61, 0x1E60, 0x1E61 }, +{ 0x1E62, 0x1E62, 0x1E63 }, +{ 0x1E63, 0x1E62, 0x1E63 }, +{ 0x1E64, 0x1E64, 0x1E65 }, +{ 0x1E65, 0x1E64, 0x1E65 }, +{ 0x1E66, 0x1E66, 0x1E67 }, +{ 0x1E67, 0x1E66, 0x1E67 }, +{ 0x1E68, 0x1E68, 0x1E69 }, +{ 0x1E69, 0x1E68, 0x1E69 }, +{ 0x1E6A, 0x1E6A, 0x1E6B }, +{ 0x1E6B, 0x1E6A, 0x1E6B }, +{ 0x1E6C, 0x1E6C, 0x1E6D }, +{ 0x1E6D, 0x1E6C, 0x1E6D }, +{ 0x1E6E, 0x1E6E, 0x1E6F }, +{ 0x1E6F, 0x1E6E, 0x1E6F }, +{ 0x1E70, 0x1E70, 0x1E71 }, +{ 0x1E71, 0x1E70, 0x1E71 }, +{ 0x1E72, 0x1E72, 0x1E73 }, +{ 0x1E73, 0x1E72, 0x1E73 }, +{ 0x1E74, 0x1E74, 0x1E75 }, +{ 0x1E75, 0x1E74, 0x1E75 }, +{ 0x1E76, 0x1E76, 0x1E77 }, +{ 0x1E77, 0x1E76, 0x1E77 }, +{ 0x1E78, 0x1E78, 0x1E79 }, +{ 0x1E79, 0x1E78, 0x1E79 }, +{ 0x1E7A, 0x1E7A, 0x1E7B }, +{ 0x1E7B, 0x1E7A, 0x1E7B }, +{ 0x1E7C, 0x1E7C, 0x1E7D }, +{ 0x1E7D, 0x1E7C, 0x1E7D }, +{ 0x1E7E, 0x1E7E, 0x1E7F }, +{ 0x1E7F, 0x1E7E, 0x1E7F }, +{ 0x1E80, 0x1E80, 0x1E81 }, +{ 0x1E81, 0x1E80, 0x1E81 }, +{ 0x1E82, 0x1E82, 0x1E83 }, +{ 0x1E83, 0x1E82, 0x1E83 }, +{ 0x1E84, 0x1E84, 0x1E85 }, +{ 0x1E85, 0x1E84, 0x1E85 }, +{ 0x1E86, 0x1E86, 0x1E87 }, +{ 0x1E87, 0x1E86, 0x1E87 }, +{ 0x1E88, 0x1E88, 0x1E89 }, +{ 0x1E89, 0x1E88, 0x1E89 }, +{ 0x1E8A, 0x1E8A, 0x1E8B }, +{ 0x1E8B, 0x1E8A, 0x1E8B }, +{ 0x1E8C, 0x1E8C, 0x1E8D }, +{ 0x1E8D, 0x1E8C, 0x1E8D }, +{ 0x1E8E, 0x1E8E, 0x1E8F }, +{ 0x1E8F, 0x1E8E, 0x1E8F }, +{ 0x1E90, 0x1E90, 0x1E91 }, +{ 0x1E91, 0x1E90, 0x1E91 }, +{ 0x1E92, 0x1E92, 0x1E93 }, +{ 0x1E93, 0x1E92, 0x1E93 }, +{ 0x1E94, 0x1E94, 0x1E95 }, +{ 0x1E95, 0x1E94, 0x1E95 }, +{ 0x1E96, 0x1E96, 0x1E96 }, +{ 0x1E97, 0x1E97, 0x1E97 }, +{ 0x1E98, 0x1E98, 0x1E98 }, +{ 0x1E99, 0x1E99, 0x1E99 }, +{ 0x1E9A, 0x1E9A, 0x1E9A }, +{ 0x1E9B, 0x1E60, 0x1E9B }, +{ 0x1EA0, 0x1EA0, 0x1EA1 }, +{ 0x1EA1, 0x1EA0, 0x1EA1 }, +{ 0x1EA2, 0x1EA2, 0x1EA3 }, +{ 0x1EA3, 0x1EA2, 0x1EA3 }, +{ 0x1EA4, 0x1EA4, 0x1EA5 }, +{ 0x1EA5, 0x1EA4, 0x1EA5 }, +{ 0x1EA6, 0x1EA6, 0x1EA7 }, +{ 0x1EA7, 0x1EA6, 0x1EA7 }, +{ 0x1EA8, 0x1EA8, 0x1EA9 }, +{ 0x1EA9, 0x1EA8, 0x1EA9 }, +{ 0x1EAA, 0x1EAA, 0x1EAB }, +{ 0x1EAB, 0x1EAA, 0x1EAB }, +{ 0x1EAC, 0x1EAC, 0x1EAD }, +{ 0x1EAD, 0x1EAC, 0x1EAD }, +{ 0x1EAE, 0x1EAE, 0x1EAF }, +{ 0x1EAF, 0x1EAE, 0x1EAF }, +{ 0x1EB0, 0x1EB0, 0x1EB1 }, +{ 0x1EB1, 0x1EB0, 0x1EB1 }, +{ 0x1EB2, 0x1EB2, 0x1EB3 }, +{ 0x1EB3, 0x1EB2, 0x1EB3 }, +{ 0x1EB4, 0x1EB4, 0x1EB5 }, +{ 0x1EB5, 0x1EB4, 0x1EB5 }, +{ 0x1EB6, 0x1EB6, 0x1EB7 }, +{ 0x1EB7, 0x1EB6, 0x1EB7 }, +{ 0x1EB8, 0x1EB8, 0x1EB9 }, +{ 0x1EB9, 0x1EB8, 0x1EB9 }, +{ 0x1EBA, 0x1EBA, 0x1EBB }, +{ 0x1EBB, 0x1EBA, 0x1EBB }, +{ 0x1EBC, 0x1EBC, 0x1EBD }, +{ 0x1EBD, 0x1EBC, 0x1EBD }, +{ 0x1EBE, 0x1EBE, 0x1EBF }, +{ 0x1EBF, 0x1EBE, 0x1EBF }, +{ 0x1EC0, 0x1EC0, 0x1EC1 }, +{ 0x1EC1, 0x1EC0, 0x1EC1 }, +{ 0x1EC2, 0x1EC2, 0x1EC3 }, +{ 0x1EC3, 0x1EC2, 0x1EC3 }, +{ 0x1EC4, 0x1EC4, 0x1EC5 }, +{ 0x1EC5, 0x1EC4, 0x1EC5 }, +{ 0x1EC6, 0x1EC6, 0x1EC7 }, +{ 0x1EC7, 0x1EC6, 0x1EC7 }, +{ 0x1EC8, 0x1EC8, 0x1EC9 }, +{ 0x1EC9, 0x1EC8, 0x1EC9 }, +{ 0x1ECA, 0x1ECA, 0x1ECB }, +{ 0x1ECB, 0x1ECA, 0x1ECB }, +{ 0x1ECC, 0x1ECC, 0x1ECD }, +{ 0x1ECD, 0x1ECC, 0x1ECD }, +{ 0x1ECE, 0x1ECE, 0x1ECF }, +{ 0x1ECF, 0x1ECE, 0x1ECF }, +{ 0x1ED0, 0x1ED0, 0x1ED1 }, +{ 0x1ED1, 0x1ED0, 0x1ED1 }, +{ 0x1ED2, 0x1ED2, 0x1ED3 }, +{ 0x1ED3, 0x1ED2, 0x1ED3 }, +{ 0x1ED4, 0x1ED4, 0x1ED5 }, +{ 0x1ED5, 0x1ED4, 0x1ED5 }, +{ 0x1ED6, 0x1ED6, 0x1ED7 }, +{ 0x1ED7, 0x1ED6, 0x1ED7 }, +{ 0x1ED8, 0x1ED8, 0x1ED9 }, +{ 0x1ED9, 0x1ED8, 0x1ED9 }, +{ 0x1EDA, 0x1EDA, 0x1EDB }, +{ 0x1EDB, 0x1EDA, 0x1EDB }, +{ 0x1EDC, 0x1EDC, 0x1EDD }, +{ 0x1EDD, 0x1EDC, 0x1EDD }, +{ 0x1EDE, 0x1EDE, 0x1EDF }, +{ 0x1EDF, 0x1EDE, 0x1EDF }, +{ 0x1EE0, 0x1EE0, 0x1EE1 }, +{ 0x1EE1, 0x1EE0, 0x1EE1 }, +{ 0x1EE2, 0x1EE2, 0x1EE3 }, +{ 0x1EE3, 0x1EE2, 0x1EE3 }, +{ 0x1EE4, 0x1EE4, 0x1EE5 }, +{ 0x1EE5, 0x1EE4, 0x1EE5 }, +{ 0x1EE6, 0x1EE6, 0x1EE7 }, +{ 0x1EE7, 0x1EE6, 0x1EE7 }, +{ 0x1EE8, 0x1EE8, 0x1EE9 }, +{ 0x1EE9, 0x1EE8, 0x1EE9 }, +{ 0x1EEA, 0x1EEA, 0x1EEB }, +{ 0x1EEB, 0x1EEA, 0x1EEB }, +{ 0x1EEC, 0x1EEC, 0x1EED }, +{ 0x1EED, 0x1EEC, 0x1EED }, +{ 0x1EEE, 0x1EEE, 0x1EEF }, +{ 0x1EEF, 0x1EEE, 0x1EEF }, +{ 0x1EF0, 0x1EF0, 0x1EF1 }, +{ 0x1EF1, 0x1EF0, 0x1EF1 }, +{ 0x1EF2, 0x1EF2, 0x1EF3 }, +{ 0x1EF3, 0x1EF2, 0x1EF3 }, +{ 0x1EF4, 0x1EF4, 0x1EF5 }, +{ 0x1EF5, 0x1EF4, 0x1EF5 }, +{ 0x1EF6, 0x1EF6, 0x1EF7 }, +{ 0x1EF7, 0x1EF6, 0x1EF7 }, +{ 0x1EF8, 0x1EF8, 0x1EF9 }, +{ 0x1EF9, 0x1EF8, 0x1EF9 }, +{ 0x1F00, 0x1F08, 0x1F00 }, +{ 0x1F01, 0x1F09, 0x1F01 }, +{ 0x1F02, 0x1F0A, 0x1F02 }, +{ 0x1F03, 0x1F0B, 0x1F03 }, +{ 0x1F04, 0x1F0C, 0x1F04 }, +{ 0x1F05, 0x1F0D, 0x1F05 }, +{ 0x1F06, 0x1F0E, 0x1F06 }, +{ 0x1F07, 0x1F0F, 0x1F07 }, +{ 0x1F08, 0x1F08, 0x1F00 }, +{ 0x1F09, 0x1F09, 0x1F01 }, +{ 0x1F0A, 0x1F0A, 0x1F02 }, +{ 0x1F0B, 0x1F0B, 0x1F03 }, +{ 0x1F0C, 0x1F0C, 0x1F04 }, +{ 0x1F0D, 0x1F0D, 0x1F05 }, +{ 0x1F0E, 0x1F0E, 0x1F06 }, +{ 0x1F0F, 0x1F0F, 0x1F07 }, +{ 0x1F10, 0x1F18, 0x1F10 }, +{ 0x1F11, 0x1F19, 0x1F11 }, +{ 0x1F12, 0x1F1A, 0x1F12 }, +{ 0x1F13, 0x1F1B, 0x1F13 }, +{ 0x1F14, 0x1F1C, 0x1F14 }, +{ 0x1F15, 0x1F1D, 0x1F15 }, +{ 0x1F18, 0x1F18, 0x1F10 }, +{ 0x1F19, 0x1F19, 0x1F11 }, +{ 0x1F1A, 0x1F1A, 0x1F12 }, +{ 0x1F1B, 0x1F1B, 0x1F13 }, +{ 0x1F1C, 0x1F1C, 0x1F14 }, +{ 0x1F1D, 0x1F1D, 0x1F15 }, +{ 0x1F20, 0x1F28, 0x1F20 }, +{ 0x1F21, 0x1F29, 0x1F21 }, +{ 0x1F22, 0x1F2A, 0x1F22 }, +{ 0x1F23, 0x1F2B, 0x1F23 }, +{ 0x1F24, 0x1F2C, 0x1F24 }, +{ 0x1F25, 0x1F2D, 0x1F25 }, +{ 0x1F26, 0x1F2E, 0x1F26 }, +{ 0x1F27, 0x1F2F, 0x1F27 }, +{ 0x1F28, 0x1F28, 0x1F20 }, +{ 0x1F29, 0x1F29, 0x1F21 }, +{ 0x1F2A, 0x1F2A, 0x1F22 }, +{ 0x1F2B, 0x1F2B, 0x1F23 }, +{ 0x1F2C, 0x1F2C, 0x1F24 }, +{ 0x1F2D, 0x1F2D, 0x1F25 }, +{ 0x1F2E, 0x1F2E, 0x1F26 }, +{ 0x1F2F, 0x1F2F, 0x1F27 }, +{ 0x1F30, 0x1F38, 0x1F30 }, +{ 0x1F31, 0x1F39, 0x1F31 }, +{ 0x1F32, 0x1F3A, 0x1F32 }, +{ 0x1F33, 0x1F3B, 0x1F33 }, +{ 0x1F34, 0x1F3C, 0x1F34 }, +{ 0x1F35, 0x1F3D, 0x1F35 }, +{ 0x1F36, 0x1F3E, 0x1F36 }, +{ 0x1F37, 0x1F3F, 0x1F37 }, +{ 0x1F38, 0x1F38, 0x1F30 }, +{ 0x1F39, 0x1F39, 0x1F31 }, +{ 0x1F3A, 0x1F3A, 0x1F32 }, +{ 0x1F3B, 0x1F3B, 0x1F33 }, +{ 0x1F3C, 0x1F3C, 0x1F34 }, +{ 0x1F3D, 0x1F3D, 0x1F35 }, +{ 0x1F3E, 0x1F3E, 0x1F36 }, +{ 0x1F3F, 0x1F3F, 0x1F37 }, +{ 0x1F40, 0x1F48, 0x1F40 }, +{ 0x1F41, 0x1F49, 0x1F41 }, +{ 0x1F42, 0x1F4A, 0x1F42 }, +{ 0x1F43, 0x1F4B, 0x1F43 }, +{ 0x1F44, 0x1F4C, 0x1F44 }, +{ 0x1F45, 0x1F4D, 0x1F45 }, +{ 0x1F48, 0x1F48, 0x1F40 }, +{ 0x1F49, 0x1F49, 0x1F41 }, +{ 0x1F4A, 0x1F4A, 0x1F42 }, +{ 0x1F4B, 0x1F4B, 0x1F43 }, +{ 0x1F4C, 0x1F4C, 0x1F44 }, +{ 0x1F4D, 0x1F4D, 0x1F45 }, +{ 0x1F50, 0x1F50, 0x1F50 }, +{ 0x1F51, 0x1F59, 0x1F51 }, +{ 0x1F52, 0x1F52, 0x1F52 }, +{ 0x1F53, 0x1F5B, 0x1F53 }, +{ 0x1F54, 0x1F54, 0x1F54 }, +{ 0x1F55, 0x1F5D, 0x1F55 }, +{ 0x1F56, 0x1F56, 0x1F56 }, +{ 0x1F57, 0x1F5F, 0x1F57 }, +{ 0x1F59, 0x1F59, 0x1F51 }, +{ 0x1F5B, 0x1F5B, 0x1F53 }, +{ 0x1F5D, 0x1F5D, 0x1F55 }, +{ 0x1F5F, 0x1F5F, 0x1F57 }, +{ 0x1F60, 0x1F68, 0x1F60 }, +{ 0x1F61, 0x1F69, 0x1F61 }, +{ 0x1F62, 0x1F6A, 0x1F62 }, +{ 0x1F63, 0x1F6B, 0x1F63 }, +{ 0x1F64, 0x1F6C, 0x1F64 }, +{ 0x1F65, 0x1F6D, 0x1F65 }, +{ 0x1F66, 0x1F6E, 0x1F66 }, +{ 0x1F67, 0x1F6F, 0x1F67 }, +{ 0x1F68, 0x1F68, 0x1F60 }, +{ 0x1F69, 0x1F69, 0x1F61 }, +{ 0x1F6A, 0x1F6A, 0x1F62 }, +{ 0x1F6B, 0x1F6B, 0x1F63 }, +{ 0x1F6C, 0x1F6C, 0x1F64 }, +{ 0x1F6D, 0x1F6D, 0x1F65 }, +{ 0x1F6E, 0x1F6E, 0x1F66 }, +{ 0x1F6F, 0x1F6F, 0x1F67 }, +{ 0x1F70, 0x1FBA, 0x1F70 }, +{ 0x1F71, 0x1FBB, 0x1F71 }, +{ 0x1F72, 0x1FC8, 0x1F72 }, +{ 0x1F73, 0x1FC9, 0x1F73 }, +{ 0x1F74, 0x1FCA, 0x1F74 }, +{ 0x1F75, 0x1FCB, 0x1F75 }, +{ 0x1F76, 0x1FDA, 0x1F76 }, +{ 0x1F77, 0x1FDB, 0x1F77 }, +{ 0x1F78, 0x1FF8, 0x1F78 }, +{ 0x1F79, 0x1FF9, 0x1F79 }, +{ 0x1F7A, 0x1FEA, 0x1F7A }, +{ 0x1F7B, 0x1FEB, 0x1F7B }, +{ 0x1F7C, 0x1FFA, 0x1F7C }, +{ 0x1F7D, 0x1FFB, 0x1F7D }, +{ 0x1F80, 0x1F88, 0x1F80 }, +{ 0x1F81, 0x1F89, 0x1F81 }, +{ 0x1F82, 0x1F8A, 0x1F82 }, +{ 0x1F83, 0x1F8B, 0x1F83 }, +{ 0x1F84, 0x1F8C, 0x1F84 }, +{ 0x1F85, 0x1F8D, 0x1F85 }, +{ 0x1F86, 0x1F8E, 0x1F86 }, +{ 0x1F87, 0x1F8F, 0x1F87 }, +{ 0x1F88, 0x1F88, 0x1F80 }, +{ 0x1F89, 0x1F89, 0x1F81 }, +{ 0x1F8A, 0x1F8A, 0x1F82 }, +{ 0x1F8B, 0x1F8B, 0x1F83 }, +{ 0x1F8C, 0x1F8C, 0x1F84 }, +{ 0x1F8D, 0x1F8D, 0x1F85 }, +{ 0x1F8E, 0x1F8E, 0x1F86 }, +{ 0x1F8F, 0x1F8F, 0x1F87 }, +{ 0x1F90, 0x1F98, 0x1F90 }, +{ 0x1F91, 0x1F99, 0x1F91 }, +{ 0x1F92, 0x1F9A, 0x1F92 }, +{ 0x1F93, 0x1F9B, 0x1F93 }, +{ 0x1F94, 0x1F9C, 0x1F94 }, +{ 0x1F95, 0x1F9D, 0x1F95 }, +{ 0x1F96, 0x1F9E, 0x1F96 }, +{ 0x1F97, 0x1F9F, 0x1F97 }, +{ 0x1F98, 0x1F98, 0x1F90 }, +{ 0x1F99, 0x1F99, 0x1F91 }, +{ 0x1F9A, 0x1F9A, 0x1F92 }, +{ 0x1F9B, 0x1F9B, 0x1F93 }, +{ 0x1F9C, 0x1F9C, 0x1F94 }, +{ 0x1F9D, 0x1F9D, 0x1F95 }, +{ 0x1F9E, 0x1F9E, 0x1F96 }, +{ 0x1F9F, 0x1F9F, 0x1F97 }, +{ 0x1FA0, 0x1FA8, 0x1FA0 }, +{ 0x1FA1, 0x1FA9, 0x1FA1 }, +{ 0x1FA2, 0x1FAA, 0x1FA2 }, +{ 0x1FA3, 0x1FAB, 0x1FA3 }, +{ 0x1FA4, 0x1FAC, 0x1FA4 }, +{ 0x1FA5, 0x1FAD, 0x1FA5 }, +{ 0x1FA6, 0x1FAE, 0x1FA6 }, +{ 0x1FA7, 0x1FAF, 0x1FA7 }, +{ 0x1FA8, 0x1FA8, 0x1FA0 }, +{ 0x1FA9, 0x1FA9, 0x1FA1 }, +{ 0x1FAA, 0x1FAA, 0x1FA2 }, +{ 0x1FAB, 0x1FAB, 0x1FA3 }, +{ 0x1FAC, 0x1FAC, 0x1FA4 }, +{ 0x1FAD, 0x1FAD, 0x1FA5 }, +{ 0x1FAE, 0x1FAE, 0x1FA6 }, +{ 0x1FAF, 0x1FAF, 0x1FA7 }, +{ 0x1FB0, 0x1FB8, 0x1FB0 }, +{ 0x1FB1, 0x1FB9, 0x1FB1 }, +{ 0x1FB2, 0x1FB2, 0x1FB2 }, +{ 0x1FB3, 0x1FBC, 0x1FB3 }, +{ 0x1FB4, 0x1FB4, 0x1FB4 }, +{ 0x1FB6, 0x1FB6, 0x1FB6 }, +{ 0x1FB7, 0x1FB7, 0x1FB7 }, +{ 0x1FB8, 0x1FB8, 0x1FB0 }, +{ 0x1FB9, 0x1FB9, 0x1FB1 }, +{ 0x1FBA, 0x1FBA, 0x1F70 }, +{ 0x1FBB, 0x1FBB, 0x1F71 }, +{ 0x1FBC, 0x1FBC, 0x1FB3 }, +{ 0x1FBE, 0x0399, 0x1FBE }, +{ 0x1FC2, 0x1FC2, 0x1FC2 }, +{ 0x1FC3, 0x1FCC, 0x1FC3 }, +{ 0x1FC4, 0x1FC4, 0x1FC4 }, +{ 0x1FC6, 0x1FC6, 0x1FC6 }, +{ 0x1FC7, 0x1FC7, 0x1FC7 }, +{ 0x1FC8, 0x1FC8, 0x1F72 }, +{ 0x1FC9, 0x1FC9, 0x1F73 }, +{ 0x1FCA, 0x1FCA, 0x1F74 }, +{ 0x1FCB, 0x1FCB, 0x1F75 }, +{ 0x1FCC, 0x1FCC, 0x1FC3 }, +{ 0x1FD0, 0x1FD8, 0x1FD0 }, +{ 0x1FD1, 0x1FD9, 0x1FD1 }, +{ 0x1FD2, 0x1FD2, 0x1FD2 }, +{ 0x1FD3, 0x1FD3, 0x1FD3 }, +{ 0x1FD6, 0x1FD6, 0x1FD6 }, +{ 0x1FD7, 0x1FD7, 0x1FD7 }, +{ 0x1FD8, 0x1FD8, 0x1FD0 }, +{ 0x1FD9, 0x1FD9, 0x1FD1 }, +{ 0x1FDA, 0x1FDA, 0x1F76 }, +{ 0x1FDB, 0x1FDB, 0x1F77 }, +{ 0x1FE0, 0x1FE8, 0x1FE0 }, +{ 0x1FE1, 0x1FE9, 0x1FE1 }, +{ 0x1FE2, 0x1FE2, 0x1FE2 }, +{ 0x1FE3, 0x1FE3, 0x1FE3 }, +{ 0x1FE4, 0x1FE4, 0x1FE4 }, +{ 0x1FE5, 0x1FEC, 0x1FE5 }, +{ 0x1FE6, 0x1FE6, 0x1FE6 }, +{ 0x1FE7, 0x1FE7, 0x1FE7 }, +{ 0x1FE8, 0x1FE8, 0x1FE0 }, +{ 0x1FE9, 0x1FE9, 0x1FE1 }, +{ 0x1FEA, 0x1FEA, 0x1F7A }, +{ 0x1FEB, 0x1FEB, 0x1F7B }, +{ 0x1FEC, 0x1FEC, 0x1FE5 }, +{ 0x1FF2, 0x1FF2, 0x1FF2 }, +{ 0x1FF3, 0x1FFC, 0x1FF3 }, +{ 0x1FF4, 0x1FF4, 0x1FF4 }, +{ 0x1FF6, 0x1FF6, 0x1FF6 }, +{ 0x1FF7, 0x1FF7, 0x1FF7 }, +{ 0x1FF8, 0x1FF8, 0x1F78 }, +{ 0x1FF9, 0x1FF9, 0x1F79 }, +{ 0x1FFA, 0x1FFA, 0x1F7C }, +{ 0x1FFB, 0x1FFB, 0x1F7D }, +{ 0x1FFC, 0x1FFC, 0x1FF3 }, +{ 0x2071, 0x2071, 0x2071 }, +{ 0x207F, 0x207F, 0x207F }, +{ 0x2090, 0x2090, 0x2090 }, +{ 0x2091, 0x2091, 0x2091 }, +{ 0x2092, 0x2092, 0x2092 }, +{ 0x2093, 0x2093, 0x2093 }, +{ 0x2094, 0x2094, 0x2094 }, +{ 0x20D0, 0x20D0, 0x20D0 }, +{ 0x20D1, 0x20D1, 0x20D1 }, +{ 0x20D2, 0x20D2, 0x20D2 }, +{ 0x20D3, 0x20D3, 0x20D3 }, +{ 0x20D4, 0x20D4, 0x20D4 }, +{ 0x20D5, 0x20D5, 0x20D5 }, +{ 0x20D6, 0x20D6, 0x20D6 }, +{ 0x20D7, 0x20D7, 0x20D7 }, +{ 0x20D8, 0x20D8, 0x20D8 }, +{ 0x20D9, 0x20D9, 0x20D9 }, +{ 0x20DA, 0x20DA, 0x20DA }, +{ 0x20DB, 0x20DB, 0x20DB }, +{ 0x20DC, 0x20DC, 0x20DC }, +{ 0x20E1, 0x20E1, 0x20E1 }, +{ 0x20E5, 0x20E5, 0x20E5 }, +{ 0x20E6, 0x20E6, 0x20E6 }, +{ 0x20E7, 0x20E7, 0x20E7 }, +{ 0x20E8, 0x20E8, 0x20E8 }, +{ 0x20E9, 0x20E9, 0x20E9 }, +{ 0x20EA, 0x20EA, 0x20EA }, +{ 0x20EB, 0x20EB, 0x20EB }, +{ 0x2102, 0x2102, 0x2102 }, +{ 0x2107, 0x2107, 0x2107 }, +{ 0x210A, 0x210A, 0x210A }, +{ 0x210B, 0x210B, 0x210B }, +{ 0x210C, 0x210C, 0x210C }, +{ 0x210D, 0x210D, 0x210D }, +{ 0x210E, 0x210E, 0x210E }, +{ 0x210F, 0x210F, 0x210F }, +{ 0x2110, 0x2110, 0x2110 }, +{ 0x2111, 0x2111, 0x2111 }, +{ 0x2112, 0x2112, 0x2112 }, +{ 0x2113, 0x2113, 0x2113 }, +{ 0x2115, 0x2115, 0x2115 }, +{ 0x2119, 0x2119, 0x2119 }, +{ 0x211A, 0x211A, 0x211A }, +{ 0x211B, 0x211B, 0x211B }, +{ 0x211C, 0x211C, 0x211C }, +{ 0x211D, 0x211D, 0x211D }, +{ 0x2124, 0x2124, 0x2124 }, +{ 0x2126, 0x2126, 0x03C9 }, +{ 0x2128, 0x2128, 0x2128 }, +{ 0x212A, 0x212A, 0x006B }, +{ 0x212B, 0x212B, 0x00E5 }, +{ 0x212C, 0x212C, 0x212C }, +{ 0x212D, 0x212D, 0x212D }, +{ 0x212F, 0x212F, 0x212F }, +{ 0x2130, 0x2130, 0x2130 }, +{ 0x2131, 0x2131, 0x2131 }, +{ 0x2133, 0x2133, 0x2133 }, +{ 0x2134, 0x2134, 0x2134 }, +{ 0x2135, 0x2135, 0x2135 }, +{ 0x2136, 0x2136, 0x2136 }, +{ 0x2137, 0x2137, 0x2137 }, +{ 0x2138, 0x2138, 0x2138 }, +{ 0x2139, 0x2139, 0x2139 }, +{ 0x213C, 0x213C, 0x213C }, +{ 0x213D, 0x213D, 0x213D }, +{ 0x213E, 0x213E, 0x213E }, +{ 0x213F, 0x213F, 0x213F }, +{ 0x2145, 0x2145, 0x2145 }, +{ 0x2146, 0x2146, 0x2146 }, +{ 0x2147, 0x2147, 0x2147 }, +{ 0x2148, 0x2148, 0x2148 }, +{ 0x2149, 0x2149, 0x2149 }, +{ 0x2C00, 0x2C00, 0x2C30 }, +{ 0x2C01, 0x2C01, 0x2C31 }, +{ 0x2C02, 0x2C02, 0x2C32 }, +{ 0x2C03, 0x2C03, 0x2C33 }, +{ 0x2C04, 0x2C04, 0x2C34 }, +{ 0x2C05, 0x2C05, 0x2C35 }, +{ 0x2C06, 0x2C06, 0x2C36 }, +{ 0x2C07, 0x2C07, 0x2C37 }, +{ 0x2C08, 0x2C08, 0x2C38 }, +{ 0x2C09, 0x2C09, 0x2C39 }, +{ 0x2C0A, 0x2C0A, 0x2C3A }, +{ 0x2C0B, 0x2C0B, 0x2C3B }, +{ 0x2C0C, 0x2C0C, 0x2C3C }, +{ 0x2C0D, 0x2C0D, 0x2C3D }, +{ 0x2C0E, 0x2C0E, 0x2C3E }, +{ 0x2C0F, 0x2C0F, 0x2C3F }, +{ 0x2C10, 0x2C10, 0x2C40 }, +{ 0x2C11, 0x2C11, 0x2C41 }, +{ 0x2C12, 0x2C12, 0x2C42 }, +{ 0x2C13, 0x2C13, 0x2C43 }, +{ 0x2C14, 0x2C14, 0x2C44 }, +{ 0x2C15, 0x2C15, 0x2C45 }, +{ 0x2C16, 0x2C16, 0x2C46 }, +{ 0x2C17, 0x2C17, 0x2C47 }, +{ 0x2C18, 0x2C18, 0x2C48 }, +{ 0x2C19, 0x2C19, 0x2C49 }, +{ 0x2C1A, 0x2C1A, 0x2C4A }, +{ 0x2C1B, 0x2C1B, 0x2C4B }, +{ 0x2C1C, 0x2C1C, 0x2C4C }, +{ 0x2C1D, 0x2C1D, 0x2C4D }, +{ 0x2C1E, 0x2C1E, 0x2C4E }, +{ 0x2C1F, 0x2C1F, 0x2C4F }, +{ 0x2C20, 0x2C20, 0x2C50 }, +{ 0x2C21, 0x2C21, 0x2C51 }, +{ 0x2C22, 0x2C22, 0x2C52 }, +{ 0x2C23, 0x2C23, 0x2C53 }, +{ 0x2C24, 0x2C24, 0x2C54 }, +{ 0x2C25, 0x2C25, 0x2C55 }, +{ 0x2C26, 0x2C26, 0x2C56 }, +{ 0x2C27, 0x2C27, 0x2C57 }, +{ 0x2C28, 0x2C28, 0x2C58 }, +{ 0x2C29, 0x2C29, 0x2C59 }, +{ 0x2C2A, 0x2C2A, 0x2C5A }, +{ 0x2C2B, 0x2C2B, 0x2C5B }, +{ 0x2C2C, 0x2C2C, 0x2C5C }, +{ 0x2C2D, 0x2C2D, 0x2C5D }, +{ 0x2C2E, 0x2C2E, 0x2C5E }, +{ 0x2C30, 0x2C00, 0x2C30 }, +{ 0x2C31, 0x2C01, 0x2C31 }, +{ 0x2C32, 0x2C02, 0x2C32 }, +{ 0x2C33, 0x2C03, 0x2C33 }, +{ 0x2C34, 0x2C04, 0x2C34 }, +{ 0x2C35, 0x2C05, 0x2C35 }, +{ 0x2C36, 0x2C06, 0x2C36 }, +{ 0x2C37, 0x2C07, 0x2C37 }, +{ 0x2C38, 0x2C08, 0x2C38 }, +{ 0x2C39, 0x2C09, 0x2C39 }, +{ 0x2C3A, 0x2C0A, 0x2C3A }, +{ 0x2C3B, 0x2C0B, 0x2C3B }, +{ 0x2C3C, 0x2C0C, 0x2C3C }, +{ 0x2C3D, 0x2C0D, 0x2C3D }, +{ 0x2C3E, 0x2C0E, 0x2C3E }, +{ 0x2C3F, 0x2C0F, 0x2C3F }, +{ 0x2C40, 0x2C10, 0x2C40 }, +{ 0x2C41, 0x2C11, 0x2C41 }, +{ 0x2C42, 0x2C12, 0x2C42 }, +{ 0x2C43, 0x2C13, 0x2C43 }, +{ 0x2C44, 0x2C14, 0x2C44 }, +{ 0x2C45, 0x2C15, 0x2C45 }, +{ 0x2C46, 0x2C16, 0x2C46 }, +{ 0x2C47, 0x2C17, 0x2C47 }, +{ 0x2C48, 0x2C18, 0x2C48 }, +{ 0x2C49, 0x2C19, 0x2C49 }, +{ 0x2C4A, 0x2C1A, 0x2C4A }, +{ 0x2C4B, 0x2C1B, 0x2C4B }, +{ 0x2C4C, 0x2C1C, 0x2C4C }, +{ 0x2C4D, 0x2C1D, 0x2C4D }, +{ 0x2C4E, 0x2C1E, 0x2C4E }, +{ 0x2C4F, 0x2C1F, 0x2C4F }, +{ 0x2C50, 0x2C20, 0x2C50 }, +{ 0x2C51, 0x2C21, 0x2C51 }, +{ 0x2C52, 0x2C22, 0x2C52 }, +{ 0x2C53, 0x2C23, 0x2C53 }, +{ 0x2C54, 0x2C24, 0x2C54 }, +{ 0x2C55, 0x2C25, 0x2C55 }, +{ 0x2C56, 0x2C26, 0x2C56 }, +{ 0x2C57, 0x2C27, 0x2C57 }, +{ 0x2C58, 0x2C28, 0x2C58 }, +{ 0x2C59, 0x2C29, 0x2C59 }, +{ 0x2C5A, 0x2C2A, 0x2C5A }, +{ 0x2C5B, 0x2C2B, 0x2C5B }, +{ 0x2C5C, 0x2C2C, 0x2C5C }, +{ 0x2C5D, 0x2C2D, 0x2C5D }, +{ 0x2C5E, 0x2C2E, 0x2C5E }, +{ 0x2C80, 0x2C80, 0x2C81 }, +{ 0x2C81, 0x2C80, 0x2C81 }, +{ 0x2C82, 0x2C82, 0x2C83 }, +{ 0x2C83, 0x2C82, 0x2C83 }, +{ 0x2C84, 0x2C84, 0x2C85 }, +{ 0x2C85, 0x2C84, 0x2C85 }, +{ 0x2C86, 0x2C86, 0x2C87 }, +{ 0x2C87, 0x2C86, 0x2C87 }, +{ 0x2C88, 0x2C88, 0x2C89 }, +{ 0x2C89, 0x2C88, 0x2C89 }, +{ 0x2C8A, 0x2C8A, 0x2C8B }, +{ 0x2C8B, 0x2C8A, 0x2C8B }, +{ 0x2C8C, 0x2C8C, 0x2C8D }, +{ 0x2C8D, 0x2C8C, 0x2C8D }, +{ 0x2C8E, 0x2C8E, 0x2C8F }, +{ 0x2C8F, 0x2C8E, 0x2C8F }, +{ 0x2C90, 0x2C90, 0x2C91 }, +{ 0x2C91, 0x2C90, 0x2C91 }, +{ 0x2C92, 0x2C92, 0x2C93 }, +{ 0x2C93, 0x2C92, 0x2C93 }, +{ 0x2C94, 0x2C94, 0x2C95 }, +{ 0x2C95, 0x2C94, 0x2C95 }, +{ 0x2C96, 0x2C96, 0x2C97 }, +{ 0x2C97, 0x2C96, 0x2C97 }, +{ 0x2C98, 0x2C98, 0x2C99 }, +{ 0x2C99, 0x2C98, 0x2C99 }, +{ 0x2C9A, 0x2C9A, 0x2C9B }, +{ 0x2C9B, 0x2C9A, 0x2C9B }, +{ 0x2C9C, 0x2C9C, 0x2C9D }, +{ 0x2C9D, 0x2C9C, 0x2C9D }, +{ 0x2C9E, 0x2C9E, 0x2C9F }, +{ 0x2C9F, 0x2C9E, 0x2C9F }, +{ 0x2CA0, 0x2CA0, 0x2CA1 }, +{ 0x2CA1, 0x2CA0, 0x2CA1 }, +{ 0x2CA2, 0x2CA2, 0x2CA3 }, +{ 0x2CA3, 0x2CA2, 0x2CA3 }, +{ 0x2CA4, 0x2CA4, 0x2CA5 }, +{ 0x2CA5, 0x2CA4, 0x2CA5 }, +{ 0x2CA6, 0x2CA6, 0x2CA7 }, +{ 0x2CA7, 0x2CA6, 0x2CA7 }, +{ 0x2CA8, 0x2CA8, 0x2CA9 }, +{ 0x2CA9, 0x2CA8, 0x2CA9 }, +{ 0x2CAA, 0x2CAA, 0x2CAB }, +{ 0x2CAB, 0x2CAA, 0x2CAB }, +{ 0x2CAC, 0x2CAC, 0x2CAD }, +{ 0x2CAD, 0x2CAC, 0x2CAD }, +{ 0x2CAE, 0x2CAE, 0x2CAF }, +{ 0x2CAF, 0x2CAE, 0x2CAF }, +{ 0x2CB0, 0x2CB0, 0x2CB1 }, +{ 0x2CB1, 0x2CB0, 0x2CB1 }, +{ 0x2CB2, 0x2CB2, 0x2CB3 }, +{ 0x2CB3, 0x2CB2, 0x2CB3 }, +{ 0x2CB4, 0x2CB4, 0x2CB5 }, +{ 0x2CB5, 0x2CB4, 0x2CB5 }, +{ 0x2CB6, 0x2CB6, 0x2CB7 }, +{ 0x2CB7, 0x2CB6, 0x2CB7 }, +{ 0x2CB8, 0x2CB8, 0x2CB9 }, +{ 0x2CB9, 0x2CB8, 0x2CB9 }, +{ 0x2CBA, 0x2CBA, 0x2CBB }, +{ 0x2CBB, 0x2CBA, 0x2CBB }, +{ 0x2CBC, 0x2CBC, 0x2CBD }, +{ 0x2CBD, 0x2CBC, 0x2CBD }, +{ 0x2CBE, 0x2CBE, 0x2CBF }, +{ 0x2CBF, 0x2CBE, 0x2CBF }, +{ 0x2CC0, 0x2CC0, 0x2CC1 }, +{ 0x2CC1, 0x2CC0, 0x2CC1 }, +{ 0x2CC2, 0x2CC2, 0x2CC3 }, +{ 0x2CC3, 0x2CC2, 0x2CC3 }, +{ 0x2CC4, 0x2CC4, 0x2CC5 }, +{ 0x2CC5, 0x2CC4, 0x2CC5 }, +{ 0x2CC6, 0x2CC6, 0x2CC7 }, +{ 0x2CC7, 0x2CC6, 0x2CC7 }, +{ 0x2CC8, 0x2CC8, 0x2CC9 }, +{ 0x2CC9, 0x2CC8, 0x2CC9 }, +{ 0x2CCA, 0x2CCA, 0x2CCB }, +{ 0x2CCB, 0x2CCA, 0x2CCB }, +{ 0x2CCC, 0x2CCC, 0x2CCD }, +{ 0x2CCD, 0x2CCC, 0x2CCD }, +{ 0x2CCE, 0x2CCE, 0x2CCF }, +{ 0x2CCF, 0x2CCE, 0x2CCF }, +{ 0x2CD0, 0x2CD0, 0x2CD1 }, +{ 0x2CD1, 0x2CD0, 0x2CD1 }, +{ 0x2CD2, 0x2CD2, 0x2CD3 }, +{ 0x2CD3, 0x2CD2, 0x2CD3 }, +{ 0x2CD4, 0x2CD4, 0x2CD5 }, +{ 0x2CD5, 0x2CD4, 0x2CD5 }, +{ 0x2CD6, 0x2CD6, 0x2CD7 }, +{ 0x2CD7, 0x2CD6, 0x2CD7 }, +{ 0x2CD8, 0x2CD8, 0x2CD9 }, +{ 0x2CD9, 0x2CD8, 0x2CD9 }, +{ 0x2CDA, 0x2CDA, 0x2CDB }, +{ 0x2CDB, 0x2CDA, 0x2CDB }, +{ 0x2CDC, 0x2CDC, 0x2CDD }, +{ 0x2CDD, 0x2CDC, 0x2CDD }, +{ 0x2CDE, 0x2CDE, 0x2CDF }, +{ 0x2CDF, 0x2CDE, 0x2CDF }, +{ 0x2CE0, 0x2CE0, 0x2CE1 }, +{ 0x2CE1, 0x2CE0, 0x2CE1 }, +{ 0x2CE2, 0x2CE2, 0x2CE3 }, +{ 0x2CE3, 0x2CE2, 0x2CE3 }, +{ 0x2CE4, 0x2CE4, 0x2CE4 }, +{ 0x2D00, 0x10A0, 0x2D00 }, +{ 0x2D01, 0x10A1, 0x2D01 }, +{ 0x2D02, 0x10A2, 0x2D02 }, +{ 0x2D03, 0x10A3, 0x2D03 }, +{ 0x2D04, 0x10A4, 0x2D04 }, +{ 0x2D05, 0x10A5, 0x2D05 }, +{ 0x2D06, 0x10A6, 0x2D06 }, +{ 0x2D07, 0x10A7, 0x2D07 }, +{ 0x2D08, 0x10A8, 0x2D08 }, +{ 0x2D09, 0x10A9, 0x2D09 }, +{ 0x2D0A, 0x10AA, 0x2D0A }, +{ 0x2D0B, 0x10AB, 0x2D0B }, +{ 0x2D0C, 0x10AC, 0x2D0C }, +{ 0x2D0D, 0x10AD, 0x2D0D }, +{ 0x2D0E, 0x10AE, 0x2D0E }, +{ 0x2D0F, 0x10AF, 0x2D0F }, +{ 0x2D10, 0x10B0, 0x2D10 }, +{ 0x2D11, 0x10B1, 0x2D11 }, +{ 0x2D12, 0x10B2, 0x2D12 }, +{ 0x2D13, 0x10B3, 0x2D13 }, +{ 0x2D14, 0x10B4, 0x2D14 }, +{ 0x2D15, 0x10B5, 0x2D15 }, +{ 0x2D16, 0x10B6, 0x2D16 }, +{ 0x2D17, 0x10B7, 0x2D17 }, +{ 0x2D18, 0x10B8, 0x2D18 }, +{ 0x2D19, 0x10B9, 0x2D19 }, +{ 0x2D1A, 0x10BA, 0x2D1A }, +{ 0x2D1B, 0x10BB, 0x2D1B }, +{ 0x2D1C, 0x10BC, 0x2D1C }, +{ 0x2D1D, 0x10BD, 0x2D1D }, +{ 0x2D1E, 0x10BE, 0x2D1E }, +{ 0x2D1F, 0x10BF, 0x2D1F }, +{ 0x2D20, 0x10C0, 0x2D20 }, +{ 0x2D21, 0x10C1, 0x2D21 }, +{ 0x2D22, 0x10C2, 0x2D22 }, +{ 0x2D23, 0x10C3, 0x2D23 }, +{ 0x2D24, 0x10C4, 0x2D24 }, +{ 0x2D25, 0x10C5, 0x2D25 }, +{ 0x2D30, 0x2D30, 0x2D30 }, +{ 0x2D31, 0x2D31, 0x2D31 }, +{ 0x2D32, 0x2D32, 0x2D32 }, +{ 0x2D33, 0x2D33, 0x2D33 }, +{ 0x2D34, 0x2D34, 0x2D34 }, +{ 0x2D35, 0x2D35, 0x2D35 }, +{ 0x2D36, 0x2D36, 0x2D36 }, +{ 0x2D37, 0x2D37, 0x2D37 }, +{ 0x2D38, 0x2D38, 0x2D38 }, +{ 0x2D39, 0x2D39, 0x2D39 }, +{ 0x2D3A, 0x2D3A, 0x2D3A }, +{ 0x2D3B, 0x2D3B, 0x2D3B }, +{ 0x2D3C, 0x2D3C, 0x2D3C }, +{ 0x2D3D, 0x2D3D, 0x2D3D }, +{ 0x2D3E, 0x2D3E, 0x2D3E }, +{ 0x2D3F, 0x2D3F, 0x2D3F }, +{ 0x2D40, 0x2D40, 0x2D40 }, +{ 0x2D41, 0x2D41, 0x2D41 }, +{ 0x2D42, 0x2D42, 0x2D42 }, +{ 0x2D43, 0x2D43, 0x2D43 }, +{ 0x2D44, 0x2D44, 0x2D44 }, +{ 0x2D45, 0x2D45, 0x2D45 }, +{ 0x2D46, 0x2D46, 0x2D46 }, +{ 0x2D47, 0x2D47, 0x2D47 }, +{ 0x2D48, 0x2D48, 0x2D48 }, +{ 0x2D49, 0x2D49, 0x2D49 }, +{ 0x2D4A, 0x2D4A, 0x2D4A }, +{ 0x2D4B, 0x2D4B, 0x2D4B }, +{ 0x2D4C, 0x2D4C, 0x2D4C }, +{ 0x2D4D, 0x2D4D, 0x2D4D }, +{ 0x2D4E, 0x2D4E, 0x2D4E }, +{ 0x2D4F, 0x2D4F, 0x2D4F }, +{ 0x2D50, 0x2D50, 0x2D50 }, +{ 0x2D51, 0x2D51, 0x2D51 }, +{ 0x2D52, 0x2D52, 0x2D52 }, +{ 0x2D53, 0x2D53, 0x2D53 }, +{ 0x2D54, 0x2D54, 0x2D54 }, +{ 0x2D55, 0x2D55, 0x2D55 }, +{ 0x2D56, 0x2D56, 0x2D56 }, +{ 0x2D57, 0x2D57, 0x2D57 }, +{ 0x2D58, 0x2D58, 0x2D58 }, +{ 0x2D59, 0x2D59, 0x2D59 }, +{ 0x2D5A, 0x2D5A, 0x2D5A }, +{ 0x2D5B, 0x2D5B, 0x2D5B }, +{ 0x2D5C, 0x2D5C, 0x2D5C }, +{ 0x2D5D, 0x2D5D, 0x2D5D }, +{ 0x2D5E, 0x2D5E, 0x2D5E }, +{ 0x2D5F, 0x2D5F, 0x2D5F }, +{ 0x2D60, 0x2D60, 0x2D60 }, +{ 0x2D61, 0x2D61, 0x2D61 }, +{ 0x2D62, 0x2D62, 0x2D62 }, +{ 0x2D63, 0x2D63, 0x2D63 }, +{ 0x2D64, 0x2D64, 0x2D64 }, +{ 0x2D65, 0x2D65, 0x2D65 }, +{ 0x2D6F, 0x2D6F, 0x2D6F }, +{ 0x2D80, 0x2D80, 0x2D80 }, +{ 0x2D81, 0x2D81, 0x2D81 }, +{ 0x2D82, 0x2D82, 0x2D82 }, +{ 0x2D83, 0x2D83, 0x2D83 }, +{ 0x2D84, 0x2D84, 0x2D84 }, +{ 0x2D85, 0x2D85, 0x2D85 }, +{ 0x2D86, 0x2D86, 0x2D86 }, +{ 0x2D87, 0x2D87, 0x2D87 }, +{ 0x2D88, 0x2D88, 0x2D88 }, +{ 0x2D89, 0x2D89, 0x2D89 }, +{ 0x2D8A, 0x2D8A, 0x2D8A }, +{ 0x2D8B, 0x2D8B, 0x2D8B }, +{ 0x2D8C, 0x2D8C, 0x2D8C }, +{ 0x2D8D, 0x2D8D, 0x2D8D }, +{ 0x2D8E, 0x2D8E, 0x2D8E }, +{ 0x2D8F, 0x2D8F, 0x2D8F }, +{ 0x2D90, 0x2D90, 0x2D90 }, +{ 0x2D91, 0x2D91, 0x2D91 }, +{ 0x2D92, 0x2D92, 0x2D92 }, +{ 0x2D93, 0x2D93, 0x2D93 }, +{ 0x2D94, 0x2D94, 0x2D94 }, +{ 0x2D95, 0x2D95, 0x2D95 }, +{ 0x2D96, 0x2D96, 0x2D96 }, +{ 0x2DA0, 0x2DA0, 0x2DA0 }, +{ 0x2DA1, 0x2DA1, 0x2DA1 }, +{ 0x2DA2, 0x2DA2, 0x2DA2 }, +{ 0x2DA3, 0x2DA3, 0x2DA3 }, +{ 0x2DA4, 0x2DA4, 0x2DA4 }, +{ 0x2DA5, 0x2DA5, 0x2DA5 }, +{ 0x2DA6, 0x2DA6, 0x2DA6 }, +{ 0x2DA8, 0x2DA8, 0x2DA8 }, +{ 0x2DA9, 0x2DA9, 0x2DA9 }, +{ 0x2DAA, 0x2DAA, 0x2DAA }, +{ 0x2DAB, 0x2DAB, 0x2DAB }, +{ 0x2DAC, 0x2DAC, 0x2DAC }, +{ 0x2DAD, 0x2DAD, 0x2DAD }, +{ 0x2DAE, 0x2DAE, 0x2DAE }, +{ 0x2DB0, 0x2DB0, 0x2DB0 }, +{ 0x2DB1, 0x2DB1, 0x2DB1 }, +{ 0x2DB2, 0x2DB2, 0x2DB2 }, +{ 0x2DB3, 0x2DB3, 0x2DB3 }, +{ 0x2DB4, 0x2DB4, 0x2DB4 }, +{ 0x2DB5, 0x2DB5, 0x2DB5 }, +{ 0x2DB6, 0x2DB6, 0x2DB6 }, +{ 0x2DB8, 0x2DB8, 0x2DB8 }, +{ 0x2DB9, 0x2DB9, 0x2DB9 }, +{ 0x2DBA, 0x2DBA, 0x2DBA }, +{ 0x2DBB, 0x2DBB, 0x2DBB }, +{ 0x2DBC, 0x2DBC, 0x2DBC }, +{ 0x2DBD, 0x2DBD, 0x2DBD }, +{ 0x2DBE, 0x2DBE, 0x2DBE }, +{ 0x2DC0, 0x2DC0, 0x2DC0 }, +{ 0x2DC1, 0x2DC1, 0x2DC1 }, +{ 0x2DC2, 0x2DC2, 0x2DC2 }, +{ 0x2DC3, 0x2DC3, 0x2DC3 }, +{ 0x2DC4, 0x2DC4, 0x2DC4 }, +{ 0x2DC5, 0x2DC5, 0x2DC5 }, +{ 0x2DC6, 0x2DC6, 0x2DC6 }, +{ 0x2DC8, 0x2DC8, 0x2DC8 }, +{ 0x2DC9, 0x2DC9, 0x2DC9 }, +{ 0x2DCA, 0x2DCA, 0x2DCA }, +{ 0x2DCB, 0x2DCB, 0x2DCB }, +{ 0x2DCC, 0x2DCC, 0x2DCC }, +{ 0x2DCD, 0x2DCD, 0x2DCD }, +{ 0x2DCE, 0x2DCE, 0x2DCE }, +{ 0x2DD0, 0x2DD0, 0x2DD0 }, +{ 0x2DD1, 0x2DD1, 0x2DD1 }, +{ 0x2DD2, 0x2DD2, 0x2DD2 }, +{ 0x2DD3, 0x2DD3, 0x2DD3 }, +{ 0x2DD4, 0x2DD4, 0x2DD4 }, +{ 0x2DD5, 0x2DD5, 0x2DD5 }, +{ 0x2DD6, 0x2DD6, 0x2DD6 }, +{ 0x2DD8, 0x2DD8, 0x2DD8 }, +{ 0x2DD9, 0x2DD9, 0x2DD9 }, +{ 0x2DDA, 0x2DDA, 0x2DDA }, +{ 0x2DDB, 0x2DDB, 0x2DDB }, +{ 0x2DDC, 0x2DDC, 0x2DDC }, +{ 0x2DDD, 0x2DDD, 0x2DDD }, +{ 0x2DDE, 0x2DDE, 0x2DDE }, +{ 0x3005, 0x3005, 0x3005 }, +{ 0x3006, 0x3006, 0x3006 }, +{ 0x302A, 0x302A, 0x302A }, +{ 0x302B, 0x302B, 0x302B }, +{ 0x302C, 0x302C, 0x302C }, +{ 0x302D, 0x302D, 0x302D }, +{ 0x302E, 0x302E, 0x302E }, +{ 0x302F, 0x302F, 0x302F }, +{ 0x3031, 0x3031, 0x3031 }, +{ 0x3032, 0x3032, 0x3032 }, +{ 0x3033, 0x3033, 0x3033 }, +{ 0x3034, 0x3034, 0x3034 }, +{ 0x3035, 0x3035, 0x3035 }, +{ 0x303B, 0x303B, 0x303B }, +{ 0x303C, 0x303C, 0x303C }, +{ 0x3041, 0x3041, 0x3041 }, +{ 0x3042, 0x3042, 0x3042 }, +{ 0x3043, 0x3043, 0x3043 }, +{ 0x3044, 0x3044, 0x3044 }, +{ 0x3045, 0x3045, 0x3045 }, +{ 0x3046, 0x3046, 0x3046 }, +{ 0x3047, 0x3047, 0x3047 }, +{ 0x3048, 0x3048, 0x3048 }, +{ 0x3049, 0x3049, 0x3049 }, +{ 0x304A, 0x304A, 0x304A }, +{ 0x304B, 0x304B, 0x304B }, +{ 0x304C, 0x304C, 0x304C }, +{ 0x304D, 0x304D, 0x304D }, +{ 0x304E, 0x304E, 0x304E }, +{ 0x304F, 0x304F, 0x304F }, +{ 0x3050, 0x3050, 0x3050 }, +{ 0x3051, 0x3051, 0x3051 }, +{ 0x3052, 0x3052, 0x3052 }, +{ 0x3053, 0x3053, 0x3053 }, +{ 0x3054, 0x3054, 0x3054 }, +{ 0x3055, 0x3055, 0x3055 }, +{ 0x3056, 0x3056, 0x3056 }, +{ 0x3057, 0x3057, 0x3057 }, +{ 0x3058, 0x3058, 0x3058 }, +{ 0x3059, 0x3059, 0x3059 }, +{ 0x305A, 0x305A, 0x305A }, +{ 0x305B, 0x305B, 0x305B }, +{ 0x305C, 0x305C, 0x305C }, +{ 0x305D, 0x305D, 0x305D }, +{ 0x305E, 0x305E, 0x305E }, +{ 0x305F, 0x305F, 0x305F }, +{ 0x3060, 0x3060, 0x3060 }, +{ 0x3061, 0x3061, 0x3061 }, +{ 0x3062, 0x3062, 0x3062 }, +{ 0x3063, 0x3063, 0x3063 }, +{ 0x3064, 0x3064, 0x3064 }, +{ 0x3065, 0x3065, 0x3065 }, +{ 0x3066, 0x3066, 0x3066 }, +{ 0x3067, 0x3067, 0x3067 }, +{ 0x3068, 0x3068, 0x3068 }, +{ 0x3069, 0x3069, 0x3069 }, +{ 0x306A, 0x306A, 0x306A }, +{ 0x306B, 0x306B, 0x306B }, +{ 0x306C, 0x306C, 0x306C }, +{ 0x306D, 0x306D, 0x306D }, +{ 0x306E, 0x306E, 0x306E }, +{ 0x306F, 0x306F, 0x306F }, +{ 0x3070, 0x3070, 0x3070 }, +{ 0x3071, 0x3071, 0x3071 }, +{ 0x3072, 0x3072, 0x3072 }, +{ 0x3073, 0x3073, 0x3073 }, +{ 0x3074, 0x3074, 0x3074 }, +{ 0x3075, 0x3075, 0x3075 }, +{ 0x3076, 0x3076, 0x3076 }, +{ 0x3077, 0x3077, 0x3077 }, +{ 0x3078, 0x3078, 0x3078 }, +{ 0x3079, 0x3079, 0x3079 }, +{ 0x307A, 0x307A, 0x307A }, +{ 0x307B, 0x307B, 0x307B }, +{ 0x307C, 0x307C, 0x307C }, +{ 0x307D, 0x307D, 0x307D }, +{ 0x307E, 0x307E, 0x307E }, +{ 0x307F, 0x307F, 0x307F }, +{ 0x3080, 0x3080, 0x3080 }, +{ 0x3081, 0x3081, 0x3081 }, +{ 0x3082, 0x3082, 0x3082 }, +{ 0x3083, 0x3083, 0x3083 }, +{ 0x3084, 0x3084, 0x3084 }, +{ 0x3085, 0x3085, 0x3085 }, +{ 0x3086, 0x3086, 0x3086 }, +{ 0x3087, 0x3087, 0x3087 }, +{ 0x3088, 0x3088, 0x3088 }, +{ 0x3089, 0x3089, 0x3089 }, +{ 0x308A, 0x308A, 0x308A }, +{ 0x308B, 0x308B, 0x308B }, +{ 0x308C, 0x308C, 0x308C }, +{ 0x308D, 0x308D, 0x308D }, +{ 0x308E, 0x308E, 0x308E }, +{ 0x308F, 0x308F, 0x308F }, +{ 0x3090, 0x3090, 0x3090 }, +{ 0x3091, 0x3091, 0x3091 }, +{ 0x3092, 0x3092, 0x3092 }, +{ 0x3093, 0x3093, 0x3093 }, +{ 0x3094, 0x3094, 0x3094 }, +{ 0x3095, 0x3095, 0x3095 }, +{ 0x3096, 0x3096, 0x3096 }, +{ 0x3099, 0x3099, 0x3099 }, +{ 0x309A, 0x309A, 0x309A }, +{ 0x309D, 0x309D, 0x309D }, +{ 0x309E, 0x309E, 0x309E }, +{ 0x309F, 0x309F, 0x309F }, +{ 0x30A1, 0x30A1, 0x30A1 }, +{ 0x30A2, 0x30A2, 0x30A2 }, +{ 0x30A3, 0x30A3, 0x30A3 }, +{ 0x30A4, 0x30A4, 0x30A4 }, +{ 0x30A5, 0x30A5, 0x30A5 }, +{ 0x30A6, 0x30A6, 0x30A6 }, +{ 0x30A7, 0x30A7, 0x30A7 }, +{ 0x30A8, 0x30A8, 0x30A8 }, +{ 0x30A9, 0x30A9, 0x30A9 }, +{ 0x30AA, 0x30AA, 0x30AA }, +{ 0x30AB, 0x30AB, 0x30AB }, +{ 0x30AC, 0x30AC, 0x30AC }, +{ 0x30AD, 0x30AD, 0x30AD }, +{ 0x30AE, 0x30AE, 0x30AE }, +{ 0x30AF, 0x30AF, 0x30AF }, +{ 0x30B0, 0x30B0, 0x30B0 }, +{ 0x30B1, 0x30B1, 0x30B1 }, +{ 0x30B2, 0x30B2, 0x30B2 }, +{ 0x30B3, 0x30B3, 0x30B3 }, +{ 0x30B4, 0x30B4, 0x30B4 }, +{ 0x30B5, 0x30B5, 0x30B5 }, +{ 0x30B6, 0x30B6, 0x30B6 }, +{ 0x30B7, 0x30B7, 0x30B7 }, +{ 0x30B8, 0x30B8, 0x30B8 }, +{ 0x30B9, 0x30B9, 0x30B9 }, +{ 0x30BA, 0x30BA, 0x30BA }, +{ 0x30BB, 0x30BB, 0x30BB }, +{ 0x30BC, 0x30BC, 0x30BC }, +{ 0x30BD, 0x30BD, 0x30BD }, +{ 0x30BE, 0x30BE, 0x30BE }, +{ 0x30BF, 0x30BF, 0x30BF }, +{ 0x30C0, 0x30C0, 0x30C0 }, +{ 0x30C1, 0x30C1, 0x30C1 }, +{ 0x30C2, 0x30C2, 0x30C2 }, +{ 0x30C3, 0x30C3, 0x30C3 }, +{ 0x30C4, 0x30C4, 0x30C4 }, +{ 0x30C5, 0x30C5, 0x30C5 }, +{ 0x30C6, 0x30C6, 0x30C6 }, +{ 0x30C7, 0x30C7, 0x30C7 }, +{ 0x30C8, 0x30C8, 0x30C8 }, +{ 0x30C9, 0x30C9, 0x30C9 }, +{ 0x30CA, 0x30CA, 0x30CA }, +{ 0x30CB, 0x30CB, 0x30CB }, +{ 0x30CC, 0x30CC, 0x30CC }, +{ 0x30CD, 0x30CD, 0x30CD }, +{ 0x30CE, 0x30CE, 0x30CE }, +{ 0x30CF, 0x30CF, 0x30CF }, +{ 0x30D0, 0x30D0, 0x30D0 }, +{ 0x30D1, 0x30D1, 0x30D1 }, +{ 0x30D2, 0x30D2, 0x30D2 }, +{ 0x30D3, 0x30D3, 0x30D3 }, +{ 0x30D4, 0x30D4, 0x30D4 }, +{ 0x30D5, 0x30D5, 0x30D5 }, +{ 0x30D6, 0x30D6, 0x30D6 }, +{ 0x30D7, 0x30D7, 0x30D7 }, +{ 0x30D8, 0x30D8, 0x30D8 }, +{ 0x30D9, 0x30D9, 0x30D9 }, +{ 0x30DA, 0x30DA, 0x30DA }, +{ 0x30DB, 0x30DB, 0x30DB }, +{ 0x30DC, 0x30DC, 0x30DC }, +{ 0x30DD, 0x30DD, 0x30DD }, +{ 0x30DE, 0x30DE, 0x30DE }, +{ 0x30DF, 0x30DF, 0x30DF }, +{ 0x30E0, 0x30E0, 0x30E0 }, +{ 0x30E1, 0x30E1, 0x30E1 }, +{ 0x30E2, 0x30E2, 0x30E2 }, +{ 0x30E3, 0x30E3, 0x30E3 }, +{ 0x30E4, 0x30E4, 0x30E4 }, +{ 0x30E5, 0x30E5, 0x30E5 }, +{ 0x30E6, 0x30E6, 0x30E6 }, +{ 0x30E7, 0x30E7, 0x30E7 }, +{ 0x30E8, 0x30E8, 0x30E8 }, +{ 0x30E9, 0x30E9, 0x30E9 }, +{ 0x30EA, 0x30EA, 0x30EA }, +{ 0x30EB, 0x30EB, 0x30EB }, +{ 0x30EC, 0x30EC, 0x30EC }, +{ 0x30ED, 0x30ED, 0x30ED }, +{ 0x30EE, 0x30EE, 0x30EE }, +{ 0x30EF, 0x30EF, 0x30EF }, +{ 0x30F0, 0x30F0, 0x30F0 }, +{ 0x30F1, 0x30F1, 0x30F1 }, +{ 0x30F2, 0x30F2, 0x30F2 }, +{ 0x30F3, 0x30F3, 0x30F3 }, +{ 0x30F4, 0x30F4, 0x30F4 }, +{ 0x30F5, 0x30F5, 0x30F5 }, +{ 0x30F6, 0x30F6, 0x30F6 }, +{ 0x30F7, 0x30F7, 0x30F7 }, +{ 0x30F8, 0x30F8, 0x30F8 }, +{ 0x30F9, 0x30F9, 0x30F9 }, +{ 0x30FA, 0x30FA, 0x30FA }, +{ 0x30FC, 0x30FC, 0x30FC }, +{ 0x30FD, 0x30FD, 0x30FD }, +{ 0x30FE, 0x30FE, 0x30FE }, +{ 0x30FF, 0x30FF, 0x30FF }, +{ 0x3105, 0x3105, 0x3105 }, +{ 0x3106, 0x3106, 0x3106 }, +{ 0x3107, 0x3107, 0x3107 }, +{ 0x3108, 0x3108, 0x3108 }, +{ 0x3109, 0x3109, 0x3109 }, +{ 0x310A, 0x310A, 0x310A }, +{ 0x310B, 0x310B, 0x310B }, +{ 0x310C, 0x310C, 0x310C }, +{ 0x310D, 0x310D, 0x310D }, +{ 0x310E, 0x310E, 0x310E }, +{ 0x310F, 0x310F, 0x310F }, +{ 0x3110, 0x3110, 0x3110 }, +{ 0x3111, 0x3111, 0x3111 }, +{ 0x3112, 0x3112, 0x3112 }, +{ 0x3113, 0x3113, 0x3113 }, +{ 0x3114, 0x3114, 0x3114 }, +{ 0x3115, 0x3115, 0x3115 }, +{ 0x3116, 0x3116, 0x3116 }, +{ 0x3117, 0x3117, 0x3117 }, +{ 0x3118, 0x3118, 0x3118 }, +{ 0x3119, 0x3119, 0x3119 }, +{ 0x311A, 0x311A, 0x311A }, +{ 0x311B, 0x311B, 0x311B }, +{ 0x311C, 0x311C, 0x311C }, +{ 0x311D, 0x311D, 0x311D }, +{ 0x311E, 0x311E, 0x311E }, +{ 0x311F, 0x311F, 0x311F }, +{ 0x3120, 0x3120, 0x3120 }, +{ 0x3121, 0x3121, 0x3121 }, +{ 0x3122, 0x3122, 0x3122 }, +{ 0x3123, 0x3123, 0x3123 }, +{ 0x3124, 0x3124, 0x3124 }, +{ 0x3125, 0x3125, 0x3125 }, +{ 0x3126, 0x3126, 0x3126 }, +{ 0x3127, 0x3127, 0x3127 }, +{ 0x3128, 0x3128, 0x3128 }, +{ 0x3129, 0x3129, 0x3129 }, +{ 0x312A, 0x312A, 0x312A }, +{ 0x312B, 0x312B, 0x312B }, +{ 0x312C, 0x312C, 0x312C }, +{ 0x3131, 0x3131, 0x3131 }, +{ 0x3132, 0x3132, 0x3132 }, +{ 0x3133, 0x3133, 0x3133 }, +{ 0x3134, 0x3134, 0x3134 }, +{ 0x3135, 0x3135, 0x3135 }, +{ 0x3136, 0x3136, 0x3136 }, +{ 0x3137, 0x3137, 0x3137 }, +{ 0x3138, 0x3138, 0x3138 }, +{ 0x3139, 0x3139, 0x3139 }, +{ 0x313A, 0x313A, 0x313A }, +{ 0x313B, 0x313B, 0x313B }, +{ 0x313C, 0x313C, 0x313C }, +{ 0x313D, 0x313D, 0x313D }, +{ 0x313E, 0x313E, 0x313E }, +{ 0x313F, 0x313F, 0x313F }, +{ 0x3140, 0x3140, 0x3140 }, +{ 0x3141, 0x3141, 0x3141 }, +{ 0x3142, 0x3142, 0x3142 }, +{ 0x3143, 0x3143, 0x3143 }, +{ 0x3144, 0x3144, 0x3144 }, +{ 0x3145, 0x3145, 0x3145 }, +{ 0x3146, 0x3146, 0x3146 }, +{ 0x3147, 0x3147, 0x3147 }, +{ 0x3148, 0x3148, 0x3148 }, +{ 0x3149, 0x3149, 0x3149 }, +{ 0x314A, 0x314A, 0x314A }, +{ 0x314B, 0x314B, 0x314B }, +{ 0x314C, 0x314C, 0x314C }, +{ 0x314D, 0x314D, 0x314D }, +{ 0x314E, 0x314E, 0x314E }, +{ 0x314F, 0x314F, 0x314F }, +{ 0x3150, 0x3150, 0x3150 }, +{ 0x3151, 0x3151, 0x3151 }, +{ 0x3152, 0x3152, 0x3152 }, +{ 0x3153, 0x3153, 0x3153 }, +{ 0x3154, 0x3154, 0x3154 }, +{ 0x3155, 0x3155, 0x3155 }, +{ 0x3156, 0x3156, 0x3156 }, +{ 0x3157, 0x3157, 0x3157 }, +{ 0x3158, 0x3158, 0x3158 }, +{ 0x3159, 0x3159, 0x3159 }, +{ 0x315A, 0x315A, 0x315A }, +{ 0x315B, 0x315B, 0x315B }, +{ 0x315C, 0x315C, 0x315C }, +{ 0x315D, 0x315D, 0x315D }, +{ 0x315E, 0x315E, 0x315E }, +{ 0x315F, 0x315F, 0x315F }, +{ 0x3160, 0x3160, 0x3160 }, +{ 0x3161, 0x3161, 0x3161 }, +{ 0x3162, 0x3162, 0x3162 }, +{ 0x3163, 0x3163, 0x3163 }, +{ 0x3164, 0x3164, 0x3164 }, +{ 0x3165, 0x3165, 0x3165 }, +{ 0x3166, 0x3166, 0x3166 }, +{ 0x3167, 0x3167, 0x3167 }, +{ 0x3168, 0x3168, 0x3168 }, +{ 0x3169, 0x3169, 0x3169 }, +{ 0x316A, 0x316A, 0x316A }, +{ 0x316B, 0x316B, 0x316B }, +{ 0x316C, 0x316C, 0x316C }, +{ 0x316D, 0x316D, 0x316D }, +{ 0x316E, 0x316E, 0x316E }, +{ 0x316F, 0x316F, 0x316F }, +{ 0x3170, 0x3170, 0x3170 }, +{ 0x3171, 0x3171, 0x3171 }, +{ 0x3172, 0x3172, 0x3172 }, +{ 0x3173, 0x3173, 0x3173 }, +{ 0x3174, 0x3174, 0x3174 }, +{ 0x3175, 0x3175, 0x3175 }, +{ 0x3176, 0x3176, 0x3176 }, +{ 0x3177, 0x3177, 0x3177 }, +{ 0x3178, 0x3178, 0x3178 }, +{ 0x3179, 0x3179, 0x3179 }, +{ 0x317A, 0x317A, 0x317A }, +{ 0x317B, 0x317B, 0x317B }, +{ 0x317C, 0x317C, 0x317C }, +{ 0x317D, 0x317D, 0x317D }, +{ 0x317E, 0x317E, 0x317E }, +{ 0x317F, 0x317F, 0x317F }, +{ 0x3180, 0x3180, 0x3180 }, +{ 0x3181, 0x3181, 0x3181 }, +{ 0x3182, 0x3182, 0x3182 }, +{ 0x3183, 0x3183, 0x3183 }, +{ 0x3184, 0x3184, 0x3184 }, +{ 0x3185, 0x3185, 0x3185 }, +{ 0x3186, 0x3186, 0x3186 }, +{ 0x3187, 0x3187, 0x3187 }, +{ 0x3188, 0x3188, 0x3188 }, +{ 0x3189, 0x3189, 0x3189 }, +{ 0x318A, 0x318A, 0x318A }, +{ 0x318B, 0x318B, 0x318B }, +{ 0x318C, 0x318C, 0x318C }, +{ 0x318D, 0x318D, 0x318D }, +{ 0x318E, 0x318E, 0x318E }, +{ 0x31A0, 0x31A0, 0x31A0 }, +{ 0x31A1, 0x31A1, 0x31A1 }, +{ 0x31A2, 0x31A2, 0x31A2 }, +{ 0x31A3, 0x31A3, 0x31A3 }, +{ 0x31A4, 0x31A4, 0x31A4 }, +{ 0x31A5, 0x31A5, 0x31A5 }, +{ 0x31A6, 0x31A6, 0x31A6 }, +{ 0x31A7, 0x31A7, 0x31A7 }, +{ 0x31A8, 0x31A8, 0x31A8 }, +{ 0x31A9, 0x31A9, 0x31A9 }, +{ 0x31AA, 0x31AA, 0x31AA }, +{ 0x31AB, 0x31AB, 0x31AB }, +{ 0x31AC, 0x31AC, 0x31AC }, +{ 0x31AD, 0x31AD, 0x31AD }, +{ 0x31AE, 0x31AE, 0x31AE }, +{ 0x31AF, 0x31AF, 0x31AF }, +{ 0x31B0, 0x31B0, 0x31B0 }, +{ 0x31B1, 0x31B1, 0x31B1 }, +{ 0x31B2, 0x31B2, 0x31B2 }, +{ 0x31B3, 0x31B3, 0x31B3 }, +{ 0x31B4, 0x31B4, 0x31B4 }, +{ 0x31B5, 0x31B5, 0x31B5 }, +{ 0x31B6, 0x31B6, 0x31B6 }, +{ 0x31B7, 0x31B7, 0x31B7 }, +{ 0x31F0, 0x31F0, 0x31F0 }, +{ 0x31F1, 0x31F1, 0x31F1 }, +{ 0x31F2, 0x31F2, 0x31F2 }, +{ 0x31F3, 0x31F3, 0x31F3 }, +{ 0x31F4, 0x31F4, 0x31F4 }, +{ 0x31F5, 0x31F5, 0x31F5 }, +{ 0x31F6, 0x31F6, 0x31F6 }, +{ 0x31F7, 0x31F7, 0x31F7 }, +{ 0x31F8, 0x31F8, 0x31F8 }, +{ 0x31F9, 0x31F9, 0x31F9 }, +{ 0x31FA, 0x31FA, 0x31FA }, +{ 0x31FB, 0x31FB, 0x31FB }, +{ 0x31FC, 0x31FC, 0x31FC }, +{ 0x31FD, 0x31FD, 0x31FD }, +{ 0x31FE, 0x31FE, 0x31FE }, +{ 0x31FF, 0x31FF, 0x31FF }, +{ 0x3400, 0x3400, 0x3400 }, +{ 0x4DB5, 0x4DB5, 0x4DB5 }, +{ 0x4E00, 0x4E00, 0x4E00 }, +{ 0x9FBB, 0x9FBB, 0x9FBB }, +{ 0xA000, 0xA000, 0xA000 }, +{ 0xA001, 0xA001, 0xA001 }, +{ 0xA002, 0xA002, 0xA002 }, +{ 0xA003, 0xA003, 0xA003 }, +{ 0xA004, 0xA004, 0xA004 }, +{ 0xA005, 0xA005, 0xA005 }, +{ 0xA006, 0xA006, 0xA006 }, +{ 0xA007, 0xA007, 0xA007 }, +{ 0xA008, 0xA008, 0xA008 }, +{ 0xA009, 0xA009, 0xA009 }, +{ 0xA00A, 0xA00A, 0xA00A }, +{ 0xA00B, 0xA00B, 0xA00B }, +{ 0xA00C, 0xA00C, 0xA00C }, +{ 0xA00D, 0xA00D, 0xA00D }, +{ 0xA00E, 0xA00E, 0xA00E }, +{ 0xA00F, 0xA00F, 0xA00F }, +{ 0xA010, 0xA010, 0xA010 }, +{ 0xA011, 0xA011, 0xA011 }, +{ 0xA012, 0xA012, 0xA012 }, +{ 0xA013, 0xA013, 0xA013 }, +{ 0xA014, 0xA014, 0xA014 }, +{ 0xA015, 0xA015, 0xA015 }, +{ 0xA016, 0xA016, 0xA016 }, +{ 0xA017, 0xA017, 0xA017 }, +{ 0xA018, 0xA018, 0xA018 }, +{ 0xA019, 0xA019, 0xA019 }, +{ 0xA01A, 0xA01A, 0xA01A }, +{ 0xA01B, 0xA01B, 0xA01B }, +{ 0xA01C, 0xA01C, 0xA01C }, +{ 0xA01D, 0xA01D, 0xA01D }, +{ 0xA01E, 0xA01E, 0xA01E }, +{ 0xA01F, 0xA01F, 0xA01F }, +{ 0xA020, 0xA020, 0xA020 }, +{ 0xA021, 0xA021, 0xA021 }, +{ 0xA022, 0xA022, 0xA022 }, +{ 0xA023, 0xA023, 0xA023 }, +{ 0xA024, 0xA024, 0xA024 }, +{ 0xA025, 0xA025, 0xA025 }, +{ 0xA026, 0xA026, 0xA026 }, +{ 0xA027, 0xA027, 0xA027 }, +{ 0xA028, 0xA028, 0xA028 }, +{ 0xA029, 0xA029, 0xA029 }, +{ 0xA02A, 0xA02A, 0xA02A }, +{ 0xA02B, 0xA02B, 0xA02B }, +{ 0xA02C, 0xA02C, 0xA02C }, +{ 0xA02D, 0xA02D, 0xA02D }, +{ 0xA02E, 0xA02E, 0xA02E }, +{ 0xA02F, 0xA02F, 0xA02F }, +{ 0xA030, 0xA030, 0xA030 }, +{ 0xA031, 0xA031, 0xA031 }, +{ 0xA032, 0xA032, 0xA032 }, +{ 0xA033, 0xA033, 0xA033 }, +{ 0xA034, 0xA034, 0xA034 }, +{ 0xA035, 0xA035, 0xA035 }, +{ 0xA036, 0xA036, 0xA036 }, +{ 0xA037, 0xA037, 0xA037 }, +{ 0xA038, 0xA038, 0xA038 }, +{ 0xA039, 0xA039, 0xA039 }, +{ 0xA03A, 0xA03A, 0xA03A }, +{ 0xA03B, 0xA03B, 0xA03B }, +{ 0xA03C, 0xA03C, 0xA03C }, +{ 0xA03D, 0xA03D, 0xA03D }, +{ 0xA03E, 0xA03E, 0xA03E }, +{ 0xA03F, 0xA03F, 0xA03F }, +{ 0xA040, 0xA040, 0xA040 }, +{ 0xA041, 0xA041, 0xA041 }, +{ 0xA042, 0xA042, 0xA042 }, +{ 0xA043, 0xA043, 0xA043 }, +{ 0xA044, 0xA044, 0xA044 }, +{ 0xA045, 0xA045, 0xA045 }, +{ 0xA046, 0xA046, 0xA046 }, +{ 0xA047, 0xA047, 0xA047 }, +{ 0xA048, 0xA048, 0xA048 }, +{ 0xA049, 0xA049, 0xA049 }, +{ 0xA04A, 0xA04A, 0xA04A }, +{ 0xA04B, 0xA04B, 0xA04B }, +{ 0xA04C, 0xA04C, 0xA04C }, +{ 0xA04D, 0xA04D, 0xA04D }, +{ 0xA04E, 0xA04E, 0xA04E }, +{ 0xA04F, 0xA04F, 0xA04F }, +{ 0xA050, 0xA050, 0xA050 }, +{ 0xA051, 0xA051, 0xA051 }, +{ 0xA052, 0xA052, 0xA052 }, +{ 0xA053, 0xA053, 0xA053 }, +{ 0xA054, 0xA054, 0xA054 }, +{ 0xA055, 0xA055, 0xA055 }, +{ 0xA056, 0xA056, 0xA056 }, +{ 0xA057, 0xA057, 0xA057 }, +{ 0xA058, 0xA058, 0xA058 }, +{ 0xA059, 0xA059, 0xA059 }, +{ 0xA05A, 0xA05A, 0xA05A }, +{ 0xA05B, 0xA05B, 0xA05B }, +{ 0xA05C, 0xA05C, 0xA05C }, +{ 0xA05D, 0xA05D, 0xA05D }, +{ 0xA05E, 0xA05E, 0xA05E }, +{ 0xA05F, 0xA05F, 0xA05F }, +{ 0xA060, 0xA060, 0xA060 }, +{ 0xA061, 0xA061, 0xA061 }, +{ 0xA062, 0xA062, 0xA062 }, +{ 0xA063, 0xA063, 0xA063 }, +{ 0xA064, 0xA064, 0xA064 }, +{ 0xA065, 0xA065, 0xA065 }, +{ 0xA066, 0xA066, 0xA066 }, +{ 0xA067, 0xA067, 0xA067 }, +{ 0xA068, 0xA068, 0xA068 }, +{ 0xA069, 0xA069, 0xA069 }, +{ 0xA06A, 0xA06A, 0xA06A }, +{ 0xA06B, 0xA06B, 0xA06B }, +{ 0xA06C, 0xA06C, 0xA06C }, +{ 0xA06D, 0xA06D, 0xA06D }, +{ 0xA06E, 0xA06E, 0xA06E }, +{ 0xA06F, 0xA06F, 0xA06F }, +{ 0xA070, 0xA070, 0xA070 }, +{ 0xA071, 0xA071, 0xA071 }, +{ 0xA072, 0xA072, 0xA072 }, +{ 0xA073, 0xA073, 0xA073 }, +{ 0xA074, 0xA074, 0xA074 }, +{ 0xA075, 0xA075, 0xA075 }, +{ 0xA076, 0xA076, 0xA076 }, +{ 0xA077, 0xA077, 0xA077 }, +{ 0xA078, 0xA078, 0xA078 }, +{ 0xA079, 0xA079, 0xA079 }, +{ 0xA07A, 0xA07A, 0xA07A }, +{ 0xA07B, 0xA07B, 0xA07B }, +{ 0xA07C, 0xA07C, 0xA07C }, +{ 0xA07D, 0xA07D, 0xA07D }, +{ 0xA07E, 0xA07E, 0xA07E }, +{ 0xA07F, 0xA07F, 0xA07F }, +{ 0xA080, 0xA080, 0xA080 }, +{ 0xA081, 0xA081, 0xA081 }, +{ 0xA082, 0xA082, 0xA082 }, +{ 0xA083, 0xA083, 0xA083 }, +{ 0xA084, 0xA084, 0xA084 }, +{ 0xA085, 0xA085, 0xA085 }, +{ 0xA086, 0xA086, 0xA086 }, +{ 0xA087, 0xA087, 0xA087 }, +{ 0xA088, 0xA088, 0xA088 }, +{ 0xA089, 0xA089, 0xA089 }, +{ 0xA08A, 0xA08A, 0xA08A }, +{ 0xA08B, 0xA08B, 0xA08B }, +{ 0xA08C, 0xA08C, 0xA08C }, +{ 0xA08D, 0xA08D, 0xA08D }, +{ 0xA08E, 0xA08E, 0xA08E }, +{ 0xA08F, 0xA08F, 0xA08F }, +{ 0xA090, 0xA090, 0xA090 }, +{ 0xA091, 0xA091, 0xA091 }, +{ 0xA092, 0xA092, 0xA092 }, +{ 0xA093, 0xA093, 0xA093 }, +{ 0xA094, 0xA094, 0xA094 }, +{ 0xA095, 0xA095, 0xA095 }, +{ 0xA096, 0xA096, 0xA096 }, +{ 0xA097, 0xA097, 0xA097 }, +{ 0xA098, 0xA098, 0xA098 }, +{ 0xA099, 0xA099, 0xA099 }, +{ 0xA09A, 0xA09A, 0xA09A }, +{ 0xA09B, 0xA09B, 0xA09B }, +{ 0xA09C, 0xA09C, 0xA09C }, +{ 0xA09D, 0xA09D, 0xA09D }, +{ 0xA09E, 0xA09E, 0xA09E }, +{ 0xA09F, 0xA09F, 0xA09F }, +{ 0xA0A0, 0xA0A0, 0xA0A0 }, +{ 0xA0A1, 0xA0A1, 0xA0A1 }, +{ 0xA0A2, 0xA0A2, 0xA0A2 }, +{ 0xA0A3, 0xA0A3, 0xA0A3 }, +{ 0xA0A4, 0xA0A4, 0xA0A4 }, +{ 0xA0A5, 0xA0A5, 0xA0A5 }, +{ 0xA0A6, 0xA0A6, 0xA0A6 }, +{ 0xA0A7, 0xA0A7, 0xA0A7 }, +{ 0xA0A8, 0xA0A8, 0xA0A8 }, +{ 0xA0A9, 0xA0A9, 0xA0A9 }, +{ 0xA0AA, 0xA0AA, 0xA0AA }, +{ 0xA0AB, 0xA0AB, 0xA0AB }, +{ 0xA0AC, 0xA0AC, 0xA0AC }, +{ 0xA0AD, 0xA0AD, 0xA0AD }, +{ 0xA0AE, 0xA0AE, 0xA0AE }, +{ 0xA0AF, 0xA0AF, 0xA0AF }, +{ 0xA0B0, 0xA0B0, 0xA0B0 }, +{ 0xA0B1, 0xA0B1, 0xA0B1 }, +{ 0xA0B2, 0xA0B2, 0xA0B2 }, +{ 0xA0B3, 0xA0B3, 0xA0B3 }, +{ 0xA0B4, 0xA0B4, 0xA0B4 }, +{ 0xA0B5, 0xA0B5, 0xA0B5 }, +{ 0xA0B6, 0xA0B6, 0xA0B6 }, +{ 0xA0B7, 0xA0B7, 0xA0B7 }, +{ 0xA0B8, 0xA0B8, 0xA0B8 }, +{ 0xA0B9, 0xA0B9, 0xA0B9 }, +{ 0xA0BA, 0xA0BA, 0xA0BA }, +{ 0xA0BB, 0xA0BB, 0xA0BB }, +{ 0xA0BC, 0xA0BC, 0xA0BC }, +{ 0xA0BD, 0xA0BD, 0xA0BD }, +{ 0xA0BE, 0xA0BE, 0xA0BE }, +{ 0xA0BF, 0xA0BF, 0xA0BF }, +{ 0xA0C0, 0xA0C0, 0xA0C0 }, +{ 0xA0C1, 0xA0C1, 0xA0C1 }, +{ 0xA0C2, 0xA0C2, 0xA0C2 }, +{ 0xA0C3, 0xA0C3, 0xA0C3 }, +{ 0xA0C4, 0xA0C4, 0xA0C4 }, +{ 0xA0C5, 0xA0C5, 0xA0C5 }, +{ 0xA0C6, 0xA0C6, 0xA0C6 }, +{ 0xA0C7, 0xA0C7, 0xA0C7 }, +{ 0xA0C8, 0xA0C8, 0xA0C8 }, +{ 0xA0C9, 0xA0C9, 0xA0C9 }, +{ 0xA0CA, 0xA0CA, 0xA0CA }, +{ 0xA0CB, 0xA0CB, 0xA0CB }, +{ 0xA0CC, 0xA0CC, 0xA0CC }, +{ 0xA0CD, 0xA0CD, 0xA0CD }, +{ 0xA0CE, 0xA0CE, 0xA0CE }, +{ 0xA0CF, 0xA0CF, 0xA0CF }, +{ 0xA0D0, 0xA0D0, 0xA0D0 }, +{ 0xA0D1, 0xA0D1, 0xA0D1 }, +{ 0xA0D2, 0xA0D2, 0xA0D2 }, +{ 0xA0D3, 0xA0D3, 0xA0D3 }, +{ 0xA0D4, 0xA0D4, 0xA0D4 }, +{ 0xA0D5, 0xA0D5, 0xA0D5 }, +{ 0xA0D6, 0xA0D6, 0xA0D6 }, +{ 0xA0D7, 0xA0D7, 0xA0D7 }, +{ 0xA0D8, 0xA0D8, 0xA0D8 }, +{ 0xA0D9, 0xA0D9, 0xA0D9 }, +{ 0xA0DA, 0xA0DA, 0xA0DA }, +{ 0xA0DB, 0xA0DB, 0xA0DB }, +{ 0xA0DC, 0xA0DC, 0xA0DC }, +{ 0xA0DD, 0xA0DD, 0xA0DD }, +{ 0xA0DE, 0xA0DE, 0xA0DE }, +{ 0xA0DF, 0xA0DF, 0xA0DF }, +{ 0xA0E0, 0xA0E0, 0xA0E0 }, +{ 0xA0E1, 0xA0E1, 0xA0E1 }, +{ 0xA0E2, 0xA0E2, 0xA0E2 }, +{ 0xA0E3, 0xA0E3, 0xA0E3 }, +{ 0xA0E4, 0xA0E4, 0xA0E4 }, +{ 0xA0E5, 0xA0E5, 0xA0E5 }, +{ 0xA0E6, 0xA0E6, 0xA0E6 }, +{ 0xA0E7, 0xA0E7, 0xA0E7 }, +{ 0xA0E8, 0xA0E8, 0xA0E8 }, +{ 0xA0E9, 0xA0E9, 0xA0E9 }, +{ 0xA0EA, 0xA0EA, 0xA0EA }, +{ 0xA0EB, 0xA0EB, 0xA0EB }, +{ 0xA0EC, 0xA0EC, 0xA0EC }, +{ 0xA0ED, 0xA0ED, 0xA0ED }, +{ 0xA0EE, 0xA0EE, 0xA0EE }, +{ 0xA0EF, 0xA0EF, 0xA0EF }, +{ 0xA0F0, 0xA0F0, 0xA0F0 }, +{ 0xA0F1, 0xA0F1, 0xA0F1 }, +{ 0xA0F2, 0xA0F2, 0xA0F2 }, +{ 0xA0F3, 0xA0F3, 0xA0F3 }, +{ 0xA0F4, 0xA0F4, 0xA0F4 }, +{ 0xA0F5, 0xA0F5, 0xA0F5 }, +{ 0xA0F6, 0xA0F6, 0xA0F6 }, +{ 0xA0F7, 0xA0F7, 0xA0F7 }, +{ 0xA0F8, 0xA0F8, 0xA0F8 }, +{ 0xA0F9, 0xA0F9, 0xA0F9 }, +{ 0xA0FA, 0xA0FA, 0xA0FA }, +{ 0xA0FB, 0xA0FB, 0xA0FB }, +{ 0xA0FC, 0xA0FC, 0xA0FC }, +{ 0xA0FD, 0xA0FD, 0xA0FD }, +{ 0xA0FE, 0xA0FE, 0xA0FE }, +{ 0xA0FF, 0xA0FF, 0xA0FF }, +{ 0xA100, 0xA100, 0xA100 }, +{ 0xA101, 0xA101, 0xA101 }, +{ 0xA102, 0xA102, 0xA102 }, +{ 0xA103, 0xA103, 0xA103 }, +{ 0xA104, 0xA104, 0xA104 }, +{ 0xA105, 0xA105, 0xA105 }, +{ 0xA106, 0xA106, 0xA106 }, +{ 0xA107, 0xA107, 0xA107 }, +{ 0xA108, 0xA108, 0xA108 }, +{ 0xA109, 0xA109, 0xA109 }, +{ 0xA10A, 0xA10A, 0xA10A }, +{ 0xA10B, 0xA10B, 0xA10B }, +{ 0xA10C, 0xA10C, 0xA10C }, +{ 0xA10D, 0xA10D, 0xA10D }, +{ 0xA10E, 0xA10E, 0xA10E }, +{ 0xA10F, 0xA10F, 0xA10F }, +{ 0xA110, 0xA110, 0xA110 }, +{ 0xA111, 0xA111, 0xA111 }, +{ 0xA112, 0xA112, 0xA112 }, +{ 0xA113, 0xA113, 0xA113 }, +{ 0xA114, 0xA114, 0xA114 }, +{ 0xA115, 0xA115, 0xA115 }, +{ 0xA116, 0xA116, 0xA116 }, +{ 0xA117, 0xA117, 0xA117 }, +{ 0xA118, 0xA118, 0xA118 }, +{ 0xA119, 0xA119, 0xA119 }, +{ 0xA11A, 0xA11A, 0xA11A }, +{ 0xA11B, 0xA11B, 0xA11B }, +{ 0xA11C, 0xA11C, 0xA11C }, +{ 0xA11D, 0xA11D, 0xA11D }, +{ 0xA11E, 0xA11E, 0xA11E }, +{ 0xA11F, 0xA11F, 0xA11F }, +{ 0xA120, 0xA120, 0xA120 }, +{ 0xA121, 0xA121, 0xA121 }, +{ 0xA122, 0xA122, 0xA122 }, +{ 0xA123, 0xA123, 0xA123 }, +{ 0xA124, 0xA124, 0xA124 }, +{ 0xA125, 0xA125, 0xA125 }, +{ 0xA126, 0xA126, 0xA126 }, +{ 0xA127, 0xA127, 0xA127 }, +{ 0xA128, 0xA128, 0xA128 }, +{ 0xA129, 0xA129, 0xA129 }, +{ 0xA12A, 0xA12A, 0xA12A }, +{ 0xA12B, 0xA12B, 0xA12B }, +{ 0xA12C, 0xA12C, 0xA12C }, +{ 0xA12D, 0xA12D, 0xA12D }, +{ 0xA12E, 0xA12E, 0xA12E }, +{ 0xA12F, 0xA12F, 0xA12F }, +{ 0xA130, 0xA130, 0xA130 }, +{ 0xA131, 0xA131, 0xA131 }, +{ 0xA132, 0xA132, 0xA132 }, +{ 0xA133, 0xA133, 0xA133 }, +{ 0xA134, 0xA134, 0xA134 }, +{ 0xA135, 0xA135, 0xA135 }, +{ 0xA136, 0xA136, 0xA136 }, +{ 0xA137, 0xA137, 0xA137 }, +{ 0xA138, 0xA138, 0xA138 }, +{ 0xA139, 0xA139, 0xA139 }, +{ 0xA13A, 0xA13A, 0xA13A }, +{ 0xA13B, 0xA13B, 0xA13B }, +{ 0xA13C, 0xA13C, 0xA13C }, +{ 0xA13D, 0xA13D, 0xA13D }, +{ 0xA13E, 0xA13E, 0xA13E }, +{ 0xA13F, 0xA13F, 0xA13F }, +{ 0xA140, 0xA140, 0xA140 }, +{ 0xA141, 0xA141, 0xA141 }, +{ 0xA142, 0xA142, 0xA142 }, +{ 0xA143, 0xA143, 0xA143 }, +{ 0xA144, 0xA144, 0xA144 }, +{ 0xA145, 0xA145, 0xA145 }, +{ 0xA146, 0xA146, 0xA146 }, +{ 0xA147, 0xA147, 0xA147 }, +{ 0xA148, 0xA148, 0xA148 }, +{ 0xA149, 0xA149, 0xA149 }, +{ 0xA14A, 0xA14A, 0xA14A }, +{ 0xA14B, 0xA14B, 0xA14B }, +{ 0xA14C, 0xA14C, 0xA14C }, +{ 0xA14D, 0xA14D, 0xA14D }, +{ 0xA14E, 0xA14E, 0xA14E }, +{ 0xA14F, 0xA14F, 0xA14F }, +{ 0xA150, 0xA150, 0xA150 }, +{ 0xA151, 0xA151, 0xA151 }, +{ 0xA152, 0xA152, 0xA152 }, +{ 0xA153, 0xA153, 0xA153 }, +{ 0xA154, 0xA154, 0xA154 }, +{ 0xA155, 0xA155, 0xA155 }, +{ 0xA156, 0xA156, 0xA156 }, +{ 0xA157, 0xA157, 0xA157 }, +{ 0xA158, 0xA158, 0xA158 }, +{ 0xA159, 0xA159, 0xA159 }, +{ 0xA15A, 0xA15A, 0xA15A }, +{ 0xA15B, 0xA15B, 0xA15B }, +{ 0xA15C, 0xA15C, 0xA15C }, +{ 0xA15D, 0xA15D, 0xA15D }, +{ 0xA15E, 0xA15E, 0xA15E }, +{ 0xA15F, 0xA15F, 0xA15F }, +{ 0xA160, 0xA160, 0xA160 }, +{ 0xA161, 0xA161, 0xA161 }, +{ 0xA162, 0xA162, 0xA162 }, +{ 0xA163, 0xA163, 0xA163 }, +{ 0xA164, 0xA164, 0xA164 }, +{ 0xA165, 0xA165, 0xA165 }, +{ 0xA166, 0xA166, 0xA166 }, +{ 0xA167, 0xA167, 0xA167 }, +{ 0xA168, 0xA168, 0xA168 }, +{ 0xA169, 0xA169, 0xA169 }, +{ 0xA16A, 0xA16A, 0xA16A }, +{ 0xA16B, 0xA16B, 0xA16B }, +{ 0xA16C, 0xA16C, 0xA16C }, +{ 0xA16D, 0xA16D, 0xA16D }, +{ 0xA16E, 0xA16E, 0xA16E }, +{ 0xA16F, 0xA16F, 0xA16F }, +{ 0xA170, 0xA170, 0xA170 }, +{ 0xA171, 0xA171, 0xA171 }, +{ 0xA172, 0xA172, 0xA172 }, +{ 0xA173, 0xA173, 0xA173 }, +{ 0xA174, 0xA174, 0xA174 }, +{ 0xA175, 0xA175, 0xA175 }, +{ 0xA176, 0xA176, 0xA176 }, +{ 0xA177, 0xA177, 0xA177 }, +{ 0xA178, 0xA178, 0xA178 }, +{ 0xA179, 0xA179, 0xA179 }, +{ 0xA17A, 0xA17A, 0xA17A }, +{ 0xA17B, 0xA17B, 0xA17B }, +{ 0xA17C, 0xA17C, 0xA17C }, +{ 0xA17D, 0xA17D, 0xA17D }, +{ 0xA17E, 0xA17E, 0xA17E }, +{ 0xA17F, 0xA17F, 0xA17F }, +{ 0xA180, 0xA180, 0xA180 }, +{ 0xA181, 0xA181, 0xA181 }, +{ 0xA182, 0xA182, 0xA182 }, +{ 0xA183, 0xA183, 0xA183 }, +{ 0xA184, 0xA184, 0xA184 }, +{ 0xA185, 0xA185, 0xA185 }, +{ 0xA186, 0xA186, 0xA186 }, +{ 0xA187, 0xA187, 0xA187 }, +{ 0xA188, 0xA188, 0xA188 }, +{ 0xA189, 0xA189, 0xA189 }, +{ 0xA18A, 0xA18A, 0xA18A }, +{ 0xA18B, 0xA18B, 0xA18B }, +{ 0xA18C, 0xA18C, 0xA18C }, +{ 0xA18D, 0xA18D, 0xA18D }, +{ 0xA18E, 0xA18E, 0xA18E }, +{ 0xA18F, 0xA18F, 0xA18F }, +{ 0xA190, 0xA190, 0xA190 }, +{ 0xA191, 0xA191, 0xA191 }, +{ 0xA192, 0xA192, 0xA192 }, +{ 0xA193, 0xA193, 0xA193 }, +{ 0xA194, 0xA194, 0xA194 }, +{ 0xA195, 0xA195, 0xA195 }, +{ 0xA196, 0xA196, 0xA196 }, +{ 0xA197, 0xA197, 0xA197 }, +{ 0xA198, 0xA198, 0xA198 }, +{ 0xA199, 0xA199, 0xA199 }, +{ 0xA19A, 0xA19A, 0xA19A }, +{ 0xA19B, 0xA19B, 0xA19B }, +{ 0xA19C, 0xA19C, 0xA19C }, +{ 0xA19D, 0xA19D, 0xA19D }, +{ 0xA19E, 0xA19E, 0xA19E }, +{ 0xA19F, 0xA19F, 0xA19F }, +{ 0xA1A0, 0xA1A0, 0xA1A0 }, +{ 0xA1A1, 0xA1A1, 0xA1A1 }, +{ 0xA1A2, 0xA1A2, 0xA1A2 }, +{ 0xA1A3, 0xA1A3, 0xA1A3 }, +{ 0xA1A4, 0xA1A4, 0xA1A4 }, +{ 0xA1A5, 0xA1A5, 0xA1A5 }, +{ 0xA1A6, 0xA1A6, 0xA1A6 }, +{ 0xA1A7, 0xA1A7, 0xA1A7 }, +{ 0xA1A8, 0xA1A8, 0xA1A8 }, +{ 0xA1A9, 0xA1A9, 0xA1A9 }, +{ 0xA1AA, 0xA1AA, 0xA1AA }, +{ 0xA1AB, 0xA1AB, 0xA1AB }, +{ 0xA1AC, 0xA1AC, 0xA1AC }, +{ 0xA1AD, 0xA1AD, 0xA1AD }, +{ 0xA1AE, 0xA1AE, 0xA1AE }, +{ 0xA1AF, 0xA1AF, 0xA1AF }, +{ 0xA1B0, 0xA1B0, 0xA1B0 }, +{ 0xA1B1, 0xA1B1, 0xA1B1 }, +{ 0xA1B2, 0xA1B2, 0xA1B2 }, +{ 0xA1B3, 0xA1B3, 0xA1B3 }, +{ 0xA1B4, 0xA1B4, 0xA1B4 }, +{ 0xA1B5, 0xA1B5, 0xA1B5 }, +{ 0xA1B6, 0xA1B6, 0xA1B6 }, +{ 0xA1B7, 0xA1B7, 0xA1B7 }, +{ 0xA1B8, 0xA1B8, 0xA1B8 }, +{ 0xA1B9, 0xA1B9, 0xA1B9 }, +{ 0xA1BA, 0xA1BA, 0xA1BA }, +{ 0xA1BB, 0xA1BB, 0xA1BB }, +{ 0xA1BC, 0xA1BC, 0xA1BC }, +{ 0xA1BD, 0xA1BD, 0xA1BD }, +{ 0xA1BE, 0xA1BE, 0xA1BE }, +{ 0xA1BF, 0xA1BF, 0xA1BF }, +{ 0xA1C0, 0xA1C0, 0xA1C0 }, +{ 0xA1C1, 0xA1C1, 0xA1C1 }, +{ 0xA1C2, 0xA1C2, 0xA1C2 }, +{ 0xA1C3, 0xA1C3, 0xA1C3 }, +{ 0xA1C4, 0xA1C4, 0xA1C4 }, +{ 0xA1C5, 0xA1C5, 0xA1C5 }, +{ 0xA1C6, 0xA1C6, 0xA1C6 }, +{ 0xA1C7, 0xA1C7, 0xA1C7 }, +{ 0xA1C8, 0xA1C8, 0xA1C8 }, +{ 0xA1C9, 0xA1C9, 0xA1C9 }, +{ 0xA1CA, 0xA1CA, 0xA1CA }, +{ 0xA1CB, 0xA1CB, 0xA1CB }, +{ 0xA1CC, 0xA1CC, 0xA1CC }, +{ 0xA1CD, 0xA1CD, 0xA1CD }, +{ 0xA1CE, 0xA1CE, 0xA1CE }, +{ 0xA1CF, 0xA1CF, 0xA1CF }, +{ 0xA1D0, 0xA1D0, 0xA1D0 }, +{ 0xA1D1, 0xA1D1, 0xA1D1 }, +{ 0xA1D2, 0xA1D2, 0xA1D2 }, +{ 0xA1D3, 0xA1D3, 0xA1D3 }, +{ 0xA1D4, 0xA1D4, 0xA1D4 }, +{ 0xA1D5, 0xA1D5, 0xA1D5 }, +{ 0xA1D6, 0xA1D6, 0xA1D6 }, +{ 0xA1D7, 0xA1D7, 0xA1D7 }, +{ 0xA1D8, 0xA1D8, 0xA1D8 }, +{ 0xA1D9, 0xA1D9, 0xA1D9 }, +{ 0xA1DA, 0xA1DA, 0xA1DA }, +{ 0xA1DB, 0xA1DB, 0xA1DB }, +{ 0xA1DC, 0xA1DC, 0xA1DC }, +{ 0xA1DD, 0xA1DD, 0xA1DD }, +{ 0xA1DE, 0xA1DE, 0xA1DE }, +{ 0xA1DF, 0xA1DF, 0xA1DF }, +{ 0xA1E0, 0xA1E0, 0xA1E0 }, +{ 0xA1E1, 0xA1E1, 0xA1E1 }, +{ 0xA1E2, 0xA1E2, 0xA1E2 }, +{ 0xA1E3, 0xA1E3, 0xA1E3 }, +{ 0xA1E4, 0xA1E4, 0xA1E4 }, +{ 0xA1E5, 0xA1E5, 0xA1E5 }, +{ 0xA1E6, 0xA1E6, 0xA1E6 }, +{ 0xA1E7, 0xA1E7, 0xA1E7 }, +{ 0xA1E8, 0xA1E8, 0xA1E8 }, +{ 0xA1E9, 0xA1E9, 0xA1E9 }, +{ 0xA1EA, 0xA1EA, 0xA1EA }, +{ 0xA1EB, 0xA1EB, 0xA1EB }, +{ 0xA1EC, 0xA1EC, 0xA1EC }, +{ 0xA1ED, 0xA1ED, 0xA1ED }, +{ 0xA1EE, 0xA1EE, 0xA1EE }, +{ 0xA1EF, 0xA1EF, 0xA1EF }, +{ 0xA1F0, 0xA1F0, 0xA1F0 }, +{ 0xA1F1, 0xA1F1, 0xA1F1 }, +{ 0xA1F2, 0xA1F2, 0xA1F2 }, +{ 0xA1F3, 0xA1F3, 0xA1F3 }, +{ 0xA1F4, 0xA1F4, 0xA1F4 }, +{ 0xA1F5, 0xA1F5, 0xA1F5 }, +{ 0xA1F6, 0xA1F6, 0xA1F6 }, +{ 0xA1F7, 0xA1F7, 0xA1F7 }, +{ 0xA1F8, 0xA1F8, 0xA1F8 }, +{ 0xA1F9, 0xA1F9, 0xA1F9 }, +{ 0xA1FA, 0xA1FA, 0xA1FA }, +{ 0xA1FB, 0xA1FB, 0xA1FB }, +{ 0xA1FC, 0xA1FC, 0xA1FC }, +{ 0xA1FD, 0xA1FD, 0xA1FD }, +{ 0xA1FE, 0xA1FE, 0xA1FE }, +{ 0xA1FF, 0xA1FF, 0xA1FF }, +{ 0xA200, 0xA200, 0xA200 }, +{ 0xA201, 0xA201, 0xA201 }, +{ 0xA202, 0xA202, 0xA202 }, +{ 0xA203, 0xA203, 0xA203 }, +{ 0xA204, 0xA204, 0xA204 }, +{ 0xA205, 0xA205, 0xA205 }, +{ 0xA206, 0xA206, 0xA206 }, +{ 0xA207, 0xA207, 0xA207 }, +{ 0xA208, 0xA208, 0xA208 }, +{ 0xA209, 0xA209, 0xA209 }, +{ 0xA20A, 0xA20A, 0xA20A }, +{ 0xA20B, 0xA20B, 0xA20B }, +{ 0xA20C, 0xA20C, 0xA20C }, +{ 0xA20D, 0xA20D, 0xA20D }, +{ 0xA20E, 0xA20E, 0xA20E }, +{ 0xA20F, 0xA20F, 0xA20F }, +{ 0xA210, 0xA210, 0xA210 }, +{ 0xA211, 0xA211, 0xA211 }, +{ 0xA212, 0xA212, 0xA212 }, +{ 0xA213, 0xA213, 0xA213 }, +{ 0xA214, 0xA214, 0xA214 }, +{ 0xA215, 0xA215, 0xA215 }, +{ 0xA216, 0xA216, 0xA216 }, +{ 0xA217, 0xA217, 0xA217 }, +{ 0xA218, 0xA218, 0xA218 }, +{ 0xA219, 0xA219, 0xA219 }, +{ 0xA21A, 0xA21A, 0xA21A }, +{ 0xA21B, 0xA21B, 0xA21B }, +{ 0xA21C, 0xA21C, 0xA21C }, +{ 0xA21D, 0xA21D, 0xA21D }, +{ 0xA21E, 0xA21E, 0xA21E }, +{ 0xA21F, 0xA21F, 0xA21F }, +{ 0xA220, 0xA220, 0xA220 }, +{ 0xA221, 0xA221, 0xA221 }, +{ 0xA222, 0xA222, 0xA222 }, +{ 0xA223, 0xA223, 0xA223 }, +{ 0xA224, 0xA224, 0xA224 }, +{ 0xA225, 0xA225, 0xA225 }, +{ 0xA226, 0xA226, 0xA226 }, +{ 0xA227, 0xA227, 0xA227 }, +{ 0xA228, 0xA228, 0xA228 }, +{ 0xA229, 0xA229, 0xA229 }, +{ 0xA22A, 0xA22A, 0xA22A }, +{ 0xA22B, 0xA22B, 0xA22B }, +{ 0xA22C, 0xA22C, 0xA22C }, +{ 0xA22D, 0xA22D, 0xA22D }, +{ 0xA22E, 0xA22E, 0xA22E }, +{ 0xA22F, 0xA22F, 0xA22F }, +{ 0xA230, 0xA230, 0xA230 }, +{ 0xA231, 0xA231, 0xA231 }, +{ 0xA232, 0xA232, 0xA232 }, +{ 0xA233, 0xA233, 0xA233 }, +{ 0xA234, 0xA234, 0xA234 }, +{ 0xA235, 0xA235, 0xA235 }, +{ 0xA236, 0xA236, 0xA236 }, +{ 0xA237, 0xA237, 0xA237 }, +{ 0xA238, 0xA238, 0xA238 }, +{ 0xA239, 0xA239, 0xA239 }, +{ 0xA23A, 0xA23A, 0xA23A }, +{ 0xA23B, 0xA23B, 0xA23B }, +{ 0xA23C, 0xA23C, 0xA23C }, +{ 0xA23D, 0xA23D, 0xA23D }, +{ 0xA23E, 0xA23E, 0xA23E }, +{ 0xA23F, 0xA23F, 0xA23F }, +{ 0xA240, 0xA240, 0xA240 }, +{ 0xA241, 0xA241, 0xA241 }, +{ 0xA242, 0xA242, 0xA242 }, +{ 0xA243, 0xA243, 0xA243 }, +{ 0xA244, 0xA244, 0xA244 }, +{ 0xA245, 0xA245, 0xA245 }, +{ 0xA246, 0xA246, 0xA246 }, +{ 0xA247, 0xA247, 0xA247 }, +{ 0xA248, 0xA248, 0xA248 }, +{ 0xA249, 0xA249, 0xA249 }, +{ 0xA24A, 0xA24A, 0xA24A }, +{ 0xA24B, 0xA24B, 0xA24B }, +{ 0xA24C, 0xA24C, 0xA24C }, +{ 0xA24D, 0xA24D, 0xA24D }, +{ 0xA24E, 0xA24E, 0xA24E }, +{ 0xA24F, 0xA24F, 0xA24F }, +{ 0xA250, 0xA250, 0xA250 }, +{ 0xA251, 0xA251, 0xA251 }, +{ 0xA252, 0xA252, 0xA252 }, +{ 0xA253, 0xA253, 0xA253 }, +{ 0xA254, 0xA254, 0xA254 }, +{ 0xA255, 0xA255, 0xA255 }, +{ 0xA256, 0xA256, 0xA256 }, +{ 0xA257, 0xA257, 0xA257 }, +{ 0xA258, 0xA258, 0xA258 }, +{ 0xA259, 0xA259, 0xA259 }, +{ 0xA25A, 0xA25A, 0xA25A }, +{ 0xA25B, 0xA25B, 0xA25B }, +{ 0xA25C, 0xA25C, 0xA25C }, +{ 0xA25D, 0xA25D, 0xA25D }, +{ 0xA25E, 0xA25E, 0xA25E }, +{ 0xA25F, 0xA25F, 0xA25F }, +{ 0xA260, 0xA260, 0xA260 }, +{ 0xA261, 0xA261, 0xA261 }, +{ 0xA262, 0xA262, 0xA262 }, +{ 0xA263, 0xA263, 0xA263 }, +{ 0xA264, 0xA264, 0xA264 }, +{ 0xA265, 0xA265, 0xA265 }, +{ 0xA266, 0xA266, 0xA266 }, +{ 0xA267, 0xA267, 0xA267 }, +{ 0xA268, 0xA268, 0xA268 }, +{ 0xA269, 0xA269, 0xA269 }, +{ 0xA26A, 0xA26A, 0xA26A }, +{ 0xA26B, 0xA26B, 0xA26B }, +{ 0xA26C, 0xA26C, 0xA26C }, +{ 0xA26D, 0xA26D, 0xA26D }, +{ 0xA26E, 0xA26E, 0xA26E }, +{ 0xA26F, 0xA26F, 0xA26F }, +{ 0xA270, 0xA270, 0xA270 }, +{ 0xA271, 0xA271, 0xA271 }, +{ 0xA272, 0xA272, 0xA272 }, +{ 0xA273, 0xA273, 0xA273 }, +{ 0xA274, 0xA274, 0xA274 }, +{ 0xA275, 0xA275, 0xA275 }, +{ 0xA276, 0xA276, 0xA276 }, +{ 0xA277, 0xA277, 0xA277 }, +{ 0xA278, 0xA278, 0xA278 }, +{ 0xA279, 0xA279, 0xA279 }, +{ 0xA27A, 0xA27A, 0xA27A }, +{ 0xA27B, 0xA27B, 0xA27B }, +{ 0xA27C, 0xA27C, 0xA27C }, +{ 0xA27D, 0xA27D, 0xA27D }, +{ 0xA27E, 0xA27E, 0xA27E }, +{ 0xA27F, 0xA27F, 0xA27F }, +{ 0xA280, 0xA280, 0xA280 }, +{ 0xA281, 0xA281, 0xA281 }, +{ 0xA282, 0xA282, 0xA282 }, +{ 0xA283, 0xA283, 0xA283 }, +{ 0xA284, 0xA284, 0xA284 }, +{ 0xA285, 0xA285, 0xA285 }, +{ 0xA286, 0xA286, 0xA286 }, +{ 0xA287, 0xA287, 0xA287 }, +{ 0xA288, 0xA288, 0xA288 }, +{ 0xA289, 0xA289, 0xA289 }, +{ 0xA28A, 0xA28A, 0xA28A }, +{ 0xA28B, 0xA28B, 0xA28B }, +{ 0xA28C, 0xA28C, 0xA28C }, +{ 0xA28D, 0xA28D, 0xA28D }, +{ 0xA28E, 0xA28E, 0xA28E }, +{ 0xA28F, 0xA28F, 0xA28F }, +{ 0xA290, 0xA290, 0xA290 }, +{ 0xA291, 0xA291, 0xA291 }, +{ 0xA292, 0xA292, 0xA292 }, +{ 0xA293, 0xA293, 0xA293 }, +{ 0xA294, 0xA294, 0xA294 }, +{ 0xA295, 0xA295, 0xA295 }, +{ 0xA296, 0xA296, 0xA296 }, +{ 0xA297, 0xA297, 0xA297 }, +{ 0xA298, 0xA298, 0xA298 }, +{ 0xA299, 0xA299, 0xA299 }, +{ 0xA29A, 0xA29A, 0xA29A }, +{ 0xA29B, 0xA29B, 0xA29B }, +{ 0xA29C, 0xA29C, 0xA29C }, +{ 0xA29D, 0xA29D, 0xA29D }, +{ 0xA29E, 0xA29E, 0xA29E }, +{ 0xA29F, 0xA29F, 0xA29F }, +{ 0xA2A0, 0xA2A0, 0xA2A0 }, +{ 0xA2A1, 0xA2A1, 0xA2A1 }, +{ 0xA2A2, 0xA2A2, 0xA2A2 }, +{ 0xA2A3, 0xA2A3, 0xA2A3 }, +{ 0xA2A4, 0xA2A4, 0xA2A4 }, +{ 0xA2A5, 0xA2A5, 0xA2A5 }, +{ 0xA2A6, 0xA2A6, 0xA2A6 }, +{ 0xA2A7, 0xA2A7, 0xA2A7 }, +{ 0xA2A8, 0xA2A8, 0xA2A8 }, +{ 0xA2A9, 0xA2A9, 0xA2A9 }, +{ 0xA2AA, 0xA2AA, 0xA2AA }, +{ 0xA2AB, 0xA2AB, 0xA2AB }, +{ 0xA2AC, 0xA2AC, 0xA2AC }, +{ 0xA2AD, 0xA2AD, 0xA2AD }, +{ 0xA2AE, 0xA2AE, 0xA2AE }, +{ 0xA2AF, 0xA2AF, 0xA2AF }, +{ 0xA2B0, 0xA2B0, 0xA2B0 }, +{ 0xA2B1, 0xA2B1, 0xA2B1 }, +{ 0xA2B2, 0xA2B2, 0xA2B2 }, +{ 0xA2B3, 0xA2B3, 0xA2B3 }, +{ 0xA2B4, 0xA2B4, 0xA2B4 }, +{ 0xA2B5, 0xA2B5, 0xA2B5 }, +{ 0xA2B6, 0xA2B6, 0xA2B6 }, +{ 0xA2B7, 0xA2B7, 0xA2B7 }, +{ 0xA2B8, 0xA2B8, 0xA2B8 }, +{ 0xA2B9, 0xA2B9, 0xA2B9 }, +{ 0xA2BA, 0xA2BA, 0xA2BA }, +{ 0xA2BB, 0xA2BB, 0xA2BB }, +{ 0xA2BC, 0xA2BC, 0xA2BC }, +{ 0xA2BD, 0xA2BD, 0xA2BD }, +{ 0xA2BE, 0xA2BE, 0xA2BE }, +{ 0xA2BF, 0xA2BF, 0xA2BF }, +{ 0xA2C0, 0xA2C0, 0xA2C0 }, +{ 0xA2C1, 0xA2C1, 0xA2C1 }, +{ 0xA2C2, 0xA2C2, 0xA2C2 }, +{ 0xA2C3, 0xA2C3, 0xA2C3 }, +{ 0xA2C4, 0xA2C4, 0xA2C4 }, +{ 0xA2C5, 0xA2C5, 0xA2C5 }, +{ 0xA2C6, 0xA2C6, 0xA2C6 }, +{ 0xA2C7, 0xA2C7, 0xA2C7 }, +{ 0xA2C8, 0xA2C8, 0xA2C8 }, +{ 0xA2C9, 0xA2C9, 0xA2C9 }, +{ 0xA2CA, 0xA2CA, 0xA2CA }, +{ 0xA2CB, 0xA2CB, 0xA2CB }, +{ 0xA2CC, 0xA2CC, 0xA2CC }, +{ 0xA2CD, 0xA2CD, 0xA2CD }, +{ 0xA2CE, 0xA2CE, 0xA2CE }, +{ 0xA2CF, 0xA2CF, 0xA2CF }, +{ 0xA2D0, 0xA2D0, 0xA2D0 }, +{ 0xA2D1, 0xA2D1, 0xA2D1 }, +{ 0xA2D2, 0xA2D2, 0xA2D2 }, +{ 0xA2D3, 0xA2D3, 0xA2D3 }, +{ 0xA2D4, 0xA2D4, 0xA2D4 }, +{ 0xA2D5, 0xA2D5, 0xA2D5 }, +{ 0xA2D6, 0xA2D6, 0xA2D6 }, +{ 0xA2D7, 0xA2D7, 0xA2D7 }, +{ 0xA2D8, 0xA2D8, 0xA2D8 }, +{ 0xA2D9, 0xA2D9, 0xA2D9 }, +{ 0xA2DA, 0xA2DA, 0xA2DA }, +{ 0xA2DB, 0xA2DB, 0xA2DB }, +{ 0xA2DC, 0xA2DC, 0xA2DC }, +{ 0xA2DD, 0xA2DD, 0xA2DD }, +{ 0xA2DE, 0xA2DE, 0xA2DE }, +{ 0xA2DF, 0xA2DF, 0xA2DF }, +{ 0xA2E0, 0xA2E0, 0xA2E0 }, +{ 0xA2E1, 0xA2E1, 0xA2E1 }, +{ 0xA2E2, 0xA2E2, 0xA2E2 }, +{ 0xA2E3, 0xA2E3, 0xA2E3 }, +{ 0xA2E4, 0xA2E4, 0xA2E4 }, +{ 0xA2E5, 0xA2E5, 0xA2E5 }, +{ 0xA2E6, 0xA2E6, 0xA2E6 }, +{ 0xA2E7, 0xA2E7, 0xA2E7 }, +{ 0xA2E8, 0xA2E8, 0xA2E8 }, +{ 0xA2E9, 0xA2E9, 0xA2E9 }, +{ 0xA2EA, 0xA2EA, 0xA2EA }, +{ 0xA2EB, 0xA2EB, 0xA2EB }, +{ 0xA2EC, 0xA2EC, 0xA2EC }, +{ 0xA2ED, 0xA2ED, 0xA2ED }, +{ 0xA2EE, 0xA2EE, 0xA2EE }, +{ 0xA2EF, 0xA2EF, 0xA2EF }, +{ 0xA2F0, 0xA2F0, 0xA2F0 }, +{ 0xA2F1, 0xA2F1, 0xA2F1 }, +{ 0xA2F2, 0xA2F2, 0xA2F2 }, +{ 0xA2F3, 0xA2F3, 0xA2F3 }, +{ 0xA2F4, 0xA2F4, 0xA2F4 }, +{ 0xA2F5, 0xA2F5, 0xA2F5 }, +{ 0xA2F6, 0xA2F6, 0xA2F6 }, +{ 0xA2F7, 0xA2F7, 0xA2F7 }, +{ 0xA2F8, 0xA2F8, 0xA2F8 }, +{ 0xA2F9, 0xA2F9, 0xA2F9 }, +{ 0xA2FA, 0xA2FA, 0xA2FA }, +{ 0xA2FB, 0xA2FB, 0xA2FB }, +{ 0xA2FC, 0xA2FC, 0xA2FC }, +{ 0xA2FD, 0xA2FD, 0xA2FD }, +{ 0xA2FE, 0xA2FE, 0xA2FE }, +{ 0xA2FF, 0xA2FF, 0xA2FF }, +{ 0xA300, 0xA300, 0xA300 }, +{ 0xA301, 0xA301, 0xA301 }, +{ 0xA302, 0xA302, 0xA302 }, +{ 0xA303, 0xA303, 0xA303 }, +{ 0xA304, 0xA304, 0xA304 }, +{ 0xA305, 0xA305, 0xA305 }, +{ 0xA306, 0xA306, 0xA306 }, +{ 0xA307, 0xA307, 0xA307 }, +{ 0xA308, 0xA308, 0xA308 }, +{ 0xA309, 0xA309, 0xA309 }, +{ 0xA30A, 0xA30A, 0xA30A }, +{ 0xA30B, 0xA30B, 0xA30B }, +{ 0xA30C, 0xA30C, 0xA30C }, +{ 0xA30D, 0xA30D, 0xA30D }, +{ 0xA30E, 0xA30E, 0xA30E }, +{ 0xA30F, 0xA30F, 0xA30F }, +{ 0xA310, 0xA310, 0xA310 }, +{ 0xA311, 0xA311, 0xA311 }, +{ 0xA312, 0xA312, 0xA312 }, +{ 0xA313, 0xA313, 0xA313 }, +{ 0xA314, 0xA314, 0xA314 }, +{ 0xA315, 0xA315, 0xA315 }, +{ 0xA316, 0xA316, 0xA316 }, +{ 0xA317, 0xA317, 0xA317 }, +{ 0xA318, 0xA318, 0xA318 }, +{ 0xA319, 0xA319, 0xA319 }, +{ 0xA31A, 0xA31A, 0xA31A }, +{ 0xA31B, 0xA31B, 0xA31B }, +{ 0xA31C, 0xA31C, 0xA31C }, +{ 0xA31D, 0xA31D, 0xA31D }, +{ 0xA31E, 0xA31E, 0xA31E }, +{ 0xA31F, 0xA31F, 0xA31F }, +{ 0xA320, 0xA320, 0xA320 }, +{ 0xA321, 0xA321, 0xA321 }, +{ 0xA322, 0xA322, 0xA322 }, +{ 0xA323, 0xA323, 0xA323 }, +{ 0xA324, 0xA324, 0xA324 }, +{ 0xA325, 0xA325, 0xA325 }, +{ 0xA326, 0xA326, 0xA326 }, +{ 0xA327, 0xA327, 0xA327 }, +{ 0xA328, 0xA328, 0xA328 }, +{ 0xA329, 0xA329, 0xA329 }, +{ 0xA32A, 0xA32A, 0xA32A }, +{ 0xA32B, 0xA32B, 0xA32B }, +{ 0xA32C, 0xA32C, 0xA32C }, +{ 0xA32D, 0xA32D, 0xA32D }, +{ 0xA32E, 0xA32E, 0xA32E }, +{ 0xA32F, 0xA32F, 0xA32F }, +{ 0xA330, 0xA330, 0xA330 }, +{ 0xA331, 0xA331, 0xA331 }, +{ 0xA332, 0xA332, 0xA332 }, +{ 0xA333, 0xA333, 0xA333 }, +{ 0xA334, 0xA334, 0xA334 }, +{ 0xA335, 0xA335, 0xA335 }, +{ 0xA336, 0xA336, 0xA336 }, +{ 0xA337, 0xA337, 0xA337 }, +{ 0xA338, 0xA338, 0xA338 }, +{ 0xA339, 0xA339, 0xA339 }, +{ 0xA33A, 0xA33A, 0xA33A }, +{ 0xA33B, 0xA33B, 0xA33B }, +{ 0xA33C, 0xA33C, 0xA33C }, +{ 0xA33D, 0xA33D, 0xA33D }, +{ 0xA33E, 0xA33E, 0xA33E }, +{ 0xA33F, 0xA33F, 0xA33F }, +{ 0xA340, 0xA340, 0xA340 }, +{ 0xA341, 0xA341, 0xA341 }, +{ 0xA342, 0xA342, 0xA342 }, +{ 0xA343, 0xA343, 0xA343 }, +{ 0xA344, 0xA344, 0xA344 }, +{ 0xA345, 0xA345, 0xA345 }, +{ 0xA346, 0xA346, 0xA346 }, +{ 0xA347, 0xA347, 0xA347 }, +{ 0xA348, 0xA348, 0xA348 }, +{ 0xA349, 0xA349, 0xA349 }, +{ 0xA34A, 0xA34A, 0xA34A }, +{ 0xA34B, 0xA34B, 0xA34B }, +{ 0xA34C, 0xA34C, 0xA34C }, +{ 0xA34D, 0xA34D, 0xA34D }, +{ 0xA34E, 0xA34E, 0xA34E }, +{ 0xA34F, 0xA34F, 0xA34F }, +{ 0xA350, 0xA350, 0xA350 }, +{ 0xA351, 0xA351, 0xA351 }, +{ 0xA352, 0xA352, 0xA352 }, +{ 0xA353, 0xA353, 0xA353 }, +{ 0xA354, 0xA354, 0xA354 }, +{ 0xA355, 0xA355, 0xA355 }, +{ 0xA356, 0xA356, 0xA356 }, +{ 0xA357, 0xA357, 0xA357 }, +{ 0xA358, 0xA358, 0xA358 }, +{ 0xA359, 0xA359, 0xA359 }, +{ 0xA35A, 0xA35A, 0xA35A }, +{ 0xA35B, 0xA35B, 0xA35B }, +{ 0xA35C, 0xA35C, 0xA35C }, +{ 0xA35D, 0xA35D, 0xA35D }, +{ 0xA35E, 0xA35E, 0xA35E }, +{ 0xA35F, 0xA35F, 0xA35F }, +{ 0xA360, 0xA360, 0xA360 }, +{ 0xA361, 0xA361, 0xA361 }, +{ 0xA362, 0xA362, 0xA362 }, +{ 0xA363, 0xA363, 0xA363 }, +{ 0xA364, 0xA364, 0xA364 }, +{ 0xA365, 0xA365, 0xA365 }, +{ 0xA366, 0xA366, 0xA366 }, +{ 0xA367, 0xA367, 0xA367 }, +{ 0xA368, 0xA368, 0xA368 }, +{ 0xA369, 0xA369, 0xA369 }, +{ 0xA36A, 0xA36A, 0xA36A }, +{ 0xA36B, 0xA36B, 0xA36B }, +{ 0xA36C, 0xA36C, 0xA36C }, +{ 0xA36D, 0xA36D, 0xA36D }, +{ 0xA36E, 0xA36E, 0xA36E }, +{ 0xA36F, 0xA36F, 0xA36F }, +{ 0xA370, 0xA370, 0xA370 }, +{ 0xA371, 0xA371, 0xA371 }, +{ 0xA372, 0xA372, 0xA372 }, +{ 0xA373, 0xA373, 0xA373 }, +{ 0xA374, 0xA374, 0xA374 }, +{ 0xA375, 0xA375, 0xA375 }, +{ 0xA376, 0xA376, 0xA376 }, +{ 0xA377, 0xA377, 0xA377 }, +{ 0xA378, 0xA378, 0xA378 }, +{ 0xA379, 0xA379, 0xA379 }, +{ 0xA37A, 0xA37A, 0xA37A }, +{ 0xA37B, 0xA37B, 0xA37B }, +{ 0xA37C, 0xA37C, 0xA37C }, +{ 0xA37D, 0xA37D, 0xA37D }, +{ 0xA37E, 0xA37E, 0xA37E }, +{ 0xA37F, 0xA37F, 0xA37F }, +{ 0xA380, 0xA380, 0xA380 }, +{ 0xA381, 0xA381, 0xA381 }, +{ 0xA382, 0xA382, 0xA382 }, +{ 0xA383, 0xA383, 0xA383 }, +{ 0xA384, 0xA384, 0xA384 }, +{ 0xA385, 0xA385, 0xA385 }, +{ 0xA386, 0xA386, 0xA386 }, +{ 0xA387, 0xA387, 0xA387 }, +{ 0xA388, 0xA388, 0xA388 }, +{ 0xA389, 0xA389, 0xA389 }, +{ 0xA38A, 0xA38A, 0xA38A }, +{ 0xA38B, 0xA38B, 0xA38B }, +{ 0xA38C, 0xA38C, 0xA38C }, +{ 0xA38D, 0xA38D, 0xA38D }, +{ 0xA38E, 0xA38E, 0xA38E }, +{ 0xA38F, 0xA38F, 0xA38F }, +{ 0xA390, 0xA390, 0xA390 }, +{ 0xA391, 0xA391, 0xA391 }, +{ 0xA392, 0xA392, 0xA392 }, +{ 0xA393, 0xA393, 0xA393 }, +{ 0xA394, 0xA394, 0xA394 }, +{ 0xA395, 0xA395, 0xA395 }, +{ 0xA396, 0xA396, 0xA396 }, +{ 0xA397, 0xA397, 0xA397 }, +{ 0xA398, 0xA398, 0xA398 }, +{ 0xA399, 0xA399, 0xA399 }, +{ 0xA39A, 0xA39A, 0xA39A }, +{ 0xA39B, 0xA39B, 0xA39B }, +{ 0xA39C, 0xA39C, 0xA39C }, +{ 0xA39D, 0xA39D, 0xA39D }, +{ 0xA39E, 0xA39E, 0xA39E }, +{ 0xA39F, 0xA39F, 0xA39F }, +{ 0xA3A0, 0xA3A0, 0xA3A0 }, +{ 0xA3A1, 0xA3A1, 0xA3A1 }, +{ 0xA3A2, 0xA3A2, 0xA3A2 }, +{ 0xA3A3, 0xA3A3, 0xA3A3 }, +{ 0xA3A4, 0xA3A4, 0xA3A4 }, +{ 0xA3A5, 0xA3A5, 0xA3A5 }, +{ 0xA3A6, 0xA3A6, 0xA3A6 }, +{ 0xA3A7, 0xA3A7, 0xA3A7 }, +{ 0xA3A8, 0xA3A8, 0xA3A8 }, +{ 0xA3A9, 0xA3A9, 0xA3A9 }, +{ 0xA3AA, 0xA3AA, 0xA3AA }, +{ 0xA3AB, 0xA3AB, 0xA3AB }, +{ 0xA3AC, 0xA3AC, 0xA3AC }, +{ 0xA3AD, 0xA3AD, 0xA3AD }, +{ 0xA3AE, 0xA3AE, 0xA3AE }, +{ 0xA3AF, 0xA3AF, 0xA3AF }, +{ 0xA3B0, 0xA3B0, 0xA3B0 }, +{ 0xA3B1, 0xA3B1, 0xA3B1 }, +{ 0xA3B2, 0xA3B2, 0xA3B2 }, +{ 0xA3B3, 0xA3B3, 0xA3B3 }, +{ 0xA3B4, 0xA3B4, 0xA3B4 }, +{ 0xA3B5, 0xA3B5, 0xA3B5 }, +{ 0xA3B6, 0xA3B6, 0xA3B6 }, +{ 0xA3B7, 0xA3B7, 0xA3B7 }, +{ 0xA3B8, 0xA3B8, 0xA3B8 }, +{ 0xA3B9, 0xA3B9, 0xA3B9 }, +{ 0xA3BA, 0xA3BA, 0xA3BA }, +{ 0xA3BB, 0xA3BB, 0xA3BB }, +{ 0xA3BC, 0xA3BC, 0xA3BC }, +{ 0xA3BD, 0xA3BD, 0xA3BD }, +{ 0xA3BE, 0xA3BE, 0xA3BE }, +{ 0xA3BF, 0xA3BF, 0xA3BF }, +{ 0xA3C0, 0xA3C0, 0xA3C0 }, +{ 0xA3C1, 0xA3C1, 0xA3C1 }, +{ 0xA3C2, 0xA3C2, 0xA3C2 }, +{ 0xA3C3, 0xA3C3, 0xA3C3 }, +{ 0xA3C4, 0xA3C4, 0xA3C4 }, +{ 0xA3C5, 0xA3C5, 0xA3C5 }, +{ 0xA3C6, 0xA3C6, 0xA3C6 }, +{ 0xA3C7, 0xA3C7, 0xA3C7 }, +{ 0xA3C8, 0xA3C8, 0xA3C8 }, +{ 0xA3C9, 0xA3C9, 0xA3C9 }, +{ 0xA3CA, 0xA3CA, 0xA3CA }, +{ 0xA3CB, 0xA3CB, 0xA3CB }, +{ 0xA3CC, 0xA3CC, 0xA3CC }, +{ 0xA3CD, 0xA3CD, 0xA3CD }, +{ 0xA3CE, 0xA3CE, 0xA3CE }, +{ 0xA3CF, 0xA3CF, 0xA3CF }, +{ 0xA3D0, 0xA3D0, 0xA3D0 }, +{ 0xA3D1, 0xA3D1, 0xA3D1 }, +{ 0xA3D2, 0xA3D2, 0xA3D2 }, +{ 0xA3D3, 0xA3D3, 0xA3D3 }, +{ 0xA3D4, 0xA3D4, 0xA3D4 }, +{ 0xA3D5, 0xA3D5, 0xA3D5 }, +{ 0xA3D6, 0xA3D6, 0xA3D6 }, +{ 0xA3D7, 0xA3D7, 0xA3D7 }, +{ 0xA3D8, 0xA3D8, 0xA3D8 }, +{ 0xA3D9, 0xA3D9, 0xA3D9 }, +{ 0xA3DA, 0xA3DA, 0xA3DA }, +{ 0xA3DB, 0xA3DB, 0xA3DB }, +{ 0xA3DC, 0xA3DC, 0xA3DC }, +{ 0xA3DD, 0xA3DD, 0xA3DD }, +{ 0xA3DE, 0xA3DE, 0xA3DE }, +{ 0xA3DF, 0xA3DF, 0xA3DF }, +{ 0xA3E0, 0xA3E0, 0xA3E0 }, +{ 0xA3E1, 0xA3E1, 0xA3E1 }, +{ 0xA3E2, 0xA3E2, 0xA3E2 }, +{ 0xA3E3, 0xA3E3, 0xA3E3 }, +{ 0xA3E4, 0xA3E4, 0xA3E4 }, +{ 0xA3E5, 0xA3E5, 0xA3E5 }, +{ 0xA3E6, 0xA3E6, 0xA3E6 }, +{ 0xA3E7, 0xA3E7, 0xA3E7 }, +{ 0xA3E8, 0xA3E8, 0xA3E8 }, +{ 0xA3E9, 0xA3E9, 0xA3E9 }, +{ 0xA3EA, 0xA3EA, 0xA3EA }, +{ 0xA3EB, 0xA3EB, 0xA3EB }, +{ 0xA3EC, 0xA3EC, 0xA3EC }, +{ 0xA3ED, 0xA3ED, 0xA3ED }, +{ 0xA3EE, 0xA3EE, 0xA3EE }, +{ 0xA3EF, 0xA3EF, 0xA3EF }, +{ 0xA3F0, 0xA3F0, 0xA3F0 }, +{ 0xA3F1, 0xA3F1, 0xA3F1 }, +{ 0xA3F2, 0xA3F2, 0xA3F2 }, +{ 0xA3F3, 0xA3F3, 0xA3F3 }, +{ 0xA3F4, 0xA3F4, 0xA3F4 }, +{ 0xA3F5, 0xA3F5, 0xA3F5 }, +{ 0xA3F6, 0xA3F6, 0xA3F6 }, +{ 0xA3F7, 0xA3F7, 0xA3F7 }, +{ 0xA3F8, 0xA3F8, 0xA3F8 }, +{ 0xA3F9, 0xA3F9, 0xA3F9 }, +{ 0xA3FA, 0xA3FA, 0xA3FA }, +{ 0xA3FB, 0xA3FB, 0xA3FB }, +{ 0xA3FC, 0xA3FC, 0xA3FC }, +{ 0xA3FD, 0xA3FD, 0xA3FD }, +{ 0xA3FE, 0xA3FE, 0xA3FE }, +{ 0xA3FF, 0xA3FF, 0xA3FF }, +{ 0xA400, 0xA400, 0xA400 }, +{ 0xA401, 0xA401, 0xA401 }, +{ 0xA402, 0xA402, 0xA402 }, +{ 0xA403, 0xA403, 0xA403 }, +{ 0xA404, 0xA404, 0xA404 }, +{ 0xA405, 0xA405, 0xA405 }, +{ 0xA406, 0xA406, 0xA406 }, +{ 0xA407, 0xA407, 0xA407 }, +{ 0xA408, 0xA408, 0xA408 }, +{ 0xA409, 0xA409, 0xA409 }, +{ 0xA40A, 0xA40A, 0xA40A }, +{ 0xA40B, 0xA40B, 0xA40B }, +{ 0xA40C, 0xA40C, 0xA40C }, +{ 0xA40D, 0xA40D, 0xA40D }, +{ 0xA40E, 0xA40E, 0xA40E }, +{ 0xA40F, 0xA40F, 0xA40F }, +{ 0xA410, 0xA410, 0xA410 }, +{ 0xA411, 0xA411, 0xA411 }, +{ 0xA412, 0xA412, 0xA412 }, +{ 0xA413, 0xA413, 0xA413 }, +{ 0xA414, 0xA414, 0xA414 }, +{ 0xA415, 0xA415, 0xA415 }, +{ 0xA416, 0xA416, 0xA416 }, +{ 0xA417, 0xA417, 0xA417 }, +{ 0xA418, 0xA418, 0xA418 }, +{ 0xA419, 0xA419, 0xA419 }, +{ 0xA41A, 0xA41A, 0xA41A }, +{ 0xA41B, 0xA41B, 0xA41B }, +{ 0xA41C, 0xA41C, 0xA41C }, +{ 0xA41D, 0xA41D, 0xA41D }, +{ 0xA41E, 0xA41E, 0xA41E }, +{ 0xA41F, 0xA41F, 0xA41F }, +{ 0xA420, 0xA420, 0xA420 }, +{ 0xA421, 0xA421, 0xA421 }, +{ 0xA422, 0xA422, 0xA422 }, +{ 0xA423, 0xA423, 0xA423 }, +{ 0xA424, 0xA424, 0xA424 }, +{ 0xA425, 0xA425, 0xA425 }, +{ 0xA426, 0xA426, 0xA426 }, +{ 0xA427, 0xA427, 0xA427 }, +{ 0xA428, 0xA428, 0xA428 }, +{ 0xA429, 0xA429, 0xA429 }, +{ 0xA42A, 0xA42A, 0xA42A }, +{ 0xA42B, 0xA42B, 0xA42B }, +{ 0xA42C, 0xA42C, 0xA42C }, +{ 0xA42D, 0xA42D, 0xA42D }, +{ 0xA42E, 0xA42E, 0xA42E }, +{ 0xA42F, 0xA42F, 0xA42F }, +{ 0xA430, 0xA430, 0xA430 }, +{ 0xA431, 0xA431, 0xA431 }, +{ 0xA432, 0xA432, 0xA432 }, +{ 0xA433, 0xA433, 0xA433 }, +{ 0xA434, 0xA434, 0xA434 }, +{ 0xA435, 0xA435, 0xA435 }, +{ 0xA436, 0xA436, 0xA436 }, +{ 0xA437, 0xA437, 0xA437 }, +{ 0xA438, 0xA438, 0xA438 }, +{ 0xA439, 0xA439, 0xA439 }, +{ 0xA43A, 0xA43A, 0xA43A }, +{ 0xA43B, 0xA43B, 0xA43B }, +{ 0xA43C, 0xA43C, 0xA43C }, +{ 0xA43D, 0xA43D, 0xA43D }, +{ 0xA43E, 0xA43E, 0xA43E }, +{ 0xA43F, 0xA43F, 0xA43F }, +{ 0xA440, 0xA440, 0xA440 }, +{ 0xA441, 0xA441, 0xA441 }, +{ 0xA442, 0xA442, 0xA442 }, +{ 0xA443, 0xA443, 0xA443 }, +{ 0xA444, 0xA444, 0xA444 }, +{ 0xA445, 0xA445, 0xA445 }, +{ 0xA446, 0xA446, 0xA446 }, +{ 0xA447, 0xA447, 0xA447 }, +{ 0xA448, 0xA448, 0xA448 }, +{ 0xA449, 0xA449, 0xA449 }, +{ 0xA44A, 0xA44A, 0xA44A }, +{ 0xA44B, 0xA44B, 0xA44B }, +{ 0xA44C, 0xA44C, 0xA44C }, +{ 0xA44D, 0xA44D, 0xA44D }, +{ 0xA44E, 0xA44E, 0xA44E }, +{ 0xA44F, 0xA44F, 0xA44F }, +{ 0xA450, 0xA450, 0xA450 }, +{ 0xA451, 0xA451, 0xA451 }, +{ 0xA452, 0xA452, 0xA452 }, +{ 0xA453, 0xA453, 0xA453 }, +{ 0xA454, 0xA454, 0xA454 }, +{ 0xA455, 0xA455, 0xA455 }, +{ 0xA456, 0xA456, 0xA456 }, +{ 0xA457, 0xA457, 0xA457 }, +{ 0xA458, 0xA458, 0xA458 }, +{ 0xA459, 0xA459, 0xA459 }, +{ 0xA45A, 0xA45A, 0xA45A }, +{ 0xA45B, 0xA45B, 0xA45B }, +{ 0xA45C, 0xA45C, 0xA45C }, +{ 0xA45D, 0xA45D, 0xA45D }, +{ 0xA45E, 0xA45E, 0xA45E }, +{ 0xA45F, 0xA45F, 0xA45F }, +{ 0xA460, 0xA460, 0xA460 }, +{ 0xA461, 0xA461, 0xA461 }, +{ 0xA462, 0xA462, 0xA462 }, +{ 0xA463, 0xA463, 0xA463 }, +{ 0xA464, 0xA464, 0xA464 }, +{ 0xA465, 0xA465, 0xA465 }, +{ 0xA466, 0xA466, 0xA466 }, +{ 0xA467, 0xA467, 0xA467 }, +{ 0xA468, 0xA468, 0xA468 }, +{ 0xA469, 0xA469, 0xA469 }, +{ 0xA46A, 0xA46A, 0xA46A }, +{ 0xA46B, 0xA46B, 0xA46B }, +{ 0xA46C, 0xA46C, 0xA46C }, +{ 0xA46D, 0xA46D, 0xA46D }, +{ 0xA46E, 0xA46E, 0xA46E }, +{ 0xA46F, 0xA46F, 0xA46F }, +{ 0xA470, 0xA470, 0xA470 }, +{ 0xA471, 0xA471, 0xA471 }, +{ 0xA472, 0xA472, 0xA472 }, +{ 0xA473, 0xA473, 0xA473 }, +{ 0xA474, 0xA474, 0xA474 }, +{ 0xA475, 0xA475, 0xA475 }, +{ 0xA476, 0xA476, 0xA476 }, +{ 0xA477, 0xA477, 0xA477 }, +{ 0xA478, 0xA478, 0xA478 }, +{ 0xA479, 0xA479, 0xA479 }, +{ 0xA47A, 0xA47A, 0xA47A }, +{ 0xA47B, 0xA47B, 0xA47B }, +{ 0xA47C, 0xA47C, 0xA47C }, +{ 0xA47D, 0xA47D, 0xA47D }, +{ 0xA47E, 0xA47E, 0xA47E }, +{ 0xA47F, 0xA47F, 0xA47F }, +{ 0xA480, 0xA480, 0xA480 }, +{ 0xA481, 0xA481, 0xA481 }, +{ 0xA482, 0xA482, 0xA482 }, +{ 0xA483, 0xA483, 0xA483 }, +{ 0xA484, 0xA484, 0xA484 }, +{ 0xA485, 0xA485, 0xA485 }, +{ 0xA486, 0xA486, 0xA486 }, +{ 0xA487, 0xA487, 0xA487 }, +{ 0xA488, 0xA488, 0xA488 }, +{ 0xA489, 0xA489, 0xA489 }, +{ 0xA48A, 0xA48A, 0xA48A }, +{ 0xA48B, 0xA48B, 0xA48B }, +{ 0xA48C, 0xA48C, 0xA48C }, +{ 0xA800, 0xA800, 0xA800 }, +{ 0xA801, 0xA801, 0xA801 }, +{ 0xA803, 0xA803, 0xA803 }, +{ 0xA804, 0xA804, 0xA804 }, +{ 0xA805, 0xA805, 0xA805 }, +{ 0xA806, 0xA806, 0xA806 }, +{ 0xA807, 0xA807, 0xA807 }, +{ 0xA808, 0xA808, 0xA808 }, +{ 0xA809, 0xA809, 0xA809 }, +{ 0xA80A, 0xA80A, 0xA80A }, +{ 0xA80B, 0xA80B, 0xA80B }, +{ 0xA80C, 0xA80C, 0xA80C }, +{ 0xA80D, 0xA80D, 0xA80D }, +{ 0xA80E, 0xA80E, 0xA80E }, +{ 0xA80F, 0xA80F, 0xA80F }, +{ 0xA810, 0xA810, 0xA810 }, +{ 0xA811, 0xA811, 0xA811 }, +{ 0xA812, 0xA812, 0xA812 }, +{ 0xA813, 0xA813, 0xA813 }, +{ 0xA814, 0xA814, 0xA814 }, +{ 0xA815, 0xA815, 0xA815 }, +{ 0xA816, 0xA816, 0xA816 }, +{ 0xA817, 0xA817, 0xA817 }, +{ 0xA818, 0xA818, 0xA818 }, +{ 0xA819, 0xA819, 0xA819 }, +{ 0xA81A, 0xA81A, 0xA81A }, +{ 0xA81B, 0xA81B, 0xA81B }, +{ 0xA81C, 0xA81C, 0xA81C }, +{ 0xA81D, 0xA81D, 0xA81D }, +{ 0xA81E, 0xA81E, 0xA81E }, +{ 0xA81F, 0xA81F, 0xA81F }, +{ 0xA820, 0xA820, 0xA820 }, +{ 0xA821, 0xA821, 0xA821 }, +{ 0xA822, 0xA822, 0xA822 }, +{ 0xA825, 0xA825, 0xA825 }, +{ 0xA826, 0xA826, 0xA826 }, +{ 0xAC00, 0xAC00, 0xAC00 }, +{ 0xD7A3, 0xD7A3, 0xD7A3 }, +{ 0xF900, 0xF900, 0xF900 }, +{ 0xF901, 0xF901, 0xF901 }, +{ 0xF902, 0xF902, 0xF902 }, +{ 0xF903, 0xF903, 0xF903 }, +{ 0xF904, 0xF904, 0xF904 }, +{ 0xF905, 0xF905, 0xF905 }, +{ 0xF906, 0xF906, 0xF906 }, +{ 0xF907, 0xF907, 0xF907 }, +{ 0xF908, 0xF908, 0xF908 }, +{ 0xF909, 0xF909, 0xF909 }, +{ 0xF90A, 0xF90A, 0xF90A }, +{ 0xF90B, 0xF90B, 0xF90B }, +{ 0xF90C, 0xF90C, 0xF90C }, +{ 0xF90D, 0xF90D, 0xF90D }, +{ 0xF90E, 0xF90E, 0xF90E }, +{ 0xF90F, 0xF90F, 0xF90F }, +{ 0xF910, 0xF910, 0xF910 }, +{ 0xF911, 0xF911, 0xF911 }, +{ 0xF912, 0xF912, 0xF912 }, +{ 0xF913, 0xF913, 0xF913 }, +{ 0xF914, 0xF914, 0xF914 }, +{ 0xF915, 0xF915, 0xF915 }, +{ 0xF916, 0xF916, 0xF916 }, +{ 0xF917, 0xF917, 0xF917 }, +{ 0xF918, 0xF918, 0xF918 }, +{ 0xF919, 0xF919, 0xF919 }, +{ 0xF91A, 0xF91A, 0xF91A }, +{ 0xF91B, 0xF91B, 0xF91B }, +{ 0xF91C, 0xF91C, 0xF91C }, +{ 0xF91D, 0xF91D, 0xF91D }, +{ 0xF91E, 0xF91E, 0xF91E }, +{ 0xF91F, 0xF91F, 0xF91F }, +{ 0xF920, 0xF920, 0xF920 }, +{ 0xF921, 0xF921, 0xF921 }, +{ 0xF922, 0xF922, 0xF922 }, +{ 0xF923, 0xF923, 0xF923 }, +{ 0xF924, 0xF924, 0xF924 }, +{ 0xF925, 0xF925, 0xF925 }, +{ 0xF926, 0xF926, 0xF926 }, +{ 0xF927, 0xF927, 0xF927 }, +{ 0xF928, 0xF928, 0xF928 }, +{ 0xF929, 0xF929, 0xF929 }, +{ 0xF92A, 0xF92A, 0xF92A }, +{ 0xF92B, 0xF92B, 0xF92B }, +{ 0xF92C, 0xF92C, 0xF92C }, +{ 0xF92D, 0xF92D, 0xF92D }, +{ 0xF92E, 0xF92E, 0xF92E }, +{ 0xF92F, 0xF92F, 0xF92F }, +{ 0xF930, 0xF930, 0xF930 }, +{ 0xF931, 0xF931, 0xF931 }, +{ 0xF932, 0xF932, 0xF932 }, +{ 0xF933, 0xF933, 0xF933 }, +{ 0xF934, 0xF934, 0xF934 }, +{ 0xF935, 0xF935, 0xF935 }, +{ 0xF936, 0xF936, 0xF936 }, +{ 0xF937, 0xF937, 0xF937 }, +{ 0xF938, 0xF938, 0xF938 }, +{ 0xF939, 0xF939, 0xF939 }, +{ 0xF93A, 0xF93A, 0xF93A }, +{ 0xF93B, 0xF93B, 0xF93B }, +{ 0xF93C, 0xF93C, 0xF93C }, +{ 0xF93D, 0xF93D, 0xF93D }, +{ 0xF93E, 0xF93E, 0xF93E }, +{ 0xF93F, 0xF93F, 0xF93F }, +{ 0xF940, 0xF940, 0xF940 }, +{ 0xF941, 0xF941, 0xF941 }, +{ 0xF942, 0xF942, 0xF942 }, +{ 0xF943, 0xF943, 0xF943 }, +{ 0xF944, 0xF944, 0xF944 }, +{ 0xF945, 0xF945, 0xF945 }, +{ 0xF946, 0xF946, 0xF946 }, +{ 0xF947, 0xF947, 0xF947 }, +{ 0xF948, 0xF948, 0xF948 }, +{ 0xF949, 0xF949, 0xF949 }, +{ 0xF94A, 0xF94A, 0xF94A }, +{ 0xF94B, 0xF94B, 0xF94B }, +{ 0xF94C, 0xF94C, 0xF94C }, +{ 0xF94D, 0xF94D, 0xF94D }, +{ 0xF94E, 0xF94E, 0xF94E }, +{ 0xF94F, 0xF94F, 0xF94F }, +{ 0xF950, 0xF950, 0xF950 }, +{ 0xF951, 0xF951, 0xF951 }, +{ 0xF952, 0xF952, 0xF952 }, +{ 0xF953, 0xF953, 0xF953 }, +{ 0xF954, 0xF954, 0xF954 }, +{ 0xF955, 0xF955, 0xF955 }, +{ 0xF956, 0xF956, 0xF956 }, +{ 0xF957, 0xF957, 0xF957 }, +{ 0xF958, 0xF958, 0xF958 }, +{ 0xF959, 0xF959, 0xF959 }, +{ 0xF95A, 0xF95A, 0xF95A }, +{ 0xF95B, 0xF95B, 0xF95B }, +{ 0xF95C, 0xF95C, 0xF95C }, +{ 0xF95D, 0xF95D, 0xF95D }, +{ 0xF95E, 0xF95E, 0xF95E }, +{ 0xF95F, 0xF95F, 0xF95F }, +{ 0xF960, 0xF960, 0xF960 }, +{ 0xF961, 0xF961, 0xF961 }, +{ 0xF962, 0xF962, 0xF962 }, +{ 0xF963, 0xF963, 0xF963 }, +{ 0xF964, 0xF964, 0xF964 }, +{ 0xF965, 0xF965, 0xF965 }, +{ 0xF966, 0xF966, 0xF966 }, +{ 0xF967, 0xF967, 0xF967 }, +{ 0xF968, 0xF968, 0xF968 }, +{ 0xF969, 0xF969, 0xF969 }, +{ 0xF96A, 0xF96A, 0xF96A }, +{ 0xF96B, 0xF96B, 0xF96B }, +{ 0xF96C, 0xF96C, 0xF96C }, +{ 0xF96D, 0xF96D, 0xF96D }, +{ 0xF96E, 0xF96E, 0xF96E }, +{ 0xF96F, 0xF96F, 0xF96F }, +{ 0xF970, 0xF970, 0xF970 }, +{ 0xF971, 0xF971, 0xF971 }, +{ 0xF972, 0xF972, 0xF972 }, +{ 0xF973, 0xF973, 0xF973 }, +{ 0xF974, 0xF974, 0xF974 }, +{ 0xF975, 0xF975, 0xF975 }, +{ 0xF976, 0xF976, 0xF976 }, +{ 0xF977, 0xF977, 0xF977 }, +{ 0xF978, 0xF978, 0xF978 }, +{ 0xF979, 0xF979, 0xF979 }, +{ 0xF97A, 0xF97A, 0xF97A }, +{ 0xF97B, 0xF97B, 0xF97B }, +{ 0xF97C, 0xF97C, 0xF97C }, +{ 0xF97D, 0xF97D, 0xF97D }, +{ 0xF97E, 0xF97E, 0xF97E }, +{ 0xF97F, 0xF97F, 0xF97F }, +{ 0xF980, 0xF980, 0xF980 }, +{ 0xF981, 0xF981, 0xF981 }, +{ 0xF982, 0xF982, 0xF982 }, +{ 0xF983, 0xF983, 0xF983 }, +{ 0xF984, 0xF984, 0xF984 }, +{ 0xF985, 0xF985, 0xF985 }, +{ 0xF986, 0xF986, 0xF986 }, +{ 0xF987, 0xF987, 0xF987 }, +{ 0xF988, 0xF988, 0xF988 }, +{ 0xF989, 0xF989, 0xF989 }, +{ 0xF98A, 0xF98A, 0xF98A }, +{ 0xF98B, 0xF98B, 0xF98B }, +{ 0xF98C, 0xF98C, 0xF98C }, +{ 0xF98D, 0xF98D, 0xF98D }, +{ 0xF98E, 0xF98E, 0xF98E }, +{ 0xF98F, 0xF98F, 0xF98F }, +{ 0xF990, 0xF990, 0xF990 }, +{ 0xF991, 0xF991, 0xF991 }, +{ 0xF992, 0xF992, 0xF992 }, +{ 0xF993, 0xF993, 0xF993 }, +{ 0xF994, 0xF994, 0xF994 }, +{ 0xF995, 0xF995, 0xF995 }, +{ 0xF996, 0xF996, 0xF996 }, +{ 0xF997, 0xF997, 0xF997 }, +{ 0xF998, 0xF998, 0xF998 }, +{ 0xF999, 0xF999, 0xF999 }, +{ 0xF99A, 0xF99A, 0xF99A }, +{ 0xF99B, 0xF99B, 0xF99B }, +{ 0xF99C, 0xF99C, 0xF99C }, +{ 0xF99D, 0xF99D, 0xF99D }, +{ 0xF99E, 0xF99E, 0xF99E }, +{ 0xF99F, 0xF99F, 0xF99F }, +{ 0xF9A0, 0xF9A0, 0xF9A0 }, +{ 0xF9A1, 0xF9A1, 0xF9A1 }, +{ 0xF9A2, 0xF9A2, 0xF9A2 }, +{ 0xF9A3, 0xF9A3, 0xF9A3 }, +{ 0xF9A4, 0xF9A4, 0xF9A4 }, +{ 0xF9A5, 0xF9A5, 0xF9A5 }, +{ 0xF9A6, 0xF9A6, 0xF9A6 }, +{ 0xF9A7, 0xF9A7, 0xF9A7 }, +{ 0xF9A8, 0xF9A8, 0xF9A8 }, +{ 0xF9A9, 0xF9A9, 0xF9A9 }, +{ 0xF9AA, 0xF9AA, 0xF9AA }, +{ 0xF9AB, 0xF9AB, 0xF9AB }, +{ 0xF9AC, 0xF9AC, 0xF9AC }, +{ 0xF9AD, 0xF9AD, 0xF9AD }, +{ 0xF9AE, 0xF9AE, 0xF9AE }, +{ 0xF9AF, 0xF9AF, 0xF9AF }, +{ 0xF9B0, 0xF9B0, 0xF9B0 }, +{ 0xF9B1, 0xF9B1, 0xF9B1 }, +{ 0xF9B2, 0xF9B2, 0xF9B2 }, +{ 0xF9B3, 0xF9B3, 0xF9B3 }, +{ 0xF9B4, 0xF9B4, 0xF9B4 }, +{ 0xF9B5, 0xF9B5, 0xF9B5 }, +{ 0xF9B6, 0xF9B6, 0xF9B6 }, +{ 0xF9B7, 0xF9B7, 0xF9B7 }, +{ 0xF9B8, 0xF9B8, 0xF9B8 }, +{ 0xF9B9, 0xF9B9, 0xF9B9 }, +{ 0xF9BA, 0xF9BA, 0xF9BA }, +{ 0xF9BB, 0xF9BB, 0xF9BB }, +{ 0xF9BC, 0xF9BC, 0xF9BC }, +{ 0xF9BD, 0xF9BD, 0xF9BD }, +{ 0xF9BE, 0xF9BE, 0xF9BE }, +{ 0xF9BF, 0xF9BF, 0xF9BF }, +{ 0xF9C0, 0xF9C0, 0xF9C0 }, +{ 0xF9C1, 0xF9C1, 0xF9C1 }, +{ 0xF9C2, 0xF9C2, 0xF9C2 }, +{ 0xF9C3, 0xF9C3, 0xF9C3 }, +{ 0xF9C4, 0xF9C4, 0xF9C4 }, +{ 0xF9C5, 0xF9C5, 0xF9C5 }, +{ 0xF9C6, 0xF9C6, 0xF9C6 }, +{ 0xF9C7, 0xF9C7, 0xF9C7 }, +{ 0xF9C8, 0xF9C8, 0xF9C8 }, +{ 0xF9C9, 0xF9C9, 0xF9C9 }, +{ 0xF9CA, 0xF9CA, 0xF9CA }, +{ 0xF9CB, 0xF9CB, 0xF9CB }, +{ 0xF9CC, 0xF9CC, 0xF9CC }, +{ 0xF9CD, 0xF9CD, 0xF9CD }, +{ 0xF9CE, 0xF9CE, 0xF9CE }, +{ 0xF9CF, 0xF9CF, 0xF9CF }, +{ 0xF9D0, 0xF9D0, 0xF9D0 }, +{ 0xF9D1, 0xF9D1, 0xF9D1 }, +{ 0xF9D2, 0xF9D2, 0xF9D2 }, +{ 0xF9D3, 0xF9D3, 0xF9D3 }, +{ 0xF9D4, 0xF9D4, 0xF9D4 }, +{ 0xF9D5, 0xF9D5, 0xF9D5 }, +{ 0xF9D6, 0xF9D6, 0xF9D6 }, +{ 0xF9D7, 0xF9D7, 0xF9D7 }, +{ 0xF9D8, 0xF9D8, 0xF9D8 }, +{ 0xF9D9, 0xF9D9, 0xF9D9 }, +{ 0xF9DA, 0xF9DA, 0xF9DA }, +{ 0xF9DB, 0xF9DB, 0xF9DB }, +{ 0xF9DC, 0xF9DC, 0xF9DC }, +{ 0xF9DD, 0xF9DD, 0xF9DD }, +{ 0xF9DE, 0xF9DE, 0xF9DE }, +{ 0xF9DF, 0xF9DF, 0xF9DF }, +{ 0xF9E0, 0xF9E0, 0xF9E0 }, +{ 0xF9E1, 0xF9E1, 0xF9E1 }, +{ 0xF9E2, 0xF9E2, 0xF9E2 }, +{ 0xF9E3, 0xF9E3, 0xF9E3 }, +{ 0xF9E4, 0xF9E4, 0xF9E4 }, +{ 0xF9E5, 0xF9E5, 0xF9E5 }, +{ 0xF9E6, 0xF9E6, 0xF9E6 }, +{ 0xF9E7, 0xF9E7, 0xF9E7 }, +{ 0xF9E8, 0xF9E8, 0xF9E8 }, +{ 0xF9E9, 0xF9E9, 0xF9E9 }, +{ 0xF9EA, 0xF9EA, 0xF9EA }, +{ 0xF9EB, 0xF9EB, 0xF9EB }, +{ 0xF9EC, 0xF9EC, 0xF9EC }, +{ 0xF9ED, 0xF9ED, 0xF9ED }, +{ 0xF9EE, 0xF9EE, 0xF9EE }, +{ 0xF9EF, 0xF9EF, 0xF9EF }, +{ 0xF9F0, 0xF9F0, 0xF9F0 }, +{ 0xF9F1, 0xF9F1, 0xF9F1 }, +{ 0xF9F2, 0xF9F2, 0xF9F2 }, +{ 0xF9F3, 0xF9F3, 0xF9F3 }, +{ 0xF9F4, 0xF9F4, 0xF9F4 }, +{ 0xF9F5, 0xF9F5, 0xF9F5 }, +{ 0xF9F6, 0xF9F6, 0xF9F6 }, +{ 0xF9F7, 0xF9F7, 0xF9F7 }, +{ 0xF9F8, 0xF9F8, 0xF9F8 }, +{ 0xF9F9, 0xF9F9, 0xF9F9 }, +{ 0xF9FA, 0xF9FA, 0xF9FA }, +{ 0xF9FB, 0xF9FB, 0xF9FB }, +{ 0xF9FC, 0xF9FC, 0xF9FC }, +{ 0xF9FD, 0xF9FD, 0xF9FD }, +{ 0xF9FE, 0xF9FE, 0xF9FE }, +{ 0xF9FF, 0xF9FF, 0xF9FF }, +{ 0xFA00, 0xFA00, 0xFA00 }, +{ 0xFA01, 0xFA01, 0xFA01 }, +{ 0xFA02, 0xFA02, 0xFA02 }, +{ 0xFA03, 0xFA03, 0xFA03 }, +{ 0xFA04, 0xFA04, 0xFA04 }, +{ 0xFA05, 0xFA05, 0xFA05 }, +{ 0xFA06, 0xFA06, 0xFA06 }, +{ 0xFA07, 0xFA07, 0xFA07 }, +{ 0xFA08, 0xFA08, 0xFA08 }, +{ 0xFA09, 0xFA09, 0xFA09 }, +{ 0xFA0A, 0xFA0A, 0xFA0A }, +{ 0xFA0B, 0xFA0B, 0xFA0B }, +{ 0xFA0C, 0xFA0C, 0xFA0C }, +{ 0xFA0D, 0xFA0D, 0xFA0D }, +{ 0xFA0E, 0xFA0E, 0xFA0E }, +{ 0xFA0F, 0xFA0F, 0xFA0F }, +{ 0xFA10, 0xFA10, 0xFA10 }, +{ 0xFA11, 0xFA11, 0xFA11 }, +{ 0xFA12, 0xFA12, 0xFA12 }, +{ 0xFA13, 0xFA13, 0xFA13 }, +{ 0xFA14, 0xFA14, 0xFA14 }, +{ 0xFA15, 0xFA15, 0xFA15 }, +{ 0xFA16, 0xFA16, 0xFA16 }, +{ 0xFA17, 0xFA17, 0xFA17 }, +{ 0xFA18, 0xFA18, 0xFA18 }, +{ 0xFA19, 0xFA19, 0xFA19 }, +{ 0xFA1A, 0xFA1A, 0xFA1A }, +{ 0xFA1B, 0xFA1B, 0xFA1B }, +{ 0xFA1C, 0xFA1C, 0xFA1C }, +{ 0xFA1D, 0xFA1D, 0xFA1D }, +{ 0xFA1E, 0xFA1E, 0xFA1E }, +{ 0xFA1F, 0xFA1F, 0xFA1F }, +{ 0xFA20, 0xFA20, 0xFA20 }, +{ 0xFA21, 0xFA21, 0xFA21 }, +{ 0xFA22, 0xFA22, 0xFA22 }, +{ 0xFA23, 0xFA23, 0xFA23 }, +{ 0xFA24, 0xFA24, 0xFA24 }, +{ 0xFA25, 0xFA25, 0xFA25 }, +{ 0xFA26, 0xFA26, 0xFA26 }, +{ 0xFA27, 0xFA27, 0xFA27 }, +{ 0xFA28, 0xFA28, 0xFA28 }, +{ 0xFA29, 0xFA29, 0xFA29 }, +{ 0xFA2A, 0xFA2A, 0xFA2A }, +{ 0xFA2B, 0xFA2B, 0xFA2B }, +{ 0xFA2C, 0xFA2C, 0xFA2C }, +{ 0xFA2D, 0xFA2D, 0xFA2D }, +{ 0xFA30, 0xFA30, 0xFA30 }, +{ 0xFA31, 0xFA31, 0xFA31 }, +{ 0xFA32, 0xFA32, 0xFA32 }, +{ 0xFA33, 0xFA33, 0xFA33 }, +{ 0xFA34, 0xFA34, 0xFA34 }, +{ 0xFA35, 0xFA35, 0xFA35 }, +{ 0xFA36, 0xFA36, 0xFA36 }, +{ 0xFA37, 0xFA37, 0xFA37 }, +{ 0xFA38, 0xFA38, 0xFA38 }, +{ 0xFA39, 0xFA39, 0xFA39 }, +{ 0xFA3A, 0xFA3A, 0xFA3A }, +{ 0xFA3B, 0xFA3B, 0xFA3B }, +{ 0xFA3C, 0xFA3C, 0xFA3C }, +{ 0xFA3D, 0xFA3D, 0xFA3D }, +{ 0xFA3E, 0xFA3E, 0xFA3E }, +{ 0xFA3F, 0xFA3F, 0xFA3F }, +{ 0xFA40, 0xFA40, 0xFA40 }, +{ 0xFA41, 0xFA41, 0xFA41 }, +{ 0xFA42, 0xFA42, 0xFA42 }, +{ 0xFA43, 0xFA43, 0xFA43 }, +{ 0xFA44, 0xFA44, 0xFA44 }, +{ 0xFA45, 0xFA45, 0xFA45 }, +{ 0xFA46, 0xFA46, 0xFA46 }, +{ 0xFA47, 0xFA47, 0xFA47 }, +{ 0xFA48, 0xFA48, 0xFA48 }, +{ 0xFA49, 0xFA49, 0xFA49 }, +{ 0xFA4A, 0xFA4A, 0xFA4A }, +{ 0xFA4B, 0xFA4B, 0xFA4B }, +{ 0xFA4C, 0xFA4C, 0xFA4C }, +{ 0xFA4D, 0xFA4D, 0xFA4D }, +{ 0xFA4E, 0xFA4E, 0xFA4E }, +{ 0xFA4F, 0xFA4F, 0xFA4F }, +{ 0xFA50, 0xFA50, 0xFA50 }, +{ 0xFA51, 0xFA51, 0xFA51 }, +{ 0xFA52, 0xFA52, 0xFA52 }, +{ 0xFA53, 0xFA53, 0xFA53 }, +{ 0xFA54, 0xFA54, 0xFA54 }, +{ 0xFA55, 0xFA55, 0xFA55 }, +{ 0xFA56, 0xFA56, 0xFA56 }, +{ 0xFA57, 0xFA57, 0xFA57 }, +{ 0xFA58, 0xFA58, 0xFA58 }, +{ 0xFA59, 0xFA59, 0xFA59 }, +{ 0xFA5A, 0xFA5A, 0xFA5A }, +{ 0xFA5B, 0xFA5B, 0xFA5B }, +{ 0xFA5C, 0xFA5C, 0xFA5C }, +{ 0xFA5D, 0xFA5D, 0xFA5D }, +{ 0xFA5E, 0xFA5E, 0xFA5E }, +{ 0xFA5F, 0xFA5F, 0xFA5F }, +{ 0xFA60, 0xFA60, 0xFA60 }, +{ 0xFA61, 0xFA61, 0xFA61 }, +{ 0xFA62, 0xFA62, 0xFA62 }, +{ 0xFA63, 0xFA63, 0xFA63 }, +{ 0xFA64, 0xFA64, 0xFA64 }, +{ 0xFA65, 0xFA65, 0xFA65 }, +{ 0xFA66, 0xFA66, 0xFA66 }, +{ 0xFA67, 0xFA67, 0xFA67 }, +{ 0xFA68, 0xFA68, 0xFA68 }, +{ 0xFA69, 0xFA69, 0xFA69 }, +{ 0xFA6A, 0xFA6A, 0xFA6A }, +{ 0xFA70, 0xFA70, 0xFA70 }, +{ 0xFA71, 0xFA71, 0xFA71 }, +{ 0xFA72, 0xFA72, 0xFA72 }, +{ 0xFA73, 0xFA73, 0xFA73 }, +{ 0xFA74, 0xFA74, 0xFA74 }, +{ 0xFA75, 0xFA75, 0xFA75 }, +{ 0xFA76, 0xFA76, 0xFA76 }, +{ 0xFA77, 0xFA77, 0xFA77 }, +{ 0xFA78, 0xFA78, 0xFA78 }, +{ 0xFA79, 0xFA79, 0xFA79 }, +{ 0xFA7A, 0xFA7A, 0xFA7A }, +{ 0xFA7B, 0xFA7B, 0xFA7B }, +{ 0xFA7C, 0xFA7C, 0xFA7C }, +{ 0xFA7D, 0xFA7D, 0xFA7D }, +{ 0xFA7E, 0xFA7E, 0xFA7E }, +{ 0xFA7F, 0xFA7F, 0xFA7F }, +{ 0xFA80, 0xFA80, 0xFA80 }, +{ 0xFA81, 0xFA81, 0xFA81 }, +{ 0xFA82, 0xFA82, 0xFA82 }, +{ 0xFA83, 0xFA83, 0xFA83 }, +{ 0xFA84, 0xFA84, 0xFA84 }, +{ 0xFA85, 0xFA85, 0xFA85 }, +{ 0xFA86, 0xFA86, 0xFA86 }, +{ 0xFA87, 0xFA87, 0xFA87 }, +{ 0xFA88, 0xFA88, 0xFA88 }, +{ 0xFA89, 0xFA89, 0xFA89 }, +{ 0xFA8A, 0xFA8A, 0xFA8A }, +{ 0xFA8B, 0xFA8B, 0xFA8B }, +{ 0xFA8C, 0xFA8C, 0xFA8C }, +{ 0xFA8D, 0xFA8D, 0xFA8D }, +{ 0xFA8E, 0xFA8E, 0xFA8E }, +{ 0xFA8F, 0xFA8F, 0xFA8F }, +{ 0xFA90, 0xFA90, 0xFA90 }, +{ 0xFA91, 0xFA91, 0xFA91 }, +{ 0xFA92, 0xFA92, 0xFA92 }, +{ 0xFA93, 0xFA93, 0xFA93 }, +{ 0xFA94, 0xFA94, 0xFA94 }, +{ 0xFA95, 0xFA95, 0xFA95 }, +{ 0xFA96, 0xFA96, 0xFA96 }, +{ 0xFA97, 0xFA97, 0xFA97 }, +{ 0xFA98, 0xFA98, 0xFA98 }, +{ 0xFA99, 0xFA99, 0xFA99 }, +{ 0xFA9A, 0xFA9A, 0xFA9A }, +{ 0xFA9B, 0xFA9B, 0xFA9B }, +{ 0xFA9C, 0xFA9C, 0xFA9C }, +{ 0xFA9D, 0xFA9D, 0xFA9D }, +{ 0xFA9E, 0xFA9E, 0xFA9E }, +{ 0xFA9F, 0xFA9F, 0xFA9F }, +{ 0xFAA0, 0xFAA0, 0xFAA0 }, +{ 0xFAA1, 0xFAA1, 0xFAA1 }, +{ 0xFAA2, 0xFAA2, 0xFAA2 }, +{ 0xFAA3, 0xFAA3, 0xFAA3 }, +{ 0xFAA4, 0xFAA4, 0xFAA4 }, +{ 0xFAA5, 0xFAA5, 0xFAA5 }, +{ 0xFAA6, 0xFAA6, 0xFAA6 }, +{ 0xFAA7, 0xFAA7, 0xFAA7 }, +{ 0xFAA8, 0xFAA8, 0xFAA8 }, +{ 0xFAA9, 0xFAA9, 0xFAA9 }, +{ 0xFAAA, 0xFAAA, 0xFAAA }, +{ 0xFAAB, 0xFAAB, 0xFAAB }, +{ 0xFAAC, 0xFAAC, 0xFAAC }, +{ 0xFAAD, 0xFAAD, 0xFAAD }, +{ 0xFAAE, 0xFAAE, 0xFAAE }, +{ 0xFAAF, 0xFAAF, 0xFAAF }, +{ 0xFAB0, 0xFAB0, 0xFAB0 }, +{ 0xFAB1, 0xFAB1, 0xFAB1 }, +{ 0xFAB2, 0xFAB2, 0xFAB2 }, +{ 0xFAB3, 0xFAB3, 0xFAB3 }, +{ 0xFAB4, 0xFAB4, 0xFAB4 }, +{ 0xFAB5, 0xFAB5, 0xFAB5 }, +{ 0xFAB6, 0xFAB6, 0xFAB6 }, +{ 0xFAB7, 0xFAB7, 0xFAB7 }, +{ 0xFAB8, 0xFAB8, 0xFAB8 }, +{ 0xFAB9, 0xFAB9, 0xFAB9 }, +{ 0xFABA, 0xFABA, 0xFABA }, +{ 0xFABB, 0xFABB, 0xFABB }, +{ 0xFABC, 0xFABC, 0xFABC }, +{ 0xFABD, 0xFABD, 0xFABD }, +{ 0xFABE, 0xFABE, 0xFABE }, +{ 0xFABF, 0xFABF, 0xFABF }, +{ 0xFAC0, 0xFAC0, 0xFAC0 }, +{ 0xFAC1, 0xFAC1, 0xFAC1 }, +{ 0xFAC2, 0xFAC2, 0xFAC2 }, +{ 0xFAC3, 0xFAC3, 0xFAC3 }, +{ 0xFAC4, 0xFAC4, 0xFAC4 }, +{ 0xFAC5, 0xFAC5, 0xFAC5 }, +{ 0xFAC6, 0xFAC6, 0xFAC6 }, +{ 0xFAC7, 0xFAC7, 0xFAC7 }, +{ 0xFAC8, 0xFAC8, 0xFAC8 }, +{ 0xFAC9, 0xFAC9, 0xFAC9 }, +{ 0xFACA, 0xFACA, 0xFACA }, +{ 0xFACB, 0xFACB, 0xFACB }, +{ 0xFACC, 0xFACC, 0xFACC }, +{ 0xFACD, 0xFACD, 0xFACD }, +{ 0xFACE, 0xFACE, 0xFACE }, +{ 0xFACF, 0xFACF, 0xFACF }, +{ 0xFAD0, 0xFAD0, 0xFAD0 }, +{ 0xFAD1, 0xFAD1, 0xFAD1 }, +{ 0xFAD2, 0xFAD2, 0xFAD2 }, +{ 0xFAD3, 0xFAD3, 0xFAD3 }, +{ 0xFAD4, 0xFAD4, 0xFAD4 }, +{ 0xFAD5, 0xFAD5, 0xFAD5 }, +{ 0xFAD6, 0xFAD6, 0xFAD6 }, +{ 0xFAD7, 0xFAD7, 0xFAD7 }, +{ 0xFAD8, 0xFAD8, 0xFAD8 }, +{ 0xFAD9, 0xFAD9, 0xFAD9 }, +{ 0xFB00, 0xFB00, 0xFB00 }, +{ 0xFB01, 0xFB01, 0xFB01 }, +{ 0xFB02, 0xFB02, 0xFB02 }, +{ 0xFB03, 0xFB03, 0xFB03 }, +{ 0xFB04, 0xFB04, 0xFB04 }, +{ 0xFB05, 0xFB05, 0xFB05 }, +{ 0xFB06, 0xFB06, 0xFB06 }, +{ 0xFB13, 0xFB13, 0xFB13 }, +{ 0xFB14, 0xFB14, 0xFB14 }, +{ 0xFB15, 0xFB15, 0xFB15 }, +{ 0xFB16, 0xFB16, 0xFB16 }, +{ 0xFB17, 0xFB17, 0xFB17 }, +{ 0xFB1D, 0xFB1D, 0xFB1D }, +{ 0xFB1E, 0xFB1E, 0xFB1E }, +{ 0xFB1F, 0xFB1F, 0xFB1F }, +{ 0xFB20, 0xFB20, 0xFB20 }, +{ 0xFB21, 0xFB21, 0xFB21 }, +{ 0xFB22, 0xFB22, 0xFB22 }, +{ 0xFB23, 0xFB23, 0xFB23 }, +{ 0xFB24, 0xFB24, 0xFB24 }, +{ 0xFB25, 0xFB25, 0xFB25 }, +{ 0xFB26, 0xFB26, 0xFB26 }, +{ 0xFB27, 0xFB27, 0xFB27 }, +{ 0xFB28, 0xFB28, 0xFB28 }, +{ 0xFB2A, 0xFB2A, 0xFB2A }, +{ 0xFB2B, 0xFB2B, 0xFB2B }, +{ 0xFB2C, 0xFB2C, 0xFB2C }, +{ 0xFB2D, 0xFB2D, 0xFB2D }, +{ 0xFB2E, 0xFB2E, 0xFB2E }, +{ 0xFB2F, 0xFB2F, 0xFB2F }, +{ 0xFB30, 0xFB30, 0xFB30 }, +{ 0xFB31, 0xFB31, 0xFB31 }, +{ 0xFB32, 0xFB32, 0xFB32 }, +{ 0xFB33, 0xFB33, 0xFB33 }, +{ 0xFB34, 0xFB34, 0xFB34 }, +{ 0xFB35, 0xFB35, 0xFB35 }, +{ 0xFB36, 0xFB36, 0xFB36 }, +{ 0xFB38, 0xFB38, 0xFB38 }, +{ 0xFB39, 0xFB39, 0xFB39 }, +{ 0xFB3A, 0xFB3A, 0xFB3A }, +{ 0xFB3B, 0xFB3B, 0xFB3B }, +{ 0xFB3C, 0xFB3C, 0xFB3C }, +{ 0xFB3E, 0xFB3E, 0xFB3E }, +{ 0xFB40, 0xFB40, 0xFB40 }, +{ 0xFB41, 0xFB41, 0xFB41 }, +{ 0xFB43, 0xFB43, 0xFB43 }, +{ 0xFB44, 0xFB44, 0xFB44 }, +{ 0xFB46, 0xFB46, 0xFB46 }, +{ 0xFB47, 0xFB47, 0xFB47 }, +{ 0xFB48, 0xFB48, 0xFB48 }, +{ 0xFB49, 0xFB49, 0xFB49 }, +{ 0xFB4A, 0xFB4A, 0xFB4A }, +{ 0xFB4B, 0xFB4B, 0xFB4B }, +{ 0xFB4C, 0xFB4C, 0xFB4C }, +{ 0xFB4D, 0xFB4D, 0xFB4D }, +{ 0xFB4E, 0xFB4E, 0xFB4E }, +{ 0xFB4F, 0xFB4F, 0xFB4F }, +{ 0xFB50, 0xFB50, 0xFB50 }, +{ 0xFB51, 0xFB51, 0xFB51 }, +{ 0xFB52, 0xFB52, 0xFB52 }, +{ 0xFB53, 0xFB53, 0xFB53 }, +{ 0xFB54, 0xFB54, 0xFB54 }, +{ 0xFB55, 0xFB55, 0xFB55 }, +{ 0xFB56, 0xFB56, 0xFB56 }, +{ 0xFB57, 0xFB57, 0xFB57 }, +{ 0xFB58, 0xFB58, 0xFB58 }, +{ 0xFB59, 0xFB59, 0xFB59 }, +{ 0xFB5A, 0xFB5A, 0xFB5A }, +{ 0xFB5B, 0xFB5B, 0xFB5B }, +{ 0xFB5C, 0xFB5C, 0xFB5C }, +{ 0xFB5D, 0xFB5D, 0xFB5D }, +{ 0xFB5E, 0xFB5E, 0xFB5E }, +{ 0xFB5F, 0xFB5F, 0xFB5F }, +{ 0xFB60, 0xFB60, 0xFB60 }, +{ 0xFB61, 0xFB61, 0xFB61 }, +{ 0xFB62, 0xFB62, 0xFB62 }, +{ 0xFB63, 0xFB63, 0xFB63 }, +{ 0xFB64, 0xFB64, 0xFB64 }, +{ 0xFB65, 0xFB65, 0xFB65 }, +{ 0xFB66, 0xFB66, 0xFB66 }, +{ 0xFB67, 0xFB67, 0xFB67 }, +{ 0xFB68, 0xFB68, 0xFB68 }, +{ 0xFB69, 0xFB69, 0xFB69 }, +{ 0xFB6A, 0xFB6A, 0xFB6A }, +{ 0xFB6B, 0xFB6B, 0xFB6B }, +{ 0xFB6C, 0xFB6C, 0xFB6C }, +{ 0xFB6D, 0xFB6D, 0xFB6D }, +{ 0xFB6E, 0xFB6E, 0xFB6E }, +{ 0xFB6F, 0xFB6F, 0xFB6F }, +{ 0xFB70, 0xFB70, 0xFB70 }, +{ 0xFB71, 0xFB71, 0xFB71 }, +{ 0xFB72, 0xFB72, 0xFB72 }, +{ 0xFB73, 0xFB73, 0xFB73 }, +{ 0xFB74, 0xFB74, 0xFB74 }, +{ 0xFB75, 0xFB75, 0xFB75 }, +{ 0xFB76, 0xFB76, 0xFB76 }, +{ 0xFB77, 0xFB77, 0xFB77 }, +{ 0xFB78, 0xFB78, 0xFB78 }, +{ 0xFB79, 0xFB79, 0xFB79 }, +{ 0xFB7A, 0xFB7A, 0xFB7A }, +{ 0xFB7B, 0xFB7B, 0xFB7B }, +{ 0xFB7C, 0xFB7C, 0xFB7C }, +{ 0xFB7D, 0xFB7D, 0xFB7D }, +{ 0xFB7E, 0xFB7E, 0xFB7E }, +{ 0xFB7F, 0xFB7F, 0xFB7F }, +{ 0xFB80, 0xFB80, 0xFB80 }, +{ 0xFB81, 0xFB81, 0xFB81 }, +{ 0xFB82, 0xFB82, 0xFB82 }, +{ 0xFB83, 0xFB83, 0xFB83 }, +{ 0xFB84, 0xFB84, 0xFB84 }, +{ 0xFB85, 0xFB85, 0xFB85 }, +{ 0xFB86, 0xFB86, 0xFB86 }, +{ 0xFB87, 0xFB87, 0xFB87 }, +{ 0xFB88, 0xFB88, 0xFB88 }, +{ 0xFB89, 0xFB89, 0xFB89 }, +{ 0xFB8A, 0xFB8A, 0xFB8A }, +{ 0xFB8B, 0xFB8B, 0xFB8B }, +{ 0xFB8C, 0xFB8C, 0xFB8C }, +{ 0xFB8D, 0xFB8D, 0xFB8D }, +{ 0xFB8E, 0xFB8E, 0xFB8E }, +{ 0xFB8F, 0xFB8F, 0xFB8F }, +{ 0xFB90, 0xFB90, 0xFB90 }, +{ 0xFB91, 0xFB91, 0xFB91 }, +{ 0xFB92, 0xFB92, 0xFB92 }, +{ 0xFB93, 0xFB93, 0xFB93 }, +{ 0xFB94, 0xFB94, 0xFB94 }, +{ 0xFB95, 0xFB95, 0xFB95 }, +{ 0xFB96, 0xFB96, 0xFB96 }, +{ 0xFB97, 0xFB97, 0xFB97 }, +{ 0xFB98, 0xFB98, 0xFB98 }, +{ 0xFB99, 0xFB99, 0xFB99 }, +{ 0xFB9A, 0xFB9A, 0xFB9A }, +{ 0xFB9B, 0xFB9B, 0xFB9B }, +{ 0xFB9C, 0xFB9C, 0xFB9C }, +{ 0xFB9D, 0xFB9D, 0xFB9D }, +{ 0xFB9E, 0xFB9E, 0xFB9E }, +{ 0xFB9F, 0xFB9F, 0xFB9F }, +{ 0xFBA0, 0xFBA0, 0xFBA0 }, +{ 0xFBA1, 0xFBA1, 0xFBA1 }, +{ 0xFBA2, 0xFBA2, 0xFBA2 }, +{ 0xFBA3, 0xFBA3, 0xFBA3 }, +{ 0xFBA4, 0xFBA4, 0xFBA4 }, +{ 0xFBA5, 0xFBA5, 0xFBA5 }, +{ 0xFBA6, 0xFBA6, 0xFBA6 }, +{ 0xFBA7, 0xFBA7, 0xFBA7 }, +{ 0xFBA8, 0xFBA8, 0xFBA8 }, +{ 0xFBA9, 0xFBA9, 0xFBA9 }, +{ 0xFBAA, 0xFBAA, 0xFBAA }, +{ 0xFBAB, 0xFBAB, 0xFBAB }, +{ 0xFBAC, 0xFBAC, 0xFBAC }, +{ 0xFBAD, 0xFBAD, 0xFBAD }, +{ 0xFBAE, 0xFBAE, 0xFBAE }, +{ 0xFBAF, 0xFBAF, 0xFBAF }, +{ 0xFBB0, 0xFBB0, 0xFBB0 }, +{ 0xFBB1, 0xFBB1, 0xFBB1 }, +{ 0xFBD3, 0xFBD3, 0xFBD3 }, +{ 0xFBD4, 0xFBD4, 0xFBD4 }, +{ 0xFBD5, 0xFBD5, 0xFBD5 }, +{ 0xFBD6, 0xFBD6, 0xFBD6 }, +{ 0xFBD7, 0xFBD7, 0xFBD7 }, +{ 0xFBD8, 0xFBD8, 0xFBD8 }, +{ 0xFBD9, 0xFBD9, 0xFBD9 }, +{ 0xFBDA, 0xFBDA, 0xFBDA }, +{ 0xFBDB, 0xFBDB, 0xFBDB }, +{ 0xFBDC, 0xFBDC, 0xFBDC }, +{ 0xFBDD, 0xFBDD, 0xFBDD }, +{ 0xFBDE, 0xFBDE, 0xFBDE }, +{ 0xFBDF, 0xFBDF, 0xFBDF }, +{ 0xFBE0, 0xFBE0, 0xFBE0 }, +{ 0xFBE1, 0xFBE1, 0xFBE1 }, +{ 0xFBE2, 0xFBE2, 0xFBE2 }, +{ 0xFBE3, 0xFBE3, 0xFBE3 }, +{ 0xFBE4, 0xFBE4, 0xFBE4 }, +{ 0xFBE5, 0xFBE5, 0xFBE5 }, +{ 0xFBE6, 0xFBE6, 0xFBE6 }, +{ 0xFBE7, 0xFBE7, 0xFBE7 }, +{ 0xFBE8, 0xFBE8, 0xFBE8 }, +{ 0xFBE9, 0xFBE9, 0xFBE9 }, +{ 0xFBEA, 0xFBEA, 0xFBEA }, +{ 0xFBEB, 0xFBEB, 0xFBEB }, +{ 0xFBEC, 0xFBEC, 0xFBEC }, +{ 0xFBED, 0xFBED, 0xFBED }, +{ 0xFBEE, 0xFBEE, 0xFBEE }, +{ 0xFBEF, 0xFBEF, 0xFBEF }, +{ 0xFBF0, 0xFBF0, 0xFBF0 }, +{ 0xFBF1, 0xFBF1, 0xFBF1 }, +{ 0xFBF2, 0xFBF2, 0xFBF2 }, +{ 0xFBF3, 0xFBF3, 0xFBF3 }, +{ 0xFBF4, 0xFBF4, 0xFBF4 }, +{ 0xFBF5, 0xFBF5, 0xFBF5 }, +{ 0xFBF6, 0xFBF6, 0xFBF6 }, +{ 0xFBF7, 0xFBF7, 0xFBF7 }, +{ 0xFBF8, 0xFBF8, 0xFBF8 }, +{ 0xFBF9, 0xFBF9, 0xFBF9 }, +{ 0xFBFA, 0xFBFA, 0xFBFA }, +{ 0xFBFB, 0xFBFB, 0xFBFB }, +{ 0xFBFC, 0xFBFC, 0xFBFC }, +{ 0xFBFD, 0xFBFD, 0xFBFD }, +{ 0xFBFE, 0xFBFE, 0xFBFE }, +{ 0xFBFF, 0xFBFF, 0xFBFF }, +{ 0xFC00, 0xFC00, 0xFC00 }, +{ 0xFC01, 0xFC01, 0xFC01 }, +{ 0xFC02, 0xFC02, 0xFC02 }, +{ 0xFC03, 0xFC03, 0xFC03 }, +{ 0xFC04, 0xFC04, 0xFC04 }, +{ 0xFC05, 0xFC05, 0xFC05 }, +{ 0xFC06, 0xFC06, 0xFC06 }, +{ 0xFC07, 0xFC07, 0xFC07 }, +{ 0xFC08, 0xFC08, 0xFC08 }, +{ 0xFC09, 0xFC09, 0xFC09 }, +{ 0xFC0A, 0xFC0A, 0xFC0A }, +{ 0xFC0B, 0xFC0B, 0xFC0B }, +{ 0xFC0C, 0xFC0C, 0xFC0C }, +{ 0xFC0D, 0xFC0D, 0xFC0D }, +{ 0xFC0E, 0xFC0E, 0xFC0E }, +{ 0xFC0F, 0xFC0F, 0xFC0F }, +{ 0xFC10, 0xFC10, 0xFC10 }, +{ 0xFC11, 0xFC11, 0xFC11 }, +{ 0xFC12, 0xFC12, 0xFC12 }, +{ 0xFC13, 0xFC13, 0xFC13 }, +{ 0xFC14, 0xFC14, 0xFC14 }, +{ 0xFC15, 0xFC15, 0xFC15 }, +{ 0xFC16, 0xFC16, 0xFC16 }, +{ 0xFC17, 0xFC17, 0xFC17 }, +{ 0xFC18, 0xFC18, 0xFC18 }, +{ 0xFC19, 0xFC19, 0xFC19 }, +{ 0xFC1A, 0xFC1A, 0xFC1A }, +{ 0xFC1B, 0xFC1B, 0xFC1B }, +{ 0xFC1C, 0xFC1C, 0xFC1C }, +{ 0xFC1D, 0xFC1D, 0xFC1D }, +{ 0xFC1E, 0xFC1E, 0xFC1E }, +{ 0xFC1F, 0xFC1F, 0xFC1F }, +{ 0xFC20, 0xFC20, 0xFC20 }, +{ 0xFC21, 0xFC21, 0xFC21 }, +{ 0xFC22, 0xFC22, 0xFC22 }, +{ 0xFC23, 0xFC23, 0xFC23 }, +{ 0xFC24, 0xFC24, 0xFC24 }, +{ 0xFC25, 0xFC25, 0xFC25 }, +{ 0xFC26, 0xFC26, 0xFC26 }, +{ 0xFC27, 0xFC27, 0xFC27 }, +{ 0xFC28, 0xFC28, 0xFC28 }, +{ 0xFC29, 0xFC29, 0xFC29 }, +{ 0xFC2A, 0xFC2A, 0xFC2A }, +{ 0xFC2B, 0xFC2B, 0xFC2B }, +{ 0xFC2C, 0xFC2C, 0xFC2C }, +{ 0xFC2D, 0xFC2D, 0xFC2D }, +{ 0xFC2E, 0xFC2E, 0xFC2E }, +{ 0xFC2F, 0xFC2F, 0xFC2F }, +{ 0xFC30, 0xFC30, 0xFC30 }, +{ 0xFC31, 0xFC31, 0xFC31 }, +{ 0xFC32, 0xFC32, 0xFC32 }, +{ 0xFC33, 0xFC33, 0xFC33 }, +{ 0xFC34, 0xFC34, 0xFC34 }, +{ 0xFC35, 0xFC35, 0xFC35 }, +{ 0xFC36, 0xFC36, 0xFC36 }, +{ 0xFC37, 0xFC37, 0xFC37 }, +{ 0xFC38, 0xFC38, 0xFC38 }, +{ 0xFC39, 0xFC39, 0xFC39 }, +{ 0xFC3A, 0xFC3A, 0xFC3A }, +{ 0xFC3B, 0xFC3B, 0xFC3B }, +{ 0xFC3C, 0xFC3C, 0xFC3C }, +{ 0xFC3D, 0xFC3D, 0xFC3D }, +{ 0xFC3E, 0xFC3E, 0xFC3E }, +{ 0xFC3F, 0xFC3F, 0xFC3F }, +{ 0xFC40, 0xFC40, 0xFC40 }, +{ 0xFC41, 0xFC41, 0xFC41 }, +{ 0xFC42, 0xFC42, 0xFC42 }, +{ 0xFC43, 0xFC43, 0xFC43 }, +{ 0xFC44, 0xFC44, 0xFC44 }, +{ 0xFC45, 0xFC45, 0xFC45 }, +{ 0xFC46, 0xFC46, 0xFC46 }, +{ 0xFC47, 0xFC47, 0xFC47 }, +{ 0xFC48, 0xFC48, 0xFC48 }, +{ 0xFC49, 0xFC49, 0xFC49 }, +{ 0xFC4A, 0xFC4A, 0xFC4A }, +{ 0xFC4B, 0xFC4B, 0xFC4B }, +{ 0xFC4C, 0xFC4C, 0xFC4C }, +{ 0xFC4D, 0xFC4D, 0xFC4D }, +{ 0xFC4E, 0xFC4E, 0xFC4E }, +{ 0xFC4F, 0xFC4F, 0xFC4F }, +{ 0xFC50, 0xFC50, 0xFC50 }, +{ 0xFC51, 0xFC51, 0xFC51 }, +{ 0xFC52, 0xFC52, 0xFC52 }, +{ 0xFC53, 0xFC53, 0xFC53 }, +{ 0xFC54, 0xFC54, 0xFC54 }, +{ 0xFC55, 0xFC55, 0xFC55 }, +{ 0xFC56, 0xFC56, 0xFC56 }, +{ 0xFC57, 0xFC57, 0xFC57 }, +{ 0xFC58, 0xFC58, 0xFC58 }, +{ 0xFC59, 0xFC59, 0xFC59 }, +{ 0xFC5A, 0xFC5A, 0xFC5A }, +{ 0xFC5B, 0xFC5B, 0xFC5B }, +{ 0xFC5C, 0xFC5C, 0xFC5C }, +{ 0xFC5D, 0xFC5D, 0xFC5D }, +{ 0xFC5E, 0xFC5E, 0xFC5E }, +{ 0xFC5F, 0xFC5F, 0xFC5F }, +{ 0xFC60, 0xFC60, 0xFC60 }, +{ 0xFC61, 0xFC61, 0xFC61 }, +{ 0xFC62, 0xFC62, 0xFC62 }, +{ 0xFC63, 0xFC63, 0xFC63 }, +{ 0xFC64, 0xFC64, 0xFC64 }, +{ 0xFC65, 0xFC65, 0xFC65 }, +{ 0xFC66, 0xFC66, 0xFC66 }, +{ 0xFC67, 0xFC67, 0xFC67 }, +{ 0xFC68, 0xFC68, 0xFC68 }, +{ 0xFC69, 0xFC69, 0xFC69 }, +{ 0xFC6A, 0xFC6A, 0xFC6A }, +{ 0xFC6B, 0xFC6B, 0xFC6B }, +{ 0xFC6C, 0xFC6C, 0xFC6C }, +{ 0xFC6D, 0xFC6D, 0xFC6D }, +{ 0xFC6E, 0xFC6E, 0xFC6E }, +{ 0xFC6F, 0xFC6F, 0xFC6F }, +{ 0xFC70, 0xFC70, 0xFC70 }, +{ 0xFC71, 0xFC71, 0xFC71 }, +{ 0xFC72, 0xFC72, 0xFC72 }, +{ 0xFC73, 0xFC73, 0xFC73 }, +{ 0xFC74, 0xFC74, 0xFC74 }, +{ 0xFC75, 0xFC75, 0xFC75 }, +{ 0xFC76, 0xFC76, 0xFC76 }, +{ 0xFC77, 0xFC77, 0xFC77 }, +{ 0xFC78, 0xFC78, 0xFC78 }, +{ 0xFC79, 0xFC79, 0xFC79 }, +{ 0xFC7A, 0xFC7A, 0xFC7A }, +{ 0xFC7B, 0xFC7B, 0xFC7B }, +{ 0xFC7C, 0xFC7C, 0xFC7C }, +{ 0xFC7D, 0xFC7D, 0xFC7D }, +{ 0xFC7E, 0xFC7E, 0xFC7E }, +{ 0xFC7F, 0xFC7F, 0xFC7F }, +{ 0xFC80, 0xFC80, 0xFC80 }, +{ 0xFC81, 0xFC81, 0xFC81 }, +{ 0xFC82, 0xFC82, 0xFC82 }, +{ 0xFC83, 0xFC83, 0xFC83 }, +{ 0xFC84, 0xFC84, 0xFC84 }, +{ 0xFC85, 0xFC85, 0xFC85 }, +{ 0xFC86, 0xFC86, 0xFC86 }, +{ 0xFC87, 0xFC87, 0xFC87 }, +{ 0xFC88, 0xFC88, 0xFC88 }, +{ 0xFC89, 0xFC89, 0xFC89 }, +{ 0xFC8A, 0xFC8A, 0xFC8A }, +{ 0xFC8B, 0xFC8B, 0xFC8B }, +{ 0xFC8C, 0xFC8C, 0xFC8C }, +{ 0xFC8D, 0xFC8D, 0xFC8D }, +{ 0xFC8E, 0xFC8E, 0xFC8E }, +{ 0xFC8F, 0xFC8F, 0xFC8F }, +{ 0xFC90, 0xFC90, 0xFC90 }, +{ 0xFC91, 0xFC91, 0xFC91 }, +{ 0xFC92, 0xFC92, 0xFC92 }, +{ 0xFC93, 0xFC93, 0xFC93 }, +{ 0xFC94, 0xFC94, 0xFC94 }, +{ 0xFC95, 0xFC95, 0xFC95 }, +{ 0xFC96, 0xFC96, 0xFC96 }, +{ 0xFC97, 0xFC97, 0xFC97 }, +{ 0xFC98, 0xFC98, 0xFC98 }, +{ 0xFC99, 0xFC99, 0xFC99 }, +{ 0xFC9A, 0xFC9A, 0xFC9A }, +{ 0xFC9B, 0xFC9B, 0xFC9B }, +{ 0xFC9C, 0xFC9C, 0xFC9C }, +{ 0xFC9D, 0xFC9D, 0xFC9D }, +{ 0xFC9E, 0xFC9E, 0xFC9E }, +{ 0xFC9F, 0xFC9F, 0xFC9F }, +{ 0xFCA0, 0xFCA0, 0xFCA0 }, +{ 0xFCA1, 0xFCA1, 0xFCA1 }, +{ 0xFCA2, 0xFCA2, 0xFCA2 }, +{ 0xFCA3, 0xFCA3, 0xFCA3 }, +{ 0xFCA4, 0xFCA4, 0xFCA4 }, +{ 0xFCA5, 0xFCA5, 0xFCA5 }, +{ 0xFCA6, 0xFCA6, 0xFCA6 }, +{ 0xFCA7, 0xFCA7, 0xFCA7 }, +{ 0xFCA8, 0xFCA8, 0xFCA8 }, +{ 0xFCA9, 0xFCA9, 0xFCA9 }, +{ 0xFCAA, 0xFCAA, 0xFCAA }, +{ 0xFCAB, 0xFCAB, 0xFCAB }, +{ 0xFCAC, 0xFCAC, 0xFCAC }, +{ 0xFCAD, 0xFCAD, 0xFCAD }, +{ 0xFCAE, 0xFCAE, 0xFCAE }, +{ 0xFCAF, 0xFCAF, 0xFCAF }, +{ 0xFCB0, 0xFCB0, 0xFCB0 }, +{ 0xFCB1, 0xFCB1, 0xFCB1 }, +{ 0xFCB2, 0xFCB2, 0xFCB2 }, +{ 0xFCB3, 0xFCB3, 0xFCB3 }, +{ 0xFCB4, 0xFCB4, 0xFCB4 }, +{ 0xFCB5, 0xFCB5, 0xFCB5 }, +{ 0xFCB6, 0xFCB6, 0xFCB6 }, +{ 0xFCB7, 0xFCB7, 0xFCB7 }, +{ 0xFCB8, 0xFCB8, 0xFCB8 }, +{ 0xFCB9, 0xFCB9, 0xFCB9 }, +{ 0xFCBA, 0xFCBA, 0xFCBA }, +{ 0xFCBB, 0xFCBB, 0xFCBB }, +{ 0xFCBC, 0xFCBC, 0xFCBC }, +{ 0xFCBD, 0xFCBD, 0xFCBD }, +{ 0xFCBE, 0xFCBE, 0xFCBE }, +{ 0xFCBF, 0xFCBF, 0xFCBF }, +{ 0xFCC0, 0xFCC0, 0xFCC0 }, +{ 0xFCC1, 0xFCC1, 0xFCC1 }, +{ 0xFCC2, 0xFCC2, 0xFCC2 }, +{ 0xFCC3, 0xFCC3, 0xFCC3 }, +{ 0xFCC4, 0xFCC4, 0xFCC4 }, +{ 0xFCC5, 0xFCC5, 0xFCC5 }, +{ 0xFCC6, 0xFCC6, 0xFCC6 }, +{ 0xFCC7, 0xFCC7, 0xFCC7 }, +{ 0xFCC8, 0xFCC8, 0xFCC8 }, +{ 0xFCC9, 0xFCC9, 0xFCC9 }, +{ 0xFCCA, 0xFCCA, 0xFCCA }, +{ 0xFCCB, 0xFCCB, 0xFCCB }, +{ 0xFCCC, 0xFCCC, 0xFCCC }, +{ 0xFCCD, 0xFCCD, 0xFCCD }, +{ 0xFCCE, 0xFCCE, 0xFCCE }, +{ 0xFCCF, 0xFCCF, 0xFCCF }, +{ 0xFCD0, 0xFCD0, 0xFCD0 }, +{ 0xFCD1, 0xFCD1, 0xFCD1 }, +{ 0xFCD2, 0xFCD2, 0xFCD2 }, +{ 0xFCD3, 0xFCD3, 0xFCD3 }, +{ 0xFCD4, 0xFCD4, 0xFCD4 }, +{ 0xFCD5, 0xFCD5, 0xFCD5 }, +{ 0xFCD6, 0xFCD6, 0xFCD6 }, +{ 0xFCD7, 0xFCD7, 0xFCD7 }, +{ 0xFCD8, 0xFCD8, 0xFCD8 }, +{ 0xFCD9, 0xFCD9, 0xFCD9 }, +{ 0xFCDA, 0xFCDA, 0xFCDA }, +{ 0xFCDB, 0xFCDB, 0xFCDB }, +{ 0xFCDC, 0xFCDC, 0xFCDC }, +{ 0xFCDD, 0xFCDD, 0xFCDD }, +{ 0xFCDE, 0xFCDE, 0xFCDE }, +{ 0xFCDF, 0xFCDF, 0xFCDF }, +{ 0xFCE0, 0xFCE0, 0xFCE0 }, +{ 0xFCE1, 0xFCE1, 0xFCE1 }, +{ 0xFCE2, 0xFCE2, 0xFCE2 }, +{ 0xFCE3, 0xFCE3, 0xFCE3 }, +{ 0xFCE4, 0xFCE4, 0xFCE4 }, +{ 0xFCE5, 0xFCE5, 0xFCE5 }, +{ 0xFCE6, 0xFCE6, 0xFCE6 }, +{ 0xFCE7, 0xFCE7, 0xFCE7 }, +{ 0xFCE8, 0xFCE8, 0xFCE8 }, +{ 0xFCE9, 0xFCE9, 0xFCE9 }, +{ 0xFCEA, 0xFCEA, 0xFCEA }, +{ 0xFCEB, 0xFCEB, 0xFCEB }, +{ 0xFCEC, 0xFCEC, 0xFCEC }, +{ 0xFCED, 0xFCED, 0xFCED }, +{ 0xFCEE, 0xFCEE, 0xFCEE }, +{ 0xFCEF, 0xFCEF, 0xFCEF }, +{ 0xFCF0, 0xFCF0, 0xFCF0 }, +{ 0xFCF1, 0xFCF1, 0xFCF1 }, +{ 0xFCF2, 0xFCF2, 0xFCF2 }, +{ 0xFCF3, 0xFCF3, 0xFCF3 }, +{ 0xFCF4, 0xFCF4, 0xFCF4 }, +{ 0xFCF5, 0xFCF5, 0xFCF5 }, +{ 0xFCF6, 0xFCF6, 0xFCF6 }, +{ 0xFCF7, 0xFCF7, 0xFCF7 }, +{ 0xFCF8, 0xFCF8, 0xFCF8 }, +{ 0xFCF9, 0xFCF9, 0xFCF9 }, +{ 0xFCFA, 0xFCFA, 0xFCFA }, +{ 0xFCFB, 0xFCFB, 0xFCFB }, +{ 0xFCFC, 0xFCFC, 0xFCFC }, +{ 0xFCFD, 0xFCFD, 0xFCFD }, +{ 0xFCFE, 0xFCFE, 0xFCFE }, +{ 0xFCFF, 0xFCFF, 0xFCFF }, +{ 0xFD00, 0xFD00, 0xFD00 }, +{ 0xFD01, 0xFD01, 0xFD01 }, +{ 0xFD02, 0xFD02, 0xFD02 }, +{ 0xFD03, 0xFD03, 0xFD03 }, +{ 0xFD04, 0xFD04, 0xFD04 }, +{ 0xFD05, 0xFD05, 0xFD05 }, +{ 0xFD06, 0xFD06, 0xFD06 }, +{ 0xFD07, 0xFD07, 0xFD07 }, +{ 0xFD08, 0xFD08, 0xFD08 }, +{ 0xFD09, 0xFD09, 0xFD09 }, +{ 0xFD0A, 0xFD0A, 0xFD0A }, +{ 0xFD0B, 0xFD0B, 0xFD0B }, +{ 0xFD0C, 0xFD0C, 0xFD0C }, +{ 0xFD0D, 0xFD0D, 0xFD0D }, +{ 0xFD0E, 0xFD0E, 0xFD0E }, +{ 0xFD0F, 0xFD0F, 0xFD0F }, +{ 0xFD10, 0xFD10, 0xFD10 }, +{ 0xFD11, 0xFD11, 0xFD11 }, +{ 0xFD12, 0xFD12, 0xFD12 }, +{ 0xFD13, 0xFD13, 0xFD13 }, +{ 0xFD14, 0xFD14, 0xFD14 }, +{ 0xFD15, 0xFD15, 0xFD15 }, +{ 0xFD16, 0xFD16, 0xFD16 }, +{ 0xFD17, 0xFD17, 0xFD17 }, +{ 0xFD18, 0xFD18, 0xFD18 }, +{ 0xFD19, 0xFD19, 0xFD19 }, +{ 0xFD1A, 0xFD1A, 0xFD1A }, +{ 0xFD1B, 0xFD1B, 0xFD1B }, +{ 0xFD1C, 0xFD1C, 0xFD1C }, +{ 0xFD1D, 0xFD1D, 0xFD1D }, +{ 0xFD1E, 0xFD1E, 0xFD1E }, +{ 0xFD1F, 0xFD1F, 0xFD1F }, +{ 0xFD20, 0xFD20, 0xFD20 }, +{ 0xFD21, 0xFD21, 0xFD21 }, +{ 0xFD22, 0xFD22, 0xFD22 }, +{ 0xFD23, 0xFD23, 0xFD23 }, +{ 0xFD24, 0xFD24, 0xFD24 }, +{ 0xFD25, 0xFD25, 0xFD25 }, +{ 0xFD26, 0xFD26, 0xFD26 }, +{ 0xFD27, 0xFD27, 0xFD27 }, +{ 0xFD28, 0xFD28, 0xFD28 }, +{ 0xFD29, 0xFD29, 0xFD29 }, +{ 0xFD2A, 0xFD2A, 0xFD2A }, +{ 0xFD2B, 0xFD2B, 0xFD2B }, +{ 0xFD2C, 0xFD2C, 0xFD2C }, +{ 0xFD2D, 0xFD2D, 0xFD2D }, +{ 0xFD2E, 0xFD2E, 0xFD2E }, +{ 0xFD2F, 0xFD2F, 0xFD2F }, +{ 0xFD30, 0xFD30, 0xFD30 }, +{ 0xFD31, 0xFD31, 0xFD31 }, +{ 0xFD32, 0xFD32, 0xFD32 }, +{ 0xFD33, 0xFD33, 0xFD33 }, +{ 0xFD34, 0xFD34, 0xFD34 }, +{ 0xFD35, 0xFD35, 0xFD35 }, +{ 0xFD36, 0xFD36, 0xFD36 }, +{ 0xFD37, 0xFD37, 0xFD37 }, +{ 0xFD38, 0xFD38, 0xFD38 }, +{ 0xFD39, 0xFD39, 0xFD39 }, +{ 0xFD3A, 0xFD3A, 0xFD3A }, +{ 0xFD3B, 0xFD3B, 0xFD3B }, +{ 0xFD3C, 0xFD3C, 0xFD3C }, +{ 0xFD3D, 0xFD3D, 0xFD3D }, +{ 0xFD50, 0xFD50, 0xFD50 }, +{ 0xFD51, 0xFD51, 0xFD51 }, +{ 0xFD52, 0xFD52, 0xFD52 }, +{ 0xFD53, 0xFD53, 0xFD53 }, +{ 0xFD54, 0xFD54, 0xFD54 }, +{ 0xFD55, 0xFD55, 0xFD55 }, +{ 0xFD56, 0xFD56, 0xFD56 }, +{ 0xFD57, 0xFD57, 0xFD57 }, +{ 0xFD58, 0xFD58, 0xFD58 }, +{ 0xFD59, 0xFD59, 0xFD59 }, +{ 0xFD5A, 0xFD5A, 0xFD5A }, +{ 0xFD5B, 0xFD5B, 0xFD5B }, +{ 0xFD5C, 0xFD5C, 0xFD5C }, +{ 0xFD5D, 0xFD5D, 0xFD5D }, +{ 0xFD5E, 0xFD5E, 0xFD5E }, +{ 0xFD5F, 0xFD5F, 0xFD5F }, +{ 0xFD60, 0xFD60, 0xFD60 }, +{ 0xFD61, 0xFD61, 0xFD61 }, +{ 0xFD62, 0xFD62, 0xFD62 }, +{ 0xFD63, 0xFD63, 0xFD63 }, +{ 0xFD64, 0xFD64, 0xFD64 }, +{ 0xFD65, 0xFD65, 0xFD65 }, +{ 0xFD66, 0xFD66, 0xFD66 }, +{ 0xFD67, 0xFD67, 0xFD67 }, +{ 0xFD68, 0xFD68, 0xFD68 }, +{ 0xFD69, 0xFD69, 0xFD69 }, +{ 0xFD6A, 0xFD6A, 0xFD6A }, +{ 0xFD6B, 0xFD6B, 0xFD6B }, +{ 0xFD6C, 0xFD6C, 0xFD6C }, +{ 0xFD6D, 0xFD6D, 0xFD6D }, +{ 0xFD6E, 0xFD6E, 0xFD6E }, +{ 0xFD6F, 0xFD6F, 0xFD6F }, +{ 0xFD70, 0xFD70, 0xFD70 }, +{ 0xFD71, 0xFD71, 0xFD71 }, +{ 0xFD72, 0xFD72, 0xFD72 }, +{ 0xFD73, 0xFD73, 0xFD73 }, +{ 0xFD74, 0xFD74, 0xFD74 }, +{ 0xFD75, 0xFD75, 0xFD75 }, +{ 0xFD76, 0xFD76, 0xFD76 }, +{ 0xFD77, 0xFD77, 0xFD77 }, +{ 0xFD78, 0xFD78, 0xFD78 }, +{ 0xFD79, 0xFD79, 0xFD79 }, +{ 0xFD7A, 0xFD7A, 0xFD7A }, +{ 0xFD7B, 0xFD7B, 0xFD7B }, +{ 0xFD7C, 0xFD7C, 0xFD7C }, +{ 0xFD7D, 0xFD7D, 0xFD7D }, +{ 0xFD7E, 0xFD7E, 0xFD7E }, +{ 0xFD7F, 0xFD7F, 0xFD7F }, +{ 0xFD80, 0xFD80, 0xFD80 }, +{ 0xFD81, 0xFD81, 0xFD81 }, +{ 0xFD82, 0xFD82, 0xFD82 }, +{ 0xFD83, 0xFD83, 0xFD83 }, +{ 0xFD84, 0xFD84, 0xFD84 }, +{ 0xFD85, 0xFD85, 0xFD85 }, +{ 0xFD86, 0xFD86, 0xFD86 }, +{ 0xFD87, 0xFD87, 0xFD87 }, +{ 0xFD88, 0xFD88, 0xFD88 }, +{ 0xFD89, 0xFD89, 0xFD89 }, +{ 0xFD8A, 0xFD8A, 0xFD8A }, +{ 0xFD8B, 0xFD8B, 0xFD8B }, +{ 0xFD8C, 0xFD8C, 0xFD8C }, +{ 0xFD8D, 0xFD8D, 0xFD8D }, +{ 0xFD8E, 0xFD8E, 0xFD8E }, +{ 0xFD8F, 0xFD8F, 0xFD8F }, +{ 0xFD92, 0xFD92, 0xFD92 }, +{ 0xFD93, 0xFD93, 0xFD93 }, +{ 0xFD94, 0xFD94, 0xFD94 }, +{ 0xFD95, 0xFD95, 0xFD95 }, +{ 0xFD96, 0xFD96, 0xFD96 }, +{ 0xFD97, 0xFD97, 0xFD97 }, +{ 0xFD98, 0xFD98, 0xFD98 }, +{ 0xFD99, 0xFD99, 0xFD99 }, +{ 0xFD9A, 0xFD9A, 0xFD9A }, +{ 0xFD9B, 0xFD9B, 0xFD9B }, +{ 0xFD9C, 0xFD9C, 0xFD9C }, +{ 0xFD9D, 0xFD9D, 0xFD9D }, +{ 0xFD9E, 0xFD9E, 0xFD9E }, +{ 0xFD9F, 0xFD9F, 0xFD9F }, +{ 0xFDA0, 0xFDA0, 0xFDA0 }, +{ 0xFDA1, 0xFDA1, 0xFDA1 }, +{ 0xFDA2, 0xFDA2, 0xFDA2 }, +{ 0xFDA3, 0xFDA3, 0xFDA3 }, +{ 0xFDA4, 0xFDA4, 0xFDA4 }, +{ 0xFDA5, 0xFDA5, 0xFDA5 }, +{ 0xFDA6, 0xFDA6, 0xFDA6 }, +{ 0xFDA7, 0xFDA7, 0xFDA7 }, +{ 0xFDA8, 0xFDA8, 0xFDA8 }, +{ 0xFDA9, 0xFDA9, 0xFDA9 }, +{ 0xFDAA, 0xFDAA, 0xFDAA }, +{ 0xFDAB, 0xFDAB, 0xFDAB }, +{ 0xFDAC, 0xFDAC, 0xFDAC }, +{ 0xFDAD, 0xFDAD, 0xFDAD }, +{ 0xFDAE, 0xFDAE, 0xFDAE }, +{ 0xFDAF, 0xFDAF, 0xFDAF }, +{ 0xFDB0, 0xFDB0, 0xFDB0 }, +{ 0xFDB1, 0xFDB1, 0xFDB1 }, +{ 0xFDB2, 0xFDB2, 0xFDB2 }, +{ 0xFDB3, 0xFDB3, 0xFDB3 }, +{ 0xFDB4, 0xFDB4, 0xFDB4 }, +{ 0xFDB5, 0xFDB5, 0xFDB5 }, +{ 0xFDB6, 0xFDB6, 0xFDB6 }, +{ 0xFDB7, 0xFDB7, 0xFDB7 }, +{ 0xFDB8, 0xFDB8, 0xFDB8 }, +{ 0xFDB9, 0xFDB9, 0xFDB9 }, +{ 0xFDBA, 0xFDBA, 0xFDBA }, +{ 0xFDBB, 0xFDBB, 0xFDBB }, +{ 0xFDBC, 0xFDBC, 0xFDBC }, +{ 0xFDBD, 0xFDBD, 0xFDBD }, +{ 0xFDBE, 0xFDBE, 0xFDBE }, +{ 0xFDBF, 0xFDBF, 0xFDBF }, +{ 0xFDC0, 0xFDC0, 0xFDC0 }, +{ 0xFDC1, 0xFDC1, 0xFDC1 }, +{ 0xFDC2, 0xFDC2, 0xFDC2 }, +{ 0xFDC3, 0xFDC3, 0xFDC3 }, +{ 0xFDC4, 0xFDC4, 0xFDC4 }, +{ 0xFDC5, 0xFDC5, 0xFDC5 }, +{ 0xFDC6, 0xFDC6, 0xFDC6 }, +{ 0xFDC7, 0xFDC7, 0xFDC7 }, +{ 0xFDF0, 0xFDF0, 0xFDF0 }, +{ 0xFDF1, 0xFDF1, 0xFDF1 }, +{ 0xFDF2, 0xFDF2, 0xFDF2 }, +{ 0xFDF3, 0xFDF3, 0xFDF3 }, +{ 0xFDF4, 0xFDF4, 0xFDF4 }, +{ 0xFDF5, 0xFDF5, 0xFDF5 }, +{ 0xFDF6, 0xFDF6, 0xFDF6 }, +{ 0xFDF7, 0xFDF7, 0xFDF7 }, +{ 0xFDF8, 0xFDF8, 0xFDF8 }, +{ 0xFDF9, 0xFDF9, 0xFDF9 }, +{ 0xFDFA, 0xFDFA, 0xFDFA }, +{ 0xFDFB, 0xFDFB, 0xFDFB }, +{ 0xFE00, 0xFE00, 0xFE00 }, +{ 0xFE01, 0xFE01, 0xFE01 }, +{ 0xFE02, 0xFE02, 0xFE02 }, +{ 0xFE03, 0xFE03, 0xFE03 }, +{ 0xFE04, 0xFE04, 0xFE04 }, +{ 0xFE05, 0xFE05, 0xFE05 }, +{ 0xFE06, 0xFE06, 0xFE06 }, +{ 0xFE07, 0xFE07, 0xFE07 }, +{ 0xFE08, 0xFE08, 0xFE08 }, +{ 0xFE09, 0xFE09, 0xFE09 }, +{ 0xFE0A, 0xFE0A, 0xFE0A }, +{ 0xFE0B, 0xFE0B, 0xFE0B }, +{ 0xFE0C, 0xFE0C, 0xFE0C }, +{ 0xFE0D, 0xFE0D, 0xFE0D }, +{ 0xFE0E, 0xFE0E, 0xFE0E }, +{ 0xFE0F, 0xFE0F, 0xFE0F }, +{ 0xFE20, 0xFE20, 0xFE20 }, +{ 0xFE21, 0xFE21, 0xFE21 }, +{ 0xFE22, 0xFE22, 0xFE22 }, +{ 0xFE23, 0xFE23, 0xFE23 }, +{ 0xFE70, 0xFE70, 0xFE70 }, +{ 0xFE71, 0xFE71, 0xFE71 }, +{ 0xFE72, 0xFE72, 0xFE72 }, +{ 0xFE73, 0xFE73, 0xFE73 }, +{ 0xFE74, 0xFE74, 0xFE74 }, +{ 0xFE76, 0xFE76, 0xFE76 }, +{ 0xFE77, 0xFE77, 0xFE77 }, +{ 0xFE78, 0xFE78, 0xFE78 }, +{ 0xFE79, 0xFE79, 0xFE79 }, +{ 0xFE7A, 0xFE7A, 0xFE7A }, +{ 0xFE7B, 0xFE7B, 0xFE7B }, +{ 0xFE7C, 0xFE7C, 0xFE7C }, +{ 0xFE7D, 0xFE7D, 0xFE7D }, +{ 0xFE7E, 0xFE7E, 0xFE7E }, +{ 0xFE7F, 0xFE7F, 0xFE7F }, +{ 0xFE80, 0xFE80, 0xFE80 }, +{ 0xFE81, 0xFE81, 0xFE81 }, +{ 0xFE82, 0xFE82, 0xFE82 }, +{ 0xFE83, 0xFE83, 0xFE83 }, +{ 0xFE84, 0xFE84, 0xFE84 }, +{ 0xFE85, 0xFE85, 0xFE85 }, +{ 0xFE86, 0xFE86, 0xFE86 }, +{ 0xFE87, 0xFE87, 0xFE87 }, +{ 0xFE88, 0xFE88, 0xFE88 }, +{ 0xFE89, 0xFE89, 0xFE89 }, +{ 0xFE8A, 0xFE8A, 0xFE8A }, +{ 0xFE8B, 0xFE8B, 0xFE8B }, +{ 0xFE8C, 0xFE8C, 0xFE8C }, +{ 0xFE8D, 0xFE8D, 0xFE8D }, +{ 0xFE8E, 0xFE8E, 0xFE8E }, +{ 0xFE8F, 0xFE8F, 0xFE8F }, +{ 0xFE90, 0xFE90, 0xFE90 }, +{ 0xFE91, 0xFE91, 0xFE91 }, +{ 0xFE92, 0xFE92, 0xFE92 }, +{ 0xFE93, 0xFE93, 0xFE93 }, +{ 0xFE94, 0xFE94, 0xFE94 }, +{ 0xFE95, 0xFE95, 0xFE95 }, +{ 0xFE96, 0xFE96, 0xFE96 }, +{ 0xFE97, 0xFE97, 0xFE97 }, +{ 0xFE98, 0xFE98, 0xFE98 }, +{ 0xFE99, 0xFE99, 0xFE99 }, +{ 0xFE9A, 0xFE9A, 0xFE9A }, +{ 0xFE9B, 0xFE9B, 0xFE9B }, +{ 0xFE9C, 0xFE9C, 0xFE9C }, +{ 0xFE9D, 0xFE9D, 0xFE9D }, +{ 0xFE9E, 0xFE9E, 0xFE9E }, +{ 0xFE9F, 0xFE9F, 0xFE9F }, +{ 0xFEA0, 0xFEA0, 0xFEA0 }, +{ 0xFEA1, 0xFEA1, 0xFEA1 }, +{ 0xFEA2, 0xFEA2, 0xFEA2 }, +{ 0xFEA3, 0xFEA3, 0xFEA3 }, +{ 0xFEA4, 0xFEA4, 0xFEA4 }, +{ 0xFEA5, 0xFEA5, 0xFEA5 }, +{ 0xFEA6, 0xFEA6, 0xFEA6 }, +{ 0xFEA7, 0xFEA7, 0xFEA7 }, +{ 0xFEA8, 0xFEA8, 0xFEA8 }, +{ 0xFEA9, 0xFEA9, 0xFEA9 }, +{ 0xFEAA, 0xFEAA, 0xFEAA }, +{ 0xFEAB, 0xFEAB, 0xFEAB }, +{ 0xFEAC, 0xFEAC, 0xFEAC }, +{ 0xFEAD, 0xFEAD, 0xFEAD }, +{ 0xFEAE, 0xFEAE, 0xFEAE }, +{ 0xFEAF, 0xFEAF, 0xFEAF }, +{ 0xFEB0, 0xFEB0, 0xFEB0 }, +{ 0xFEB1, 0xFEB1, 0xFEB1 }, +{ 0xFEB2, 0xFEB2, 0xFEB2 }, +{ 0xFEB3, 0xFEB3, 0xFEB3 }, +{ 0xFEB4, 0xFEB4, 0xFEB4 }, +{ 0xFEB5, 0xFEB5, 0xFEB5 }, +{ 0xFEB6, 0xFEB6, 0xFEB6 }, +{ 0xFEB7, 0xFEB7, 0xFEB7 }, +{ 0xFEB8, 0xFEB8, 0xFEB8 }, +{ 0xFEB9, 0xFEB9, 0xFEB9 }, +{ 0xFEBA, 0xFEBA, 0xFEBA }, +{ 0xFEBB, 0xFEBB, 0xFEBB }, +{ 0xFEBC, 0xFEBC, 0xFEBC }, +{ 0xFEBD, 0xFEBD, 0xFEBD }, +{ 0xFEBE, 0xFEBE, 0xFEBE }, +{ 0xFEBF, 0xFEBF, 0xFEBF }, +{ 0xFEC0, 0xFEC0, 0xFEC0 }, +{ 0xFEC1, 0xFEC1, 0xFEC1 }, +{ 0xFEC2, 0xFEC2, 0xFEC2 }, +{ 0xFEC3, 0xFEC3, 0xFEC3 }, +{ 0xFEC4, 0xFEC4, 0xFEC4 }, +{ 0xFEC5, 0xFEC5, 0xFEC5 }, +{ 0xFEC6, 0xFEC6, 0xFEC6 }, +{ 0xFEC7, 0xFEC7, 0xFEC7 }, +{ 0xFEC8, 0xFEC8, 0xFEC8 }, +{ 0xFEC9, 0xFEC9, 0xFEC9 }, +{ 0xFECA, 0xFECA, 0xFECA }, +{ 0xFECB, 0xFECB, 0xFECB }, +{ 0xFECC, 0xFECC, 0xFECC }, +{ 0xFECD, 0xFECD, 0xFECD }, +{ 0xFECE, 0xFECE, 0xFECE }, +{ 0xFECF, 0xFECF, 0xFECF }, +{ 0xFED0, 0xFED0, 0xFED0 }, +{ 0xFED1, 0xFED1, 0xFED1 }, +{ 0xFED2, 0xFED2, 0xFED2 }, +{ 0xFED3, 0xFED3, 0xFED3 }, +{ 0xFED4, 0xFED4, 0xFED4 }, +{ 0xFED5, 0xFED5, 0xFED5 }, +{ 0xFED6, 0xFED6, 0xFED6 }, +{ 0xFED7, 0xFED7, 0xFED7 }, +{ 0xFED8, 0xFED8, 0xFED8 }, +{ 0xFED9, 0xFED9, 0xFED9 }, +{ 0xFEDA, 0xFEDA, 0xFEDA }, +{ 0xFEDB, 0xFEDB, 0xFEDB }, +{ 0xFEDC, 0xFEDC, 0xFEDC }, +{ 0xFEDD, 0xFEDD, 0xFEDD }, +{ 0xFEDE, 0xFEDE, 0xFEDE }, +{ 0xFEDF, 0xFEDF, 0xFEDF }, +{ 0xFEE0, 0xFEE0, 0xFEE0 }, +{ 0xFEE1, 0xFEE1, 0xFEE1 }, +{ 0xFEE2, 0xFEE2, 0xFEE2 }, +{ 0xFEE3, 0xFEE3, 0xFEE3 }, +{ 0xFEE4, 0xFEE4, 0xFEE4 }, +{ 0xFEE5, 0xFEE5, 0xFEE5 }, +{ 0xFEE6, 0xFEE6, 0xFEE6 }, +{ 0xFEE7, 0xFEE7, 0xFEE7 }, +{ 0xFEE8, 0xFEE8, 0xFEE8 }, +{ 0xFEE9, 0xFEE9, 0xFEE9 }, +{ 0xFEEA, 0xFEEA, 0xFEEA }, +{ 0xFEEB, 0xFEEB, 0xFEEB }, +{ 0xFEEC, 0xFEEC, 0xFEEC }, +{ 0xFEED, 0xFEED, 0xFEED }, +{ 0xFEEE, 0xFEEE, 0xFEEE }, +{ 0xFEEF, 0xFEEF, 0xFEEF }, +{ 0xFEF0, 0xFEF0, 0xFEF0 }, +{ 0xFEF1, 0xFEF1, 0xFEF1 }, +{ 0xFEF2, 0xFEF2, 0xFEF2 }, +{ 0xFEF3, 0xFEF3, 0xFEF3 }, +{ 0xFEF4, 0xFEF4, 0xFEF4 }, +{ 0xFEF5, 0xFEF5, 0xFEF5 }, +{ 0xFEF6, 0xFEF6, 0xFEF6 }, +{ 0xFEF7, 0xFEF7, 0xFEF7 }, +{ 0xFEF8, 0xFEF8, 0xFEF8 }, +{ 0xFEF9, 0xFEF9, 0xFEF9 }, +{ 0xFEFA, 0xFEFA, 0xFEFA }, +{ 0xFEFB, 0xFEFB, 0xFEFB }, +{ 0xFEFC, 0xFEFC, 0xFEFC }, +{ 0xFF21, 0xFF21, 0xFF41 }, +{ 0xFF22, 0xFF22, 0xFF42 }, +{ 0xFF23, 0xFF23, 0xFF43 }, +{ 0xFF24, 0xFF24, 0xFF44 }, +{ 0xFF25, 0xFF25, 0xFF45 }, +{ 0xFF26, 0xFF26, 0xFF46 }, +{ 0xFF27, 0xFF27, 0xFF47 }, +{ 0xFF28, 0xFF28, 0xFF48 }, +{ 0xFF29, 0xFF29, 0xFF49 }, +{ 0xFF2A, 0xFF2A, 0xFF4A }, +{ 0xFF2B, 0xFF2B, 0xFF4B }, +{ 0xFF2C, 0xFF2C, 0xFF4C }, +{ 0xFF2D, 0xFF2D, 0xFF4D }, +{ 0xFF2E, 0xFF2E, 0xFF4E }, +{ 0xFF2F, 0xFF2F, 0xFF4F }, +{ 0xFF30, 0xFF30, 0xFF50 }, +{ 0xFF31, 0xFF31, 0xFF51 }, +{ 0xFF32, 0xFF32, 0xFF52 }, +{ 0xFF33, 0xFF33, 0xFF53 }, +{ 0xFF34, 0xFF34, 0xFF54 }, +{ 0xFF35, 0xFF35, 0xFF55 }, +{ 0xFF36, 0xFF36, 0xFF56 }, +{ 0xFF37, 0xFF37, 0xFF57 }, +{ 0xFF38, 0xFF38, 0xFF58 }, +{ 0xFF39, 0xFF39, 0xFF59 }, +{ 0xFF3A, 0xFF3A, 0xFF5A }, +{ 0xFF41, 0xFF21, 0xFF41 }, +{ 0xFF42, 0xFF22, 0xFF42 }, +{ 0xFF43, 0xFF23, 0xFF43 }, +{ 0xFF44, 0xFF24, 0xFF44 }, +{ 0xFF45, 0xFF25, 0xFF45 }, +{ 0xFF46, 0xFF26, 0xFF46 }, +{ 0xFF47, 0xFF27, 0xFF47 }, +{ 0xFF48, 0xFF28, 0xFF48 }, +{ 0xFF49, 0xFF29, 0xFF49 }, +{ 0xFF4A, 0xFF2A, 0xFF4A }, +{ 0xFF4B, 0xFF2B, 0xFF4B }, +{ 0xFF4C, 0xFF2C, 0xFF4C }, +{ 0xFF4D, 0xFF2D, 0xFF4D }, +{ 0xFF4E, 0xFF2E, 0xFF4E }, +{ 0xFF4F, 0xFF2F, 0xFF4F }, +{ 0xFF50, 0xFF30, 0xFF50 }, +{ 0xFF51, 0xFF31, 0xFF51 }, +{ 0xFF52, 0xFF32, 0xFF52 }, +{ 0xFF53, 0xFF33, 0xFF53 }, +{ 0xFF54, 0xFF34, 0xFF54 }, +{ 0xFF55, 0xFF35, 0xFF55 }, +{ 0xFF56, 0xFF36, 0xFF56 }, +{ 0xFF57, 0xFF37, 0xFF57 }, +{ 0xFF58, 0xFF38, 0xFF58 }, +{ 0xFF59, 0xFF39, 0xFF59 }, +{ 0xFF5A, 0xFF3A, 0xFF5A }, +{ 0xFF66, 0xFF66, 0xFF66 }, +{ 0xFF67, 0xFF67, 0xFF67 }, +{ 0xFF68, 0xFF68, 0xFF68 }, +{ 0xFF69, 0xFF69, 0xFF69 }, +{ 0xFF6A, 0xFF6A, 0xFF6A }, +{ 0xFF6B, 0xFF6B, 0xFF6B }, +{ 0xFF6C, 0xFF6C, 0xFF6C }, +{ 0xFF6D, 0xFF6D, 0xFF6D }, +{ 0xFF6E, 0xFF6E, 0xFF6E }, +{ 0xFF6F, 0xFF6F, 0xFF6F }, +{ 0xFF70, 0xFF70, 0xFF70 }, +{ 0xFF71, 0xFF71, 0xFF71 }, +{ 0xFF72, 0xFF72, 0xFF72 }, +{ 0xFF73, 0xFF73, 0xFF73 }, +{ 0xFF74, 0xFF74, 0xFF74 }, +{ 0xFF75, 0xFF75, 0xFF75 }, +{ 0xFF76, 0xFF76, 0xFF76 }, +{ 0xFF77, 0xFF77, 0xFF77 }, +{ 0xFF78, 0xFF78, 0xFF78 }, +{ 0xFF79, 0xFF79, 0xFF79 }, +{ 0xFF7A, 0xFF7A, 0xFF7A }, +{ 0xFF7B, 0xFF7B, 0xFF7B }, +{ 0xFF7C, 0xFF7C, 0xFF7C }, +{ 0xFF7D, 0xFF7D, 0xFF7D }, +{ 0xFF7E, 0xFF7E, 0xFF7E }, +{ 0xFF7F, 0xFF7F, 0xFF7F }, +{ 0xFF80, 0xFF80, 0xFF80 }, +{ 0xFF81, 0xFF81, 0xFF81 }, +{ 0xFF82, 0xFF82, 0xFF82 }, +{ 0xFF83, 0xFF83, 0xFF83 }, +{ 0xFF84, 0xFF84, 0xFF84 }, +{ 0xFF85, 0xFF85, 0xFF85 }, +{ 0xFF86, 0xFF86, 0xFF86 }, +{ 0xFF87, 0xFF87, 0xFF87 }, +{ 0xFF88, 0xFF88, 0xFF88 }, +{ 0xFF89, 0xFF89, 0xFF89 }, +{ 0xFF8A, 0xFF8A, 0xFF8A }, +{ 0xFF8B, 0xFF8B, 0xFF8B }, +{ 0xFF8C, 0xFF8C, 0xFF8C }, +{ 0xFF8D, 0xFF8D, 0xFF8D }, +{ 0xFF8E, 0xFF8E, 0xFF8E }, +{ 0xFF8F, 0xFF8F, 0xFF8F }, +{ 0xFF90, 0xFF90, 0xFF90 }, +{ 0xFF91, 0xFF91, 0xFF91 }, +{ 0xFF92, 0xFF92, 0xFF92 }, +{ 0xFF93, 0xFF93, 0xFF93 }, +{ 0xFF94, 0xFF94, 0xFF94 }, +{ 0xFF95, 0xFF95, 0xFF95 }, +{ 0xFF96, 0xFF96, 0xFF96 }, +{ 0xFF97, 0xFF97, 0xFF97 }, +{ 0xFF98, 0xFF98, 0xFF98 }, +{ 0xFF99, 0xFF99, 0xFF99 }, +{ 0xFF9A, 0xFF9A, 0xFF9A }, +{ 0xFF9B, 0xFF9B, 0xFF9B }, +{ 0xFF9C, 0xFF9C, 0xFF9C }, +{ 0xFF9D, 0xFF9D, 0xFF9D }, +{ 0xFF9E, 0xFF9E, 0xFF9E }, +{ 0xFF9F, 0xFF9F, 0xFF9F }, +{ 0xFFA0, 0xFFA0, 0xFFA0 }, +{ 0xFFA1, 0xFFA1, 0xFFA1 }, +{ 0xFFA2, 0xFFA2, 0xFFA2 }, +{ 0xFFA3, 0xFFA3, 0xFFA3 }, +{ 0xFFA4, 0xFFA4, 0xFFA4 }, +{ 0xFFA5, 0xFFA5, 0xFFA5 }, +{ 0xFFA6, 0xFFA6, 0xFFA6 }, +{ 0xFFA7, 0xFFA7, 0xFFA7 }, +{ 0xFFA8, 0xFFA8, 0xFFA8 }, +{ 0xFFA9, 0xFFA9, 0xFFA9 }, +{ 0xFFAA, 0xFFAA, 0xFFAA }, +{ 0xFFAB, 0xFFAB, 0xFFAB }, +{ 0xFFAC, 0xFFAC, 0xFFAC }, +{ 0xFFAD, 0xFFAD, 0xFFAD }, +{ 0xFFAE, 0xFFAE, 0xFFAE }, +{ 0xFFAF, 0xFFAF, 0xFFAF }, +{ 0xFFB0, 0xFFB0, 0xFFB0 }, +{ 0xFFB1, 0xFFB1, 0xFFB1 }, +{ 0xFFB2, 0xFFB2, 0xFFB2 }, +{ 0xFFB3, 0xFFB3, 0xFFB3 }, +{ 0xFFB4, 0xFFB4, 0xFFB4 }, +{ 0xFFB5, 0xFFB5, 0xFFB5 }, +{ 0xFFB6, 0xFFB6, 0xFFB6 }, +{ 0xFFB7, 0xFFB7, 0xFFB7 }, +{ 0xFFB8, 0xFFB8, 0xFFB8 }, +{ 0xFFB9, 0xFFB9, 0xFFB9 }, +{ 0xFFBA, 0xFFBA, 0xFFBA }, +{ 0xFFBB, 0xFFBB, 0xFFBB }, +{ 0xFFBC, 0xFFBC, 0xFFBC }, +{ 0xFFBD, 0xFFBD, 0xFFBD }, +{ 0xFFBE, 0xFFBE, 0xFFBE }, +{ 0xFFC2, 0xFFC2, 0xFFC2 }, +{ 0xFFC3, 0xFFC3, 0xFFC3 }, +{ 0xFFC4, 0xFFC4, 0xFFC4 }, +{ 0xFFC5, 0xFFC5, 0xFFC5 }, +{ 0xFFC6, 0xFFC6, 0xFFC6 }, +{ 0xFFC7, 0xFFC7, 0xFFC7 }, +{ 0xFFCA, 0xFFCA, 0xFFCA }, +{ 0xFFCB, 0xFFCB, 0xFFCB }, +{ 0xFFCC, 0xFFCC, 0xFFCC }, +{ 0xFFCD, 0xFFCD, 0xFFCD }, +{ 0xFFCE, 0xFFCE, 0xFFCE }, +{ 0xFFCF, 0xFFCF, 0xFFCF }, +{ 0xFFD2, 0xFFD2, 0xFFD2 }, +{ 0xFFD3, 0xFFD3, 0xFFD3 }, +{ 0xFFD4, 0xFFD4, 0xFFD4 }, +{ 0xFFD5, 0xFFD5, 0xFFD5 }, +{ 0xFFD6, 0xFFD6, 0xFFD6 }, +{ 0xFFD7, 0xFFD7, 0xFFD7 }, +{ 0xFFDA, 0xFFDA, 0xFFDA }, +{ 0xFFDB, 0xFFDB, 0xFFDB }, +{ 0xFFDC, 0xFFDC, 0xFFDC } +}; diff --git a/hunspell/src/parsers/Makefile.am b/hunspell/src/parsers/Makefile.am new file mode 100644 index 000000000..ffd13f345 --- /dev/null +++ b/hunspell/src/parsers/Makefile.am @@ -0,0 +1,10 @@ +lib_LIBRARIES=libparsers.a +libparsers_a_SOURCES=firstparser.cxx htmlparser.cxx \ + latexparser.cxx manparser.cxx \ + textparser.cxx + +noinst_PROGRAMS=testparser +testparser_SOURCES=firstparser.cxx firstparser.hxx htmlparser.cxx htmlparser.hxx latexparser.cxx latexparser.hxx manparser.cxx manparser.hxx testparser.cxx textparser.cxx textparser.hxx + +# need mystrdup() +LDADD = ../hunspell/libhunspell.la diff --git a/hunspell/src/parsers/Makefile.in b/hunspell/src/parsers/Makefile.in new file mode 100644 index 000000000..888958b3a --- /dev/null +++ b/hunspell/src/parsers/Makefile.in @@ -0,0 +1,533 @@ +# Makefile.in generated by automake 1.9.6 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +target_triplet = @target@ +noinst_PROGRAMS = testparser$(EXEEXT) +subdir = src/parsers +DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \ + $(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \ + $(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/isc-posix.m4 \ + $(top_srcdir)/m4/lcmessage.m4 $(top_srcdir)/m4/lib-ld.m4 \ + $(top_srcdir)/m4/lib-link.m4 $(top_srcdir)/m4/lib-prefix.m4 \ + $(top_srcdir)/m4/progtest.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = `echo $$p | sed -e 's|^.*/||'`; +am__installdirs = "$(DESTDIR)$(libdir)" +libLIBRARIES_INSTALL = $(INSTALL_DATA) +LIBRARIES = $(lib_LIBRARIES) +ARFLAGS = cru +libparsers_a_AR = $(AR) $(ARFLAGS) +libparsers_a_LIBADD = +am_libparsers_a_OBJECTS = firstparser.$(OBJEXT) htmlparser.$(OBJEXT) \ + latexparser.$(OBJEXT) manparser.$(OBJEXT) textparser.$(OBJEXT) +libparsers_a_OBJECTS = $(am_libparsers_a_OBJECTS) +PROGRAMS = $(noinst_PROGRAMS) +am_testparser_OBJECTS = firstparser.$(OBJEXT) htmlparser.$(OBJEXT) \ + latexparser.$(OBJEXT) manparser.$(OBJEXT) testparser.$(OBJEXT) \ + textparser.$(OBJEXT) +testparser_OBJECTS = $(am_testparser_OBJECTS) +testparser_LDADD = $(LDADD) +testparser_DEPENDENCIES = ../hunspell/libhunspell.la +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) --tag=CXX --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +SOURCES = $(libparsers_a_SOURCES) $(testparser_SOURCES) +DIST_SOURCES = $(libparsers_a_SOURCES) $(testparser_SOURCES) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ALLOCA = @ALLOCA@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CURSESLIB = @CURSESLIB@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DATADIRNAME = @DATADIRNAME@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO = @ECHO@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +F77 = @F77@ +FFLAGS = @FFLAGS@ +GENCAT = @GENCAT@ +GLIBC21 = @GLIBC21@ +GMSGFMT = @GMSGFMT@ +HUNSPELL_VERSION_MAJOR = @HUNSPELL_VERSION_MAJOR@ +HUNSPELL_VERSION_MINOR = @HUNSPELL_VERSION_MINOR@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +LDFLAGS = @LDFLAGS@ +LIBICONV = @LIBICONV@ +LIBINTL = @LIBINTL@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LTLIBICONV = @LTLIBICONV@ +LTLIBINTL = @LTLIBINTL@ +LTLIBOBJS = @LTLIBOBJS@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +MSGMERGE = @MSGMERGE@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +READLINELIB = @READLINELIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +VERSION = @VERSION@ +XFAILED = @XFAILED@ +XGETTEXT = @XGETTEXT@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_F77 = @ac_ct_F77@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@ +am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ +lib_LIBRARIES = libparsers.a +libparsers_a_SOURCES = firstparser.cxx htmlparser.cxx \ + latexparser.cxx manparser.cxx \ + textparser.cxx + +testparser_SOURCES = firstparser.cxx firstparser.hxx htmlparser.cxx htmlparser.hxx latexparser.cxx latexparser.hxx manparser.cxx manparser.hxx testparser.cxx textparser.cxx textparser.hxx + +# need mystrdup() +LDADD = ../hunspell/libhunspell.la +all: all-am + +.SUFFIXES: +.SUFFIXES: .cxx .lo .o .obj +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ + && exit 0; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/parsers/Makefile'; \ + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/parsers/Makefile +.PRECIOUS: Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +install-libLIBRARIES: $(lib_LIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)" + @list='$(lib_LIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + f=$(am__strip_dir) \ + echo " $(libLIBRARIES_INSTALL) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \ + $(libLIBRARIES_INSTALL) "$$p" "$(DESTDIR)$(libdir)/$$f"; \ + else :; fi; \ + done + @$(POST_INSTALL) + @list='$(lib_LIBRARIES)'; for p in $$list; do \ + if test -f $$p; then \ + p=$(am__strip_dir) \ + echo " $(RANLIB) '$(DESTDIR)$(libdir)/$$p'"; \ + $(RANLIB) "$(DESTDIR)$(libdir)/$$p"; \ + else :; fi; \ + done + +uninstall-libLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LIBRARIES)'; for p in $$list; do \ + p=$(am__strip_dir) \ + echo " rm -f '$(DESTDIR)$(libdir)/$$p'"; \ + rm -f "$(DESTDIR)$(libdir)/$$p"; \ + done + +clean-libLIBRARIES: + -test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES) +libparsers.a: $(libparsers_a_OBJECTS) $(libparsers_a_DEPENDENCIES) + -rm -f libparsers.a + $(libparsers_a_AR) libparsers.a $(libparsers_a_OBJECTS) $(libparsers_a_LIBADD) + $(RANLIB) libparsers.a + +clean-noinstPROGRAMS: + @list='$(noinst_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +testparser$(EXEEXT): $(testparser_OBJECTS) $(testparser_DEPENDENCIES) + @rm -f testparser$(EXEEXT) + $(CXXLINK) $(testparser_LDFLAGS) $(testparser_OBJECTS) $(testparser_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/firstparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/htmlparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/latexparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/manparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/testparser.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/textparser.Po@am__quote@ + +.cxx.o: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $< + +.cxx.obj: +@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cxx.lo: +@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ +@am__fastdepCXX_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkdir_p) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LIBRARIES) $(PROGRAMS) +installdirs: + for dir in "$(DESTDIR)$(libdir)"; do \ + test -z "$$dir" || $(mkdir_p) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libLIBRARIES clean-libtool \ + clean-noinstPROGRAMS mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-libLIBRARIES + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-info-am uninstall-libLIBRARIES + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ + clean-libLIBRARIES clean-libtool clean-noinstPROGRAMS ctags \ + distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-libLIBRARIES install-man install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-info-am \ + uninstall-libLIBRARIES + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/hunspell/src/parsers/firstparser.cxx b/hunspell/src/parsers/firstparser.cxx new file mode 100644 index 000000000..786ecea2e --- /dev/null +++ b/hunspell/src/parsers/firstparser.cxx @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +#include "../hunspell/csutil.hxx" +#include "firstparser.hxx" + +#ifndef W32 +using namespace std; +#endif + +FirstParser::FirstParser(const char * wordchars) +{ + init(wordchars); +} + +FirstParser::~FirstParser() +{ +} + +char * FirstParser::next_token() +{ + char * tabpos = strchr(line[actual],'\t'); + if ((tabpos) && (tabpos - line[actual]>token)) { + char * t = (char *) malloc(tabpos - line[actual] + 1); + t[tabpos - line[actual]] = '\0'; + token = tabpos - line[actual] +1; + if (t) return strncpy(t, line[actual], tabpos - line[actual]); + fprintf(stderr,"Error - Insufficient Memory\n"); + } + return NULL; +} diff --git a/hunspell/src/parsers/firstparser.hxx b/hunspell/src/parsers/firstparser.hxx new file mode 100644 index 000000000..1f792899c --- /dev/null +++ b/hunspell/src/parsers/firstparser.hxx @@ -0,0 +1,34 @@ +/* + * parser classes of HunTools + * + * implemented: text, HTML, TeX, first word + * + * Copyright (C) 2003, Laszlo Nemeth + * + */ + +#ifndef _FIRSTPARSER_HXX_ +#define _FIRSTPARSER_HXX_ + +#include "textparser.hxx" + +/* + * Check first word of the input line + * + */ + +class FirstParser : public TextParser +{ + +public: + + + FirstParser(const char * wc); + virtual ~FirstParser(); + + virtual char * next_token(); + +}; + +#endif + diff --git a/hunspell/src/parsers/htmlparser.cxx b/hunspell/src/parsers/htmlparser.cxx new file mode 100644 index 000000000..06ead697d --- /dev/null +++ b/hunspell/src/parsers/htmlparser.cxx @@ -0,0 +1,151 @@ +#include +#include +#include +#include + +#include "../hunspell/csutil.hxx" +#include "htmlparser.hxx" + + +#ifndef W32 +using namespace std; +#endif + +enum { ST_NON_WORD, ST_WORD, ST_TAG, ST_CHAR_ENTITY, ST_OTHER_TAG, ST_ATTRIB }; + +static char * PATTERN[][2] = { + { "" }, + { "" }, + { "" }, + { "" }, + { "" }, + { "" }, + { "" }, + { "" }, + { "" }, + { "" }, + { "<[cdata[", "]]>" }, // XML comment + { "<", ">" } +}; + +#define PATTERN_LEN (sizeof(PATTERN) / (sizeof(char *) * 2)) + +static char * PATTERN2[][2] = { + { " 0) && (line[actual][head] == '>')) { + state = ST_NON_WORD; + } else if (((i = look_pattern(PATTERN, PATTERN_LEN, 1)) != -1) && + (strcmp(PATTERN[i][1],PATTERN[pattern_num][1]) == 0)) { + state = ST_NON_WORD; + head += strlen(PATTERN[pattern_num][1]) - 1; + } else if ( (strcmp(PATTERN[pattern_num][0], "<") == 0) && + ((line[actual][head] == '"') || (line[actual][head] == '\''))) { + quotmark = line[actual][head]; + state = ST_ATTRIB; + } + break; + case ST_ATTRIB: // non word chars + prevstate = ST_ATTRIB; + if (line[actual][head] == quotmark) { + state = ST_TAG; + if (checkattr == 2) checkattr = 1; + // for IMG ALT + } else if (is_wordchar(line[actual] + head) && (checkattr == 2)) { + state = ST_WORD; + token = head; + } else if (line[actual][head] == '&') { + state = ST_CHAR_ENTITY; + } + break; + case ST_CHAR_ENTITY: // SGML element + if ((tolower(line[actual][head]) < 'a') || (tolower(line[actual][head]) > 'z')) { + state = prevstate; + head--; + } + } + if (next_char(line[actual], &head)) return NULL; + } +} diff --git a/hunspell/src/parsers/htmlparser.hxx b/hunspell/src/parsers/htmlparser.hxx new file mode 100644 index 000000000..72a02306a --- /dev/null +++ b/hunspell/src/parsers/htmlparser.hxx @@ -0,0 +1,44 @@ +/* + * HTML parser class for MySpell + * + * implemented: text, HTML, TeX + * + * Copyright (C) 2002, Laszlo Nemeth + * + */ + +#ifndef _HTMLPARSER_HXX_ +#define _HTMLPARSER_HXX_ + + +#include "textparser.hxx" + +/* + * HTML Parser + * + */ + +class HTMLParser : public TextParser +{ +public: + + HTMLParser(const char * wc); + HTMLParser(unsigned short * wordchars, int len); + virtual ~HTMLParser(); + + virtual char * next_token(); + +private: + + int look_pattern(char * p[][2], unsigned int len, int column); + int pattern_num; + int pattern2_num; + int prevstate; + int checkattr; + char quotmark; + +}; + + +#endif + diff --git a/hunspell/src/parsers/latexparser.cxx b/hunspell/src/parsers/latexparser.cxx new file mode 100644 index 000000000..4b0a32600 --- /dev/null +++ b/hunspell/src/parsers/latexparser.cxx @@ -0,0 +1,214 @@ +#include +#include +#include +#include + +#include "../hunspell/csutil.hxx" +#include "latexparser.hxx" + +#ifndef W32 +using namespace std; +#endif + +static struct { + char * pat[2]; + int arg; +} PATTERN[] = { + { { "\\(", "\\)" } , 0 }, + { { "$$", "$$" } , 0 }, + { { "$", "$" } , 0 }, + { { "\\begin{math}", "\\end{math}" } , 0 }, + { { "\\[", "\\]" } , 0 }, + { { "\\begin{displaymath}", "\\end{displaymath}" } , 0 }, + { { "\\begin{equation}", "\\end{equation}" } , 0 }, + { { "\\cite", NULL } , 1 }, + { { "\\nocite", NULL } , 1 }, + { { "\\index", NULL } , 1 }, + { { "\\label", NULL } , 1 }, + { { "\\ref", NULL } , 1 }, + { { "\\pageref", NULL } , 1 }, + { { "\\parbox", NULL } , 1 }, + { { "\\begin{verbatim}", "\\end{verbatim}" } , 0 }, + { { "\\verb+", "+" } , 0 }, + { { "\\verb|", "|" } , 0 }, + { { "\\verb#", "#" } , 0 }, + { { "\\verb*", "*" } , 0 }, + { { "\\documentstyle", "\\begin{document}" } , 0 }, + { { "\\documentclass", "\\begin{document}" } , 0 }, +// { { "\\documentclass", NULL } , 1 }, + { { "\\usepackage", NULL } , 1 }, + { { "\\includeonly", NULL } , 1 }, + { { "\\include", NULL } , 1 }, + { { "\\input", NULL } , 1 }, + { { "\\vspace", NULL } , 1 }, + { { "\\setlength", NULL } , 2 }, + { { "\\addtolength", NULL } , 2 }, + { { "\\settowidth", NULL } , 2 }, + { { "\\rule", NULL } , 2 }, + { { "\\hspace", NULL } , 1 } , + { { "\\vspace", NULL } , 1 } , + { { "\\\\[", "]" } , 0 }, + { { "\\pagebreak[", "]" } , 0 } , + { { "\\nopagebreak[", "]" } , 0 } , + { { "\\enlargethispage", NULL } , 1 } , + { { "\\begin{tabular}", NULL } , 1 } , + { { "\\addcontentsline", NULL } , 2 } , + { { "\\begin{thebibliography}", NULL } , 1 } , + { { "\\bibliography", NULL } , 1 } , + { { "\\bibliographystyle", NULL } , 1 } , + { { "\\bibitem", NULL } , 1 } , + { { "\\begin", NULL } , 1 } , + { { "\\end", NULL } , 1 } , + { { "\\pagestyle", NULL } , 1 } , + { { "\\pagenumbering", NULL } , 1 } , + { { "\\thispagestyle", NULL } , 1 } , + { { "\\newtheorem", NULL } , 2 }, + { { "\\newcommand", NULL } , 2 }, + { { "\\renewcommand", NULL } , 2 }, + { { "\\setcounter", NULL } , 2 }, + { { "\\addtocounter", NULL } , 1 }, + { { "\\stepcounter", NULL } , 1 }, + { { "\\selectlanguage", NULL } , 1 }, + { { "\\inputencoding", NULL } , 1 }, + { { "\\hyphenation", NULL } , 1 }, + { { "\\definecolor", NULL } , 3 }, + { { "\\color", NULL } , 1 }, + { { "\\textcolor", NULL } , 1 }, + { { "\\pagecolor", NULL } , 1 }, + { { "\\colorbox", NULL } , 2 }, + { { "\\fcolorbox", NULL } , 2 }, + { { "\\declaregraphicsextensions", NULL } , 1 }, + { { "\\psfig", NULL } , 1 }, + { { "\\url", NULL } , 1 } +}; + +#define PATTERN_LEN (sizeof(PATTERN) / ((sizeof(char *) * 2) + sizeof(int))) + +LaTeXParser::LaTeXParser(const char * wordchars) +{ + init(wordchars); +} + +LaTeXParser::LaTeXParser(unsigned short * wordchars, int len) +{ + init(wordchars, len); +} + +LaTeXParser::~LaTeXParser() +{ +} + +int LaTeXParser::look_pattern(int col) +{ + for (unsigned int i = 0; i < PATTERN_LEN; i++) { + char * j = line[actual] + head; + char * k = PATTERN[i].pat[col]; + if (! k) continue; + while ((*k != '\0') && (tolower(*j) == *k)) { + j++; + k++; + } + if (*k == '\0') return i; + } + return -1; +} + +/* + * LaTeXParser + * + * state 0: not wordchar + * state 1: wordchar + * state 2: comments + * state 3: commands + * state 4: commands with arguments + * state 5: % comment + * + */ + + +char * LaTeXParser::next_token() +{ + int i; + int slash = 0; + for (;;) { + // fprintf(stderr,"depth: %d, state: %d, , arg: %d, token: %s\n",depth,state,arg,line[actual]+head); + + switch (state) + { + case 0: // non word chars + if ((pattern_num = look_pattern(0)) != -1) { + if (PATTERN[pattern_num].pat[1]) { + state = 2; + } else { + state = 4; + depth = 0; + arg = 0; + opt = 1; + } + head += strlen(PATTERN[pattern_num].pat[0]) - 1; + } else if ((line[actual][head] == '%')) { + state = 5; + } else if (is_wordchar(line[actual] + head)) { + state = 1; + token = head; + } else if (line[actual][head] == '\\') { + if (line[actual][head + 1] == '\\' || // \\ (linebreak) + (line[actual][head + 1] == '$') || // \$ (dollar sign) + (line[actual][head + 1] == '%')) { // \% (percent) + head++; + break; + } + state = 3; + } else if (line[actual][head] == '%') { + if ((head==0) || (line[actual][head - 1] != '\\')) state = 5; + } + break; + case 1: // wordchar + if (! is_wordchar(line[actual] + head)) { + state = 0; + char * t = alloc_token(token, &head); + if (t) return t; + } + break; + case 2: // comment, labels, etc + if (((i = look_pattern(1)) != -1) && + (strcmp(PATTERN[i].pat[1],PATTERN[pattern_num].pat[1]) == 0)) { + state = 0; + head += strlen(PATTERN[pattern_num].pat[1]) - 1; + } + break; + case 3: // command + if ((tolower(line[actual][head]) < 'a') || (tolower(line[actual][head]) > 'z')) { + state = 0; + head--; + } + break; + case 4: // command with arguments + if (slash && (line[actual][head] != '\0')) { + slash = 0; + head++; + break; + } else if (line[actual][head]=='\\') { + slash = 1; + } else if ((line[actual][head] == '{') || + ((opt) && (line[actual][head] == '['))) { + depth++; + opt = 0; + } else if (line[actual][head] == '}') { + depth--; + if (depth == 0) { + opt = 1; + arg++; + } + if (((depth == 0) && (arg == PATTERN[pattern_num].arg)) || + (depth < 0) ) { + state = 0; // XXX not handles the last optional arg. + } + } else if (line[actual][head] == ']') depth--; + } // case + if (next_char(line[actual], &head)) { + if (state == 5) state = 0; + return NULL; + } + } +} diff --git a/hunspell/src/parsers/latexparser.hxx b/hunspell/src/parsers/latexparser.hxx new file mode 100644 index 000000000..851ecb9a4 --- /dev/null +++ b/hunspell/src/parsers/latexparser.hxx @@ -0,0 +1,44 @@ +/* + * parser classes for MySpell + * + * implemented: text, HTML, TeX + * + * Copyright (C) 2002, Laszlo Nemeth + * + */ + +#ifndef _LATEXPARSER_HXX_ +#define _LATEXPARSER_HXX_ + + +#include "textparser.hxx" + +/* + * HTML Parser + * + */ + +class LaTeXParser : public TextParser +{ + int pattern_num; // number of comment + int depth; // depth of blocks + int arg; // arguments's number + int opt; // optional argument attrib. + +public: + + LaTeXParser(const char * wc); + LaTeXParser(unsigned short * wordchars, int len); + virtual ~LaTeXParser(); + + virtual char * next_token(); + +private: + + int look_pattern(int col); + +}; + + +#endif + diff --git a/hunspell/src/parsers/manparser.cxx b/hunspell/src/parsers/manparser.cxx new file mode 100644 index 000000000..25858dad8 --- /dev/null +++ b/hunspell/src/parsers/manparser.cxx @@ -0,0 +1,71 @@ +#include +#include +#include +#include + +#include "../hunspell/csutil.hxx" +#include "manparser.hxx" + + +#ifndef W32 +using namespace std; +#endif + +ManParser::ManParser() { +} + +ManParser::ManParser(const char * wordchars) +{ + init(wordchars); +} + +ManParser::ManParser(unsigned short * wordchars, int len) +{ + init(wordchars, len); +} + +ManParser::~ManParser() +{ +} + +char * ManParser::next_token() +{ + for (;;) { + switch (state) + { + case 1: // command arguments + if (line[actual][head] == ' ') state = 2; + break; + case 0: // dot in begin of line + if (line[actual][0] == '.') { + state = 1; + break; + } else { + state = 2; + } + // no break + case 2: // non word chars + if (is_wordchar(line[actual] + head)) { + state = 3; + token = head; + } else if ((line[actual][head] == '\\') && + (line[actual][head + 1] == 'f') && + (line[actual][head + 2] != '\0')) { + head += 2; + } + break; + case 3: // wordchar + if (! is_wordchar(line[actual] + head)) { + state = 2; + char * t = alloc_token(token, &head); + if (t) return t; + } + break; + } + if (next_char(line[actual], &head)) { + state = 0; + return NULL; + } + } +} + diff --git a/hunspell/src/parsers/manparser.hxx b/hunspell/src/parsers/manparser.hxx new file mode 100644 index 000000000..6db37c539 --- /dev/null +++ b/hunspell/src/parsers/manparser.hxx @@ -0,0 +1,38 @@ +/* + * parser classes for MySpell + * + * implemented: text, HTML, TeX + * + * Copyright (C) 2002, Laszlo Nemeth + * + */ + +#ifndef _MANPARSER_HXX_ +#define _MANPARSER_HXX_ + +#include "textparser.hxx" + +/* + * Manparse Parser + * + */ + +class ManParser : public TextParser +{ + +protected: + + +public: + + ManParser(); + ManParser(const char * wc); + ManParser(unsigned short * wordchars, int len); + virtual ~ManParser(); + + virtual char * next_token(); + +}; + +#endif + diff --git a/hunspell/src/parsers/testparser.cxx b/hunspell/src/parsers/testparser.cxx new file mode 100644 index 000000000..379fb1455 --- /dev/null +++ b/hunspell/src/parsers/testparser.cxx @@ -0,0 +1,52 @@ +#include +#include +#include + +#include "textparser.hxx" +#include "htmlparser.hxx" +#include "latexparser.hxx" + +#ifndef W32 +using namespace std; +#endif + +int +main(int argc, char** argv) +{ + FILE * f; + /* first parse the command line options */ + + if (! argv[1]) { + fprintf(stderr,"correct syntax is:\n"); + fprintf(stderr,"testparser file\n"); + fprintf(stderr,"example: testparser /dev/stdin\n"); + exit(1); + } + + /* open the words to check list */ + f = fopen(argv[1],"r"); + if (!f) { + fprintf(stderr,"Error - could not open file of words to check\n"); + exit(1); + } + + TextParser * p = new LaTeXParser("qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"); + + char buf[MAXLNLEN]; + char * next; + + while(fgets(buf,MAXLNLEN,f)) { + fprintf(stdout,"---------------------------------------\n"); + p->put_line(buf); + fprintf(stderr, "x:%s\n", buf); + p->set_url_checking(1); + while ((next=p->next_token())) { + fprintf(stdout,"token: %s\n",next); + free(next); + } + } + + delete p; + return 0; +} + diff --git a/hunspell/src/parsers/textparser.cxx b/hunspell/src/parsers/textparser.cxx new file mode 100644 index 000000000..b69126229 --- /dev/null +++ b/hunspell/src/parsers/textparser.cxx @@ -0,0 +1,291 @@ +#include +#include +#include +#include + +#include "../hunspell/csutil.hxx" +#include "textparser.hxx" + +#ifndef W32 +using namespace std; +#endif + +// ISO-8859-1 HTML character entities + +static char * LATIN1[] = { + "À", + "Ã", + "Å", + "Æ", + "È", + "Ê", + "Ì", + "Ï", + "Ð", + "Ñ", + "Ò", + "Ø", + "Ù", + "Þ", + "à", + "ã", + "å", + "æ", + "è", + "ê", + "ì", + "ï", + "ð", + "ñ", + "ò", + "ø", + "ù", + "þ", + "ÿ" +}; + +#define LATIN1_LEN (sizeof(LATIN1) / sizeof(char *)) + +TextParser::TextParser() { + init((char *) NULL); +} + +TextParser::TextParser(const char * wordchars) +{ + init(wordchars); +} + +TextParser::TextParser(unsigned short * wordchars, int len) +{ + init(wordchars, len); +} + +TextParser::~TextParser() +{ +} + +int TextParser::is_wordchar(char * w) +{ + if (*w == '\0') return 0; + if (utf8) { + w_char wc; + unsigned short idx; + u8_u16(&wc, 1, w); + idx = (wc.h << 8) + wc.l; + return (unicodeisalpha(idx) || (wordchars_utf16 && flag_bsearch(wordchars_utf16, *((unsigned short *) &wc), wclen))); + } else { + return wordcharacters[(*w + 256) % 256]; + } +} + +char * TextParser::get_latin1(char * s) +{ + if (s[0] == '&') { + unsigned int i = 0; + while ((i < LATIN1_LEN) && + strncmp(LATIN1[i], s, strlen(LATIN1[i]))) i++; + if (i != LATIN1_LEN) return LATIN1[i]; + } + return NULL; +} + +void TextParser::init(const char * wordchars) +{ + for (int i = 0; i < MAXPREVLINE; i++) { + line[i][0] = '\0'; + } + actual = 0; + head = 0; + token = 0; + state = 0; + utf8 = 0; + checkurl = 0; + unsigned int j; + for (j = 0; j < 256; j++) { + wordcharacters[j] = 0; + } + if (!wordchars) wordchars = "qwertzuiopasdfghjklyxcvbnmQWERTZUIOPASDFGHJKLYXCVBNM"; + for (j = 0; j < strlen(wordchars); j++) { + wordcharacters[(wordchars[j] + 256) % 256] = 1; + } +} + +void TextParser::init(unsigned short * wc, int len) +{ + for (int i = 0; i < MAXPREVLINE; i++) { + line[i][0] = '\0'; + } + actual = 0; + head = 0; + token = 0; + state = 0; + utf8 = 1; + checkurl = 0; + wordchars_utf16 = wc; + wclen = len; +} + +int TextParser::next_char(char * line, int * pos) { + if (*(line + *pos) == '\0') return 1; + if (utf8) { + if (*(line + *pos) >> 7) { + // jump to next UTF-8 character + for((*pos)++; (*(line + *pos) & 0xc0) == 0x80; (*pos)++); + } else { + (*pos)++; + } + } else (*pos)++; + return 0; +} + +void TextParser::put_line(char * word) +{ + actual = (actual + 1) % MAXPREVLINE; + strcpy(line[actual], word); + token = 0; + head = 0; + check_urls(); +} + +char * TextParser::get_prevline(int n) +{ + return mystrdup(line[(actual + MAXPREVLINE - n) % MAXPREVLINE]); +} + +char * TextParser::get_line() +{ + return get_prevline(0); +} + +char * TextParser::next_token() +{ + char * latin1; + + for (;;) { + switch (state) + { + case 0: // non word chars + if (is_wordchar(line[actual] + head)) { + state = 1; + token = head; + } else if ((latin1 = get_latin1(line[actual] + head))) { + state = 1; + token = head; + head += strlen(latin1); + } + break; + case 1: // wordchar + if ((latin1 = get_latin1(line[actual] + head))) { + head += strlen(latin1); + } else if (! is_wordchar(line[actual] + head)) { + state = 0; + char * t = alloc_token(token, &head); + if (t) return t; + } + break; + } + if (next_char(line[actual], &head)) return NULL; + } +} + +int TextParser::get_tokenpos() +{ + return token; +} + +int TextParser::change_token(const char * word) +{ + if (word) { + char * r = mystrdup(line[actual] + head); + strcpy(line[actual] + token, word); + strcat(line[actual], r); + head = token; + free(r); + return 1; + } + return 0; +} + +void TextParser::check_urls() +{ + int url_state = 0; + int url_head = 0; + int url_token = 0; + int url = 0; + for (;;) { + switch (url_state) + { + case 0: // non word chars + if (is_wordchar(line[actual] + url_head)) { + url_state = 1; + url_token = url_head; + // Unix path + } else if (*(line[actual] + url_head) == '/') { + url_state = 1; + url_token = url_head; + url = 1; + } + break; + case 1: // wordchar + char ch = *(line[actual] + url_head); + // e-mail address + if ((ch == '@') || + // MS-DOS, Windows path + (strncmp(line[actual] + url_head, ":\\", 2) == 0) || + // URL + (strncmp(line[actual] + url_head, "://", 3) == 0)) { + url = 1; + } else if (! (is_wordchar(line[actual] + url_head) || + (ch == '-') || (ch == '_') || (ch == '\\') || + (ch == '.') || (ch == ':') || (ch == '/') || + (ch == '~') || (ch == '%') || (ch == '*') || + (ch == '$') || (ch == '[') || (ch == ']') || + (ch == '?') || (ch == '!') || + ((ch >= '0') && (ch <= '9')))) { + url_state = 0; + if (url == 1) { + for (int i = url_token; i < url_head; i++) { + *(urlline + i) = 1; + } + } + url = 0; + } + break; + } + *(urlline + url_head) = 0; + if (next_char(line[actual], &url_head)) return; + } +} + +int TextParser::get_url(int token_pos, int * head) +{ + for (int i = *head; urlline[i] && *(line[actual]+i); i++, (*head)++); + return checkurl ? 0 : urlline[token_pos]; +} + +void TextParser::set_url_checking(int check) +{ + checkurl = check; +} + + +char * TextParser::alloc_token(int token, int * head) +{ + if (get_url(token, head)) return NULL; + char * t = (char *) malloc(*head - token + 1); + if (t) { + t[*head - token] = '\0'; + strncpy(t, line[actual] + token, *head - token); + // remove colon for Finnish and Swedish language + if (t[*head - token - 1] == ':') { + t[*head - token - 1] = '\0'; + if (!t[0]) { + free(t); + return NULL; + } + } + return t; + } + fprintf(stderr,"Error - Insufficient Memory\n"); + return NULL; +} diff --git a/hunspell/src/parsers/textparser.hxx b/hunspell/src/parsers/textparser.hxx new file mode 100644 index 000000000..22f6d24dc --- /dev/null +++ b/hunspell/src/parsers/textparser.hxx @@ -0,0 +1,69 @@ +/* + * parser classes for MySpell + * + * implemented: text, HTML, TeX + * + * Copyright (C) 2002, Laszlo Nemeth + * + */ + +#ifndef _TEXTPARSER_HXX_ +#define _TEXTPARSER_HXX_ + +// set sum of actual and previous lines +#define MAXPREVLINE 4 + +#ifndef MAXLNLEN +#define MAXLNLEN 8192 +#endif + +/* + * Base Text Parser + * + */ + +class TextParser +{ + +protected: + void init(const char *); + void init(unsigned short * wordchars, int len); + int wordcharacters[256]; // for detection of the word boundaries + char line[MAXPREVLINE][MAXLNLEN]; // parsed and previous lines + char urlline[MAXLNLEN]; // mask for url detection + int checkurl; + int actual; // actual line + int head; // head position + int token; // begin of token + int state; // state of automata + int utf8; // UTF-8 character encoding + int next_char(char * line, int * pos); + unsigned short * wordchars_utf16; + int wclen; + +public: + + TextParser(); + TextParser(unsigned short * wordchars, int len); + TextParser(const char * wc); + virtual ~TextParser(); + + void put_line(char * line); + char * get_line(); + char * get_prevline(int n); + virtual char * next_token(); + int change_token(const char * word); + void set_url_checking(int check); + + int get_tokenpos(); + int is_wordchar(char * w); + char * get_latin1(char * s); + char * next_char(); + int tokenize_urls(); + void check_urls(); + int get_url(int token_pos, int * head); + char * alloc_token(int token, int * head); +}; + +#endif + diff --git a/hunspell/src/win_api/Hunspell.rc b/hunspell/src/win_api/Hunspell.rc new file mode 100644 index 000000000..33021bb9b --- /dev/null +++ b/hunspell/src/win_api/Hunspell.rc @@ -0,0 +1,32 @@ + +#include + +VS_VERSION_INFO VERSIONINFO +FILEVERSION 1,2,1,0 +PRODUCTVERSION 1,2,1,0 +FILEFLAGSMASK 0x17L +FILEFLAGS 0 +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_APP +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "Hunspell (http://hunspell.sourceforge.net/) by Lszl Nmeth" + VALUE "CompanyName", "http://hunspell.sourceforge.net/" + VALUE "FileDescription", "libhunspell" + VALUE "FileVersion", "1.2.1" + VALUE "InternalName", "libhunspell" + VALUE "LegalCopyright", "Copyright (c) 2007" + VALUE "OriginalFilename", "libhunspell.dll" + VALUE "ProductName", "Hunspell Dynamic Link Library" + VALUE "ProductVersion", "1.2.1" + END + END +END diff --git a/hunspell/src/win_api/config.h b/hunspell/src/win_api/config.h new file mode 100644 index 000000000..fe3e70c01 --- /dev/null +++ b/hunspell/src/win_api/config.h @@ -0,0 +1,215 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#define CRAY_STACKSEG_END 1 + +/* Define to 1 if using `alloca.c'. */ +#define C_ALLOCA 1 + +/* Define to 1 if translation of program messages to the user's native + language is requested. */ +#undef ENABLE_NLS + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +#define HAVE_ALLOCA_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ARGZ_H 1 + +/* "Define if you have the header" */ +#undef HAVE_CURSES_H + +/* Define if the GNU dcgettext() function is already present or preinstalled. + */ +#define HAVE_DCGETTEXT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_ERROR_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `feof_unlocked' function. */ +#define HAVE_FEOF_UNLOCKED 1 + +/* Define to 1 if you have the `fgets_unlocked' function. */ +#define HAVE_FGETS_UNLOCKED 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getc_unlocked' function. */ +#define HAVE_GETC_UNLOCKED 1 + +/* Define to 1 if you have the `getegid' function. */ +#define HAVE_GETEGID 1 + +/* Define to 1 if you have the `geteuid' function. */ +#define HAVE_GETEUID 1 + +/* Define to 1 if you have the `getgid' function. */ +#define HAVE_GETGID 1 + +/* Define to 1 if you have the `getpagesize' function. */ +#define HAVE_GETPAGESIZE 1 + +/* Define if the GNU gettext() function is already present or preinstalled. */ +#define HAVE_GETTEXT 1 + +/* Define to 1 if you have the `getuid' function. */ +#define HAVE_GETUID 1 + +/* Define if you have the iconv() function. */ +#undef HAVE_ICONV + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have and nl_langinfo(CODESET). */ +#define HAVE_LANGINFO_CODESET 1 + +/* Define if your file defines LC_MESSAGES. */ +#define HAVE_LC_MESSAGES 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIBINTL_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LIMITS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_LOCALE_H 1 + +/* Define to 1 if your system has a GNU libc compatible `malloc' function, and + to 0 otherwise. */ +#define HAVE_MALLOC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MALLOC_H 1 + +/* Define to 1 if you have the `memchr' function. */ +#define HAVE_MEMCHR 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mempcpy' function. */ +#define HAVE_MEMPCPY 1 + +/* Define to 1 if you have a working `mmap' system call. */ +#define HAVE_MMAP 1 + +/* Define to 1 if you have the `munmap' function. */ +#define HAVE_MUNMAP 1 + +/* "Define if you have the header" */ +#define HAVE_NCURSESW_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_NL_TYPES_H 1 + +/* Define to 1 if you have the `putenv' function. */ +#define HAVE_PUTENV 1 + +/* "Define if you have fancy command input editing with Readline" */ +#undef HAVE_READLINE + +/* Define to 1 if you have the `setenv' function. */ +#define HAVE_SETENV 1 + +/* Define to 1 if you have the `setlocale' function. */ +#define HAVE_SETLOCALE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDDEF_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `stpcpy' function. */ +#define HAVE_STPCPY 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strstr' function. */ +#define HAVE_STRSTR 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `tsearch' function. */ +#define HAVE_TSEARCH 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the `__argz_count' function. */ +#define HAVE___ARGZ_COUNT 1 + +/* Define to 1 if you have the `__argz_next' function. */ +#define HAVE___ARGZ_NEXT 1 + +/* Define to 1 if you have the `__argz_stringify' function. */ +#define HAVE___ARGZ_STRINGIFY 1 + +/* "Define if you use exterimental functions" */ +#undef HUNSPELL_EXPERIMENTAL + +/* "Define if you need warning messages" */ +#undef HUNSPELL_WARNING_ON + +/* Define as const if the declaration of iconv() needs const. */ +#define ICONV_CONST 1 + +/* Name of package */ +#define PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#define PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "1.1.11" +#define VERSION "1.1.11" diff --git a/hunspell/src/win_api/hunspelldll.c b/hunspell/src/win_api/hunspelldll.c new file mode 100644 index 000000000..b9fc9572b --- /dev/null +++ b/hunspell/src/win_api/hunspelldll.c @@ -0,0 +1,112 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Copyright (C) 2006 + * Miha Vrhovnik (http://simail.sf.net, http://xcollect.sf.net) + * All Rights Reserved. + * + * Contributor(s): + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** **/ +#include "hunspelldll.h" +#include + +#ifdef BORLAND +#include +#include +#include +#include +#include +#endif + +DLLEXPORT void * hunspell_initialize(char *aff_file, char *dict_file) +{ + Hunspell * pMS = new Hunspell(aff_file, dict_file); + return pMS; +} + +DLLEXPORT void hunspell_uninitialize(Hunspell *pMS) +{ + delete pMS; +} + +DLLEXPORT int hunspell_spell(Hunspell *pMS, char *word) +{ + return pMS->spell(word); +} + +DLLEXPORT int hunspell_suggest(Hunspell *pMS, char *word, char ***slst) +{ + return pMS->suggest(slst, word); +} + +#ifdef HUNSPELL_EXPERIMENTAL +DLLEXPORT int hunspell_suggest_auto(Hunspell *pMS, char *word, char ***slst) +{ + return pMS->suggest_auto(slst, word); +} +#endif + +DLLEXPORT void hunspell_suggest_free(Hunspell *pMS, char **slst, int len) +{ + for (int i = 0; i < len; i++) { + free(slst[i]); + } +} + +DLLEXPORT char * hunspell_get_dic_encoding(Hunspell *pMS) +{ + return pMS->get_dic_encoding(); +} + +DLLEXPORT int hunspell_put_word(Hunspell *pMS, char *word) +{ + return pMS->add(word); +} + + +BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */ , + DWORD reason /* Reason this function is being called. */ , + LPVOID reserved /* Not used. */ ) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + break; + + case DLL_PROCESS_DETACH: + break; + + case DLL_THREAD_ATTACH: + break; + + case DLL_THREAD_DETACH: + break; + } + + /* Returns TRUE on success, FALSE on failure */ + return TRUE; +} diff --git a/hunspell/src/win_api/hunspelldll.h b/hunspell/src/win_api/hunspelldll.h new file mode 100644 index 000000000..f9251e5e3 --- /dev/null +++ b/hunspell/src/win_api/hunspelldll.h @@ -0,0 +1,74 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * Copyright (C) 2006 + * Miha Vrhovnik (http://simail.sf.net, http://xcollect.sf.net) + * All Rights Reserved. + * + * Contributor(s): + * + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** **/ +#include "hunspell.hxx" + +#ifndef _DLL_H_ +#define _DLL_H_ + +#ifdef HUNSPELL_STATIC + #define DLLEXPORT +#else + #ifdef HUNSPELL_EXPORTS + #define DLLEXPORT __declspec( dllexport ) + #else + #define DLLEXPORT __declspec( dllimport ) + #endif +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +//returns pointer to spell object, params are aff file name and dict file name +DLLEXPORT void *hunspell_initialize(char *aff_file, char *dict_file); +//frees spell object +DLLEXPORT void hunspell_uninitialize(Hunspell *pMS); +//spellcheck word, returns 1 if word ok otherwise 0 +DLLEXPORT int hunspell_spell(Hunspell *pMS, char *word); +//suggest words for word, returns number of words in slst +// YOU NEED TO CALL hunspell_suggest_free after you've done with words +DLLEXPORT int hunspell_suggest(Hunspell *pMS, char *word, char ***slst); +DLLEXPORT int hunspell_suggest_auto(Hunspell *pMS, char *word, char ***slst); +//free slst array +DLLEXPORT void hunspell_suggest_free(Hunspell *pMS, char **slst, int len); +//make local copy of returned string!! +DLLEXPORT char * hunspell_get_dic_encoding(Hunspell *pMS); +//add word to dict (word is valid until spell object is not destroyed) +DLLEXPORT int hunspell_put_word(Hunspell *pMS, char *word); + +#ifdef __cplusplus +} +#endif + +#endif /* _DLL_H_ */ diff --git a/hunspell/src/win_api/libhunspell.vcproj b/hunspell/src/win_api/libhunspell.vcproj new file mode 100644 index 000000000..5c73accc1 --- /dev/null +++ b/hunspell/src/win_api/libhunspell.vcproj @@ -0,0 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +