Back to index

lightning-sunbird  0.9+nobinonly
txXSLTNumber.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is TransforMiiX XSLT processor code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Jonas Sicking.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Jonas Sicking <sicking@bigfoot.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "txXSLTNumber.h"
00040 #include "txAtoms.h"
00041 #include "txCore.h"
00042 #include <math.h>
00043 #include "Expr.h"
00044 #include "ExprResult.h"
00045 #include "txXSLTPatterns.h"
00046 #include "txIXPathContext.h"
00047 #include "txXPathTreeWalker.h"
00048 
00049 nsresult txXSLTNumber::createNumber(Expr* aValueExpr, txPattern* aCountPattern,
00050                                     txPattern* aFromPattern, LevelType aLevel,
00051                                     Expr* aGroupSize, Expr* aGroupSeparator,
00052                                     Expr* aFormat, txIEvalContext* aContext,
00053                                     nsAString& aResult)
00054 {
00055     aResult.Truncate();
00056     nsresult rv = NS_OK;
00057 
00058     // Parse format
00059     txList counters;
00060     nsAutoString head, tail;
00061     rv = getCounters(aGroupSize, aGroupSeparator, aFormat, aContext, counters,
00062                      head, tail);
00063     NS_ENSURE_SUCCESS(rv, rv);
00064     
00065     // Create list of values to format
00066     txList values;
00067     nsAutoString valueString;
00068     rv = getValueList(aValueExpr, aCountPattern, aFromPattern, aLevel,
00069                       aContext, values, valueString);
00070     NS_ENSURE_SUCCESS(rv, rv);
00071 
00072     if (!valueString.IsEmpty()) {
00073         aResult = valueString;
00074 
00075         return NS_OK;
00076     }
00077 
00078     // Create resulting string
00079     aResult = head;
00080     MBool first = MB_TRUE;
00081     txListIterator valueIter(&values);
00082     txListIterator counterIter(&counters);
00083     valueIter.resetToEnd();
00084     PRInt32 value;
00085     txFormattedCounter* counter = 0;
00086     while ((value = NS_PTR_TO_INT32(valueIter.previous()))) {
00087         if (counterIter.hasNext()) {
00088             counter = (txFormattedCounter*)counterIter.next();
00089         }
00090 
00091         if (!first) {
00092             aResult.Append(counter->mSeparator);
00093         }
00094 
00095         counter->appendNumber(value, aResult);
00096         first = MB_FALSE;
00097     }
00098     
00099     aResult.Append(tail);
00100     
00101     txListIterator iter(&counters);
00102     while (iter.hasNext()) {
00103         delete (txFormattedCounter*)iter.next();
00104     }
00105 
00106     return NS_OK;
00107 }
00108 
00109 nsresult
00110 txXSLTNumber::getValueList(Expr* aValueExpr, txPattern* aCountPattern,
00111                            txPattern* aFromPattern, LevelType aLevel,
00112                            txIEvalContext* aContext, txList& aValues,
00113                            nsAString& aValueString)
00114 {
00115     aValueString.Truncate();
00116     nsresult rv = NS_OK;
00117 
00118     // If the value attribute exists then use that
00119     if (aValueExpr) {
00120         nsRefPtr<txAExprResult> result;
00121         rv = aValueExpr->evaluate(aContext, getter_AddRefs(result));
00122         NS_ENSURE_SUCCESS(rv, rv);
00123 
00124         double value = result->numberValue();
00125 
00126         if (Double::isInfinite(value) || Double::isNaN(value) ||
00127             value < 0.5) {
00128             Double::toString(value, aValueString);
00129             return NS_OK;
00130         }
00131         
00132         aValues.add(NS_INT32_TO_PTR((PRInt32)floor(value + 0.5)));
00133         return NS_OK;
00134     }
00135 
00136 
00137     // Otherwise use count/from/level
00138 
00139     txPattern* countPattern = aCountPattern;
00140     MBool ownsCountPattern = MB_FALSE;
00141     const txXPathNode& currNode = aContext->getContextNode();
00142 
00143     // Parse count- and from-attributes
00144 
00145     if (!aCountPattern) {
00146         ownsCountPattern = MB_TRUE;
00147         txNodeTest* nodeTest = 0;
00148         PRUint16 nodeType = txXPathNodeUtils::getNodeType(currNode);
00149         switch (nodeType) {
00150             case txXPathNodeType::ELEMENT_NODE:
00151             {
00152                 nsCOMPtr<nsIAtom> localName =
00153                     txXPathNodeUtils::getLocalName(currNode);
00154                 PRInt32 namespaceID = txXPathNodeUtils::getNamespaceID(currNode);
00155                 nodeTest = new txNameTest(0, localName, namespaceID,
00156                                           txXPathNodeType::ELEMENT_NODE);
00157                 break;
00158             }
00159             case txXPathNodeType::TEXT_NODE:
00160             case txXPathNodeType::CDATA_SECTION_NODE:
00161             {
00162                 nodeTest = new txNodeTypeTest(txNodeTypeTest::TEXT_TYPE);
00163                 break;
00164             }
00165             case txXPathNodeType::PROCESSING_INSTRUCTION_NODE:
00166             {
00167                 txNodeTypeTest* typeTest;
00168                 typeTest = new txNodeTypeTest(txNodeTypeTest::PI_TYPE);
00169                 if (typeTest) {
00170                     nsAutoString nodeName;
00171                     txXPathNodeUtils::getNodeName(currNode, nodeName);
00172                     typeTest->setNodeName(nodeName);
00173                 }
00174                 nodeTest = typeTest;
00175                 break;
00176             }
00177             case txXPathNodeType::COMMENT_NODE:
00178             {
00179                 nodeTest = new txNodeTypeTest(txNodeTypeTest::COMMENT_TYPE);
00180                 break;
00181             }
00182             case txXPathNodeType::DOCUMENT_NODE:
00183             case txXPathNodeType::ATTRIBUTE_NODE:
00184             default:
00185             {
00186                 // this won't match anything as we walk up the tree
00187                 // but it's what the spec says to do
00188                 nodeTest = new txNameTest(0, txXPathAtoms::_asterix, 0,
00189                                           nodeType);
00190                 break;
00191             }
00192         }
00193         NS_ENSURE_TRUE(nodeTest, NS_ERROR_OUT_OF_MEMORY);
00194 
00195         countPattern = new txStepPattern(nodeTest, MB_FALSE);
00196         if (!countPattern) {
00197             // XXX error reporting
00198             delete nodeTest;
00199             return NS_ERROR_OUT_OF_MEMORY;
00200         }
00201     }
00202 
00203 
00204     // Generate list of values depending on the value of the level-attribute
00205 
00206     // level = "single"
00207     if (aLevel == eLevelSingle) {
00208         txXPathTreeWalker walker(currNode);
00209         do {
00210             if (aFromPattern && !walker.isOnNode(currNode) &&
00211                 aFromPattern->matches(walker.getCurrentPosition(), aContext)) {
00212                 break;
00213             }
00214 
00215             if (countPattern->matches(walker.getCurrentPosition(), aContext)) {
00216                 aValues.add(NS_INT32_TO_PTR(getSiblingCount(walker, countPattern,
00217                                                             aContext)));
00218                 break;
00219             }
00220 
00221         } while (walker.moveToParent());
00222 
00223         // Spec says to only match ancestors that are decendants of the
00224         // ancestor that matches the from-pattern, so keep going to make
00225         // sure that there is an ancestor that does.
00226         if (aFromPattern && aValues.getLength()) {
00227             PRBool hasParent;
00228             while ((hasParent = walker.moveToParent())) {
00229                 if (aFromPattern->matches(walker.getCurrentPosition(), aContext)) {
00230                     break;
00231                 }
00232             }
00233 
00234             if (!hasParent) {
00235                 aValues.clear();
00236             }
00237         }
00238     }
00239     // level = "multiple"
00240     else if (aLevel == eLevelMultiple) {
00241         // find all ancestor-or-selfs that matches count until...
00242         txXPathTreeWalker walker(currNode);
00243         MBool matchedFrom = MB_FALSE;
00244         do {
00245             if (aFromPattern && !walker.isOnNode(currNode) &&
00246                 aFromPattern->matches(walker.getCurrentPosition(), aContext)) {
00247                 //... we find one that matches from
00248                 matchedFrom = MB_TRUE;
00249                 break;
00250             }
00251 
00252             if (countPattern->matches(walker.getCurrentPosition(), aContext)) {
00253                 aValues.add(NS_INT32_TO_PTR(getSiblingCount(walker, countPattern,
00254                                                             aContext)));
00255             }
00256         } while (walker.moveToParent());
00257 
00258         // Spec says to only match ancestors that are decendants of the
00259         // ancestor that matches the from-pattern, so if none did then
00260         // we shouldn't search anything
00261         if (aFromPattern && !matchedFrom) {
00262             aValues.clear();
00263         }
00264     }
00265     // level = "any"
00266     else if (aLevel == eLevelAny) {
00267         PRInt32 value = 0;
00268         MBool matchedFrom = MB_FALSE;
00269 
00270         txXPathTreeWalker walker(currNode);
00271         do {
00272             if (aFromPattern && !walker.isOnNode(currNode) &&
00273                 aFromPattern->matches(walker.getCurrentPosition(), aContext)) {
00274                 matchedFrom = MB_TRUE;
00275                 break;
00276             }
00277 
00278             if (countPattern->matches(walker.getCurrentPosition(), aContext)) {
00279                 ++value;
00280             }
00281 
00282         } while (getPrevInDocumentOrder(walker));
00283 
00284         // Spec says to only count nodes that follows the first node that
00285         // matches the from pattern. So so if none did then we shouldn't
00286         // count any
00287         if (aFromPattern && !matchedFrom) {
00288             value = 0;
00289         }
00290 
00291         if (value) {
00292             aValues.add(NS_INT32_TO_PTR(value));
00293         }
00294     }
00295 
00296     if (ownsCountPattern) {
00297         delete countPattern;
00298     }
00299     
00300     return NS_OK;
00301 }
00302 
00303 
00304 nsresult
00305 txXSLTNumber::getCounters(Expr* aGroupSize, Expr* aGroupSeparator,
00306                           Expr* aFormat, txIEvalContext* aContext,
00307                           txList& aCounters, nsAString& aHead,
00308                           nsAString& aTail)
00309 {
00310     aHead.Truncate();
00311     aTail.Truncate();
00312 
00313     nsresult rv = NS_OK;
00314 
00315     nsAutoString groupSeparator;
00316     PRInt32 groupSize = 0;
00317     if (aGroupSize && aGroupSeparator) {
00318         nsRefPtr<txAExprResult> exprRes;
00319         rv = aGroupSize->evaluate(aContext, getter_AddRefs(exprRes));
00320         NS_ENSURE_SUCCESS(rv, rv);
00321 
00322         nsAutoString sizeStr;
00323         exprRes->stringValue(sizeStr);
00324 
00325         double size = Double::toDouble(sizeStr);
00326         groupSize = (PRInt32)size;
00327         if ((double)groupSize != size) {
00328             groupSize = 0;
00329         }
00330 
00331         rv = aGroupSeparator->evaluate(aContext, getter_AddRefs(exprRes));
00332         NS_ENSURE_SUCCESS(rv, rv);
00333         
00334         exprRes->stringValue(groupSeparator);
00335     }
00336 
00337     nsAutoString format;
00338     if (aFormat) {
00339         nsRefPtr<txAExprResult> formatRes;
00340         rv = aFormat->evaluate(aContext, getter_AddRefs(formatRes));
00341         NS_ENSURE_SUCCESS(rv, rv);
00342 
00343         formatRes->stringValue(format);
00344     }
00345     PRUint32 formatLen = format.Length();
00346     PRUint32 formatPos = 0;
00347     PRUnichar ch = 0;
00348 
00349     // start with header
00350     while (formatPos < formatLen &&
00351            !isAlphaNumeric(ch = format.CharAt(formatPos))) {
00352         aHead.Append(ch);
00353         ++formatPos;
00354     }
00355 
00356     // If there are no formatting tokens we need to create a default one.
00357     if (formatPos == formatLen) {
00358         txFormattedCounter* defaultCounter;
00359         rv = txFormattedCounter::getCounterFor(NS_LITERAL_STRING("1"), groupSize,
00360                                                groupSeparator, defaultCounter);
00361         NS_ENSURE_SUCCESS(rv, rv);
00362 
00363         defaultCounter->mSeparator.AssignLiteral(".");
00364         rv = aCounters.add(defaultCounter);
00365         if (NS_FAILED(rv)) {
00366             // XXX ErrorReport: out of memory
00367             delete defaultCounter;
00368             return rv;
00369         }
00370 
00371         return NS_OK;
00372     }
00373 
00374     while (formatPos < formatLen) {
00375         nsAutoString sepToken;
00376         // parse separator token
00377         if (!aCounters.getLength()) {
00378             // Set the first counters separator to default value so that if
00379             // there is only one formatting token and we're formatting a
00380             // value-list longer then one we use the default separator. This
00381             // won't be used when formatting the first value anyway.
00382             sepToken.AssignLiteral(".");
00383         }
00384         else {
00385             while (formatPos < formatLen &&
00386                    !isAlphaNumeric(ch = format.CharAt(formatPos))) {
00387                 sepToken.Append(ch);
00388                 ++formatPos;
00389             }
00390         }
00391 
00392         // if we're at the end of the string then the previous token was the tail
00393         if (formatPos == formatLen) {
00394             aTail = sepToken;
00395             return NS_OK;
00396         }
00397 
00398         // parse formatting token
00399         nsAutoString numToken;
00400         while (formatPos < formatLen &&
00401                isAlphaNumeric(ch = format.CharAt(formatPos))) {
00402             numToken.Append(ch);
00403             ++formatPos;
00404         }
00405         
00406         txFormattedCounter* counter = 0;
00407         rv = txFormattedCounter::getCounterFor(numToken, groupSize,
00408                                                groupSeparator, counter);
00409         if (NS_FAILED(rv)) {
00410             txListIterator iter(&aCounters);
00411             while (iter.hasNext()) {
00412                 delete (txFormattedCounter*)iter.next();
00413             }
00414             aCounters.clear();
00415             return rv;
00416         }
00417 
00418         // Add to list of counters
00419         counter->mSeparator = sepToken;
00420         rv = aCounters.add(counter);
00421         if (NS_FAILED(rv)) {
00422             // XXX ErrorReport: out of memory
00423             txListIterator iter(&aCounters);
00424             while (iter.hasNext()) {
00425                 delete (txFormattedCounter*)iter.next();
00426             }
00427             aCounters.clear();
00428             return rv;
00429         }
00430     }
00431     
00432     return NS_OK;
00433 }
00434 
00435 PRInt32
00436 txXSLTNumber::getSiblingCount(txXPathTreeWalker& aWalker,
00437                               txPattern* aCountPattern,
00438                               txIMatchContext* aContext)
00439 {
00440     PRInt32 value = 1;
00441     while (aWalker.moveToPreviousSibling()) {
00442         if (aCountPattern->matches(aWalker.getCurrentPosition(), aContext)) {
00443             ++value;
00444         }
00445     }
00446     return value;
00447 }
00448 
00449 PRBool
00450 txXSLTNumber::getPrevInDocumentOrder(txXPathTreeWalker& aWalker)
00451 {
00452     if (aWalker.moveToPreviousSibling()) {
00453         while (aWalker.moveToLastChild()) {
00454             // do nothing
00455         }
00456         return PR_TRUE;
00457     }
00458     return aWalker.moveToParent();
00459 }
00460 
00461 #define TX_CHAR_RANGE(ch, a, b) if (ch < a) return MB_FALSE; \
00462     if (ch <= b) return MB_TRUE
00463 #define TX_MATCH_CHAR(ch, a) if (ch < a) return MB_FALSE; \
00464     if (ch == a) return MB_TRUE
00465 
00466 MBool txXSLTNumber::isAlphaNumeric(PRUnichar ch)
00467 {
00468     TX_CHAR_RANGE(ch, 0x0030, 0x0039);
00469     TX_CHAR_RANGE(ch, 0x0041, 0x005A);
00470     TX_CHAR_RANGE(ch, 0x0061, 0x007A);
00471     TX_MATCH_CHAR(ch, 0x00AA);
00472     TX_CHAR_RANGE(ch, 0x00B2, 0x00B3);
00473     TX_MATCH_CHAR(ch, 0x00B5);
00474     TX_CHAR_RANGE(ch, 0x00B9, 0x00BA);
00475     TX_CHAR_RANGE(ch, 0x00BC, 0x00BE);
00476     TX_CHAR_RANGE(ch, 0x00C0, 0x00D6);
00477     TX_CHAR_RANGE(ch, 0x00D8, 0x00F6);
00478     TX_CHAR_RANGE(ch, 0x00F8, 0x021F);
00479     TX_CHAR_RANGE(ch, 0x0222, 0x0233);
00480     TX_CHAR_RANGE(ch, 0x0250, 0x02AD);
00481     TX_CHAR_RANGE(ch, 0x02B0, 0x02B8);
00482     TX_CHAR_RANGE(ch, 0x02BB, 0x02C1);
00483     TX_CHAR_RANGE(ch, 0x02D0, 0x02D1);
00484     TX_CHAR_RANGE(ch, 0x02E0, 0x02E4);
00485     TX_MATCH_CHAR(ch, 0x02EE);
00486     TX_MATCH_CHAR(ch, 0x037A);
00487     TX_MATCH_CHAR(ch, 0x0386);
00488     TX_CHAR_RANGE(ch, 0x0388, 0x038A);
00489     TX_MATCH_CHAR(ch, 0x038C);
00490     TX_CHAR_RANGE(ch, 0x038E, 0x03A1);
00491     TX_CHAR_RANGE(ch, 0x03A3, 0x03CE);
00492     TX_CHAR_RANGE(ch, 0x03D0, 0x03D7);
00493     TX_CHAR_RANGE(ch, 0x03DA, 0x03F3);
00494     TX_CHAR_RANGE(ch, 0x0400, 0x0481);
00495     TX_CHAR_RANGE(ch, 0x048C, 0x04C4);
00496     TX_CHAR_RANGE(ch, 0x04C7, 0x04C8);
00497     TX_CHAR_RANGE(ch, 0x04CB, 0x04CC);
00498     TX_CHAR_RANGE(ch, 0x04D0, 0x04F5);
00499     TX_CHAR_RANGE(ch, 0x04F8, 0x04F9);
00500     TX_CHAR_RANGE(ch, 0x0531, 0x0556);
00501     TX_MATCH_CHAR(ch, 0x0559);
00502     TX_CHAR_RANGE(ch, 0x0561, 0x0587);
00503     TX_CHAR_RANGE(ch, 0x05D0, 0x05EA);
00504     TX_CHAR_RANGE(ch, 0x05F0, 0x05F2);
00505     TX_CHAR_RANGE(ch, 0x0621, 0x063A);
00506     TX_CHAR_RANGE(ch, 0x0640, 0x064A);
00507     TX_CHAR_RANGE(ch, 0x0660, 0x0669);
00508     TX_CHAR_RANGE(ch, 0x0671, 0x06D3);
00509     TX_MATCH_CHAR(ch, 0x06D5);
00510     TX_CHAR_RANGE(ch, 0x06E5, 0x06E6);
00511     TX_CHAR_RANGE(ch, 0x06F0, 0x06FC);
00512     TX_MATCH_CHAR(ch, 0x0710);
00513     TX_CHAR_RANGE(ch, 0x0712, 0x072C);
00514     TX_CHAR_RANGE(ch, 0x0780, 0x07A5);
00515     TX_CHAR_RANGE(ch, 0x0905, 0x0939);
00516     TX_MATCH_CHAR(ch, 0x093D);
00517     TX_MATCH_CHAR(ch, 0x0950);
00518     TX_CHAR_RANGE(ch, 0x0958, 0x0961);
00519     TX_CHAR_RANGE(ch, 0x0966, 0x096F);
00520     TX_CHAR_RANGE(ch, 0x0985, 0x098C);
00521     TX_CHAR_RANGE(ch, 0x098F, 0x0990);
00522     TX_CHAR_RANGE(ch, 0x0993, 0x09A8);
00523     TX_CHAR_RANGE(ch, 0x09AA, 0x09B0);
00524     TX_MATCH_CHAR(ch, 0x09B2);
00525     TX_CHAR_RANGE(ch, 0x09B6, 0x09B9);
00526     TX_CHAR_RANGE(ch, 0x09DC, 0x09DD);
00527     TX_CHAR_RANGE(ch, 0x09DF, 0x09E1);
00528     TX_CHAR_RANGE(ch, 0x09E6, 0x09F1);
00529     TX_CHAR_RANGE(ch, 0x09F4, 0x09F9);
00530     TX_CHAR_RANGE(ch, 0x0A05, 0x0A0A);
00531     TX_CHAR_RANGE(ch, 0x0A0F, 0x0A10);
00532     TX_CHAR_RANGE(ch, 0x0A13, 0x0A28);
00533     TX_CHAR_RANGE(ch, 0x0A2A, 0x0A30);
00534     TX_CHAR_RANGE(ch, 0x0A32, 0x0A33);
00535     TX_CHAR_RANGE(ch, 0x0A35, 0x0A36);
00536     TX_CHAR_RANGE(ch, 0x0A38, 0x0A39);
00537     TX_CHAR_RANGE(ch, 0x0A59, 0x0A5C);
00538     TX_MATCH_CHAR(ch, 0x0A5E);
00539     TX_CHAR_RANGE(ch, 0x0A66, 0x0A6F);
00540     TX_CHAR_RANGE(ch, 0x0A72, 0x0A74);
00541     TX_CHAR_RANGE(ch, 0x0A85, 0x0A8B);
00542     TX_MATCH_CHAR(ch, 0x0A8D);
00543     TX_CHAR_RANGE(ch, 0x0A8F, 0x0A91);
00544     TX_CHAR_RANGE(ch, 0x0A93, 0x0AA8);
00545     TX_CHAR_RANGE(ch, 0x0AAA, 0x0AB0);
00546     TX_CHAR_RANGE(ch, 0x0AB2, 0x0AB3);
00547     TX_CHAR_RANGE(ch, 0x0AB5, 0x0AB9);
00548     TX_MATCH_CHAR(ch, 0x0ABD);
00549     TX_MATCH_CHAR(ch, 0x0AD0);
00550     TX_MATCH_CHAR(ch, 0x0AE0);
00551     TX_CHAR_RANGE(ch, 0x0AE6, 0x0AEF);
00552     TX_CHAR_RANGE(ch, 0x0B05, 0x0B0C);
00553     TX_CHAR_RANGE(ch, 0x0B0F, 0x0B10);
00554     TX_CHAR_RANGE(ch, 0x0B13, 0x0B28);
00555     TX_CHAR_RANGE(ch, 0x0B2A, 0x0B30);
00556     TX_CHAR_RANGE(ch, 0x0B32, 0x0B33);
00557     TX_CHAR_RANGE(ch, 0x0B36, 0x0B39);
00558     TX_MATCH_CHAR(ch, 0x0B3D);
00559     TX_CHAR_RANGE(ch, 0x0B5C, 0x0B5D);
00560     TX_CHAR_RANGE(ch, 0x0B5F, 0x0B61);
00561     TX_CHAR_RANGE(ch, 0x0B66, 0x0B6F);
00562     TX_CHAR_RANGE(ch, 0x0B85, 0x0B8A);
00563     TX_CHAR_RANGE(ch, 0x0B8E, 0x0B90);
00564     TX_CHAR_RANGE(ch, 0x0B92, 0x0B95);
00565     TX_CHAR_RANGE(ch, 0x0B99, 0x0B9A);
00566     TX_MATCH_CHAR(ch, 0x0B9C);
00567     TX_CHAR_RANGE(ch, 0x0B9E, 0x0B9F);
00568     TX_CHAR_RANGE(ch, 0x0BA3, 0x0BA4);
00569     TX_CHAR_RANGE(ch, 0x0BA8, 0x0BAA);
00570     TX_CHAR_RANGE(ch, 0x0BAE, 0x0BB5);
00571     TX_CHAR_RANGE(ch, 0x0BB7, 0x0BB9);
00572     TX_CHAR_RANGE(ch, 0x0BE7, 0x0BF2);
00573     TX_CHAR_RANGE(ch, 0x0C05, 0x0C0C);
00574     TX_CHAR_RANGE(ch, 0x0C0E, 0x0C10);
00575     TX_CHAR_RANGE(ch, 0x0C12, 0x0C28);
00576     TX_CHAR_RANGE(ch, 0x0C2A, 0x0C33);
00577     TX_CHAR_RANGE(ch, 0x0C35, 0x0C39);
00578     TX_CHAR_RANGE(ch, 0x0C60, 0x0C61);
00579     TX_CHAR_RANGE(ch, 0x0C66, 0x0C6F);
00580     TX_CHAR_RANGE(ch, 0x0C85, 0x0C8C);
00581     TX_CHAR_RANGE(ch, 0x0C8E, 0x0C90);
00582     TX_CHAR_RANGE(ch, 0x0C92, 0x0CA8);
00583     TX_CHAR_RANGE(ch, 0x0CAA, 0x0CB3);
00584     TX_CHAR_RANGE(ch, 0x0CB5, 0x0CB9);
00585     TX_MATCH_CHAR(ch, 0x0CDE);
00586     TX_CHAR_RANGE(ch, 0x0CE0, 0x0CE1);
00587     TX_CHAR_RANGE(ch, 0x0CE6, 0x0CEF);
00588     TX_CHAR_RANGE(ch, 0x0D05, 0x0D0C);
00589     TX_CHAR_RANGE(ch, 0x0D0E, 0x0D10);
00590     TX_CHAR_RANGE(ch, 0x0D12, 0x0D28);
00591     TX_CHAR_RANGE(ch, 0x0D2A, 0x0D39);
00592     TX_CHAR_RANGE(ch, 0x0D60, 0x0D61);
00593     TX_CHAR_RANGE(ch, 0x0D66, 0x0D6F);
00594     TX_CHAR_RANGE(ch, 0x0D85, 0x0D96);
00595     TX_CHAR_RANGE(ch, 0x0D9A, 0x0DB1);
00596     TX_CHAR_RANGE(ch, 0x0DB3, 0x0DBB);
00597     TX_MATCH_CHAR(ch, 0x0DBD);
00598     TX_CHAR_RANGE(ch, 0x0DC0, 0x0DC6);
00599     TX_CHAR_RANGE(ch, 0x0E01, 0x0E30);
00600     TX_CHAR_RANGE(ch, 0x0E32, 0x0E33);
00601     TX_CHAR_RANGE(ch, 0x0E40, 0x0E46);
00602     TX_CHAR_RANGE(ch, 0x0E50, 0x0E59);
00603     TX_CHAR_RANGE(ch, 0x0E81, 0x0E82);
00604     TX_MATCH_CHAR(ch, 0x0E84);
00605     TX_CHAR_RANGE(ch, 0x0E87, 0x0E88);
00606     TX_MATCH_CHAR(ch, 0x0E8A);
00607     TX_MATCH_CHAR(ch, 0x0E8D);
00608     TX_CHAR_RANGE(ch, 0x0E94, 0x0E97);
00609     TX_CHAR_RANGE(ch, 0x0E99, 0x0E9F);
00610     TX_CHAR_RANGE(ch, 0x0EA1, 0x0EA3);
00611     TX_MATCH_CHAR(ch, 0x0EA5);
00612     TX_MATCH_CHAR(ch, 0x0EA7);
00613     TX_CHAR_RANGE(ch, 0x0EAA, 0x0EAB);
00614     TX_CHAR_RANGE(ch, 0x0EAD, 0x0EB0);
00615     TX_CHAR_RANGE(ch, 0x0EB2, 0x0EB3);
00616     TX_MATCH_CHAR(ch, 0x0EBD);
00617     TX_CHAR_RANGE(ch, 0x0EC0, 0x0EC4);
00618     TX_MATCH_CHAR(ch, 0x0EC6);
00619     TX_CHAR_RANGE(ch, 0x0ED0, 0x0ED9);
00620     TX_CHAR_RANGE(ch, 0x0EDC, 0x0EDD);
00621     TX_MATCH_CHAR(ch, 0x0F00);
00622     TX_CHAR_RANGE(ch, 0x0F20, 0x0F33);
00623     TX_CHAR_RANGE(ch, 0x0F40, 0x0F47);
00624     TX_CHAR_RANGE(ch, 0x0F49, 0x0F6A);
00625     TX_CHAR_RANGE(ch, 0x0F88, 0x0F8B);
00626     TX_CHAR_RANGE(ch, 0x1000, 0x1021);
00627     TX_CHAR_RANGE(ch, 0x1023, 0x1027);
00628     TX_CHAR_RANGE(ch, 0x1029, 0x102A);
00629     TX_CHAR_RANGE(ch, 0x1040, 0x1049);
00630     TX_CHAR_RANGE(ch, 0x1050, 0x1055);
00631     TX_CHAR_RANGE(ch, 0x10A0, 0x10C5);
00632     TX_CHAR_RANGE(ch, 0x10D0, 0x10F6);
00633     TX_CHAR_RANGE(ch, 0x1100, 0x1159);
00634     TX_CHAR_RANGE(ch, 0x115F, 0x11A2);
00635     TX_CHAR_RANGE(ch, 0x11A8, 0x11F9);
00636     TX_CHAR_RANGE(ch, 0x1200, 0x1206);
00637     TX_CHAR_RANGE(ch, 0x1208, 0x1246);
00638     TX_MATCH_CHAR(ch, 0x1248);
00639     TX_CHAR_RANGE(ch, 0x124A, 0x124D);
00640     TX_CHAR_RANGE(ch, 0x1250, 0x1256);
00641     TX_MATCH_CHAR(ch, 0x1258);
00642     TX_CHAR_RANGE(ch, 0x125A, 0x125D);
00643     TX_CHAR_RANGE(ch, 0x1260, 0x1286);
00644     TX_MATCH_CHAR(ch, 0x1288);
00645     TX_CHAR_RANGE(ch, 0x128A, 0x128D);
00646     TX_CHAR_RANGE(ch, 0x1290, 0x12AE);
00647     TX_MATCH_CHAR(ch, 0x12B0);
00648     TX_CHAR_RANGE(ch, 0x12B2, 0x12B5);
00649     TX_CHAR_RANGE(ch, 0x12B8, 0x12BE);
00650     TX_MATCH_CHAR(ch, 0x12C0);
00651     TX_CHAR_RANGE(ch, 0x12C2, 0x12C5);
00652     TX_CHAR_RANGE(ch, 0x12C8, 0x12CE);
00653     TX_CHAR_RANGE(ch, 0x12D0, 0x12D6);
00654     TX_CHAR_RANGE(ch, 0x12D8, 0x12EE);
00655     TX_CHAR_RANGE(ch, 0x12F0, 0x130E);
00656     TX_MATCH_CHAR(ch, 0x1310);
00657     TX_CHAR_RANGE(ch, 0x1312, 0x1315);
00658     TX_CHAR_RANGE(ch, 0x1318, 0x131E);
00659     TX_CHAR_RANGE(ch, 0x1320, 0x1346);
00660     TX_CHAR_RANGE(ch, 0x1348, 0x135A);
00661     TX_CHAR_RANGE(ch, 0x1369, 0x137C);
00662     TX_CHAR_RANGE(ch, 0x13A0, 0x13F4);
00663     TX_CHAR_RANGE(ch, 0x1401, 0x166C);
00664     TX_CHAR_RANGE(ch, 0x166F, 0x1676);
00665     TX_CHAR_RANGE(ch, 0x1681, 0x169A);
00666     TX_CHAR_RANGE(ch, 0x16A0, 0x16EA);
00667     TX_CHAR_RANGE(ch, 0x16EE, 0x16F0);
00668     TX_CHAR_RANGE(ch, 0x1780, 0x17B3);
00669     TX_CHAR_RANGE(ch, 0x17E0, 0x17E9);
00670     TX_CHAR_RANGE(ch, 0x1810, 0x1819);
00671     TX_CHAR_RANGE(ch, 0x1820, 0x1877);
00672     TX_CHAR_RANGE(ch, 0x1880, 0x18A8);
00673     TX_CHAR_RANGE(ch, 0x1E00, 0x1E9B);
00674     TX_CHAR_RANGE(ch, 0x1EA0, 0x1EF9);
00675     TX_CHAR_RANGE(ch, 0x1F00, 0x1F15);
00676     TX_CHAR_RANGE(ch, 0x1F18, 0x1F1D);
00677     TX_CHAR_RANGE(ch, 0x1F20, 0x1F45);
00678     TX_CHAR_RANGE(ch, 0x1F48, 0x1F4D);
00679     TX_CHAR_RANGE(ch, 0x1F50, 0x1F57);
00680     TX_MATCH_CHAR(ch, 0x1F59);
00681     TX_MATCH_CHAR(ch, 0x1F5B);
00682     TX_MATCH_CHAR(ch, 0x1F5D);
00683     TX_CHAR_RANGE(ch, 0x1F5F, 0x1F7D);
00684     TX_CHAR_RANGE(ch, 0x1F80, 0x1FB4);
00685     TX_CHAR_RANGE(ch, 0x1FB6, 0x1FBC);
00686     TX_MATCH_CHAR(ch, 0x1FBE);
00687     TX_CHAR_RANGE(ch, 0x1FC2, 0x1FC4);
00688     TX_CHAR_RANGE(ch, 0x1FC6, 0x1FCC);
00689     TX_CHAR_RANGE(ch, 0x1FD0, 0x1FD3);
00690     TX_CHAR_RANGE(ch, 0x1FD6, 0x1FDB);
00691     TX_CHAR_RANGE(ch, 0x1FE0, 0x1FEC);
00692     TX_CHAR_RANGE(ch, 0x1FF2, 0x1FF4);
00693     TX_CHAR_RANGE(ch, 0x1FF6, 0x1FFC);
00694     TX_MATCH_CHAR(ch, 0x2070);
00695     TX_CHAR_RANGE(ch, 0x2074, 0x2079);
00696     TX_CHAR_RANGE(ch, 0x207F, 0x2089);
00697     TX_MATCH_CHAR(ch, 0x2102);
00698     TX_MATCH_CHAR(ch, 0x2107);
00699     TX_CHAR_RANGE(ch, 0x210A, 0x2113);
00700     TX_MATCH_CHAR(ch, 0x2115);
00701     TX_CHAR_RANGE(ch, 0x2119, 0x211D);
00702     TX_MATCH_CHAR(ch, 0x2124);
00703     TX_MATCH_CHAR(ch, 0x2126);
00704     TX_MATCH_CHAR(ch, 0x2128);
00705     TX_CHAR_RANGE(ch, 0x212A, 0x212D);
00706     TX_CHAR_RANGE(ch, 0x212F, 0x2131);
00707     TX_CHAR_RANGE(ch, 0x2133, 0x2139);
00708     TX_CHAR_RANGE(ch, 0x2153, 0x2183);
00709     TX_CHAR_RANGE(ch, 0x2460, 0x249B);
00710     TX_MATCH_CHAR(ch, 0x24EA);
00711     TX_CHAR_RANGE(ch, 0x2776, 0x2793);
00712     TX_CHAR_RANGE(ch, 0x3005, 0x3007);
00713     TX_CHAR_RANGE(ch, 0x3021, 0x3029);
00714     TX_CHAR_RANGE(ch, 0x3031, 0x3035);
00715     TX_CHAR_RANGE(ch, 0x3038, 0x303A);
00716     TX_CHAR_RANGE(ch, 0x3041, 0x3094);
00717     TX_CHAR_RANGE(ch, 0x309D, 0x309E);
00718     TX_CHAR_RANGE(ch, 0x30A1, 0x30FA);
00719     TX_CHAR_RANGE(ch, 0x30FC, 0x30FE);
00720     TX_CHAR_RANGE(ch, 0x3105, 0x312C);
00721     TX_CHAR_RANGE(ch, 0x3131, 0x318E);
00722     TX_CHAR_RANGE(ch, 0x3192, 0x3195);
00723     TX_CHAR_RANGE(ch, 0x31A0, 0x31B7);
00724     TX_CHAR_RANGE(ch, 0x3220, 0x3229);
00725     TX_CHAR_RANGE(ch, 0x3280, 0x3289);
00726     TX_MATCH_CHAR(ch, 0x3400);
00727     TX_MATCH_CHAR(ch, 0x4DB5);
00728     TX_MATCH_CHAR(ch, 0x4E00);
00729     TX_MATCH_CHAR(ch, 0x9FA5);
00730     TX_CHAR_RANGE(ch, 0xA000, 0xA48C);
00731     TX_MATCH_CHAR(ch, 0xAC00);
00732     TX_MATCH_CHAR(ch, 0xD7A3);
00733     TX_CHAR_RANGE(ch, 0xF900, 0xFA2D);
00734     TX_CHAR_RANGE(ch, 0xFB00, 0xFB06);
00735     TX_CHAR_RANGE(ch, 0xFB13, 0xFB17);
00736     TX_MATCH_CHAR(ch, 0xFB1D);
00737     TX_CHAR_RANGE(ch, 0xFB1F, 0xFB28);
00738     TX_CHAR_RANGE(ch, 0xFB2A, 0xFB36);
00739     TX_CHAR_RANGE(ch, 0xFB38, 0xFB3C);
00740     TX_MATCH_CHAR(ch, 0xFB3E);
00741     TX_CHAR_RANGE(ch, 0xFB40, 0xFB41);
00742     TX_CHAR_RANGE(ch, 0xFB43, 0xFB44);
00743     TX_CHAR_RANGE(ch, 0xFB46, 0xFBB1);
00744     TX_CHAR_RANGE(ch, 0xFBD3, 0xFD3D);
00745     TX_CHAR_RANGE(ch, 0xFD50, 0xFD8F);
00746     TX_CHAR_RANGE(ch, 0xFD92, 0xFDC7);
00747     TX_CHAR_RANGE(ch, 0xFDF0, 0xFDFB);
00748     TX_CHAR_RANGE(ch, 0xFE70, 0xFE72);
00749     TX_MATCH_CHAR(ch, 0xFE74);
00750     TX_CHAR_RANGE(ch, 0xFE76, 0xFEFC);
00751     TX_CHAR_RANGE(ch, 0xFF10, 0xFF19);
00752     TX_CHAR_RANGE(ch, 0xFF21, 0xFF3A);
00753     TX_CHAR_RANGE(ch, 0xFF41, 0xFF5A);
00754     TX_CHAR_RANGE(ch, 0xFF66, 0xFFBE);
00755     TX_CHAR_RANGE(ch, 0xFFC2, 0xFFC7);
00756     TX_CHAR_RANGE(ch, 0xFFCA, 0xFFCF);
00757     TX_CHAR_RANGE(ch, 0xFFD2, 0xFFD7);
00758     return MB_FALSE;
00759 }