Back to index

lightning-sunbird  0.9+nobinonly
nsBidi.h
Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is mozilla.org code.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * IBM Corporation.
00020  * Portions created by the Initial Developer are Copyright (C) 2000
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Simon Montagu
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #ifndef nsBidi_h__
00041 #define nsBidi_h__
00042 
00043 #include "nsCOMPtr.h"
00044 #include "nsString.h"
00045 
00046 // Bidi reordering engine from ICU
00047 /*
00048  * javadoc-style comments are intended to be transformed into HTML
00049  * using DOC++ - see
00050  * http://www.zib.de/Visual/software/doc++/index.html .
00051  *
00052  * The HTML documentation is created with
00053  *  doc++ -H nsIBidi.h
00054  */
00055 
00118 typedef PRUint8 nsBidiLevel;
00119 
00123 #define NSBIDI_DEFAULT_LTR 0xfe
00124 
00128 #define NSBIDI_DEFAULT_RTL 0xff
00129 
00135 #define NSBIDI_MAX_EXPLICIT_LEVEL 61
00136 
00140 #define NSBIDI_LEVEL_OVERRIDE 0x80
00141 
00145 enum nsBidiDirection {
00147   NSBIDI_LTR,
00149   NSBIDI_RTL,
00151   NSBIDI_MIXED
00152 };
00153 
00154 typedef enum nsBidiDirection nsBidiDirection;
00155 
00156 /* miscellaneous definitions ------------------------------------------------ */
00157 
00167 typedef enum {
00168   eBidiCat_Undefined,
00169   eBidiCat_L,          /* Left-to-Right               */
00170   eBidiCat_R,          /* Right-to-Left               */
00171   eBidiCat_AL,         /* Right-to-Left Arabic        */
00172   eBidiCat_AN,         /* Arabic Number               */
00173   eBidiCat_EN,         /* European Number             */
00174   eBidiCat_ES,         /* European Number Separator   */
00175   eBidiCat_ET,         /* European Number Terminator  */
00176   eBidiCat_CS,         /* Common Number Separator     */
00177   eBidiCat_ON,         /* Other Neutrals              */
00178   eBidiCat_NSM,        /* Non-Spacing Mark            */
00179   eBidiCat_BN,         /* Boundary Neutral            */
00180   eBidiCat_B,          /* Paragraph Separator         */
00181   eBidiCat_S,          /* Segment Separator           */
00182   eBidiCat_WS,         /* Whitespace                  */
00183   eBidiCat_CC = 0xf,   /* Control Code                */
00184                        /* (internal use only - will never be outputed) */
00185   eBidiCat_LRE = 0x2a, /* Left-to-Right Embedding     */
00186   eBidiCat_RLE = 0x2b, /* Right-to-Left Embedding     */
00187   eBidiCat_PDF = 0x2c, /* Pop Directional Formatting  */
00188   eBidiCat_LRO = 0x2d, /* Left-to-Right Override      */
00189   eBidiCat_RLO = 0x2e  /* Right-to-Left Override      */
00190 } eBidiCategory;
00191 
00192 enum nsCharType   { 
00193   eCharType_LeftToRight              = 0, 
00194   eCharType_RightToLeft              = 1, 
00195   eCharType_EuropeanNumber           = 2,
00196   eCharType_EuropeanNumberSeparator  = 3,
00197   eCharType_EuropeanNumberTerminator = 4,
00198   eCharType_ArabicNumber             = 5,
00199   eCharType_CommonNumberSeparator    = 6,
00200   eCharType_BlockSeparator           = 7,
00201   eCharType_SegmentSeparator         = 8,
00202   eCharType_WhiteSpaceNeutral        = 9, 
00203   eCharType_OtherNeutral             = 10, 
00204   eCharType_LeftToRightEmbedding     = 11,
00205   eCharType_LeftToRightOverride      = 12,
00206   eCharType_RightToLeftArabic        = 13,
00207   eCharType_RightToLeftEmbedding     = 14,
00208   eCharType_RightToLeftOverride      = 15,
00209   eCharType_PopDirectionalFormat     = 16,
00210   eCharType_DirNonSpacingMark        = 17,
00211   eCharType_BoundaryNeutral          = 18,
00212   eCharType_CharTypeCount
00213 };
00214 
00218 typedef enum nsCharType nsCharType;
00219 
00224 #define CHARTYPE_IS_RTL(val) ( ( (val) == eCharType_RightToLeft) || ( (val) == eCharType_RightToLeftArabic) )
00225 
00226 #define CHARTYPE_IS_WEAK(val) ( ( (val) == eCharType_EuropeanNumberSeparator)    \
00227                            || ( (val) == eCharType_EuropeanNumberTerminator) \
00228                            || ( ( (val) > eCharType_ArabicNumber) && ( (val) != eCharType_RightToLeftArabic) ) )
00229 
00237 #define NSBIDI_KEEP_BASE_COMBINING       1
00238 
00246 #define NSBIDI_DO_MIRRORING              2
00247 
00254 #define NSBIDI_REMOVE_BIDI_CONTROLS      8
00255 
00256 /* helper macros for each allocated array member */
00257 #define GETDIRPROPSMEMORY(length) \
00258                                   GetMemory((void **)&mDirPropsMemory, &mDirPropsSize, \
00259                                   mMayAllocateText, (length))
00260 
00261 #define GETLEVELSMEMORY(length) \
00262                                 GetMemory((void **)&mLevelsMemory, &mLevelsSize, \
00263                                 mMayAllocateText, (length))
00264 
00265 #define GETRUNSMEMORY(length) \
00266                               GetMemory((void **)&mRunsMemory, &mRunsSize, \
00267                               mMayAllocateRuns, (length)*sizeof(Run))
00268 
00269 /* additional macros used by constructor - always allow allocation */
00270 #define GETINITIALDIRPROPSMEMORY(length) \
00271                                          GetMemory((void **)&mDirPropsMemory, &mDirPropsSize, \
00272                                          PR_TRUE, (length))
00273 
00274 #define GETINITIALLEVELSMEMORY(length) \
00275                                        GetMemory((void **)&mLevelsMemory, &mLevelsSize, \
00276                                        PR_TRUE, (length))
00277 
00278 #define GETINITIALRUNSMEMORY(length) \
00279                                      GetMemory((void **)&mRunsMemory, &mRunsSize, \
00280                                      PR_TRUE, (length)*sizeof(Run))
00281 
00282 /*
00283  * Sometimes, bit values are more appropriate
00284  * to deal with directionality properties.
00285  * Abbreviations in these macro names refer to names
00286  * used in the Bidi algorithm.
00287  */
00288 typedef PRUint8 DirProp;
00289 
00290 #define DIRPROP_FLAG(dir) (1UL<<(dir))
00291 
00292 /* special flag for multiple runs from explicit embedding codes */
00293 #define DIRPROP_FLAG_MULTI_RUNS (1UL<<31)
00294 
00295 /* are there any characters that are LTR or RTL? */
00296 #define MASK_LTR (DIRPROP_FLAG(L)|DIRPROP_FLAG(EN)|DIRPROP_FLAG(AN)|DIRPROP_FLAG(LRE)|DIRPROP_FLAG(LRO))
00297 #define MASK_RTL (DIRPROP_FLAG(R)|DIRPROP_FLAG(AL)|DIRPROP_FLAG(RLE)|DIRPROP_FLAG(RLO))
00298 
00299 /* explicit embedding codes */
00300 #define MASK_LRX (DIRPROP_FLAG(LRE)|DIRPROP_FLAG(LRO))
00301 #define MASK_RLX (DIRPROP_FLAG(RLE)|DIRPROP_FLAG(RLO))
00302 #define MASK_OVERRIDE (DIRPROP_FLAG(LRO)|DIRPROP_FLAG(RLO))
00303 
00304 #define MASK_EXPLICIT (MASK_LRX|MASK_RLX|DIRPROP_FLAG(PDF))
00305 #define MASK_BN_EXPLICIT (DIRPROP_FLAG(BN)|MASK_EXPLICIT)
00306 
00307 /* paragraph and segment separators */
00308 #define MASK_B_S (DIRPROP_FLAG(B)|DIRPROP_FLAG(S))
00309 
00310 /* all types that are counted as White Space or Neutral in some steps */
00311 #define MASK_WS (MASK_B_S|DIRPROP_FLAG(WS)|MASK_BN_EXPLICIT)
00312 #define MASK_N (DIRPROP_FLAG(O_N)|MASK_WS)
00313 
00314 /* all types that are included in a sequence of European Terminators for (W5) */
00315 #define MASK_ET_NSM_BN (DIRPROP_FLAG(ET)|DIRPROP_FLAG(NSM)|MASK_BN_EXPLICIT)
00316 
00317 /* types that are neutrals or could becomes neutrals in (Wn) */
00318 #define MASK_POSSIBLE_N (DIRPROP_FLAG(CS)|DIRPROP_FLAG(ES)|DIRPROP_FLAG(ET)|MASK_N)
00319 
00320 /*
00321  * These types may be changed to "e",
00322  * the embedding type (L or R) of the run,
00323  * in the Bidi algorithm (N2)
00324  */
00325 #define MASK_EMBEDDING (DIRPROP_FLAG(NSM)|MASK_POSSIBLE_N)
00326 
00327 /* the dirProp's L and R are defined to 0 and 1 values in nsCharType */
00328 #define GET_LR_FROM_LEVEL(level) ((DirProp)((level)&1))
00329 
00330 #define IS_DEFAULT_LEVEL(level) (((level)&0xfe)==0xfe)
00331 
00332 /* handle surrogate pairs --------------------------------------------------- */
00333 
00334 #define IS_FIRST_SURROGATE(uchar) (((uchar)&0xfc00)==0xd800)
00335 #define IS_SECOND_SURROGATE(uchar) (((uchar)&0xfc00)==0xdc00)
00336 
00337 /* get the UTF-32 value directly from the surrogate pseudo-characters */
00338 #define SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000)
00339 #define GET_UTF_32(first, second) (((first)<<10UL)+(second)-SURROGATE_OFFSET)
00340 
00341 
00342 #define UTF_ERROR_VALUE 0xffff
00343 /* definitions with forward iteration --------------------------------------- */
00344 
00345 /*
00346  * all the macros that go forward assume that
00347  * the initial offset is 0<=i<length;
00348  * they update the offset
00349  */
00350 
00351 /* fast versions, no error-checking */
00352 
00353 #define UTF16_APPEND_CHAR_UNSAFE(s, i, c){ \
00354                                          if((PRUint32)(c)<=0xffff) { \
00355                                          (s)[(i)++]=(PRUnichar)(c); \
00356                                          } else { \
00357                                          (s)[(i)++]=(PRUnichar)((c)>>10)+0xd7c0; \
00358                                          (s)[(i)++]=(PRUnichar)(c)&0x3ff|0xdc00; \
00359                                          } \
00360 }
00361 
00362 /* safe versions with error-checking and optional regularity-checking */
00363 
00364 #define UTF16_APPEND_CHAR_SAFE(s, i, length, c) { \
00365                                                 if((PRUInt32)(c)<=0xffff) { \
00366                                                 (s)[(i)++]=(PRUnichar)(c); \
00367                                                 } else if((PRUInt32)(c)<=0x10ffff) { \
00368                                                 if((i)+1<(length)) { \
00369                                                 (s)[(i)++]=(PRUnichar)((c)>>10)+0xd7c0; \
00370                                                 (s)[(i)++]=(PRUnichar)(c)&0x3ff|0xdc00; \
00371                                                 } else /* not enough space */ { \
00372                                                 (s)[(i)++]=UTF_ERROR_VALUE; \
00373                                                 } \
00374                                                 } else /* c>0x10ffff, write error value */ { \
00375                                                 (s)[(i)++]=UTF_ERROR_VALUE; \
00376                                                 } \
00377 }
00378 
00379 /* definitions with backward iteration -------------------------------------- */
00380 
00381 /*
00382  * all the macros that go backward assume that
00383  * the valid buffer range starts at offset 0
00384  * and that the initial offset is 0<i<=length;
00385  * they update the offset
00386  */
00387 
00388 /* fast versions, no error-checking */
00389 
00390 /*
00391  * Get a single code point from an offset that points behind the last
00392  * of the code units that belong to that code point.
00393  * Assume 0<=i<length.
00394  */
00395 #define UTF16_PREV_CHAR_UNSAFE(s, i, c) { \
00396                                         (c)=(s)[--(i)]; \
00397                                         if(IS_SECOND_SURROGATE(c)) { \
00398                                         (c)=GET_UTF_32((s)[--(i)], (c)); \
00399                                         } \
00400 }
00401 
00402 #define UTF16_BACK_1_UNSAFE(s, i) { \
00403                                   if(IS_SECOND_SURROGATE((s)[--(i)])) { \
00404                                   --(i); \
00405                                   } \
00406 }
00407 
00408 #define UTF16_BACK_N_UNSAFE(s, i, n) { \
00409                                      PRInt32 __N=(n); \
00410                                      while(__N>0) { \
00411                                      UTF16_BACK_1_UNSAFE(s, i); \
00412                                      --__N; \
00413                                      } \
00414 }
00415 
00416 /* safe versions with error-checking and optional regularity-checking */
00417 
00418 #define UTF16_PREV_CHAR_SAFE(s, start, i, c, strict) { \
00419                                                      (c)=(s)[--(i)]; \
00420                                                      if(IS_SECOND_SURROGATE(c)) { \
00421                                                      PRUnichar __c2; \
00422                                                      if((i)>(start) && IS_FIRST_SURROGATE(__c2=(s)[(i)-1])) { \
00423                                                      --(i); \
00424                                                      (c)=GET_UTF_32(__c2, (c)); \
00425       /* strict: ((c)&0xfffe)==0xfffe is caught by UTF_IS_ERROR() */ \
00426                                                      } else if(strict) {\
00427       /* unmatched second surrogate */ \
00428                                                      (c)=UTF_ERROR_VALUE; \
00429                                                      } \
00430                                                      } else if(strict && IS_FIRST_SURROGATE(c)) { \
00431       /* unmatched first surrogate */ \
00432                                                      (c)=UTF_ERROR_VALUE; \
00433   /* else strict: (c)==0xfffe is caught by UTF_IS_ERROR() */ \
00434                                                      } \
00435 }
00436 
00437 #define UTF16_BACK_1_SAFE(s, start, i) { \
00438                                        if(IS_SECOND_SURROGATE((s)[--(i)]) && (i)>(start) && IS_FIRST_SURROGATE((s)[(i)-1])) { \
00439                                        --(i); \
00440                                        } \
00441 }
00442 
00443 #define UTF16_BACK_N_SAFE(s, start, i, n) { \
00444                                           PRInt32 __N=(n); \
00445                                           while(__N>0 && (i)>(start)) { \
00446                                           UTF16_BACK_1_SAFE(s, start, i); \
00447                                           --__N; \
00448                                           } \
00449 }
00450 
00451 #define UTF_PREV_CHAR_UNSAFE(s, i, c)                UTF16_PREV_CHAR_UNSAFE(s, i, c)
00452 #define UTF_PREV_CHAR_SAFE(s, start, i, c, strict)   UTF16_PREV_CHAR_SAFE(s, start, i, c, strict)
00453 #define UTF_BACK_1_UNSAFE(s, i)                      UTF16_BACK_1_UNSAFE(s, i)
00454 #define UTF_BACK_1_SAFE(s, start, i)                 UTF16_BACK_1_SAFE(s, start, i)
00455 #define UTF_BACK_N_UNSAFE(s, i, n)                   UTF16_BACK_N_UNSAFE(s, i, n)
00456 #define UTF_BACK_N_SAFE(s, start, i, n)              UTF16_BACK_N_SAFE(s, start, i, n)
00457 #define UTF_APPEND_CHAR_UNSAFE(s, i, c)              UTF16_APPEND_CHAR_UNSAFE(s, i, c)
00458 #define UTF_APPEND_CHAR_SAFE(s, i, length, c)        UTF16_APPEND_CHAR_SAFE(s, i, length, c)
00459 
00460 #define UTF_PREV_CHAR(s, start, i, c)                UTF_PREV_CHAR_SAFE(s, start, i, c, PR_FALSE)
00461 #define UTF_BACK_1(s, start, i)                      UTF_BACK_1_SAFE(s, start, i)
00462 #define UTF_BACK_N(s, start, i, n)                   UTF_BACK_N_SAFE(s, start, i, n)
00463 #define UTF_APPEND_CHAR(s, i, length, c)             UTF_APPEND_CHAR_SAFE(s, i, length, c)
00464 
00465 /* Run structure for reordering --------------------------------------------- */
00466 
00467 typedef struct Run {
00468   PRInt32 logicalStart,  /* first character of the run; b31 indicates even/odd level */
00469   visualLimit;  /* last visual position of the run +1 */
00470 } Run;
00471 
00472 /* in a Run, logicalStart will get this bit set if the run level is odd */
00473 #define INDEX_ODD_BIT (1UL<<31)
00474 
00475 #define MAKE_INDEX_ODD_PAIR(index, level) (index|((PRUint32)level<<31))
00476 #define ADD_ODD_BIT_FROM_LEVEL(x, level)  ((x)|=((PRUint32)level<<31))
00477 #define REMOVE_ODD_BIT(x)          ((x)&=~INDEX_ODD_BIT)
00478 
00479 #define GET_INDEX(x)   (x&~INDEX_ODD_BIT)
00480 #define GET_ODD_BIT(x) ((PRUint32)x>>31)
00481 #define IS_ODD_RUN(x)  ((x&INDEX_ODD_BIT)!=0)
00482 #define IS_EVEN_RUN(x) ((x&INDEX_ODD_BIT)==0)
00483 
00484 typedef PRUint32 Flags;
00485 
00502 class nsBidi
00503 {
00504 public: 
00516   nsBidi();
00517 
00551   nsBidi(PRUint32 aMaxLength, PRUint32 aMaxRunCount);
00552 
00554   virtual ~nsBidi();
00555 
00556 
00618   nsresult SetPara(const PRUnichar *aText, PRInt32 aLength, nsBidiLevel aParaLevel, nsBidiLevel *aEmbeddingLevels);
00619 
00620 #ifdef FULL_BIDI_ENGINE
00621 
00654   nsresult SetLine(nsIBidi* aParaBidi, PRInt32 aStart, PRInt32 aLimit);  
00655 
00665   nsresult GetDirection(nsBidiDirection* aDirection);
00666 
00672   nsresult GetLength(PRInt32* aLength);
00673 
00681   nsresult GetParaLevel(nsBidiLevel* aParaLevel);
00682 
00692   nsresult GetLevelAt(PRInt32 aCharIndex,  nsBidiLevel* aLevel);
00693 
00705   nsresult GetLevels(nsBidiLevel** aLevels);
00706 #endif // FULL_BIDI_ENGINE
00707 
00714   nsresult GetCharTypeAt(PRInt32 aCharIndex,  nsCharType* aType);
00715 
00735   nsresult GetLogicalRun(PRInt32 aLogicalStart, PRInt32* aLogicalLimit, nsBidiLevel* aLevel);
00736 
00747   nsresult CountRuns(PRInt32* aRunCount);
00748 
00797   nsresult GetVisualRun(PRInt32 aRunIndex, PRInt32* aLogicalStart, PRInt32* aLength, nsBidiDirection* aDirection);
00798 
00799 #ifdef FULL_BIDI_ENGINE
00800 
00817   nsresult GetVisualIndex(PRInt32 aLogicalIndex, PRInt32* aVisualIndex);
00818 
00834   nsresult GetLogicalIndex(PRInt32 aVisualIndex, PRInt32* aLogicalIndex);
00835 
00848   nsresult GetLogicalMap(PRInt32 *aIndexMap);
00849 
00862   nsresult GetVisualMap(PRInt32 *aIndexMap);
00863 
00883   nsresult ReorderLogical(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap);
00884 #endif // FULL_BIDI_ENGINE
00885 
00904   nsresult ReorderVisual(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap);
00905 
00906 #ifdef FULL_BIDI_ENGINE
00907 
00920   nsresult InvertMap(const PRInt32 *aSrcMap, PRInt32 *aDestMap, PRInt32 aLength);
00921 #endif // FULL_BIDI_ENGINE
00922 
00957   nsresult WriteReverse(const PRUnichar *aSrc, PRInt32 aSrcLength, PRUnichar *aDest, PRUint16 aOptions, PRInt32 *aDestSize);
00958 
00964   PRBool IsBidiControl(PRUint32 aChar);
00965 
00966 protected:
00968   PRInt32 mLength;
00969 
00971   PRSize mDirPropsSize, mLevelsSize, mRunsSize;
00972 
00974   DirProp* mDirPropsMemory;
00975   nsBidiLevel* mLevelsMemory;
00976   Run* mRunsMemory;
00977 
00979   PRBool mMayAllocateText, mMayAllocateRuns;
00980 
00981   const DirProp* mDirProps;
00982   nsBidiLevel* mLevels;
00983 
00985   nsBidiLevel mParaLevel;
00986 
00988   Flags mFlags;
00989 
00991   nsBidiDirection mDirection;
00992 
00994   /* implicitly at the paraLevel (rule (L1)) - levels may not reflect that */
00995   PRInt32 mTrailingWSStart;
00996 
00998   PRInt32 mRunCount;     /* ==-1: runs not set up yet */
00999   Run* mRuns;
01000 
01002   Run mSimpleRuns[1];
01003 
01004 private:
01005 
01006   void Init();
01007 
01008   PRBool GetMemory(void **aMemory, PRSize* aSize, PRBool aMayAllocate, PRSize aSizeNeeded);
01009 
01010   void Free();
01011 
01012   void GetDirProps(const PRUnichar *aText);
01013 
01014   nsBidiDirection ResolveExplicitLevels();
01015 
01016   nsresult CheckExplicitLevels(nsBidiDirection *aDirection);
01017 
01018   nsBidiDirection DirectionFromFlags(Flags aFlags);
01019 
01020   void ResolveImplicitLevels(PRInt32 aStart, PRInt32 aLimit, DirProp aSOR, DirProp aEOR);
01021 
01022   void AdjustWSLevels();
01023 
01024   void SetTrailingWSStart();
01025 
01026   PRBool GetRuns();
01027 
01028   void GetSingleRun(nsBidiLevel aLevel);
01029 
01030   void ReorderLine(nsBidiLevel aMinLevel, nsBidiLevel aMaxLevel);
01031 
01032   PRBool PrepareReorder(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap, nsBidiLevel *aMinLevel, nsBidiLevel *aMaxLevel);
01036   eBidiCategory GetBidiCategory(PRUint32 aChar);
01037 
01043   PRBool IsBidiCategory(PRUint32 aChar, eBidiCategory aBidiCategory);
01044 
01048   nsCharType GetCharType(PRUint32 aChar);
01049 
01053   PRUint32 SymmSwap(PRUint32 aChar);
01054 
01055   PRInt32 doWriteReverse(const PRUnichar *src, PRInt32 srcLength,
01056                          PRUnichar *dest, PRUint16 options);
01057 
01058 };
01059 
01060 #endif // _nsBidi_h_