LCOV - code coverage report
Current view: directory - layout/xul/base/src - nsTextBoxFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 475 0 0.0 %
Date: 2012-06-02 Functions: 47 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       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                 :  *   Eric Vaughan, Netscape Communications
      24                 :  *   Peter Annema <disttsc@bart.nl>
      25                 :  *   Dean Tessman <dean_tessman@hotmail.com>
      26                 :  *   Masayuki Nakano <masayuki@d-toybox.com>
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : #include "nsTextBoxFrame.h"
      43                 : 
      44                 : #include "nsReadableUtils.h"
      45                 : #include "nsCOMPtr.h"
      46                 : #include "nsGkAtoms.h"
      47                 : #include "nsPresContext.h"
      48                 : #include "nsRenderingContext.h"
      49                 : #include "nsStyleContext.h"
      50                 : #include "nsIContent.h"
      51                 : #include "nsINameSpaceManager.h"
      52                 : #include "nsBoxLayoutState.h"
      53                 : #include "nsMenuBarListener.h"
      54                 : #include "nsXPIDLString.h"
      55                 : #include "nsIServiceManager.h"
      56                 : #include "nsIDocument.h"
      57                 : #include "nsIDOMDocument.h"
      58                 : #include "nsIDOMElement.h"
      59                 : #include "nsIDOMXULLabelElement.h"
      60                 : #include "nsEventStateManager.h"
      61                 : #include "nsITheme.h"
      62                 : #include "nsUnicharUtils.h"
      63                 : #include "nsContentUtils.h"
      64                 : #include "nsDisplayList.h"
      65                 : #include "nsCSSRendering.h"
      66                 : #include "nsIReflowCallback.h"
      67                 : #include "nsBoxFrame.h"
      68                 : #include "mozilla/Preferences.h"
      69                 : #include "nsLayoutUtils.h"
      70                 : 
      71                 : #ifdef IBMBIDI
      72                 : #include "nsBidiUtils.h"
      73                 : #include "nsBidiPresUtils.h"
      74                 : #endif // IBMBIDI
      75                 : 
      76                 : using namespace mozilla;
      77                 : 
      78                 : class nsAccessKeyInfo
      79                 : {
      80                 : public:
      81                 :     PRInt32 mAccesskeyIndex;
      82                 :     nscoord mBeforeWidth, mAccessWidth, mAccessUnderlineSize, mAccessOffset;
      83                 : };
      84                 : 
      85                 : 
      86                 : bool nsTextBoxFrame::gAlwaysAppendAccessKey          = false;
      87                 : bool nsTextBoxFrame::gAccessKeyPrefInitialized       = false;
      88                 : bool nsTextBoxFrame::gInsertSeparatorBeforeAccessKey = false;
      89                 : bool nsTextBoxFrame::gInsertSeparatorPrefInitialized = false;
      90                 : 
      91                 : nsIFrame*
      92               0 : NS_NewTextBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
      93                 : {
      94               0 :     return new (aPresShell) nsTextBoxFrame (aPresShell, aContext);
      95                 : }
      96                 : 
      97               0 : NS_IMPL_FRAMEARENA_HELPERS(nsTextBoxFrame)
      98                 : 
      99                 : 
     100                 : NS_IMETHODIMP
     101               0 : nsTextBoxFrame::AttributeChanged(PRInt32         aNameSpaceID,
     102                 :                                  nsIAtom*        aAttribute,
     103                 :                                  PRInt32         aModType)
     104                 : {
     105                 :     bool aResize;
     106                 :     bool aRedraw;
     107                 : 
     108               0 :     UpdateAttributes(aAttribute, aResize, aRedraw);
     109                 : 
     110               0 :     if (aResize) {
     111               0 :         PresContext()->PresShell()->
     112                 :             FrameNeedsReflow(this, nsIPresShell::eStyleChange,
     113               0 :                              NS_FRAME_IS_DIRTY);
     114               0 :     } else if (aRedraw) {
     115               0 :         nsBoxLayoutState state(PresContext());
     116               0 :         Redraw(state);
     117                 :     }
     118                 : 
     119                 :     // If the accesskey changed, register for the new value
     120                 :     // The old value has been unregistered in nsXULElement::SetAttr
     121               0 :     if (aAttribute == nsGkAtoms::accesskey || aAttribute == nsGkAtoms::control)
     122               0 :         RegUnregAccessKey(true);
     123                 : 
     124               0 :     return NS_OK;
     125                 : }
     126                 : 
     127               0 : nsTextBoxFrame::nsTextBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext):
     128                 :   nsLeafBoxFrame(aShell, aContext), mAccessKeyInfo(nsnull), mCropType(CropRight),
     129               0 :   mNeedsReflowCallback(false)
     130                 : {
     131               0 :     MarkIntrinsicWidthsDirty();
     132               0 : }
     133                 : 
     134               0 : nsTextBoxFrame::~nsTextBoxFrame()
     135                 : {
     136               0 :     delete mAccessKeyInfo;
     137               0 : }
     138                 : 
     139                 : 
     140                 : NS_IMETHODIMP
     141               0 : nsTextBoxFrame::Init(nsIContent*      aContent,
     142                 :                      nsIFrame*        aParent,
     143                 :                      nsIFrame*        aPrevInFlow)
     144                 : {
     145               0 :     nsTextBoxFrameSuper::Init(aContent, aParent, aPrevInFlow);
     146                 : 
     147                 :     bool aResize;
     148                 :     bool aRedraw;
     149               0 :     UpdateAttributes(nsnull, aResize, aRedraw); /* update all */
     150                 : 
     151                 :     // register access key
     152               0 :     RegUnregAccessKey(true);
     153                 : 
     154               0 :     return NS_OK;
     155                 : }
     156                 : 
     157                 : void
     158               0 : nsTextBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
     159                 : {
     160                 :     // unregister access key
     161               0 :     RegUnregAccessKey(false);
     162               0 :     nsTextBoxFrameSuper::DestroyFrom(aDestructRoot);
     163               0 : }
     164                 : 
     165                 : bool
     166               0 : nsTextBoxFrame::AlwaysAppendAccessKey()
     167                 : {
     168               0 :   if (!gAccessKeyPrefInitialized) 
     169                 :   {
     170               0 :     gAccessKeyPrefInitialized = true;
     171                 : 
     172               0 :     const char* prefName = "intl.menuitems.alwaysappendaccesskeys";
     173               0 :     nsAdoptingString val = Preferences::GetLocalizedString(prefName);
     174               0 :     gAlwaysAppendAccessKey = val.Equals(NS_LITERAL_STRING("true"));
     175                 :   }
     176               0 :   return gAlwaysAppendAccessKey;
     177                 : }
     178                 : 
     179                 : bool
     180               0 : nsTextBoxFrame::InsertSeparatorBeforeAccessKey()
     181                 : {
     182               0 :   if (!gInsertSeparatorPrefInitialized)
     183                 :   {
     184               0 :     gInsertSeparatorPrefInitialized = true;
     185                 : 
     186               0 :     const char* prefName = "intl.menuitems.insertseparatorbeforeaccesskeys";
     187               0 :     nsAdoptingString val = Preferences::GetLocalizedString(prefName);
     188               0 :     gInsertSeparatorBeforeAccessKey = val.EqualsLiteral("true");
     189                 :   }
     190               0 :   return gInsertSeparatorBeforeAccessKey;
     191                 : }
     192                 : 
     193                 : class nsAsyncAccesskeyUpdate : public nsIReflowCallback
     194               0 : {
     195                 : public:
     196               0 :     nsAsyncAccesskeyUpdate(nsIFrame* aFrame) : mWeakFrame(aFrame)
     197                 :     {
     198               0 :     }
     199                 : 
     200               0 :     virtual bool ReflowFinished()
     201                 :     {
     202               0 :         bool shouldFlush = false;
     203                 :         nsTextBoxFrame* frame =
     204               0 :             static_cast<nsTextBoxFrame*>(mWeakFrame.GetFrame());
     205               0 :         if (frame) {
     206               0 :             shouldFlush = frame->UpdateAccesskey(mWeakFrame);
     207                 :         }
     208               0 :         delete this;
     209               0 :         return shouldFlush;
     210                 :     }
     211                 : 
     212               0 :     virtual void ReflowCallbackCanceled()
     213                 :     {
     214               0 :         delete this;
     215               0 :     }
     216                 : 
     217                 :     nsWeakFrame mWeakFrame;
     218                 : };
     219                 : 
     220                 : bool
     221               0 : nsTextBoxFrame::UpdateAccesskey(nsWeakFrame& aWeakThis)
     222                 : {
     223               0 :     nsAutoString accesskey;
     224               0 :     nsCOMPtr<nsIDOMXULLabelElement> labelElement = do_QueryInterface(mContent);
     225               0 :     NS_ENSURE_TRUE(aWeakThis.IsAlive(), false);
     226               0 :     if (labelElement) {
     227                 :         // Accesskey may be stored on control.
     228                 :         // Because this method is called by the reflow callback, current context
     229                 :         // may not be the right one. Pushing the context of mContent so that
     230                 :         // if nsIDOMXULLabelElement is implemented in XBL, we don't get a
     231                 :         // security exception.
     232               0 :         nsCxPusher cx;
     233               0 :         if (cx.Push(mContent)) {
     234               0 :           labelElement->GetAccessKey(accesskey);
     235               0 :           NS_ENSURE_TRUE(aWeakThis.IsAlive(), false);
     236                 :         }
     237                 :     }
     238                 :     else {
     239               0 :         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accesskey);
     240                 :     }
     241                 : 
     242               0 :     if (!accesskey.Equals(mAccessKey)) {
     243                 :         // Need to get clean mTitle.
     244               0 :         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, mTitle);
     245               0 :         mAccessKey = accesskey;
     246               0 :         UpdateAccessTitle();
     247               0 :         PresContext()->PresShell()->
     248                 :             FrameNeedsReflow(this, nsIPresShell::eStyleChange,
     249               0 :                              NS_FRAME_IS_DIRTY);
     250               0 :         return true;
     251                 :     }
     252               0 :     return false;
     253                 : }
     254                 : 
     255                 : void
     256               0 : nsTextBoxFrame::UpdateAttributes(nsIAtom*         aAttribute,
     257                 :                                  bool&          aResize,
     258                 :                                  bool&          aRedraw)
     259                 : {
     260               0 :     bool doUpdateTitle = false;
     261               0 :     aResize = false;
     262               0 :     aRedraw = false;
     263                 : 
     264               0 :     if (aAttribute == nsnull || aAttribute == nsGkAtoms::crop) {
     265                 :         static nsIContent::AttrValuesArray strings[] =
     266                 :           {&nsGkAtoms::left, &nsGkAtoms::start, &nsGkAtoms::center,
     267                 :            &nsGkAtoms::right, &nsGkAtoms::end, nsnull};
     268                 :         CroppingStyle cropType;
     269               0 :         switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::crop,
     270               0 :                                           strings, eCaseMatters)) {
     271                 :           case 0:
     272                 :           case 1:
     273               0 :             cropType = CropLeft;
     274               0 :             break;
     275                 :           case 2:
     276               0 :             cropType = CropCenter;
     277               0 :             break;
     278                 :           case 3:
     279                 :           case 4:
     280               0 :             cropType = CropRight;
     281               0 :             break;
     282                 :           default:
     283               0 :             cropType = CropNone;
     284               0 :             break;
     285                 :         }
     286                 : 
     287               0 :         if (cropType != mCropType) {
     288               0 :             aResize = true;
     289               0 :             mCropType = cropType;
     290                 :         }
     291                 :     }
     292                 : 
     293               0 :     if (aAttribute == nsnull || aAttribute == nsGkAtoms::value) {
     294               0 :         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, mTitle);
     295               0 :         doUpdateTitle = true;
     296                 :     }
     297                 : 
     298               0 :     if (aAttribute == nsnull || aAttribute == nsGkAtoms::accesskey) {
     299               0 :         mNeedsReflowCallback = true;
     300                 :         // Ensure that layout is refreshed and reflow callback called.
     301               0 :         aResize = true;
     302                 :     }
     303                 : 
     304               0 :     if (doUpdateTitle) {
     305               0 :         UpdateAccessTitle();
     306               0 :         aResize = true;
     307                 :     }
     308                 : 
     309               0 : }
     310                 : 
     311                 : class nsDisplayXULTextBox : public nsDisplayItem {
     312                 : public:
     313               0 :   nsDisplayXULTextBox(nsDisplayListBuilder* aBuilder,
     314                 :                       nsTextBoxFrame* aFrame) :
     315                 :     nsDisplayItem(aBuilder, aFrame),
     316               0 :     mDisableSubpixelAA(false)
     317                 :   {
     318               0 :     MOZ_COUNT_CTOR(nsDisplayXULTextBox);
     319               0 :   }
     320                 : #ifdef NS_BUILD_REFCNT_LOGGING
     321               0 :   virtual ~nsDisplayXULTextBox() {
     322               0 :     MOZ_COUNT_DTOR(nsDisplayXULTextBox);
     323               0 :   }
     324                 : #endif
     325                 : 
     326                 :   virtual void Paint(nsDisplayListBuilder* aBuilder,
     327                 :                      nsRenderingContext* aCtx);
     328                 :   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
     329               0 :   NS_DISPLAY_DECL_NAME("XULTextBox", TYPE_XUL_TEXT_BOX)
     330                 : 
     331                 :   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder);
     332                 : 
     333               0 :   virtual void DisableComponentAlpha() { mDisableSubpixelAA = true; }
     334                 : 
     335                 :   void PaintTextToContext(nsRenderingContext* aCtx,
     336                 :                           nsPoint aOffset,
     337                 :                           const nscolor* aColor);
     338                 : 
     339                 :   bool mDisableSubpixelAA;
     340                 : };
     341                 : 
     342                 : static void
     343               0 : PaintTextShadowCallback(nsRenderingContext* aCtx,
     344                 :                         nsPoint aShadowOffset,
     345                 :                         const nscolor& aShadowColor,
     346                 :                         void* aData)
     347                 : {
     348                 :   reinterpret_cast<nsDisplayXULTextBox*>(aData)->
     349               0 :            PaintTextToContext(aCtx, aShadowOffset, &aShadowColor);
     350               0 : }
     351                 : 
     352                 : void
     353               0 : nsDisplayXULTextBox::Paint(nsDisplayListBuilder* aBuilder,
     354                 :                            nsRenderingContext* aCtx)
     355                 : {
     356                 :   gfxContextAutoDisableSubpixelAntialiasing disable(aCtx->ThebesContext(),
     357               0 :                                                     mDisableSubpixelAA);
     358                 : 
     359                 :   // Paint the text shadow before doing any foreground stuff
     360                 :   nsRect drawRect = static_cast<nsTextBoxFrame*>(mFrame)->mTextDrawRect +
     361               0 :                     ToReferenceFrame();
     362                 :   nsLayoutUtils::PaintTextShadow(mFrame, aCtx,
     363                 :                                  drawRect, mVisibleRect,
     364               0 :                                  mFrame->GetStyleColor()->mColor,
     365                 :                                  PaintTextShadowCallback,
     366               0 :                                  (void*)this);
     367                 : 
     368               0 :   PaintTextToContext(aCtx, nsPoint(0, 0), nsnull);
     369               0 : }
     370                 : 
     371                 : void
     372               0 : nsDisplayXULTextBox::PaintTextToContext(nsRenderingContext* aCtx,
     373                 :                                         nsPoint aOffset,
     374                 :                                         const nscolor* aColor)
     375                 : {
     376                 :   static_cast<nsTextBoxFrame*>(mFrame)->
     377               0 :     PaintTitle(*aCtx, mVisibleRect, ToReferenceFrame() + aOffset, aColor);
     378               0 : }
     379                 : 
     380                 : nsRect
     381               0 : nsDisplayXULTextBox::GetBounds(nsDisplayListBuilder* aBuilder) {
     382               0 :   return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
     383                 : }
     384                 : 
     385                 : nsRect
     386               0 : nsDisplayXULTextBox::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder)
     387                 : {
     388               0 :   return static_cast<nsTextBoxFrame*>(mFrame)->GetComponentAlphaBounds() +
     389               0 :       ToReferenceFrame();
     390                 : }
     391                 : 
     392                 : NS_IMETHODIMP
     393               0 : nsTextBoxFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     394                 :                                  const nsRect&           aDirtyRect,
     395                 :                                  const nsDisplayListSet& aLists)
     396                 : {
     397               0 :     if (!IsVisibleForPainting(aBuilder))
     398               0 :       return NS_OK;
     399                 : 
     400               0 :     nsresult rv = nsLeafBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
     401               0 :     NS_ENSURE_SUCCESS(rv, rv);
     402                 :     
     403                 :     return aLists.Content()->AppendNewToTop(new (aBuilder)
     404               0 :         nsDisplayXULTextBox(aBuilder, this));
     405                 : }
     406                 : 
     407                 : void
     408               0 : nsTextBoxFrame::PaintTitle(nsRenderingContext& aRenderingContext,
     409                 :                            const nsRect&        aDirtyRect,
     410                 :                            nsPoint              aPt,
     411                 :                            const nscolor*       aOverrideColor)
     412                 : {
     413               0 :     if (mTitle.IsEmpty())
     414               0 :         return;
     415                 : 
     416               0 :     DrawText(aRenderingContext, aDirtyRect, mTextDrawRect + aPt, aOverrideColor);
     417                 : }
     418                 : 
     419                 : void
     420               0 : nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
     421                 :                          const nsRect&       aDirtyRect,
     422                 :                          const nsRect&       aTextRect,
     423                 :                          const nscolor*      aOverrideColor)
     424                 : {
     425               0 :     nsPresContext* presContext = PresContext();
     426                 : 
     427                 :     // paint the title
     428                 :     nscolor overColor;
     429                 :     nscolor underColor;
     430                 :     nscolor strikeColor;
     431                 :     PRUint8 overStyle;
     432                 :     PRUint8 underStyle;
     433                 :     PRUint8 strikeStyle;
     434                 : 
     435                 :     // Begin with no decorations
     436               0 :     PRUint8 decorations = NS_STYLE_TEXT_DECORATION_LINE_NONE;
     437                 :     // A mask of all possible decorations.
     438               0 :     PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK;
     439                 : 
     440               0 :     nsIFrame* f = this;
     441               0 :     do {  // find decoration colors
     442               0 :       nsStyleContext* context = f->GetStyleContext();
     443               0 :       if (!context->HasTextDecorationLines()) {
     444               0 :         break;
     445                 :       }
     446               0 :       const nsStyleTextReset* styleText = context->GetStyleTextReset();
     447                 :       
     448               0 :       if (decorMask & styleText->mTextDecorationLine) {  // a decoration defined here
     449                 :         nscolor color;
     450               0 :         if (aOverrideColor) {
     451               0 :           color = *aOverrideColor;
     452                 :         } else {
     453                 :           bool isForeground;
     454               0 :           styleText->GetDecorationColor(color, isForeground);
     455               0 :           if (isForeground) {
     456               0 :             color = nsLayoutUtils::GetColor(f, eCSSProperty_color);
     457                 :           }
     458                 :         }
     459               0 :         PRUint8 style = styleText->GetDecorationStyle();
     460                 : 
     461               0 :         if (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE & decorMask &
     462                 :               styleText->mTextDecorationLine) {
     463               0 :           underColor = color;
     464               0 :           underStyle = style;
     465               0 :           decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
     466               0 :           decorations |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
     467                 :         }
     468               0 :         if (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE & decorMask &
     469                 :               styleText->mTextDecorationLine) {
     470               0 :           overColor = color;
     471               0 :           overStyle = style;
     472               0 :           decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
     473               0 :           decorations |= NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
     474                 :         }
     475               0 :         if (NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH & decorMask &
     476                 :               styleText->mTextDecorationLine) {
     477               0 :           strikeColor = color;
     478               0 :           strikeStyle = style;
     479               0 :           decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
     480               0 :           decorations |= NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
     481                 :         }
     482                 :       }
     483                 :     } while (0 != decorMask &&
     484                 :              (f = nsLayoutUtils::GetParentOrPlaceholderFor(
     485               0 :                                    presContext->FrameManager(), f)));
     486                 : 
     487               0 :     nsRefPtr<nsFontMetrics> fontMet;
     488               0 :     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
     489                 : 
     490                 :     nscoord offset;
     491                 :     nscoord size;
     492               0 :     nscoord ascent = fontMet->MaxAscent();
     493                 : 
     494                 :     nscoord baseline =
     495               0 :       presContext->RoundAppUnitsToNearestDevPixels(aTextRect.y + ascent);
     496               0 :     nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
     497                 :     gfxPoint pt(presContext->AppUnitsToGfxUnits(aTextRect.x),
     498               0 :                 presContext->AppUnitsToGfxUnits(aTextRect.y));
     499               0 :     gfxFloat width = presContext->AppUnitsToGfxUnits(aTextRect.width);
     500               0 :     gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent);
     501               0 :     gfxRect dirtyRect(presContext->AppUnitsToGfxUnits(aDirtyRect));
     502                 : 
     503                 :     // Underlines are drawn before overlines, and both before the text
     504                 :     // itself, per http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1.
     505                 :     // (We don't apply this rule to the access-key underline because we only
     506                 :     // find out where that is as a side effect of drawing the text, in the
     507                 :     // general case -- see below.)
     508               0 :     if (decorations & (NS_FONT_DECORATION_OVERLINE |
     509                 :                        NS_FONT_DECORATION_UNDERLINE)) {
     510               0 :       fontMet->GetUnderline(offset, size);
     511               0 :       gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
     512               0 :       gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
     513               0 :       if ((decorations & NS_FONT_DECORATION_UNDERLINE) &&
     514                 :           underStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
     515                 :         nsCSSRendering::PaintDecorationLine(ctx, dirtyRect, underColor,
     516                 :                           pt, gfxSize(width, sizePixel),
     517                 :                           ascentPixel, offsetPixel,
     518               0 :                           NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, underStyle);
     519                 :       }
     520               0 :       if ((decorations & NS_FONT_DECORATION_OVERLINE) &&
     521                 :           overStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
     522                 :         nsCSSRendering::PaintDecorationLine(ctx, dirtyRect, overColor,
     523                 :                           pt, gfxSize(width, sizePixel),
     524                 :                           ascentPixel, ascentPixel,
     525               0 :                           NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, overStyle);
     526                 :       }
     527                 :     }
     528                 : 
     529                 :     nsRefPtr<nsRenderingContext> refContext =
     530               0 :         PresContext()->PresShell()->GetReferenceRenderingContext();
     531                 : 
     532               0 :     aRenderingContext.SetFont(fontMet);
     533               0 :     refContext->SetFont(fontMet);
     534                 : 
     535               0 :     CalculateUnderline(*refContext);
     536                 : 
     537               0 :     aRenderingContext.SetColor(aOverrideColor ? *aOverrideColor : GetStyleColor()->mColor);
     538                 : 
     539                 : #ifdef IBMBIDI
     540               0 :     nsresult rv = NS_ERROR_FAILURE;
     541                 : 
     542               0 :     if (mState & NS_FRAME_IS_BIDI) {
     543               0 :       presContext->SetBidiEnabled();
     544               0 :       const nsStyleVisibility* vis = GetStyleVisibility();
     545               0 :       nsBidiDirection direction = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ? NSBIDI_RTL : NSBIDI_LTR;
     546               0 :       if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
     547                 :           // We let the RenderText function calculate the mnemonic's
     548                 :           // underline position for us.
     549                 :           nsBidiPositionResolve posResolve;
     550               0 :           posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex;
     551               0 :           rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
     552                 :                                            presContext, aRenderingContext,
     553               0 :                                            *refContext,
     554                 :                                            aTextRect.x, baseline,
     555                 :                                            &posResolve,
     556               0 :                                            1);
     557               0 :           mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips;
     558               0 :           mAccessKeyInfo->mAccessWidth = posResolve.visualWidth;
     559                 :       }
     560                 :       else
     561                 :       {
     562               0 :           rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
     563                 :                                            presContext, aRenderingContext,
     564               0 :                                            *refContext,
     565               0 :                                            aTextRect.x, baseline);
     566                 :       }
     567                 :     }
     568               0 :     if (NS_FAILED(rv) )
     569                 : #endif // IBMBIDI
     570                 :     {
     571               0 :        aRenderingContext.SetTextRunRTL(false);
     572                 : 
     573               0 :        if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
     574                 :            // In the simple (non-BiDi) case, we calculate the mnemonic's
     575                 :            // underline position by getting the text metric.
     576                 :            // XXX are attribute values always two byte?
     577               0 :            if (mAccessKeyInfo->mAccesskeyIndex > 0)
     578                 :                mAccessKeyInfo->mBeforeWidth =
     579                 :                    refContext->GetWidth(mCroppedTitle.get(),
     580               0 :                                         mAccessKeyInfo->mAccesskeyIndex);
     581                 :            else
     582               0 :                mAccessKeyInfo->mBeforeWidth = 0;
     583                 :        }
     584                 : 
     585                 :        fontMet->DrawString(mCroppedTitle.get(), mCroppedTitle.Length(),
     586                 :                            aTextRect.x, baseline, &aRenderingContext,
     587               0 :                            refContext.get());
     588                 :     }
     589                 : 
     590               0 :     if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
     591                 :         aRenderingContext.FillRect(aTextRect.x + mAccessKeyInfo->mBeforeWidth,
     592                 :                                    aTextRect.y + mAccessKeyInfo->mAccessOffset,
     593                 :                                    mAccessKeyInfo->mAccessWidth,
     594               0 :                                    mAccessKeyInfo->mAccessUnderlineSize);
     595                 :     }
     596                 : 
     597                 :     // Strikeout is drawn on top of the text, per
     598                 :     // http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1.
     599               0 :     if ((decorations & NS_FONT_DECORATION_LINE_THROUGH) &&
     600                 :         strikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) {
     601               0 :       fontMet->GetStrikeout(offset, size);
     602               0 :       gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset);
     603               0 :       gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size);
     604                 :       nsCSSRendering::PaintDecorationLine(ctx, dirtyRect, strikeColor,
     605                 :                         pt, gfxSize(width, sizePixel), ascentPixel, offsetPixel,
     606                 :                         NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH,
     607               0 :                         strikeStyle);
     608                 :     }
     609               0 : }
     610                 : 
     611                 : void
     612               0 : nsTextBoxFrame::CalculateUnderline(nsRenderingContext& aRenderingContext)
     613                 : {
     614               0 :     if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
     615                 :          // Calculate all fields of mAccessKeyInfo which
     616                 :          // are the same for both BiDi and non-BiDi frames.
     617               0 :          const PRUnichar *titleString = mCroppedTitle.get();
     618               0 :          aRenderingContext.SetTextRunRTL(false);
     619                 :          mAccessKeyInfo->mAccessWidth =
     620                 :              aRenderingContext.GetWidth(titleString[mAccessKeyInfo->
     621               0 :                                                     mAccesskeyIndex]);
     622                 : 
     623                 :          nscoord offset, baseline;
     624               0 :          nsFontMetrics* metrics = aRenderingContext.FontMetrics();
     625               0 :          metrics->GetUnderline(offset, mAccessKeyInfo->mAccessUnderlineSize);
     626               0 :          baseline = metrics->MaxAscent();
     627               0 :          mAccessKeyInfo->mAccessOffset = baseline - offset;
     628                 :     }
     629               0 : }
     630                 : 
     631                 : nscoord
     632               0 : nsTextBoxFrame::CalculateTitleForWidth(nsPresContext*      aPresContext,
     633                 :                                        nsRenderingContext& aRenderingContext,
     634                 :                                        nscoord              aWidth)
     635                 : {
     636               0 :     if (mTitle.IsEmpty())
     637               0 :         return 0;
     638                 : 
     639               0 :     nsRefPtr<nsFontMetrics> fm;
     640               0 :     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm));
     641               0 :     aRenderingContext.SetFont(fm);
     642                 : 
     643                 :     // see if the text will completely fit in the width given
     644                 :     nscoord titleWidth = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
     645               0 :                                                        mTitle.get(), mTitle.Length());
     646                 : 
     647               0 :     if (titleWidth <= aWidth) {
     648               0 :         mCroppedTitle = mTitle;
     649                 : #ifdef IBMBIDI
     650               0 :         if (HasRTLChars(mTitle)) {
     651               0 :             mState |= NS_FRAME_IS_BIDI;
     652                 :         }
     653                 : #endif // IBMBIDI
     654               0 :         return titleWidth;  // fits, done.
     655                 :     }
     656                 : 
     657               0 :     const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
     658                 :     // start with an ellipsis
     659               0 :     mCroppedTitle.Assign(kEllipsis);
     660                 : 
     661                 :     // see if the width is even smaller than the ellipsis
     662                 :     // if so, clear the text (XXX set as many '.' as we can?).
     663               0 :     aRenderingContext.SetTextRunRTL(false);
     664               0 :     titleWidth = aRenderingContext.GetWidth(kEllipsis);
     665                 : 
     666               0 :     if (titleWidth > aWidth) {
     667               0 :         mCroppedTitle.SetLength(0);
     668               0 :         return 0;
     669                 :     }
     670                 : 
     671                 :     // if the ellipsis fits perfectly, no use in trying to insert
     672               0 :     if (titleWidth == aWidth)
     673               0 :         return titleWidth;
     674                 : 
     675               0 :     aWidth -= titleWidth;
     676                 : 
     677                 :     // XXX: This whole block should probably take surrogates into account
     678                 :     // XXX and clusters!
     679                 :     // ok crop things
     680               0 :     switch (mCropType)
     681                 :     {
     682                 :         case CropNone:
     683                 :         case CropRight:
     684                 :         {
     685                 :             nscoord cwidth;
     686               0 :             nscoord twidth = 0;
     687               0 :             int length = mTitle.Length();
     688                 :             int i;
     689               0 :             for (i = 0; i < length; ++i) {
     690               0 :                 PRUnichar ch = mTitle.CharAt(i);
     691                 :                 // still in LTR mode
     692               0 :                 cwidth = aRenderingContext.GetWidth(ch);
     693               0 :                 if (twidth + cwidth > aWidth)
     694               0 :                     break;
     695                 : 
     696               0 :                 twidth += cwidth;
     697                 : #ifdef IBMBIDI
     698               0 :                 if (UCS2_CHAR_IS_BIDI(ch) ) {
     699               0 :                   mState |= NS_FRAME_IS_BIDI;
     700                 :                 }
     701                 : #endif // IBMBIDI
     702                 :             }
     703                 : 
     704               0 :             if (i == 0)
     705               0 :                 return titleWidth;
     706                 : 
     707                 :             // insert what character we can in.
     708               0 :             nsAutoString title( mTitle );
     709               0 :             title.Truncate(i);
     710               0 :             mCroppedTitle.Insert(title, 0);
     711                 :         }
     712               0 :         break;
     713                 : 
     714                 :         case CropLeft:
     715                 :         {
     716                 :             nscoord cwidth;
     717               0 :             nscoord twidth = 0;
     718               0 :             int length = mTitle.Length();
     719                 :             int i;
     720               0 :             for (i=length-1; i >= 0; --i) {
     721               0 :                 PRUnichar ch = mTitle.CharAt(i);
     722               0 :                 cwidth = aRenderingContext.GetWidth(ch);
     723               0 :                 if (twidth + cwidth > aWidth)
     724               0 :                     break;
     725                 : 
     726               0 :                 twidth += cwidth;
     727                 : #ifdef IBMBIDI
     728               0 :                 if (UCS2_CHAR_IS_BIDI(ch) ) {
     729               0 :                   mState |= NS_FRAME_IS_BIDI;
     730                 :                 }
     731                 : #endif // IBMBIDI
     732                 :             }
     733                 : 
     734               0 :             if (i == length-1)
     735               0 :                 return titleWidth;
     736                 : 
     737               0 :             nsAutoString copy;
     738               0 :             mTitle.Right(copy, length-1-i);
     739               0 :             mCroppedTitle += copy;
     740                 :         }
     741               0 :         break;
     742                 : 
     743                 :         case CropCenter:
     744                 :         {
     745                 :             nscoord stringWidth =
     746                 :                 nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
     747               0 :                                               mTitle.get(), mTitle.Length());
     748               0 :             if (stringWidth <= aWidth) {
     749                 :                 // the entire string will fit in the maximum width
     750               0 :                 mCroppedTitle.Insert(mTitle, 0);
     751               0 :                 break;
     752                 :             }
     753                 : 
     754                 :             // determine how much of the string will fit in the max width
     755               0 :             nscoord charWidth = 0;
     756               0 :             nscoord totalWidth = 0;
     757                 :             PRUnichar ch;
     758                 :             int leftPos, rightPos;
     759               0 :             nsAutoString leftString, rightString;
     760                 : 
     761               0 :             rightPos = mTitle.Length() - 1;
     762               0 :             aRenderingContext.SetTextRunRTL(false);
     763               0 :             for (leftPos = 0; leftPos <= rightPos;) {
     764                 :                 // look at the next character on the left end
     765               0 :                 ch = mTitle.CharAt(leftPos);
     766               0 :                 charWidth = aRenderingContext.GetWidth(ch);
     767               0 :                 totalWidth += charWidth;
     768               0 :                 if (totalWidth > aWidth)
     769                 :                     // greater than the allowable width
     770               0 :                     break;
     771               0 :                 leftString.Insert(ch, leftString.Length());
     772                 : 
     773                 : #ifdef IBMBIDI
     774               0 :                 if (UCS2_CHAR_IS_BIDI(ch))
     775               0 :                     mState |= NS_FRAME_IS_BIDI;
     776                 : #endif
     777                 : 
     778                 :                 // look at the next character on the right end
     779               0 :                 if (rightPos > leftPos) {
     780                 :                     // haven't looked at this character yet
     781               0 :                     ch = mTitle.CharAt(rightPos);
     782               0 :                     charWidth = aRenderingContext.GetWidth(ch);
     783               0 :                     totalWidth += charWidth;
     784               0 :                     if (totalWidth > aWidth)
     785                 :                         // greater than the allowable width
     786               0 :                         break;
     787               0 :                     rightString.Insert(ch, 0);
     788                 : 
     789                 : #ifdef IBMBIDI
     790               0 :                     if (UCS2_CHAR_IS_BIDI(ch))
     791               0 :                         mState |= NS_FRAME_IS_BIDI;
     792                 : #endif
     793                 :                 }
     794                 : 
     795                 :                 // look at the next two characters
     796               0 :                 leftPos++;
     797               0 :                 rightPos--;
     798                 :             }
     799                 : 
     800               0 :             mCroppedTitle = leftString + kEllipsis + rightString;
     801                 :         }
     802               0 :         break;
     803                 :     }
     804                 : 
     805                 :     return nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
     806               0 :                                          mCroppedTitle.get(), mCroppedTitle.Length());
     807                 : }
     808                 : 
     809                 : #define OLD_ELLIPSIS NS_LITERAL_STRING("...")
     810                 : 
     811                 : // the following block is to append the accesskey to mTitle if there is an accesskey
     812                 : // but the mTitle doesn't have the character
     813                 : void
     814               0 : nsTextBoxFrame::UpdateAccessTitle()
     815                 : {
     816                 :     /*
     817                 :      * Note that if you change appending access key label spec,
     818                 :      * you need to maintain same logic in following methods. See bug 324159.
     819                 :      * toolkit/content/commonDialog.js (setLabelForNode)
     820                 :      * toolkit/content/widgets/text.xml (formatAccessKey)
     821                 :      */
     822                 :     PRInt32 menuAccessKey;
     823               0 :     nsMenuBarListener::GetMenuAccessKey(&menuAccessKey);
     824               0 :     if (!menuAccessKey || mAccessKey.IsEmpty())
     825               0 :         return;
     826                 : 
     827               0 :     if (!AlwaysAppendAccessKey() &&
     828               0 :         FindInReadable(mAccessKey, mTitle, nsCaseInsensitiveStringComparator()))
     829               0 :         return;
     830                 : 
     831               0 :     nsAutoString accessKeyLabel;
     832               0 :     accessKeyLabel += '(';
     833               0 :     accessKeyLabel += mAccessKey;
     834               0 :     ToUpperCase(accessKeyLabel);
     835               0 :     accessKeyLabel += ')';
     836                 : 
     837               0 :     if (mTitle.IsEmpty()) {
     838               0 :         mTitle = accessKeyLabel;
     839                 :         return;
     840                 :     }
     841                 : 
     842               0 :     const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis();
     843               0 :     PRUint32 offset = mTitle.Length();
     844               0 :     if (StringEndsWith(mTitle, kEllipsis)) {
     845               0 :         offset -= kEllipsis.Length();
     846               0 :     } else if (StringEndsWith(mTitle, OLD_ELLIPSIS)) {
     847                 :         // Try to check with our old ellipsis (for old addons)
     848               0 :         offset -= OLD_ELLIPSIS.Length();
     849                 :     } else {
     850                 :         // Try to check with
     851                 :         // our default ellipsis (for non-localized addons) or ':'
     852               0 :         const PRUnichar kLastChar = mTitle.Last();
     853               0 :         if (kLastChar == PRUnichar(0x2026) || kLastChar == PRUnichar(':'))
     854               0 :             offset--;
     855                 :     }
     856                 : 
     857               0 :     if (InsertSeparatorBeforeAccessKey() &&
     858               0 :         offset > 0 && !NS_IS_SPACE(mTitle[offset - 1])) {
     859               0 :         mTitle.Insert(' ', offset);
     860               0 :         offset++;
     861                 :     }
     862                 : 
     863               0 :     mTitle.Insert(accessKeyLabel, offset);
     864                 : }
     865                 : 
     866                 : void
     867               0 : nsTextBoxFrame::UpdateAccessIndex()
     868                 : {
     869                 :     PRInt32 menuAccessKey;
     870               0 :     nsMenuBarListener::GetMenuAccessKey(&menuAccessKey);
     871               0 :     if (menuAccessKey) {
     872               0 :         if (mAccessKey.IsEmpty()) {
     873               0 :             if (mAccessKeyInfo) {
     874               0 :                 delete mAccessKeyInfo;
     875               0 :                 mAccessKeyInfo = nsnull;
     876                 :             }
     877                 :         } else {
     878               0 :             if (!mAccessKeyInfo) {
     879               0 :                 mAccessKeyInfo = new nsAccessKeyInfo();
     880               0 :                 if (!mAccessKeyInfo)
     881               0 :                     return;
     882                 :             }
     883                 : 
     884               0 :             nsAString::const_iterator start, end;
     885                 :                 
     886               0 :             mCroppedTitle.BeginReading(start);
     887               0 :             mCroppedTitle.EndReading(end);
     888                 :             
     889                 :             // remember the beginning of the string
     890               0 :             nsAString::const_iterator originalStart = start;
     891                 : 
     892                 :             bool found;
     893               0 :             if (!AlwaysAppendAccessKey()) {
     894                 :                 // not appending access key - do case-sensitive search
     895                 :                 // first
     896               0 :                 found = FindInReadable(mAccessKey, start, end);
     897               0 :                 if (!found) {
     898                 :                     // didn't find it - perform a case-insensitive search
     899               0 :                     start = originalStart;
     900                 :                     found = FindInReadable(mAccessKey, start, end,
     901               0 :                                            nsCaseInsensitiveStringComparator());
     902                 :                 }
     903                 :             } else {
     904                 :                 found = RFindInReadable(mAccessKey, start, end,
     905               0 :                                         nsCaseInsensitiveStringComparator());
     906                 :             }
     907                 :             
     908               0 :             if (found)
     909               0 :                 mAccessKeyInfo->mAccesskeyIndex = Distance(originalStart, start);
     910                 :             else
     911               0 :                 mAccessKeyInfo->mAccesskeyIndex = kNotFound;
     912                 :         }
     913                 :     }
     914                 : }
     915                 : 
     916                 : NS_IMETHODIMP
     917               0 : nsTextBoxFrame::DoLayout(nsBoxLayoutState& aBoxLayoutState)
     918                 : {
     919               0 :     if (mNeedsReflowCallback) {
     920               0 :         nsIReflowCallback* cb = new nsAsyncAccesskeyUpdate(this);
     921               0 :         if (cb) {
     922               0 :             PresContext()->PresShell()->PostReflowCallback(cb);
     923                 :         }
     924               0 :         mNeedsReflowCallback = false;
     925                 :     }
     926                 : 
     927               0 :     nsresult rv = nsLeafBoxFrame::DoLayout(aBoxLayoutState);
     928                 : 
     929               0 :     CalcDrawRect(*aBoxLayoutState.GetRenderingContext());
     930                 : 
     931               0 :     const nsStyleText* textStyle = GetStyleText();
     932               0 :     if (textStyle->mTextShadow) {
     933               0 :       nsRect bounds(nsPoint(0, 0), GetSize());
     934               0 :       nsOverflowAreas overflow(bounds, bounds);
     935                 :       // Our scrollable overflow is our bounds; our visual overflow may
     936                 :       // extend beyond that.
     937               0 :       nsPoint origin(0,0);
     938               0 :       nsRect &vis = overflow.VisualOverflow();
     939               0 :       vis.UnionRect(vis, nsLayoutUtils::GetTextShadowRectsUnion(mTextDrawRect, this));
     940               0 :       FinishAndStoreOverflow(overflow, GetSize());
     941                 :     }
     942                 : 
     943               0 :     return rv;
     944                 : }
     945                 : 
     946                 : nsRect
     947               0 : nsTextBoxFrame::GetComponentAlphaBounds()
     948                 : {
     949                 :   return nsLayoutUtils::GetTextShadowRectsUnion(mTextDrawRect, this,
     950               0 :                                                 nsLayoutUtils::EXCLUDE_BLUR_SHADOWS);
     951                 : }
     952                 : 
     953                 : bool
     954               0 : nsTextBoxFrame::ComputesOwnOverflowArea()
     955                 : {
     956               0 :     return true;
     957                 : }
     958                 : 
     959                 : /* virtual */ void
     960               0 : nsTextBoxFrame::MarkIntrinsicWidthsDirty()
     961                 : {
     962               0 :     mNeedsRecalc = true;
     963               0 :     nsTextBoxFrameSuper::MarkIntrinsicWidthsDirty();
     964               0 : }
     965                 : 
     966                 : void
     967               0 : nsTextBoxFrame::GetTextSize(nsPresContext* aPresContext,
     968                 :                             nsRenderingContext& aRenderingContext,
     969                 :                             const nsString& aString,
     970                 :                             nsSize& aSize, nscoord& aAscent)
     971                 : {
     972               0 :     nsRefPtr<nsFontMetrics> fontMet;
     973               0 :     nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
     974               0 :     aSize.height = fontMet->MaxHeight();
     975               0 :     aRenderingContext.SetFont(fontMet);
     976                 :     aSize.width =
     977                 :       nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
     978               0 :                                     aString.get(), aString.Length());
     979               0 :     aAscent = fontMet->MaxAscent();
     980               0 : }
     981                 : 
     982                 : void
     983               0 : nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState)
     984                 : {
     985               0 :     if (mNeedsRecalc)
     986                 :     {
     987               0 :         nsSize size;
     988               0 :         nsPresContext* presContext = aBoxLayoutState.PresContext();
     989               0 :         nsRenderingContext* rendContext = aBoxLayoutState.GetRenderingContext();
     990               0 :         if (rendContext) {
     991                 :             GetTextSize(presContext, *rendContext,
     992               0 :                         mTitle, size, mAscent);
     993               0 :             mTextSize = size;
     994               0 :             mNeedsRecalc = false;
     995                 :         }
     996                 :     }
     997               0 : }
     998                 : 
     999                 : void
    1000               0 : nsTextBoxFrame::CalcDrawRect(nsRenderingContext &aRenderingContext)
    1001                 : {
    1002               0 :     nsRect textRect(nsPoint(0, 0), GetSize());
    1003               0 :     nsMargin borderPadding;
    1004               0 :     GetBorderAndPadding(borderPadding);
    1005               0 :     textRect.Deflate(borderPadding);
    1006                 : 
    1007                 :     // determine (cropped) title and underline position
    1008               0 :     nsPresContext* presContext = PresContext();
    1009                 :     // determine (cropped) title which fits in aRect.width and its width
    1010                 :     nscoord titleWidth =
    1011               0 :         CalculateTitleForWidth(presContext, aRenderingContext, textRect.width);
    1012                 :     // determine if and at which position to put the underline
    1013               0 :     UpdateAccessIndex();
    1014                 : 
    1015                 :     // make the rect as small as our (cropped) text.
    1016               0 :     nscoord outerWidth = textRect.width;
    1017               0 :     textRect.width = titleWidth;
    1018                 : 
    1019                 :     // Align our text within the overall rect by checking our text-align property.
    1020               0 :     const nsStyleVisibility* vis = GetStyleVisibility();
    1021               0 :     const nsStyleText* textStyle = GetStyleText();
    1022                 : 
    1023               0 :     if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_CENTER)
    1024               0 :       textRect.x += (outerWidth - textRect.width)/2;
    1025               0 :     else if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_RIGHT ||
    1026                 :              (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_DEFAULT &&
    1027                 :               vis->mDirection == NS_STYLE_DIRECTION_RTL) ||
    1028                 :              (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_END &&
    1029                 :               vis->mDirection == NS_STYLE_DIRECTION_LTR)) {
    1030               0 :       textRect.x += (outerWidth - textRect.width);
    1031                 :     }
    1032                 : 
    1033               0 :     mTextDrawRect = textRect;
    1034               0 : }
    1035                 : 
    1036                 : /**
    1037                 :  * Ok return our dimensions
    1038                 :  */
    1039                 : nsSize
    1040               0 : nsTextBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState)
    1041                 : {
    1042               0 :     CalcTextSize(aBoxLayoutState);
    1043                 : 
    1044               0 :     nsSize size = mTextSize;
    1045               0 :     DISPLAY_PREF_SIZE(this, size);
    1046                 : 
    1047               0 :     AddBorderAndPadding(size);
    1048                 :     bool widthSet, heightSet;
    1049               0 :     nsIBox::AddCSSPrefSize(this, size, widthSet, heightSet);
    1050                 : 
    1051                 :     return size;
    1052                 : }
    1053                 : 
    1054                 : /**
    1055                 :  * Ok return our dimensions
    1056                 :  */
    1057                 : nsSize
    1058               0 : nsTextBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState)
    1059                 : {
    1060               0 :     CalcTextSize(aBoxLayoutState);
    1061                 : 
    1062               0 :     nsSize size = mTextSize;
    1063               0 :     DISPLAY_MIN_SIZE(this, size);
    1064                 : 
    1065                 :     // if there is cropping our min width becomes our border and padding
    1066               0 :     if (mCropType != CropNone)
    1067               0 :         size.width = 0;
    1068                 : 
    1069               0 :     AddBorderAndPadding(size);
    1070                 :     bool widthSet, heightSet;
    1071               0 :     nsIBox::AddCSSMinSize(aBoxLayoutState, this, size, widthSet, heightSet);
    1072                 : 
    1073                 :     return size;
    1074                 : }
    1075                 : 
    1076                 : nscoord
    1077               0 : nsTextBoxFrame::GetBoxAscent(nsBoxLayoutState& aBoxLayoutState)
    1078                 : {
    1079               0 :     CalcTextSize(aBoxLayoutState);
    1080                 : 
    1081               0 :     nscoord ascent = mAscent;
    1082                 : 
    1083               0 :     nsMargin m(0,0,0,0);
    1084               0 :     GetBorderAndPadding(m);
    1085               0 :     ascent += m.top;
    1086                 : 
    1087               0 :     return ascent;
    1088                 : }
    1089                 : 
    1090                 : #ifdef DEBUG
    1091                 : NS_IMETHODIMP
    1092               0 : nsTextBoxFrame::GetFrameName(nsAString& aResult) const
    1093                 : {
    1094               0 :     MakeFrameName(NS_LITERAL_STRING("TextBox"), aResult);
    1095               0 :     aResult += NS_LITERAL_STRING("[value=") + mTitle + NS_LITERAL_STRING("]");
    1096               0 :     return NS_OK;
    1097                 : }
    1098                 : #endif
    1099                 : 
    1100                 : // If you make changes to this function, check its counterparts 
    1101                 : // in nsBoxFrame and nsXULLabelFrame
    1102                 : nsresult
    1103               0 : nsTextBoxFrame::RegUnregAccessKey(bool aDoReg)
    1104                 : {
    1105                 :     // if we have no content, we can't do anything
    1106               0 :     if (!mContent)
    1107               0 :         return NS_ERROR_FAILURE;
    1108                 : 
    1109                 :     // check if we have a |control| attribute
    1110                 :     // do this check first because few elements have control attributes, and we
    1111                 :     // can weed out most of the elements quickly.
    1112                 : 
    1113                 :     // XXXjag a side-effect is that we filter out anonymous <label>s
    1114                 :     // in e.g. <menu>, <menuitem>, <button>. These <label>s inherit
    1115                 :     // |accesskey| and would otherwise register themselves, overwriting
    1116                 :     // the content we really meant to be registered.
    1117               0 :     if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::control))
    1118               0 :         return NS_OK;
    1119                 : 
    1120                 :     // see if we even have an access key
    1121               0 :     nsAutoString accessKey;
    1122               0 :     mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
    1123                 : 
    1124               0 :     if (accessKey.IsEmpty())
    1125               0 :         return NS_OK;
    1126                 : 
    1127                 :     // With a valid PresContext we can get the ESM 
    1128                 :     // and (un)register the access key
    1129               0 :     nsEventStateManager *esm = PresContext()->EventStateManager();
    1130                 : 
    1131               0 :     PRUint32 key = accessKey.First();
    1132               0 :     if (aDoReg)
    1133               0 :         esm->RegisterAccessKey(mContent, key);
    1134                 :     else
    1135               0 :         esm->UnregisterAccessKey(mContent, key);
    1136                 : 
    1137               0 :     return NS_OK;
    1138                 : }

Generated by: LCOV version 1.7