Back to index

lightning-sunbird  0.9+nobinonly
nsUnicodeToGBK.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00048 #include "nsUnicodeToGBK.h"
00049 #include "nsICharRepresentable.h"
00050 #include "nsUCvCnDll.h"
00051 #include "gbku.h"
00052 #include "uconvutil.h"
00053 #include "nsUnicharUtils.h"
00054 
00055 //-------------------------------------------------------------
00056 // Global table initialization function defined in gbku.h
00057 //-------------------------------------------------------------
00058 
00059 static const PRInt16 g_2BytesShiftTable[] = {
00060  0, u2BytesCharset,
00061  ShiftCell(0,0,0,0,0,0,0,0)
00062 };
00063 static const PRInt16 g_4BytesGB18030ShiftTable[] = {
00064  0, u4BytesGB18030Charset,
00065  ShiftCell(0,0,0,0,0,0,0,0)
00066 };
00067 
00068 //-----------------------------------------------------------------------
00069 //  Private class used by nsUnicodeToGB18030 and nsUnicodeToGB18030Font0
00070 //    nsUnicodeToGB18030Uniq2Bytes
00071 //-----------------------------------------------------------------------
00072 static const PRUint16 g_uf_gb18030_2bytes[] = {
00073 #include "gb18030uniq2b.uf"
00074 };
00075 class nsUnicodeToGB18030Uniq2Bytes : public nsTableEncoderSupport
00076 {
00077 public: 
00078   nsUnicodeToGB18030Uniq2Bytes() 
00079     : nsTableEncoderSupport((uShiftTable*) &g_2BytesShiftTable,
00080                             (uMappingTable*) &g_uf_gb18030_2bytes, 2) {};
00081 protected: 
00082 };
00083 //-----------------------------------------------------------------------
00084 //  Private class used by nsUnicodeToGB18030
00085 //    nsUnicodeTo4BytesGB18030
00086 //-----------------------------------------------------------------------
00087 static const PRUint16 g_uf_gb18030_4bytes[] = {
00088 #include "gb180304bytes.uf"
00089 };
00090 class nsUnicodeTo4BytesGB18030 : public nsTableEncoderSupport
00091 {
00092 public: 
00093   nsUnicodeTo4BytesGB18030()
00094     : nsTableEncoderSupport( (uShiftTable*) &g_4BytesGB18030ShiftTable,
00095                              (uMappingTable*) &g_uf_gb18030_4bytes, 4) {};
00096 protected: 
00097 };
00098 //-----------------------------------------------------------------------
00099 //  Private class used by nsUnicodeToGBK
00100 //    nsUnicodeToGBKUniq2Bytes
00101 //-----------------------------------------------------------------------
00102 static const PRUint16 g_uf_gbk_2bytes[] = {
00103 #include "gbkuniq2b.uf"
00104 };
00105 class nsUnicodeToGBKUniq2Bytes : public nsTableEncoderSupport
00106 {
00107 public: 
00108   nsUnicodeToGBKUniq2Bytes()
00109     : nsTableEncoderSupport( (uShiftTable*) &g_2BytesShiftTable,
00110                              (uMappingTable*) &g_uf_gbk_2bytes, 2) {};
00111 protected: 
00112 };
00113 //-----------------------------------------------------------------------
00114 //  nsUnicodeToGB18030
00115 //-----------------------------------------------------------------------
00116 void nsUnicodeToGB18030::CreateExtensionEncoder()
00117 {
00118   mExtensionEncoder = new nsUnicodeToGB18030Uniq2Bytes();
00119 }
00120 void nsUnicodeToGB18030::Create4BytesEncoder()
00121 {
00122   m4BytesEncoder = new nsUnicodeTo4BytesGB18030();
00123 }
00124 
00125 PRBool nsUnicodeToGB18030::EncodeSurrogate(
00126   PRUnichar aSurrogateHigh,
00127   PRUnichar aSurrogateLow,
00128   char* aOut)
00129 {
00130   if( IS_HIGH_SURROGATE(aSurrogateHigh) && 
00131       IS_LOW_SURROGATE(aSurrogateLow) )
00132   {
00133     // notice that idx does not include the 0x10000 
00134     PRUint32 idx = ((aSurrogateHigh - (PRUnichar)0xD800) << 10 ) |
00135                    (aSurrogateLow - (PRUnichar) 0xDC00);
00136 
00137     unsigned char *out = (unsigned char*) aOut;
00138     // notice this is from 0x90 for supplment planes
00139     out[0] = (idx / (10*126*10)) + 0x90; 
00140     idx %= (10*126*10);
00141     out[1] = (idx / (10*126)) + 0x30;
00142     idx %= (10*126);
00143     out[2] = (idx / (10)) + 0x81;
00144     out[3] = (idx % 10) + 0x30;
00145     return PR_TRUE;
00146   } 
00147   return PR_FALSE; 
00148 } 
00149 
00150 #ifdef MOZ_EXTRA_X11CONVERTERS
00151 //-----------------------------------------------------------------------
00152 //  nsUnicodeToGB18030Font0
00153 //-----------------------------------------------------------------------
00154 NS_IMETHODIMP nsUnicodeToGB18030Font0::GetMaxLength(const PRUnichar * aSrc, 
00155                                               PRInt32 aSrcLength,
00156                                               PRInt32 * aDestLength)
00157 {
00158   *aDestLength = 2 * aSrcLength;
00159   return NS_OK_UDEC_EXACTLENGTH; // font encoding is only 2 bytes
00160 }
00161 void nsUnicodeToGB18030Font0::Create4BytesEncoder()
00162 {
00163   m4BytesEncoder = nsnull;
00164 }
00165 
00166 NS_IMETHODIMP nsUnicodeToGB18030Font0::FillInfo(PRUint32 *aInfo)
00167 {
00168   nsresult rv = nsUnicodeToGB18030::FillInfo(aInfo); // call the super class
00169   if(NS_SUCCEEDED(rv))
00170   {
00171     // mark the first 128 bits as 0. 4 x 32 bits = 128 bits
00172     aInfo[0] = aInfo[1] = aInfo[2] = aInfo[3] = 0;
00173   }
00174   return rv;
00175 }
00176 
00177 //-----------------------------------------------------------------------
00178 //  nsUnicodeToGB18030Font1
00179 //-----------------------------------------------------------------------
00180 nsUnicodeToGB18030Font1::nsUnicodeToGB18030Font1()
00181     : nsTableEncoderSupport( (uShiftTable*) &g_2BytesShiftTable,
00182                              (uMappingTable*) &g_uf_gb18030_4bytes, 4)
00183 {
00184 
00185 }
00186 
00187 NS_IMETHODIMP nsUnicodeToGB18030Font1::FillInfo(PRUint32 *aInfo)
00188 {
00189   nsresult res = nsTableEncoderSupport::FillInfo(aInfo);
00190   PRUint32 i;
00191 
00192   for(i = (0x0000 >> 5); i<(0x0600 >> 5); i++)
00193     aInfo[i] = 0;
00194 
00195   // handle Arabic script
00196   for(i = (0x0600 >> 5); i<(0x06e0 >> 5); i++)
00197     aInfo[i] = 0;
00198   SET_REPRESENTABLE(aInfo, 0x060c);
00199   SET_REPRESENTABLE(aInfo, 0x061b);
00200   SET_REPRESENTABLE(aInfo, 0x061f);
00201   for(i = 0x0626;i <=0x0628;i++)
00202     SET_REPRESENTABLE(aInfo, i);
00203   SET_REPRESENTABLE(aInfo, 0x062a);
00204   for(i = 0x062c;i <=0x062f;i++)
00205     SET_REPRESENTABLE(aInfo, i);
00206   for(i = 0x0631;i <=0x0634;i++)
00207     SET_REPRESENTABLE(aInfo, i);
00208   for(i = 0x0639;i <=0x063a;i++)
00209     SET_REPRESENTABLE(aInfo, i);
00210   for(i = 0x0640;i <=0x064a;i++)
00211     SET_REPRESENTABLE(aInfo, i);
00212   for(i = 0x0674;i <=0x0678;i++)
00213     SET_REPRESENTABLE(aInfo, i);
00214   SET_REPRESENTABLE(aInfo, 0x067e);
00215   SET_REPRESENTABLE(aInfo, 0x0686);
00216   SET_REPRESENTABLE(aInfo, 0x0698);
00217   SET_REPRESENTABLE(aInfo, 0x06a9);
00218   SET_REPRESENTABLE(aInfo, 0x06ad);
00219   SET_REPRESENTABLE(aInfo, 0x06af);
00220   SET_REPRESENTABLE(aInfo, 0x06be);
00221   for(i = 0x06c5;i <=0x06c9;i++)
00222     SET_REPRESENTABLE(aInfo, i);
00223   for(i = 0x06cb;i <=0x06cc;i++)
00224     SET_REPRESENTABLE(aInfo, i);
00225   SET_REPRESENTABLE(aInfo, 0x06d0);
00226   SET_REPRESENTABLE(aInfo, 0x06d5);
00227   // end of Arabic script
00228 
00229   for(i = (0x06e0 >> 5); i<(0x0f00 >> 5); i++)
00230     aInfo[i] = 0;
00231 
00232   // handle Tibetan script
00233   CLEAR_REPRESENTABLE(aInfo, 0x0f48);
00234   for(i = 0x0f6b;i <0x0f71;i++)
00235     CLEAR_REPRESENTABLE(aInfo, i);
00236   for(i = 0x0f8c;i <0x0f90;i++)
00237     CLEAR_REPRESENTABLE(aInfo, i);
00238   CLEAR_REPRESENTABLE(aInfo, 0x0f98);
00239   CLEAR_REPRESENTABLE(aInfo, 0x0fbd);
00240   CLEAR_REPRESENTABLE(aInfo, 0x0fcd);
00241   CLEAR_REPRESENTABLE(aInfo, 0x0fce);
00242   for(i = 0x0fd0;i <0x0fe0;i++)
00243     CLEAR_REPRESENTABLE(aInfo, i);
00244   // end of Tibetan script
00245 
00246   for(i = (0x0fe0 >> 5); i<(0x1800 >> 5); i++)
00247     aInfo[i] = 0;
00248 
00249   // handle Mongolian script
00250   CLEAR_REPRESENTABLE(aInfo, 0x180f);
00251   for(i = 0x181a;i <0x1820;i++)
00252     CLEAR_REPRESENTABLE(aInfo, i);
00253   for(i = 0x1878;i <0x1880;i++)
00254     CLEAR_REPRESENTABLE(aInfo, i);
00255   for(i = 0x18aa;i <0x18c0;i++)
00256     CLEAR_REPRESENTABLE(aInfo, i);
00257   // end of Mongolian script
00258 
00259   for(i = (0x18c0 >> 5); i<(0x3400 >> 5); i++)
00260     aInfo[i] = 0;
00261 
00262   // handle Han Ideograph
00263   // remove above U+4db5
00264   //   remove U+4db6 to U+4dbf one by one
00265   for(i = 0x4db6;i <0x4dc0;i++)
00266     CLEAR_REPRESENTABLE(aInfo, i);
00267   // end of Han Ideograph
00268 
00269   //   remove  U+4dc0 to 0xa000
00270   for(i = (0x4dc0 >> 5);i < (0xa000>>5) ; i++)
00271     aInfo[i] = 0;
00272 
00273   // handle Yi script
00274   for(i = 0xa48d;i <0xa490;i++)
00275     CLEAR_REPRESENTABLE(aInfo, i);
00276 
00277   CLEAR_REPRESENTABLE(aInfo, 0xa4a2);
00278   CLEAR_REPRESENTABLE(aInfo, 0xa4a3);
00279   CLEAR_REPRESENTABLE(aInfo, 0xa4b4);
00280   CLEAR_REPRESENTABLE(aInfo, 0xa4c1);
00281   CLEAR_REPRESENTABLE(aInfo, 0xa4c5);
00282 
00283   for(i = 0xa4c7;i <0xa4e0;i++)
00284     CLEAR_REPRESENTABLE(aInfo, i);
00285   // end of Yi script
00286 
00287   for(i = (0xa4e0 >> 5);i < (0xfb00>>5) ; i++)
00288     aInfo[i] = 0;
00289 
00290   // handle Arabic script
00291   for(i = (0xfb00 >> 5);i < (0xfc00>>5) ; i++)
00292     aInfo[i] = 0;
00293   for(i = 0xfb56;i <=0xfb59;i++)
00294     SET_REPRESENTABLE(aInfo, i);
00295   for(i = 0xfb7a;i <=0xfb95;i++)
00296     SET_REPRESENTABLE(aInfo, i);
00297   for(i = 0xfbaa;i <=0xfbad;i++)
00298     SET_REPRESENTABLE(aInfo, i);
00299   for(i = 0xfbd3;i <=0xfbff;i++)
00300     SET_REPRESENTABLE(aInfo, i);
00301   // end of Arabic script
00302 
00303   for(i = (0xfc00 >> 5);i < (0xfe80>>5) ; i++)
00304     aInfo[i] = 0;
00305 
00306   // handle Arabic script
00307   for(i = (0xfe80 >> 5);i < (0x10000>>5) ; i++)
00308     aInfo[i] = 0;
00309   for(i = 0xfe89;i <=0xfe98;i++)
00310     SET_REPRESENTABLE(aInfo, i);
00311   for(i = 0xfe9d;i <=0xfeaa;i++)
00312     SET_REPRESENTABLE(aInfo, i);
00313   SET_REPRESENTABLE(aInfo, 0xfead);
00314   for(i = 0xfeae;i <=0xfeb8;i++)
00315     SET_REPRESENTABLE(aInfo, i);
00316   for(i = 0xfec9;i <=0xfef4;i++)
00317     SET_REPRESENTABLE(aInfo, i);
00318   SET_REPRESENTABLE(aInfo, 0xfefb);
00319   SET_REPRESENTABLE(aInfo, 0xfefc);
00320   // end of Arabic script
00321   return res;
00322 }
00323 #endif
00324 //----------------------------------------------------------------------
00325 // Class nsUnicodeToGBK [implementation]
00326 
00327 nsUnicodeToGBK::nsUnicodeToGBK(PRUint32 aMaxLength) :
00328   nsEncoderSupport(aMaxLength)
00329 {
00330   mExtensionEncoder = nsnull;
00331   m4BytesEncoder = nsnull;
00332   mUtil.InitToGBKTable();
00333   mSurrogateHigh = 0;
00334 }
00335 void nsUnicodeToGBK::CreateExtensionEncoder()
00336 {
00337   mExtensionEncoder = new nsUnicodeToGBKUniq2Bytes();
00338 }
00339 void nsUnicodeToGBK::Create4BytesEncoder()
00340 {
00341   m4BytesEncoder = nsnull;
00342 }
00343 PRBool nsUnicodeToGBK::TryExtensionEncoder(
00344   PRUnichar aChar,
00345   char* aOut,
00346   PRInt32 *aOutLen
00347 )
00348 {
00349   if( IS_HIGH_SURROGATE(aChar) || 
00350       IS_LOW_SURROGATE(aChar) )
00351   {
00352     // performance tune for surrogate characters
00353     return PR_FALSE;
00354   }
00355   if(! mExtensionEncoder )
00356     CreateExtensionEncoder();
00357   if(mExtensionEncoder) 
00358   {
00359     PRInt32 len = 1;
00360     nsresult res = NS_OK;
00361     res = mExtensionEncoder->Convert(&aChar, &len, aOut, aOutLen);
00362     if(NS_SUCCEEDED(res) && (*aOutLen > 0))
00363       return PR_TRUE;
00364   }
00365   return PR_FALSE;
00366 }
00367 
00368 PRBool nsUnicodeToGBK::Try4BytesEncoder(
00369   PRUnichar aChar,
00370   char* aOut,
00371   PRInt32 *aOutLen
00372 )
00373 {
00374   if( IS_HIGH_SURROGATE(aChar) || 
00375       IS_LOW_SURROGATE(aChar) )
00376   {
00377     // performance tune for surrogate characters
00378     return PR_FALSE;
00379   }
00380   if(! m4BytesEncoder )
00381     Create4BytesEncoder();
00382   if(m4BytesEncoder) 
00383   {
00384     PRInt32 len = 1;
00385     nsresult res = NS_OK;
00386     res = m4BytesEncoder->Convert(&aChar, &len, aOut, aOutLen);
00387     NS_ASSERTION(NS_FAILED(res) || ((1 == len) && (4 == *aOutLen)),
00388       "unexpect conversion length");
00389     if(NS_SUCCEEDED(res) && (*aOutLen > 0))
00390       return PR_TRUE;
00391   }
00392   return PR_FALSE;
00393 }
00394 PRBool nsUnicodeToGBK::EncodeSurrogate(
00395   PRUnichar aSurrogateHigh,
00396   PRUnichar aSurrogateLow,
00397   char* aOut)
00398 {
00399   return PR_FALSE; // GBK cannot encode Surrogate, let the subclass encode it.
00400 } 
00401 
00402 NS_IMETHODIMP nsUnicodeToGBK::ConvertNoBuff(
00403   const PRUnichar * aSrc, 
00404   PRInt32 * aSrcLength, 
00405   char * aDest, 
00406   PRInt32 * aDestLength)
00407 {
00408   PRInt32 iSrcLength = 0;
00409   PRInt32 iDestLength = 0;
00410   PRUnichar unicode;
00411   nsresult res = NS_OK;
00412   while (iSrcLength < *aSrcLength )
00413   {
00414     unicode = *aSrc;
00415     //if unicode's hi byte has something, it is not ASCII, must be a GB
00416     if(IS_ASCII(unicode))
00417     {
00418       // this is an ASCII
00419       *aDest = CAST_UNICHAR_TO_CHAR(*aSrc);
00420       aDest++; // increment 1 byte
00421       iDestLength +=1;
00422     } else {
00423       char byte1, byte2;
00424       if(mUtil.UnicodeToGBKChar( unicode, PR_FALSE, &byte1, &byte2))
00425       {
00426         // make sure we still have 2 bytes for output first
00427         if(iDestLength+2 > *aDestLength)
00428         {
00429           res = NS_OK_UENC_MOREOUTPUT;
00430           break;
00431         }
00432         aDest[0] = byte1;
00433         aDest[1] = byte2;
00434         aDest += 2;  // increment 2 bytes
00435         iDestLength +=2;
00436       } else {
00437         PRInt32 aOutLen = 2;
00438         // make sure we still have 2 bytes for output first
00439         if(iDestLength+2 > *aDestLength)
00440         {
00441           res = NS_OK_UENC_MOREOUTPUT;
00442           break;
00443         }
00444         // we cannot map in the common mapping. Let's try to
00445         // call the delegated 2 byte converter for the gbk or gb18030
00446         // unique 2 byte mapping
00447         if(TryExtensionEncoder(unicode, aDest, &aOutLen))
00448         {
00449           iDestLength += aOutLen;
00450           aDest += aOutLen;
00451         } else {
00452           // make sure we still have 4 bytes for output first
00453           if(iDestLength+4 > *aDestLength)
00454           {
00455             res = NS_OK_UENC_MOREOUTPUT;
00456             break;
00457           }
00458           // we still cannot map. Let's try to
00459           // call the delegated GB18030 4 byte converter 
00460           aOutLen = 4;
00461           if( IS_HIGH_SURROGATE(unicode) )
00462           {
00463             if((iSrcLength+1) < *aSrcLength ) {
00464               if(EncodeSurrogate(aSrc[0],aSrc[1], aDest)) {
00465                 // since we got a surrogate pair, we need to increment src.
00466                 iSrcLength++ ; 
00467                 aSrc++;
00468                 iDestLength += aOutLen;
00469                 aDest += aOutLen;
00470               } else {
00471                 // only get a high surrogate, but not a low surrogate
00472                 res = NS_ERROR_UENC_NOMAPPING;
00473                 iSrcLength++;   // include length of the unmapped character
00474                 break;
00475               }
00476             } else {
00477               mSurrogateHigh = aSrc[0];
00478               break; // this will go to afterwhileloop
00479             }
00480           } else {
00481             if( IS_LOW_SURROGATE(unicode) )
00482             {
00483               if(IS_HIGH_SURROGATE(mSurrogateHigh)) {
00484                 if(EncodeSurrogate(mSurrogateHigh, aSrc[0], aDest)) {
00485                   iDestLength += aOutLen;
00486                   aDest += aOutLen;
00487                 } else {
00488                   // only get a high surrogate, but not a low surrogate
00489                   res = NS_ERROR_UENC_NOMAPPING;
00490                   iSrcLength++;   // include length of the unmapped character
00491                   break;
00492                 }
00493               } else {
00494                 // only get a low surrogate, but not a low surrogate
00495                 res = NS_ERROR_UENC_NOMAPPING;
00496                 iSrcLength++;   // include length of the unmapped character
00497                 break;
00498               }
00499             } else {
00500               if(Try4BytesEncoder(unicode, aDest, &aOutLen))
00501               {
00502                 NS_ASSERTION((aOutLen == 4), "we should always generate 4 bytes here");
00503                 iDestLength += aOutLen;
00504                 aDest += aOutLen;
00505               } else {
00506                 res = NS_ERROR_UENC_NOMAPPING;
00507                 iSrcLength++;   // include length of the unmapped character
00508                 break;
00509               }
00510             }
00511           }
00512         }
00513       } 
00514     }
00515     iSrcLength++ ; // Each unicode char just count as one in PRUnichar string;        
00516     mSurrogateHigh = 0;
00517     aSrc++;
00518     if ( iDestLength >= (*aDestLength) && (iSrcLength < *aSrcLength) )
00519     {
00520       res = NS_OK_UENC_MOREOUTPUT;
00521       break;
00522     }
00523   }
00524 //afterwhileloop:
00525   *aDestLength = iDestLength;
00526   *aSrcLength = iSrcLength;
00527   return res;
00528 }
00529 
00530 //----------------------------------------------------------------------
00531 // Subclassing of nsTableEncoderSupport class [implementation]
00532 
00533 NS_IMETHODIMP nsUnicodeToGBK::FillInfo(PRUint32 *aInfo)
00534 {
00535   mUtil.FillInfo(aInfo, 0x81, 0xFE, 0x40, 0xFE);
00536   if(! mExtensionEncoder )
00537     CreateExtensionEncoder();
00538   if(mExtensionEncoder) 
00539   {
00540     nsCOMPtr<nsICharRepresentable> aRep = do_QueryInterface(mExtensionEncoder);
00541     aRep->FillInfo(aInfo);
00542   }
00543   
00544   if(! m4BytesEncoder )
00545     Create4BytesEncoder();
00546   if(m4BytesEncoder) 
00547   {
00548     nsCOMPtr<nsICharRepresentable> aRep = do_QueryInterface(m4BytesEncoder);
00549     aRep->FillInfo(aInfo);
00550   }
00551 
00552   //GBK font lib also have single byte ASCII characters, set them here
00553   for (PRUint16 SrcUnicode = 0x0000; SrcUnicode <= 0x007F; SrcUnicode++)
00554     SET_REPRESENTABLE(aInfo, SrcUnicode);
00555   SET_REPRESENTABLE(aInfo, 0x20ac); // euro
00556   return NS_OK;
00557 }