--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/xulrunner-1.9-venkman.install
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/xulrunner-1.9-venkman.install
@@ -0,0 +1 @@
+debian/tmp/usr/lib/xulrunner-1.9*/extensions/venkman@mozilla.org usr/lib/xulrunner-addons/extensions
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/system-greprefs.js
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/system-greprefs.js
@@ -0,0 +1,6 @@
+//
+// insert your system greprefs here
+//
+
+// pref("general.config.filename", "defaults/syspref/system.cfg");
+
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/MPL
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/MPL
@@ -0,0 +1,567 @@
+ 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.]
+
+ ----------------------------------------------------------------------
+
+ AMENDMENTS
+
+ The Netscape Public License Version 1.1 ("NPL") consists of the
+ Mozilla Public License Version 1.1 with the following Amendments,
+ including Exhibit A-Netscape Public License. Files identified with
+ "Exhibit A-Netscape Public License" are governed by the Netscape
+ Public License Version 1.1.
+
+ Additional Terms applicable to the Netscape Public License.
+ I. Effect.
+ These additional terms described in this Netscape Public
+ License -- Amendments shall apply to the Mozilla Communicator
+ client code and to all Covered Code under this License.
+
+ II. "Netscape's Branded Code" means Covered Code that Netscape
+ distributes and/or permits others to distribute under one or more
+ trademark(s) which are controlled by Netscape but which are not
+ licensed for use under this License.
+
+ III. Netscape and logo.
+ This License does not grant any rights to use the trademarks
+ "Netscape", the "Netscape N and horizon" logo or the "Netscape
+ lighthouse" logo, "Netcenter", "Gecko", "Java" or "JavaScript",
+ "Smart Browsing" even if such marks are included in the Original
+ Code or Modifications.
+
+ IV. Inability to Comply Due to Contractual Obligation.
+ Prior to licensing the Original Code under this License, Netscape
+ has licensed third party code for use in Netscape's Branded Code.
+ To the extent that Netscape is limited contractually from making
+ such third party code available under this License, Netscape may
+ choose to reintegrate such code into Covered Code without being
+ required to distribute such code in Source Code form, even if
+ such code would otherwise be considered "Modifications" under
+ this License.
+
+ V. Use of Modifications and Covered Code by Initial Developer.
+ V.1. In General.
+ The obligations of Section 3 apply to Netscape, except to
+ the extent specified in this Amendment, Section V.2 and V.3.
+
+ V.2. Other Products.
+ Netscape may include Covered Code in products other than the
+ Netscape's Branded Code which are released by Netscape
+ during the two (2) years following the release date of the
+ Original Code, without such additional products becoming
+ subject to the terms of this License, and may license such
+ additional products on different terms from those contained
+ in this License.
+
+ V.3. Alternative Licensing.
+ Netscape may license the Source Code of Netscape's Branded
+ Code, including Modifications incorporated therein, without
+ such Netscape Branded Code becoming subject to the terms of
+ this License, and may license such Netscape Branded Code on
+ different terms from those contained in this License.
+
+ VI. Litigation.
+ Notwithstanding the limitations of Section 11 above, the
+ provisions regarding litigation in Section 11(a), (b) and (c) of
+ the License shall apply to all disputes relating to this License.
+
+ EXHIBIT A-Netscape Public License.
+
+ "The contents of this file are subject to the Netscape 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/NPL/
+
+ 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 Mozilla Communicator client code, released
+ March 31, 1998.
+
+ The Initial Developer of the Original Code is Netscape
+ Communications Corporation. Portions created by Netscape are
+ Copyright (C) 1998-1999 Netscape Communications Corporation. 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 NPL, 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 NPL or the
+ [___] License."
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/translation-support/install.rdf.in
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/translation-support/install.rdf.in
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+ toolkit@mozilla.org
+ @EM_TOOLKIT_MIN_VERSION@
+ @EM_TOOLKIT_MAX_VERSION@
+
+
+
+
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/xulrunner-1.9.prerm
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/xulrunner-1.9.prerm
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+set -e
+if [ "$1" = "remove" ] || [ "$1" = upgrade ]; then
+ /usr/sbin/update-alternatives --remove xulrunner /usr/bin/xulrunner-1.9
+ if [ "$(update-alternatives --list xulrunner | wc -l)" = "0" ]; then
+ /usr/sbin/update-alternatives --remove-all xulrunner
+ fi
+fi
+
+#DEBHELPER#
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/xulrunner-1.9.postinst
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/xulrunner-1.9.postinst
@@ -0,0 +1,11 @@
+#!/bin/sh
+set -e
+if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
+ /usr/sbin/update-alternatives --install /usr/bin/xulrunner \
+ xulrunner /usr/bin/xulrunner-1.9 50
+ if test -e /usr/lib/xulrunner-1.9*/.autoreg; then
+ touch /usr/lib/xulrunner-1.9*/.autoreg
+ fi
+fi
+
+#DEBHELPER#
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/xulrunner-1.9.dirs
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/xulrunner-1.9.dirs
@@ -0,0 +1,7 @@
+# ubuntu global extension and plugin directories
+usr/lib/xulrunner-addons/extensions
+usr/lib/xulrunner-addons/plugins
+
+# distro independent extensions directories for third party installer
+usr/lib/mozilla/extensions
+usr/share/mozilla/extensions
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/docs
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/docs
@@ -0,0 +1 @@
+debian/MPL
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/xulrunner-1.9-dom-inspector.install
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/xulrunner-1.9-dom-inspector.install
@@ -0,0 +1,2 @@
+debian/tmp/usr/lib/xulrunner-1.9*/extensions/inspector@mozilla.org/[cdi]* usr/lib/xulrunner-addons/extensions/inspector@mozilla.org
+debian/tmp/usr/lib/xulrunner-1.9*/extensions/inspector@mozilla.org/platform/Linux usr/lib/xulrunner-addons/extensions/inspector@mozilla.org/platform
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/compat
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/compat
@@ -0,0 +1 @@
+5
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bzXXX-dont-reset-user-prefs-on-upgrade.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bzXXX-dont-reset-user-prefs-on-upgrade.patch
@@ -0,0 +1,102 @@
+
+This bug is due to the fact, applications are restarted before extension
+defaults are loaded.
+
+To reproduce, choose any preference and set the values like:
+system default:
+ pref("prefkey",systemvalue);
+extension default:
+ pref("prefkey", extensiondefault);
+user pref:
+ user_pref("prefkey", systemvalue);
+
+Next, trigger application behaviour similar to upgrade by removing compreg.dat
+from profile and start the application.
+
+Result:
+User sees extensiondefault after upgrade, because the user_pref has been
+eliminated ... which is definitly not what the user expects because he explicitly
+had *systemvalue* set before the upgrade.
+
+Evaluation:
+The bug happens because restart is performed *before* extension defaults have been
+loaded and the prefapi.cpp always eliminate user preference if the user preference
+is equal to the actual default (which happens to be extensiondefault normally - so
+no reset, but is systemvalue during restart).
+
+Fix:
+1. savePrefs should not try to be smart ... this patch removes the heuristic that guesses
+whether a setting can be eliminated or not; it should be sufficient to only eliminate
+prefs in hashPrefs.
+
+2. This patch prevents hashPrefs from eliminating the user pref in case we are in
+*startup* ... unfortunately no such state info exists, which lets us guess that
+we are in startup for the previously not dealt case: !set_default &&
+!pref_ValueChanged(pref->defaultPref, value, type) && !PREF_HAS_USER_VALUE(pref).
+
+If is the case we explicitly remember that this setting is a user-pref ...
+even though it might be temporarily equal to the default pref.
+
+---
+ modules/libpref/src/prefapi.cpp | 20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+Index: mozilla/modules/libpref/src/prefapi.cpp
+===================================================================
+--- mozilla.orig/modules/libpref/src/prefapi.cpp 2006-07-14 02:58:20.000000000 +0200
++++ mozilla/modules/libpref/src/prefapi.cpp 2007-07-20 13:07:53.000000000 +0200
+@@ -319,23 +319,20 @@
+ if (!pref)
+ return PL_DHASH_NEXT;
+
+ nsCAutoString prefValue;
+
+ // where we're getting our pref from
+ PrefValue* sourcePref;
+
+- if (PREF_HAS_USER_VALUE(pref) &&
+- pref_ValueChanged(pref->defaultPref,
+- pref->userPref,
+- (PrefType) PREF_TYPE(pref)))
+- sourcePref = &pref->userPref;
+- else if (PREF_IS_LOCKED(pref))
++ if (PREF_IS_LOCKED(pref))
+ sourcePref = &pref->defaultPref;
++ else if (PREF_HAS_USER_VALUE(pref))
++ sourcePref = &pref->userPref;
+ else
+ // do not save default prefs that haven't changed
+ return PL_DHASH_NEXT;
+
+ #if MOZ_PROFILESHARING
+ if ((argData->saveTypes == SAVE_SHARED &&
+ !gSharedPrefHandler->IsPrefShared(pref->key)) ||
+ (argData->saveTypes == SAVE_NONSHARED &&
+@@ -732,16 +729,27 @@
+ Otherwise, set the user value only if it has changed */
+ if ( !pref_ValueChanged(pref->defaultPref, value, type) )
+ {
+ if (PREF_HAS_USER_VALUE(pref))
+ {
+ pref->flags &= ~PREF_USERSET;
+ if (!PREF_IS_LOCKED(pref))
+ valueChanged = PR_TRUE;
++ } else {
++ // this is tricky: we have !set_default ...
++ // thus we are setting a user pref; however the user
++ // pref set is same as *current default*; this normally
++ // means to un-set ... however since we have
++ // !PREF_HAS_USER_VALUE(pref) this can only be during
++ // startup
++ pref_SetValue(&pref->userPref, value, type);
++ pref->flags |= PREF_USERSET;
++ if (!PREF_IS_LOCKED(pref))
++ valueChanged = PR_TRUE;
+ }
+ }
+ else if ( !PREF_HAS_USER_VALUE(pref) ||
+ pref_ValueChanged(pref->userPref, value, type) )
+ {
+ pref_SetValue(&pref->userPref, value, type);
+ pref->flags |= PREF_USERSET;
+ if (!PREF_IS_LOCKED(pref))
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/protect_tests_by_ifdefs.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/protect_tests_by_ifdefs.patch
@@ -0,0 +1,94 @@
+---
+ content/xul/content/Makefile.in | 6 +++++-
+ dom/Makefile.in | 6 +++++-
+ toolkit/components/commandlines/Makefile.in | 5 ++++-
+ toolkit/components/downloads/Makefile.in | 6 +++++-
+ 4 files changed, 19 insertions(+), 4 deletions(-)
+
+Index: mozilla/content/xul/content/Makefile.in
+===================================================================
+--- mozilla.orig/content/xul/content/Makefile.in
++++ mozilla/content/xul/content/Makefile.in
+@@ -38,12 +38,16 @@
+ DEPTH = ../../..
+ topsrcdir = @top_srcdir@
+ srcdir = @srcdir@
+ VPATH = @srcdir@
+
+ include $(DEPTH)/config/autoconf.mk
+
+ MODULE = xul
+-DIRS = src test
++DIRS = src
++
++ifdef ENABLE_TESTS
++DIRS += test
++endif
+
+ include $(topsrcdir)/config/rules.mk
+
+Index: mozilla/toolkit/components/downloads/Makefile.in
+===================================================================
+--- mozilla.orig/toolkit/components/downloads/Makefile.in
++++ mozilla/toolkit/components/downloads/Makefile.in
+@@ -37,12 +37,16 @@
+
+ DEPTH = ../../..
+ topsrcdir = @top_srcdir@
+ srcdir = @srcdir@
+ VPATH = @srcdir@
+
+ include $(DEPTH)/config/autoconf.mk
+
+-DIRS = public src test
++DIRS = public src
++
++ifdef ENABLE_TESTS
++DIRS += test
++endif
+
+ include $(topsrcdir)/config/rules.mk
+
+Index: mozilla/toolkit/components/commandlines/Makefile.in
+===================================================================
+--- mozilla.orig/toolkit/components/commandlines/Makefile.in
++++ mozilla/toolkit/components/commandlines/Makefile.in
+@@ -40,12 +40,15 @@
+ srcdir = @srcdir@
+ VPATH = @srcdir@
+
+ include $(DEPTH)/config/autoconf.mk
+
+ DIRS = \
+ public \
+ src \
+- test \
+ $(NULL)
+
++ifdef ENABLE_TESTS
++DIRS += test
++endif
++
+ include $(topsrcdir)/config/rules.mk
+Index: mozilla/dom/Makefile.in
+===================================================================
+--- mozilla.orig/dom/Makefile.in
++++ mozilla/dom/Makefile.in
+@@ -38,12 +38,16 @@
+ DEPTH = ..
+ topsrcdir = @top_srcdir@
+ srcdir = @srcdir@
+ VPATH = @srcdir@
+
+ include $(DEPTH)/config/autoconf.mk
+
+ MODULE = dom
+-DIRS = public src locales tests
++DIRS = public src locales
++
++ifdef ENABLE_TESTS
++DIRS += tests
++endif
+
+ include $(topsrcdir)/config/rules.mk
+
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bz233371_att297343_fix_outofscreen_embed_tooltip.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bz233371_att297343_fix_outofscreen_embed_tooltip.patch
@@ -0,0 +1,137 @@
+Index: embedding/browser/gtk/src/EmbedWindow.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/embedding/browser/gtk/src/EmbedWindow.cpp,v
+retrieving revision 1.43
+diff -u -p -8 -r1.43 EmbedWindow.cpp
+--- a/embedding/browser/gtk/src/EmbedWindow.cpp 11 Jan 2008 22:16:15 -0000 1.43
++++ b/embedding/browser/gtk/src/EmbedWindow.cpp 16 Jan 2008 00:08:24 -0000
+@@ -379,72 +379,95 @@ tooltips_paint_window(GtkWidget *window)
+
+ return FALSE;
+ }
+
+ NS_IMETHODIMP
+ EmbedWindow::OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords,
+ const PRUnichar *aTipText)
+ {
+- nsAutoString tipText ( aTipText );
+-
+- const char* tipString = ToNewUTF8String(tipText);
++ NS_ENSURE_STATE(mOwner && mOwner->mOwningWidget &&
++ GTK_WIDGET_REALIZED(mOwner->mOwningWidget));
+
+ if (sTipWindow)
+ gtk_widget_destroy(sTipWindow);
+
+- // get the root origin for this content window
+- nsCOMPtr mainWidget;
+- mBaseWindow->GetMainWidget(getter_AddRefs(mainWidget));
+- GdkWindow *window;
+- window = static_cast(mainWidget->GetNativeData(NS_NATIVE_WINDOW));
+- gint root_x, root_y;
+- gdk_window_get_origin(window, &root_x, &root_y);
+-
+- // XXX work around until I can get pink to figure out why
+- // tooltips vanish if they show up right at the origin of the
+- // cursor.
+- root_y += 10;
+
+ sTipWindow = gtk_window_new(GTK_WINDOW_POPUP);
++ GtkWindow *tipWinAsWindow = GTK_WINDOW(sTipWindow);
++
+ gtk_widget_set_app_paintable(sTipWindow, TRUE);
+- gtk_window_set_resizable(GTK_WINDOW(sTipWindow), TRUE);
++ gtk_window_set_resizable(tipWinAsWindow, FALSE);
+ // needed to get colors + fonts etc correctly
+ gtk_widget_set_name(sTipWindow, "gtk-tooltips");
++ gtk_container_set_border_width(GTK_CONTAINER(sTipWindow), 4);
+
+ // set up the popup window as a transient of the widget.
+- GtkWidget *toplevel_window;
+- toplevel_window = gtk_widget_get_toplevel(GTK_WIDGET(mOwner->mOwningWidget));
+- if (!GTK_WINDOW(toplevel_window)) {
++ GtkWidget *widget = (GtkWidget *) mOwner->mOwningWidget;
++ GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
++ if (!GTK_IS_WINDOW(toplevel) || !GTK_WIDGET_TOPLEVEL(toplevel)) {
+ NS_ERROR("no gtk window in hierarchy!\n");
+ return NS_ERROR_FAILURE;
+ }
+- gtk_window_set_transient_for(GTK_WINDOW(sTipWindow),
+- GTK_WINDOW(toplevel_window));
++ gtk_window_set_transient_for(tipWinAsWindow, GTK_WINDOW(toplevel));
+
+- // realize the widget
+- gtk_widget_realize(sTipWindow);
+-
+- g_signal_connect(G_OBJECT(sTipWindow), "expose_event",
+- G_CALLBACK(tooltips_paint_window), NULL);
++ g_signal_connect (sTipWindow, "expose-event",
++ G_CALLBACK(tooltips_paint_window), NULL);
+
+ // set up the label for the tooltip
+- GtkWidget *label = gtk_label_new(tipString);
++ GtkWidget *label = gtk_label_new(NS_ConvertUTF16toUTF8(aTipText).get());
+ // wrap automatically
+ gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
++ gtk_misc_set_alignment (GTK_MISC(label), 0.5, 0.5);
+ gtk_container_add(GTK_CONTAINER(sTipWindow), label);
+- gtk_container_set_border_width(GTK_CONTAINER(sTipWindow), 4);
+- // set the coords for the widget
+- gtk_widget_set_uposition(sTipWindow, aXCoords + root_x,
+- aYCoords + root_y);
++ gtk_widget_show(label);
++
++ GdkScreen *screen = gtk_widget_get_screen(widget);
++ gtk_window_set_screen (tipWinAsWindow, screen);
++
++ gint monitor_num = gdk_screen_get_monitor_at_window(screen, widget->window);
++ if (monitor_num < 0)
++ monitor_num = 0;
++
++ GdkRectangle monitor;
++ gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor);
++
++ gtk_widget_ensure_style(sTipWindow);
++
++ GtkRequisition req;
++ gtk_widget_size_request(sTipWindow, &req);
++
++ gint x, y;
++ gdk_window_get_origin(widget->window, &x, &y);
++
++ x += aXCoords;
++ y += aYCoords;
++
++ // Ideally we'd query the cursor size and hotspot,
++ // but there appears to be no way to do that */
++ int xoffset = 8, yoffset = 8;
++
++ if (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_RTL) {
++ x -= req.width + xoffset;
++ } else {
++ x += xoffset;
++ }
+
+- // and show it.
+- gtk_widget_show_all(sTipWindow);
++ if (x + req.width > monitor.x + monitor.width)
++ x = monitor.x + monitor.width - req.width;
++ else if (x < monitor.x)
++ x = monitor.x;
++
++ if (y + req.height + yoffset <= monitor.y + monitor.height)
++ y += yoffset;
++ else
++ y -= req.height + yoffset;
+
+- nsMemory::Free( (void*)tipString );
++ gtk_window_move(tipWinAsWindow, x, y);
++ gtk_widget_show(sTipWindow);
+
+ return NS_OK;
+ }
+
+ NS_IMETHODIMP
+ EmbedWindow::OnHideTooltip(void)
+ {
+ if (sTipWindow)
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bzXXX_gre_autoreg.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bzXXX_gre_autoreg.patch
@@ -0,0 +1,82 @@
+Index: xpcom/build/nsXPComInit.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/xpcom/build/nsXPComInit.cpp,v
+retrieving revision 1.261
+diff -u -p -8 -r1.261 nsXPComInit.cpp
+--- a/xpcom/build/nsXPComInit.cpp 8 Mar 2008 09:50:29 -0000 1.261
++++ b/xpcom/build/nsXPComInit.cpp 2 Apr 2008 20:39:53 -0000
+@@ -284,52 +284,63 @@ RegisterGenericFactory(nsIComponentRegis
+ // In order to support the installer, we need
+ // to be told out of band if we should cause
+ // an autoregister. If the file ".autoreg" exists in the binary
+ // directory, we check its timestamp against the timestamp of the
+ // compreg.dat file. If the .autoreg file is newer, we autoregister.
+ static PRBool CheckUpdateFile()
+ {
+ nsresult rv;
+- nsCOMPtr file;
++
++ nsCOMPtr pfile;
+ rv = nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
+ NS_GET_IID(nsIFile),
+- getter_AddRefs(file));
+-
++ getter_AddRefs(pfile));
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
+ return PR_FALSE;
+ }
++ pfile->AppendNative(nsDependentCString(".autoreg"));
++ PRBool pexists;
++ pfile->Exists(&pexists);
+
+- file->AppendNative(nsDependentCString(".autoreg"));
+-
+- PRBool exists;
+- file->Exists(&exists);
+- if (!exists)
++
++ nsCOMPtr gfile;
++ rv = nsDirectoryService::gService->Get(NS_GRE_DIR,
++ NS_GET_IID(nsIFile),
++ getter_AddRefs(gfile));
++ gfile->AppendNative(nsDependentCString(".autoreg"));
++ PRBool gexists;
++ gfile->Exists(&gexists);
++
++
++ if (!pexists && !gexists)
+ return PR_FALSE;
+
+ nsCOMPtr compregFile;
+ rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
+ NS_GET_IID(nsIFile),
+ getter_AddRefs(compregFile));
+
+
+ if (NS_FAILED(rv)) {
+ NS_WARNING("Getting NS_XPCOM_COMPONENT_REGISTRY_FILE failed");
+ return PR_FALSE;
+ }
+
++ PRBool exists;
+ if (NS_FAILED(compregFile->Exists(&exists)) || !exists)
+ return PR_TRUE;
+
+- PRInt64 compregModTime, autoregModTime;
++ PRInt64 compregModTime, autoreg1ModTime, autoreg2ModTime;
+ compregFile->GetLastModifiedTime(&compregModTime);
+- file->GetLastModifiedTime(&autoregModTime);
++ pfile->GetLastModifiedTime(&autoreg1ModTime);
++ gfile->GetLastModifiedTime(&autoreg2ModTime);
+
+- return LL_CMP(autoregModTime, >, compregModTime);
++ return LL_CMP(PR_MAX(autoreg1ModTime, autoreg2ModTime), >, compregModTime);
+ }
+
+
+ nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
+ PRBool gXPCOMShuttingDown = PR_FALSE;
+
+ // For each class that wishes to support nsIClassInfo, add a line like this
+ // NS_DECL_CLASSINFO(nsMyClass)
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bzXXX_no_zlib_export_if_native.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bzXXX_no_zlib_export_if_native.patch
@@ -0,0 +1,27 @@
+Index: modules/zlib/standalone/Makefile.in
+===================================================================
+RCS file: /cvsroot/mozilla/modules/zlib/standalone/Makefile.in,v
+retrieving revision 1.20
+diff -u -p -8 -r1.20 Makefile.in
+--- mozilla/modules/zlib/standalone/Makefile.in 31 Dec 2005 16:02:07 -0000 1.20
++++ mozilla/modules/zlib/standalone/Makefile.in 1 Jan 2008 23:27:42 -0000
+@@ -43,17 +43,19 @@ VPATH = @srcdir@
+
+ include $(DEPTH)/config/autoconf.mk
+ include $(srcdir)/../src/objs.mk
+
+ MODULE = zlib
+ LIBRARY_NAME = mozz_s
+
+ CSRCS = $(MODULES_ZLIB_SRC_LCSRCS)
++ifndef MOZ_NATIVE_ZLIB
+ EXPORTS = $(MODULES_ZLIB_SRC_EXPORTS)
++endif
+
+ FORCE_STATIC_LIB = 1
+ SRCS_IN_OBJDIR = 1
+
+ ifeq ($(OS_ARCH),WINNT)
+ USE_STATIC_LIBS=1
+ endif
+
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bzXXX_gre_extension_plugin_support.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bzXXX_gre_extension_plugin_support.patch
@@ -0,0 +1,417 @@
+---
+ toolkit/mozapps/extensions/src/nsExtensionManager.js.in | 27 ++++++---
+ toolkit/xre/nsXREDirProvider.cpp | 5 +
+ xpcom/io/nsAppDirectoryServiceDefs.h | 1
+ xpcom/io/nsAppFileLocationProvider.cpp | 47 ++++++++++++++--
+ xpcom/io/nsAppFileLocationProvider.h | 2
+ 5 files changed, 71 insertions(+), 11 deletions(-)
+
+Index: mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
+===================================================================
+--- mozilla.orig/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
++++ mozilla/toolkit/mozapps/extensions/src/nsExtensionManager.js.in
+@@ -92,16 +92,17 @@
+ const UNKNOWN_XPCOM_ABI = "unknownABI";
+
+ const FILE_DEFAULT_THEME_JAR = "classic.jar";
+ const TOOLKIT_ID = "toolkit@mozilla.org"
+
+ const KEY_PROFILEDIR = "ProfD";
+ const KEY_PROFILEDS = "ProfDS";
+ const KEY_APPDIR = "XCurProcD";
++const KEY_GREDIR = "GreD";
+ const KEY_TEMPDIR = "TmpD";
+
+ const EM_ACTION_REQUESTED_TOPIC = "em-action-requested";
+ const EM_ITEM_INSTALLED = "item-installed";
+ const EM_ITEM_UPGRADED = "item-upgraded";
+ const EM_ITEM_UNINSTALLED = "item-uninstalled";
+ const EM_ITEM_ENABLED = "item-enabled";
+ const EM_ITEM_DISABLED = "item-disabled";
+@@ -111,16 +112,17 @@
+ const OP_NEEDS_INSTALL = "needs-install";
+ const OP_NEEDS_UPGRADE = "needs-upgrade";
+ const OP_NEEDS_UNINSTALL = "needs-uninstall";
+ const OP_NEEDS_ENABLE = "needs-enable";
+ const OP_NEEDS_DISABLE = "needs-disable";
+
+ const KEY_APP_PROFILE = "app-profile";
+ const KEY_APP_GLOBAL = "app-global";
++const KEY_GRE_GLOBAL = "gre-global";
+ const KEY_APP_SYSTEM_LOCAL = "app-system-local";
+ const KEY_APP_SYSTEM_SHARE = "app-system-share";
+ const KEY_APP_SYSTEM_USER = "app-system-user";
+
+ const CATEGORY_INSTALL_LOCATIONS = "extension-install-locations";
+ const CATEGORY_UPDATE_PARAMS = "extension-update-params";
+
+ const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#";
+@@ -2011,16 +2013,17 @@
+ " ... rolling back file moves and aborting installation.");
+ rollbackMove();
+ cleanUpTrash(itemLocationTrash);
+ throw e;
+ }
+ }
+ }
+ else if (installLocation.name == KEY_APP_PROFILE ||
++ installLocation.name == KEY_GRE_GLOBAL ||
+ installLocation.name == KEY_APP_GLOBAL ||
+ installLocation.name == KEY_APP_SYSTEM_USER) {
+ // Check for a pointer file and move it aside if it exists
+ var pointerFile = installLocation.location.clone();
+ pointerFile.append(itemID);
+ if (pointerFile.exists() && !pointerFile.isDirectory()) {
+ var trashFileName = itemID + "-trash";
+ var itemLocationTrash = installLocation.location.clone();
+@@ -2417,17 +2420,25 @@
+
+ gConsole = Cc["@mozilla.org/consoleservice;1"].
+ getService(Ci.nsIConsoleService);
+
+ gRDF = Cc["@mozilla.org/rdf/rdf-service;1"].
+ getService(Ci.nsIRDFService);
+ gInstallManifestRoot = gRDF.GetResource(RDFURI_INSTALL_MANIFEST_ROOT);
+
+- // Register Global Install Location
++ // Register Global GRE Install Location
++ var greGlobalExtensions = getDirNoCreate(KEY_GREDIR, [DIR_EXTENSIONS]);
++ var priority = Ci.nsIInstallLocation.PRIORITY_APP_SYSTEM_GLOBAL;
++ var greGlobalLocation = new DirectoryInstallLocation(KEY_GRE_GLOBAL,
++ greGlobalExtensions, true,
++ priority);
++ InstallLocations.put(greGlobalLocation);
++
++ // Register Global Application Install Location
+ var appGlobalExtensions = getDirNoCreate(KEY_APPDIR, [DIR_EXTENSIONS]);
+ var priority = Ci.nsIInstallLocation.PRIORITY_APP_SYSTEM_GLOBAL;
+ var globalLocation = new DirectoryInstallLocation(KEY_APP_GLOBAL,
+ appGlobalExtensions, true,
+ priority, false);
+ InstallLocations.put(globalLocation);
+
+ // Register App-Profile Install Location
+@@ -3613,17 +3624,17 @@
+ badItems.push(id);
+ continue;
+ }
+
+ if (ds.getItemProperty(id, "appManaged") == "true") {
+ // Force an update of the metadata for appManaged extensions since the
+ // last modified time is not updated for directories on FAT / FAT32
+ // filesystems when software update applies a new version of the app.
+- if (location.name == KEY_APP_GLOBAL) {
++ if (location.name == KEY_APP_GLOBAL || location.name == KEY_GRE_GLOBAL) {
+ var installRDF = location.getItemFile(id, FILE_INSTALL_MANIFEST);
+ if (installRDF.exists()) {
+ var metadataDS = getInstallManifest(installRDF);
+ ds.addItemMetadata(id, metadataDS, location);
+ ds.updateProperty(id, "compatible");
+ }
+ }
+ }
+@@ -3771,17 +3782,17 @@
+
+ // return early to avoid migrating data twice if we already have a
+ // toolkit 1.8 extension datasource.
+ if (dsExists)
+ return;
+
+ // Prepare themes for installation
+ // Only enumerate directories in the app-profile and app-global locations.
+- var locations = [KEY_APP_PROFILE, KEY_APP_GLOBAL];
++ var locations = [KEY_APP_PROFILE, KEY_APP_GLOBAL, KEY_GRE_GLOBAL];
+ for (var i = 0; i < locations.length; ++i) {
+ var location = InstallLocations.get(locations[i]);
+ if (!location.canAccess)
+ continue;
+
+ var entries = location.itemLocations;
+ var entry;
+ while ((entry = entries.nextFile)) {
+@@ -3837,17 +3848,18 @@
+ // items since the datasource hasn't been created yet.
+ var itemsToCheck = [];
+ if (this._checkForFileChanges()) {
+ // Create a list of all items that are to be installed so we can migrate
+ // these items's settings to the new datasource.
+ var items = PendingOperations.getOperations(OP_NEEDS_INSTALL);
+ for (i = items.length - 1; i >= 0; --i) {
+ if (items[i].locationKey == KEY_APP_PROFILE ||
+- items[i].locationKey == KEY_APP_GLOBAL)
++ items[i].locationKey == KEY_APP_GLOBAL ||
++ items[i].locationKey == KEY_GRE_GLOBAL)
+ itemsToCheck.push(items[i].id);
+ }
+ this._finishOperations();
+ }
+
+ // If there are no items to migrate settings for return early.
+ if (itemsToCheck.length == 0)
+ return;
+@@ -4933,16 +4945,17 @@
+ StartupCache.put(installLocation, id, OP_NONE, true);
+ var restartRequired = this.installRequiresRestart(id, ds.getItemProperty(id, "type"))
+ this._updateManifests(restartRequired);
+ return;
+ }
+ }
+ }
+ else if (installLocation.name == KEY_APP_PROFILE ||
++ installLocation.name == KEY_GRE_GLOBAL ||
+ installLocation.name == KEY_APP_GLOBAL ||
+ installLocation.name == KEY_APP_SYSTEM_USER) {
+ // Check for a pointer file and remove it if it exists
+ var pointerFile = installLocation.location.clone();
+ pointerFile.append(id);
+ if (pointerFile.exists() && !pointerFile.isDirectory())
+ pointerFile.remove(false);
+ }
+@@ -7094,17 +7107,17 @@
+ // with and maintained by this application AND it is installed in the
+ // global install location (i.e. the place installed by the app installer)
+ // it is and can be managed by the update file - it's not an item that has
+ // been manually installed by the user into their profile dir, and as such
+ // it is always compatible with the next release of the application since
+ // we will continue to support it.
+ var locationKey = this.getItemProperty(id, "installLocation");
+ var appManaged = this.getItemProperty(id, "appManaged") == "true";
+- if (appManaged && locationKey == KEY_APP_GLOBAL)
++ if (appManaged && (locationKey == KEY_APP_GLOBAL || locationKey == KEY_GRE_GLOBAL))
+ continue;
+
+ if (type != -1 && (type & desiredType) &&
+ !this.isCompatible(this, item, appVersion, platformVersion))
+ items.push(this.getItemForID(id));
+ }
+ return items;
+ },
+@@ -7660,17 +7673,17 @@
+ // Assert properties with single values
+ var singleProps = ["version", "updateURL", "updateService", "optionsURL",
+ "aboutURL", "iconURL", "internalName", "updateKey"];
+
+ // Items installed into restricted Install Locations can also be locked
+ // (can't be removed or disabled), and hidden (not shown in the UI)
+ if (installLocation.restricted)
+ singleProps = singleProps.concat(["locked", "hidden"]);
+- if (installLocation.name == KEY_APP_GLOBAL)
++ if (installLocation.name == KEY_APP_GLOBAL || installLocation.name == KEY_GRE_GLOBAL)
+ singleProps = singleProps.concat(["appManaged"]);
+ for (var i = 0; i < singleProps.length; ++i) {
+ var property = EM_R(singleProps[i]);
+ var literal = installManifest.GetTarget(gInstallManifestRoot, property, true);
+ // If literal is null, _setProperty will remove any existing.
+ this._setProperty(this._inner, targetRes, property, literal);
+ }
+
+@@ -8326,17 +8339,17 @@
+
+ /**
+ * Get the em:appManaged property. This prevents extensions from hiding
+ * extensions installed into locations other than the app-global location.
+ */
+ _rdfGet_appManaged: function(item, property) {
+ var id = stripPrefix(item.Value, PREFIX_ITEM_URI);
+ var locationKey = this.getItemProperty(id, "installLocation");
+- if (locationKey != KEY_APP_GLOBAL)
++ if (locationKey != KEY_APP_GLOBAL && locationKey != KEY_GRE_GLOBAL)
+ return EM_L("false");
+ return null;
+ },
+
+ /**
+ * Get the em:hidden property. This prevents extensions from hiding
+ * extensions installed into locations other than restricted locations.
+ */
+Index: mozilla/xpcom/io/nsAppDirectoryServiceDefs.h
+===================================================================
+--- mozilla.orig/xpcom/io/nsAppDirectoryServiceDefs.h
++++ mozilla/xpcom/io/nsAppDirectoryServiceDefs.h
+@@ -71,16 +71,17 @@
+
+ #define NS_APP_USER_PROFILES_ROOT_DIR "DefProfRt" // The dir where user profile dirs live.
+ #define NS_APP_USER_PROFILES_LOCAL_ROOT_DIR "DefProfLRt" // The dir where user profile temp dirs live.
+
+ #define NS_APP_RES_DIR "ARes"
+ #define NS_APP_CHROME_DIR "AChrom"
+ #define NS_APP_PLUGINS_DIR "APlugns" // Deprecated - use NS_APP_PLUGINS_DIR_LIST
+ #define NS_APP_SEARCH_DIR "SrchPlugns"
++#define NS_GRE_PLUGINS_DIR "GrePlugns" // Usually you want NS_APP_PLUGINS_DIR_LIST
+
+ #define NS_APP_CHROME_DIR_LIST "AChromDL"
+ #define NS_APP_PLUGINS_DIR_LIST "APluginsDL"
+ #define NS_APP_SEARCH_DIR_LIST "SrchPluginsDL"
+
+ // --------------------------------------------------------------------------------------
+ // Files and directories which exist on a per-profile basis
+ // These locations are typically provided by the profile mgr
+Index: mozilla/xpcom/io/nsAppFileLocationProvider.cpp
+===================================================================
+--- mozilla.orig/xpcom/io/nsAppFileLocationProvider.cpp
++++ mozilla/xpcom/io/nsAppFileLocationProvider.cpp
+@@ -194,16 +194,22 @@
+ rv = localFile->AppendRelativeNativePath(RES_DIR_NAME);
+ }
+ else if (nsCRT::strcmp(prop, NS_APP_CHROME_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(CHROME_DIR_NAME);
+ }
++ else if (nsCRT::strcmp(prop, NS_GRE_PLUGINS_DIR) == 0)
++ {
++ rv = CloneMozGreDirectory(getter_AddRefs(localFile));
++ if (NS_SUCCEEDED(rv))
++ rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
++ }
+ else if (nsCRT::strcmp(prop, NS_APP_PLUGINS_DIR) == 0)
+ {
+ rv = CloneMozBinDirectory(getter_AddRefs(localFile));
+ if (NS_SUCCEEDED(rv))
+ rv = localFile->AppendRelativeNativePath(PLUGINS_DIR_NAME);
+ }
+ #ifdef XP_MACOSX
+ else if (nsCRT::strcmp(prop, NS_MACOSX_USER_PLUGIN_DIR) == 0)
+@@ -276,16 +282,51 @@
+
+ if (localFile && NS_SUCCEEDED(rv))
+ return localFile->QueryInterface(NS_GET_IID(nsIFile), (void**)_retval);
+
+ return rv;
+ }
+
+
++NS_METHOD nsAppFileLocationProvider::CloneMozGreDirectory(nsILocalFile **aLocalFile)
++{
++ NS_ENSURE_ARG_POINTER(aLocalFile);
++ nsresult rv;
++
++ if (!mMozGreDirectory)
++ {
++ // Get the mozilla bin directory
++ // 1. Check the directory service first for NS_XPCOM_CURRENT_PROCESS_DIR
++ // This will be set if a directory was passed to NS_InitXPCOM
++ // 2. If that doesn't work, set it to be the current process directory
++ nsCOMPtr
++ directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
++ if (NS_FAILED(rv))
++ return rv;
++
++ rv = directoryService->Get(NS_GRE_DIR, NS_GET_IID(nsIFile), getter_AddRefs(mMozGreDirectory));
++ if (NS_FAILED(rv))
++ return rv;
++ }
++
++ nsCOMPtr aFile;
++ rv = mMozGreDirectory->Clone(getter_AddRefs(aFile));
++ if (NS_FAILED(rv))
++ return rv;
++
++ nsCOMPtr lfile = do_QueryInterface (aFile);
++ if (!lfile)
++ return NS_ERROR_FAILURE;
++
++ NS_IF_ADDREF(*aLocalFile = lfile);
++ return NS_OK;
++}
++
++
+ NS_METHOD nsAppFileLocationProvider::CloneMozBinDirectory(nsILocalFile **aLocalFile)
+ {
+ NS_ENSURE_ARG_POINTER(aLocalFile);
+ nsresult rv;
+
+ if (!mMozBinDirectory)
+ {
+ // Get the mozilla bin directory
+@@ -578,30 +619,30 @@
+ {
+ NS_ENSURE_ARG_POINTER(_retval);
+ *_retval = nsnull;
+ nsresult rv = NS_ERROR_FAILURE;
+
+ if (!nsCRT::strcmp(prop, NS_APP_PLUGINS_DIR_LIST))
+ {
+ #ifdef XP_MACOSX
+- static const char* osXKeys[] = { NS_APP_PLUGINS_DIR, NS_MACOSX_USER_PLUGIN_DIR, NS_MACOSX_LOCAL_PLUGIN_DIR, nsnull };
+- static const char* os9Keys[] = { NS_APP_PLUGINS_DIR, NS_MAC_CLASSIC_PLUGIN_DIR, nsnull };
++ static const char* osXKeys[] = { NS_APP_PLUGINS_DIR, NS_GRE_PLUGINS_DIR, NS_MACOSX_USER_PLUGIN_DIR, NS_MACOSX_LOCAL_PLUGIN_DIR, nsnull };
++ static const char* os9Keys[] = { NS_APP_PLUGINS_DIR, NS_GRE_PLUGINS_DIR, NS_MAC_CLASSIC_PLUGIN_DIR, nsnull };
+ static const char** keys;
+
+ if (!keys) {
+ OSErr err;
+ long response;
+ err = ::Gestalt(gestaltSystemVersion, &response);
+ keys = (!err && response >= 0x00001000) ? osXKeys : os9Keys;
+ }
+
+ *_retval = new nsAppDirectoryEnumerator(this, keys);
+ #else
+- static const char* keys[] = { nsnull, NS_USER_PLUGINS_DIR, NS_APP_PLUGINS_DIR, nsnull };
++ static const char* keys[] = { nsnull, NS_USER_PLUGINS_DIR, NS_APP_PLUGINS_DIR, NS_GRE_PLUGINS_DIR, nsnull };
+ if (!keys[0] && !(keys[0] = PR_GetEnv("MOZ_PLUGIN_PATH"))) {
+ static const char nullstr = 0;
+ keys[0] = &nullstr;
+ }
+ *_retval = new nsPathsDirectoryEnumerator(this, keys);
+ #endif
+ NS_IF_ADDREF(*_retval);
+ rv = *_retval ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
+Index: mozilla/xpcom/io/nsAppFileLocationProvider.h
+===================================================================
+--- mozilla.orig/xpcom/io/nsAppFileLocationProvider.h
++++ mozilla/xpcom/io/nsAppFileLocationProvider.h
+@@ -55,22 +55,24 @@
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER
+ NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
+
+ private:
+ ~nsAppFileLocationProvider() {}
+
+ protected:
+ NS_METHOD CloneMozBinDirectory(nsILocalFile **aLocalFile);
++ NS_METHOD CloneMozGreDirectory(nsILocalFile **aLocalFile);
+ /**
+ * Get the product directory. This is a user-specific directory for storing
+ * application settings (e.g. the Application Data directory on windows
+ * systems).
+ * @param aLocal If true, should try to get a directory that is only stored
+ * locally (ie not transferred with roaming profiles)
+ */
+ NS_METHOD GetProductDirectory(nsILocalFile **aLocalFile,
+ PRBool aLocal = PR_FALSE);
+ NS_METHOD GetDefaultUserProfileRoot(nsILocalFile **aLocalFile,
+ PRBool aLocal = PR_FALSE);
+
+ nsCOMPtr mMozBinDirectory;
++ nsCOMPtr mMozGreDirectory;
+ };
+Index: mozilla/toolkit/xre/nsXREDirProvider.cpp
+===================================================================
+--- mozilla.orig/toolkit/xre/nsXREDirProvider.cpp
++++ mozilla/toolkit/xre/nsXREDirProvider.cpp
+@@ -747,18 +747,21 @@
+
+ rv = NS_NewArrayEnumerator(aResult, directories);
+ }
+ else if (!strcmp(aProperty, NS_APP_PLUGINS_DIR_LIST)) {
+ static const char *const kAppendPlugins[] = { "plugins", nsnull };
+ nsCOMArray directories;
+
+ // The root dirserviceprovider does quite a bit for us: we're mainly
+- // interested in xulapp and extension-provided plugins.
++ // interested in gre, xulapp, and extension-provided plugins.
+ LoadBundleDirectories();
++ LoadAppDirIntoArray(mGREDir,
++ kAppendPlugins,
++ directories);
+ LoadDirsIntoArray(mAppBundleDirectories,
+ kAppendPlugins,
+ directories);
+ LoadDirsIntoArray(mExtensionDirectories,
+ kAppendPlugins,
+ directories);
+
+ rv = NS_NewArrayEnumerator(aResult, directories);
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bz429747_att317495+move_hunspell_1.2.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bz429747_att317495+move_hunspell_1.2.patch
@@ -0,0 +1,35178 @@
+---
+ extensions/spellcheck/hunspell/Makefile.in | 8
+ extensions/spellcheck/hunspell/hunspell/Makefile.in | 66
+ extensions/spellcheck/hunspell/hunspell/README.hunspell | 59
+ extensions/spellcheck/hunspell/hunspell/affentry.cpp | 924 ++
+ extensions/spellcheck/hunspell/hunspell/affentry.hxx | 187
+ extensions/spellcheck/hunspell/hunspell/affixmgr.cpp | 4155 ++++++++++++
+ extensions/spellcheck/hunspell/hunspell/affixmgr.hxx | 272
+ extensions/spellcheck/hunspell/hunspell/atypes.hxx | 154
+ extensions/spellcheck/hunspell/hunspell/baseaffix.hxx | 87
+ extensions/spellcheck/hunspell/hunspell/csutil.cpp | 5400 ++++++++++++++++
+ extensions/spellcheck/hunspell/hunspell/csutil.hxx | 233
+ extensions/spellcheck/hunspell/hunspell/hashmgr.cpp | 941 ++
+ extensions/spellcheck/hunspell/hunspell/hashmgr.hxx | 129
+ extensions/spellcheck/hunspell/hunspell/htypes.hxx | 85
+ extensions/spellcheck/hunspell/hunspell/hunspell.cpp | 1807 +++++
+ extensions/spellcheck/hunspell/hunspell/hunspell.h | 89
+ extensions/spellcheck/hunspell/hunspell/hunspell.hxx | 195
+ extensions/spellcheck/hunspell/hunspell/langnum.hxx | 94
+ extensions/spellcheck/hunspell/hunspell/phonet.cpp | 310
+ extensions/spellcheck/hunspell/hunspell/phonet.hxx | 66
+ extensions/spellcheck/hunspell/hunspell/suggestmgr.cpp | 2036 ++++++
+ extensions/spellcheck/hunspell/hunspell/suggestmgr.hxx | 160
+ extensions/spellcheck/hunspell/src/Makefile.in | 13
+ extensions/spellcheck/hunspell/src/README.hunspell | 59
+ extensions/spellcheck/hunspell/src/affentry.cpp | 924 --
+ extensions/spellcheck/hunspell/src/affentry.hxx | 187
+ extensions/spellcheck/hunspell/src/affixmgr.cpp | 4155 ------------
+ extensions/spellcheck/hunspell/src/affixmgr.hxx | 272
+ extensions/spellcheck/hunspell/src/atypes.hxx | 154
+ extensions/spellcheck/hunspell/src/baseaffix.hxx | 87
+ extensions/spellcheck/hunspell/src/csutil.cpp | 5400 ----------------
+ extensions/spellcheck/hunspell/src/csutil.hxx | 233
+ extensions/spellcheck/hunspell/src/hashmgr.cpp | 941 --
+ extensions/spellcheck/hunspell/src/hashmgr.hxx | 129
+ extensions/spellcheck/hunspell/src/htypes.hxx | 85
+ extensions/spellcheck/hunspell/src/hunspell.cpp | 1807 -----
+ extensions/spellcheck/hunspell/src/hunspell.h | 89
+ extensions/spellcheck/hunspell/src/hunspell.hxx | 195
+ extensions/spellcheck/hunspell/src/langnum.hxx | 94
+ extensions/spellcheck/hunspell/src/phonet.cpp | 310
+ extensions/spellcheck/hunspell/src/phonet.hxx | 66
+ extensions/spellcheck/hunspell/src/suggestmgr.cpp | 2036 ------
+ extensions/spellcheck/hunspell/src/suggestmgr.hxx | 160
+ extensions/spellcheck/src/Makefile.in | 6
+ 44 files changed, 17464 insertions(+), 17395 deletions(-)
+
+Index: mozilla/extensions/spellcheck/hunspell/Makefile.in
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/Makefile.in
++++ mozilla/extensions/spellcheck/hunspell/Makefile.in
+@@ -36,12 +36,18 @@
+ DEPTH = ../../..
+ topsrcdir = @top_srcdir@
+ srcdir = @srcdir@
+ VPATH = @srcdir@
+
+ include $(DEPTH)/config/autoconf.mk
+
+ MODULE = hunspell
+-DIRS = src
++
++ifndef MOZ_NATIVE_HUNSPELL
++DIRS += hunspell
++endif
++
++DIRS += src
++
+
+ include $(topsrcdir)/config/rules.mk
+
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/README.hunspell
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/README.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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++* and László Németh (Hunspell). Portions created by the Initial Developers
++* are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++*
++* Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++* David Einstein (deinst@world.std.com)
++* László Németh (nemethl@gyorsposta.hu)
++* Ryan VanderMeulen (ryanvm@gmail.com)
++*
++* 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 *******
++
++Hunspell Version: 1.1.12
++
++Hunspell Author: László Németh
++MySpell Author: Kevin Hendricks & David Einstein
++
++Hunspell is a spell checker and morphological analyser library. Hunspell
++is based on OpenOffice.org's Myspell. Documentation, tests, and examples
++are available at http://hunspell.sourceforge.net.
++
++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://lasr.cs.ucla.edu/geoff/ispell.html (Ispell homepage)
++
++An almost complete rewrite of MySpell for use by the Mozilla project was
++developed by David Einstein. David was a significant help in improving MySpell.
++
++Special thanks also goes to László Né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
++along with rewriting MySpell as Hunspell and ensuring compatibility with the
++Mozilla codebase.
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/affentry.cpp
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/affentry.cpp
+@@ -0,0 +1,924 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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; // number of conditions to match
++ opts = dp->opts; // cross product flag
++ // then copy over all of the conditions
++ memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0]));
++ next = NULL;
++ nextne = NULL;
++ nexteq = NULL;
++#ifdef HUNSPELL_EXPERIMENTAL
++ morphcode = dp->morphcode;
++#endif
++ 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 & aeUTF8) {
++ for (int i = 0; i < numconds; i++) {
++ if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]);
++ }
++ }
++#ifdef HUNSPELL_EXPERIMENTAL
++ if (morphcode && !(opts & aeALIASM)) free(morphcode);
++#endif
++ 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 int PfxEntry::test_condition(const char * st)
++{
++ int cond;
++ unsigned char * cp = (unsigned char *)st;
++ if (!(opts & aeUTF8)) { // 256-character codepage
++ for (cond = 0; cond < numconds; cond++) {
++ if ((conds.base[*cp++] & (1 << cond)) == 0) return 0;
++ }
++ } else { // UTF-8 encoding
++ unsigned short wc;
++ for (cond = 0; cond < numconds; cond++) {
++ // a simple 7-bit ASCII character in UTF-8
++ if ((*cp >> 7) == 0) {
++ // also check limit (end of word)
++ if ((!*cp) || ((conds.utf8.ascii[*cp++] & (1 << cond)) == 0)) return 0;
++ // UTF-8 multibyte character
++ } else {
++ // not dot wildcard in rule
++ if (!conds.utf8.all[cond]) {
++ if (conds.utf8.neg[cond]) {
++ u8_u16((w_char *) &wc, 1, (char *) cp);
++ if (conds.utf8.wchars[cond] &&
++ flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
++ wc, (short) conds.utf8.wlen[cond])) return 0;
++ } else {
++ if (!conds.utf8.wchars[cond]) return 0;
++ u8_u16((w_char *) &wc, 1, (char *) cp);
++ if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
++ wc, (short)conds.utf8.wlen[cond])) return 0;
++ }
++ }
++ // jump to next UTF-8 character
++ for(cp++; (*cp & 0xc0) == 0x80; cp++);
++ }
++ }
++ }
++ 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)) {
++
++ // 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 pseudoroot flag
++ ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), 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)) {
++
++ // 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;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++// 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)) {
++
++ // 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)) {
++
++ // 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 pseudoroot flag
++ ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), contclasslen) &&
++ // needflag
++ ((!needflag) || TESTAFF(he->astr, needflag, he->alen) ||
++ (contclass && TESTAFF(contclass, needflag, contclasslen)))) {
++ if (morphcode) strcat(result, morphcode); else strcat(result,getKey());
++ if (he->description) {
++ if ((*(he->description)=='[')||(*(he->description)=='<')) strcat(result,he->word);
++ strcat(result,he->description);
++ }
++ 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;
++}
++#endif // END OF HUNSPELL_EXPERIMENTAL CODE
++
++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; // number of conditions to match
++ opts = dp->opts; // cross product flag
++
++ // then copy over all of the conditions
++ memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0]));
++
++ rappnd = myrevstrdup(appnd);
++
++#ifdef HUNSPELL_EXPERIMENTAL
++ morphcode = dp->morphcode;
++#endif
++ 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 & aeUTF8) {
++ for (int i = 0; i < numconds; i++) {
++ if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]);
++ }
++ }
++#ifdef HUNSPELL_EXPERIMENTAL
++ if (morphcode && !(opts & aeALIASM)) free(morphcode);
++#endif
++ 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 int SfxEntry::test_condition(const char * st, const char * beg)
++{
++ int cond;
++ unsigned char * cp = (unsigned char *) st;
++ if (!(opts & aeUTF8)) { // 256-character codepage
++ // Domolki affix algorithm
++ for (cond = numconds; --cond >= 0; ) {
++ if ((conds.base[*--cp] & (1 << cond)) == 0) return 0;
++ }
++ } else { // UTF-8 encoding
++ unsigned short wc;
++ for (cond = numconds; --cond >= 0; ) {
++ // go to next character position and check limit
++ if ((char *) --cp < beg) return 0;
++ // a simple 7-bit ASCII character in UTF-8
++ if ((*cp >> 7) == 0) {
++ if ((conds.utf8.ascii[*cp] & (1 << cond)) == 0) return 0;
++ // UTF-8 multibyte character
++ } else {
++ // go to first character of UTF-8 multibyte character
++ for (; (*cp & 0xc0) == 0x80; cp--);
++ // not dot wildcard in rule
++ if (!conds.utf8.all[cond]) {
++ if (conds.utf8.neg[cond]) {
++ u8_u16((w_char *) &wc, 1, (char *) cp);
++ if (conds.utf8.wchars[cond] &&
++ flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
++ wc, (short) conds.utf8.wlen[cond])) return 0;
++ } else {
++ if (!conds.utf8.wchars[cond]) return 0;
++ u8_u16((w_char *) &wc, 1, (char *) cp);
++ if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
++ wc, (short)conds.utf8.wlen[cond])) return 0;
++ }
++ }
++ }
++ }
++ }
++ 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)) {
++
++ // 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)) {
++
++ // 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;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++// 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)) {
++
++ // 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,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;
++}
++#endif // END OF HUNSPELL_EXPERIMENTAL CODE
++
++// 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
++
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/affentry.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/affentry.hxx
+@@ -0,0 +1,187 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 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 int test_condition(const char * st, const char * begin);
++};
++
++#endif
++
++
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/affixmgr.cpp
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/affixmgr.cpp
+@@ -0,0 +1,4155 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 = FLAG_NULL; // 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)
++ pseudoroot = 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;
++
++ 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(pseudoroot);
++ 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 `pseudoroots' */
++ if (strncmp(line,"PSEUDOROOT",10) == 0) {
++ if (parse_flag(line, &pseudoroot, "PSEUDOROOT")) {
++ fclose(afflst);
++ return 1;
++ }
++ }
++
++ /* parse in the flag used by `pseudoroots' */
++ if (strncmp(line,"NEEDAFFIX",9) == 0) {
++ if (parse_flag(line, &pseudoroot, "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;
++ }
++ }
++
++ 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;
++}
++
++
++
++// takes aff file condition string and creates the
++// conds array - please see the appendix at the end of the
++// file affentry.cpp which describes what is going on here
++// in much more detail
++
++int AffixMgr::encodeit(struct affentry * ptr, char * cs)
++{
++ unsigned char c;
++ int i, j, k;
++ unsigned char mbr[MAXLNLEN];
++ w_char wmbr[MAXLNLEN];
++ w_char * wpos = wmbr;
++
++ // now clear the conditions array */
++ for (i=0;iconds.base[i] = (unsigned char) 0;
++
++ // now parse the string to create the conds array */
++ int nc = strlen(cs);
++ unsigned char neg = 0; // complement indicator
++ int grp = 0; // group indicator
++ unsigned char n = 0; // number of conditions
++ int ec = 0; // end condition indicator
++ int nm = 0; // number of member in group
++
++ // if no condition just return
++ if (strcmp(cs,".")==0) {
++ ptr->numconds = 0;
++ return 0;
++ }
++
++ i = 0;
++ while (i < nc) {
++ c = *((unsigned char *)(cs + i));
++
++ // start group indicator
++ if (c == '[') {
++ grp = 1;
++ c = 0;
++ }
++
++ // complement flag
++ if ((grp == 1) && (c == '^')) {
++ neg = 1;
++ c = 0;
++ }
++
++ // end goup indicator
++ if (c == ']') {
++ ec = 1;
++ c = 0;
++ }
++
++ // add character of group to list
++ if ((grp == 1) && (c != 0)) {
++ *(mbr + nm) = c;
++ nm++;
++ c = 0;
++ }
++
++ // end of condition
++ if (c != 0) {
++ ec = 1;
++ }
++
++ if (ec) {
++ if (!utf8) {
++ if (grp == 1) {
++ if (neg == 0) {
++ // set the proper bits in the condition array vals for those chars
++ for (j=0;jconds.base[k] = ptr->conds.base[k] | ((unsigned char)1 << n);
++ }
++ } else {
++ // complement so set all of them and then unset indicated ones
++ for (j=0;jconds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n);
++ for (j=0;jconds.base[k] = ptr->conds.base[k] & ~((unsigned char)1 << n);
++ }
++ }
++ neg = 0;
++ grp = 0;
++ nm = 0;
++ } else {
++ // not a group so just set the proper bit for this char
++ // but first handle special case of . inside condition
++ if (c == '.') {
++ // wild card character so set them all
++ for (j=0;jconds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n);
++ } else {
++ ptr->conds.base[(unsigned int) c] = ptr->conds.base[(unsigned int)c] | ((unsigned char)1 << n);
++ }
++ }
++ n++;
++ ec = 0;
++ } else { // UTF-8 character set
++ if (grp == 1) {
++ ptr->conds.utf8.neg[n] = neg;
++ if (neg == 0) {
++ // set the proper bits in the condition array vals for those chars
++ for (j=0;j> 7) {
++ u8_u16(wpos, 1, (char *) mbr + j);
++ wpos++;
++ if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character
++ } else {
++ ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] | ((unsigned char)1 << n);
++ }
++ }
++ } else { // neg == 1
++ // complement so set all of them and then unset indicated ones
++ for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n);
++ for (j=0;j> 7) {
++ u8_u16(wpos, 1, (char *) mbr + j);
++ wpos++;
++ if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character
++ } else {
++ ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] & ~((unsigned char)1 << n);
++ }
++ }
++ }
++ neg = 0;
++ grp = 0;
++ nm = 0;
++ ptr->conds.utf8.wlen[n] = wpos - wmbr;
++ if ((wpos - wmbr) != 0) {
++ ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char) * (wpos - wmbr));
++ if (!ptr->conds.utf8.wchars[n]) return 1;
++ memcpy(ptr->conds.utf8.wchars[n], wmbr, sizeof(w_char) * (wpos - wmbr));
++ flag_qsort((unsigned short *) ptr->conds.utf8.wchars[n], 0, ptr->conds.utf8.wlen[n]);
++ wpos = wmbr;
++ }
++ } else { // grp == 0
++ // is UTF-8 character?
++ if (c >> 7) {
++ ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char));
++ if (!ptr->conds.utf8.wchars[n]) return 1;
++ ptr->conds.utf8.wlen[n] = 1;
++ u8_u16(ptr->conds.utf8.wchars[n], 1, cs + i);
++ if ((c & 0xe0) == 0xe0) i+=2; else i++; // 3-byte UFT-8 character
++ } else {
++ ptr->conds.utf8.wchars[n] = NULL;
++ // not a group so just set the proper bit for this char
++ // but first handle special case of . inside condition
++ if (c == '.') {
++ ptr->conds.utf8.all[n] = 1;
++ // wild card character so set them all
++ for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n);
++ } else {
++ ptr->conds.utf8.all[n] = 0;
++ ptr->conds.utf8.ascii[(unsigned int) c] = ptr->conds.utf8.ascii[(unsigned int)c] | ((unsigned char)1 << n);
++ }
++ }
++ neg = 0;
++ }
++ n++;
++ ec = 0;
++ neg = 0;
++ }
++ }
++
++ i++;
++ }
++ ptr->numconds = n;
++ return 0;
++}
++
++ // return 1 if s1 is a leading subset of s2
++/* inline int AffixMgr::isSubset(const char * s1, const char * s2)
++ {
++ while ((*s1 == *s2) && *s1) {
++ s1++;
++ s2++;
++ }
++ return (*s1 == '\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;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++// 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;
++}
++#endif // END OF HUNSPELL_EXPERIMENTAL CODE
++
++
++// 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 &&
++ ((pseudoroot && TESTAFF(rv->astr, pseudoroot, 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 pseudoroot
++ } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
++ TESTAFF(rv->astr, pseudoroot, 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) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, 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+1word), rv->clen)<=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;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++// 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 &&
++ ((pseudoroot && TESTAFF(rv->astr, pseudoroot, 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 (rv->description) {
++ if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
++ strcat(presult, st);
++ strcat(presult, rv->description);
++ }
++ }
++
++ 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 ((wordnum == 0) && compoundbegin) {
++ p = affix_check_morph(st, i, compoundbegin);
++ } else if ((wordnum > 0) && compoundmiddle) {
++ p = affix_check_morph(st, i, compoundmiddle);
++ }
++ }
++ if (*p != '\0') {
++ line_uniq(p);
++ if (strchr(p, '\n')) {
++ strcat(presult, "(");
++ strcat(presult, line_join(p, '|'));
++ strcat(presult, ")");
++ } else {
++ strcat(presult, p);
++ }
++ }
++ if (presult[strlen(presult) - 1] == '\n') {
++ presult[strlen(presult) - 1] = '\0';
++ }
++ checked_prefix = 1;
++ //strcat(presult, "+");
++ }
++ // else check forbiddenwords
++ } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
++ TESTAFF(rv->astr, pseudoroot, 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) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, 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);
++ if (complexprefixes && rv->description) strcat(*result, rv->description);
++ if (rv->description && ((!rv->astr) ||
++ !TESTAFF(rv->astr, lemma_present, rv->alen)))
++ strcat(*result, &(rv->word));
++ if (!complexprefixes && rv->description) strcat(*result, rv->description);
++ 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+1word),rv->wlen)<=cpdmaxsyllable))
++ )
++ && (
++ (!checkcompounddup || (rv != rv_first))
++ )
++ )
++ {
++ // bad compound word
++ strcat(*result, presult);
++
++ if (rv->description) {
++ if (complexprefixes) strcat(*result, rv->description);
++ if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
++ strcat(*result, &(rv->word));
++ if (!complexprefixes) strcat(*result, rv->description);
++ }
++ 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)
++ m = affix_check_morph((word+i),strlen(word+i), compoundend);
++ strcat(*result, presult);
++ if (m) {
++ line_uniq(m);
++ if (strchr(m, '\n')) {
++ strcat(*result, "(");
++ strcat(*result, line_join(m, '|'));
++ strcat(*result, ")");
++ } else {
++ strcat(*result, 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, pseudoroot, 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()))))) &&
++ // pseudoroot on prefix or first suffix
++ (cclass ||
++ !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) ||
++ (ppfx && !((ep->getCont()) &&
++ TESTAFF(ep->getCont(), pseudoroot,
++ 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()))))) &&
++ // pseudoroot on prefix or first suffix
++ (cclass ||
++ !(sptr->getCont() && TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) ||
++ (ppfx && !((ep->getCont()) &&
++ TESTAFF(ep->getCont(), pseudoroot,
++ 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 {
++ strcpy(result, derived); // XXX check size
++ strcat(result, "\n");
++ strcat(result, word);
++ 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;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++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, st);
++ free(st);
++ if (se->getMorph()) 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, 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()))))) &&
++ // pseudoroot on prefix or first suffix
++ (cclass ||
++ !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) ||
++ (ppfx && !((ep->getCont()) &&
++ TESTAFF(ep->getCont(), pseudoroot,
++ 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());
++ }
++ if (complexprefixes && rv->description) strcat(result, rv->description);
++ if (rv->description && ((!rv->astr) ||
++ !TESTAFF(rv->astr, lemma_present, rv->alen)))
++ strcat(result, &(rv->word));
++ if (!complexprefixes && rv->description) strcat(result, rv->description);
++ if (se->getMorph()) 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()))))) &&
++ // pseudoroot on first suffix
++ (cclass || !(sptr->getCont() &&
++ TESTAFF(sptr->getCont(), pseudoroot, 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());
++ }
++ if (complexprefixes && rv->description) strcat(result, rv->description);
++ if (rv->description && ((!rv->astr) ||
++ !TESTAFF(rv->astr, lemma_present, rv->alen))) strcat(result, &(rv->word));
++ if (!complexprefixes && rv->description) strcat(result, rv->description);
++#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, 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;
++}
++#endif // END OF HUNSPELL_EXPERIMENTAL CODE
++
++
++// 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;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++// 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);
++}
++#endif // END OF HUNSPELL_EXPERIMENTAL CODE
++
++
++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 && ((pseudoroot && TESTAFF(ap, pseudoroot, 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 pseudoroot flag
++ !(sptr->getCont() && ((pseudoroot &&
++ TESTAFF(sptr->getCont(), pseudoroot, 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 pseudoroot flag
++ !(ptr->getCont() && ((pseudoroot &&
++ TESTAFF(ptr->getCont(), pseudoroot, 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_pseudoroot()
++{
++ return pseudoroot;
++}
++
++// 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) {
++ 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;
++}
++
++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;
++#ifdef HUNSPELL_EXPERIMENTAL
++ if (pHMgr->is_aliasm()) ptr->opts += aeALIASM;
++#endif
++ 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;
++ 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;
++#ifdef HUNSPELL_EXPERIMENTAL
++ nptr->morphcode = NULL;
++#endif
++ 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) {
++ int neg = 0;
++ if (utf8) reverseword_utf(piece); else reverseword(piece);
++ // reverse condition
++ 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;
++ }
++ }
++ }
++ }
++ if (nptr->stripl && (strcmp(piece, ".") != 0) &&
++ redundant_condition(at, nptr->strip, nptr->stripl, piece, nl))
++ strcpy(piece, ".");
++ if (encodeit(nptr,piece)) return 1;
++ break;
++ }
++
++#ifdef HUNSPELL_EXPERIMENTAL
++ case 5: {
++ np++;
++ if (pHMgr->is_aliasm()) {
++ int index = atoi(piece);
++ nptr->morphcode = pHMgr->get_aliasm(index);
++ } else {
++ if (complexprefixes) {
++ if (utf8) reverseword_utf(piece); else reverseword(piece);
++ }
++ nptr->morphcode = mystrdup(piece);
++ }
++ break;
++ }
++#endif
++
++ 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
++#ifdef HUNSPELL_EXPERIMENTAL
++ // 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
++#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;
++}
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/affixmgr.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/affixmgr.hxx
+@@ -0,0 +1,272 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 pseudoroot;
++ 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;
++ 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);
++
++ 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_pseudoroot();
++ 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_string(char * line, char ** out, const char * name);
++ int parse_flag(char * line, unsigned short * out, const char * name);
++ int parse_num(char * line, int * out, const char * name);
++// int parse_array(char * line, char ** out, unsigned short ** out_utf16,
++// int * out_utf16_len, 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);
++
++ 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
++
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/atypes.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/atypes.hxx
+@@ -0,0 +1,154 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 aeINFIX (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 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;
++ union {
++ char base[SETSIZE];
++ struct {
++ char ascii[SETSIZE/2];
++ char neg[8];
++ char all[8];
++ w_char * wchars[8];
++ int wlen[8];
++ } utf8;
++ } conds;
++#ifdef HUNSPELL_EXPERIMENTAL
++ char * morphcode;
++#endif
++ unsigned short * contclass;
++ short contclasslen;
++};
++
++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
++
++
++
++
++
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/baseaffix.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/baseaffix.hxx
+@@ -0,0 +1,87 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 base[SETSIZE];
++ struct {
++ char ascii[SETSIZE/2];
++ char neg[8];
++ char all[8];
++ w_char * wchars[8];
++ int wlen[8];
++ } utf8;
++ } conds;
++ char * morphcode;
++ unsigned short * contclass;
++ short contclasslen;
++};
++
++#endif
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/csutil.cpp
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/csutil.cpp
+@@ -0,0 +1,5400 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 %d. character position\n%s\n", 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 %d. character position:\n%s\n", 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 %d. character position:\n%s\n", u8 - src, src);
++ u2->h = 0xff;
++ u2->l = 0xfd;
++ }
++ } else {
++ HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", 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 * rv = NULL;
++ char * mp = *stringp;
++ int n = strlen(mp);
++ if (n > 0) {
++ char * dp;
++ if (delim) {
++ dp = (char *)memchr(mp,(int)((unsigned char)delim),n);
++ } 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);
++ 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 * 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;
++ }
++
++#ifdef HUNSPELL_EXPERIMENTAL
++ // 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);
++ }
++
++// break text to lines
++// return number of lines
++int line_tok(const char * text, char *** lines) {
++ int linenum = 0;
++ char * dup = mystrdup(text);
++ char * p = strchr(dup, '\n');
++ while (p) {
++ linenum++;
++ *p = '\0';
++ p++;
++ p = strchr(p, '\n');
++ }
++ *lines = (char **) calloc(linenum + 1, sizeof(char *));
++ if (!(*lines)) return -1;
++
++ p = dup;
++ for (int i = 0; i < linenum + 1; i++) {
++ (*lines)[i] = mystrdup(p);
++ p += strlen(p) + 1;
++ }
++ free(dup);
++ return linenum;
++}
++
++// uniq line in place
++char * line_uniq(char * text) {
++ char ** lines;
++ int linenum = line_tok(text, &lines);
++ 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')) strcat(text, "\n");
++ strcat(text, lines[i]);
++ }
++ }
++ for ( i = 0; i<=linenum; i++ ) {
++ if (lines[i]) free(lines[i]);
++ }
++ if (lines) free(lines);
++ return text;
++}
++
++// change \n to char c
++char * line_join(char * text, char c) {
++ char * p;
++ for (p = text; *p; p++) if (*p == '\n') *p = c;
++ return text;
++}
++
++// leave only last {[^}]*} substring for handling zero morphemes
++char * delete_zeros(char * morphout) {
++ char * p = morphout;
++ char * q = p;
++ char * q2 = NULL;
++ int suffix = 0;
++
++ for (;*p && *(p+1);) {
++ switch (*p) {
++ case '{':
++ q2 = q;
++ q--;
++ break;
++ case '}':
++ if (q2) {
++ suffix = 1;
++ q--;
++ }
++ break;
++ default:
++ if (suffix) {
++ q = q2;
++ }
++ suffix = 0;
++ *q = *p;
++ }
++ p++;
++ q++;
++ }
++ *q = '\0';
++ return morphout;
++}
++#endif // END OF HUNSPELL_EXPERIMENTAL CODE
++
++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;
++ }
++
++ // 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;
++}
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/csutil.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/csutil.hxx
+@@ -0,0 +1,233 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 FIELD_STEM "st:"
++#define FIELD_POS "po:"
++#define FIELD_SUFF "su:"
++#define FIELD_PREF "pr:"
++#define FIELD_FREQ "fr:"
++#define FIELD_PHON "ph:"
++#define FIELD_HYPH "hy:"
++#define FIELD_COMP "co:"
++
++// default flags
++#define ONLYUPCASEFLAG 65535
++
++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);
++
++// tokenize into lines with new line and uniq in place
++ char * line_uniq(char * text);
++
++// change \n to c in place
++ char * line_join(char * text, char c);
++
++// leave only last {[^}]*} pattern in string
++ char * delete_zeros(char * morphout);
++
++// reverse word
++ int reverseword(char *);
++
++// reverse word
++ int reverseword_utf(char *);
++
++// 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);
++
++#endif
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/hashmgr.cpp
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/hashmgr.cpp
+@@ -0,0 +1,941 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 = FLAG_NULL; // 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;
++/* if (pt) {
++ if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr);
++#ifdef HUNSPELL_EXPERIMENTAL
++ if (pt->description && !aliasm) free(pt->description);
++#endif
++ pt = pt->next;
++ }
++*/
++ while(pt) {
++ nt = pt->next;
++ if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr);
++#ifdef HUNSPELL_EXPERIMENTAL
++ if (pt->description && !aliasm) free(pt->description);
++#endif
++ 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) ? strlen(desc) : 0;
++ // variable-length hash record with word and optional fields
++ // instead of mmap implementation temporarily
++ struct hentry* hp =
++ (struct hentry *) malloc (sizeof(struct hentry) + wbl + descl + 1);
++ if (!hp) return 1;
++ char * hpw = &(hp->word);
++ strcpy(hpw, word);
++ if (desc && strncmp(desc, FIELD_PHON, strlen(FIELD_PHON)) == 0) {
++ strcpy(hpw + wbl + 1, desc + strlen(FIELD_PHON));
++ hp->var = 1;
++ } else {
++ hp->var = 0;
++ }
++ 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;
++#ifdef HUNSPELL_EXPERIMENTAL
++ if (aliasm) {
++ hp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc);
++ } else {
++ hp->description = mystrdup(desc);
++ if (desc && !hp->description)
++ {
++ free(hp->astr);
++ free(hp);
++ return 1;
++ }
++ if (hp->description && complexprefixes) {
++ if (utf8) reverseword_utf(hp->description); else reverseword(hp->description);
++ }
++ }
++#endif
++
++ 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;
++}
++
++// add a custom dic. word to the hash table (public)
++int HashMgr::put_word(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::put_word_pattern(const char * word, const char * pattern)
++{
++ // detect captype and modify word length for UTF-8 encoding
++ struct hentry * dp = lookup(pattern);
++ 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;
++ }
++ }
++
++#ifdef HUNSPELL_EXPERIMENTAL
++ if ((strncmp(line,"AM",2) == 0) && isspace(line[2])) {
++ if (parse_aliasm(line, afflst)) {
++ fclose(afflst);
++ return 1;
++ }
++ }
++#endif
++ 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;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++/* 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, 0);
++ 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: {
++ if (complexprefixes) {
++ if (utf8) reverseword_utf(piece);
++ else reverseword(piece);
++ }
++ aliasm[j] = mystrdup(piece);
++ break; }
++ default: break;
++ }
++ i++;
++ }
++ free(piece);
++ piece = mystrsep(&tp, 0);
++ }
++ 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;
++}
++#endif
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/hashmgr.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/hashmgr.hxx
+@@ -0,0 +1,129 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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 put_word(const char * word, char * ap);
++ int put_word_pattern(const char * word, const char * pattern);
++ 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);
++#ifdef HUNSPELL_EXPERIMENTAL
++ int is_aliasm();
++ char * get_aliasm(int index);
++#endif
++
++
++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);
++#ifdef HUNSPELL_EXPERIMENTAL
++ int parse_aliasm(char * line, FILE * af);
++#endif
++
++};
++
++#endif
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/htypes.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/htypes.hxx
+@@ -0,0 +1,85 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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));
++
++// 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)
++#ifdef HUNSPELL_EXPERIMENTAL
++ char * description; // morphological data (optional)
++#endif
++ char var; // variable fields (only for special pronounciation yet)
++ char word; // variable-length word (8-bit or UTF-8 encoding)
++};
++
++#endif
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/hunspell.cpp
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/hunspell.cpp
+@@ -0,0 +1,1807 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#ifndef MOZILLA_CLIENT
++#include
++#include
++#include
++#else
++#include
++#include
++#include
++#endif
++
++#include "hunspell.hxx"
++#include "hunspell.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;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++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);
++}
++#endif
++
++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 pseudoroot, onlyincompound homonym or onlyupcase word
++ while (he && (he->astr) &&
++ ((pAMgr->get_pseudoroot() && TESTAFF(he->astr, pAMgr->get_pseudoroot(), 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;
++}
++
++// XXX need UTF-8 support
++int Hunspell::stem(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 HUHCAP:
++ case NOCAP: {
++ ns = pSMgr->suggest_stems(slst, cw, ns);
++
++ if ((abbv) && (ns == 0)) {
++ memcpy(wspace,cw,wl);
++ *(wspace+wl) = '.';
++ *(wspace+wl+1) = '\0';
++ ns = pSMgr->suggest_stems(slst, wspace, ns);
++ }
++
++ break;
++ }
++
++ case INITCAP: {
++
++ ns = pSMgr->suggest_stems(slst, cw, ns);
++
++ if (ns == 0) {
++ memcpy(wspace,cw,(wl+1));
++ mkallsmall(wspace);
++ ns = pSMgr->suggest_stems(slst, wspace, ns);
++
++ }
++
++ if ((abbv) && (ns == 0)) {
++ memcpy(wspace,cw,wl);
++ mkallsmall(wspace);
++ *(wspace+wl) = '.';
++ *(wspace+wl+1) = '\0';
++ ns = pSMgr->suggest_stems(slst, wspace, ns);
++ }
++
++ break;
++
++ }
++
++ case ALLCAP: {
++ ns = pSMgr->suggest_stems(slst, cw, ns);
++ if (ns != 0) break;
++
++ memcpy(wspace,cw,(wl+1));
++ mkallsmall(wspace);
++ ns = pSMgr->suggest_stems(slst, wspace, ns);
++
++ if (ns == 0) {
++ mkinitcap(wspace);
++ ns = pSMgr->suggest_stems(slst, wspace, ns);
++ }
++
++ if ((abbv) && (ns == 0)) {
++ memcpy(wspace,cw,wl);
++ mkallsmall(wspace);
++ *(wspace+wl) = '.';
++ *(wspace+wl+1) = '\0';
++ ns = pSMgr->suggest_stems(slst, wspace, ns);
++ }
++
++
++ break;
++ }
++ }
++
++ return ns;
++}
++
++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::put_word(const char * word)
++{
++ if (pHMgr) return pHMgr->put_word(word, NULL);
++ return 0;
++}
++
++int Hunspell::put_word_pattern(const char * word, const char * pattern)
++{
++ if (pHMgr) return pHMgr->put_word_pattern(word, pattern);
++ return 0;
++}
++
++const char * Hunspell::get_version()
++{
++ return pAMgr->get_version();
++}
++
++struct cs_info * Hunspell::get_csconv()
++{
++ return csconv;
++}
++
++#ifdef HUNSPELL_EXPERIMENTAL
++// XXX need UTF-8 support
++char * Hunspell::morph(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 NULL;
++ 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) {
++ st = pSMgr->suggest_morph(cw + n - 1);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++ } else {
++ char sign = cw[n];
++ cw[n] = '\0';
++ st = pSMgr->suggest_morph(cw + n - 1);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++ strcat(result, "+"); // XXX SPEC. MORPHCODE
++ cw[n] = sign;
++ st = pSMgr->suggest_morph(cw + n);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++ }
++ return mystrdup(result);
++ }
++ }
++ // END OF LANG_hu section
++
++ switch(captype) {
++ case NOCAP: {
++ st = pSMgr->suggest_morph(cw);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++ if (abbv) {
++ memcpy(wspace,cw,wl);
++ *(wspace+wl) = '.';
++ *(wspace+wl+1) = '\0';
++ st = pSMgr->suggest_morph(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(wspace);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++ st = pSMgr->suggest_morph(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(wspace);
++ if (st) {
++ if (*result) strcat(result, "\n");
++ strcat(result, st);
++ free(st);
++ }
++ mkinitcap(wspace);
++ st = pSMgr->suggest_morph(wspace);
++ if (st) {
++ if (*result) strcat(result, "\n");
++ strcat(result, st);
++ free(st);
++ }
++ }
++ break;
++ }
++ case HUHCAP: {
++ st = pSMgr->suggest_morph(cw);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++#if 0
++ memcpy(wspace,cw,(wl+1));
++ mkallsmall(wspace);
++ st = pSMgr->suggest_morph(wspace);
++ if (st) {
++ if (*result) strcat(result, "\n");
++ strcat(result, st);
++ free(st);
++ }
++#endif
++ break;
++ }
++ case ALLCAP: {
++ memcpy(wspace,cw,(wl+1));
++ st = pSMgr->suggest_morph(wspace);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++ mkallsmall(wspace);
++ st = pSMgr->suggest_morph(wspace);
++ if (st) {
++ if (*result) strcat(result, "\n");
++ strcat(result, st);
++ free(st);
++ }
++ mkinitcap(wspace);
++ st = pSMgr->suggest_morph(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(wspace);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++ mkallsmall(wspace);
++ st = pSMgr->suggest_morph(wspace);
++ if (st) {
++ if (*result) strcat(result, "\n");
++ strcat(result, st);
++ free(st);
++ }
++ mkinitcap(wspace);
++ st = pSMgr->suggest_morph(wspace);
++ if (st) {
++ if (*result) strcat(result, "\n");
++ strcat(result, st);
++ free(st);
++ }
++ }
++ break;
++ }
++ }
++
++ if (result && (*result)) {
++ // word reversing wrapper for complex prefixes
++ if (complexprefixes) {
++ if (utf8) reverseword_utf(result); else reverseword(result);
++ }
++ return mystrdup(result);
++ }
++
++ // 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 pSMgr->suggest_morph(cw);
++ } 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 mystrdup(result);
++ }
++ } 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 = morph(cw);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ strcat(result,"+"); // XXX spec. separator in MORPHCODE
++ }
++ st = morph(dash+1);
++ if (st) {
++ strcat(result, st);
++ free(st);
++ }
++ return mystrdup(result);
++ }
++ }
++ // 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 mystrdup(result);
++ }
++ }
++ }
++ }
++ return NULL;
++}
++
++// XXX need UTF-8 support
++char * Hunspell::morph_with_correction(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;
++
++ 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;
++}
++
++/* analyze word
++ * return line count
++ * XXX need a better data structure for morphological analysis */
++int Hunspell::analyze(char ***out, const char *word) {
++ int n = 0;
++ if (!word) return 0;
++ char * m = morph(word);
++ if(!m) return 0;
++ if (!out)
++ {
++ n = line_tok(m, out);
++ free(m);
++ return n;
++ }
++
++ // without memory allocation
++ /* BUG missing buffer size checking */
++ int i, p;
++ for(p = 0, i = 0; m[i]; i++) {
++ if(m[i] == '\n' || !m[i+1]) {
++ n++;
++ strncpy((*out)[n++], m + p, i - p + 1);
++ if (m[i] == '\n') (*out)[n++][i - p] = '\0';
++ if(!m[i+1]) break;
++ p = i + 1;
++ }
++ }
++ free(m);
++ return n;
++}
++
++#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);
++}
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/hunspell.h
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/hunspell.h
+@@ -0,0 +1,89 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/hunspell.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/hunspell.hxx
+@@ -0,0 +1,195 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 "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();
++
++ /* handling custom dictionary */
++
++ int put_word(const char * word);
++
++ /* pattern is a sample dictionary word
++ * put word into custom dictionary with affix flags of pattern word
++ */
++
++ int put_word_pattern(const char * word, const char * pattern);
++
++ /* 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 functions */
++
++#ifdef HUNSPELL_EXPERIMENTAL
++ /* suffix is an affix flag string, similarly in dictionary files */
++
++ int put_word_suffix(const char * word, const char * suffix);
++
++ /* morphological analysis */
++
++ char * morph(const char * word);
++ int analyze(char*** out, const char *word);
++
++ char * morph_with_correction(const char * word);
++
++ /* stemmer function */
++
++ int stem(char*** slst, 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);
++
++};
++
++#endif
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/langnum.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/langnum.hxx
+@@ -0,0 +1,94 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/phonet.cpp
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/phonet.cpp
+@@ -0,0 +1,310 @@
++/******* 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 Initial Developer of the Original Code is Björn Jacke. Portions created
++ * by the Initial Developers are Copyright (C) 2000-2007 the Initial
++ * Developers. All Rights Reserved.
++ *
++ * Contributor(s): Björn Jacke (bjoern.jacke@gmx.de)
++ * László Németh (nemethl@gyorsposta.hu)
++ *
++ * 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.
++ *
++ * Changelog:
++ * 2000-01-05 Björn Jacke
++ * Initial Release insprired by the article about phonetic
++ * transformations out of c't 25/1999
++ *
++ * 2007-07-26 Björn Jacke
++ * Released under MPL/GPL/LGPL tri-license for Hunspell
++ *
++ * 2007-08-23 László Németh
++ * Porting from Aspell to Hunspell using C-like structs
++ *
++ ******* END LICENSE BLOCK *******/
++
++#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" **/
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/phonet.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/phonet.hxx
+@@ -0,0 +1,66 @@
++/******* 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 Initial Developer of the Original Code is Björn Jacke. Portions created
++ * by the Initial Developers are Copyright (C) 2000-2007 the Initial
++ * Developers. All Rights Reserved.
++ *
++ * Contributor(s): Björn Jacke (bjoern.jacke@gmx.de)
++ * László Németh (nemethl@gyorsposta.hu)
++ *
++ * 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.
++ *
++ * Changelog:
++ * 2000-01-05 Björn Jacke
++ * Initial Release insprired by the article about phonetic
++ * transformations out of c't 25/1999
++ *
++ * 2007-07-20 Björn Jacke
++ * Released under MPL/GPL/LGPL tri-license for Hunspell
++ *
++ * 2007-08-22 László Németh
++ * Porting from Aspell to Hunspell by little modifications
++ *
++ ******* END LICENSE BLOCK *******/
++
++#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
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/suggestmgr.cpp
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/suggestmgr.cpp
+@@ -0,0 +1,2036 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#ifndef MOZILLA_CLIENT
++#include
++#include
++#include
++#include
++#else
++#include
++#include
++#include
++#include
++#endif
++
++#include "suggestmgr.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; else *
++
++ // 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 * 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);
++// fprintf(stderr, "Tip: %s->%s\n", candidate, target);
++ }
++
++ 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, &(hp->word), NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
++ leftcommonsubstring(word, &(hp->word));
++
++ // check special pronounciation
++ if (hp->var) {
++ int sc2 = ngram(3, word, &(hp->word) + hp->blen + 1, NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
++ leftcommonsubstring(word, &(hp->word) + hp->blen + 1);
++ if (sc2 > sc) sc = sc2;
++ }
++
++ if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) {
++ char target2[MAXSWUTF8L];
++ strcpy(candidate, &(hp->word));
++ 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] = &(hp->word);
++ 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, &(rp->word), rp->blen,
++ rp->astr, rp->alen, word, nc,
++ ((rp->var) ? &(rp->word) + rp->blen + 1 : 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_pseudoroot(),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_pseudoroot(),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 stems, XXX experimental code
++int SuggestMgr::suggest_stems(char*** slst, const char * w, int nsug)
++{
++ char buf[MAXSWUTF8L];
++ char ** wlst;
++ int prevnsug = nsug;
++
++ 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 **) calloc(maxSug, sizeof(char *));
++ if (wlst == NULL) return -1;
++ }
++ // perhaps there are a fix stem in the dictionary
++ if ((nsug < maxSug) && (nsug > -1)) {
++
++ nsug = fixstems(wlst, word, nsug);
++ if (nsug == prevnsug) {
++ char * s = mystrdup(word);
++ char * p = s + strlen(s);
++ while ((*p != '-') && (p != s)) p--;
++ if (*p == '-') {
++ *p = '\0';
++ nsug = fixstems(wlst, s, nsug);
++ if ((nsug == prevnsug) && (nsug < maxSug) && (nsug >= 0)) {
++ char * t;
++ buf[0] = '\0';
++ for (t = s; (t[0] != '\0') && ((t[0] >= '0') || (t[0] <= '9')); t++); // is a number?
++ if (*t != '\0') strcpy(buf, "# ");
++ strcat(buf, s);
++ wlst[nsug] = mystrdup(buf);
++ if (wlst[nsug] == NULL) return -1;
++ nsug++;
++ }
++ p++;
++ nsug = fixstems(wlst, p, nsug);
++ }
++
++ free(s);
++ }
++ }
++
++ if (nsug < 0) {
++ for (int i=0;ilookup(word);
++ if (rv) {
++ dicstem = 0;
++ } else {
++ // try stripping off affixes
++ rv = pAMgr->affix_check(word, wl);
++
++ // else try check compound word
++ if (!rv && pAMgr->get_compound()) {
++ rv = pAMgr->compound_check(word, wl,
++ 0, 0, 100, 0, NULL, 0, &cmpdstemnum, cmpdstem,1);
++
++ if (rv) {
++ dicstem = 2;
++ for (int j = 0; j < cmpdstemnum; j++) {
++ cpdindex += cmpdstem[j];
++ }
++ if(! (pAMgr->lookup(word + cpdindex)))
++ pAMgr->affix_check(word + cpdindex, wl - cpdindex); // for prefix
++ }
++ }
++
++
++ if (pAMgr->get_prefix()) {
++ strcpy(prefix, pAMgr->get_prefix());
++ }
++
++ // XXX obsolete, will be a general solution for stemming
++ if ((prefix) && (strncmp(prefix, "leg", 3)==0)) prefix[0] = '\0'; // (HU)
++ }
++
++ }
++
++
++
++ if ((rv) && (ns < maxSug)) {
++
++ // check fixstem flag and not_valid_stem flag
++ // first word
++ if ((ns < maxSug) && (dicstem < 2)) {
++ strcpy(buf, prefix);
++ if ((dicstem > 0) && pAMgr->get_derived()) {
++ // XXX obsolote
++ if (strlen(prefix) == 1) {
++ strcat(buf, (pAMgr->get_derived()) + 1);
++ } else {
++ strcat(buf, pAMgr->get_derived());
++ }
++ } else {
++ // special stem in affix description
++ const char * wordchars = pAMgr->get_wordchars();
++ if (rv->description &&
++ (strchr(wordchars, *(rv->description)))) {
++ char * desc = (rv->description) + 1;
++ while (strchr(wordchars, *desc)) desc++;
++ strncat(buf, rv->description, desc - (rv->description));
++ } else {
++ strcat(buf, rv->word);
++ }
++ }
++ wlst[ns] = mystrdup(buf);
++ if (wlst[ns] == NULL) return -1;
++ ns++;
++ }
++
++ if (dicstem == 2) {
++
++ // compound stem
++
++// if (rv->astr && (strchr(rv->astr, '0') == NULL)) {
++ if (rv->astr) {
++ strcpy(buf, word);
++ buf[cpdindex] = '\0';
++ if (prefix) strcat(buf, prefix);
++ if (pAMgr->get_derived()) {
++ strcat(buf, pAMgr->get_derived());
++ } else {
++ // special stem in affix description
++ const char * wordchars = pAMgr->get_wordchars();
++ if (rv->description &&
++ (strchr(wordchars, *(rv->description)))) {
++ char * desc = (rv->description) + 1;
++ while (strchr(wordchars, *desc)) desc++;
++ strncat(buf, rv->description, desc - (rv->description));
++ } else {
++ strcat(buf, rv->word);
++ }
++ }
++ if (ns < maxSug) {
++ wlst[ns] = mystrdup(buf);
++ if (wlst[ns] == NULL) return -1;
++ ns++;
++ }
++ }
++ }
++ }
++ return ns;
++}
++
++// 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;
++}
++
++
++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_pseudoroot(), rv->alen) ||
++ TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) {
++ if (rv->description && ((!rv->astr) ||
++ !TESTAFF(rv->astr, pAMgr->get_lemma_present(), rv->alen)))
++ strcat(result, word);
++ if (rv->description) strcat(result, rv->description);
++ 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(delete_zeros(result))) : NULL;
++}
++
++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);
++ 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
++
++
++// 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;
++}
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/suggestmgr.hxx
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/suggestmgr.hxx
+@@ -0,0 +1,160 @@
++/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++ * and László Németh (Hunspell). Portions created by the Initial Developers
++ * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++ *
++ * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
++ * David Einstein (deinst@world.std.com)
++ * László Németh (nemethl@gyorsposta.hu)
++ * 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 *******/
++
++#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_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);
++
++};
++
++#endif
+Index: mozilla/extensions/spellcheck/hunspell/src/Makefile.in
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/Makefile.in
++++ mozilla/extensions/spellcheck/hunspell/src/Makefile.in
+@@ -51,36 +51,27 @@
+ unicharutil \
+ spellchecker \
+ xulapp \
+ $(NULL)
+
+ CPPSRCS = mozHunspell.cpp \
+ $(NULL)
+
+-ifndef MOZ_NATIVE_HUNSPELL
+-CPPSRCS += affentry.cpp \
+- affixmgr.cpp \
+- csutil.cpp \
+- hashmgr.cpp \
+- hunspell.cpp \
+- phonet.cpp \
+- suggestmgr.cpp \
+- $(NULL)
+-endif
+-
+ ifdef MOZ_XUL_APP
+ CPPSRCS += mozHunspellDirProvider.cpp
+ endif
+
+ EXTRA_DSO_LDOPTS = \
+ $(LIBS_DIR) \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(MOZ_UNICHARUTIL_LIBS) \
+ $(MOZ_HUNSPELL_LIBS) \
+ $(NULL)
+
+ include $(topsrcdir)/config/rules.mk
+
+ ifdef MOZ_NATIVE_HUNSPELL
+ CXXFLAGS += $(MOZ_HUNSPELL_CFLAGS)
++else
++CXXFLAGS += -I$(srcdir)/../hunspell
+ endif
+Index: mozilla/extensions/spellcheck/hunspell/src/README.hunspell
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/README.hunspell
++++ /dev/null
+@@ -1,59 +0,0 @@
+-******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+-* and László Németh (Hunspell). Portions created by the Initial Developers
+-* are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+-*
+-* Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+-* David Einstein (deinst@world.std.com)
+-* László Németh (nemethl@gyorsposta.hu)
+-* Ryan VanderMeulen (ryanvm@gmail.com)
+-*
+-* 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 *******
+-
+-Hunspell Version: 1.1.12
+-
+-Hunspell Author: László Németh
+-MySpell Author: Kevin Hendricks & David Einstein
+-
+-Hunspell is a spell checker and morphological analyser library. Hunspell
+-is based on OpenOffice.org's Myspell. Documentation, tests, and examples
+-are available at http://hunspell.sourceforge.net.
+-
+-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://lasr.cs.ucla.edu/geoff/ispell.html (Ispell homepage)
+-
+-An almost complete rewrite of MySpell for use by the Mozilla project was
+-developed by David Einstein. David was a significant help in improving MySpell.
+-
+-Special thanks also goes to László Né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
+-along with rewriting MySpell as Hunspell and ensuring compatibility with the
+-Mozilla codebase.
+Index: mozilla/extensions/spellcheck/hunspell/src/affentry.cpp
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/affentry.cpp
++++ /dev/null
+@@ -1,924 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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; // number of conditions to match
+- opts = dp->opts; // cross product flag
+- // then copy over all of the conditions
+- memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0]));
+- next = NULL;
+- nextne = NULL;
+- nexteq = NULL;
+-#ifdef HUNSPELL_EXPERIMENTAL
+- morphcode = dp->morphcode;
+-#endif
+- 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 & aeUTF8) {
+- for (int i = 0; i < numconds; i++) {
+- if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]);
+- }
+- }
+-#ifdef HUNSPELL_EXPERIMENTAL
+- if (morphcode && !(opts & aeALIASM)) free(morphcode);
+-#endif
+- 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 int PfxEntry::test_condition(const char * st)
+-{
+- int cond;
+- unsigned char * cp = (unsigned char *)st;
+- if (!(opts & aeUTF8)) { // 256-character codepage
+- for (cond = 0; cond < numconds; cond++) {
+- if ((conds.base[*cp++] & (1 << cond)) == 0) return 0;
+- }
+- } else { // UTF-8 encoding
+- unsigned short wc;
+- for (cond = 0; cond < numconds; cond++) {
+- // a simple 7-bit ASCII character in UTF-8
+- if ((*cp >> 7) == 0) {
+- // also check limit (end of word)
+- if ((!*cp) || ((conds.utf8.ascii[*cp++] & (1 << cond)) == 0)) return 0;
+- // UTF-8 multibyte character
+- } else {
+- // not dot wildcard in rule
+- if (!conds.utf8.all[cond]) {
+- if (conds.utf8.neg[cond]) {
+- u8_u16((w_char *) &wc, 1, (char *) cp);
+- if (conds.utf8.wchars[cond] &&
+- flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
+- wc, (short) conds.utf8.wlen[cond])) return 0;
+- } else {
+- if (!conds.utf8.wchars[cond]) return 0;
+- u8_u16((w_char *) &wc, 1, (char *) cp);
+- if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
+- wc, (short)conds.utf8.wlen[cond])) return 0;
+- }
+- }
+- // jump to next UTF-8 character
+- for(cp++; (*cp & 0xc0) == 0x80; cp++);
+- }
+- }
+- }
+- 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)) {
+-
+- // 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 pseudoroot flag
+- ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), 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)) {
+-
+- // 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;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-// 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)) {
+-
+- // 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)) {
+-
+- // 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 pseudoroot flag
+- ! TESTAFF(contclass, pmyMgr->get_pseudoroot(), contclasslen) &&
+- // needflag
+- ((!needflag) || TESTAFF(he->astr, needflag, he->alen) ||
+- (contclass && TESTAFF(contclass, needflag, contclasslen)))) {
+- if (morphcode) strcat(result, morphcode); else strcat(result,getKey());
+- if (he->description) {
+- if ((*(he->description)=='[')||(*(he->description)=='<')) strcat(result,he->word);
+- strcat(result,he->description);
+- }
+- 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;
+-}
+-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+-
+-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; // number of conditions to match
+- opts = dp->opts; // cross product flag
+-
+- // then copy over all of the conditions
+- memcpy(&conds.base[0],&dp->conds.base[0],SETSIZE*sizeof(conds.base[0]));
+-
+- rappnd = myrevstrdup(appnd);
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+- morphcode = dp->morphcode;
+-#endif
+- 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 & aeUTF8) {
+- for (int i = 0; i < numconds; i++) {
+- if (conds.utf8.wchars[i]) free(conds.utf8.wchars[i]);
+- }
+- }
+-#ifdef HUNSPELL_EXPERIMENTAL
+- if (morphcode && !(opts & aeALIASM)) free(morphcode);
+-#endif
+- 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 int SfxEntry::test_condition(const char * st, const char * beg)
+-{
+- int cond;
+- unsigned char * cp = (unsigned char *) st;
+- if (!(opts & aeUTF8)) { // 256-character codepage
+- // Domolki affix algorithm
+- for (cond = numconds; --cond >= 0; ) {
+- if ((conds.base[*--cp] & (1 << cond)) == 0) return 0;
+- }
+- } else { // UTF-8 encoding
+- unsigned short wc;
+- for (cond = numconds; --cond >= 0; ) {
+- // go to next character position and check limit
+- if ((char *) --cp < beg) return 0;
+- // a simple 7-bit ASCII character in UTF-8
+- if ((*cp >> 7) == 0) {
+- if ((conds.utf8.ascii[*cp] & (1 << cond)) == 0) return 0;
+- // UTF-8 multibyte character
+- } else {
+- // go to first character of UTF-8 multibyte character
+- for (; (*cp & 0xc0) == 0x80; cp--);
+- // not dot wildcard in rule
+- if (!conds.utf8.all[cond]) {
+- if (conds.utf8.neg[cond]) {
+- u8_u16((w_char *) &wc, 1, (char *) cp);
+- if (conds.utf8.wchars[cond] &&
+- flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
+- wc, (short) conds.utf8.wlen[cond])) return 0;
+- } else {
+- if (!conds.utf8.wchars[cond]) return 0;
+- u8_u16((w_char *) &wc, 1, (char *) cp);
+- if (!flag_bsearch((unsigned short *)conds.utf8.wchars[cond],
+- wc, (short)conds.utf8.wlen[cond])) return 0;
+- }
+- }
+- }
+- }
+- }
+- 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)) {
+-
+- // 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)) {
+-
+- // 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;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-// 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)) {
+-
+- // 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,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;
+-}
+-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+-
+-// 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
+-
+Index: mozilla/extensions/spellcheck/hunspell/src/affentry.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/affentry.hxx
++++ /dev/null
+@@ -1,187 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 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 int test_condition(const char * st, const char * begin);
+-};
+-
+-#endif
+-
+-
+Index: mozilla/extensions/spellcheck/hunspell/src/affixmgr.cpp
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/affixmgr.cpp
++++ /dev/null
+@@ -1,4155 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 = FLAG_NULL; // 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)
+- pseudoroot = 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;
+-
+- 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(pseudoroot);
+- 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 `pseudoroots' */
+- if (strncmp(line,"PSEUDOROOT",10) == 0) {
+- if (parse_flag(line, &pseudoroot, "PSEUDOROOT")) {
+- fclose(afflst);
+- return 1;
+- }
+- }
+-
+- /* parse in the flag used by `pseudoroots' */
+- if (strncmp(line,"NEEDAFFIX",9) == 0) {
+- if (parse_flag(line, &pseudoroot, "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;
+- }
+- }
+-
+- 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;
+-}
+-
+-
+-
+-// takes aff file condition string and creates the
+-// conds array - please see the appendix at the end of the
+-// file affentry.cpp which describes what is going on here
+-// in much more detail
+-
+-int AffixMgr::encodeit(struct affentry * ptr, char * cs)
+-{
+- unsigned char c;
+- int i, j, k;
+- unsigned char mbr[MAXLNLEN];
+- w_char wmbr[MAXLNLEN];
+- w_char * wpos = wmbr;
+-
+- // now clear the conditions array */
+- for (i=0;iconds.base[i] = (unsigned char) 0;
+-
+- // now parse the string to create the conds array */
+- int nc = strlen(cs);
+- unsigned char neg = 0; // complement indicator
+- int grp = 0; // group indicator
+- unsigned char n = 0; // number of conditions
+- int ec = 0; // end condition indicator
+- int nm = 0; // number of member in group
+-
+- // if no condition just return
+- if (strcmp(cs,".")==0) {
+- ptr->numconds = 0;
+- return 0;
+- }
+-
+- i = 0;
+- while (i < nc) {
+- c = *((unsigned char *)(cs + i));
+-
+- // start group indicator
+- if (c == '[') {
+- grp = 1;
+- c = 0;
+- }
+-
+- // complement flag
+- if ((grp == 1) && (c == '^')) {
+- neg = 1;
+- c = 0;
+- }
+-
+- // end goup indicator
+- if (c == ']') {
+- ec = 1;
+- c = 0;
+- }
+-
+- // add character of group to list
+- if ((grp == 1) && (c != 0)) {
+- *(mbr + nm) = c;
+- nm++;
+- c = 0;
+- }
+-
+- // end of condition
+- if (c != 0) {
+- ec = 1;
+- }
+-
+- if (ec) {
+- if (!utf8) {
+- if (grp == 1) {
+- if (neg == 0) {
+- // set the proper bits in the condition array vals for those chars
+- for (j=0;jconds.base[k] = ptr->conds.base[k] | ((unsigned char)1 << n);
+- }
+- } else {
+- // complement so set all of them and then unset indicated ones
+- for (j=0;jconds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n);
+- for (j=0;jconds.base[k] = ptr->conds.base[k] & ~((unsigned char)1 << n);
+- }
+- }
+- neg = 0;
+- grp = 0;
+- nm = 0;
+- } else {
+- // not a group so just set the proper bit for this char
+- // but first handle special case of . inside condition
+- if (c == '.') {
+- // wild card character so set them all
+- for (j=0;jconds.base[j] = ptr->conds.base[j] | ((unsigned char)1 << n);
+- } else {
+- ptr->conds.base[(unsigned int) c] = ptr->conds.base[(unsigned int)c] | ((unsigned char)1 << n);
+- }
+- }
+- n++;
+- ec = 0;
+- } else { // UTF-8 character set
+- if (grp == 1) {
+- ptr->conds.utf8.neg[n] = neg;
+- if (neg == 0) {
+- // set the proper bits in the condition array vals for those chars
+- for (j=0;j> 7) {
+- u8_u16(wpos, 1, (char *) mbr + j);
+- wpos++;
+- if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character
+- } else {
+- ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] | ((unsigned char)1 << n);
+- }
+- }
+- } else { // neg == 1
+- // complement so set all of them and then unset indicated ones
+- for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n);
+- for (j=0;j> 7) {
+- u8_u16(wpos, 1, (char *) mbr + j);
+- wpos++;
+- if ((k & 0xe0) == 0xe0) j+=2; else j++; // 3-byte UTF-8 character
+- } else {
+- ptr->conds.utf8.ascii[k] = ptr->conds.utf8.ascii[k] & ~((unsigned char)1 << n);
+- }
+- }
+- }
+- neg = 0;
+- grp = 0;
+- nm = 0;
+- ptr->conds.utf8.wlen[n] = wpos - wmbr;
+- if ((wpos - wmbr) != 0) {
+- ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char) * (wpos - wmbr));
+- if (!ptr->conds.utf8.wchars[n]) return 1;
+- memcpy(ptr->conds.utf8.wchars[n], wmbr, sizeof(w_char) * (wpos - wmbr));
+- flag_qsort((unsigned short *) ptr->conds.utf8.wchars[n], 0, ptr->conds.utf8.wlen[n]);
+- wpos = wmbr;
+- }
+- } else { // grp == 0
+- // is UTF-8 character?
+- if (c >> 7) {
+- ptr->conds.utf8.wchars[n] = (w_char *) malloc(sizeof(w_char));
+- if (!ptr->conds.utf8.wchars[n]) return 1;
+- ptr->conds.utf8.wlen[n] = 1;
+- u8_u16(ptr->conds.utf8.wchars[n], 1, cs + i);
+- if ((c & 0xe0) == 0xe0) i+=2; else i++; // 3-byte UFT-8 character
+- } else {
+- ptr->conds.utf8.wchars[n] = NULL;
+- // not a group so just set the proper bit for this char
+- // but first handle special case of . inside condition
+- if (c == '.') {
+- ptr->conds.utf8.all[n] = 1;
+- // wild card character so set them all
+- for (j=0;j<(SETSIZE/2);j++) ptr->conds.utf8.ascii[j] = ptr->conds.utf8.ascii[j] | ((unsigned char)1 << n);
+- } else {
+- ptr->conds.utf8.all[n] = 0;
+- ptr->conds.utf8.ascii[(unsigned int) c] = ptr->conds.utf8.ascii[(unsigned int)c] | ((unsigned char)1 << n);
+- }
+- }
+- neg = 0;
+- }
+- n++;
+- ec = 0;
+- neg = 0;
+- }
+- }
+-
+- i++;
+- }
+- ptr->numconds = n;
+- return 0;
+-}
+-
+- // return 1 if s1 is a leading subset of s2
+-/* inline int AffixMgr::isSubset(const char * s1, const char * s2)
+- {
+- while ((*s1 == *s2) && *s1) {
+- s1++;
+- s2++;
+- }
+- return (*s1 == '\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;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-// 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;
+-}
+-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+-
+-
+-// 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 &&
+- ((pseudoroot && TESTAFF(rv->astr, pseudoroot, 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 pseudoroot
+- } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
+- TESTAFF(rv->astr, pseudoroot, 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) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, 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+1word), rv->clen)<=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;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-// 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 &&
+- ((pseudoroot && TESTAFF(rv->astr, pseudoroot, 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 (rv->description) {
+- if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
+- strcat(presult, st);
+- strcat(presult, rv->description);
+- }
+- }
+-
+- 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 ((wordnum == 0) && compoundbegin) {
+- p = affix_check_morph(st, i, compoundbegin);
+- } else if ((wordnum > 0) && compoundmiddle) {
+- p = affix_check_morph(st, i, compoundmiddle);
+- }
+- }
+- if (*p != '\0') {
+- line_uniq(p);
+- if (strchr(p, '\n')) {
+- strcat(presult, "(");
+- strcat(presult, line_join(p, '|'));
+- strcat(presult, ")");
+- } else {
+- strcat(presult, p);
+- }
+- }
+- if (presult[strlen(presult) - 1] == '\n') {
+- presult[strlen(presult) - 1] = '\0';
+- }
+- checked_prefix = 1;
+- //strcat(presult, "+");
+- }
+- // else check forbiddenwords
+- } else if (rv->astr && (TESTAFF(rv->astr, forbiddenword, rv->alen) ||
+- TESTAFF(rv->astr, pseudoroot, 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) && ((pseudoroot && TESTAFF(rv->astr, pseudoroot, 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);
+- if (complexprefixes && rv->description) strcat(*result, rv->description);
+- if (rv->description && ((!rv->astr) ||
+- !TESTAFF(rv->astr, lemma_present, rv->alen)))
+- strcat(*result, &(rv->word));
+- if (!complexprefixes && rv->description) strcat(*result, rv->description);
+- 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+1word),rv->wlen)<=cpdmaxsyllable))
+- )
+- && (
+- (!checkcompounddup || (rv != rv_first))
+- )
+- )
+- {
+- // bad compound word
+- strcat(*result, presult);
+-
+- if (rv->description) {
+- if (complexprefixes) strcat(*result, rv->description);
+- if ((!rv->astr) || !TESTAFF(rv->astr, lemma_present, rv->alen))
+- strcat(*result, &(rv->word));
+- if (!complexprefixes) strcat(*result, rv->description);
+- }
+- 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)
+- m = affix_check_morph((word+i),strlen(word+i), compoundend);
+- strcat(*result, presult);
+- if (m) {
+- line_uniq(m);
+- if (strchr(m, '\n')) {
+- strcat(*result, "(");
+- strcat(*result, line_join(m, '|'));
+- strcat(*result, ")");
+- } else {
+- strcat(*result, 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, pseudoroot, 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()))))) &&
+- // pseudoroot on prefix or first suffix
+- (cclass ||
+- !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) ||
+- (ppfx && !((ep->getCont()) &&
+- TESTAFF(ep->getCont(), pseudoroot,
+- 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()))))) &&
+- // pseudoroot on prefix or first suffix
+- (cclass ||
+- !(sptr->getCont() && TESTAFF(sptr->getCont(), pseudoroot, sptr->getContLen())) ||
+- (ppfx && !((ep->getCont()) &&
+- TESTAFF(ep->getCont(), pseudoroot,
+- 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 {
+- strcpy(result, derived); // XXX check size
+- strcat(result, "\n");
+- strcat(result, word);
+- 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;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-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, st);
+- free(st);
+- if (se->getMorph()) 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, 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()))))) &&
+- // pseudoroot on prefix or first suffix
+- (cclass ||
+- !(se->getCont() && TESTAFF(se->getCont(), pseudoroot, se->getContLen())) ||
+- (ppfx && !((ep->getCont()) &&
+- TESTAFF(ep->getCont(), pseudoroot,
+- 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());
+- }
+- if (complexprefixes && rv->description) strcat(result, rv->description);
+- if (rv->description && ((!rv->astr) ||
+- !TESTAFF(rv->astr, lemma_present, rv->alen)))
+- strcat(result, &(rv->word));
+- if (!complexprefixes && rv->description) strcat(result, rv->description);
+- if (se->getMorph()) 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()))))) &&
+- // pseudoroot on first suffix
+- (cclass || !(sptr->getCont() &&
+- TESTAFF(sptr->getCont(), pseudoroot, 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());
+- }
+- if (complexprefixes && rv->description) strcat(result, rv->description);
+- if (rv->description && ((!rv->astr) ||
+- !TESTAFF(rv->astr, lemma_present, rv->alen))) strcat(result, &(rv->word));
+- if (!complexprefixes && rv->description) strcat(result, rv->description);
+-#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, 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;
+-}
+-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+-
+-
+-// 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;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-// 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);
+-}
+-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+-
+-
+-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 && ((pseudoroot && TESTAFF(ap, pseudoroot, 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 pseudoroot flag
+- !(sptr->getCont() && ((pseudoroot &&
+- TESTAFF(sptr->getCont(), pseudoroot, 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 pseudoroot flag
+- !(ptr->getCont() && ((pseudoroot &&
+- TESTAFF(ptr->getCont(), pseudoroot, 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_pseudoroot()
+-{
+- return pseudoroot;
+-}
+-
+-// 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) {
+- 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;
+-}
+-
+-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;
+-#ifdef HUNSPELL_EXPERIMENTAL
+- if (pHMgr->is_aliasm()) ptr->opts += aeALIASM;
+-#endif
+- 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;
+- 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;
+-#ifdef HUNSPELL_EXPERIMENTAL
+- nptr->morphcode = NULL;
+-#endif
+- 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) {
+- int neg = 0;
+- if (utf8) reverseword_utf(piece); else reverseword(piece);
+- // reverse condition
+- 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;
+- }
+- }
+- }
+- }
+- if (nptr->stripl && (strcmp(piece, ".") != 0) &&
+- redundant_condition(at, nptr->strip, nptr->stripl, piece, nl))
+- strcpy(piece, ".");
+- if (encodeit(nptr,piece)) return 1;
+- break;
+- }
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+- case 5: {
+- np++;
+- if (pHMgr->is_aliasm()) {
+- int index = atoi(piece);
+- nptr->morphcode = pHMgr->get_aliasm(index);
+- } else {
+- if (complexprefixes) {
+- if (utf8) reverseword_utf(piece); else reverseword(piece);
+- }
+- nptr->morphcode = mystrdup(piece);
+- }
+- break;
+- }
+-#endif
+-
+- 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
+-#ifdef HUNSPELL_EXPERIMENTAL
+- // 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
+-#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;
+-}
+Index: mozilla/extensions/spellcheck/hunspell/src/affixmgr.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/affixmgr.hxx
++++ /dev/null
+@@ -1,272 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 pseudoroot;
+- 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;
+- 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);
+-
+- 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_pseudoroot();
+- 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_string(char * line, char ** out, const char * name);
+- int parse_flag(char * line, unsigned short * out, const char * name);
+- int parse_num(char * line, int * out, const char * name);
+-// int parse_array(char * line, char ** out, unsigned short ** out_utf16,
+-// int * out_utf16_len, 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);
+-
+- 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
+-
+Index: mozilla/extensions/spellcheck/hunspell/src/atypes.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/atypes.hxx
++++ /dev/null
+@@ -1,154 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 aeINFIX (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 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;
+- union {
+- char base[SETSIZE];
+- struct {
+- char ascii[SETSIZE/2];
+- char neg[8];
+- char all[8];
+- w_char * wchars[8];
+- int wlen[8];
+- } utf8;
+- } conds;
+-#ifdef HUNSPELL_EXPERIMENTAL
+- char * morphcode;
+-#endif
+- unsigned short * contclass;
+- short contclasslen;
+-};
+-
+-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
+-
+-
+-
+-
+-
+Index: mozilla/extensions/spellcheck/hunspell/src/baseaffix.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/baseaffix.hxx
++++ /dev/null
+@@ -1,87 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 base[SETSIZE];
+- struct {
+- char ascii[SETSIZE/2];
+- char neg[8];
+- char all[8];
+- w_char * wchars[8];
+- int wlen[8];
+- } utf8;
+- } conds;
+- char * morphcode;
+- unsigned short * contclass;
+- short contclasslen;
+-};
+-
+-#endif
+Index: mozilla/extensions/spellcheck/hunspell/src/csutil.cpp
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/csutil.cpp
++++ /dev/null
+@@ -1,5400 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 %d. character position\n%s\n", 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 %d. character position:\n%s\n", 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 %d. character position:\n%s\n", u8 - src, src);
+- u2->h = 0xff;
+- u2->l = 0xfd;
+- }
+- } else {
+- HUNSPELL_WARNING(stderr, "UTF-8 encoding error. Missing continuation byte in %d. character position:\n%s\n", 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 * rv = NULL;
+- char * mp = *stringp;
+- int n = strlen(mp);
+- if (n > 0) {
+- char * dp;
+- if (delim) {
+- dp = (char *)memchr(mp,(int)((unsigned char)delim),n);
+- } 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);
+- 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 * 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;
+- }
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+- // 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);
+- }
+-
+-// break text to lines
+-// return number of lines
+-int line_tok(const char * text, char *** lines) {
+- int linenum = 0;
+- char * dup = mystrdup(text);
+- char * p = strchr(dup, '\n');
+- while (p) {
+- linenum++;
+- *p = '\0';
+- p++;
+- p = strchr(p, '\n');
+- }
+- *lines = (char **) calloc(linenum + 1, sizeof(char *));
+- if (!(*lines)) return -1;
+-
+- p = dup;
+- for (int i = 0; i < linenum + 1; i++) {
+- (*lines)[i] = mystrdup(p);
+- p += strlen(p) + 1;
+- }
+- free(dup);
+- return linenum;
+-}
+-
+-// uniq line in place
+-char * line_uniq(char * text) {
+- char ** lines;
+- int linenum = line_tok(text, &lines);
+- 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')) strcat(text, "\n");
+- strcat(text, lines[i]);
+- }
+- }
+- for ( i = 0; i<=linenum; i++ ) {
+- if (lines[i]) free(lines[i]);
+- }
+- if (lines) free(lines);
+- return text;
+-}
+-
+-// change \n to char c
+-char * line_join(char * text, char c) {
+- char * p;
+- for (p = text; *p; p++) if (*p == '\n') *p = c;
+- return text;
+-}
+-
+-// leave only last {[^}]*} substring for handling zero morphemes
+-char * delete_zeros(char * morphout) {
+- char * p = morphout;
+- char * q = p;
+- char * q2 = NULL;
+- int suffix = 0;
+-
+- for (;*p && *(p+1);) {
+- switch (*p) {
+- case '{':
+- q2 = q;
+- q--;
+- break;
+- case '}':
+- if (q2) {
+- suffix = 1;
+- q--;
+- }
+- break;
+- default:
+- if (suffix) {
+- q = q2;
+- }
+- suffix = 0;
+- *q = *p;
+- }
+- p++;
+- q++;
+- }
+- *q = '\0';
+- return morphout;
+-}
+-#endif // END OF HUNSPELL_EXPERIMENTAL CODE
+-
+-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;
+- }
+-
+- // 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;
+-}
+Index: mozilla/extensions/spellcheck/hunspell/src/csutil.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/csutil.hxx
++++ /dev/null
+@@ -1,233 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 FIELD_STEM "st:"
+-#define FIELD_POS "po:"
+-#define FIELD_SUFF "su:"
+-#define FIELD_PREF "pr:"
+-#define FIELD_FREQ "fr:"
+-#define FIELD_PHON "ph:"
+-#define FIELD_HYPH "hy:"
+-#define FIELD_COMP "co:"
+-
+-// default flags
+-#define ONLYUPCASEFLAG 65535
+-
+-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);
+-
+-// tokenize into lines with new line and uniq in place
+- char * line_uniq(char * text);
+-
+-// change \n to c in place
+- char * line_join(char * text, char c);
+-
+-// leave only last {[^}]*} pattern in string
+- char * delete_zeros(char * morphout);
+-
+-// reverse word
+- int reverseword(char *);
+-
+-// reverse word
+- int reverseword_utf(char *);
+-
+-// 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);
+-
+-#endif
+Index: mozilla/extensions/spellcheck/hunspell/src/hashmgr.cpp
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/hashmgr.cpp
++++ /dev/null
+@@ -1,941 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 = FLAG_NULL; // 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;
+-/* if (pt) {
+- if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr);
+-#ifdef HUNSPELL_EXPERIMENTAL
+- if (pt->description && !aliasm) free(pt->description);
+-#endif
+- pt = pt->next;
+- }
+-*/
+- while(pt) {
+- nt = pt->next;
+- if (pt->astr && (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) free(pt->astr);
+-#ifdef HUNSPELL_EXPERIMENTAL
+- if (pt->description && !aliasm) free(pt->description);
+-#endif
+- 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) ? strlen(desc) : 0;
+- // variable-length hash record with word and optional fields
+- // instead of mmap implementation temporarily
+- struct hentry* hp =
+- (struct hentry *) malloc (sizeof(struct hentry) + wbl + descl + 1);
+- if (!hp) return 1;
+- char * hpw = &(hp->word);
+- strcpy(hpw, word);
+- if (desc && strncmp(desc, FIELD_PHON, strlen(FIELD_PHON)) == 0) {
+- strcpy(hpw + wbl + 1, desc + strlen(FIELD_PHON));
+- hp->var = 1;
+- } else {
+- hp->var = 0;
+- }
+- 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;
+-#ifdef HUNSPELL_EXPERIMENTAL
+- if (aliasm) {
+- hp->description = (desc) ? get_aliasm(atoi(desc)) : mystrdup(desc);
+- } else {
+- hp->description = mystrdup(desc);
+- if (desc && !hp->description)
+- {
+- free(hp->astr);
+- free(hp);
+- return 1;
+- }
+- if (hp->description && complexprefixes) {
+- if (utf8) reverseword_utf(hp->description); else reverseword(hp->description);
+- }
+- }
+-#endif
+-
+- 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;
+-}
+-
+-// add a custom dic. word to the hash table (public)
+-int HashMgr::put_word(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::put_word_pattern(const char * word, const char * pattern)
+-{
+- // detect captype and modify word length for UTF-8 encoding
+- struct hentry * dp = lookup(pattern);
+- 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;
+- }
+- }
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+- if ((strncmp(line,"AM",2) == 0) && isspace(line[2])) {
+- if (parse_aliasm(line, afflst)) {
+- fclose(afflst);
+- return 1;
+- }
+- }
+-#endif
+- 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;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-/* 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, 0);
+- 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: {
+- if (complexprefixes) {
+- if (utf8) reverseword_utf(piece);
+- else reverseword(piece);
+- }
+- aliasm[j] = mystrdup(piece);
+- break; }
+- default: break;
+- }
+- i++;
+- }
+- free(piece);
+- piece = mystrsep(&tp, 0);
+- }
+- 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;
+-}
+-#endif
+Index: mozilla/extensions/spellcheck/hunspell/src/hashmgr.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/hashmgr.hxx
++++ /dev/null
+@@ -1,129 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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 put_word(const char * word, char * ap);
+- int put_word_pattern(const char * word, const char * pattern);
+- 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);
+-#ifdef HUNSPELL_EXPERIMENTAL
+- int is_aliasm();
+- char * get_aliasm(int index);
+-#endif
+-
+-
+-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);
+-#ifdef HUNSPELL_EXPERIMENTAL
+- int parse_aliasm(char * line, FILE * af);
+-#endif
+-
+-};
+-
+-#endif
+Index: mozilla/extensions/spellcheck/hunspell/src/htypes.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/htypes.hxx
++++ /dev/null
+@@ -1,85 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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));
+-
+-// 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)
+-#ifdef HUNSPELL_EXPERIMENTAL
+- char * description; // morphological data (optional)
+-#endif
+- char var; // variable fields (only for special pronounciation yet)
+- char word; // variable-length word (8-bit or UTF-8 encoding)
+-};
+-
+-#endif
+Index: mozilla/extensions/spellcheck/hunspell/src/hunspell.cpp
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/hunspell.cpp
++++ /dev/null
+@@ -1,1807 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#ifndef MOZILLA_CLIENT
+-#include
+-#include
+-#include
+-#else
+-#include
+-#include
+-#include
+-#endif
+-
+-#include "hunspell.hxx"
+-#include "hunspell.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;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-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);
+-}
+-#endif
+-
+-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 pseudoroot, onlyincompound homonym or onlyupcase word
+- while (he && (he->astr) &&
+- ((pAMgr->get_pseudoroot() && TESTAFF(he->astr, pAMgr->get_pseudoroot(), 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;
+-}
+-
+-// XXX need UTF-8 support
+-int Hunspell::stem(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 HUHCAP:
+- case NOCAP: {
+- ns = pSMgr->suggest_stems(slst, cw, ns);
+-
+- if ((abbv) && (ns == 0)) {
+- memcpy(wspace,cw,wl);
+- *(wspace+wl) = '.';
+- *(wspace+wl+1) = '\0';
+- ns = pSMgr->suggest_stems(slst, wspace, ns);
+- }
+-
+- break;
+- }
+-
+- case INITCAP: {
+-
+- ns = pSMgr->suggest_stems(slst, cw, ns);
+-
+- if (ns == 0) {
+- memcpy(wspace,cw,(wl+1));
+- mkallsmall(wspace);
+- ns = pSMgr->suggest_stems(slst, wspace, ns);
+-
+- }
+-
+- if ((abbv) && (ns == 0)) {
+- memcpy(wspace,cw,wl);
+- mkallsmall(wspace);
+- *(wspace+wl) = '.';
+- *(wspace+wl+1) = '\0';
+- ns = pSMgr->suggest_stems(slst, wspace, ns);
+- }
+-
+- break;
+-
+- }
+-
+- case ALLCAP: {
+- ns = pSMgr->suggest_stems(slst, cw, ns);
+- if (ns != 0) break;
+-
+- memcpy(wspace,cw,(wl+1));
+- mkallsmall(wspace);
+- ns = pSMgr->suggest_stems(slst, wspace, ns);
+-
+- if (ns == 0) {
+- mkinitcap(wspace);
+- ns = pSMgr->suggest_stems(slst, wspace, ns);
+- }
+-
+- if ((abbv) && (ns == 0)) {
+- memcpy(wspace,cw,wl);
+- mkallsmall(wspace);
+- *(wspace+wl) = '.';
+- *(wspace+wl+1) = '\0';
+- ns = pSMgr->suggest_stems(slst, wspace, ns);
+- }
+-
+-
+- break;
+- }
+- }
+-
+- return ns;
+-}
+-
+-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::put_word(const char * word)
+-{
+- if (pHMgr) return pHMgr->put_word(word, NULL);
+- return 0;
+-}
+-
+-int Hunspell::put_word_pattern(const char * word, const char * pattern)
+-{
+- if (pHMgr) return pHMgr->put_word_pattern(word, pattern);
+- return 0;
+-}
+-
+-const char * Hunspell::get_version()
+-{
+- return pAMgr->get_version();
+-}
+-
+-struct cs_info * Hunspell::get_csconv()
+-{
+- return csconv;
+-}
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+-// XXX need UTF-8 support
+-char * Hunspell::morph(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 NULL;
+- 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) {
+- st = pSMgr->suggest_morph(cw + n - 1);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+- } else {
+- char sign = cw[n];
+- cw[n] = '\0';
+- st = pSMgr->suggest_morph(cw + n - 1);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+- strcat(result, "+"); // XXX SPEC. MORPHCODE
+- cw[n] = sign;
+- st = pSMgr->suggest_morph(cw + n);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+- }
+- return mystrdup(result);
+- }
+- }
+- // END OF LANG_hu section
+-
+- switch(captype) {
+- case NOCAP: {
+- st = pSMgr->suggest_morph(cw);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+- if (abbv) {
+- memcpy(wspace,cw,wl);
+- *(wspace+wl) = '.';
+- *(wspace+wl+1) = '\0';
+- st = pSMgr->suggest_morph(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(wspace);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+- st = pSMgr->suggest_morph(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(wspace);
+- if (st) {
+- if (*result) strcat(result, "\n");
+- strcat(result, st);
+- free(st);
+- }
+- mkinitcap(wspace);
+- st = pSMgr->suggest_morph(wspace);
+- if (st) {
+- if (*result) strcat(result, "\n");
+- strcat(result, st);
+- free(st);
+- }
+- }
+- break;
+- }
+- case HUHCAP: {
+- st = pSMgr->suggest_morph(cw);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+-#if 0
+- memcpy(wspace,cw,(wl+1));
+- mkallsmall(wspace);
+- st = pSMgr->suggest_morph(wspace);
+- if (st) {
+- if (*result) strcat(result, "\n");
+- strcat(result, st);
+- free(st);
+- }
+-#endif
+- break;
+- }
+- case ALLCAP: {
+- memcpy(wspace,cw,(wl+1));
+- st = pSMgr->suggest_morph(wspace);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+- mkallsmall(wspace);
+- st = pSMgr->suggest_morph(wspace);
+- if (st) {
+- if (*result) strcat(result, "\n");
+- strcat(result, st);
+- free(st);
+- }
+- mkinitcap(wspace);
+- st = pSMgr->suggest_morph(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(wspace);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+- mkallsmall(wspace);
+- st = pSMgr->suggest_morph(wspace);
+- if (st) {
+- if (*result) strcat(result, "\n");
+- strcat(result, st);
+- free(st);
+- }
+- mkinitcap(wspace);
+- st = pSMgr->suggest_morph(wspace);
+- if (st) {
+- if (*result) strcat(result, "\n");
+- strcat(result, st);
+- free(st);
+- }
+- }
+- break;
+- }
+- }
+-
+- if (result && (*result)) {
+- // word reversing wrapper for complex prefixes
+- if (complexprefixes) {
+- if (utf8) reverseword_utf(result); else reverseword(result);
+- }
+- return mystrdup(result);
+- }
+-
+- // 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 pSMgr->suggest_morph(cw);
+- } 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 mystrdup(result);
+- }
+- } 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 = morph(cw);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- strcat(result,"+"); // XXX spec. separator in MORPHCODE
+- }
+- st = morph(dash+1);
+- if (st) {
+- strcat(result, st);
+- free(st);
+- }
+- return mystrdup(result);
+- }
+- }
+- // 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 mystrdup(result);
+- }
+- }
+- }
+- }
+- return NULL;
+-}
+-
+-// XXX need UTF-8 support
+-char * Hunspell::morph_with_correction(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;
+-
+- 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;
+-}
+-
+-/* analyze word
+- * return line count
+- * XXX need a better data structure for morphological analysis */
+-int Hunspell::analyze(char ***out, const char *word) {
+- int n = 0;
+- if (!word) return 0;
+- char * m = morph(word);
+- if(!m) return 0;
+- if (!out)
+- {
+- n = line_tok(m, out);
+- free(m);
+- return n;
+- }
+-
+- // without memory allocation
+- /* BUG missing buffer size checking */
+- int i, p;
+- for(p = 0, i = 0; m[i]; i++) {
+- if(m[i] == '\n' || !m[i+1]) {
+- n++;
+- strncpy((*out)[n++], m + p, i - p + 1);
+- if (m[i] == '\n') (*out)[n++][i - p] = '\0';
+- if(!m[i+1]) break;
+- p = i + 1;
+- }
+- }
+- free(m);
+- return n;
+-}
+-
+-#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);
+-}
+Index: mozilla/extensions/spellcheck/hunspell/src/hunspell.h
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/hunspell.h
++++ /dev/null
+@@ -1,89 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif
+Index: mozilla/extensions/spellcheck/hunspell/src/hunspell.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/hunspell.hxx
++++ /dev/null
+@@ -1,195 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 "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();
+-
+- /* handling custom dictionary */
+-
+- int put_word(const char * word);
+-
+- /* pattern is a sample dictionary word
+- * put word into custom dictionary with affix flags of pattern word
+- */
+-
+- int put_word_pattern(const char * word, const char * pattern);
+-
+- /* 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 functions */
+-
+-#ifdef HUNSPELL_EXPERIMENTAL
+- /* suffix is an affix flag string, similarly in dictionary files */
+-
+- int put_word_suffix(const char * word, const char * suffix);
+-
+- /* morphological analysis */
+-
+- char * morph(const char * word);
+- int analyze(char*** out, const char *word);
+-
+- char * morph_with_correction(const char * word);
+-
+- /* stemmer function */
+-
+- int stem(char*** slst, 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);
+-
+-};
+-
+-#endif
+Index: mozilla/extensions/spellcheck/hunspell/src/langnum.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/langnum.hxx
++++ /dev/null
+@@ -1,94 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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
+Index: mozilla/extensions/spellcheck/hunspell/src/phonet.cpp
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/phonet.cpp
++++ /dev/null
+@@ -1,310 +0,0 @@
+-/******* 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 Initial Developer of the Original Code is Björn Jacke. Portions created
+- * by the Initial Developers are Copyright (C) 2000-2007 the Initial
+- * Developers. All Rights Reserved.
+- *
+- * Contributor(s): Björn Jacke (bjoern.jacke@gmx.de)
+- * László Németh (nemethl@gyorsposta.hu)
+- *
+- * 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.
+- *
+- * Changelog:
+- * 2000-01-05 Björn Jacke
+- * Initial Release insprired by the article about phonetic
+- * transformations out of c't 25/1999
+- *
+- * 2007-07-26 Björn Jacke
+- * Released under MPL/GPL/LGPL tri-license for Hunspell
+- *
+- * 2007-08-23 László Németh
+- * Porting from Aspell to Hunspell using C-like structs
+- *
+- ******* END LICENSE BLOCK *******/
+-
+-#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" **/
+Index: mozilla/extensions/spellcheck/hunspell/src/phonet.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/phonet.hxx
++++ /dev/null
+@@ -1,66 +0,0 @@
+-/******* 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 Initial Developer of the Original Code is Björn Jacke. Portions created
+- * by the Initial Developers are Copyright (C) 2000-2007 the Initial
+- * Developers. All Rights Reserved.
+- *
+- * Contributor(s): Björn Jacke (bjoern.jacke@gmx.de)
+- * László Németh (nemethl@gyorsposta.hu)
+- *
+- * 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.
+- *
+- * Changelog:
+- * 2000-01-05 Björn Jacke
+- * Initial Release insprired by the article about phonetic
+- * transformations out of c't 25/1999
+- *
+- * 2007-07-20 Björn Jacke
+- * Released under MPL/GPL/LGPL tri-license for Hunspell
+- *
+- * 2007-08-22 László Németh
+- * Porting from Aspell to Hunspell by little modifications
+- *
+- ******* END LICENSE BLOCK *******/
+-
+-#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
+Index: mozilla/extensions/spellcheck/hunspell/src/suggestmgr.cpp
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/suggestmgr.cpp
++++ /dev/null
+@@ -1,2036 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#ifndef MOZILLA_CLIENT
+-#include
+-#include
+-#include
+-#include
+-#else
+-#include
+-#include
+-#include
+-#include
+-#endif
+-
+-#include "suggestmgr.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; else *
+-
+- // 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 * 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);
+-// fprintf(stderr, "Tip: %s->%s\n", candidate, target);
+- }
+-
+- 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, &(hp->word), NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
+- leftcommonsubstring(word, &(hp->word));
+-
+- // check special pronounciation
+- if (hp->var) {
+- int sc2 = ngram(3, word, &(hp->word) + hp->blen + 1, NGRAM_LONGER_WORSE + NGRAM_LOWERING) +
+- leftcommonsubstring(word, &(hp->word) + hp->blen + 1);
+- if (sc2 > sc) sc = sc2;
+- }
+-
+- if (ph && (sc > 2) && (abs(n - (int) hp->clen) <= 3)) {
+- char target2[MAXSWUTF8L];
+- strcpy(candidate, &(hp->word));
+- 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] = &(hp->word);
+- 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, &(rp->word), rp->blen,
+- rp->astr, rp->alen, word, nc,
+- ((rp->var) ? &(rp->word) + rp->blen + 1 : 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_pseudoroot(),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_pseudoroot(),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 stems, XXX experimental code
+-int SuggestMgr::suggest_stems(char*** slst, const char * w, int nsug)
+-{
+- char buf[MAXSWUTF8L];
+- char ** wlst;
+- int prevnsug = nsug;
+-
+- 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 **) calloc(maxSug, sizeof(char *));
+- if (wlst == NULL) return -1;
+- }
+- // perhaps there are a fix stem in the dictionary
+- if ((nsug < maxSug) && (nsug > -1)) {
+-
+- nsug = fixstems(wlst, word, nsug);
+- if (nsug == prevnsug) {
+- char * s = mystrdup(word);
+- char * p = s + strlen(s);
+- while ((*p != '-') && (p != s)) p--;
+- if (*p == '-') {
+- *p = '\0';
+- nsug = fixstems(wlst, s, nsug);
+- if ((nsug == prevnsug) && (nsug < maxSug) && (nsug >= 0)) {
+- char * t;
+- buf[0] = '\0';
+- for (t = s; (t[0] != '\0') && ((t[0] >= '0') || (t[0] <= '9')); t++); // is a number?
+- if (*t != '\0') strcpy(buf, "# ");
+- strcat(buf, s);
+- wlst[nsug] = mystrdup(buf);
+- if (wlst[nsug] == NULL) return -1;
+- nsug++;
+- }
+- p++;
+- nsug = fixstems(wlst, p, nsug);
+- }
+-
+- free(s);
+- }
+- }
+-
+- if (nsug < 0) {
+- for (int i=0;ilookup(word);
+- if (rv) {
+- dicstem = 0;
+- } else {
+- // try stripping off affixes
+- rv = pAMgr->affix_check(word, wl);
+-
+- // else try check compound word
+- if (!rv && pAMgr->get_compound()) {
+- rv = pAMgr->compound_check(word, wl,
+- 0, 0, 100, 0, NULL, 0, &cmpdstemnum, cmpdstem,1);
+-
+- if (rv) {
+- dicstem = 2;
+- for (int j = 0; j < cmpdstemnum; j++) {
+- cpdindex += cmpdstem[j];
+- }
+- if(! (pAMgr->lookup(word + cpdindex)))
+- pAMgr->affix_check(word + cpdindex, wl - cpdindex); // for prefix
+- }
+- }
+-
+-
+- if (pAMgr->get_prefix()) {
+- strcpy(prefix, pAMgr->get_prefix());
+- }
+-
+- // XXX obsolete, will be a general solution for stemming
+- if ((prefix) && (strncmp(prefix, "leg", 3)==0)) prefix[0] = '\0'; // (HU)
+- }
+-
+- }
+-
+-
+-
+- if ((rv) && (ns < maxSug)) {
+-
+- // check fixstem flag and not_valid_stem flag
+- // first word
+- if ((ns < maxSug) && (dicstem < 2)) {
+- strcpy(buf, prefix);
+- if ((dicstem > 0) && pAMgr->get_derived()) {
+- // XXX obsolote
+- if (strlen(prefix) == 1) {
+- strcat(buf, (pAMgr->get_derived()) + 1);
+- } else {
+- strcat(buf, pAMgr->get_derived());
+- }
+- } else {
+- // special stem in affix description
+- const char * wordchars = pAMgr->get_wordchars();
+- if (rv->description &&
+- (strchr(wordchars, *(rv->description)))) {
+- char * desc = (rv->description) + 1;
+- while (strchr(wordchars, *desc)) desc++;
+- strncat(buf, rv->description, desc - (rv->description));
+- } else {
+- strcat(buf, rv->word);
+- }
+- }
+- wlst[ns] = mystrdup(buf);
+- if (wlst[ns] == NULL) return -1;
+- ns++;
+- }
+-
+- if (dicstem == 2) {
+-
+- // compound stem
+-
+-// if (rv->astr && (strchr(rv->astr, '0') == NULL)) {
+- if (rv->astr) {
+- strcpy(buf, word);
+- buf[cpdindex] = '\0';
+- if (prefix) strcat(buf, prefix);
+- if (pAMgr->get_derived()) {
+- strcat(buf, pAMgr->get_derived());
+- } else {
+- // special stem in affix description
+- const char * wordchars = pAMgr->get_wordchars();
+- if (rv->description &&
+- (strchr(wordchars, *(rv->description)))) {
+- char * desc = (rv->description) + 1;
+- while (strchr(wordchars, *desc)) desc++;
+- strncat(buf, rv->description, desc - (rv->description));
+- } else {
+- strcat(buf, rv->word);
+- }
+- }
+- if (ns < maxSug) {
+- wlst[ns] = mystrdup(buf);
+- if (wlst[ns] == NULL) return -1;
+- ns++;
+- }
+- }
+- }
+- }
+- return ns;
+-}
+-
+-// 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;
+-}
+-
+-
+-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_pseudoroot(), rv->alen) ||
+- TESTAFF(rv->astr,pAMgr->get_onlyincompound(),rv->alen))) {
+- if (rv->description && ((!rv->astr) ||
+- !TESTAFF(rv->astr, pAMgr->get_lemma_present(), rv->alen)))
+- strcat(result, word);
+- if (rv->description) strcat(result, rv->description);
+- 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(delete_zeros(result))) : NULL;
+-}
+-
+-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);
+- 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
+-
+-
+-// 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;
+-}
+Index: mozilla/extensions/spellcheck/hunspell/src/suggestmgr.hxx
+===================================================================
+--- mozilla.orig/extensions/spellcheck/hunspell/src/suggestmgr.hxx
++++ /dev/null
+@@ -1,160 +0,0 @@
+-/******* 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
+- * and László Németh (Hunspell). Portions created by the Initial Developers
+- * are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
+- *
+- * Contributor(s): Kevin Hendricks (kevin.hendricks@sympatico.ca)
+- * David Einstein (deinst@world.std.com)
+- * László Németh (nemethl@gyorsposta.hu)
+- * 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 *******/
+-
+-#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_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);
+-
+-};
+-
+-#endif
+Index: mozilla/extensions/spellcheck/src/Makefile.in
+===================================================================
+--- mozilla.orig/extensions/spellcheck/src/Makefile.in
++++ mozilla/extensions/spellcheck/src/Makefile.in
+@@ -77,16 +77,22 @@
+ $(NULL)
+
+ ifeq (camino,$(MOZ_BUILD_APP))
+ SHARED_LIBRARY_LIBS += ../osxspell/src/$(LIB_PREFIX)osxspell_s.$(LIB_SUFFIX)
+ LOCAL_INCLUDES += -I$(srcdir)/../osxspell/src
+ else
+ SHARED_LIBRARY_LIBS += ../hunspell/src/$(LIB_PREFIX)hunspell_s.$(LIB_SUFFIX)
+ LOCAL_INCLUDES += -I$(srcdir)/../hunspell/src
++ifndef MOZ_NATIVE_HUNSPELL
++LOCAL_INCLUDES += -I$(srcdir)/../hunspell/hunspell
++SHARED_LIBRARY_LIBS += ../hunspell/hunspell/$(LIB_PREFIX)libhunspell_s.$(LIB_SUFFIX)
++else
++LOCAL_INCLUDES += $(MOZ_HUNSPELL_CFLAGS)
++endif
+ endif
+
+ EXTRA_DSO_LDOPTS = \
+ $(LIBS_DIR) \
+ $(MOZ_COMPONENT_LIBS) \
+ $(MOZ_UNICHARUTIL_LIBS) \
+ $(MOZ_HUNSPELL_LIBS) \
+ $(NULL)
+Index: mozilla/extensions/spellcheck/hunspell/hunspell/Makefile.in
+===================================================================
+--- /dev/null
++++ mozilla/extensions/spellcheck/hunspell/hunspell/Makefile.in
+@@ -0,0 +1,66 @@
++# ****** 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 Initial Developers of the Original Code are Kevin Hendricks (MySpell)
++# and László Németh (Hunspell). Portions created by the Initial Developers
++# are Copyright (C) 2002-2005 the Initial Developers. All Rights Reserved.
++#
++# Contributor(s): David Einstein (deinst@world.std.com)
++# László Németh (nemethl@gyorsposta.hu)
++# Ryan VanderMeulen (ryanvm@gmail.com)
++#
++# 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 ******
++
++DEPTH = ../../../..
++topsrcdir = @top_srcdir@
++srcdir = @srcdir@
++VPATH = @srcdir@
++
++include $(DEPTH)/config/autoconf.mk
++
++MODULE = hunspell
++LIBRARY_NAME = libhunspell_s
++FORCE_STATIC_LIB = 1
++LIBXUL_LIBRARY = 1
++
++REQUIRES = xpcom \
++ string \
++ uconv \
++ unicharutil \
++ spellchecker \
++ xulapp \
++ $(NULL)
++
++CPPSRCS += affentry.cpp \
++ affixmgr.cpp \
++ csutil.cpp \
++ hashmgr.cpp \
++ hunspell.cpp \
++ phonet.cpp \
++ suggestmgr.cpp \
++ $(NULL)
++
++include $(topsrcdir)/config/rules.mk
++
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/series
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/series
@@ -0,0 +1,23 @@
+installer_use_stdout_for_missing_files.patch
+dont_install_so_in_dev.patch
+rename_venkman_addon.patch
+protect_tests_by_ifdefs.patch
+dom_inspector_support_for_prism.patch
+bzXXX_pc_honour_system_nspr_nss.patch
+bzXXX_no_zlib_export_if_native.patch
+bzXXX_gre_extension_plugin_support.patch
+bz233371_att297343_fix_outofscreen_embed_tooltip.patch
+bzXXX_attXXX_fix_remember_password_for_embedders_without_branding.patch
+bz394103_dont_scale_images.patch
+#bz394103_scale_images_for_192+dpi.patch
+#drop_bz418016.patch
+#bzr423334_att310581_leak_initparser.patch
+add_syspref_dir.patch
+bzXXX_autoconfig_in_gre.patch
+bzXXX_gre_autoreg.patch
+bzXXX-dont-reset-user-prefs-on-upgrade.patch
+#bz321315_gconf_backend_for_19.patch
+bzXXX_urlclassifier_prefs_in_toolkit.patch
+bz368428_attachment_308130.patch
+bz421482_att320806_synchronous_NORMAL_for_storage_connections.patch
+bz429747_att317495+move_hunspell_1.2.patch
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/installer_use_stdout_for_missing_files.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/installer_use_stdout_for_missing_files.patch
@@ -0,0 +1,27 @@
+---
+ xpinstall/packager/Packager.pm | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+Index: mozilla/xpinstall/packager/Packager.pm
+===================================================================
+--- mozilla.orig/xpinstall/packager/Packager.pm
++++ mozilla/xpinstall/packager/Packager.pm
+@@ -142,17 +142,17 @@
+ (-d "$srcdir/$line") && do {
+ ($debug >= 10) && print "directory copy.\n";
+ do_copydir ("$srcdir/$line");
+ next LINE;
+ };
+
+ # if we hit this, it's either a file in the package file that is
+ # not in the src directory, or it is not a valid entry.
+- warn "Warning: package error or possible missing or unnecessary file: $line ($package, $lineno).\n";
++ print "Warning: package error or possible missing or unnecessary file: $line ($package, $lineno).\n";
+
+ } # LINE
+
+ close (MANIFEST);
+ chdir ($saved_cwd);
+
+ }
+
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bzXXX_pc_honour_system_nspr_nss.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bzXXX_pc_honour_system_nspr_nss.patch
@@ -0,0 +1,114 @@
+---
+ xulrunner/installer/Makefile.in | 17 ++++++++++++++---
+ xulrunner/installer/libxul-embedding-unstable.pc.in | 2 +-
+ xulrunner/installer/libxul-embedding.pc.in | 2 +-
+ xulrunner/installer/mozilla-nss.pc.in | 6 +++---
+ 4 files changed, 19 insertions(+), 8 deletions(-)
+
+Index: mozilla/xulrunner/installer/Makefile.in
+===================================================================
+--- mozilla.orig/xulrunner/installer/Makefile.in
++++ mozilla/xulrunner/installer/Makefile.in
+@@ -90,40 +90,51 @@
+ mozilla-plugin.pc \
+ mozilla-gtkmozembed.pc \
+ mozilla-gtkmozembed-embedding.pc \
+ $(NULL)
+
+ ifdef MOZ_NATIVE_NSPR
+ NSPR_NAME=nspr
+ NSPR_VERSION=$(shell $(NSPR_CONFIG) --version)
++FULL_NSPR_CFLAGS=$(shell $(NSPR_CONFIG) --cflags)
++FULL_NSPR_LIBS=$(shell $(NSPR_CONFIG) --libs)
+ else
+-pkg_config_files += mozilla-nspr.pc
+ NSPR_NAME=mozilla-nspr
+ FULL_NSPR_CFLAGS=-I\$${includedir}/stable
+ FULL_NSPR_LIBS=$(subst $(prefix),\$${sdkdir},$(shell $(DEPTH)/nsprpub/config/nspr-config --libs))
+ NSPR_VERSION=$(shell $(DEPTH)/nsprpub/config/nspr-config --version)
+ endif
++pkg_config_files += mozilla-nspr.pc
+
+ $(warning FULL_NSPR_CFLAGS=$(FULL_NSPR_CFLAGS))
+
+-ifndef MOZ_NATIVE_NSS
+-pkg_config_files += mozilla-nss.pc
++ifdef MOZ_NATIVE_NSS
++NSPR_VERSION=$(shell $(NSS_CONFIG) --version)
++FULL_NSS_CFLAGS=$(shell $(NSS_CONFIG) --cflags)
++FULL_NSS_LIBS=$(shell $(NSS_CONFIG) --libs)
++else
++NSS_VERSION=$(shell $(DEPTH)/nsprpub/config/nss-config --version)
++FULL_NSS_CFLAGS=-I\$${includedir}/stable
++FULL_NSS_LIBS=$(subst $(prefix),\$${sdkdir},$(shell $(DEPTH)/nsprpub/config/nss-config --libs))
+ endif
++pkg_config_files += mozilla-nss.pc
+
+ %.pc: $(srcdir)/%.pc.in Makefile.in Makefile $(DEPTH)/config/autoconf.mk
+ cat $< | sed \
+ -e "s|%prefix%|$(prefix)|" \
+ -e "s|%includedir%|$(includedir)|" \
+ -e "s|%idldir%|$(idldir)|" \
+ -e "s|%sdkdir%|$(sdkdir)|" \
+ -e "s|%MOZ_APP_NAME%|$(MOZ_APP_NAME)|" \
+ -e "s|%MOZILLA_VERSION%|$(MOZ_APP_VERSION)|" \
+ -e "s|%FULL_NSPR_LIBS%|$(FULL_NSPR_LIBS)|" \
+ -e "s|%FULL_NSPR_CFLAGS%|$(FULL_NSPR_CFLAGS)|" \
++ -e "s|%FULL_NSS_LIBS%|$(FULL_NSS_LIBS)|" \
++ -e "s|%FULL_NSS_CFLAGS%|$(FULL_NSS_CFLAGS)|" \
+ -e "s|%NSPR_NAME%|$(NSPR_NAME)|" \
+ -e "s|%NSPR_VERSION%|$(NSPR_VERSION)|" > $@
+ chmod 644 $@
+
+ install:: $(pkg_config_files)
+ @echo pkg_config_file: $(pkg_config_files)
+ $(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(libdir)/pkgconfig
+
+Index: mozilla/xulrunner/installer/libxul-embedding-unstable.pc.in
+===================================================================
+--- mozilla.orig/xulrunner/installer/libxul-embedding-unstable.pc.in
++++ mozilla/xulrunner/installer/libxul-embedding-unstable.pc.in
+@@ -3,9 +3,9 @@
+ includedir=%includedir%
+ idldir=%idldir%
+ includetype=unstable
+
+ Name: libxul-embedding-unstable
+ Description: Static library for version-independent embedding of the Mozilla runtime (unstable API)
+ Version: %MOZILLA_VERSION%
+ Libs: -L${sdkdir}/lib -lxpcomglue
+-Cflags: -DXPCOM_GLUE -I${includedir}/${includetype} -fshort-wchar
++Cflags: -DXPCOM_GLUE -I${includedir}/${includetype} -fshort-wchar %FULL_NSPR_CFLAGS%
+Index: mozilla/xulrunner/installer/libxul-embedding.pc.in
+===================================================================
+--- mozilla.orig/xulrunner/installer/libxul-embedding.pc.in
++++ mozilla/xulrunner/installer/libxul-embedding.pc.in
+@@ -7,9 +7,9 @@
+ # Note: the default pkg-config cflags will only list include directories
+ # that contain stable (frozen or safe for linking) header files. To include
+ # nonfrozen headers, run pkg-config with --define-variable=includetype=unstable
+
+ Name: libxul-embedding
+ Description: Static library for version-independent embedding of the Mozilla runtime
+ Version: %MOZILLA_VERSION%
+ Libs: -L${sdkdir}/lib -lxpcomglue
+-Cflags: -DXPCOM_GLUE -I${includedir}/${includetype} -fshort-wchar
++Cflags: -DXPCOM_GLUE -I${includedir}/${includetype} -fshort-wchar %FULL_NSPR_CFLAGS%
+Index: mozilla/xulrunner/installer/mozilla-nss.pc.in
+===================================================================
+--- mozilla.orig/xulrunner/installer/mozilla-nss.pc.in
++++ mozilla/xulrunner/installer/mozilla-nss.pc.in
+@@ -1,10 +1,10 @@
+ prefix=%prefix%
+ sdkdir=%sdkdir%
+ includedir=%includedir%
+
+ Name: NSS
+ Description: Mozilla Network Security Services
+-Version: %MOZILLA_VERSION%
++Version: %NSS_VERSION%
+ Requires: %NSPR_NAME% >= %NSPR_VERSION%
+-Libs: -L${sdkdir}/lib -lnss3 -lnssutil3 -lsmime3 -lssl3 -lsoftokn3
+-Cflags: -I${includedir}/stable
++Libs: %FULL_NSS_LIBS%
++Cflags: %FULL_NSS_CFLAGS%
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bzr423334_att310581_leak_initparser.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bzr423334_att310581_leak_initparser.patch
@@ -0,0 +1,30 @@
+---
+ xulrunner/stub/nsXULStub.cpp | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+Index: mozilla/xulrunner/stub/nsXULStub.cpp
+===================================================================
+--- mozilla.orig/xulrunner/stub/nsXULStub.cpp
++++ mozilla/xulrunner/stub/nsXULStub.cpp
+@@ -231,17 +231,20 @@
+ iniPath);
+
+ greFound = (access(greDir, R_OK) == 0);
+
+ strncpy(lastSlash, "application.ini", sizeof(iniPath) - (lastSlash - iniPath));
+
+ #endif
+
+- nsINIParser parser;
++ // Leak the INI parser intentionally, because it allocates memory using the
++ // libc malloc and, once we load libxul, would deallocate it using
++ // jemalloc free()
++ nsINIParser &parser = *new nsINIParser();
+ rv = parser.Init(iniPath);
+ if (NS_FAILED(rv)) {
+ fprintf(stderr, "Could not read application.ini\n");
+ return 1;
+ }
+
+ if (!greFound) {
+ char minVersion[VERSION_MAXLEN];
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/dom_inspector_support_for_prism.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/dom_inspector_support_for_prism.patch
@@ -0,0 +1,34 @@
+---
+ extensions/inspector/install.rdf | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+Index: mozilla/extensions/inspector/install.rdf
+===================================================================
+--- mozilla.orig/extensions/inspector/install.rdf
++++ mozilla/extensions/inspector/install.rdf
+@@ -40,16 +40,25 @@
+
+ {92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}
+ 2.0a
+ 2.0.*
+
+
+
+
++
++
++ prism@developer.mozilla.org
++ 0.4
++ 1.0.0.*
++
++
++
++
+
+
+ toolkit@mozilla.org
+ 1.9a1
+ 1.9
+
+
+
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bz394103_scale_images_for_192+dpi.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bz394103_scale_images_for_192+dpi.patch
@@ -0,0 +1,27 @@
+Index: gfx/src/thebes/nsThebesDeviceContext.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/thebes/nsThebesDeviceContext.cpp,v
+retrieving revision 1.68
+diff -u -8 -p -r1.68 nsThebesDeviceContext.cpp
+--- a/gfx/src/thebes/nsThebesDeviceContext.cpp 17 Feb 2008 21:23:37 -0000 1.68
++++ b/gfx/src/thebes/nsThebesDeviceContext.cpp 25 Feb 2008 10:35:19 -0000
+@@ -232,18 +232,17 @@ nsThebesDeviceContext::SetDPI()
+ NS_ASSERTION(dpi != -1, "no dpi set");
+
+ if (dotsArePixels) {
+ // First figure out the closest multiple of 96, which is the number of
+ // dev pixels per CSS pixel. Then, divide that into AppUnitsPerCSSPixel()
+ // to get the number of app units per dev pixel. The PR_MAXes are to
+ // make sure we don't end up dividing by zero.
+ mAppUnitsPerDevNotScaledPixel = PR_MAX(1, AppUnitsPerCSSPixel() /
+- PR_MAX(1, (dpi + 48) / 96));
+-
++ PR_MAX(1, dpi / 96));
+ } else {
+ /* set mAppUnitsPerDevPixel so we're using exactly 72 dpi, even
+ * though that means we have a non-integer number of device "pixels"
+ * per CSS pixel
+ */
+ mAppUnitsPerDevNotScaledPixel = (AppUnitsPerCSSPixel() * 96) / dpi;
+ }
+
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bzXXX_autoconfig_in_gre.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bzXXX_autoconfig_in_gre.patch
@@ -0,0 +1,35 @@
+---
+ extensions/pref/autoconfig/src/nsReadConfig.cpp | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+Index: mozilla/extensions/pref/autoconfig/src/nsReadConfig.cpp
+===================================================================
+--- mozilla.orig/extensions/pref/autoconfig/src/nsReadConfig.cpp
++++ mozilla/extensions/pref/autoconfig/src/nsReadConfig.cpp
+@@ -279,20 +279,25 @@
+ getter_AddRefs(jsFile));
+ if (NS_FAILED(rv))
+ return rv;
+
+ #ifdef XP_MAC
+ jsFile->AppendNative(NS_LITERAL_CSTRING("Essential Files"));
+ #endif
+ } else {
+- rv = NS_GetSpecialDirectory(NS_APP_DEFAULTS_50_DIR,
++ rv = NS_GetSpecialDirectory(NS_GRE_DIR,
+ getter_AddRefs(jsFile));
+ if (NS_FAILED(rv))
+ return rv;
++
++ rv = jsFile->AppendNative(NS_LITERAL_CSTRING("defaults"));
++ if (NS_FAILED(rv))
++ return rv;
++
+ rv = jsFile->AppendNative(NS_LITERAL_CSTRING("autoconfig"));
+ if (NS_FAILED(rv))
+ return rv;
+ }
+ rv = jsFile->AppendNative(nsDependentCString(aFileName));
+ if (NS_FAILED(rv))
+ return rv;
+
--- xulrunner-1.9-1.9~rc1+nobinonly.orig/debian/patches/bz321315_gconf_backend_for_19.patch
+++ xulrunner-1.9-1.9~rc1+nobinonly/debian/patches/bz321315_gconf_backend_for_19.patch
@@ -0,0 +1,3437 @@
+diff -Naur mozilla.orig/config/autoconf.mk.in mozilla/config/autoconf.mk.in
+--- mozilla.orig/config/autoconf.mk.in 2008-03-18 10:37:00.000000000 -0700
++++ mozilla/config/autoconf.mk.in 2008-04-10 11:33:28.000000000 -0700
+@@ -246,6 +246,7 @@
+ MOZ_GNOMEVFS_CFLAGS = @MOZ_GNOMEVFS_CFLAGS@
+ MOZ_GNOMEVFS_LIBS = @MOZ_GNOMEVFS_LIBS@
+
++MOZ_ENABLE_GCONF = @MOZ_ENABLE_GCONF@
+ MOZ_GCONF_CFLAGS = @MOZ_GCONF_CFLAGS@
+ MOZ_GCONF_LIBS = @MOZ_GCONF_LIBS@
+
+diff -Naur mozilla.orig/configure.in mozilla/configure.in
+--- mozilla.orig/configure.in 2008-03-20 12:17:09.000000000 -0700
++++ mozilla/configure.in 2008-04-10 11:39:22.000000000 -0700
+@@ -4957,6 +4957,7 @@
+ ])
+ fi
+
++ AC_SUBST(MOZ_ENABLE_GCONF)
+ AC_SUBST(MOZ_GCONF_CFLAGS)
+ AC_SUBST(MOZ_GCONF_LIBS)
+
+diff -Naur mozilla.orig/extensions/pref/system-pref/src/gconf/Makefile.in mozilla/extensions/pref/system-pref/src/gconf/Makefile.in
+--- mozilla.orig/extensions/pref/system-pref/src/gconf/Makefile.in 2006-04-28 07:54:52.000000000 -0700
++++ mozilla/extensions/pref/system-pref/src/gconf/Makefile.in 2008-04-01 16:50:49.000000000 -0700
+@@ -42,45 +42,37 @@
+
+ include $(DEPTH)/config/autoconf.mk
+
+-MODULE = system-pref
+-LIBRARY_NAME = system-pref
++MODULE = syspref-gconf
++MODULE_NAME = nsSystemPrefServiceModule
++LIBRARY_NAME = syspref-gconf
++ifneq ($(OS_ARCH),WINNT)
++SHORT_LIBNAME = spgconf
++endif
++
++EXPORT_LIBRARY = 1
++IS_COMPONENT = 1
++FORCE_STATIC_LIB = 1
+ LIBXUL_LIBRARY = 1
+
+ REQUIRES = pref \
++ system-pref \
+ string \
+ xpcom \
+ embedcomponents \
++ necko \
+ $(NULL)
+
+ CPPSRCS = \
+ nsSystemPrefService.cpp \
+- nsSystemPrefFactory.cpp \
+ $(NULL)
+
+-SHARED_LIBRARY_LIBS = ../libsystem-pref_s.a
+-
+ EXTRA_DSO_LDOPTS = \
+- -L$(DIST)/bin \
+ $(MOZ_COMPONENT_LIBS) \
+- $(MOZ_GTK2_LIBS) \
+- $(NULL)
+-
+-EXPORT_LIBRARY = 1
+-IS_COMPONENT = 1
+-MODULE_NAME = nsSystemPrefModule
+-
+-EXPORTS = \
+- nsSystemPrefService.h \
++ $(MOZ_GTK2_LIBS) \
++ $(MOZ_GCONF_LIBS) \
+ $(NULL)
+
+ include $(topsrcdir)/config/rules.mk
+
+-CFLAGS += $(MOZ_GTK2_CFLAGS)
+-CXXFLAGS += $(MOZ_GTK2_CFLAGS)
+-
+-LOCAL_INCLUDES = -I$(srcdir)/..
+-
+-export::
+- $(INSTALL) $(srcdir)/../nsSystemPrefFactory.cpp .
+-
+-GARBAGE += nsSystemPrefFactory.cpp
++CFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_GCONF_CFLAGS)
++CXXFLAGS += $(MOZ_GTK2_CFLAGS) $(MOZ_GCONF_CFLAGS)
+diff -Naur mozilla.orig/extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp mozilla/extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp
+--- mozilla.orig/extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp 2007-07-08 00:08:21.000000000 -0700
++++ mozilla/extensions/pref/system-pref/src/gconf/nsSystemPrefService.cpp 2008-04-01 16:50:49.000000000 -0700
+@@ -23,7 +23,7 @@
+ *
+ * Original Author: Bolian Yin (bolian.yin@sun.com)
+ *
+- * Contributor(s):
++ * Contributor(s): Robert O'Callahan/Novell (rocallahan@novell.com)
+ *
+ * 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
+@@ -41,6 +41,7 @@
+
+ #include
+ #include
++#include
+
+ #include "plstr.h"
+ #include "nsCOMPtr.h"
+@@ -48,867 +49,1270 @@
+ #include "nsIServiceManager.h"
+ #include "nsIObserver.h"
+ #include "nsWeakReference.h"
+-
++#include "nsIPrefBranch2.h"
++#include "nsISystemPrefService.h"
++#include "nsDataHashtable.h"
++#include "nsHashKeys.h"
++#include "nsICategoryManager.h"
++#include "nsIGenericFactory.h"
+ #include "nsString.h"
+-#include "nsSystemPrefLog.h"
+-#include "nsSystemPrefService.h"
+-
+-/*************************************************************************
+- * The strange thing here is that we load the gconf library manually and
+- * search the function pointers we need. If that process fails, no gconf
+- * support is available in mozilla. The aim is to make mozilla independent
+- * on gconf, in both compile time and run time.
+- ************************************************************************/
+-
+-//gconf types
+-extern "C" {
+-
+- typedef enum {
+- GCONF_VALUE_INVALID,
+- GCONF_VALUE_STRING,
+- GCONF_VALUE_INT,
+- GCONF_VALUE_FLOAT,
+- GCONF_VALUE_BOOL,
+- GCONF_VALUE_SCHEMA,
+-
+- GCONF_VALUE_LIST,
+- GCONF_VALUE_PAIR
+-
+- }GConfValueType;
+-
+- typedef struct {
+- GConfValueType type;
+- }GConfValue;
+-
+- typedef void * (*GConfClientGetDefaultType) (void);
+- typedef PRBool (*GConfClientGetBoolType) (void *client, const gchar *key,
+- GError **err);
+- typedef gchar* (*GConfClientGetStringType) (void *client, const gchar *key,
+- GError **err);
+- typedef PRInt32 (*GConfClientGetIntType) (void *client, const gchar *key,
+- GError **err);
+- typedef GSList* (*GConfClientGetListType) (void *client, const gchar *key,
+- GConfValueType list_type,
+- GError **err);
+- typedef void (*GConfClientNotifyFuncType) (void* client, guint cnxn_id,
+- void *entry,
+- gpointer user_data);
+- typedef guint (*GConfClientNotifyAddType) (void* client,
+- const gchar* namespace_section,
+- GConfClientNotifyFuncType func,
+- gpointer user_data,
+- GFreeFunc destroy_notify,
+- GError** err);
+- typedef void (*GConfClientNotifyRemoveType) (void *client,
+- guint cnxn);
+- typedef void (*GConfClientAddDirType) (void *client,
+- const gchar *dir,
+- guint8 preload,
+- GError **err);
+- typedef void (*GConfClientRemoveDirType) (void *client,
+- const gchar *dir,
+- GError **err);
+-
+- typedef const char* (*GConfEntryGetKeyType) (const void *entry);
+- typedef GConfValue* (*GConfEntryGetValueType) (const void *entry);
+-
+- typedef const char* (*GConfValueGetStringType) (const GConfValue *value);
+- typedef PRInt32 (*GConfValueGetIntType) (const GConfValue *value);
+- typedef PRBool (*GConfValueGetBoolType) (const GConfValue *value);
++#include "nsIPermissionManager.h"
+
+-
+- static void gconf_key_listener (void* client, guint cnxn_id,
+- void *entry, gpointer user_data);
+-}
++#define NS_SYSTEMPREF_SERVICE_CID \
++ { /* {3724e748-b088-4bf8-9298-aad426b66293} */ \
++ 0x3724e748, \
++ 0xb088, \
++ 0x4bf8, \
++ { 0x92, 0x98, 0xaa, 0xd4, 0x26, 0xb6, 0x62, 0x93 } \
++ }
++
++#define NS_SYSTEMPREF_SERVICE_CLASSNAME "System Preferences Platform Service"
++
++/**
++ * We can link directly to the gconf library. If it's not available,
++ * this component just won't load and no system prefs will be offered.
++ */
++
++#define NUM_ELEM(a) (sizeof(a)/sizeof(a[0]))
++
++class nsSystemPrefService;
++
++/**
++ * List the preferences that have a simple mapping between Moz and gconf.
++ * These preferences have the same meaning and their values are
++ * automatically converted.
++ */
++struct SimplePrefMapping {
++ const char *mozPrefName;
++ const char *gconfPrefName;
++ /**
++ * If this is PR_FALSE, then we never allow Mozilla to change
++ * this setting. The Mozilla pref will always be locked.
++ * If this is PR_TRUE then Mozilla will be allowed to change
++ * the setting --- but only if it is writable in gconf.
++ */
++ PRBool allowWritesFromMozilla;
++};
++typedef nsresult (* ComplexGConfPrefChanged)(nsSystemPrefService* aPrefService,
++ GConfClient* aClient);
++typedef nsresult (* ComplexMozPrefChanged)(nsSystemPrefService* aPrefService,
++ GConfClient* aClient);
++struct ComplexGConfPrefMapping {
++ const char* gconfPrefName;
++ ComplexGConfPrefChanged callback;
++};
+
+-struct GConfCallbackData
+-{
+- GConfProxy *proxy;
+- void * userData;
+- PRUint32 atom;
+- PRUint32 notifyId;
++struct ComplexMozPrefMapping {
++ const char* mozPrefName;
++ ComplexMozPrefChanged callback;
+ };
+-//////////////////////////////////////////////////////////////////////
+-// GConPrxoy is a thin wrapper for easy use of gconf funcs. It loads the
+-// gconf library and initializes the func pointers for later use.
+-//////////////////////////////////////////////////////////////////////
+-class GConfProxy
++
++class nsSystemPrefService : public nsISystemPrefService
+ {
+ public:
+- GConfProxy(nsSystemPrefService* aSysPrefService);
+- ~GConfProxy();
+- PRBool Init();
+-
+- nsresult GetBoolPref(const char *aMozKey, PRBool *retval);
+- nsresult GetCharPref(const char *aMozKey, char **retval);
+- nsresult GetIntPref(const char *aMozKey, PRInt32 *retval);
++ NS_DECL_ISUPPORTS
+
+- nsresult NotifyAdd (PRUint32 aAtom, void *aUserData);
+- nsresult NotifyRemove (PRUint32 aAtom, const void *aUserData);
++ nsresult Init();
+
+- nsresult GetAtomForMozKey(const char *aMozKey, PRUint32 *aAtom) {
+- return GetAtom(aMozKey, 0, aAtom);
+- }
+- const char *GetMozKey(PRUint32 aAtom) {
+- return GetKey(aAtom, 0);
++ virtual nsresult LoadSystemPreferences(nsISystemPref* aPrefs);
++ virtual nsresult NotifyMozillaPrefChanged(const char* aPrefName);
++ virtual nsresult NotifyUnloadSystemPreferences();
++
++ nsSystemPrefService();
++ virtual ~nsSystemPrefService();
++
++ nsISystemPref* GetPrefs() { return mPref; }
++ SimplePrefMapping* GetSimpleCallbackData(PRUint32 aKey) {
++ SimplePrefMapping* result = nsnull;
++ mGConfSimpleCallbacks.Get(aKey, &result);
++ return result;
++ }
++ ComplexGConfPrefMapping* GetComplexCallbackData(PRUint32 aKey) {
++ ComplexGConfPrefMapping* result = nsnull;
++ mGConfComplexCallbacks.Get(aKey, &result);
++ return result;
+ }
+
+- void OnNotify(void *aClient, void * aEntry, PRUint32 aNotifyId,
+- GConfCallbackData *aData);
+-
+ private:
+- void *mGConfClient;
+- PRLibrary *mGConfLib;
+- PRBool mInitialized;
+- nsSystemPrefService *mSysPrefService;
+-
+- //listeners
+- nsAutoVoidArray *mObservers;
+-
+- void InitFuncPtrs();
+- //gconf public func ptrs
+-
+- //gconf client funcs
+- GConfClientGetDefaultType GConfClientGetDefault;
+- GConfClientGetBoolType GConfClientGetBool;
+- GConfClientGetStringType GConfClientGetString;
+- GConfClientGetIntType GConfClientGetInt;
+- GConfClientGetListType GConfClientGetList;
+- GConfClientNotifyAddType GConfClientNotifyAdd;
+- GConfClientNotifyRemoveType GConfClientNotifyRemove;
+- GConfClientAddDirType GConfClientAddDir;
+- GConfClientRemoveDirType GConfClientRemoveDir;
+-
+- //gconf entry funcs
+- GConfEntryGetValueType GConfEntryGetValue;
+- GConfEntryGetKeyType GConfEntryGetKey;
+-
+- //gconf value funcs
+- GConfValueGetBoolType GConfValueGetBool;
+- GConfValueGetStringType GConfValueGetString;
+- GConfValueGetIntType GConfValueGetInt;
+-
+- //pref name translating stuff
+- nsresult GetAtom(const char *aKey, PRUint8 aNameType, PRUint32 *aAtom);
+- nsresult GetAtomForGConfKey(const char *aGConfKey, PRUint32 *aAtom) \
+- {return GetAtom(aGConfKey, 1, aAtom);}
+- const char *GetKey(PRUint32 aAtom, PRUint8 aNameType);
+- const char *GetGConfKey(PRUint32 aAtom) \
+- {return GetKey(aAtom, 1); }
+- inline const char *MozKey2GConfKey(const char *aMozKey);
+-
+- //const strings
+- static const char sPrefGConfKey[];
+- static const char sDefaultLibName1[];
+- static const char sDefaultLibName2[];
++ nsISystemPref* mPref;
++ nsDataHashtable mGConfSimpleCallbacks;
++ nsDataHashtable mGConfComplexCallbacks;
++ // This is set to PR_FALSE temporarily to stop listening to gconf
++ // change notifications (while we change gconf values)
++ PRPackedBool mListenToGConf;
+ };
+
+-struct SysPrefCallbackData {
+- nsISupports *observer;
+- PRBool bIsWeakRef;
+- PRUint32 prefAtom;
+-};
+-
+-PRBool PR_CALLBACK
+-sysPrefDeleteObserver(void *aElement, void *aData) {
+- SysPrefCallbackData *pElement =
+- static_cast(aElement);
+- NS_RELEASE(pElement->observer);
+- nsMemory::Free(pElement);
+- return PR_TRUE;
+-}
+-
+-NS_IMPL_ISUPPORTS2(nsSystemPrefService, nsIPrefBranch, nsIPrefBranch2)
+-
+-/* public */
+ nsSystemPrefService::nsSystemPrefService()
+- :mInitialized(PR_FALSE),
+- mGConf(nsnull),
+- mObservers(nsnull)
++ : mPref(nsnull), mListenToGConf(PR_TRUE)
+ {
++ mGConfSimpleCallbacks.Init();
++ mGConfComplexCallbacks.Init();
+ }
+
+ nsSystemPrefService::~nsSystemPrefService()
+ {
+- mInitialized = PR_FALSE;
+-
+- if (mGConf)
+- delete mGConf;
+- if (mObservers) {
+- (void)mObservers->EnumerateForwards(sysPrefDeleteObserver, nsnull);
+- delete mObservers;
+- }
++ NotifyUnloadSystemPreferences();
+ }
+
+ nsresult
+ nsSystemPrefService::Init()
+ {
+- if (!gSysPrefLog) {
+- gSysPrefLog = PR_NewLogModule("Syspref");
+- if (!gSysPrefLog) return NS_ERROR_OUT_OF_MEMORY;
+- }
+-
+- SYSPREF_LOG(("Init SystemPref Service\n"));
+- if (mInitialized)
+- return NS_ERROR_FAILURE;
+-
+- if (!mGConf) {
+- mGConf = new GConfProxy(this);
+- if (!mGConf->Init()) {
+- delete mGConf;
+- mGConf = nsnull;
+- return NS_ERROR_FAILURE;
+- }
+- }
+-
+- mInitialized = PR_TRUE;
+ return NS_OK;
+ }
+
+-/* readonly attribute string root; */
+-NS_IMETHODIMP nsSystemPrefService::GetRoot(char * *aRoot)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
+-}
++NS_IMPL_ISUPPORTS1(nsSystemPrefService, nsISystemPrefService)
+
+-/* long getPrefType (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::GetPrefType(const char *aPrefName, PRInt32 *_retval)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
++static GConfClient* GetGConf() {
++ return gconf_client_get_default();
+ }
+
+-/* boolean getBoolPref (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::GetBoolPref(const char *aPrefName, PRBool *_retval)
++static PRBool VerifyMatchingTypes(nsISystemPref* aPrefs,
++ const char* aMozPref, GConfValue* aVal)
+ {
+- return mInitialized ?
+- mGConf->GetBoolPref(aPrefName, _retval) : NS_ERROR_FAILURE;
+-}
++ nsCOMPtr prefBranch = aPrefs->GetPrefUserBranch();
++ PRInt32 type;
++ nsresult rv = prefBranch->GetPrefType(aMozPref, &type);
++ if (NS_FAILED(rv)) {
++ // pref probably doesn't exist. Let gconf set it.
++ return PR_TRUE;
++ }
+
+-/* void setBoolPref (in string aPrefName, in long aValue); */
+-NS_IMETHODIMP nsSystemPrefService::SetBoolPref(const char *aPrefName, PRInt32 aValue)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
++ PRBool ok;
++ switch (aVal->type) {
++ case GCONF_VALUE_STRING:
++ ok = type == nsIPrefBranch2::PREF_STRING;
++ break;
++ case GCONF_VALUE_INT:
++ ok = type == nsIPrefBranch2::PREF_INT;
++ break;
++ case GCONF_VALUE_BOOL:
++ ok = type == nsIPrefBranch2::PREF_BOOL;
++ break;
++ default:
++ NS_ERROR("Unhandled gconf preference type");
++ return PR_FALSE;
++ }
++
++ NS_ASSERTION(ok, "Mismatched gconf/Mozilla pref types");
++ return ok;
+ }
+
+-/* string getCharPref (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::GetCharPref(const char *aPrefName, char **_retval)
+-{
+- return mInitialized ?
+- mGConf->GetCharPref(aPrefName, _retval) : NS_ERROR_FAILURE;
+-}
++/**
++ * Map a gconf pref value into the corresponding Mozilla pref.
++ */
++static nsresult ApplySimpleMapping(SimplePrefMapping* aMap,
++ nsISystemPref* aPrefs,
++ GConfClient* aClient)
++{
++ GConfValue* val = gconf_client_get(aClient, aMap->gconfPrefName, nsnull);
++ if (!val) {
++ // No gconf key, so there's really nothing to do
++ return NS_OK;
++ }
+
+-/* void setCharPref (in string aPrefName, in string aValue); */
+-NS_IMETHODIMP nsSystemPrefService::SetCharPref(const char *aPrefName, const char *aValue)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
+-}
++ VerifyMatchingTypes(aPrefs, aMap->mozPrefName, val);
+
+-/* long getIntPref (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::GetIntPref(const char *aPrefName, PRInt32 *_retval)
+-{
+- return mInitialized ?
+- mGConf->GetIntPref(aPrefName, _retval) : NS_ERROR_FAILURE;
+-}
++ PRBool locked = !aMap->allowWritesFromMozilla ||
++ !gconf_client_key_is_writable(aClient, aMap->gconfPrefName, nsnull);
++ nsresult rv;
++ switch (val->type) {
++ case GCONF_VALUE_STRING: {
++ const char* str = gconf_value_get_string(val);
++ rv = aPrefs->SetOverridingMozillaStringPref(aMap->mozPrefName, str, locked);
++ // XXX do we need to free 'str' here?
++ break;
++ }
++ case GCONF_VALUE_INT:
++ rv = aPrefs->SetOverridingMozillaIntPref(aMap->mozPrefName,
++ gconf_value_get_int(val), locked);
++ break;
++ case GCONF_VALUE_BOOL:
++ rv = aPrefs->SetOverridingMozillaBoolPref(aMap->mozPrefName,
++ gconf_value_get_bool(val), locked);
++ break;
++ default:
++ NS_ERROR("Unusable gconf value type");
++ rv = NS_ERROR_FAILURE;
++ break;
++ }
++
++ gconf_value_free(val);
++ return rv;
++}
++
++/**
++ * Map a Mozilla pref into the corresponding gconf pref, if
++ * that's allowed.
++ */
++static nsresult ReverseApplySimpleMapping(SimplePrefMapping* aMap,
++ nsISystemPref* aPrefs,
++ GConfClient* aClient)
++{
++ // Verify that the gconf key has the right type, if it exists
++ GConfValue* val = gconf_client_get(aClient, aMap->gconfPrefName, nsnull);
++ if (val) {
++ VerifyMatchingTypes(aPrefs, aMap->mozPrefName, val);
++ gconf_value_free(val);
++ }
++
++ PRBool writable = aMap->allowWritesFromMozilla &&
++ gconf_client_key_is_writable(aClient, aMap->gconfPrefName, nsnull);
++ if (!writable) {
++ NS_ERROR("Gconf key is not writable");
++ return NS_ERROR_FAILURE;
++ }
+
+-/* void setIntPref (in string aPrefName, in long aValue); */
+-NS_IMETHODIMP nsSystemPrefService::SetIntPref(const char *aPrefName, PRInt32 aValue)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
+-}
++ nsCOMPtr prefBranch = aPrefs->GetPrefUserBranch();
++ PRInt32 type;
++ nsresult rv = prefBranch->GetPrefType(aMap->mozPrefName, &type);
++ if (NS_FAILED(rv)) {
++ NS_ERROR("Writing back a pref that doesn't exist?");
++ return rv;
++ }
+
+-/* void getComplexValue (in string aPrefName, in nsIIDRef aType, [iid_is (aType), retval] out nsQIResult aValue); */
+-NS_IMETHODIMP nsSystemPrefService::GetComplexValue(const char *aPrefName, const nsIID & aType, void * *aValue)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
+-}
++ switch (type) {
++ case nsIPrefBranch2::PREF_STRING:
++ {
++ char* result;
++ rv = prefBranch->GetCharPref(aMap->mozPrefName, &result);
++ if (NS_FAILED(rv))
++ return rv;
+
+-/* void setComplexValue (in string aPrefName, in nsIIDRef aType, in nsISupports aValue); */
+-NS_IMETHODIMP nsSystemPrefService::SetComplexValue(const char *aPrefName, const nsIID & aType, nsISupports *aValue)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
+-}
++ gconf_client_set_string(aClient, aMap->gconfPrefName, result, nsnull);
++ nsMemory::Free(result);
++ }
++ break;
++ case nsIPrefBranch2::PREF_INT:
++ {
++ PRInt32 result;
++ rv = prefBranch->GetIntPref(aMap->mozPrefName, &result);
++ if (NS_FAILED(rv))
++ return rv;
+
+-/* void clearUserPref (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::ClearUserPref(const char *aPrefName)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
+-}
++ gconf_client_set_int(aClient, aMap->gconfPrefName, result, nsnull);
++ }
++ break;
++ case nsIPrefBranch2::PREF_BOOL:
++ {
++ PRBool result;
++ rv = prefBranch->GetBoolPref(aMap->mozPrefName, &result);
++ if (NS_FAILED(rv))
++ return rv;
+
+-/* void lockPref (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::LockPref(const char *aPrefName)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
+-}
++ gconf_client_set_bool(aClient, aMap->gconfPrefName, result, nsnull);
++ }
++ break;
++ default:
++ NS_ERROR("Unhandled gconf preference type");
++ return NS_ERROR_FAILURE;
++ }
+
+-/* boolean prefHasUserValue (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::PrefHasUserValue(const char *aPrefName, PRBool *_retval)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
++ return NS_OK;
+ }
+
+-/* boolean prefIsLocked (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::PrefIsLocked(const char *aPrefName, PRBool *_retval)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
+-}
++/* BEGIN preference mapping definition area
++ *
++ * There are a few rules that our preference maps have to obey:
++ *
++ * 1) Each mapping defines a relationship R between a set of GConf preferences and
++ * a set of Mozilla preferences that must *always* be true. Thus, when a Mozilla
++ * pref changes or a gconf pref changes, we may need to change something on the
++ * other side to preserve R. If a GConf preference is read-only, then we may
++ * need to lock one or more Mozilla preferences to avoid a situation where the
++ * Mozilla preference changes and we can't update the GConf preference to
++ * ensure R continues to hold.
++ *
++ * 2) If an unlocked Mozilla preference is changed, then we can only
++ * preserve R by changing GConf preferences; we are not allowed to
++ * change Mozilla preferences.
++ *
++ * 3) If a GConf preference is changed, then we can only preserve R by
++ * changing Moozilla preferences; we are nt allowed to change GConf
++ * preferences.
++ *
++ * For "simple" mappings, the relationship R is just of the form
++ * "GConf preference 'A' is equal to Mozilla preference 'B'". R is
++ * preserved by setting A to B when B changes, and by setting B to A
++ * when A changes. If A is read-only then we lock B (or we may just
++ * decide to lock B for other reasons). Thus rules 1-3 are satisfied.
++ *
++ * For "complex" mappings we have more complicated
++ * relationships. These are documented below.
++ */
++
++static SimplePrefMapping sSimplePrefMappings[] = {
++ // GNOME proxy settings; allow these to be set through the Firefox UI
++ {"network.proxy.http", "/system/http_proxy/host", PR_TRUE},
++ {"network.proxy.http_port", "/system/http_proxy/port", PR_TRUE},
++ {"network.proxy.ftp", "/system/proxy/ftp_host", PR_TRUE},
++ {"network.proxy.ftp_port", "/system/proxy/ftp_port", PR_TRUE},
++ {"network.proxy.ssl", "/system/proxy/secure_host", PR_TRUE},
++ {"network.proxy.ssl_port", "/system/proxy/secure_port", PR_TRUE},
++ {"network.proxy.socks", "/system/proxy/socks_host", PR_TRUE},
++ {"network.proxy.socks_port", "/system/proxy/socks_port", PR_TRUE},
++ {"network.proxy.autoconfig_url", "/system/proxy/autoconfig_url", PR_TRUE},
++
++ // GNOME accessibility setting; never allow this to be set by Firefox
++ {"config.use_system_prefs.accessibility",
++ "/desktop/gnome/interface/accessibility", PR_FALSE},
++
++ // GConf Firefox preferences; allow these to be set through the Firefox UI
++ {"security.enable_java", "/apps/firefox/web/java_enabled", PR_TRUE},
++ {"javascript.enabled", "/apps/firefox/web/javascript_enabled", PR_TRUE},
++ {"browser.startup.homepage", "/apps/firefox/general/homepage_url", PR_TRUE},
++ {"browser.cache.disk.capacity", "/apps/firefox/web/cache_size", PR_TRUE},
++ {"network.cookie.lifetimePolicy", "/apps/firefox/web/cookie_accept", PR_TRUE},
++
++ // UI lockdown settings; never allow these to be set by Firefox. There is no
++ // Firefox UI for these but they could otherwise be set via about:config.
++ {"config.lockdown.printing", "/desktop/gnome/lockdown/disable_printing", PR_FALSE},
++ {"config.lockdown.printsetup", "/desktop/gnome/lockdown/disable_print_setup", PR_FALSE},
++ {"config.lockdown.savepage", "/desktop/gnome/lockdown/disable_save_to_disk", PR_FALSE},
++ {"config.lockdown.history", "/apps/firefox/lockdown/disable_history", PR_FALSE},
++ {"config.lockdown.toolbarediting", "/apps/firefox/lockdown/disable_toolbar_editing", PR_FALSE},
++ {"config.lockdown.urlbar", "/apps/firefox/lockdown/disable_url_bar", PR_FALSE},
++ {"config.lockdown.bookmark", "/apps/firefox/lockdown/disable_bookmark_editing", PR_FALSE},
++ {"config.lockdown.disable_themes", "/apps/firefox/lockdown/disable_themes", PR_FALSE},
++ {"config.lockdown.disable_extensions", "/apps/firefox/lockdown/disable_extensions", PR_FALSE},
++ {"config.lockdown.searchbar", "/apps/firefox/lockdown/disable_searchbar", PR_FALSE},
++ {"config.lockdown.hidebookmark", "/apps/firefox/lockdown/hide_bookmark", PR_FALSE},
++};
+
+-/* void unlockPref (in string aPrefName); */
+-NS_IMETHODIMP nsSystemPrefService::UnlockPref(const char *aPrefName)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
++static nsresult ApplyListPref(nsSystemPrefService* aPrefService,
++ GConfClient* aClient,
++ const char* aGConfKey, const char* aMozKey,
++ char aSeparator)
++{
++ GSList* list = gconf_client_get_list(aClient, aGConfKey,
++ GCONF_VALUE_STRING, nsnull);
++ nsCAutoString str;
++ for (GSList* l = list; l; l = l->next) {
++ str.Append((const char*)l->data);
++ if (l->next) {
++ str.Append(aSeparator);
++ }
++ }
++ PRBool lock = !gconf_client_key_is_writable(aClient, aGConfKey, nsnull);
++ nsresult rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaStringPref(aMozKey, str.get(), lock);
++ // XXX does this free the strings? Should it?
++ g_slist_free(list);
++ return rv;
++}
++static nsresult ReverseApplyListPref(nsSystemPrefService* aPrefService,
++ GConfClient* aClient,
++ const char* aGConfKey, const char* aMozKey,
++ char aSeparator)
++{
++ char* data = nsnull;
++ nsCOMPtr prefs =
++ aPrefService->GetPrefs()->GetPrefUserBranch();
++ prefs->GetCharPref(aMozKey, &data);
++ if (!data)
++ return NS_ERROR_FAILURE;
++ nsresult rv = NS_OK;
++ GSList* list = nsnull;
++ PRInt32 i = 0;
++ while (data[i]) {
++ const char* nextComma = strchr(data+i, ',');
++ PRInt32 tokLen = nextComma ? nextComma - (data+i) : strlen(data+i);
++ char* tok = strndup(data+i, tokLen);
++ if (!tok)
++ break;
++ GSList* newList = g_slist_append(list, tok);
++ if (!newList) {
++ rv = NS_ERROR_OUT_OF_MEMORY;
++ break;
++ }
++ list = newList;
++ if (!nextComma)
++ break;
++ i = nextComma + 1 - data;
++ }
++ nsMemory::Free(data);
++ if (NS_SUCCEEDED(rv)) {
++ gconf_client_set_list(aClient, aGConfKey, GCONF_VALUE_STRING, list, nsnull);
++ }
++ for (GSList* l = list; l; l = l->next) {
++ free(l->data);
++ }
++ g_slist_free(list);
++ return rv;
+ }
+
+-/* void deleteBranch (in string aStartingAt); */
+-NS_IMETHODIMP nsSystemPrefService::DeleteBranch(const char *aStartingAt)
++/**
++ * The relationship R is
++ * "network.negotiate-auth.trusted-uris" is the comma-separated concatenation
++ * of the elements of the list "/apps/firefox/general/trusted_URIs"
++ */
++static const char GConfKey_TrustedURIs[] = "/apps/firefox/general/trusted_URIs";
++static const char MozKey_TrustedURIs[] = "network.negotiate-auth.trusted-uris";
++static nsresult ApplyTrustedURIs(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ return ApplyListPref(aPrefService, aClient,
++ GConfKey_TrustedURIs, MozKey_TrustedURIs, ',');
++}
++static nsresult ReverseApplyTrustedURIs(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ return ReverseApplyListPref(aPrefService, aClient,
++ GConfKey_TrustedURIs, MozKey_TrustedURIs, ',');
++}
++
++/**
++ * The relationship R is
++ * "network.negotiate-auth.delegation-uris" is the comma-separated concatenation
++ * of the elements of the list "/apps/firefox/general/delegation_URIs"
++ */
++static const char GConfKey_DelegationURIs[] = "/apps/firefox/general/delegation_URIs";
++static const char MozKey_DelegationURIs[] = "network.negotiate-auth.delegation-uris";
++static nsresult ApplyDelegationURIs(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ return ApplyListPref(aPrefService, aClient,
++ GConfKey_DelegationURIs, MozKey_DelegationURIs, ',');
++}
++static nsresult ReverseApplyDelegationURIs(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ return ReverseApplyListPref(aPrefService, aClient,
++ GConfKey_DelegationURIs, MozKey_DelegationURIs, ',');
++}
++
++/**
++ * The relationship R is
++ * "network.proxy.no_proxies_on" is the comma-separated concatenation
++ * of the elements of the list "/system/http_proxy/ignore_hosts"
++ */
++static const char GConfKey_IgnoreHosts[] = "/system/http_proxy/ignore_hosts";
++static const char MozKey_IgnoreHosts[] = "network.proxy.no_proxies_on";
++static nsresult ApplyIgnoreHosts(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ return ApplyListPref(aPrefService, aClient,
++ GConfKey_IgnoreHosts, MozKey_IgnoreHosts, ',');
++}
++static nsresult ReverseApplyIgnoreHosts(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ return ReverseApplyListPref(aPrefService, aClient,
++ GConfKey_IgnoreHosts, MozKey_IgnoreHosts, ',');
++}
++
++/**
++ * The relationship R is
++ * ("/system/proxy/mode" is 'manual' if and only if "network.proxy.type" is eProxyConfig_Manual (1))
++ * AND ("/system/proxy/mode" is 'auto' if and only if "network.proxy.type" is eProxyConfig_PAC (2))
++ *
++ * [This means 'none' matches any value of "network.proxy.type" other than 1 or 2.]
++ */
++static const char GConfKey_ProxyMode[] = "/system/proxy/mode";
++static const char MozKey_ProxyMode[] = "network.proxy.type";
++static nsresult ApplyProxyMode(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
+ {
+- return NS_ERROR_NOT_IMPLEMENTED;
++ char* str = gconf_client_get_string(aClient, GConfKey_ProxyMode, nsnull);
++ if (!str)
++ return NS_ERROR_FAILURE;
++ PRInt32 val = -1;
++ nsCOMPtr prefs =
++ aPrefService->GetPrefs()->GetPrefUserBranch();
++ prefs->GetIntPref(MozKey_ProxyMode, &val);
++ if (val < 0)
++ return NS_ERROR_FAILURE;
++ if (!strcmp(str, "manual")) {
++ val = 1;
++ } else if (!strcmp(str, "auto")) {
++ val = 2;
++ } else if (strcmp(str, "none")) {
++ // invalid value for this gconf pref; do nothing
++ g_free(str);
++ return NS_OK;
++ } else {
++ if (val == 1 || val == 2) {
++ // We need to make it something that 'none' maps to
++ val = 0;
++ }
++ }
++ g_free(str);
++ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_ProxyMode, nsnull);
++ nsresult rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaIntPref(MozKey_ProxyMode, val, lock);
++ return rv;
++}
++static nsresult ReverseApplyProxyMode(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ PRInt32 val = -1;
++ nsCOMPtr prefs =
++ aPrefService->GetPrefs()->GetPrefUserBranch();
++ prefs->GetIntPref(MozKey_ProxyMode, &val);
++ if (val < 0)
++ return NS_ERROR_FAILURE;
++ const char* str;
++ switch (val) {
++ case 1: str = "manual"; break;
++ case 2: str = "auto"; break;
++ default: str = "none"; break;
++ }
++ gconf_client_set_string(aClient, GConfKey_ProxyMode, str, nsnull);
++ return NS_OK;
+ }
+
+-/* void getChildList (in string aStartingAt, out unsigned long aCount, [array, size_is (aCount), retval] out string aChildArray); */
+-NS_IMETHODIMP nsSystemPrefService::GetChildList(const char *aStartingAt, PRUint32 *aCount, char ***aChildArray)
++/**
++ * The relationship R is
++ * If "/apps/firefox/web/download_defaultfolder" is the empty string, then
++ * "browser.download.useDownloadDir" is false;
++ * otherwise "browser.download.useDownloadDir" is true and "browser.download.folderList"
++ * is (0 if "/apps/firefox/web/download_defaultfolder" is "Desktop";
++ * 1 if "/apps/firefox/web/download_defaultfolder" is "My Downloads";
++ * 3 if "/apps/firefox/web/download_defaultfolder" is "Home";
++ * otherwise 2 and "browser.download.dir" = "/apps/firefox/web/download_defaultfolder")
++ */
++static const char GConfKey_DownloadFolder[] = "/apps/firefox/web/download_defaultfolder";
++static const char MozKey_UseDownloadDir[] = "browser.download.useDownloadDir";
++static const char MozKey_DownloadDirType[] = "browser.download.folderList";
++static const char MozKey_DownloadDirExplicit[] = "browser.download.dir";
++static nsresult ApplyDownloadFolder(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
+ {
+- return NS_ERROR_NOT_IMPLEMENTED;
++ char* str = gconf_client_get_string(aClient, GConfKey_DownloadFolder, nsnull);
++ if (!str)
++ return NS_ERROR_FAILURE;
++ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DownloadFolder, nsnull);
++ nsresult rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_UseDownloadDir, *str != 0, lock);
++ if (NS_FAILED(rv)) {
++ g_free(str);
++ return rv;
++ }
++ PRInt32 dirType = 0;
++ if (!strcmp(str, "Desktop")) {
++ dirType = 0;
++ } else if (!strcmp(str, "My Downloads")) {
++ dirType = 1;
++ } else if (!strcmp(str, "Home")) {
++ dirType = 3;
++ } else {
++ dirType = 2;
++ }
++ // Always set all three Mozilla preferences. This is simpler and avoids
++ // problems; e.g., if the gconf value changes from "/home/rocallahan" to "Desktop"
++ // we might leave MozKey_DownloadDirType accidentally locked.
++ rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaIntPref(MozKey_DownloadDirType, dirType, lock);
++ if (NS_SUCCEEDED(rv)) {
++ rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaStringPref(MozKey_DownloadDirExplicit, str, lock);
++ }
++ g_free(str);
++ return rv;
+ }
+
+-/* void resetBranch (in string aStartingAt); */
+-NS_IMETHODIMP nsSystemPrefService::ResetBranch(const char *aStartingAt)
+-{
+- return NS_ERROR_NOT_IMPLEMENTED;
++static nsresult ReverseApplyDownloadFolder(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ PRBool useDownloadDir = PR_FALSE;
++ const char* result;
++ char* explicitStr = nsnull;
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ prefs->GetBoolPref(MozKey_UseDownloadDir, &useDownloadDir);
++ if (!useDownloadDir) {
++ result = "";
++ } else {
++ PRInt32 type = -1;
++ prefs->GetIntPref(MozKey_DownloadDirType, &type);
++ if (type < 0)
++ return NS_ERROR_FAILURE;
++ switch (type) {
++ case 0: result = "Desktop"; break;
++ case 1: result = "My Downloads"; break;
++ case 2:
++ prefs->GetCharPref(MozKey_DownloadDirExplicit, &explicitStr);
++ result = explicitStr;
++ break;
++ case 3: result = "Home"; break;
++ default:
++ NS_ERROR("Unknown download dir type");
++ return NS_ERROR_FAILURE;
++ }
++ }
++ if (!result)
++ return NS_ERROR_FAILURE;
++ gconf_client_set_string(aClient, GConfKey_DownloadFolder,
++ result, nsnull);
++ nsMemory::Free(explicitStr);
++ return NS_OK;
+ }
+
+-/* void addObserver (in string aDomain, in nsIObserver aObserver, in boolean aHoldWeak); */
+-NS_IMETHODIMP nsSystemPrefService::AddObserver(const char *aDomain, nsIObserver *aObserver, PRBool aHoldWeak)
+-{
+- nsresult rv;
+-
+- NS_ENSURE_ARG_POINTER(aDomain);
+- NS_ENSURE_ARG_POINTER(aObserver);
+-
+- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+-
+- PRUint32 prefAtom;
+- // make sure the pref name is supported
+- rv = mGConf->GetAtomForMozKey(aDomain, &prefAtom);
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- if (!mObservers) {
+- mObservers = new nsAutoVoidArray();
+- if (mObservers == nsnull)
+- return NS_ERROR_OUT_OF_MEMORY;
+- }
+-
+- SysPrefCallbackData *pCallbackData = (SysPrefCallbackData *)
+- nsMemory::Alloc(sizeof(SysPrefCallbackData));
+- if (pCallbackData == nsnull)
+- return NS_ERROR_OUT_OF_MEMORY;
+-
+- pCallbackData->bIsWeakRef = aHoldWeak;
+- pCallbackData->prefAtom = prefAtom;
+- // hold a weak reference to the observer if so requested
+- nsCOMPtr observerRef;
+- if (aHoldWeak) {
+- nsCOMPtr weakRefFactory =
+- do_QueryInterface(aObserver);
+- if (!weakRefFactory) {
+- // the caller didn't give us a object that supports weak reference.
+- // ... tell them
+- nsMemory::Free(pCallbackData);
+- return NS_ERROR_INVALID_ARG;
+- }
+- nsCOMPtr tmp = do_GetWeakReference(weakRefFactory);
+- observerRef = tmp;
++/**
++ * The relationship R is
++ * "/apps/firefox/web/disable_cookies" is true if and only if
++ * "network.cookie.cookieBehavior" is 2 ('dontUse')
++ */
++static const char GConfKey_DisableCookies[] = "/apps/firefox/web/disable_cookies";
++static const char MozKey_CookieBehavior[] = "network.cookie.cookieBehavior";
++static const char MozKey_CookieExceptions[] = "network.cookie.honorExceptions";
++static const char MozKey_CookieViewExceptions[] = "pref.privacy.disable_button.cookie_exceptions";
++static nsresult ApplyDisableCookies(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableCookies, nsnull);
++ PRInt32 behavior = -1;
++ nsCOMPtr prefs =
++ aPrefService->GetPrefs()->GetPrefUserBranch();
++ prefs->GetIntPref(MozKey_CookieBehavior, &behavior);
++ if (behavior < 0)
++ return NS_ERROR_FAILURE;
++ if (disable) {
++ behavior = 2;
+ } else {
+- observerRef = aObserver;
++ if (behavior == 2) {
++ behavior = 0;
++ }
+ }
++ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableCookies, nsnull);
++ nsresult rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_CookieExceptions, !lock, lock);
++ if (NS_FAILED(rv))
++ return rv;
++ rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_CookieViewExceptions, lock, lock);
++ if (NS_FAILED(rv))
++ return rv;
++ return aPrefService->GetPrefs()->
++ SetOverridingMozillaIntPref(MozKey_CookieBehavior, behavior, lock);
++}
++static nsresult ReverseApplyDisableCookies(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ PRInt32 behavior = -1;
++ nsCOMPtr prefs =
++ aPrefService->GetPrefs()->GetPrefUserBranch();
++ prefs->GetIntPref(MozKey_CookieBehavior, &behavior);
++ if (behavior < 0)
++ return NS_ERROR_FAILURE;
++ gconf_client_set_bool(aClient, GConfKey_DisableCookies, behavior == 2, nsnull);
++ return NS_OK;
++}
+
+- rv = mGConf->NotifyAdd(prefAtom, pCallbackData);
+- if (NS_FAILED(rv)) {
+- nsMemory::Free(pCallbackData);
+- return rv;
++static char const* windowOpenFeatures[] = {
++ "dom.disable_window_open_feature.close",
++ "dom.disable_window_open_feature.directories",
++ "dom.disable_window_open_feature.location",
++ "dom.disable_window_open_feature.menubar",
++ "dom.disable_window_open_feature.minimizable",
++ "dom.disable_window_open_feature.personalbar",
++ "dom.disable_window_open_feature.resizable",
++ "dom.disable_window_open_feature.scrollbars",
++ "dom.disable_window_open_feature.status",
++ "dom.disable_window_open_feature.titlebar",
++ "dom.disable_window_open_feature.toolbar"
++};
++/**
++ * The relationship R is
++ * "/apps/firefox/lockdown/disable_javascript_chrome" is true if and only if
++ * all of windowOpenFeatures are true
++ */
++static const char GConfKey_DisableJSChrome[] =
++ "/apps/firefox/lockdown/disable_javascript_chrome";
++static nsresult ApplyWindowOpen(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableJSChrome, nsnull);
++ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableJSChrome, nsnull);
++ PRBool curValues[NUM_ELEM(windowOpenFeatures)];
++ PRUint32 i;
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ PRBool allDisabled = PR_TRUE;
++ for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
++ nsresult rv = prefs->GetBoolPref(windowOpenFeatures[i], &curValues[i]);
++ if (NS_FAILED(rv))
++ return rv;
++ if (!curValues[i]) {
++ allDisabled = PR_FALSE;
++ }
++ }
++ for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
++ PRBool newVal = curValues[i];
++ if (disable) {
++ newVal = PR_TRUE;
++ } else if (allDisabled) {
++ // If all disable-window-open-feature prefs are currently
++ // PR_TRUE, then we need to set at least one of them to
++ // PR_FALSE. Set all of them to PR_FALSE.
++ newVal = PR_FALSE;
++ } // If at least one disable-window-open-feature pref is
++ // currently PR_FALSE, then we don't need to change anything
++ // when the gconf pref says don't disable
++ nsresult rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(windowOpenFeatures[i], newVal, lock);
++ if (NS_FAILED(rv))
++ return rv;
+ }
+-
+- pCallbackData->observer = observerRef;
+- NS_ADDREF(pCallbackData->observer);
+-
+- mObservers->AppendElement(pCallbackData);
+ return NS_OK;
+ }
+
+-/* void removeObserver (in string aDomain, in nsIObserver aObserver); */
+-NS_IMETHODIMP nsSystemPrefService::RemoveObserver(const char *aDomain, nsIObserver *aObserver)
++static nsresult ReverseApplyWindowOpen(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
+ {
+- nsresult rv;
+-
+- NS_ENSURE_ARG_POINTER(aDomain);
+- NS_ENSURE_ARG_POINTER(aObserver);
+- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+-
+- if (!mObservers)
+- return NS_OK;
+-
+- PRUint32 prefAtom;
+- // make sure the pref name is supported
+- rv = mGConf->GetAtomForMozKey(aDomain, &prefAtom);
+- NS_ENSURE_SUCCESS(rv, rv);
+-
+- // need to find the index of observer, so we can remove it
+- PRIntn count = mObservers->Count();
+- if (count <= 0)
+- return NS_OK;
+-
+- PRIntn i;
+- SysPrefCallbackData *pCallbackData;
+- for (i = 0; i < count; ++i) {
+- pCallbackData = (SysPrefCallbackData *)mObservers->ElementAt(i);
+- if (pCallbackData) {
+- nsCOMPtr observerRef;
+- if (pCallbackData->bIsWeakRef) {
+- nsCOMPtr weakRefFactory =
+- do_QueryInterface(aObserver);
+- if (weakRefFactory) {
+- nsCOMPtr tmp =
+- do_GetWeakReference(aObserver);
+- observerRef = tmp;
+- }
+- }
+- if (!observerRef)
+- observerRef = aObserver;
+-
+- if (pCallbackData->observer == observerRef &&
+- pCallbackData->prefAtom == prefAtom) {
+- rv = mGConf->NotifyRemove(prefAtom, pCallbackData);
+- if (NS_SUCCEEDED(rv)) {
+- mObservers->RemoveElementAt(i);
+- NS_RELEASE(pCallbackData->observer);
+- nsMemory::Free(pCallbackData);
+- }
+- return rv;
+- }
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ PRBool allDisabled = PR_TRUE;
++ PRBool curValues[NUM_ELEM(windowOpenFeatures)];
++ for (PRUint32 i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
++ nsresult rv = prefs->GetBoolPref(windowOpenFeatures[i], &curValues[i]);
++ if (NS_FAILED(rv))
++ return rv;
++ if (!curValues[i]) {
++ allDisabled = PR_FALSE;
+ }
+ }
++ gconf_client_set_bool(aClient, GConfKey_DisableJSChrome, allDisabled, nsnull);
+ return NS_OK;
+ }
+
+-void
+-nsSystemPrefService::OnPrefChange(PRUint32 aPrefAtom, void *aData)
+-{
+- if (!mInitialized)
+- return;
++/**
++ * The relationship R is
++ * If "/apps/firefox/lockdown/disable_unsafe_protocol" is true then
++ * -- "network.protocol-handler.blocked-default" is true
++ * -- "network.protocol-handler.blocked.XYZ" is false if and only if
++ * XYZ is a builtin non-disablable protocol or in
++ * "/apps/firefox/lockdown/additional_safe_protocols"
++ * AND if "/apps/firefox/lockdown/disable_unsafe_protocol" is false then
++ * -- "network.protocol-handler.blocked-default" is false
++ * -- if "network.protocol-handler.blocked.XYZ" exists then it is false
++ */
++static const char GConfKey_DisableUnsafeProtocols[] =
++ "/apps/firefox/lockdown/disable_unsafe_protocol";
++static const char GConfKey_AdditionalSafeProtocols[] =
++ "/apps/firefox/lockdown/additional_safe_protocols";
++static const char MozKey_BlockedDefault[] =
++ "network.protocol-handler.blocked-default";
++static const char MozKey_BlockedPrefix[] =
++ "network.protocol-handler.blocked.";
++static const char* nonDisablableBuiltinProtocols[] =
++ { "about", "data", "jar", "keyword", "resource", "viewsource",
++ "chrome", "moz-icon", "javascript", "file" };
++static PRBool FindString(const char** aList, PRInt32 aCount,
++ const char* aStr)
++{
++ for (PRInt32 i = 0; i < aCount; ++i) {
++ if (!strcmp(aStr, aList[i]))
++ return PR_TRUE;
++ }
++ return PR_FALSE;
++}
++typedef nsDataHashtable StringSet;
++/** Collect the set of protocol names that we want to set preferences for */
++static nsresult AddAllProtocols(nsSystemPrefService* aPrefService,
++ const char* aSafeProtocols,
++ StringSet* aProtocolSet,
++ StringSet* aSafeSet)
++{
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ PRUint32 childCount;
++ char **childArray = nsnull;
++ nsresult rv = prefs->GetChildList(MozKey_BlockedPrefix, &childCount, &childArray);
++ if (NS_FAILED(rv))
++ return rv;
++ PRUint32 i;
++ for (i = 0; i < childCount; ++i) {
++ nsDependentCString tmp(childArray[i] + NUM_ELEM(MozKey_BlockedPrefix)-1);
++ aProtocolSet->Put(tmp, 1); // copies
++ }
++ for (i = 0; i < NUM_ELEM(nonDisablableBuiltinProtocols); ++i) {
++ nsDependentCString tmp(nonDisablableBuiltinProtocols[i]);
++ aProtocolSet->Put(tmp, 1);
++ }
++ i = 0;
++ while (aSafeProtocols[i]) {
++ const char* nextComma = strchr(aSafeProtocols+i, ',');
++ PRUint32 tokLen = nextComma ? nextComma - (aSafeProtocols+i)
++ : strlen(aSafeProtocols+i);
++ nsCAutoString tok(aSafeProtocols+i, tokLen);
++ aProtocolSet->Put(tok, 1);
++ aSafeSet->Put(tok, 1);
++ if (nextComma) {
++ i = nextComma - aSafeProtocols + 1;
++ } else {
++ break;
++ }
++ }
++ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
++ return NS_OK;
++}
+
+- SysPrefCallbackData *pData = (SysPrefCallbackData *)aData;
+- if (pData->prefAtom != aPrefAtom)
+- return;
++struct ProtocolPrefClosure {
++ StringSet safeProtocolSet;
++ nsIPrefBranch2* prefs;
++ nsISystemPref* prefSetter;
++ PRPackedBool disableUnsafe;
++ PRPackedBool lock;
++};
+
+- nsCOMPtr observer;
+- if (pData->bIsWeakRef) {
+- nsCOMPtr weakRef =
+- do_QueryInterface(pData->observer);
+- if(weakRef)
+- observer = do_QueryReferent(weakRef);
+- if (!observer) {
+- // this weak referenced observer went away, remove it from the list
+- nsresult rv = mGConf->NotifyRemove(aPrefAtom, pData);
+- if (NS_SUCCEEDED(rv)) {
+- mObservers->RemoveElement(pData);
+- NS_RELEASE(pData->observer);
+- nsMemory::Free(pData);
++static PLDHashOperator PR_CALLBACK SetProtocolPref(const nsACString& aKey,
++ int aItem,
++ void* aClosure)
++{
++ ProtocolPrefClosure* closure = static_cast(aClosure);
++ const nsCString& protocol = PromiseFlatCString(aKey);
++ PRBool blockProtocol = PR_FALSE;
++ if (closure->disableUnsafe &&
++ !FindString(nonDisablableBuiltinProtocols,
++ NUM_ELEM(nonDisablableBuiltinProtocols), protocol.get()) &&
++ !closure->safeProtocolSet.Get(aKey, nsnull)) {
++ blockProtocol = PR_TRUE;
++ }
++
++ nsCAutoString prefName;
++ prefName.Append(MozKey_BlockedPrefix);
++ prefName.Append(protocol);
++ closure->prefSetter->SetOverridingMozillaBoolPref(prefName.get(), blockProtocol,
++ closure->lock);
++ return PL_DHASH_NEXT;
++}
++static nsresult ApplyUnsafeProtocols(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableUnsafeProtocols, nsnull)
++ || !gconf_client_key_is_writable(aClient, GConfKey_AdditionalSafeProtocols, nsnull);
++ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableUnsafeProtocols, nsnull);
++ char* protocols = gconf_client_get_string(aClient, GConfKey_AdditionalSafeProtocols, nsnull);
++ if (!protocols)
++ return NS_ERROR_FAILURE;
++ nsresult rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_BlockedDefault, disable, lock);
++ StringSet protocolSet;
++ ProtocolPrefClosure closure;
++ protocolSet.Init();
++ closure.safeProtocolSet.Init();
++ if (NS_SUCCEEDED(rv)) {
++ rv = AddAllProtocols(aPrefService, protocols, &protocolSet,
++ &closure.safeProtocolSet);
++ }
++ if (NS_SUCCEEDED(rv)) {
++ closure.disableUnsafe = disable;
++ closure.lock = lock;
++ closure.prefSetter = aPrefService->GetPrefs();
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ closure.prefs = prefs;
++ protocolSet.EnumerateRead(SetProtocolPref, &closure);
++ }
++ g_free(protocols);
++ return rv;
++}
++
++static nsresult ReverseApplyUnsafeProtocols(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ PRBool blockedDefault;
++ nsresult rv = prefs->GetBoolPref(MozKey_BlockedDefault, &blockedDefault);
++ if (NS_FAILED(rv))
++ return rv;
++ nsCAutoString enabledProtocols;
++ PRUint32 childCount;
++ char **childArray = nsnull;
++ rv = prefs->GetChildList(MozKey_BlockedPrefix, &childCount, &childArray);
++ if (NS_FAILED(rv))
++ return rv;
++ for (PRUint32 i = 0; i < childCount; ++i) {
++ PRBool val = PR_FALSE;
++ prefs->GetBoolPref(childArray[i], &val);
++ if (val) {
++ if (enabledProtocols.Length() > 0) {
++ enabledProtocols.Append(',');
+ }
+- return;
++ enabledProtocols.Append(childArray[i] + NUM_ELEM(MozKey_BlockedPrefix)-1);
+ }
+ }
+- else
+- observer = do_QueryInterface(pData->observer);
++ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
++ gconf_client_set_bool(aClient, GConfKey_DisableUnsafeProtocols, blockedDefault, nsnull);
++ gconf_client_set_string(aClient, GConfKey_AdditionalSafeProtocols,
++ enabledProtocols.get(), nsnull);
++ return NS_OK;
++}
+
+- if (observer)
+- observer->Observe(static_cast(this),
+- NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID,
+- NS_ConvertUTF8toUTF16(mGConf->GetMozKey(aPrefAtom)).
+- get());
++/**
++ * Set config.lockdown.setwallpaper if and only if
++ * /desktop/gnome/background/picture_filename is write-only. Always
++ * lock it.
++ */
++static const char MozKey_LockdownWallpaper[] = "config.lockdown.setwallpaper";
++static const char GConfKey_WallpaperSetting[] =
++ "/desktop/gnome/background/picture_filename";
++static nsresult ApplyWallpaper(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ PRBool canSetWallpaper =
++ gconf_client_key_is_writable(aClient, GConfKey_WallpaperSetting, nsnull);
++ return aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_LockdownWallpaper,
++ !canSetWallpaper, PR_TRUE);
++}
++// No ReverseApplyWallpaper because this Mozilla pref can never be
++// modified
++
++/**
++ * The relationship R is
++ * "signon.rememberSignons" is true if and only if "/apps/firefox/web/disable_save_password"
++ * is false.
++ */
++static const char MozKey_RememberSignons[] = "signon.rememberSignons";
++static const char GConfKey_DisableSavePassword[] = "/apps/firefox/web/disable_save_password";
++static nsresult ApplyDisableSavePassword(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisableSavePassword, nsnull);
++ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisableSavePassword, nsnull);
++ return aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_RememberSignons, !disable, lock);
++}
++
++static nsresult ReverseApplyDisableSavePassword(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ PRBool remember;
++ nsresult rv = prefs->GetBoolPref(MozKey_RememberSignons, &remember);
++ if (NS_FAILED(rv))
++ return rv;
++ gconf_client_set_bool(aClient, GConfKey_DisableSavePassword, !remember, nsnull);
++ return NS_OK;
+ }
+
+-/*************************************************************
+- * GConfProxy
++/**
++ * The relationship R is
++ * "permissions.default.image" is 1 (nsIPermissionManager::ALLOW_ACTION) if and only if
++ * "/apps/firefox/web/images_load" is 0, AND
++ * "permissions.default.image" is 2 (nsIPermissionManager::DENY_ACTION) if and only if
++ * "/apps/firefox/web/images_load" is 2, AND
++ * "permissions.default.image" is 3 if and only if "/apps/firefox/web/images_load" is 1
+ *
+- ************************************************************/
+-
+-struct GConfFuncListType {
+- const char *FuncName;
+- PRFuncPtr FuncPtr;
+-};
+-
+-struct PrefNamePair {
+- const char *mozPrefName;
+- const char *gconfPrefName;
+-};
+-
+-const char
+-GConfProxy::sPrefGConfKey[] = "accessibility.unix.gconf2.shared-library";
+-const char GConfProxy::sDefaultLibName1[] = "libgconf-2.so.4";
+-const char GConfProxy::sDefaultLibName2[] = "libgconf-2.so";
+-
+-#define GCONF_FUNCS_POINTER_BEGIN \
+- static GConfFuncListType sGConfFuncList[] = {
+-#define GCONF_FUNCS_POINTER_ADD(func_name) \
+- {func_name, nsnull},
+-#define GCONF_FUNCS_POINTER_END \
+- {nsnull, nsnull}, };
+-
+-GCONF_FUNCS_POINTER_BEGIN
+- GCONF_FUNCS_POINTER_ADD("gconf_client_get_default") // 0
+- GCONF_FUNCS_POINTER_ADD("gconf_client_get_bool") // 1
+- GCONF_FUNCS_POINTER_ADD("gconf_client_get_string") //2
+- GCONF_FUNCS_POINTER_ADD("gconf_client_get_int") //3
+- GCONF_FUNCS_POINTER_ADD("gconf_client_notify_add") //4
+- GCONF_FUNCS_POINTER_ADD("gconf_client_notify_remove") //5
+- GCONF_FUNCS_POINTER_ADD("gconf_client_add_dir") //6
+- GCONF_FUNCS_POINTER_ADD("gconf_client_remove_dir") //7
+- GCONF_FUNCS_POINTER_ADD("gconf_entry_get_value") //8
+- GCONF_FUNCS_POINTER_ADD("gconf_entry_get_key") //9
+- GCONF_FUNCS_POINTER_ADD("gconf_value_get_bool") //10
+- GCONF_FUNCS_POINTER_ADD("gconf_value_get_string") //11
+- GCONF_FUNCS_POINTER_ADD("gconf_value_get_int") //12
+- GCONF_FUNCS_POINTER_ADD("gconf_client_get_list") //13
+-GCONF_FUNCS_POINTER_END
+-
+-/////////////////////////////////////////////////////////////////////////////
+-// the list is the mapping table, between mozilla prefs and gconf prefs
+-// It is expected to include all the pref pairs that are related in mozilla
+-// and gconf.
+-//
+-// Note: the prefs listed here are not neccessarily be read from gconf, they
+-// are the prefs that could be read from gconf. Mozilla has another
+-// list (see sSysPrefList in nsSystemPref.cpp) that decide which prefs
+-// are really read.
+-//////////////////////////////////////////////////////////////////////////////
+-
+-static const PrefNamePair sPrefNameMapping[] = {
+-#include "gconf_pref_list.inc"
+- {nsnull, nsnull},
+-};
+-
+-PRBool PR_CALLBACK
+-gconfDeleteObserver(void *aElement, void *aData) {
+- nsMemory::Free(aElement);
+- return PR_TRUE;
++ * Also, we set pref.advanced.images.disable_button.view_image iff
++ * /apps/firefox/web/images_load is read-only
++ * And we set permissions.default.honorExceptions iff
++ * /apps/firefox/web/images_load is not read-only
++ */
++static const char MozKey_ImagePermissions[] = "permissions.default.image";
++static const char MozKey_ImageExceptions[] = "permissions.honorExceptions.image";
++static const char MozKey_ImageViewExceptions[] = "pref.advanced.images.disable_button.view_image";
++static const char GConfKey_LoadImages[] = "/apps/firefox/web/images_load";
++static nsresult ApplyLoadImages(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_LoadImages, nsnull);
++ // 0 == accept, 1 == no-foreign, 2 == reject
++ gint setting = gconf_client_get_int(aClient, GConfKey_LoadImages, nsnull);
++ PRInt32 pref;
++ switch (setting) {
++ case 0: pref = nsIPermissionManager::ALLOW_ACTION; break;
++ case 2: pref = nsIPermissionManager::DENY_ACTION; break;
++ case 1: pref = 3; break;
++ default: return NS_ERROR_FAILURE;
++ }
++ nsresult rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_ImageExceptions, !lock, lock);
++ if (NS_FAILED(rv))
++ return rv;
++ rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_ImageViewExceptions, lock, lock);
++ if (NS_FAILED(rv))
++ return rv;
++ return aPrefService->GetPrefs()->
++ SetOverridingMozillaIntPref(MozKey_ImagePermissions, pref, lock);
+ }
+
+-GConfProxy::GConfProxy(nsSystemPrefService *aSysPrefService):
+- mGConfClient(nsnull),
+- mGConfLib(nsnull),
+- mInitialized(PR_FALSE),
+- mSysPrefService(aSysPrefService),
+- mObservers(nsnull)
++static nsresult ReverseApplyLoadImages(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
+ {
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ PRInt32 pref;
++ nsresult rv = prefs->GetIntPref(MozKey_ImagePermissions, &pref);
++ if (NS_FAILED(rv))
++ return rv;
++ gint setting;
++ switch (pref) {
++ case nsIPermissionManager::ALLOW_ACTION: setting = 0; break;
++ case nsIPermissionManager::DENY_ACTION: setting = 2; break;
++ case 3: setting = 1; break;
++ default: return NS_ERROR_FAILURE;
++ }
++ gconf_client_set_int(aClient, GConfKey_LoadImages, setting, nsnull);
++ return NS_OK;
+ }
+
+-GConfProxy::~GConfProxy()
++/**
++ * The relationship R is
++ * "/apps/firefox/web/disable_popups" is true if and only if
++ * "dom.disable_open_during_load" is true
++ * AND if "/apps/firefox/web/disable_popups" is true then
++ * "privacy.popups.showBrowserMessage" is false.
++ */
++static const char MozKey_DisablePopups[] = "dom.disable_open_during_load";
++static const char MozKey_DisableBrowserPopupMessage[] = "privacy.popups.showBrowserMessage";
++static const char GConfKey_DisablePopups[] = "/apps/firefox/web/disable_popups";
++static nsresult ApplyDisablePopups(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
++{
++ PRBool lock = !gconf_client_key_is_writable(aClient, GConfKey_DisablePopups, nsnull);
++ gboolean disable = gconf_client_get_bool(aClient, GConfKey_DisablePopups, nsnull);
++ nsresult rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_DisablePopups, disable, lock);
++ if (NS_SUCCEEDED(rv)) {
++ if (disable) {
++ rv = aPrefService->GetPrefs()->
++ SetOverridingMozillaBoolPref(MozKey_DisableBrowserPopupMessage, PR_TRUE, lock);
++ } else {
++ rv = aPrefService->GetPrefs()->
++ StopOverridingMozillaPref(MozKey_DisableBrowserPopupMessage);
++ }
++ }
++ return rv;
++}
++
++static nsresult ReverseApplyDisablePopups(nsSystemPrefService* aPrefService,
++ GConfClient* aClient)
+ {
+- if (mGConfClient)
+- g_object_unref(G_OBJECT(mGConfClient));
++ nsCOMPtr prefs = aPrefService->GetPrefs()->GetPrefUserBranch();
++ PRBool disabled;
++ nsresult rv = prefs->GetBoolPref(MozKey_DisablePopups, &disabled);
++ if (NS_FAILED(rv))
++ return rv;
++ gconf_client_set_bool(aClient, GConfKey_DisablePopups, disabled, nsnull);
++ return NS_OK;
++}
+
+- if (mObservers) {
+- (void)mObservers->EnumerateForwards(gconfDeleteObserver, nsnull);
+- delete mObservers;
+- }
++static ComplexGConfPrefMapping sComplexGConfPrefMappings[] = {
++ {GConfKey_TrustedURIs, ApplyTrustedURIs},
++ {GConfKey_DelegationURIs, ApplyDelegationURIs},
++ {GConfKey_IgnoreHosts, ApplyIgnoreHosts},
++ {GConfKey_ProxyMode, ApplyProxyMode},
++ {GConfKey_DownloadFolder, ApplyDownloadFolder},
++ {GConfKey_DisableCookies, ApplyDisableCookies},
++ {GConfKey_DisableJSChrome, ApplyWindowOpen},
++ {GConfKey_DisableUnsafeProtocols, ApplyUnsafeProtocols},
++ {GConfKey_AdditionalSafeProtocols, ApplyUnsafeProtocols},
++ {GConfKey_WallpaperSetting, ApplyWallpaper},
++ {GConfKey_DisableSavePassword, ApplyDisableSavePassword},
++ {GConfKey_LoadImages, ApplyLoadImages},
++ {GConfKey_DisablePopups, ApplyDisablePopups}
++};
++static ComplexMozPrefMapping sComplexMozPrefMappings[] = {
++ {MozKey_TrustedURIs, ReverseApplyTrustedURIs},
++ {MozKey_DelegationURIs, ReverseApplyDelegationURIs},
++ {MozKey_IgnoreHosts, ReverseApplyIgnoreHosts},
++ {MozKey_ProxyMode, ReverseApplyProxyMode},
++ {MozKey_UseDownloadDir, ReverseApplyDownloadFolder},
++ {MozKey_DownloadDirType, ReverseApplyDownloadFolder},
++ {MozKey_DownloadDirExplicit, ReverseApplyDownloadFolder},
++ {MozKey_CookieBehavior, ReverseApplyDisableCookies},
++ {MozKey_RememberSignons, ReverseApplyDisableSavePassword},
++ {MozKey_ImagePermissions, ReverseApplyLoadImages},
++ {MozKey_DisablePopups, ReverseApplyDisablePopups}
++};
++// The unsafe protocol preferences are handled specially because
++// they affect an unknown number of Mozilla preferences
++// Window opener permissions are also handled specially so we don't have to
++// repeat the windowOpenFeatures list.
++
++static PR_CALLBACK void GConfSimpleNotification(GConfClient* client,
++ guint cnxn_id,
++ GConfEntry *entry,
++ gpointer user_data)
++{
++ nsSystemPrefService* service = static_cast(user_data);
++ SimplePrefMapping* map = static_cast(
++ service->GetSimpleCallbackData(cnxn_id));
++ NS_ASSERTION(map, "Can't find mapping for callback");
++ if (!map)
++ return;
+
+- // bug 379666: can't unload GConf-2 since it registers atexit handlers
+- //PR_UnloadLibrary(mGConfLib);
++ ApplySimpleMapping(map, service->GetPrefs(), client);
+ }
+
+-PRBool
+-GConfProxy::Init()
+-{
+- SYSPREF_LOG(("GConfProxy:: Init GConfProxy\n"));
+- if (!mSysPrefService)
+- return PR_FALSE;
+- if (mInitialized)
+- return PR_TRUE;
++static PR_CALLBACK void GConfComplexNotification(GConfClient* client,
++ guint cnxn_id,
++ GConfEntry *entry,
++ gpointer user_data)
++{
++ nsSystemPrefService* service = static_cast(user_data);
++ ComplexGConfPrefMapping* map = static_cast(
++ service->GetComplexCallbackData(cnxn_id));
++ NS_ASSERTION(map, "Can't find mapping for callback");
++ if (!map)
++ return;
+
+- nsCOMPtr pref = do_GetService(NS_PREF_CONTRACTID);
+- if (!pref)
+- return PR_FALSE;
++ map->callback(service, GetGConf());
++}
+
+- nsXPIDLCString gconfLibName;
+- nsresult rv;
++static const char GConfKey_Homepage_Url[] =
++ "/apps/firefox/general/homepage_url";
+
+- //check if gconf-2 library is given in prefs
+- rv = pref->GetCharPref(sPrefGConfKey, getter_Copies(gconfLibName));
+- if (NS_SUCCEEDED(rv)) {
+- //use the library name in the preference
+- SYSPREF_LOG(("GConf library in prefs is %s\n", gconfLibName.get()));
+- mGConfLib = PR_LoadLibrary(gconfLibName.get());
+- }
+- else {
+- SYSPREF_LOG(("GConf library not specified in prefs, try the default: "
+- "%s and %s\n", sDefaultLibName1, sDefaultLibName2));
+- mGConfLib = PR_LoadLibrary(sDefaultLibName1);
+- if (!mGConfLib)
+- mGConfLib = PR_LoadLibrary(sDefaultLibName2);
++nsresult nsSystemPrefService::LoadSystemPreferences(nsISystemPref* aPrefs)
++{
++ mPref = aPrefs;
++
++ GConfClient* client = GetGConf();
++ PRUint32 i;
++ nsCOMPtr userPrefs = aPrefs->GetPrefUserBranch();
++
++ // Update gconf settings with any Mozilla settings that have
++ // changed from the default. Do it before we register our
++ // gconf notifications.
++ for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
++ gconf_client_add_dir(client, sSimplePrefMappings[i].gconfPrefName,
++ GCONF_CLIENT_PRELOAD_NONE, nsnull);
++
++ PRBool hasUserPref = PR_FALSE;
++ nsresult rv =
++ userPrefs->PrefHasUserValue(sSimplePrefMappings[i].mozPrefName,
++ &hasUserPref);
++ if (NS_FAILED(rv))
++ return rv;
++ if (hasUserPref && sSimplePrefMappings[i].allowWritesFromMozilla &&
++ gconf_client_key_is_writable(client,
++ sSimplePrefMappings[i].gconfPrefName,
++ nsnull)) {
++ rv = ReverseApplySimpleMapping(&sSimplePrefMappings[i],
++ aPrefs, client);
++ if (NS_FAILED(rv))
++ return rv;
++ }
+ }
+-
+- if (!mGConfLib) {
+- SYSPREF_LOG(("Fail to load GConf library\n"));
+- return PR_FALSE;
++ for (i = 0; i < NUM_ELEM(sComplexGConfPrefMappings); ++i) {
++ gconf_client_add_dir(client, sComplexGConfPrefMappings[i].gconfPrefName,
++ GCONF_CLIENT_PRELOAD_NONE, nsnull);
++ }
++ ComplexMozPrefChanged lastMozCallback = nsnull;
++ for (i = 0; i < NUM_ELEM(sComplexMozPrefMappings); ++i) {
++ PRBool hasUserPref = PR_FALSE;
++ nsresult rv =
++ userPrefs->PrefHasUserValue(sComplexMozPrefMappings[i].mozPrefName,
++ &hasUserPref);
++ if (NS_FAILED(rv))
++ return rv;
++ if (hasUserPref) {
++ ComplexMozPrefChanged cb = sComplexMozPrefMappings[i].callback;
++ if (cb != lastMozCallback) {
++ cb(this, client);
++ lastMozCallback = cb;
++ }
++ }
+ }
+-
+- //check every func we need in the gconf library
+- GConfFuncListType *funcList;
+- PRFuncPtr func;
+- for (funcList = sGConfFuncList; funcList->FuncName; ++funcList) {
+- func = PR_FindFunctionSymbol(mGConfLib, funcList->FuncName);
+- if (!func) {
+- SYSPREF_LOG(("Check GConf Func Error: %s", funcList->FuncName));
+- goto init_failed_unload;
++
++ // Register simple mappings and callbacks
++ for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
++ guint cx = gconf_client_notify_add(client,
++ sSimplePrefMappings[i].gconfPrefName,
++ GConfSimpleNotification, this,
++ nsnull, nsnull);
++ mGConfSimpleCallbacks.Put(cx, &sSimplePrefMappings[i]);
++ nsresult rv = ApplySimpleMapping(&sSimplePrefMappings[i], aPrefs, client);
++ if (NS_FAILED(rv))
++ return rv;
++ }
++
++ ComplexGConfPrefChanged lastCallback = nsnull;
++ for (i = 0; i < NUM_ELEM(sComplexGConfPrefMappings); ++i) {
++ guint cx = gconf_client_notify_add(client,
++ sComplexGConfPrefMappings[i].gconfPrefName,
++ GConfComplexNotification, this,
++ nsnull, nsnull);
++ mGConfComplexCallbacks.Put(cx, &sComplexGConfPrefMappings[i]);
++ ComplexGConfPrefChanged cb = sComplexGConfPrefMappings[i].callback;
++ if (cb != lastCallback) {
++ cb(this, client);
++ lastCallback = cb;
+ }
+- funcList->FuncPtr = func;
+ }
+
+- InitFuncPtrs();
+-
+- mGConfClient = GConfClientGetDefault();
+-
+- // Don't unload past this point, since GConf's initialization of ORBit
+- // causes atexit handlers to be registered.
++ if (!gconf_client_get(client, GConfKey_DisablePopups, nsnull))
++ {
++ gconf_client_set_bool(client, GConfKey_DisablePopups, true, nsnull);
++ }
+
+- if (!mGConfClient) {
+- SYSPREF_LOG(("Fail to Get default gconf client\n"));
+- goto init_failed;
++ if (!gconf_client_get(client, GConfKey_Homepage_Url, nsnull))
++ {
++ gconf_client_set_string(client, GConfKey_Homepage_Url, "", nsnull);
+ }
+- mInitialized = PR_TRUE;
+- return PR_TRUE;
+
+- init_failed_unload:
+- PR_UnloadLibrary(mGConfLib);
+- init_failed:
+- mGConfLib = nsnull;
+- return PR_FALSE;
+-}
++ ApplyUnsafeProtocols(this, client);
+
+-nsresult
+-GConfProxy::GetBoolPref(const char *aMozKey, PRBool *retval)
+-{
+- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+- *retval = GConfClientGetBool(mGConfClient, MozKey2GConfKey(aMozKey), NULL);
+ return NS_OK;
+ }
+
+-nsresult
+-GConfProxy::GetCharPref(const char *aMozKey, char **retval)
++nsresult nsSystemPrefService::NotifyMozillaPrefChanged(const char* aPrefName)
+ {
+- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+-
+- const gchar *gconfkey = MozKey2GConfKey(aMozKey);
+-
+- if (!strcmp (aMozKey, "network.proxy.no_proxies_on")) {
+- GSList *s;
+- nsCString noproxy;
+- GSList *gslist = GConfClientGetList(mGConfClient, gconfkey,
+- GCONF_VALUE_STRING, NULL);
++ PRUint32 i;
++ GConfClient* client = GetGConf();
+
+- for (s = gslist; s; s = g_slist_next(s)) {
+- noproxy += (char *)s->data;
+- noproxy += ", ";
+- g_free ((char *)s->data);
++ for (i = 0; i < NUM_ELEM(sSimplePrefMappings); ++i) {
++ if (!strcmp(aPrefName, sSimplePrefMappings[i].mozPrefName)) {
++ ReverseApplySimpleMapping(&sSimplePrefMappings[i],
++ mPref, client);
+ }
+- g_slist_free (gslist);
++ }
+
+- *retval = PL_strdup(noproxy.get());
+- } else {
+- gchar *str = GConfClientGetString(mGConfClient, gconfkey, NULL);
+- if (str) {
+- *retval = PL_strdup(str);
+- g_free (str);
++ for (i = 0; i < NUM_ELEM(sComplexMozPrefMappings); ++i) {
++ if (!strcmp(aPrefName, sComplexMozPrefMappings[i].mozPrefName)) {
++ sComplexMozPrefMappings[i].callback(this, client);
+ }
+ }
+
+- return NS_OK;
+-}
+-
+-nsresult
+-GConfProxy::GetIntPref(const char *aMozKey, PRInt32 *retval)
+-{
+- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+- if (strcmp (aMozKey, "network.proxy.type") == 0) {
+- gchar *str;
+-
+- str = GConfClientGetString(mGConfClient,
+- MozKey2GConfKey (aMozKey), NULL);
+-
+- if (str) {
+- if (strcmp (str, "manual") == 0)
+- *retval = 1;
+- else if (strcmp (str, "auto") == 0)
+- *retval = 2;
+- else
+- *retval = 0;
+-
+- g_free (str);
+- } else
+- *retval = 0;
+- } else {
+- *retval = GConfClientGetInt(mGConfClient,
+- MozKey2GConfKey(aMozKey), NULL);
++ for (i = 0; i < NUM_ELEM(windowOpenFeatures); ++i) {
++ if (!strcmp(aPrefName, windowOpenFeatures[i])) {
++ ReverseApplyWindowOpen(this, client);
++ }
+ }
+
++ ReverseApplyUnsafeProtocols(this, client);
++
+ return NS_OK;
+ }
+
+-nsresult
+-GConfProxy::NotifyAdd (PRUint32 aAtom, void *aUserData)
++static PLDHashOperator PR_CALLBACK UnregisterSimple(const PRUint32& aKey,
++ SimplePrefMapping* aData,
++ void* aClosure)
+ {
+- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+-
+- const char *gconfKey = GetGConfKey(aAtom);
+- if (!gconfKey)
+- return NS_ERROR_FAILURE;
+-
+- if (!mObservers) {
+- mObservers = new nsAutoVoidArray();
+- if (mObservers == nsnull)
+- return NS_ERROR_OUT_OF_MEMORY;
+- }
+-
+- GConfCallbackData *pData = (GConfCallbackData *)
+- nsMemory::Alloc(sizeof(GConfCallbackData));
+- NS_ENSURE_TRUE(pData, NS_ERROR_OUT_OF_MEMORY);
+-
+- pData->proxy = this;
+- pData->userData = aUserData;
+- pData->atom = aAtom;
+- mObservers->AppendElement(pData);
+-
+- GConfClientAddDir(mGConfClient, gconfKey,
+- 0, // GCONF_CLIENT_PRELOAD_NONE, don't preload anything
+- NULL);
+-
+- pData->notifyId = GConfClientNotifyAdd(mGConfClient, gconfKey,
+- gconf_key_listener, pData,
+- NULL, NULL);
+- return NS_OK;
++ GConfClient* client = GetGConf();
++ gconf_client_notify_remove(client, aKey);
++ gconf_client_remove_dir(client, aData->gconfPrefName, nsnull);
++ return PL_DHASH_NEXT;
+ }
+
+-nsresult
+-GConfProxy::NotifyRemove (PRUint32 aAtom, const void *aUserData)
++static PLDHashOperator PR_CALLBACK UnregisterComplex(const PRUint32& aKey,
++ ComplexGConfPrefMapping* aData,
++ void* aClosure)
+ {
+- NS_ENSURE_TRUE(mInitialized, NS_ERROR_FAILURE);
+-
+- PRIntn count = mObservers->Count();
+- if (count <= 0)
+- return NS_OK;
+-
+- PRIntn i;
+- GConfCallbackData *pData;
+- for (i = 0; i < count; ++i) {
+- pData = (GConfCallbackData *)mObservers->ElementAt(i);
+- if (pData && pData->atom == aAtom && pData->userData == aUserData) {
+- GConfClientNotifyRemove(mGConfClient, pData->notifyId);
+- GConfClientRemoveDir(mGConfClient,
+- GetGConfKey(pData->atom), NULL);
+- mObservers->RemoveElementAt(i);
+- nsMemory::Free(pData);
+- break;
+- }
+- }
+- return NS_OK;
++ GConfClient* client = GetGConf();
++ gconf_client_notify_remove(client, aKey);
++ gconf_client_remove_dir(client, aData->gconfPrefName, nsnull);
++ return PL_DHASH_NEXT;
+ }
+
+-void
+-GConfProxy::InitFuncPtrs()
+-{
+- //gconf client funcs
+- GConfClientGetDefault =
+- (GConfClientGetDefaultType) sGConfFuncList[0].FuncPtr;
+- GConfClientGetBool =
+- (GConfClientGetBoolType) sGConfFuncList[1].FuncPtr;
+- GConfClientGetString =
+- (GConfClientGetStringType) sGConfFuncList[2].FuncPtr;
+- GConfClientGetInt =
+- (GConfClientGetIntType) sGConfFuncList[3].FuncPtr;
+- GConfClientNotifyAdd =
+- (GConfClientNotifyAddType) sGConfFuncList[4].FuncPtr;
+- GConfClientNotifyRemove =
+- (GConfClientNotifyRemoveType) sGConfFuncList[5].FuncPtr;
+- GConfClientAddDir =
+- (GConfClientAddDirType) sGConfFuncList[6].FuncPtr;
+- GConfClientRemoveDir =
+- (GConfClientRemoveDirType) sGConfFuncList[7].FuncPtr;
+-
+- //gconf entry funcs
+- GConfEntryGetValue = (GConfEntryGetValueType) sGConfFuncList[8].FuncPtr;
+- GConfEntryGetKey = (GConfEntryGetKeyType) sGConfFuncList[9].FuncPtr;
+-
+- //gconf value funcs
+- GConfValueGetBool = (GConfValueGetBoolType) sGConfFuncList[10].FuncPtr;
+- GConfValueGetString = (GConfValueGetStringType) sGConfFuncList[11].FuncPtr;
+- GConfValueGetInt = (GConfValueGetIntType) sGConfFuncList[12].FuncPtr;
+-
+- //gconf client list func
+- GConfClientGetList =
+- (GConfClientGetListType) sGConfFuncList[13].FuncPtr;
+-}
+-
+-void
+-GConfProxy::OnNotify(void *aClient, void * aEntry, PRUint32 aNotifyId,
+- GConfCallbackData *aData)
++nsresult nsSystemPrefService::NotifyUnloadSystemPreferences()
+ {
+- if (!mInitialized || !aEntry || (mGConfClient != aClient) || !aData)
+- return;
+-
+- if (GConfEntryGetValue(aEntry) == NULL)
+- return;
++ // Unregister callbacks
++ mGConfSimpleCallbacks.EnumerateRead(UnregisterSimple, this);
++ mGConfSimpleCallbacks.Clear();
++ mGConfComplexCallbacks.EnumerateRead(UnregisterComplex, this);
++ mGConfComplexCallbacks.Clear();
+
+- PRUint32 prefAtom;
+- nsresult rv = GetAtomForGConfKey(GConfEntryGetKey(aEntry), &prefAtom);
+- if (NS_FAILED(rv))
+- return;
+-
+- mSysPrefService->OnPrefChange(prefAtom, aData->userData);
++ return NS_OK;
+ }
+
+-nsresult
+-GConfProxy::GetAtom(const char *aKey, PRUint8 aNameType, PRUint32 *aAtom)
+-{
+- if (!aKey)
+- return NS_ERROR_FAILURE;
+- PRUint32 prefSize = sizeof(sPrefNameMapping) / sizeof(sPrefNameMapping[0]);
+- for (PRUint32 index = 0; index < prefSize; ++index) {
+- if (!strcmp((aNameType == 0) ? sPrefNameMapping[index].mozPrefName :
+- sPrefNameMapping[index].gconfPrefName, aKey)) {
+- *aAtom = index;
+- return NS_OK;
+- }
+- }
+- return NS_ERROR_FAILURE;
+-}
++// Factory stuff
+
+-const char *
+-GConfProxy::GetKey(PRUint32 aAtom, PRUint8 aNameType)
+-{
+- PRUint32 mapSize = sizeof(sPrefNameMapping) / sizeof(sPrefNameMapping[0]);
+- if (aAtom >= 0 && aAtom < mapSize)
+- return (aNameType == 0) ? sPrefNameMapping[aAtom].mozPrefName :
+- sPrefNameMapping[aAtom].gconfPrefName;
+- return NULL;
+-}
++NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSystemPrefService, Init)
+
+-inline const char *
+-GConfProxy::MozKey2GConfKey(const char *aMozKey)
+-{
+- PRUint32 atom;
+- nsresult rv = GetAtomForMozKey(aMozKey, &atom);
+- if (NS_SUCCEEDED(rv))
+- return GetGConfKey(atom);
+- return NULL;
+-}
++static const nsModuleComponentInfo components[] = {
++ { NS_SYSTEMPREF_SERVICE_CLASSNAME,
++ NS_SYSTEMPREF_SERVICE_CID,
++ NS_SYSTEMPREF_SERVICE_CONTRACTID,
++ nsSystemPrefServiceConstructor,
++ },
++};
+
+-/* static */
+-void gconf_key_listener (void* client, guint cnxn_id,
+- void *entry, gpointer user_data)
+-{
+- SYSPREF_LOG(("...SYSPREF_LOG...key listener get called \n"));
+- if (!user_data)
+- return;
+- GConfCallbackData *pData = reinterpret_cast
+- (user_data);
+- pData->proxy->OnNotify(client, entry, cnxn_id, pData);
+-}
++NS_IMPL_NSGETMODULE(nsSystemPrefServiceModule, components)
+diff -Naur mozilla.orig/extensions/pref/system-pref/src/gconf/nsSystemPrefService.h mozilla/extensions/pref/system-pref/src/gconf/nsSystemPrefService.h
+--- mozilla.orig/extensions/pref/system-pref/src/gconf/nsSystemPrefService.h 2005-02-23 08:15:37.000000000 -0800
++++ mozilla/extensions/pref/system-pref/src/gconf/nsSystemPrefService.h 1969-12-31 16:00:00.000000000 -0800
+@@ -1,93 +0,0 @@
+-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+-/* vim:expandtab:shiftwidth=4:tabstop=4:
+- */
+-/* ***** BEGIN LICENSE BLOCK *****
+- * Version: NPL 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 mozilla.org code.
+- *
+- * The Initial Developer of the Original Code is Sun Microsystems, Inc.
+- * Portions created by Sun Microsystems are Copyright (C) 2003 Sun
+- * Microsystems, Inc. All Rights Reserved.
+- *
+- * Original Author: Bolian Yin (bolian.yin@sun.com)
+- *
+- * 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 NPL, 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 NPL, the GPL or the LGPL.
+- *
+- * ***** END LICENSE BLOCK ***** */
+-
+-#ifndef __SYSTEM_PREF_SERVICE_H__
+-#define __SYSTEM_PREF_SERVICE_H__
+-
+-#include "prlink.h"
+-#include "nsVoidArray.h"
+-#include "nsWeakPtr.h"
+-#include "nsIPrefBranch.h"
+-#include "nsIPrefBranch2.h"
+-
+-class GConfProxy;
+-
+-////////////////////////////////////////////////////////////////////////////
+-// nsSystemPrefService provide a interface for read system prefs. It is
+-// platform related. This directory (system-pref/gconf) impls it for gconf
+-// on the gconf platform.
+-////////////////////////////////////////////////////////////////////////////
+-
+-class nsSystemPrefService : public nsIPrefBranch2
+-{
+-public:
+- NS_DECL_ISUPPORTS
+- NS_DECL_NSIPREFBRANCH
+- NS_DECL_NSIPREFBRANCH2
+-
+- nsSystemPrefService();
+- virtual ~nsSystemPrefService();
+- nsresult Init();
+-
+- void OnPrefChange(PRUint32 aPrefAtom, void *aData);
+-
+-private:
+- PRBool mInitialized;
+- GConfProxy *mGConf;
+-
+- //listeners
+- nsAutoVoidArray *mObservers;
+-};
+-
+-#define NS_SYSTEMPREF_SERVICE_CID \
+- { /* {94f1de09-d0e5-4ca8-94c2-98b049316b7f} */ \
+- 0x94f1de09, \
+- 0xd0e5, \
+- 0x4ca8, \
+- { 0x94, 0xc2, 0x98, 0xb0, 0x49, 0x31, 0x6b, 0x7f } \
+- }
+-
+-#define NS_SYSTEMPREF_SERVICE_CONTRACTID "@mozilla.org/system-preference-service;1"
+-#define NS_SYSTEMPREF_SERVICE_CLASSNAME "System Preferences Service"
+-
+-#define NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID "nsSystemPrefService:pref-changed"
+-
+-#endif /* __SYSTEM_PREF_SERVICE_H__ */
+diff -Naur mozilla.orig/extensions/pref/system-pref/src/Makefile.in mozilla/extensions/pref/system-pref/src/Makefile.in
+--- mozilla.orig/extensions/pref/system-pref/src/Makefile.in 2005-12-31 04:14:42.000000000 -0800
++++ mozilla/extensions/pref/system-pref/src/Makefile.in 2008-04-01 16:50:49.000000000 -0700
+@@ -43,12 +43,14 @@
+ include $(DEPTH)/config/autoconf.mk
+
+ MODULE = system-pref
+-LIBRARY_NAME = system-pref_s
++MODULE_NAME = nsSystemPrefModule
++LIBRARY_NAME = system-pref
+ ifneq ($(OS_ARCH),WINNT)
+ SHORT_LIBNAME = syspref
+ endif
+
+-# We want to force the creation of a static lib.
++IS_COMPONENT = 1
++EXPORT_LIBRARY = 1
+ FORCE_STATIC_LIB = 1
+ LIBXUL_LIBRARY = 1
+
+@@ -58,27 +60,22 @@
+ pref \
+ $(NULL)
+
+-ifdef MOZ_ENABLE_GTK2
++ifdef MOZ_ENABLE_GCONF
+ DIRS = gconf
+ endif
+
+-EXTRA_DSO_LDOPTS = \
+- -L$(DIST)/bin \
+- $(MOZ_COMPONENT_LIBS) \
+- $(NULL)
+-
+ CPPSRCS = \
+ nsSystemPref.cpp \
++ nsSystemPrefFactory.cpp \
+ $(NULL)
+
++EXTRA_DSO_LDOPTS = \
++ $(MOZ_COMPONENT_LIBS) \
++ $(NULL)
++
+ EXPORTS = \
+- nsSystemPrefLog.h \
++ nsISystemPrefService.h \
+ $(NULL)
+
+-include $(topsrcdir)/config/rules.mk
+
+-ifdef MOZ_ENABLE_GTK2
+-INCLUDES += \
+- -I$(srcdir)/gconf \
+- $(NULL)
+-endif
++include $(topsrcdir)/config/rules.mk
+diff -Naur mozilla.orig/extensions/pref/system-pref/src/nsISystemPrefService.h mozilla/extensions/pref/system-pref/src/nsISystemPrefService.h
+--- mozilla.orig/extensions/pref/system-pref/src/nsISystemPrefService.h 1969-12-31 16:00:00.000000000 -0800
++++ mozilla/extensions/pref/system-pref/src/nsISystemPrefService.h 2008-04-01 16:50:49.000000000 -0700
+@@ -0,0 +1,109 @@
++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* vim:expandtab:shiftwidth=4:tabstop=4:
++ */
++/* ***** 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 mozilla.org code.
++ *
++ * The Initial Developer of the Original Code is Novell
++ * Portions created by Novell are Copyright (C) 2005 Novell,
++ * All Rights Reserved.
++ *
++ * Original Author: Robert O'Callahan (rocallahan@novell.com)
++ *
++ * 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 NPL, 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 NPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#ifndef nsISystemPrefService_h__
++#define nsISystemPrefService_h__
++
++#include "nsCOMPtr.h"
++#include "nsIPrefBranchInternal.h"
++
++#define NS_SYSTEMPREF_SERVICE_CONTRACTID "@mozilla.org/system-preferences-service;1"
++
++#define NS_ISYSTEMPREFSERVICE_IID \
++{ 0x006e1cfd, 0xd66a, 0x40b9, \
++ { 0x84, 0xa1, 0x84, 0xf3, 0xe6, 0xa2, 0xca, 0xbc } }
++
++class nsISystemPref {
++public:
++ /**
++ * Call one of these three methods to override a Mozilla
++ * preference with a system value. You can call it multiple
++ * times to change the value of a given preference to track
++ * the underlying system value.
++ *
++ * If aLocked is true then we set the default preference and
++ * lock it so the user value is ignored. If aLocked is false
++ * then we unlock the Mozilla preference and set the Mozilla
++ * user value.
++ */
++ virtual nsresult SetOverridingMozillaBoolPref(const char* aPrefName,
++ PRBool aValue, PRBool aLocked,
++ PRBool aPresent = PR_TRUE) = 0;
++ virtual nsresult SetOverridingMozillaIntPref(const char* aPrefName,
++ PRInt32 aValue, PRBool aLocked,
++ PRBool aPresent = PR_TRUE) = 0;
++ virtual nsresult SetOverridingMozillaStringPref(const char* aPrefName,
++ const char* aValue, PRBool aLocked,
++ PRBool aPresent = PR_TRUE) = 0;
++ virtual nsresult StopOverridingMozillaPref(const char* aPrefName) = 0;
++ virtual already_AddRefed GetPrefUserBranch() = 0;
++ virtual already_AddRefed GetPrefDefaultBranch() = 0;
++};
++
++class nsISystemPrefService : public nsISupports {
++public:
++ NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISYSTEMPREFSERVICE_IID)
++
++ /**
++ * Load the system prefs from the store into their corresponding
++ * Mozilla prefs, calling SetOverridingMozillaPref on each
++ * such pref.
++ */
++ virtual nsresult LoadSystemPreferences(nsISystemPref* aPrefs) = 0;
++
++ /**
++ * Notify that a Mozilla user pref that is being overridden by the
++ * store has changed. The new value of the Mozilla pref should be
++ * written back to the store.
++ */
++ virtual nsresult NotifyMozillaPrefChanged(const char* aPrefName) = 0;
++
++ /**
++ * Notify that we're about to stop using the system prefs. After
++ * this, nsSystemPref will automatically stop overriding all
++ * Mozilla prefs that are being overridden.
++ */
++ virtual nsresult NotifyUnloadSystemPreferences() = 0;
++};
++
++NS_DEFINE_STATIC_IID_ACCESSOR(nsISystemPrefService, NS_ISYSTEMPREFSERVICE_IID)
++
++#endif
+diff -Naur mozilla.orig/extensions/pref/system-pref/src/nsSystemPref.cpp mozilla/extensions/pref/system-pref/src/nsSystemPref.cpp
+--- mozilla.orig/extensions/pref/system-pref/src/nsSystemPref.cpp 2006-04-17 15:03:46.000000000 -0700
++++ mozilla/extensions/pref/system-pref/src/nsSystemPref.cpp 2008-04-01 16:50:49.000000000 -0700
+@@ -24,6 +24,7 @@
+ * Original Author: Bolian Yin (bolian.yin@sun.com)
+ *
+ * Contributor(s):
++ * Robert O'Callahan (rocallahan@novell.com)
+ *
+ * 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
+@@ -41,66 +42,60 @@
+
+ #include "nsSystemPref.h"
+ #include "nsIObserverService.h"
++#include "nsIAppStartupNotifier.h"
++#include "nsIPrefService.h"
++#include "nsIPrefBranch.h"
++#include "nsICategoryManager.h"
++#include "nsIServiceManager.h"
+
+ #include "nsSystemPrefLog.h"
+-#include "nsSystemPrefService.h"
+ #include "nsString.h"
+
+-const char sSysPrefString[] = "config.use_system_prefs";
+-union MozPrefValue {
+- char * stringVal;
+- PRInt32 intVal;
+- PRBool boolVal;
+-};
++#include
+
+ struct SysPrefItem {
+- const char *prefName; // mozilla pref string name
+- MozPrefValue defaultValue; // store the mozilla default value
+- PRBool isLocked; // store the mozilla lock status
++ // Saved values on both branches
++ PRInt32 savedUserValueScalar;
++ char* savedUserValueString;
++ PRInt32 savedDefaultValueScalar;
++ char* savedDefaultValueString;
++ // When this is true, then the value was locked originally
++ PRPackedBool savedLocked;
++ // When this is true, then there was a user value
++ PRPackedBool savedUserPresent;
++ PRPackedBool ignore;
++
+ SysPrefItem() {
+- prefName = nsnull;
+- defaultValue.intVal = 0;
+- defaultValue.stringVal = nsnull;
+- defaultValue.boolVal = PR_FALSE;
+- isLocked = PR_FALSE;
++ savedUserValueScalar = 0;
++ savedUserValueString = nsnull;
++ savedDefaultValueScalar = 0;
++ savedDefaultValueString = nsnull;
++ savedUserPresent = PR_FALSE;
++ savedLocked = PR_FALSE;
++ ignore = PR_FALSE;
+ }
+- void SetPrefName(const char *aPrefName) {
+- prefName = aPrefName;
++
++ virtual ~SysPrefItem() {
++ nsMemory::Free(savedUserValueString);
++ nsMemory::Free(savedDefaultValueString);
+ }
+ };
+
+-// all prefs that mozilla need to read from host system if they are available
+-static const char *sSysPrefList[] = {
+- "network.proxy.http",
+- "network.proxy.http_port",
+- "network.proxy.ftp",
+- "network.proxy.ftp_port",
+- "network.proxy.ssl",
+- "network.proxy.ssl_port",
+- "network.proxy.socks",
+- "network.proxy.socks_port",
+- "network.proxy.no_proxies_on",
+- "network.proxy.autoconfig_url",
+- "network.proxy.type",
+- "config.use_system_prefs.accessibility",
+-};
++static const char sSysPrefString[] = "config.use_system_prefs";
+
+ PRLogModuleInfo *gSysPrefLog = NULL;
+
+ NS_IMPL_ISUPPORTS2(nsSystemPref, nsIObserver, nsISupportsWeakReference)
+
+-nsSystemPref::nsSystemPref():
+- mSysPrefService(nsnull),
+- mEnabled(PR_FALSE),
+- mSysPrefs(nsnull)
++nsSystemPref::nsSystemPref() : mIgnorePrefSetting(PR_FALSE)
+ {
++ mSavedPrefs.Init();
++ mCachedUserPrefBranch = nsnull;
++ mCachedDefaultPrefBranch = nsnull;
+ }
+
+ nsSystemPref::~nsSystemPref()
+ {
+- mSysPrefService = nsnull;
+- mEnabled = PR_FALSE;
+- delete [] mSysPrefs;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+@@ -131,6 +126,54 @@
+ return(rv);
+ }
+
++already_AddRefed
++nsSystemPref::GetPrefUserBranch()
++{
++ if (mCachedUserPrefBranch) {
++ NS_ADDREF(mCachedUserPrefBranch);
++ return mCachedUserPrefBranch;
++ }
++
++ nsresult rv;
++ nsCOMPtr prefService =
++ do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
++ if (NS_FAILED(rv))
++ return nsnull;
++ nsCOMPtr prefBranch;
++ rv = prefService->GetBranch(nsnull, getter_AddRefs(prefBranch));
++ if (NS_FAILED(rv))
++ return nsnull;
++ nsCOMPtr pb2(do_QueryInterface(prefBranch));
++ if (!pb2)
++ return nsnull;
++
++ nsIPrefBranch2* result = nsnull;
++ pb2.swap(result);
++ return result;
++}
++
++already_AddRefed
++nsSystemPref::GetPrefDefaultBranch()
++{
++ if (mCachedDefaultPrefBranch) {
++ NS_ADDREF(mCachedDefaultPrefBranch);
++ return mCachedDefaultPrefBranch;
++ }
++
++ nsresult rv;
++ nsCOMPtr prefService =
++ do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
++ if (NS_FAILED(rv))
++ return nsnull;
++ nsCOMPtr prefBranch;
++ rv = prefService->GetDefaultBranch(nsnull, getter_AddRefs(prefBranch));
++ if (NS_FAILED(rv))
++ return nsnull;
++ nsIPrefBranch* pb = nsnull;
++ prefBranch.swap(pb);
++ return pb;
++}
++
+ ///////////////////////////////////////////////////////////////////////////////
+ // nsSystemPref::Observe
+ // Observe notifications from mozilla pref system and system prefs (if enabled)
+@@ -145,330 +188,438 @@
+ if (!aTopic)
+ return NS_OK;
+
+- // if we are notified by pref service
+- // check the system pref settings
++ nsCOMPtr userBranch = GetPrefUserBranch();
++ PRBool enabled;
++ rv = userBranch->GetBoolPref(sSysPrefString, &enabled);
++ if (NS_FAILED(rv)) {
++ SYSPREF_LOG(("...Failed to Get %s\n", sSysPrefString));
++ return rv;
++ }
++
+ if (!nsCRT::strcmp(aTopic, NS_PREFSERVICE_READ_TOPIC_ID)) {
++ // The prefs have just loaded. This is the first thing that
++ // happens to us.
+ SYSPREF_LOG(("Observed: %s\n", aTopic));
+
+- nsCOMPtr prefBranch =
+- do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+- if (NS_FAILED(rv))
+- return rv;
+-
+- rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
++ // listen on changes to use_system_pref. It's OK to
++ // hold a strong reference because we don't keep a reference
++ // to the pref branch.
++ rv = userBranch->AddObserver(sSysPrefString, this, PR_TRUE);
+ if (NS_FAILED(rv)) {
+- SYSPREF_LOG(("...FAil to Get %s\n", sSysPrefString));
++ SYSPREF_LOG(("...Failed to add observer for %s\n", sSysPrefString));
+ return rv;
+ }
+
+- // if there is no system pref service, assume nothing happen to us
+- mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
+- if (NS_FAILED(rv) || !mSysPrefService) {
+- SYSPREF_LOG(("...No System Pref Service\n"));
++ NS_ASSERTION(!mSysPrefService, "Should not be already enabled");
++ if (!enabled) {
++ // Don't load the system pref service if the preference is
++ // not set.
+ return NS_OK;
+ }
+
+- // listen on its changes
+- rv = prefBranch->AddObserver(sSysPrefString, this, PR_TRUE);
+- if (NS_FAILED(rv)) {
+- SYSPREF_LOG(("...FAil to add observer for %s\n", sSysPrefString));
+- return rv;
+- }
+-
+- if (!mEnabled) {
+- SYSPREF_LOG(("%s is disabled\n", sSysPrefString));
+- return NS_OK;
+- }
+ SYSPREF_LOG(("%s is enabled\n", sSysPrefString));
+- rv = UseSystemPrefs();
+-
+- }
+- // sSysPrefString value was changed, update ...
+- else if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
+- NS_ConvertUTF8toUTF16(sSysPrefString).Equals(aData)) {
+- SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
+- aTopic, NS_ConvertUTF16toUTF8(aData).get()));
+
+- nsCOMPtr prefBranch =
+- do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
++ rv = LoadSystemPrefs();
+ if (NS_FAILED(rv))
+ return rv;
+
+- PRBool enabled = mEnabled;
+- rv = prefBranch->GetBoolPref(sSysPrefString, &mEnabled);
+- if (enabled != mEnabled) {
+- if (mEnabled)
+- //read prefs from system
+- rv = UseSystemPrefs();
+- else
+- //roll back to mozilla prefs
+- rv = UseMozillaPrefs();
++ // Lock config.use_system_prefs so the user can't undo
++ // it. Really this should already be locked because if it's
++ // not locked at a lower level the user can set it to false in
++ // their in prefs.js. But only do this if the value was not
++ // specially set by the user; if it was set by the user, then
++ // locking it would actually unset the value! And the user
++ // should be allowed to turn off something they set
++ // themselves.
++ PRBool hasUserValue;
++ rv = userBranch->PrefHasUserValue(sSysPrefString, &hasUserValue);
++ if (NS_SUCCEEDED(rv) && !hasUserValue) {
++ userBranch->LockPref(sSysPrefString);
+ }
+ }
+
+- // if the system pref notify us that some pref has been changed by user
+- // outside mozilla. We need to read it again.
+- else if (!nsCRT::strcmp(aTopic, NS_SYSTEMPREF_PREFCHANGE_TOPIC_ID) &&
+- aData) {
+- NS_ASSERTION(mEnabled == PR_TRUE, "Should not listen when disabled");
+- SYSPREF_LOG(("====== System Pref Notify topic=%s data=%s\n",
+- aTopic, (char*)aData));
+- rv = ReadSystemPref(NS_LossyConvertUTF16toASCII(aData).get());
+- return NS_OK;
+- } else if (!nsCRT::strcmp(aTopic,"profile-before-change")) {
+- //roll back to mozilla prefs
+- if (mEnabled)
+- UseMozillaPrefs();
+- mEnabled = PR_FALSE;
+- mSysPrefService = nsnull;
+- delete [] mSysPrefs;
+- mSysPrefs = nsnull;
+- } else
+- SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
+- return rv;
+-}
++ if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) &&
++ nsDependentString(aData).EqualsASCII(sSysPrefString)) {
++ // sSysPrefString value was changed, update...
++ SYSPREF_LOG(("++++++ Notify: topic=%s data=%s\n",
++ aTopic, NS_ConvertUTF16toUTF8(aData).get()));
++ if (mSysPrefService && !enabled)
++ return RestoreMozillaPrefs();
++ if (!mSysPrefService && enabled) {
++ // Don't lock it. If the user enabled use_system_prefs,
++ // they should be allowed to unlock it.
++ return LoadSystemPrefs();
++ }
+
+-/* private */
++ // didn't change?
++ return NS_OK;
++ }
+
+-////////////////////////////////////////////////////////////////
+-// nsSystemPref::UseSystemPrefs
+-// Read all the prefs in the table from system, listen for their
+-// changes in system pref service.
+-////////////////////////////////////////////////////////////////
+-nsresult
+-nsSystemPref::UseSystemPrefs()
+-{
+- SYSPREF_LOG(("\n====Now Use system prefs==\n"));
+- nsresult rv = NS_OK;
+- if (!mSysPrefService) {
+- return NS_ERROR_FAILURE;
++ if (!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
++ // some other pref changed, tell the backend if there is one
++ if (mSysPrefService && !mIgnorePrefSetting) {
++ NS_LossyConvertUTF16toASCII tmp(aData);
++#ifdef DEBUG
++ PRBool isLocked;
++ userBranch->PrefIsLocked(tmp.get(), &isLocked);
++ NS_ASSERTION(!isLocked, "Locked pref is changing?");
++#endif
++ SysPrefItem* item;
++ if (!mSavedPrefs.Get(tmp, &item)) {
++ NS_ERROR("Notified about pref change that we didn't ask about?");
++ } else {
++ if (!item->ignore) {
++ mSysPrefService->NotifyMozillaPrefChanged(tmp.get());
++ }
++ }
++ }
++ return NS_OK;
+ }
+
+- PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
++ if (!nsCRT::strcmp(aTopic,"profile-before-change"))
++ return RestoreMozillaPrefs();
+
+- if (!mSysPrefs) {
+- mSysPrefs = new SysPrefItem[sysPrefCount];
+- if (!mSysPrefs)
+- return NS_ERROR_OUT_OF_MEMORY;
+- for (PRIntn index = 0; index < sysPrefCount; ++index)
+- mSysPrefs[index].SetPrefName(sSysPrefList[index]);
+- }
++ SYSPREF_LOG(("Not needed topic Received %s\n", aTopic));
+
+- for (PRIntn index = 0; index < sysPrefCount; ++index) {
+- // save mozilla prefs
+- SaveMozDefaultPref(mSysPrefs[index].prefName,
+- &mSysPrefs[index].defaultValue,
+- &mSysPrefs[index].isLocked);
+-
+- // get the system prefs
+- ReadSystemPref(mSysPrefs[index].prefName);
+- SYSPREF_LOG(("Add Listener on %s\n", mSysPrefs[index].prefName));
+- mSysPrefService->AddObserver(mSysPrefs[index].prefName,
+- this, PR_TRUE);
+- }
+ return rv;
+ }
+
+-//////////////////////////////////////////////////////////////////////
+-// nsSystemPref::ReadSystemPref
+-// Read a pref value from system pref service, and lock it in mozilla.
+-//////////////////////////////////////////////////////////////////////
+ nsresult
+-nsSystemPref::ReadSystemPref(const char *aPrefName)
++nsSystemPref::SetOverridingMozillaBoolPref(const char* aPrefName,
++ PRBool aValue, PRBool aLock, PRBool aPresent)
+ {
+- if (!mSysPrefService)
+- return NS_ERROR_FAILURE;
+- nsresult rv;
+-
+- nsCOMPtr prefBranch
+- (do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+- if (NS_FAILED(rv))
+- return rv;
+-
+- SYSPREF_LOG(("about to read aPrefName %s\n", aPrefName));
++ return OverridePref(aPrefName, nsIPrefBranch::PREF_BOOL,
++ (void*)aValue, aLock, aPresent);
++}
+
+- prefBranch->UnlockPref(aPrefName);
++nsresult
++nsSystemPref::SetOverridingMozillaIntPref(const char* aPrefName,
++ PRInt32 aValue, PRBool aLock, PRBool aPresent)
++{
++ return OverridePref(aPrefName, nsIPrefBranch::PREF_INT,
++ (void*)aValue, aLock, aPresent);
++}
+
+- PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
+- nsXPIDLCString strValue;
+- PRInt32 intValue = 0;
+- PRBool boolValue = PR_FALSE;
++nsresult
++nsSystemPref::SetOverridingMozillaStringPref(const char* aPrefName,
++ const char* aValue, PRBool aLock, PRBool aPresent)
++{
++ return OverridePref(aPrefName, nsIPrefBranch::PREF_STRING,
++ (void*)aValue, aLock, aPresent);
++}
+
+- rv = prefBranch->GetPrefType(aPrefName, &prefType);
+- if (NS_FAILED(rv))
+- return rv;
+- switch (prefType) {
++static nsresult RestorePrefValue(PRInt32 aPrefType,
++ const char* aPrefName,
++ SysPrefItem* aItem,
++ nsIPrefBranch* aUser,
++ nsIPrefBranch* aDefault)
++{
++ switch (aPrefType) {
+ case nsIPrefBranch::PREF_STRING:
+- mSysPrefService->GetCharPref(aPrefName, getter_Copies(strValue));
+- SYSPREF_LOG(("system value is %s\n", strValue.get()));
+-
+- prefBranch->SetCharPref(aPrefName, strValue.get());
++ aDefault->SetCharPref(aPrefName,
++ aItem->savedDefaultValueString);
++ if (aItem->savedUserPresent) {
++ aUser->SetCharPref(aPrefName, aItem->savedUserValueString);
++ }
+ break;
+ case nsIPrefBranch::PREF_INT:
+- mSysPrefService->GetIntPref(aPrefName, &intValue);
+- SYSPREF_LOG(("system value is %d\n", intValue));
+-
+- prefBranch->SetIntPref(aPrefName, intValue);
++ aDefault->SetIntPref(aPrefName, aItem->savedDefaultValueScalar);
++ if (aItem->savedUserPresent) {
++ aUser->SetIntPref(aPrefName, aItem->savedUserValueScalar);
++ }
+ break;
+ case nsIPrefBranch::PREF_BOOL:
+- mSysPrefService->GetBoolPref(aPrefName, &boolValue);
+- SYSPREF_LOG(("system value is %s\n", boolValue ? "TRUE" : "FALSE"));
+-
+- prefBranch->SetBoolPref(aPrefName, boolValue);
++ aDefault->SetBoolPref(aPrefName, aItem->savedDefaultValueScalar);
++ if (aItem->savedUserPresent) {
++ aUser->SetBoolPref(aPrefName, aItem->savedUserValueScalar);
++ }
+ break;
+ default:
+- SYSPREF_LOG(("Fail to system value for it\n"));
++ NS_ERROR("Unknown preference type");
+ return NS_ERROR_FAILURE;
+ }
+- prefBranch->LockPref(aPrefName);
++
++ if (!aItem->savedUserPresent) {
++ aUser->DeleteBranch(aPrefName);
++ }
++
+ return NS_OK;
+ }
+
+-//////////////////////////////////////////////////////////////////////
+-// nsSystemPref::UseMozillaPrefs
+-// Restore mozilla default prefs, remove system pref listeners
+-/////////////////////////////////////////////////////////////////////
+-nsresult
+-nsSystemPref::UseMozillaPrefs()
++static PLDHashOperator PR_CALLBACK RestorePref(const nsACString& aKey,
++ SysPrefItem* aItem,
++ void* aClosure)
+ {
+- nsresult rv = NS_OK;
+- SYSPREF_LOG(("\n====Now rollback to Mozilla prefs==\n"));
++ nsSystemPref* prefs = static_cast(aClosure);
++ nsCOMPtr userBranch = prefs->GetPrefUserBranch();
++ const nsCString& prefName = PromiseFlatCString(aKey);
++
++ PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
++ nsresult rv = userBranch->GetPrefType(prefName.get(), &prefType);
++ if (NS_FAILED(rv))
++ return PL_DHASH_NEXT;
++ PRBool isLocked;
++ userBranch->PrefIsLocked(prefName.get(), &isLocked);
++ if (NS_FAILED(rv))
++ return PL_DHASH_NEXT;
+
+- // if we did not use system prefs, do nothing
+- if (!mSysPrefService)
+- return NS_OK;
++ // Remove our observer before we change the value
++ userBranch->RemoveObserver(prefName.get(), prefs);
++ // Remember to ignore this item. Because some prefs start with "config.use_system_prefs",
++ // which we always observe, even after we remove the observer, changes to the pref will
++ // still be observed by us. We must ignore them.
++ aItem->ignore = PR_TRUE;
+
+- PRIntn sysPrefCount= sizeof(sSysPrefList) / sizeof(sSysPrefList[0]);
+- for (PRIntn index = 0; index < sysPrefCount; ++index) {
+- // restore mozilla default value and free string memory if needed
+- RestoreMozDefaultPref(mSysPrefs[index].prefName,
+- &mSysPrefs[index].defaultValue,
+- mSysPrefs[index].isLocked);
+- SYSPREF_LOG(("stop listening on %s\n", mSysPrefs[index].prefName));
+- mSysPrefService->RemoveObserver(mSysPrefs[index].prefName,
+- this);
++ // Unlock the pref so we can set it
++ if (isLocked) {
++ userBranch->UnlockPref(prefName.get());
+ }
+- return rv;
++
++ nsCOMPtr defaultBranch = prefs->GetPrefDefaultBranch();
++
++ RestorePrefValue(prefType, prefName.get(), aItem,
++ userBranch, defaultBranch);
++
++ if (aItem->savedLocked) {
++ userBranch->LockPref(prefName.get());
++ }
++
++ return PL_DHASH_NEXT;
+ }
+
+-////////////////////////////////////////////////////////////////////////////
+-// nsSystemPref::RestoreMozDefaultPref
+-// Save the saved mozilla default value.
+-// It is also responsible for allocate the string memory when needed, because
+-// this method know what type of value is stored.
+-/////////////////////////////////////////////////////////////////////////////
+ nsresult
+-nsSystemPref::SaveMozDefaultPref(const char *aPrefName,
+- MozPrefValue *aPrefValue,
+- PRBool *aLocked)
+-{
+- NS_ENSURE_ARG_POINTER(aPrefName);
+- NS_ENSURE_ARG_POINTER(aPrefValue);
+- NS_ENSURE_ARG_POINTER(aLocked);
+-
+- nsresult rv;
++nsSystemPref::StopOverridingMozillaPref(const char* aPrefName)
++{
++ SysPrefItem* item;
++ nsDependentCString prefNameStr(aPrefName);
++ if (!mSavedPrefs.Get(prefNameStr, &item))
++ return NS_OK;
+
+- nsCOMPtr prefBranch =
+- do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
+- if (NS_FAILED(rv))
+- return rv;
++ RestorePref(prefNameStr, item, this);
++ mSavedPrefs.Remove(prefNameStr);
++ //delete item;
++ return NS_OK;
++}
+
+- SYSPREF_LOG(("Save Mozilla value for %s\n", aPrefName));
++/* private */
+
++nsresult
++nsSystemPref::OverridePref(const char* aPrefName, PRInt32 aType,
++ void* aValue, PRBool aLock, PRBool aPresent)
++{
++ nsCOMPtr userBranch = GetPrefUserBranch();
++ nsCOMPtr defaultBranch = GetPrefDefaultBranch();
+ PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
+- nsXPIDLCString strValue;
+-
+- rv = prefBranch->GetPrefType(aPrefName, &prefType);
++ nsresult rv = userBranch->GetPrefType(aPrefName, &prefType);
+ if (NS_FAILED(rv))
+ return rv;
+- switch (prefType) {
+- case nsIPrefBranch::PREF_STRING:
+- prefBranch->GetCharPref(aPrefName,
+- getter_Copies(strValue));
+- SYSPREF_LOG(("Mozilla value is %s", strValue.get()));
+-
+- if (aPrefValue->stringVal)
+- PL_strfree(aPrefValue->stringVal);
+- aPrefValue->stringVal = PL_strdup(strValue.get());
+- break;
+- case nsIPrefBranch::PREF_INT:
+- prefBranch->GetIntPref(aPrefName, &aPrefValue->intVal);
+- SYSPREF_LOG(("Mozilla value is %d\n", aPrefValue->intVal));
+
+- break;
+- case nsIPrefBranch::PREF_BOOL:
+- prefBranch->GetBoolPref(aPrefName, &aPrefValue->boolVal);
+- SYSPREF_LOG(("Mozilla value is %s\n",
+- aPrefValue->boolVal ? "TRUE" : "FALSE"));
++ PRBool isLocked;
++ rv = userBranch->PrefIsLocked(aPrefName, &isLocked);
++ if (NS_FAILED(rv))
++ return rv;
++ PRBool hasUserValue;
++ rv = userBranch->PrefHasUserValue(aPrefName, &hasUserValue);
++ if (NS_FAILED(rv))
++ return rv;
+
+- break;
+- default:
+- SYSPREF_LOG(("Fail to Read Mozilla value for it\n"));
+- return NS_ERROR_FAILURE;
++ if (prefType == 0) {
++ // Preference does not exist. Allow the system prefs to
++ // set it.
++ } else {
++ NS_ASSERTION(aType == prefType,
++ "System pref engine passed incorrect type for Mozilla pref");
++ if (aType != prefType)
++ return NS_ERROR_FAILURE;
++ }
++
++ if (prefType != 0) {
++ nsDependentCString prefNameStr(aPrefName);
++ SysPrefItem* item = nsnull;
++ if (!mSavedPrefs.Get(prefNameStr, &item)) {
++ // Need to save the existing value away
++ item = new SysPrefItem();
++ if (!item)
++ return NS_ERROR_OUT_OF_MEMORY;
++
++ item->savedLocked = isLocked;
++ item->savedUserPresent = hasUserValue;
++
++ switch (prefType) {
++ case nsIPrefBranch::PREF_STRING:
++ if (hasUserValue) {
++ userBranch->GetCharPref(aPrefName, &item->savedUserValueString);
++ }
++ defaultBranch->GetCharPref(aPrefName, &item->savedDefaultValueString);
++ break;
++ case nsIPrefBranch::PREF_INT:
++ if (hasUserValue) {
++ userBranch->GetIntPref(aPrefName, &item->savedUserValueScalar);
++ }
++ defaultBranch->GetIntPref(aPrefName, &item->savedDefaultValueScalar);
++ break;
++ case nsIPrefBranch::PREF_BOOL:
++ if (hasUserValue) {
++ userBranch->GetBoolPref(aPrefName, &item->savedUserValueScalar);
++ }
++ defaultBranch->GetBoolPref(aPrefName, &item->savedDefaultValueScalar);
++ break;
++ default:
++ NS_ERROR("Unknown preference type");
++ delete item;
++ return NS_ERROR_FAILURE;
++ }
++
++ mSavedPrefs.Put(prefNameStr, item);
++
++ // Watch the user value in case it changes on the Mozilla side
++ // If 'aLock' is true then it shouldn't change and we don't
++ // need the observer, but don't bother optimizing for that.
++ userBranch->AddObserver(aPrefName, this, PR_TRUE);
++ } else {
++ if (isLocked != aLock) {
++ // restore pref value on user and default branches
++ RestorePrefValue(prefType, aPrefName, item,
++ userBranch, defaultBranch);
++ }
++ }
+ }
+- rv = prefBranch->PrefIsLocked(aPrefName, aLocked);
+- SYSPREF_LOG((" (%s).\n", aLocked ? "Locked" : "NOT Locked"));
+- return rv;
+-}
+
+-////////////////////////////////////////////////////////////////////////////
+-// nsSystemPref::RestoreMozDefaultPref
+-// Restore the saved mozilla default value to pref service.
+-// It is also responsible for free the string memory when needed, because
+-// this method know what type of value is stored.
+-/////////////////////////////////////////////////////////////////////////////
+-nsresult
+-nsSystemPref::RestoreMozDefaultPref(const char *aPrefName,
+- MozPrefValue *aPrefValue,
+- PRBool aLocked)
+-{
+- NS_ENSURE_ARG_POINTER(aPrefName);
++ // We need to ignore pref changes due to our own calls here
++ mIgnorePrefSetting = PR_TRUE;
+
+- nsresult rv;
++ // Unlock it if it's locked, so we can set it
++ if (isLocked) {
++ rv = userBranch->UnlockPref(aPrefName);
++ if (NS_FAILED(rv))
++ return rv;
++ }
+
+- nsCOMPtr prefBranch =
+- do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
++ // Set the pref on the default branch if we're locking it, because
++ // only the default branch gets used when the pref is locked.
++ // Set the pref on the user branch if we're not locking it, because
++ // that's where the user change will go.
++ nsIPrefBranch* settingBranch =
++ aLock ? defaultBranch.get() : static_cast(userBranch.get());
++
++ if (!aPresent) {
++ rv = settingBranch->DeleteBranch(aPrefName);
++ } else {
++ switch (aType) {
++ case nsIPrefBranch::PREF_STRING:
++ rv = settingBranch->SetCharPref(aPrefName, (const char*)aValue);
++ break;
++ case nsIPrefBranch::PREF_INT:
++ rv = settingBranch->SetIntPref(aPrefName, (PRInt32)(NS_PTR_TO_INT32(aValue)));
++ break;
++ case nsIPrefBranch::PREF_BOOL:
++ rv = settingBranch->SetBoolPref(aPrefName, (PRBool)(NS_PTR_TO_INT32(aValue)));
++ break;
++ default:
++ NS_ERROR("Unknown preference type");
++ mIgnorePrefSetting = PR_FALSE;
++ return NS_ERROR_FAILURE;
++ }
++ }
+ if (NS_FAILED(rv))
+ return rv;
++ if (aLock) {
++ rv = userBranch->LockPref(aPrefName);
++ }
+
+- SYSPREF_LOG(("Restore Mozilla value for %s\n", aPrefName));
++ mIgnorePrefSetting = PR_FALSE;
++ return rv;
++}
+
+- PRInt32 prefType = nsIPrefBranch::PREF_INVALID;
+- rv = prefBranch->GetPrefType(aPrefName, &prefType);
++nsresult
++nsSystemPref::FixupLockdownPrefs()
++{
++ nsCOMPtr userPrefs = GetPrefUserBranch();
++ nsCOMPtr defaultPrefs = GetPrefUserBranch();
++ PRUint32 childCount;
++ char **childArray = nsnull;
++ nsresult rv = userPrefs->GetChildList("config.lockdown.",
++ &childCount, &childArray);
+ if (NS_FAILED(rv))
+ return rv;
++ for (PRUint32 i = 0; i < childCount; ++i) {
++ PRInt32 type;
++ rv = defaultPrefs->GetPrefType(childArray[i], &type);
++ if (NS_FAILED(rv))
++ return rv;
++ NS_ASSERTION(type == nsIPrefBranch2::PREF_BOOL,
++ "All config.lockdown.* prefs should be boolean");
++ if (type == nsIPrefBranch2::PREF_BOOL) {
++ rv = defaultPrefs->SetBoolPref(childArray[i], PR_FALSE);
++ if (NS_FAILED(rv))
++ return rv;
++ }
++ }
++ NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(childCount, childArray);
++ return NS_OK;
++}
+
+- // unlock, if it is locked
+- prefBranch->UnlockPref(aPrefName);
++nsresult
++nsSystemPref::LoadSystemPrefs()
++{
++ SYSPREF_LOG(("\n====Now Use system prefs==\n"));
++ NS_ASSERTION(!mSysPrefService,
++ "Shouldn't have the pref service here");
++ nsresult rv;
++ mSysPrefService = do_GetService(NS_SYSTEMPREF_SERVICE_CONTRACTID, &rv);
++ if (NS_FAILED(rv) || !mSysPrefService) {
++ FixupLockdownPrefs();
++ SYSPREF_LOG(("...No System Pref Service\n"));
++ return NS_OK;
++ }
+
+- switch (prefType) {
+- case nsIPrefBranch::PREF_STRING:
+- prefBranch->SetCharPref(aPrefName,
+- aPrefValue->stringVal);
+- SYSPREF_LOG(("Mozilla value is %s\n", aPrefValue->stringVal));
++ // Cache the pref-branch while we load up the system prefs.
++ NS_ASSERTION(!mCachedUserPrefBranch,
++ "Shouldn't have a cache here");
++ nsCOMPtr