LCOV - code coverage report
Current view: directory - layout/generic - nsBulletFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 594 0 0.0 %
Date: 2012-06-02 Functions: 61 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : /* rendering object for list-item bullets */
      39                 : 
      40                 : #include "nsCOMPtr.h"
      41                 : #include "nsBulletFrame.h"
      42                 : #include "nsGkAtoms.h"
      43                 : #include "nsHTMLParts.h"
      44                 : #include "nsContainerFrame.h"
      45                 : #include "nsGenericHTMLElement.h"
      46                 : #include "nsPresContext.h"
      47                 : #include "nsIPresShell.h"
      48                 : #include "nsIDocument.h"
      49                 : #include "nsRenderingContext.h"
      50                 : #include "nsILoadGroup.h"
      51                 : #include "nsIURL.h"
      52                 : #include "nsNetUtil.h"
      53                 : #include "prprf.h"
      54                 : #include "nsDisplayList.h"
      55                 : 
      56                 : #include "imgILoader.h"
      57                 : #include "imgIContainer.h"
      58                 : 
      59                 : #include "nsIServiceManager.h"
      60                 : #include "nsIComponentManager.h"
      61                 : #include "nsContentUtils.h"
      62                 : 
      63                 : #ifdef ACCESSIBILITY
      64                 : #include "nsAccessibilityService.h"
      65                 : #endif
      66                 : 
      67                 : using namespace mozilla;
      68                 : 
      69               0 : NS_DECLARE_FRAME_PROPERTY(FontSizeInflationProperty, nsnull)
      70                 : 
      71               0 : NS_IMPL_FRAMEARENA_HELPERS(nsBulletFrame)
      72                 : 
      73               0 : nsBulletFrame::~nsBulletFrame()
      74                 : {
      75               0 : }
      76                 : 
      77                 : void
      78               0 : nsBulletFrame::DestroyFrom(nsIFrame* aDestructRoot)
      79                 : {
      80                 :   // Stop image loading first
      81               0 :   if (mImageRequest) {
      82                 :     // Deregister our image request from the refresh driver
      83                 :     nsLayoutUtils::DeregisterImageRequest(PresContext(),
      84                 :                                           mImageRequest,
      85               0 :                                           &mRequestRegistered);
      86               0 :     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
      87               0 :     mImageRequest = nsnull;
      88                 :   }
      89                 : 
      90               0 :   if (mListener) {
      91               0 :     mListener->SetFrame(nsnull);
      92                 :   }
      93                 : 
      94                 :   // Let base class do the rest
      95               0 :   nsFrame::DestroyFrom(aDestructRoot);
      96               0 : }
      97                 : 
      98                 : #ifdef NS_DEBUG
      99                 : NS_IMETHODIMP
     100               0 : nsBulletFrame::GetFrameName(nsAString& aResult) const
     101                 : {
     102               0 :   return MakeFrameName(NS_LITERAL_STRING("Bullet"), aResult);
     103                 : }
     104                 : #endif
     105                 : 
     106                 : nsIAtom*
     107               0 : nsBulletFrame::GetType() const
     108                 : {
     109               0 :   return nsGkAtoms::bulletFrame;
     110                 : }
     111                 : 
     112                 : bool
     113               0 : nsBulletFrame::IsEmpty()
     114                 : {
     115               0 :   return IsSelfEmpty();
     116                 : }
     117                 : 
     118                 : bool
     119               0 : nsBulletFrame::IsSelfEmpty() 
     120                 : {
     121               0 :   return GetStyleList()->mListStyleType == NS_STYLE_LIST_STYLE_NONE;
     122                 : }
     123                 : 
     124                 : /* virtual */ void
     125               0 : nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
     126                 : {
     127               0 :   nsFrame::DidSetStyleContext(aOldStyleContext);
     128                 : 
     129               0 :   imgIRequest *newRequest = GetStyleList()->GetListStyleImage();
     130                 : 
     131               0 :   if (newRequest) {
     132                 : 
     133               0 :     if (!mListener) {
     134               0 :       mListener = new nsBulletListener();
     135               0 :       mListener->SetFrame(this);
     136                 :     }
     137                 : 
     138               0 :     bool needNewRequest = true;
     139                 : 
     140               0 :     if (mImageRequest) {
     141                 :       // Reload the image, maybe...
     142               0 :       nsCOMPtr<nsIURI> oldURI;
     143               0 :       mImageRequest->GetURI(getter_AddRefs(oldURI));
     144               0 :       nsCOMPtr<nsIURI> newURI;
     145               0 :       newRequest->GetURI(getter_AddRefs(newURI));
     146               0 :       if (oldURI && newURI) {
     147                 :         bool same;
     148               0 :         newURI->Equals(oldURI, &same);
     149               0 :         if (same) {
     150               0 :           needNewRequest = false;
     151                 :         } else {
     152                 :           nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
     153               0 :                                                 &mRequestRegistered);
     154               0 :           mImageRequest->Cancel(NS_ERROR_FAILURE);
     155               0 :           mImageRequest = nsnull;
     156                 :         }
     157                 :       }
     158                 :     }
     159                 : 
     160               0 :     if (needNewRequest) {
     161               0 :       newRequest->Clone(mListener, getter_AddRefs(mImageRequest));
     162               0 :       if (mImageRequest) {
     163                 :         nsLayoutUtils::RegisterImageRequestIfAnimated(PresContext(),
     164                 :                                                       mImageRequest,
     165               0 :                                                       &mRequestRegistered);
     166                 :       }
     167                 :     }
     168                 :   } else {
     169                 :     // No image request on the new style context
     170               0 :     if (mImageRequest) {
     171                 :       nsLayoutUtils::DeregisterImageRequest(PresContext(), mImageRequest,
     172               0 :                                             &mRequestRegistered);
     173                 : 
     174               0 :       mImageRequest->Cancel(NS_ERROR_FAILURE);
     175               0 :       mImageRequest = nsnull;
     176                 :     }
     177                 :   }
     178                 : 
     179                 : #ifdef ACCESSIBILITY
     180                 :   // Update the list bullet accessible. If old style list isn't available then
     181                 :   // no need to update the accessible tree because it's not created yet.
     182               0 :   if (aOldStyleContext) {
     183               0 :     nsAccessibilityService* accService = nsIPresShell::AccService();
     184               0 :     if (accService) {
     185               0 :       const nsStyleList* oldStyleList = aOldStyleContext->PeekStyleList();
     186               0 :       if (oldStyleList) {
     187               0 :         bool hadBullet = oldStyleList->GetListStyleImage() ||
     188               0 :             oldStyleList->mListStyleType != NS_STYLE_LIST_STYLE_NONE;
     189                 : 
     190               0 :         const nsStyleList* newStyleList = GetStyleList();
     191               0 :         bool hasBullet = newStyleList->GetListStyleImage() ||
     192               0 :             newStyleList->mListStyleType != NS_STYLE_LIST_STYLE_NONE;
     193                 : 
     194               0 :         if (hadBullet != hasBullet) {
     195                 :           accService->UpdateListBullet(PresContext()->GetPresShell(), mContent,
     196               0 :                                        hasBullet);
     197                 :         }
     198                 :       }
     199                 :     }
     200                 :   }
     201                 : #endif
     202               0 : }
     203                 : 
     204                 : class nsDisplayBullet : public nsDisplayItem {
     205                 : public:
     206               0 :   nsDisplayBullet(nsDisplayListBuilder* aBuilder, nsBulletFrame* aFrame) :
     207               0 :     nsDisplayItem(aBuilder, aFrame) {
     208               0 :     MOZ_COUNT_CTOR(nsDisplayBullet);
     209               0 :   }
     210                 : #ifdef NS_BUILD_REFCNT_LOGGING
     211               0 :   virtual ~nsDisplayBullet() {
     212               0 :     MOZ_COUNT_DTOR(nsDisplayBullet);
     213               0 :   }
     214                 : #endif
     215                 : 
     216               0 :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
     217                 :   {
     218               0 :     return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
     219                 :   }
     220               0 :   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
     221                 :                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) {
     222               0 :     aOutFrames->AppendElement(mFrame);
     223               0 :   }
     224                 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     225                 :                      nsRenderingContext* aCtx);
     226               0 :   NS_DISPLAY_DECL_NAME("Bullet", TYPE_BULLET)
     227                 : 
     228               0 :   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
     229                 :   {
     230               0 :     return GetBounds(aBuilder);
     231                 :   }
     232                 : };
     233                 : 
     234               0 : void nsDisplayBullet::Paint(nsDisplayListBuilder* aBuilder,
     235                 :                             nsRenderingContext* aCtx)
     236                 : {
     237                 :   static_cast<nsBulletFrame*>(mFrame)->
     238               0 :     PaintBullet(*aCtx, ToReferenceFrame(), mVisibleRect);
     239               0 : }
     240                 : 
     241                 : NS_IMETHODIMP
     242               0 : nsBulletFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     243                 :                                 const nsRect&           aDirtyRect,
     244                 :                                 const nsDisplayListSet& aLists)
     245                 : {
     246               0 :   if (!IsVisibleForPainting(aBuilder))
     247               0 :     return NS_OK;
     248                 : 
     249               0 :   DO_GLOBAL_REFLOW_COUNT_DSP("nsBulletFrame");
     250                 :   
     251                 :   return aLists.Content()->AppendNewToTop(
     252               0 :       new (aBuilder) nsDisplayBullet(aBuilder, this));
     253                 : }
     254                 : 
     255                 : void
     256               0 : nsBulletFrame::PaintBullet(nsRenderingContext& aRenderingContext, nsPoint aPt,
     257                 :                            const nsRect& aDirtyRect)
     258                 : {
     259               0 :   const nsStyleList* myList = GetStyleList();
     260               0 :   PRUint8 listStyleType = myList->mListStyleType;
     261                 : 
     262               0 :   if (myList->GetListStyleImage() && mImageRequest) {
     263                 :     PRUint32 status;
     264               0 :     mImageRequest->GetImageStatus(&status);
     265               0 :     if (status & imgIRequest::STATUS_LOAD_COMPLETE &&
     266               0 :         !(status & imgIRequest::STATUS_ERROR)) {
     267               0 :       nsCOMPtr<imgIContainer> imageCon;
     268               0 :       mImageRequest->GetImage(getter_AddRefs(imageCon));
     269               0 :       if (imageCon) {
     270                 :         nsRect dest(mPadding.left, mPadding.top,
     271                 :                     mRect.width - (mPadding.left + mPadding.right),
     272               0 :                     mRect.height - (mPadding.top + mPadding.bottom));
     273                 :         nsLayoutUtils::DrawSingleImage(&aRenderingContext,
     274                 :              imageCon, nsLayoutUtils::GetGraphicsFilterForFrame(this),
     275               0 :              dest + aPt, aDirtyRect, imgIContainer::FLAG_NONE);
     276                 :         return;
     277                 :       }
     278                 :     }
     279                 :   }
     280                 : 
     281               0 :   nsRefPtr<nsFontMetrics> fm;
     282               0 :   aRenderingContext.SetColor(nsLayoutUtils::GetColor(this, eCSSProperty_color));
     283                 : 
     284               0 :   mTextIsRTL = false;
     285                 : 
     286               0 :   nsAutoString text;
     287               0 :   switch (listStyleType) {
     288                 :   case NS_STYLE_LIST_STYLE_NONE:
     289               0 :     break;
     290                 : 
     291                 :   default:
     292                 :   case NS_STYLE_LIST_STYLE_DISC:
     293                 :     aRenderingContext.FillEllipse(mPadding.left + aPt.x, mPadding.top + aPt.y,
     294                 :                                   mRect.width - (mPadding.left + mPadding.right),
     295               0 :                                   mRect.height - (mPadding.top + mPadding.bottom));
     296               0 :     break;
     297                 : 
     298                 :   case NS_STYLE_LIST_STYLE_CIRCLE:
     299                 :     aRenderingContext.DrawEllipse(mPadding.left + aPt.x, mPadding.top + aPt.y,
     300                 :                                   mRect.width - (mPadding.left + mPadding.right),
     301               0 :                                   mRect.height - (mPadding.top + mPadding.bottom));
     302               0 :     break;
     303                 : 
     304                 :   case NS_STYLE_LIST_STYLE_SQUARE:
     305                 :     {
     306               0 :       nsRect rect(aPt, mRect.Size());
     307               0 :       rect.Deflate(mPadding);
     308                 : 
     309                 :       // Snap the height and the width of the rectangle to device pixels,
     310                 :       // and then center the result within the original rectangle, so that
     311                 :       // all square bullets at the same font size have the same visual
     312                 :       // size (bug 376690).
     313                 :       // FIXME: We should really only do this if we're not transformed
     314                 :       // (like gfxContext::UserToDevicePixelSnapped does).
     315               0 :       nsPresContext *pc = PresContext();
     316                 :       nsRect snapRect(rect.x, rect.y, 
     317                 :                       pc->RoundAppUnitsToNearestDevPixels(rect.width),
     318               0 :                       pc->RoundAppUnitsToNearestDevPixels(rect.height));
     319                 :       snapRect.MoveBy((rect.width - snapRect.width) / 2,
     320               0 :                       (rect.height - snapRect.height) / 2);
     321                 :       aRenderingContext.FillRect(snapRect.x, snapRect.y,
     322               0 :                                  snapRect.width, snapRect.height);
     323                 :     }
     324               0 :     break;
     325                 : 
     326                 :   case NS_STYLE_LIST_STYLE_DECIMAL:
     327                 :   case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
     328                 :   case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
     329                 :   case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
     330                 :   case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
     331                 :   case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
     332                 :   case NS_STYLE_LIST_STYLE_LOWER_GREEK:
     333                 :   case NS_STYLE_LIST_STYLE_HEBREW:
     334                 :   case NS_STYLE_LIST_STYLE_ARMENIAN:
     335                 :   case NS_STYLE_LIST_STYLE_GEORGIAN:
     336                 :   case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC:
     337                 :   case NS_STYLE_LIST_STYLE_HIRAGANA:
     338                 :   case NS_STYLE_LIST_STYLE_KATAKANA:
     339                 :   case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA:
     340                 :   case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
     341                 :   case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL: 
     342                 :   case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL: 
     343                 :   case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL: 
     344                 :   case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL: 
     345                 :   case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL: 
     346                 :   case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL: 
     347                 :   case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
     348                 :   case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
     349                 :   case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
     350                 :   case NS_STYLE_LIST_STYLE_MOZ_PERSIAN:
     351                 :   case NS_STYLE_LIST_STYLE_MOZ_URDU:
     352                 :   case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI:
     353                 :   case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI:
     354                 :   case NS_STYLE_LIST_STYLE_MOZ_GUJARATI:
     355                 :   case NS_STYLE_LIST_STYLE_MOZ_ORIYA:
     356                 :   case NS_STYLE_LIST_STYLE_MOZ_KANNADA:
     357                 :   case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM:
     358                 :   case NS_STYLE_LIST_STYLE_MOZ_BENGALI:
     359                 :   case NS_STYLE_LIST_STYLE_MOZ_TAMIL:
     360                 :   case NS_STYLE_LIST_STYLE_MOZ_TELUGU:
     361                 :   case NS_STYLE_LIST_STYLE_MOZ_THAI:
     362                 :   case NS_STYLE_LIST_STYLE_MOZ_LAO:
     363                 :   case NS_STYLE_LIST_STYLE_MOZ_MYANMAR:
     364                 :   case NS_STYLE_LIST_STYLE_MOZ_KHMER:
     365                 :   case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
     366                 :   case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
     367                 :   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
     368                 :   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
     369                 :   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
     370                 :   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
     371                 :   case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
     372                 :     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
     373               0 :                                           GetFontSizeInflation());
     374               0 :     GetListItemText(*myList, text);
     375               0 :     aRenderingContext.SetFont(fm);
     376               0 :     nscoord ascent = fm->MaxAscent();
     377               0 :     aRenderingContext.SetTextRunRTL(mTextIsRTL);
     378                 :     aRenderingContext.DrawString(text, mPadding.left + aPt.x,
     379               0 :                                  mPadding.top + aPt.y + ascent);
     380               0 :     break;
     381                 :   }
     382                 : }
     383                 : 
     384                 : PRInt32
     385               0 : nsBulletFrame::SetListItemOrdinal(PRInt32 aNextOrdinal,
     386                 :                                   bool* aChanged)
     387                 : {
     388                 :   // Assume that the ordinal comes from the caller
     389               0 :   PRInt32 oldOrdinal = mOrdinal;
     390               0 :   mOrdinal = aNextOrdinal;
     391                 : 
     392                 :   // Try to get value directly from the list-item, if it specifies a
     393                 :   // value attribute. Note: we do this with our parent's content
     394                 :   // because our parent is the list-item.
     395               0 :   nsIContent* parentContent = mParent->GetContent();
     396               0 :   if (parentContent) {
     397                 :     nsGenericHTMLElement *hc =
     398               0 :       nsGenericHTMLElement::FromContent(parentContent);
     399               0 :     if (hc) {
     400               0 :       const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::value);
     401               0 :       if (attr && attr->Type() == nsAttrValue::eInteger) {
     402                 :         // Use ordinal specified by the value attribute
     403               0 :         mOrdinal = attr->GetIntegerValue();
     404                 :       }
     405                 :     }
     406                 :   }
     407                 : 
     408               0 :   *aChanged = oldOrdinal != mOrdinal;
     409                 : 
     410               0 :   return mOrdinal + 1;
     411                 : }
     412                 : 
     413                 : 
     414                 : // XXX change roman/alpha to use unsigned math so that maxint and
     415                 : // maxnegint will work
     416                 : 
     417                 : /**
     418                 :  * For all functions below, a return value of true means that we
     419                 :  * could represent mOrder in the desired numbering system.  false
     420                 :  * means we had to fall back to decimal
     421                 :  */
     422               0 : static bool DecimalToText(PRInt32 ordinal, nsString& result)
     423                 : {
     424                 :    char cbuf[40];
     425               0 :    PR_snprintf(cbuf, sizeof(cbuf), "%ld", ordinal);
     426               0 :    result.AppendASCII(cbuf);
     427               0 :    return true;
     428                 : }
     429               0 : static bool DecimalLeadingZeroToText(PRInt32 ordinal, nsString& result)
     430                 : {
     431                 :    char cbuf[40];
     432               0 :    PR_snprintf(cbuf, sizeof(cbuf), "%02ld", ordinal);
     433               0 :    result.AppendASCII(cbuf);
     434               0 :    return true;
     435                 : }
     436               0 : static bool OtherDecimalToText(PRInt32 ordinal, PRUnichar zeroChar, nsString& result)
     437                 : {
     438               0 :    PRUnichar diff = zeroChar - PRUnichar('0');
     439               0 :    DecimalToText(ordinal, result);
     440               0 :    PRUnichar* p = result.BeginWriting();
     441               0 :    if (ordinal < 0) {
     442                 :      // skip the leading '-'
     443               0 :      ++p;
     444                 :    }     
     445               0 :    for(; nsnull != *p ; p++) 
     446               0 :       *p += diff;
     447               0 :    return true;
     448                 : }
     449               0 : static bool TamilToText(PRInt32 ordinal,  nsString& result)
     450                 : {
     451               0 :    PRUnichar diff = 0x0BE6 - PRUnichar('0');
     452               0 :    DecimalToText(ordinal, result); 
     453               0 :    if (ordinal < 1 || ordinal > 9999) {
     454                 :      // Can't do those in this system.
     455               0 :      return false;
     456                 :    }
     457               0 :    PRUnichar* p = result.BeginWriting();
     458               0 :    for(; nsnull != *p ; p++) 
     459               0 :       if(*p != PRUnichar('0'))
     460               0 :          *p += diff;
     461               0 :    return true;
     462                 : }
     463                 : 
     464                 : 
     465                 : static const char gLowerRomanCharsA[] = "ixcm";
     466                 : static const char gUpperRomanCharsA[] = "IXCM";
     467                 : static const char gLowerRomanCharsB[] = "vld";
     468                 : static const char gUpperRomanCharsB[] = "VLD";
     469                 : 
     470               0 : static bool RomanToText(PRInt32 ordinal, nsString& result, const char* achars, const char* bchars)
     471                 : {
     472               0 :   if (ordinal < 1 || ordinal > 3999) {
     473               0 :     DecimalToText(ordinal, result);
     474               0 :     return false;
     475                 :   }
     476               0 :   nsAutoString addOn, decStr;
     477               0 :   decStr.AppendInt(ordinal, 10);
     478               0 :   PRIntn len = decStr.Length();
     479               0 :   const PRUnichar* dp = decStr.get();
     480               0 :   const PRUnichar* end = dp + len;
     481               0 :   PRIntn romanPos = len;
     482                 :   PRIntn n;
     483                 : 
     484               0 :   for (; dp < end; dp++) {
     485               0 :     romanPos--;
     486               0 :     addOn.SetLength(0);
     487               0 :     switch(*dp) {
     488                 :       case '3':
     489               0 :         addOn.Append(PRUnichar(achars[romanPos]));
     490                 :         // FALLTHROUGH
     491                 :       case '2':
     492               0 :         addOn.Append(PRUnichar(achars[romanPos]));
     493                 :         // FALLTHROUGH
     494                 :       case '1':
     495               0 :         addOn.Append(PRUnichar(achars[romanPos]));
     496               0 :         break;
     497                 :       case '4':
     498               0 :         addOn.Append(PRUnichar(achars[romanPos]));
     499                 :         // FALLTHROUGH
     500                 :       case '5': case '6':
     501                 :       case '7': case '8':
     502               0 :         addOn.Append(PRUnichar(bchars[romanPos]));
     503               0 :         for(n=0;'5'+n<*dp;n++) {
     504               0 :           addOn.Append(PRUnichar(achars[romanPos]));
     505                 :         }
     506               0 :         break;
     507                 :       case '9':
     508               0 :         addOn.Append(PRUnichar(achars[romanPos]));
     509               0 :         addOn.Append(PRUnichar(achars[romanPos+1]));
     510               0 :         break;
     511                 :       default:
     512               0 :         break;
     513                 :     }
     514               0 :     result.Append(addOn);
     515                 :   }
     516               0 :   return true;
     517                 : }
     518                 : 
     519                 : #define ALPHA_SIZE 26
     520                 : static const PRUnichar gLowerAlphaChars[ALPHA_SIZE]  = 
     521                 : {
     522                 : 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, // A   B   C   D   E
     523                 : 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, // F   G   H   I   J
     524                 : 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, // K   L   M   N   O
     525                 : 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, // P   Q   R   S   T
     526                 : 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, // U   V   W   X   Y
     527                 : 0x007A                                  // Z
     528                 : };
     529                 : 
     530                 : static const PRUnichar gUpperAlphaChars[ALPHA_SIZE]  = 
     531                 : {
     532                 : 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, // A   B   C   D   E
     533                 : 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, // F   G   H   I   J
     534                 : 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, // K   L   M   N   O
     535                 : 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, // P   Q   R   S   T
     536                 : 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, // U   V   W   X   Y
     537                 : 0x005A                                  // Z
     538                 : };
     539                 : 
     540                 : 
     541                 : #define KATAKANA_CHARS_SIZE 48
     542                 : // Page 94 Writing Systems of The World
     543                 : // after modification by momoi
     544                 : static const PRUnichar gKatakanaChars[KATAKANA_CHARS_SIZE] =
     545                 : {
     546                 : 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, //  a    i   u    e    o
     547                 : 0x30AB, 0x30AD, 0x30AF, 0x30B1, 0x30B3, // ka   ki  ku   ke   ko
     548                 : 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, // sa  shi  su   se   so
     549                 : 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, // ta  chi tsu   te   to
     550                 : 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, // na   ni  nu   ne   no
     551                 : 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, // ha   hi  hu   he   ho
     552                 : 0x30DE, 0x30DF, 0x30E0, 0x30E1, 0x30E2, // ma   mi  mu   me   mo
     553                 : 0x30E4,         0x30E6,         0x30E8, // ya       yu        yo 
     554                 : 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, // ra   ri  ru   re   ro
     555                 : 0x30EF, 0x30F0,         0x30F1, 0x30F2, // wa (w)i     (w)e (w)o
     556                 : 0x30F3                                  //  n
     557                 : };
     558                 : 
     559                 : #define HIRAGANA_CHARS_SIZE 48 
     560                 : static const PRUnichar gHiraganaChars[HIRAGANA_CHARS_SIZE] =
     561                 : {
     562                 : 0x3042, 0x3044, 0x3046, 0x3048, 0x304A, //  a    i    u    e    o
     563                 : 0x304B, 0x304D, 0x304F, 0x3051, 0x3053, // ka   ki   ku   ke   ko
     564                 : 0x3055, 0x3057, 0x3059, 0x305B, 0x305D, // sa  shi   su   se   so
     565                 : 0x305F, 0x3061, 0x3064, 0x3066, 0x3068, // ta  chi  tsu   te   to
     566                 : 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, // na   ni   nu   ne   no
     567                 : 0x306F, 0x3072, 0x3075, 0x3078, 0x307B, // ha   hi   hu   he   ho
     568                 : 0x307E, 0x307F, 0x3080, 0x3081, 0x3082, // ma   mi   mu   me   mo
     569                 : 0x3084,         0x3086,         0x3088, // ya        yu       yo 
     570                 : 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, // ra   ri   ru   re   ro
     571                 : 0x308F, 0x3090,         0x3091, 0x3092, // wa (w)i      (w)e (w)o
     572                 : 0x3093                                  // n
     573                 : };
     574                 : 
     575                 : 
     576                 : #define HIRAGANA_IROHA_CHARS_SIZE 47
     577                 : // Page 94 Writing Systems of The World
     578                 : static const PRUnichar gHiraganaIrohaChars[HIRAGANA_IROHA_CHARS_SIZE] =
     579                 : {
     580                 : 0x3044, 0x308D, 0x306F, 0x306B, 0x307B, //  i   ro   ha   ni   ho
     581                 : 0x3078, 0x3068, 0x3061, 0x308A, 0x306C, // he   to  chi   ri   nu
     582                 : 0x308B, 0x3092, 0x308F, 0x304B, 0x3088, // ru (w)o   wa   ka   yo
     583                 : 0x305F, 0x308C, 0x305D, 0x3064, 0x306D, // ta   re   so  tsu   ne
     584                 : 0x306A, 0x3089, 0x3080, 0x3046, 0x3090, // na   ra   mu    u (w)i
     585                 : 0x306E, 0x304A, 0x304F, 0x3084, 0x307E, // no    o   ku   ya   ma
     586                 : 0x3051, 0x3075, 0x3053, 0x3048, 0x3066, // ke   hu   ko    e   te
     587                 : 0x3042, 0x3055, 0x304D, 0x3086, 0x3081, //  a   sa   ki   yu   me
     588                 : 0x307F, 0x3057, 0x3091, 0x3072, 0x3082, // mi  shi (w)e   hi   mo 
     589                 : 0x305B, 0x3059                          // se   su
     590                 : };
     591                 : 
     592                 : #define KATAKANA_IROHA_CHARS_SIZE 47
     593                 : static const PRUnichar gKatakanaIrohaChars[KATAKANA_IROHA_CHARS_SIZE] =
     594                 : {
     595                 : 0x30A4, 0x30ED, 0x30CF, 0x30CB, 0x30DB, //  i   ro   ha   ni   ho
     596                 : 0x30D8, 0x30C8, 0x30C1, 0x30EA, 0x30CC, // he   to  chi   ri   nu
     597                 : 0x30EB, 0x30F2, 0x30EF, 0x30AB, 0x30E8, // ru (w)o   wa   ka   yo
     598                 : 0x30BF, 0x30EC, 0x30BD, 0x30C4, 0x30CD, // ta   re   so  tsu   ne
     599                 : 0x30CA, 0x30E9, 0x30E0, 0x30A6, 0x30F0, // na   ra   mu    u (w)i
     600                 : 0x30CE, 0x30AA, 0x30AF, 0x30E4, 0x30DE, // no    o   ku   ya   ma
     601                 : 0x30B1, 0x30D5, 0x30B3, 0x30A8, 0x30C6, // ke   hu   ko    e   te
     602                 : 0x30A2, 0x30B5, 0x30AD, 0x30E6, 0x30E1, //  a   sa   ki   yu   me
     603                 : 0x30DF, 0x30B7, 0x30F1, 0x30D2, 0x30E2, // mi  shi (w)e   hi   mo 
     604                 : 0x30BB, 0x30B9                          // se   su
     605                 : };
     606                 : 
     607                 : #define LOWER_GREEK_CHARS_SIZE 24
     608                 : // Note: 0x03C2 GREEK FINAL SIGMA is not used in here....
     609                 : static const PRUnichar gLowerGreekChars[LOWER_GREEK_CHARS_SIZE] =
     610                 : {
     611                 : 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, // alpha  beta  gamma  delta  epsilon
     612                 : 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, // zeta   eta   theta  iota   kappa   
     613                 : 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, // lamda  mu    nu     xi     omicron 
     614                 : 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, // pi     rho   sigma  tau    upsilon 
     615                 : 0x03C6, 0x03C7, 0x03C8, 0x03C9          // phi    chi   psi    omega    
     616                 : };
     617                 : 
     618                 : #define CJK_HEAVENLY_STEM_CHARS_SIZE 10 
     619                 : static const PRUnichar gCJKHeavenlyStemChars[CJK_HEAVENLY_STEM_CHARS_SIZE] =
     620                 : {
     621                 : 0x7532, 0x4e59, 0x4e19, 0x4e01, 0x620a,
     622                 : 0x5df1, 0x5e9a, 0x8f9b, 0x58ec, 0x7678
     623                 : };
     624                 : #define CJK_EARTHLY_BRANCH_CHARS_SIZE 12 
     625                 : static const PRUnichar gCJKEarthlyBranchChars[CJK_EARTHLY_BRANCH_CHARS_SIZE] =
     626                 : {
     627                 : 0x5b50, 0x4e11, 0x5bc5, 0x536f, 0x8fb0, 0x5df3,
     628                 : 0x5348, 0x672a, 0x7533, 0x9149, 0x620c, 0x4ea5
     629                 : };
     630                 : #define HANGUL_CHARS_SIZE 14 
     631                 : static const PRUnichar gHangulChars[HANGUL_CHARS_SIZE] =
     632                 : {
     633                 : 0xac00, 0xb098, 0xb2e4, 0xb77c, 0xb9c8, 0xbc14,
     634                 : 0xc0ac, 0xc544, 0xc790, 0xcc28, 0xce74, 0xd0c0,
     635                 : 0xd30c, 0xd558
     636                 : };
     637                 : #define HANGUL_CONSONANT_CHARS_SIZE 14 
     638                 : static const PRUnichar gHangulConsonantChars[HANGUL_CONSONANT_CHARS_SIZE] =
     639                 : {                                      
     640                 : 0x3131, 0x3134, 0x3137, 0x3139, 0x3141, 0x3142,
     641                 : 0x3145, 0x3147, 0x3148, 0x314a, 0x314b, 0x314c,
     642                 : 0x314d, 0x314e
     643                 : };
     644                 : 
     645                 : // Ge'ez set of Ethiopic ordered list. There are other locale-dependent sets.
     646                 : // For the time being, let's implement two Ge'ez sets only
     647                 : // per Momoi san's suggestion in bug 102252. 
     648                 : // For details, refer to http://www.ethiopic.org/Collation/OrderedLists.html.
     649                 : #define ETHIOPIC_HALEHAME_CHARS_SIZE 26
     650                 : static const PRUnichar gEthiopicHalehameChars[ETHIOPIC_HALEHAME_CHARS_SIZE] =
     651                 : {                                      
     652                 : 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
     653                 : 0x1230, 0x1240, 0x1260, 0x1270, 0x1280, 0x1290,
     654                 : 0x12a0, 0x12a8, 0x12c8, 0x12d0, 0x12d8, 0x12e8,
     655                 : 0x12f0, 0x1308, 0x1320, 0x1330, 0x1338, 0x1340,
     656                 : 0x1348, 0x1350
     657                 : };
     658                 : #define ETHIOPIC_HALEHAME_AM_CHARS_SIZE 33
     659                 : static const PRUnichar gEthiopicHalehameAmChars[ETHIOPIC_HALEHAME_AM_CHARS_SIZE] =
     660                 : {                                      
     661                 : 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
     662                 : 0x1230, 0x1238, 0x1240, 0x1260, 0x1270, 0x1278,
     663                 : 0x1280, 0x1290, 0x1298, 0x12a0, 0x12a8, 0x12b8,
     664                 : 0x12c8, 0x12d0, 0x12d8, 0x12e0, 0x12e8, 0x12f0,
     665                 : 0x1300, 0x1308, 0x1320, 0x1328, 0x1330, 0x1338,
     666                 : 0x1340, 0x1348, 0x1350
     667                 : };
     668                 : #define ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE 31
     669                 : static const PRUnichar gEthiopicHalehameTiErChars[ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE] =
     670                 : {                                      
     671                 : 0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230,
     672                 : 0x1238, 0x1240, 0x1250, 0x1260, 0x1270, 0x1278,
     673                 : 0x1290, 0x1298, 0x12a0, 0x12a8, 0x12b8, 0x12c8,
     674                 : 0x12d0, 0x12d8, 0x12e0, 0x12e8, 0x12f0, 0x1300,
     675                 : 0x1308, 0x1320, 0x1328, 0x1330, 0x1338, 0x1348,
     676                 : 0x1350
     677                 : };
     678                 : #define ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE 34
     679                 : static const PRUnichar gEthiopicHalehameTiEtChars[ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE] =
     680                 : {                                      
     681                 : 0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228,
     682                 : 0x1230, 0x1238, 0x1240, 0x1250, 0x1260, 0x1270,
     683                 : 0x1278, 0x1280, 0x1290, 0x1298, 0x12a0, 0x12a8,
     684                 : 0x12b8, 0x12c8, 0x12d0, 0x12d8, 0x12e0, 0x12e8,
     685                 : 0x12f0, 0x1300, 0x1308, 0x1320, 0x1328, 0x1330,
     686                 : 0x1338, 0x1340, 0x1348, 0x1350
     687                 : };
     688                 : 
     689                 : 
     690                 : // We know cjk-ideographic need 31 characters to display 99,999,999,999,999,999
     691                 : // georgian needs 6 at most
     692                 : // armenian needs 12 at most
     693                 : // hebrew may need more...
     694                 : 
     695                 : #define NUM_BUF_SIZE 34 
     696                 : 
     697               0 : static bool CharListToText(PRInt32 ordinal, nsString& result, const PRUnichar* chars, PRInt32 aBase)
     698                 : {
     699                 :   PRUnichar buf[NUM_BUF_SIZE];
     700               0 :   PRInt32 idx = NUM_BUF_SIZE;
     701               0 :   if (ordinal < 1) {
     702               0 :     DecimalToText(ordinal, result);
     703               0 :     return false;
     704                 :   }
     705               0 :   do {
     706               0 :     ordinal--; // a == 0
     707               0 :     PRInt32 cur = ordinal % aBase;
     708               0 :     buf[--idx] = chars[cur];
     709               0 :     ordinal /= aBase ;
     710                 :   } while ( ordinal > 0);
     711               0 :   result.Append(buf+idx,NUM_BUF_SIZE-idx);
     712               0 :   return true;
     713                 : }
     714                 : 
     715                 : 
     716                 : static const PRUnichar gCJKIdeographicDigit1[10] =
     717                 : {
     718                 :   0x96f6, 0x4e00, 0x4e8c, 0x4e09, 0x56db,  // 0 - 4
     719                 :   0x4e94, 0x516d, 0x4e03, 0x516b, 0x4e5d   // 5 - 9
     720                 : };
     721                 : static const PRUnichar gCJKIdeographicDigit2[10] =
     722                 : {
     723                 :   0x96f6, 0x58f9, 0x8cb3, 0x53c3, 0x8086,  // 0 - 4
     724                 :   0x4f0d, 0x9678, 0x67d2, 0x634c, 0x7396   // 5 - 9
     725                 : };
     726                 : static const PRUnichar gCJKIdeographicDigit3[10] =
     727                 : {
     728                 :   0x96f6, 0x58f9, 0x8d30, 0x53c1, 0x8086,  // 0 - 4
     729                 :   0x4f0d, 0x9646, 0x67d2, 0x634c, 0x7396   // 5 - 9
     730                 : };
     731                 : static const PRUnichar gCJKIdeographicUnit1[4] =
     732                 : {
     733                 :   0x000, 0x5341, 0x767e, 0x5343
     734                 : };
     735                 : static const PRUnichar gCJKIdeographicUnit2[4] =
     736                 : {
     737                 :   0x000, 0x62FE, 0x4F70, 0x4EDF
     738                 : };
     739                 : static const PRUnichar gCJKIdeographic10KUnit1[4] =
     740                 : {
     741                 :   0x000, 0x842c, 0x5104, 0x5146
     742                 : };
     743                 : static const PRUnichar gCJKIdeographic10KUnit2[4] =
     744                 : {
     745                 :   0x000, 0x4E07, 0x4ebf, 0x5146
     746                 : };
     747                 : static const PRUnichar gCJKIdeographic10KUnit3[4] =
     748                 : {
     749                 :   0x000, 0x4E07, 0x5104, 0x5146
     750                 : };
     751                 : 
     752               0 : static const bool CJKIdeographicToText(PRInt32 ordinal, nsString& result, 
     753                 :                                    const PRUnichar* digits,
     754                 :                                    const PRUnichar *unit, 
     755                 :                                    const PRUnichar* unit10k)
     756                 : {
     757                 : // In theory, we need the following if condiction,
     758                 : // However, the limit, 10 ^ 16, is greater than the max of PRUint32
     759                 : // so we don't really need to test it here.
     760                 : // if( ordinal > 9999999999999999)
     761                 : // {
     762                 : //    PR_snprintf(cbuf, sizeof(cbuf), "%ld", ordinal);
     763                 : //    result.Append(cbuf);
     764                 : // } 
     765                 : // else 
     766                 : // {
     767               0 :   if (ordinal < 0) {
     768               0 :     DecimalToText(ordinal, result);
     769               0 :     return false;
     770                 :   }
     771               0 :   PRUnichar c10kUnit = 0;
     772               0 :   PRUnichar cUnit = 0;
     773               0 :   PRUnichar cDigit = 0;
     774               0 :   PRUint32 ud = 0;
     775                 :   PRUnichar buf[NUM_BUF_SIZE];
     776               0 :   PRInt32 idx = NUM_BUF_SIZE;
     777               0 :   bool bOutputZero = ( 0 == ordinal );
     778               0 :   do {
     779               0 :     if(0 == (ud % 4)) {
     780               0 :       c10kUnit = unit10k[ud/4];
     781                 :     }
     782               0 :     PRInt32 cur = ordinal % 10;
     783               0 :     cDigit = digits[cur];
     784               0 :     if( 0 == cur)
     785                 :     {
     786               0 :       cUnit = 0;
     787               0 :       if(bOutputZero) {
     788               0 :         bOutputZero = false;
     789               0 :         if(0 != cDigit)
     790               0 :           buf[--idx] = cDigit;
     791                 :       }
     792                 :     }
     793                 :     else
     794                 :     {
     795               0 :       bOutputZero = true;
     796               0 :       cUnit = unit[ud%4];
     797                 : 
     798               0 :       if(0 != c10kUnit)
     799               0 :         buf[--idx] = c10kUnit;
     800               0 :       if(0 != cUnit)
     801               0 :         buf[--idx] = cUnit;
     802               0 :       if((0 != cDigit) && 
     803                 :          ( (1 != cur) || (1 != (ud%4)) || ( ordinal > 10)) )
     804               0 :         buf[--idx] = cDigit;
     805                 : 
     806               0 :       c10kUnit =  0;
     807                 :     }
     808               0 :     ordinal /= 10;
     809               0 :     ++ud;
     810                 : 
     811                 :   } while( ordinal > 0);
     812               0 :   result.Append(buf+idx,NUM_BUF_SIZE-idx);
     813                 : // }
     814               0 :   return true;
     815                 : }
     816                 : 
     817                 : #define HEBREW_GERESH       0x05F3
     818                 : static const PRUnichar gHebrewDigit[22] = 
     819                 : {
     820                 : //   1       2       3       4       5       6       7       8       9
     821                 : 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8,
     822                 : //  10      20      30      40      50      60      70      80      90
     823                 : 0x05D9, 0x05DB, 0x05DC, 0x05DE, 0x05E0, 0x05E1, 0x05E2, 0x05E4, 0x05E6,
     824                 : // 100     200     300     400
     825                 : 0x05E7, 0x05E8, 0x05E9, 0x05EA
     826                 : };
     827                 : 
     828               0 : static bool HebrewToText(PRInt32 ordinal, nsString& result)
     829                 : {
     830               0 :   if (ordinal < 1 || ordinal > 999999) {
     831               0 :     DecimalToText(ordinal, result);
     832               0 :     return false;
     833                 :   }
     834               0 :   bool outputSep = false;
     835               0 :   nsAutoString allText, thousandsGroup;
     836               0 :   do {
     837               0 :     thousandsGroup.Truncate();
     838               0 :     PRInt32 n3 = ordinal % 1000;
     839                 :     // Process digit for 100 - 900
     840               0 :     for(PRInt32 n1 = 400; n1 > 0; )
     841                 :     {
     842               0 :       if( n3 >= n1)
     843                 :       {
     844               0 :         n3 -= n1;
     845               0 :         thousandsGroup.Append(gHebrewDigit[(n1/100)-1+18]);
     846                 :       } else {
     847               0 :         n1 -= 100;
     848                 :       } // if
     849                 :     } // for
     850                 : 
     851                 :     // Process digit for 10 - 90
     852                 :     PRInt32 n2;
     853               0 :     if( n3 >= 10 )
     854                 :     {
     855                 :       // Special process for 15 and 16
     856               0 :       if(( 15 == n3 ) || (16 == n3)) {
     857                 :         // Special rule for religious reason...
     858                 :         // 15 is represented by 9 and 6, not 10 and 5
     859                 :         // 16 is represented by 9 and 7, not 10 and 6
     860               0 :         n2 = 9;
     861               0 :         thousandsGroup.Append(gHebrewDigit[ n2 - 1]);
     862                 :       } else {
     863               0 :         n2 = n3 - (n3 % 10);
     864               0 :         thousandsGroup.Append(gHebrewDigit[(n2/10)-1+9]);
     865                 :       } // if
     866               0 :       n3 -= n2;
     867                 :     } // if
     868                 :   
     869                 :     // Process digit for 1 - 9 
     870               0 :     if ( n3 > 0)
     871               0 :       thousandsGroup.Append(gHebrewDigit[n3-1]);
     872               0 :     if (outputSep) 
     873               0 :       thousandsGroup.Append((PRUnichar)HEBREW_GERESH);
     874               0 :     if (allText.IsEmpty())
     875               0 :       allText = thousandsGroup;
     876                 :     else
     877               0 :       allText = thousandsGroup + allText;
     878               0 :     ordinal /= 1000;
     879               0 :     outputSep = true;
     880                 :   } while (ordinal >= 1);
     881                 : 
     882               0 :   result.Append(allText);
     883               0 :   return true;
     884                 : }
     885                 : 
     886                 : 
     887               0 : static bool ArmenianToText(PRInt32 ordinal, nsString& result)
     888                 : {
     889               0 :   if (ordinal < 1 || ordinal > 9999) { // zero or reach the limit of Armenian numbering system
     890               0 :     DecimalToText(ordinal, result);
     891               0 :     return false;
     892                 :   }
     893                 : 
     894                 :   PRUnichar buf[NUM_BUF_SIZE];
     895               0 :   PRInt32 idx = NUM_BUF_SIZE;
     896               0 :   PRInt32 d = 0;
     897               0 :   do {
     898               0 :     PRInt32 cur = ordinal % 10;
     899               0 :     if (cur > 0)
     900                 :     {
     901               0 :       PRUnichar u = 0x0530 + (d * 9) + cur;
     902               0 :       buf[--idx] = u;
     903                 :     }
     904               0 :     ++d;
     905               0 :     ordinal /= 10;
     906                 :   } while (ordinal > 0);
     907               0 :   result.Append(buf + idx, NUM_BUF_SIZE - idx);
     908               0 :   return true;
     909                 : }
     910                 : 
     911                 : 
     912                 : static const PRUnichar gGeorgianValue [ 37 ] = { // 4 * 9 + 1 = 37
     913                 : //      1       2       3       4       5       6       7       8       9
     914                 :    0x10D0, 0x10D1, 0x10D2, 0x10D3, 0x10D4, 0x10D5, 0x10D6, 0x10F1, 0x10D7,
     915                 : //     10      20      30      40      50      60      70      80      90
     916                 :    0x10D8, 0x10D9, 0x10DA, 0x10DB, 0x10DC, 0x10F2, 0x10DD, 0x10DE, 0x10DF,
     917                 : //    100     200     300     400     500     600     700     800     900
     918                 :    0x10E0, 0x10E1, 0x10E2, 0x10F3, 0x10E4, 0x10E5, 0x10E6, 0x10E7, 0x10E8,
     919                 : //   1000    2000    3000    4000    5000    6000    7000    8000    9000
     920                 :    0x10E9, 0x10EA, 0x10EB, 0x10EC, 0x10ED, 0x10EE, 0x10F4, 0x10EF, 0x10F0,
     921                 : //  10000
     922                 :    0x10F5
     923                 : };
     924               0 : static bool GeorgianToText(PRInt32 ordinal, nsString& result)
     925                 : {
     926               0 :   if (ordinal < 1 || ordinal > 19999) { // zero or reach the limit of Georgian numbering system
     927               0 :     DecimalToText(ordinal, result);
     928               0 :     return false;
     929                 :   }
     930                 : 
     931                 :   PRUnichar buf[NUM_BUF_SIZE];
     932               0 :   PRInt32 idx = NUM_BUF_SIZE;
     933               0 :   PRInt32 d = 0;
     934               0 :   do {
     935               0 :     PRInt32 cur = ordinal % 10;
     936               0 :     if (cur > 0)
     937                 :     {
     938               0 :       PRUnichar u = gGeorgianValue[(d * 9 ) + ( cur - 1)];
     939               0 :       buf[--idx] = u;
     940                 :     }
     941               0 :     ++d;
     942               0 :     ordinal /= 10;
     943                 :   } while (ordinal > 0);
     944               0 :   result.Append(buf + idx, NUM_BUF_SIZE - idx);
     945               0 :   return true;
     946                 : }
     947                 : 
     948                 : // Convert ordinal to Ethiopic numeric representation.
     949                 : // The detail is available at http://www.ethiopic.org/Numerals/
     950                 : // The algorithm used here is based on the pseudo-code put up there by
     951                 : // Daniel Yacob <yacob@geez.org>.
     952                 : // Another reference is Unicode 3.0 standard section 11.1.
     953                 : #define ETHIOPIC_ONE             0x1369
     954                 : #define ETHIOPIC_TEN             0x1372
     955                 : #define ETHIOPIC_HUNDRED         0x137B
     956                 : #define ETHIOPIC_TEN_THOUSAND    0x137C
     957                 : 
     958               0 : static bool EthiopicToText(PRInt32 ordinal, nsString& result)
     959                 : {
     960               0 :   nsAutoString asciiNumberString;      // decimal string representation of ordinal
     961               0 :   DecimalToText(ordinal, asciiNumberString);
     962               0 :   if (ordinal < 1) {
     963               0 :     result.Append(asciiNumberString);
     964               0 :     return false;
     965                 :   }
     966               0 :   PRUint8 asciiStringLength = asciiNumberString.Length();
     967                 : 
     968                 :   // If number length is odd, add a leading "0"
     969                 :   // the leading "0" preconditions the string to always have the
     970                 :   // leading tens place populated, this avoids a check within the loop.
     971                 :   // If we didn't add the leading "0", decrement asciiStringLength so
     972                 :   // it will be equivalent to a zero-based index in both cases.
     973               0 :   if (asciiStringLength & 1) {
     974               0 :     asciiNumberString.Insert(NS_LITERAL_STRING("0"), 0);
     975                 :   } else {
     976               0 :     asciiStringLength--;
     977                 :   }
     978                 : 
     979                 :   // Iterate from the highest digits to lowest
     980                 :   // indexFromLeft       indexes digits (0 = most significant)
     981                 :   // groupIndexFromRight indexes pairs of digits (0 = least significant)
     982               0 :   for (PRUint8 indexFromLeft = 0, groupIndexFromRight = asciiStringLength >> 1;
     983                 :        indexFromLeft <= asciiStringLength;
     984                 :        indexFromLeft += 2, groupIndexFromRight--) {
     985               0 :     PRUint8 tensValue  = asciiNumberString.CharAt(indexFromLeft) & 0x0F;
     986               0 :     PRUint8 unitsValue = asciiNumberString.CharAt(indexFromLeft + 1) & 0x0F;
     987               0 :     PRUint8 groupValue = tensValue * 10 + unitsValue;
     988                 : 
     989               0 :     bool oddGroup = (groupIndexFromRight & 1);
     990                 : 
     991                 :     // we want to clear ETHIOPIC_ONE when it is superfluous
     992               0 :     if (ordinal > 1 &&
     993                 :         groupValue == 1 &&                  // one without a leading ten
     994                 :         (oddGroup || indexFromLeft == 0)) { // preceding (100) or leading the sequence
     995               0 :       unitsValue = 0;
     996                 :     }
     997                 : 
     998                 :     // put it all together...
     999               0 :     if (tensValue) {
    1000                 :       // map onto Ethiopic "tens":
    1001               0 :       result.Append((PRUnichar) (tensValue +  ETHIOPIC_TEN - 1));
    1002                 :     }
    1003               0 :     if (unitsValue) {
    1004                 :       //map onto Ethiopic "units":
    1005               0 :       result.Append((PRUnichar) (unitsValue + ETHIOPIC_ONE - 1));
    1006                 :     }
    1007                 :     // Add a separator for all even groups except the last,
    1008                 :     // and for odd groups with non-zero value.
    1009               0 :     if (oddGroup) {
    1010               0 :       if (groupValue) {
    1011               0 :         result.Append((PRUnichar) ETHIOPIC_HUNDRED);
    1012                 :       }
    1013                 :     } else {
    1014               0 :       if (groupIndexFromRight) {
    1015               0 :         result.Append((PRUnichar) ETHIOPIC_TEN_THOUSAND);
    1016                 :       }
    1017                 :     }
    1018                 :   }
    1019               0 :   return true;
    1020                 : }
    1021                 : 
    1022                 : 
    1023                 : /* static */ bool
    1024               0 : nsBulletFrame::AppendCounterText(PRInt32 aListStyleType,
    1025                 :                                  PRInt32 aOrdinal,
    1026                 :                                  nsString& result)
    1027                 : {
    1028               0 :   bool success = true;
    1029                 :   
    1030               0 :   switch (aListStyleType) {
    1031                 :     case NS_STYLE_LIST_STYLE_NONE: // used by counters code only
    1032               0 :       break;
    1033                 : 
    1034                 :     case NS_STYLE_LIST_STYLE_DISC: // used by counters code only
    1035                 :       // XXX We really need to do this the same way we do list bullets.
    1036               0 :       result.Append(PRUnichar(0x2022));
    1037               0 :       break;
    1038                 : 
    1039                 :     case NS_STYLE_LIST_STYLE_CIRCLE: // used by counters code only
    1040                 :       // XXX We really need to do this the same way we do list bullets.
    1041               0 :       result.Append(PRUnichar(0x25E6));
    1042               0 :       break;
    1043                 : 
    1044                 :     case NS_STYLE_LIST_STYLE_SQUARE: // used by counters code only
    1045                 :       // XXX We really need to do this the same way we do list bullets.
    1046               0 :       result.Append(PRUnichar(0x25FE));
    1047               0 :       break;
    1048                 : 
    1049                 :     case NS_STYLE_LIST_STYLE_DECIMAL:
    1050                 :     default: // CSS2 say "A users  agent that does not recognize a numbering system
    1051                 :       // should use 'decimal'
    1052               0 :       success = DecimalToText(aOrdinal, result);
    1053               0 :       break;
    1054                 : 
    1055                 :     case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
    1056               0 :       success = DecimalLeadingZeroToText(aOrdinal, result);
    1057               0 :       break;
    1058                 : 
    1059                 :     case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
    1060                 :       success = RomanToText(aOrdinal, result,
    1061               0 :                             gLowerRomanCharsA, gLowerRomanCharsB);
    1062               0 :       break;
    1063                 :     case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
    1064                 :       success = RomanToText(aOrdinal, result,
    1065               0 :                             gUpperRomanCharsA, gUpperRomanCharsB);
    1066               0 :       break;
    1067                 : 
    1068                 :     case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
    1069               0 :       success = CharListToText(aOrdinal, result, gLowerAlphaChars, ALPHA_SIZE);
    1070               0 :       break;
    1071                 : 
    1072                 :     case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
    1073               0 :       success = CharListToText(aOrdinal, result, gUpperAlphaChars, ALPHA_SIZE);
    1074               0 :       break;
    1075                 : 
    1076                 :     case NS_STYLE_LIST_STYLE_KATAKANA:
    1077                 :       success = CharListToText(aOrdinal, result, gKatakanaChars,
    1078               0 :                                KATAKANA_CHARS_SIZE);
    1079               0 :       break;
    1080                 : 
    1081                 :     case NS_STYLE_LIST_STYLE_HIRAGANA:
    1082                 :       success = CharListToText(aOrdinal, result, gHiraganaChars,
    1083               0 :                                HIRAGANA_CHARS_SIZE);
    1084               0 :       break;
    1085                 :     
    1086                 :     case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
    1087                 :       success = CharListToText(aOrdinal, result, gKatakanaIrohaChars,
    1088               0 :                                KATAKANA_IROHA_CHARS_SIZE);
    1089               0 :       break;
    1090                 :  
    1091                 :     case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA:
    1092                 :       success = CharListToText(aOrdinal, result, gHiraganaIrohaChars,
    1093               0 :                                HIRAGANA_IROHA_CHARS_SIZE);
    1094               0 :       break;
    1095                 : 
    1096                 :     case NS_STYLE_LIST_STYLE_LOWER_GREEK:
    1097                 :       success = CharListToText(aOrdinal, result, gLowerGreekChars ,
    1098               0 :                                LOWER_GREEK_CHARS_SIZE);
    1099               0 :       break;
    1100                 : 
    1101                 :     case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC: 
    1102                 :     case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL: 
    1103                 :       success = CJKIdeographicToText(aOrdinal, result, gCJKIdeographicDigit1,
    1104                 :                                      gCJKIdeographicUnit1,
    1105               0 :                                      gCJKIdeographic10KUnit1);
    1106               0 :       break;
    1107                 : 
    1108                 :     case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL: 
    1109                 :       success = CJKIdeographicToText(aOrdinal, result, gCJKIdeographicDigit2,
    1110                 :                                      gCJKIdeographicUnit2,
    1111               0 :                                      gCJKIdeographic10KUnit1);
    1112               0 :       break;
    1113                 : 
    1114                 :     case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL: 
    1115                 :       success = CJKIdeographicToText(aOrdinal, result, gCJKIdeographicDigit1,
    1116                 :                                      gCJKIdeographicUnit1,
    1117               0 :                                      gCJKIdeographic10KUnit2);
    1118               0 :       break;
    1119                 : 
    1120                 :     case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL: 
    1121                 :       success = CJKIdeographicToText(aOrdinal, result, gCJKIdeographicDigit3,
    1122                 :                                      gCJKIdeographicUnit2,
    1123               0 :                                      gCJKIdeographic10KUnit2);
    1124               0 :       break;
    1125                 : 
    1126                 :     case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL: 
    1127                 :       success = CJKIdeographicToText(aOrdinal, result, gCJKIdeographicDigit1,
    1128                 :                                      gCJKIdeographicUnit1,
    1129               0 :                                      gCJKIdeographic10KUnit3);
    1130               0 :       break;
    1131                 : 
    1132                 :     case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL: 
    1133                 :       success = CJKIdeographicToText(aOrdinal, result, gCJKIdeographicDigit2,
    1134                 :                                      gCJKIdeographicUnit2,
    1135               0 :                                      gCJKIdeographic10KUnit3);
    1136               0 :       break;
    1137                 : 
    1138                 :     case NS_STYLE_LIST_STYLE_HEBREW: 
    1139               0 :       success = HebrewToText(aOrdinal, result);
    1140               0 :       break;
    1141                 : 
    1142                 :     case NS_STYLE_LIST_STYLE_ARMENIAN: 
    1143               0 :       success = ArmenianToText(aOrdinal, result);
    1144               0 :       break;
    1145                 : 
    1146                 :     case NS_STYLE_LIST_STYLE_GEORGIAN: 
    1147               0 :       success = GeorgianToText(aOrdinal, result);
    1148               0 :       break;
    1149                 :  
    1150                 :     case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
    1151               0 :       success = OtherDecimalToText(aOrdinal, 0x0660, result);
    1152               0 :       break;
    1153                 :  
    1154                 :     case NS_STYLE_LIST_STYLE_MOZ_PERSIAN:
    1155                 :     case NS_STYLE_LIST_STYLE_MOZ_URDU:
    1156               0 :       success = OtherDecimalToText(aOrdinal, 0x06f0, result);
    1157               0 :       break;
    1158                 :  
    1159                 :     case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI:
    1160               0 :       success = OtherDecimalToText(aOrdinal, 0x0966, result);
    1161               0 :       break;
    1162                 :  
    1163                 :     case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI:
    1164               0 :       success = OtherDecimalToText(aOrdinal, 0x0a66, result);
    1165               0 :       break;
    1166                 :  
    1167                 :     case NS_STYLE_LIST_STYLE_MOZ_GUJARATI:
    1168               0 :       success = OtherDecimalToText(aOrdinal, 0x0AE6, result);
    1169               0 :       break;
    1170                 :  
    1171                 :     case NS_STYLE_LIST_STYLE_MOZ_ORIYA:
    1172               0 :       success = OtherDecimalToText(aOrdinal, 0x0B66, result);
    1173               0 :       break;
    1174                 :  
    1175                 :     case NS_STYLE_LIST_STYLE_MOZ_KANNADA:
    1176               0 :       success = OtherDecimalToText(aOrdinal, 0x0CE6, result);
    1177               0 :       break;
    1178                 :  
    1179                 :     case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM:
    1180               0 :       success = OtherDecimalToText(aOrdinal, 0x0D66, result);
    1181               0 :       break;
    1182                 :  
    1183                 :     case NS_STYLE_LIST_STYLE_MOZ_THAI:
    1184               0 :       success = OtherDecimalToText(aOrdinal, 0x0E50, result);
    1185               0 :       break;
    1186                 :  
    1187                 :     case NS_STYLE_LIST_STYLE_MOZ_LAO:
    1188               0 :       success = OtherDecimalToText(aOrdinal, 0x0ED0, result);
    1189               0 :       break;
    1190                 :  
    1191                 :     case NS_STYLE_LIST_STYLE_MOZ_MYANMAR:
    1192               0 :       success = OtherDecimalToText(aOrdinal, 0x1040, result);
    1193               0 :       break;
    1194                 :  
    1195                 :     case NS_STYLE_LIST_STYLE_MOZ_KHMER:
    1196               0 :       success = OtherDecimalToText(aOrdinal, 0x17E0, result);
    1197               0 :       break;
    1198                 :  
    1199                 :     case NS_STYLE_LIST_STYLE_MOZ_BENGALI:
    1200               0 :       success = OtherDecimalToText(aOrdinal, 0x09E6, result);
    1201               0 :       break;
    1202                 :  
    1203                 :     case NS_STYLE_LIST_STYLE_MOZ_TELUGU:
    1204               0 :       success = OtherDecimalToText(aOrdinal, 0x0C66, result);
    1205               0 :       break;
    1206                 :  
    1207                 :     case NS_STYLE_LIST_STYLE_MOZ_TAMIL:
    1208               0 :       success = TamilToText(aOrdinal, result);
    1209               0 :       break;
    1210                 : 
    1211                 :     case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
    1212                 :       success = CharListToText(aOrdinal, result, gCJKHeavenlyStemChars,
    1213               0 :                                CJK_HEAVENLY_STEM_CHARS_SIZE);
    1214               0 :       break;
    1215                 : 
    1216                 :     case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
    1217                 :       success = CharListToText(aOrdinal, result, gCJKEarthlyBranchChars,
    1218               0 :                                CJK_EARTHLY_BRANCH_CHARS_SIZE);
    1219               0 :       break;
    1220                 : 
    1221                 :     case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
    1222               0 :       success = CharListToText(aOrdinal, result, gHangulChars, HANGUL_CHARS_SIZE);
    1223               0 :       break;
    1224                 : 
    1225                 :     case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
    1226                 :       success = CharListToText(aOrdinal, result, gHangulConsonantChars,
    1227               0 :                                HANGUL_CONSONANT_CHARS_SIZE);
    1228               0 :       break;
    1229                 : 
    1230                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
    1231                 :       success = CharListToText(aOrdinal, result, gEthiopicHalehameChars,
    1232               0 :                                ETHIOPIC_HALEHAME_CHARS_SIZE);
    1233               0 :       break;
    1234                 : 
    1235                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
    1236               0 :       success = EthiopicToText(aOrdinal, result);
    1237               0 :       break;
    1238                 : 
    1239                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
    1240                 :       success = CharListToText(aOrdinal, result, gEthiopicHalehameAmChars,
    1241               0 :                                ETHIOPIC_HALEHAME_AM_CHARS_SIZE);
    1242               0 :       break;
    1243                 : 
    1244                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
    1245                 :       success = CharListToText(aOrdinal, result, gEthiopicHalehameTiErChars,
    1246               0 :                                ETHIOPIC_HALEHAME_TI_ER_CHARS_SIZE);
    1247               0 :       break;
    1248                 : 
    1249                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
    1250                 :       success = CharListToText(aOrdinal, result, gEthiopicHalehameTiEtChars,
    1251               0 :                                ETHIOPIC_HALEHAME_TI_ET_CHARS_SIZE);
    1252               0 :       break;
    1253                 :   }
    1254               0 :   return success;
    1255                 : }
    1256                 : 
    1257                 : bool
    1258               0 : nsBulletFrame::GetListItemText(const nsStyleList& aListStyle,
    1259                 :                                nsString& result)
    1260                 : {
    1261               0 :   const nsStyleVisibility* vis = GetStyleVisibility();
    1262                 : 
    1263               0 :   NS_ASSERTION(aListStyle.mListStyleType != NS_STYLE_LIST_STYLE_NONE &&
    1264                 :                aListStyle.mListStyleType != NS_STYLE_LIST_STYLE_DISC &&
    1265                 :                aListStyle.mListStyleType != NS_STYLE_LIST_STYLE_CIRCLE &&
    1266                 :                aListStyle.mListStyleType != NS_STYLE_LIST_STYLE_SQUARE,
    1267                 :                "we should be using specialized code for these types");
    1268                 :   bool success =
    1269               0 :     AppendCounterText(aListStyle.mListStyleType, mOrdinal, result);
    1270               0 :   if (success && aListStyle.mListStyleType == NS_STYLE_LIST_STYLE_HEBREW)
    1271               0 :     mTextIsRTL = true;
    1272                 : 
    1273                 :   // XXX For some of these systems, "." is wrong!  This should really be
    1274                 :   // pushed down into the individual cases!
    1275               0 :   nsString suffix = NS_LITERAL_STRING(".");
    1276                 : 
    1277                 :   // We're not going to do proper Bidi reordering on the list item marker, but
    1278                 :   // just display the whole thing as RTL or LTR, so we fake reordering by
    1279                 :   // appending the suffix to the end of the list item marker if the
    1280                 :   // directionality of the characters is the same as the style direction or
    1281                 :   // prepending it to the beginning if they are different.
    1282                 :   result = (mTextIsRTL == (vis->mDirection == NS_STYLE_DIRECTION_RTL)) ?
    1283               0 :           result + suffix : suffix + result;
    1284               0 :   return success;
    1285                 : }
    1286                 : 
    1287                 : #define MIN_BULLET_SIZE 1
    1288                 : 
    1289                 : 
    1290                 : void
    1291               0 : nsBulletFrame::GetDesiredSize(nsPresContext*  aCX,
    1292                 :                               nsRenderingContext *aRenderingContext,
    1293                 :                               nsHTMLReflowMetrics& aMetrics,
    1294                 :                               float aFontSizeInflation)
    1295                 : {
    1296                 :   // Reset our padding.  If we need it, we'll set it below.
    1297               0 :   mPadding.SizeTo(0, 0, 0, 0);
    1298                 :   
    1299               0 :   const nsStyleList* myList = GetStyleList();
    1300                 :   nscoord ascent;
    1301                 : 
    1302               0 :   RemoveStateBits(BULLET_FRAME_IMAGE_LOADING);
    1303                 : 
    1304               0 :   if (myList->GetListStyleImage() && mImageRequest) {
    1305                 :     PRUint32 status;
    1306               0 :     mImageRequest->GetImageStatus(&status);
    1307               0 :     if (status & imgIRequest::STATUS_SIZE_AVAILABLE &&
    1308               0 :         !(status & imgIRequest::STATUS_ERROR)) {
    1309                 :       // auto size the image
    1310               0 :       mComputedSize.width = mIntrinsicSize.width;
    1311               0 :       mComputedSize.height = mIntrinsicSize.height;
    1312                 : 
    1313               0 :       aMetrics.width = mComputedSize.width;
    1314               0 :       aMetrics.ascent = aMetrics.height = mComputedSize.height;
    1315                 : 
    1316               0 :       AddStateBits(BULLET_FRAME_IMAGE_LOADING);
    1317                 : 
    1318               0 :       return;
    1319                 :     }
    1320                 :   }
    1321                 : 
    1322                 :   // If we're getting our desired size and don't have an image, reset
    1323                 :   // mIntrinsicSize to (0,0).  Otherwise, if we used to have an image, it
    1324                 :   // changed, and the new one is coming in, but we're reflowing before it's
    1325                 :   // fully there, we'll end up with mIntrinsicSize not matching our size, but
    1326                 :   // won't trigger a reflow in OnStartContainer (because mIntrinsicSize will
    1327                 :   // match the image size).
    1328               0 :   mIntrinsicSize.SizeTo(0, 0);
    1329                 : 
    1330               0 :   nsRefPtr<nsFontMetrics> fm;
    1331                 :   nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
    1332               0 :                                         aFontSizeInflation);
    1333                 :   nscoord bulletSize;
    1334                 : 
    1335               0 :   nsAutoString text;
    1336               0 :   switch (myList->mListStyleType) {
    1337                 :     case NS_STYLE_LIST_STYLE_NONE:
    1338               0 :       aMetrics.width = 0;
    1339               0 :       aMetrics.ascent = aMetrics.height = 0;
    1340               0 :       break;
    1341                 : 
    1342                 :     case NS_STYLE_LIST_STYLE_DISC:
    1343                 :     case NS_STYLE_LIST_STYLE_CIRCLE:
    1344                 :     case NS_STYLE_LIST_STYLE_SQUARE:
    1345               0 :       ascent = fm->MaxAscent();
    1346               0 :       bulletSize = NS_MAX(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
    1347               0 :                           NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
    1348               0 :       mPadding.bottom = NSToCoordRound(float(ascent) / 8.0f);
    1349               0 :       aMetrics.width = mPadding.right + bulletSize;
    1350               0 :       aMetrics.ascent = aMetrics.height = mPadding.bottom + bulletSize;
    1351               0 :       break;
    1352                 : 
    1353                 :     default:
    1354                 :     case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO:
    1355                 :     case NS_STYLE_LIST_STYLE_DECIMAL:
    1356                 :     case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
    1357                 :     case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
    1358                 :     case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
    1359                 :     case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
    1360                 :     case NS_STYLE_LIST_STYLE_KATAKANA:
    1361                 :     case NS_STYLE_LIST_STYLE_HIRAGANA:
    1362                 :     case NS_STYLE_LIST_STYLE_KATAKANA_IROHA:
    1363                 :     case NS_STYLE_LIST_STYLE_HIRAGANA_IROHA:
    1364                 :     case NS_STYLE_LIST_STYLE_LOWER_GREEK:
    1365                 :     case NS_STYLE_LIST_STYLE_HEBREW: 
    1366                 :     case NS_STYLE_LIST_STYLE_ARMENIAN: 
    1367                 :     case NS_STYLE_LIST_STYLE_GEORGIAN: 
    1368                 :     case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC: 
    1369                 :     case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_INFORMAL: 
    1370                 :     case NS_STYLE_LIST_STYLE_MOZ_SIMP_CHINESE_FORMAL: 
    1371                 :     case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_INFORMAL: 
    1372                 :     case NS_STYLE_LIST_STYLE_MOZ_TRAD_CHINESE_FORMAL: 
    1373                 :     case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_INFORMAL: 
    1374                 :     case NS_STYLE_LIST_STYLE_MOZ_JAPANESE_FORMAL: 
    1375                 :     case NS_STYLE_LIST_STYLE_MOZ_CJK_HEAVENLY_STEM:
    1376                 :     case NS_STYLE_LIST_STYLE_MOZ_CJK_EARTHLY_BRANCH:
    1377                 :     case NS_STYLE_LIST_STYLE_MOZ_ARABIC_INDIC:
    1378                 :     case NS_STYLE_LIST_STYLE_MOZ_PERSIAN:
    1379                 :     case NS_STYLE_LIST_STYLE_MOZ_URDU:
    1380                 :     case NS_STYLE_LIST_STYLE_MOZ_DEVANAGARI:
    1381                 :     case NS_STYLE_LIST_STYLE_MOZ_GURMUKHI:
    1382                 :     case NS_STYLE_LIST_STYLE_MOZ_GUJARATI:
    1383                 :     case NS_STYLE_LIST_STYLE_MOZ_ORIYA:
    1384                 :     case NS_STYLE_LIST_STYLE_MOZ_KANNADA:
    1385                 :     case NS_STYLE_LIST_STYLE_MOZ_MALAYALAM:
    1386                 :     case NS_STYLE_LIST_STYLE_MOZ_BENGALI:
    1387                 :     case NS_STYLE_LIST_STYLE_MOZ_TAMIL:
    1388                 :     case NS_STYLE_LIST_STYLE_MOZ_TELUGU:
    1389                 :     case NS_STYLE_LIST_STYLE_MOZ_THAI:
    1390                 :     case NS_STYLE_LIST_STYLE_MOZ_LAO:
    1391                 :     case NS_STYLE_LIST_STYLE_MOZ_MYANMAR:
    1392                 :     case NS_STYLE_LIST_STYLE_MOZ_KHMER:
    1393                 :     case NS_STYLE_LIST_STYLE_MOZ_HANGUL:
    1394                 :     case NS_STYLE_LIST_STYLE_MOZ_HANGUL_CONSONANT:
    1395                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME:
    1396                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_NUMERIC:
    1397                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_AM:
    1398                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ER:
    1399                 :     case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
    1400               0 :       GetListItemText(*myList, text);
    1401               0 :       aMetrics.height = fm->MaxHeight();
    1402               0 :       aRenderingContext->SetFont(fm);
    1403                 :       aMetrics.width =
    1404                 :         nsLayoutUtils::GetStringWidth(this, aRenderingContext,
    1405               0 :                                       text.get(), text.Length());
    1406               0 :       aMetrics.width += mPadding.right;
    1407               0 :       aMetrics.ascent = fm->MaxAscent();
    1408               0 :       break;
    1409                 :   }
    1410                 : }
    1411                 : 
    1412                 : NS_IMETHODIMP
    1413               0 : nsBulletFrame::Reflow(nsPresContext* aPresContext,
    1414                 :                       nsHTMLReflowMetrics& aMetrics,
    1415                 :                       const nsHTMLReflowState& aReflowState,
    1416                 :                       nsReflowStatus& aStatus)
    1417                 : {
    1418               0 :   DO_GLOBAL_REFLOW_COUNT("nsBulletFrame");
    1419               0 :   DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
    1420                 : 
    1421                 :   float inflation =
    1422               0 :     nsLayoutUtils::FontSizeInflationFor(this, nsLayoutUtils::eInReflow);
    1423               0 :   SetFontSizeInflation(inflation);
    1424                 : 
    1425                 :   // Get the base size
    1426               0 :   GetDesiredSize(aPresContext, aReflowState.rendContext, aMetrics, inflation);
    1427                 : 
    1428                 :   // Add in the border and padding; split the top/bottom between the
    1429                 :   // ascent and descent to make things look nice
    1430               0 :   const nsMargin& borderPadding = aReflowState.mComputedBorderPadding;
    1431               0 :   aMetrics.width += borderPadding.left + borderPadding.right;
    1432               0 :   aMetrics.height += borderPadding.top + borderPadding.bottom;
    1433               0 :   aMetrics.ascent += borderPadding.top;
    1434                 : 
    1435                 :   // XXX this is a bit of a hack, we're assuming that no glyphs used for bullets
    1436                 :   // overflow their font-boxes. It'll do for now; to fix it for real, we really
    1437                 :   // should rewrite all the text-handling code here to use gfxTextRun (bug
    1438                 :   // 397294).
    1439               0 :   aMetrics.SetOverflowAreasToDesiredBounds();
    1440                 : 
    1441               0 :   aStatus = NS_FRAME_COMPLETE;
    1442               0 :   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
    1443               0 :   return NS_OK;
    1444                 : }
    1445                 : 
    1446                 : /* virtual */ nscoord
    1447               0 : nsBulletFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
    1448                 : {
    1449               0 :   nsHTMLReflowMetrics metrics;
    1450               0 :   DISPLAY_MIN_WIDTH(this, metrics.width);
    1451               0 :   GetDesiredSize(PresContext(), aRenderingContext, metrics, 1.0f);
    1452               0 :   return metrics.width;
    1453                 : }
    1454                 : 
    1455                 : /* virtual */ nscoord
    1456               0 : nsBulletFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
    1457                 : {
    1458               0 :   nsHTMLReflowMetrics metrics;
    1459               0 :   DISPLAY_PREF_WIDTH(this, metrics.width);
    1460               0 :   GetDesiredSize(PresContext(), aRenderingContext, metrics, 1.0f);
    1461               0 :   return metrics.width;
    1462                 : }
    1463                 : 
    1464                 : 
    1465               0 : NS_IMETHODIMP nsBulletFrame::OnStartContainer(imgIRequest *aRequest,
    1466                 :                                               imgIContainer *aImage)
    1467                 : {
    1468               0 :   if (!aImage) return NS_ERROR_INVALID_ARG;
    1469               0 :   if (!aRequest) return NS_ERROR_INVALID_ARG;
    1470                 : 
    1471                 :   PRUint32 status;
    1472               0 :   aRequest->GetImageStatus(&status);
    1473               0 :   if (status & imgIRequest::STATUS_ERROR) {
    1474               0 :     return NS_OK;
    1475                 :   }
    1476                 :   
    1477                 :   nscoord w, h;
    1478               0 :   aImage->GetWidth(&w);
    1479               0 :   aImage->GetHeight(&h);
    1480                 : 
    1481               0 :   nsPresContext* presContext = PresContext();
    1482                 : 
    1483                 :   nsSize newsize(nsPresContext::CSSPixelsToAppUnits(w),
    1484               0 :                  nsPresContext::CSSPixelsToAppUnits(h));
    1485                 : 
    1486               0 :   if (mIntrinsicSize != newsize) {
    1487               0 :     mIntrinsicSize = newsize;
    1488                 : 
    1489                 :     // Now that the size is available (or an error occurred), trigger
    1490                 :     // a reflow of the bullet frame.
    1491               0 :     nsIPresShell *shell = presContext->GetPresShell();
    1492               0 :     if (shell) {
    1493                 :       shell->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
    1494               0 :                               NS_FRAME_IS_DIRTY);
    1495                 :     }
    1496                 :   }
    1497                 : 
    1498                 :   // Handle animations
    1499               0 :   aImage->SetAnimationMode(presContext->ImageAnimationMode());
    1500                 :   // Ensure the animation (if any) is started. Note: There is no
    1501                 :   // corresponding call to Decrement for this. This Increment will be
    1502                 :   // 'cleaned up' by the Request when it is destroyed, but only then.
    1503               0 :   aRequest->IncrementAnimationConsumers();
    1504                 :   
    1505               0 :   return NS_OK;
    1506                 : }
    1507                 : 
    1508               0 : NS_IMETHODIMP nsBulletFrame::OnDataAvailable(imgIRequest *aRequest,
    1509                 :                                              bool aCurrentFrame,
    1510                 :                                              const nsIntRect *aRect)
    1511                 : {
    1512                 :   // The image has changed.
    1513                 :   // Invalidate the entire content area. Maybe it's not optimal but it's simple and
    1514                 :   // always correct, and I'll be a stunned mullet if it ever matters for performance
    1515               0 :   Invalidate(nsRect(0, 0, mRect.width, mRect.height));
    1516                 : 
    1517               0 :   return NS_OK;
    1518                 : }
    1519                 : 
    1520               0 : NS_IMETHODIMP nsBulletFrame::OnStopDecode(imgIRequest *aRequest,
    1521                 :                                           nsresult aStatus,
    1522                 :                                           const PRUnichar *aStatusArg)
    1523                 : {
    1524                 :   // XXX should the bulletframe do anything if the image failed to load?
    1525                 :   //     it didn't in the old code...
    1526                 : 
    1527                 : #if 0
    1528                 :   if (NS_FAILED(aStatus)) {
    1529                 :     // We failed to load the image. Notify the pres shell
    1530                 :     if (NS_FAILED(aStatus) && (mImageRequest == aRequest || !mImageRequest)) {
    1531                 :       imageFailed = true;
    1532                 :     }
    1533                 :   }
    1534                 : #endif
    1535                 : 
    1536               0 :   return NS_OK;
    1537                 : }
    1538                 : 
    1539               0 : NS_IMETHODIMP nsBulletFrame::OnImageIsAnimated(imgIRequest* aRequest)
    1540                 : {
    1541                 :   // Register the image request with the refresh driver now that we know it's
    1542                 :   // animated.
    1543               0 :   if (aRequest == mImageRequest) {
    1544                 :     nsLayoutUtils::RegisterImageRequest(PresContext(), mImageRequest,
    1545               0 :                                         &mRequestRegistered);
    1546                 :   }
    1547                 : 
    1548               0 :   return NS_OK;
    1549                 : }
    1550                 : 
    1551               0 : NS_IMETHODIMP nsBulletFrame::FrameChanged(imgIRequest *aRequest,
    1552                 :                                           imgIContainer *aContainer,
    1553                 :                                           const nsIntRect *aDirtyRect)
    1554                 : {
    1555                 :   // Invalidate the entire content area. Maybe it's not optimal but it's simple and
    1556                 :   // always correct.
    1557               0 :   Invalidate(nsRect(0, 0, mRect.width, mRect.height));
    1558                 : 
    1559               0 :   return NS_OK;
    1560                 : }
    1561                 : 
    1562                 : void
    1563               0 : nsBulletFrame::GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup)
    1564                 : {
    1565               0 :   if (!aPresContext)
    1566               0 :     return;
    1567                 : 
    1568               0 :   NS_PRECONDITION(nsnull != aLoadGroup, "null OUT parameter pointer");
    1569                 : 
    1570               0 :   nsIPresShell *shell = aPresContext->GetPresShell();
    1571                 : 
    1572               0 :   if (!shell)
    1573               0 :     return;
    1574                 : 
    1575               0 :   nsIDocument *doc = shell->GetDocument();
    1576               0 :   if (!doc)
    1577               0 :     return;
    1578                 : 
    1579               0 :   *aLoadGroup = doc->GetDocumentLoadGroup().get();  // already_AddRefed
    1580                 : }
    1581                 : 
    1582                 : union VoidPtrOrFloat {
    1583               0 :   VoidPtrOrFloat() : p(nsnull) {}
    1584                 : 
    1585                 :   void *p;
    1586                 :   float f;
    1587                 : };
    1588                 : 
    1589                 : float
    1590               0 : nsBulletFrame::GetFontSizeInflation() const
    1591                 : {
    1592               0 :   if (!HasFontSizeInflation()) {
    1593               0 :     return 1.0f;
    1594                 :   }
    1595               0 :   VoidPtrOrFloat u;
    1596               0 :   u.p = Properties().Get(FontSizeInflationProperty());
    1597               0 :   return u.f;
    1598                 : }
    1599                 : 
    1600                 : void
    1601               0 : nsBulletFrame::SetFontSizeInflation(float aInflation)
    1602                 : {
    1603               0 :   if (aInflation == 1.0f) {
    1604               0 :     if (HasFontSizeInflation()) {
    1605               0 :       RemoveStateBits(BULLET_FRAME_HAS_FONT_INFLATION);
    1606               0 :       Properties().Delete(FontSizeInflationProperty());
    1607                 :     }
    1608               0 :     return;
    1609                 :   }
    1610                 : 
    1611               0 :   AddStateBits(BULLET_FRAME_HAS_FONT_INFLATION);
    1612               0 :   VoidPtrOrFloat u;
    1613               0 :   u.f = aInflation;
    1614               0 :   Properties().Set(FontSizeInflationProperty(), u.p);
    1615                 : }
    1616                 : 
    1617                 : nscoord
    1618               0 : nsBulletFrame::GetBaseline() const
    1619                 : {
    1620               0 :   nscoord ascent = 0, bottomPadding;
    1621               0 :   if (GetStateBits() & BULLET_FRAME_IMAGE_LOADING) {
    1622               0 :     ascent = GetRect().height;
    1623                 :   } else {
    1624               0 :     nsRefPtr<nsFontMetrics> fm;
    1625                 :     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm),
    1626               0 :                                           GetFontSizeInflation());
    1627               0 :     const nsStyleList* myList = GetStyleList();
    1628               0 :     switch (myList->mListStyleType) {
    1629                 :       case NS_STYLE_LIST_STYLE_NONE:
    1630               0 :         break;
    1631                 : 
    1632                 :       case NS_STYLE_LIST_STYLE_DISC:
    1633                 :       case NS_STYLE_LIST_STYLE_CIRCLE:
    1634                 :       case NS_STYLE_LIST_STYLE_SQUARE:
    1635               0 :         ascent = fm->MaxAscent();
    1636               0 :         bottomPadding = NSToCoordRound(float(ascent) / 8.0f);
    1637               0 :         ascent = NS_MAX(nsPresContext::CSSPixelsToAppUnits(MIN_BULLET_SIZE),
    1638               0 :                         NSToCoordRound(0.8f * (float(ascent) / 2.0f)));
    1639               0 :         ascent += bottomPadding;
    1640               0 :         break;
    1641                 : 
    1642                 :       default:
    1643               0 :         ascent = fm->MaxAscent();
    1644               0 :         break;
    1645                 :     }
    1646                 :   }
    1647               0 :   return ascent + GetUsedBorderAndPadding().top;
    1648                 : }
    1649                 : 
    1650                 : 
    1651                 : 
    1652                 : 
    1653                 : 
    1654                 : 
    1655                 : 
    1656                 : 
    1657               0 : NS_IMPL_ISUPPORTS2(nsBulletListener, imgIDecoderObserver, imgIContainerObserver)
    1658                 : 
    1659               0 : nsBulletListener::nsBulletListener() :
    1660               0 :   mFrame(nsnull)
    1661                 : {
    1662               0 : }
    1663                 : 
    1664               0 : nsBulletListener::~nsBulletListener()
    1665                 : {
    1666               0 : }
    1667                 : 
    1668               0 : NS_IMETHODIMP nsBulletListener::OnStartContainer(imgIRequest *aRequest,
    1669                 :                                                  imgIContainer *aImage)
    1670                 : {
    1671               0 :   if (!mFrame)
    1672               0 :     return NS_ERROR_FAILURE;
    1673                 : 
    1674               0 :   return mFrame->OnStartContainer(aRequest, aImage);
    1675                 : }
    1676                 : 
    1677               0 : NS_IMETHODIMP nsBulletListener::OnDataAvailable(imgIRequest *aRequest,
    1678                 :                                                 bool aCurrentFrame,
    1679                 :                                                 const nsIntRect *aRect)
    1680                 : {
    1681               0 :   if (!mFrame)
    1682               0 :     return NS_OK;
    1683                 : 
    1684               0 :   return mFrame->OnDataAvailable(aRequest, aCurrentFrame, aRect);
    1685                 : }
    1686                 : 
    1687               0 : NS_IMETHODIMP nsBulletListener::OnStopDecode(imgIRequest *aRequest,
    1688                 :                                              nsresult status,
    1689                 :                                              const PRUnichar *statusArg)
    1690                 : {
    1691               0 :   if (!mFrame)
    1692               0 :     return NS_OK;
    1693                 :   
    1694               0 :   return mFrame->OnStopDecode(aRequest, status, statusArg);
    1695                 : }
    1696                 : 
    1697               0 : NS_IMETHODIMP nsBulletListener::OnImageIsAnimated(imgIRequest *aRequest)
    1698                 : {
    1699               0 :   if (!mFrame)
    1700               0 :     return NS_OK;
    1701                 : 
    1702               0 :   return mFrame->OnImageIsAnimated(aRequest);
    1703                 : }
    1704                 : 
    1705               0 : NS_IMETHODIMP nsBulletListener::FrameChanged(imgIRequest *aRequest,
    1706                 :                                              imgIContainer *aContainer,
    1707                 :                                              const nsIntRect *aDirtyRect)
    1708                 : {
    1709               0 :   if (!mFrame)
    1710               0 :     return NS_OK;
    1711                 : 
    1712               0 :   return mFrame->FrameChanged(aRequest, aContainer, aDirtyRect);
    1713                 : }

Generated by: LCOV version 1.7