1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/xul/nsTextBoxFrame.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1128 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "nsTextBoxFrame.h" 1.10 + 1.11 +#include "nsReadableUtils.h" 1.12 +#include "nsCOMPtr.h" 1.13 +#include "nsGkAtoms.h" 1.14 +#include "nsPresContext.h" 1.15 +#include "nsRenderingContext.h" 1.16 +#include "nsStyleContext.h" 1.17 +#include "nsIContent.h" 1.18 +#include "nsNameSpaceManager.h" 1.19 +#include "nsBoxLayoutState.h" 1.20 +#include "nsMenuBarListener.h" 1.21 +#include "nsXPIDLString.h" 1.22 +#include "nsIServiceManager.h" 1.23 +#include "nsIDOMElement.h" 1.24 +#include "nsIDOMXULLabelElement.h" 1.25 +#include "mozilla/EventStateManager.h" 1.26 +#include "nsITheme.h" 1.27 +#include "nsUnicharUtils.h" 1.28 +#include "nsContentUtils.h" 1.29 +#include "nsCxPusher.h" 1.30 +#include "nsDisplayList.h" 1.31 +#include "nsCSSRendering.h" 1.32 +#include "nsIReflowCallback.h" 1.33 +#include "nsBoxFrame.h" 1.34 +#include "mozilla/Preferences.h" 1.35 +#include "nsLayoutUtils.h" 1.36 +#include "mozilla/Attributes.h" 1.37 + 1.38 +#ifdef ACCESSIBILITY 1.39 +#include "nsAccessibilityService.h" 1.40 +#endif 1.41 + 1.42 +#include "nsBidiUtils.h" 1.43 +#include "nsBidiPresUtils.h" 1.44 + 1.45 +using namespace mozilla; 1.46 + 1.47 +class nsAccessKeyInfo 1.48 +{ 1.49 +public: 1.50 + int32_t mAccesskeyIndex; 1.51 + nscoord mBeforeWidth, mAccessWidth, mAccessUnderlineSize, mAccessOffset; 1.52 +}; 1.53 + 1.54 + 1.55 +bool nsTextBoxFrame::gAlwaysAppendAccessKey = false; 1.56 +bool nsTextBoxFrame::gAccessKeyPrefInitialized = false; 1.57 +bool nsTextBoxFrame::gInsertSeparatorBeforeAccessKey = false; 1.58 +bool nsTextBoxFrame::gInsertSeparatorPrefInitialized = false; 1.59 + 1.60 +nsIFrame* 1.61 +NS_NewTextBoxFrame (nsIPresShell* aPresShell, nsStyleContext* aContext) 1.62 +{ 1.63 + return new (aPresShell) nsTextBoxFrame (aPresShell, aContext); 1.64 +} 1.65 + 1.66 +NS_IMPL_FRAMEARENA_HELPERS(nsTextBoxFrame) 1.67 + 1.68 +NS_QUERYFRAME_HEAD(nsTextBoxFrame) 1.69 + NS_QUERYFRAME_ENTRY(nsTextBoxFrame) 1.70 +NS_QUERYFRAME_TAIL_INHERITING(nsTextBoxFrameSuper) 1.71 + 1.72 +nsresult 1.73 +nsTextBoxFrame::AttributeChanged(int32_t aNameSpaceID, 1.74 + nsIAtom* aAttribute, 1.75 + int32_t aModType) 1.76 +{ 1.77 + bool aResize; 1.78 + bool aRedraw; 1.79 + 1.80 + UpdateAttributes(aAttribute, aResize, aRedraw); 1.81 + 1.82 + if (aResize) { 1.83 + PresContext()->PresShell()-> 1.84 + FrameNeedsReflow(this, nsIPresShell::eStyleChange, 1.85 + NS_FRAME_IS_DIRTY); 1.86 + } else if (aRedraw) { 1.87 + nsBoxLayoutState state(PresContext()); 1.88 + Redraw(state); 1.89 + } 1.90 + 1.91 + // If the accesskey changed, register for the new value 1.92 + // The old value has been unregistered in nsXULElement::SetAttr 1.93 + if (aAttribute == nsGkAtoms::accesskey || aAttribute == nsGkAtoms::control) 1.94 + RegUnregAccessKey(true); 1.95 + 1.96 + return NS_OK; 1.97 +} 1.98 + 1.99 +nsTextBoxFrame::nsTextBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext): 1.100 + nsLeafBoxFrame(aShell, aContext), mAccessKeyInfo(nullptr), mCropType(CropRight), 1.101 + mNeedsReflowCallback(false) 1.102 +{ 1.103 + MarkIntrinsicWidthsDirty(); 1.104 +} 1.105 + 1.106 +nsTextBoxFrame::~nsTextBoxFrame() 1.107 +{ 1.108 + delete mAccessKeyInfo; 1.109 +} 1.110 + 1.111 + 1.112 +void 1.113 +nsTextBoxFrame::Init(nsIContent* aContent, 1.114 + nsIFrame* aParent, 1.115 + nsIFrame* aPrevInFlow) 1.116 +{ 1.117 + nsTextBoxFrameSuper::Init(aContent, aParent, aPrevInFlow); 1.118 + 1.119 + bool aResize; 1.120 + bool aRedraw; 1.121 + UpdateAttributes(nullptr, aResize, aRedraw); /* update all */ 1.122 + 1.123 + // register access key 1.124 + RegUnregAccessKey(true); 1.125 +} 1.126 + 1.127 +void 1.128 +nsTextBoxFrame::DestroyFrom(nsIFrame* aDestructRoot) 1.129 +{ 1.130 + // unregister access key 1.131 + RegUnregAccessKey(false); 1.132 + nsTextBoxFrameSuper::DestroyFrom(aDestructRoot); 1.133 +} 1.134 + 1.135 +bool 1.136 +nsTextBoxFrame::AlwaysAppendAccessKey() 1.137 +{ 1.138 + if (!gAccessKeyPrefInitialized) 1.139 + { 1.140 + gAccessKeyPrefInitialized = true; 1.141 + 1.142 + const char* prefName = "intl.menuitems.alwaysappendaccesskeys"; 1.143 + nsAdoptingString val = Preferences::GetLocalizedString(prefName); 1.144 + gAlwaysAppendAccessKey = val.Equals(NS_LITERAL_STRING("true")); 1.145 + } 1.146 + return gAlwaysAppendAccessKey; 1.147 +} 1.148 + 1.149 +bool 1.150 +nsTextBoxFrame::InsertSeparatorBeforeAccessKey() 1.151 +{ 1.152 + if (!gInsertSeparatorPrefInitialized) 1.153 + { 1.154 + gInsertSeparatorPrefInitialized = true; 1.155 + 1.156 + const char* prefName = "intl.menuitems.insertseparatorbeforeaccesskeys"; 1.157 + nsAdoptingString val = Preferences::GetLocalizedString(prefName); 1.158 + gInsertSeparatorBeforeAccessKey = val.EqualsLiteral("true"); 1.159 + } 1.160 + return gInsertSeparatorBeforeAccessKey; 1.161 +} 1.162 + 1.163 +class nsAsyncAccesskeyUpdate MOZ_FINAL : public nsIReflowCallback 1.164 +{ 1.165 +public: 1.166 + nsAsyncAccesskeyUpdate(nsIFrame* aFrame) : mWeakFrame(aFrame) 1.167 + { 1.168 + } 1.169 + 1.170 + virtual bool ReflowFinished() MOZ_OVERRIDE 1.171 + { 1.172 + bool shouldFlush = false; 1.173 + nsTextBoxFrame* frame = 1.174 + static_cast<nsTextBoxFrame*>(mWeakFrame.GetFrame()); 1.175 + if (frame) { 1.176 + shouldFlush = frame->UpdateAccesskey(mWeakFrame); 1.177 + } 1.178 + delete this; 1.179 + return shouldFlush; 1.180 + } 1.181 + 1.182 + virtual void ReflowCallbackCanceled() MOZ_OVERRIDE 1.183 + { 1.184 + delete this; 1.185 + } 1.186 + 1.187 + nsWeakFrame mWeakFrame; 1.188 +}; 1.189 + 1.190 +bool 1.191 +nsTextBoxFrame::UpdateAccesskey(nsWeakFrame& aWeakThis) 1.192 +{ 1.193 + nsAutoString accesskey; 1.194 + nsCOMPtr<nsIDOMXULLabelElement> labelElement = do_QueryInterface(mContent); 1.195 + NS_ENSURE_TRUE(aWeakThis.IsAlive(), false); 1.196 + if (labelElement) { 1.197 + // Accesskey may be stored on control. 1.198 + // Because this method is called by the reflow callback, current context 1.199 + // may not be the right one. Pushing the context of mContent so that 1.200 + // if nsIDOMXULLabelElement is implemented in XBL, we don't get a 1.201 + // security exception. 1.202 + nsCxPusher cx; 1.203 + if (cx.Push(mContent)) { 1.204 + labelElement->GetAccessKey(accesskey); 1.205 + NS_ENSURE_TRUE(aWeakThis.IsAlive(), false); 1.206 + } 1.207 + } 1.208 + else { 1.209 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accesskey); 1.210 + } 1.211 + 1.212 + if (!accesskey.Equals(mAccessKey)) { 1.213 + // Need to get clean mTitle. 1.214 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, mTitle); 1.215 + mAccessKey = accesskey; 1.216 + UpdateAccessTitle(); 1.217 + PresContext()->PresShell()-> 1.218 + FrameNeedsReflow(this, nsIPresShell::eStyleChange, 1.219 + NS_FRAME_IS_DIRTY); 1.220 + return true; 1.221 + } 1.222 + return false; 1.223 +} 1.224 + 1.225 +void 1.226 +nsTextBoxFrame::UpdateAttributes(nsIAtom* aAttribute, 1.227 + bool& aResize, 1.228 + bool& aRedraw) 1.229 +{ 1.230 + bool doUpdateTitle = false; 1.231 + aResize = false; 1.232 + aRedraw = false; 1.233 + 1.234 + if (aAttribute == nullptr || aAttribute == nsGkAtoms::crop) { 1.235 + static nsIContent::AttrValuesArray strings[] = 1.236 + {&nsGkAtoms::left, &nsGkAtoms::start, &nsGkAtoms::center, 1.237 + &nsGkAtoms::right, &nsGkAtoms::end, nullptr}; 1.238 + CroppingStyle cropType; 1.239 + switch (mContent->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::crop, 1.240 + strings, eCaseMatters)) { 1.241 + case 0: 1.242 + case 1: 1.243 + cropType = CropLeft; 1.244 + break; 1.245 + case 2: 1.246 + cropType = CropCenter; 1.247 + break; 1.248 + case 3: 1.249 + case 4: 1.250 + cropType = CropRight; 1.251 + break; 1.252 + default: 1.253 + cropType = CropNone; 1.254 + break; 1.255 + } 1.256 + 1.257 + if (cropType != mCropType) { 1.258 + aResize = true; 1.259 + mCropType = cropType; 1.260 + } 1.261 + } 1.262 + 1.263 + if (aAttribute == nullptr || aAttribute == nsGkAtoms::value) { 1.264 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, mTitle); 1.265 + doUpdateTitle = true; 1.266 + } 1.267 + 1.268 + if (aAttribute == nullptr || aAttribute == nsGkAtoms::accesskey) { 1.269 + mNeedsReflowCallback = true; 1.270 + // Ensure that layout is refreshed and reflow callback called. 1.271 + aResize = true; 1.272 + } 1.273 + 1.274 + if (doUpdateTitle) { 1.275 + UpdateAccessTitle(); 1.276 + aResize = true; 1.277 + } 1.278 + 1.279 +} 1.280 + 1.281 +class nsDisplayXULTextBox : public nsDisplayItem { 1.282 +public: 1.283 + nsDisplayXULTextBox(nsDisplayListBuilder* aBuilder, 1.284 + nsTextBoxFrame* aFrame) : 1.285 + nsDisplayItem(aBuilder, aFrame), 1.286 + mDisableSubpixelAA(false) 1.287 + { 1.288 + MOZ_COUNT_CTOR(nsDisplayXULTextBox); 1.289 + } 1.290 +#ifdef NS_BUILD_REFCNT_LOGGING 1.291 + virtual ~nsDisplayXULTextBox() { 1.292 + MOZ_COUNT_DTOR(nsDisplayXULTextBox); 1.293 + } 1.294 +#endif 1.295 + 1.296 + virtual void Paint(nsDisplayListBuilder* aBuilder, 1.297 + nsRenderingContext* aCtx) MOZ_OVERRIDE; 1.298 + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, 1.299 + bool* aSnap) MOZ_OVERRIDE; 1.300 + NS_DISPLAY_DECL_NAME("XULTextBox", TYPE_XUL_TEXT_BOX) 1.301 + 1.302 + virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; 1.303 + 1.304 + virtual void DisableComponentAlpha() MOZ_OVERRIDE { 1.305 + mDisableSubpixelAA = true; 1.306 + } 1.307 + 1.308 + void PaintTextToContext(nsRenderingContext* aCtx, 1.309 + nsPoint aOffset, 1.310 + const nscolor* aColor); 1.311 + 1.312 + bool mDisableSubpixelAA; 1.313 +}; 1.314 + 1.315 +static void 1.316 +PaintTextShadowCallback(nsRenderingContext* aCtx, 1.317 + nsPoint aShadowOffset, 1.318 + const nscolor& aShadowColor, 1.319 + void* aData) 1.320 +{ 1.321 + reinterpret_cast<nsDisplayXULTextBox*>(aData)-> 1.322 + PaintTextToContext(aCtx, aShadowOffset, &aShadowColor); 1.323 +} 1.324 + 1.325 +void 1.326 +nsDisplayXULTextBox::Paint(nsDisplayListBuilder* aBuilder, 1.327 + nsRenderingContext* aCtx) 1.328 +{ 1.329 + gfxContextAutoDisableSubpixelAntialiasing disable(aCtx->ThebesContext(), 1.330 + mDisableSubpixelAA); 1.331 + 1.332 + // Paint the text shadow before doing any foreground stuff 1.333 + nsRect drawRect = static_cast<nsTextBoxFrame*>(mFrame)->mTextDrawRect + 1.334 + ToReferenceFrame(); 1.335 + nsLayoutUtils::PaintTextShadow(mFrame, aCtx, 1.336 + drawRect, mVisibleRect, 1.337 + mFrame->StyleColor()->mColor, 1.338 + PaintTextShadowCallback, 1.339 + (void*)this); 1.340 + 1.341 + PaintTextToContext(aCtx, nsPoint(0, 0), nullptr); 1.342 +} 1.343 + 1.344 +void 1.345 +nsDisplayXULTextBox::PaintTextToContext(nsRenderingContext* aCtx, 1.346 + nsPoint aOffset, 1.347 + const nscolor* aColor) 1.348 +{ 1.349 + static_cast<nsTextBoxFrame*>(mFrame)-> 1.350 + PaintTitle(*aCtx, mVisibleRect, ToReferenceFrame() + aOffset, aColor); 1.351 +} 1.352 + 1.353 +nsRect 1.354 +nsDisplayXULTextBox::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { 1.355 + *aSnap = false; 1.356 + return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); 1.357 +} 1.358 + 1.359 +nsRect 1.360 +nsDisplayXULTextBox::GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) 1.361 +{ 1.362 + return static_cast<nsTextBoxFrame*>(mFrame)->GetComponentAlphaBounds() + 1.363 + ToReferenceFrame(); 1.364 +} 1.365 + 1.366 +void 1.367 +nsTextBoxFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.368 + const nsRect& aDirtyRect, 1.369 + const nsDisplayListSet& aLists) 1.370 +{ 1.371 + if (!IsVisibleForPainting(aBuilder)) 1.372 + return; 1.373 + 1.374 + nsLeafBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists); 1.375 + 1.376 + aLists.Content()->AppendNewToTop(new (aBuilder) 1.377 + nsDisplayXULTextBox(aBuilder, this)); 1.378 +} 1.379 + 1.380 +void 1.381 +nsTextBoxFrame::PaintTitle(nsRenderingContext& aRenderingContext, 1.382 + const nsRect& aDirtyRect, 1.383 + nsPoint aPt, 1.384 + const nscolor* aOverrideColor) 1.385 +{ 1.386 + if (mTitle.IsEmpty()) 1.387 + return; 1.388 + 1.389 + DrawText(aRenderingContext, aDirtyRect, mTextDrawRect + aPt, aOverrideColor); 1.390 +} 1.391 + 1.392 +void 1.393 +nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext, 1.394 + const nsRect& aDirtyRect, 1.395 + const nsRect& aTextRect, 1.396 + const nscolor* aOverrideColor) 1.397 +{ 1.398 + nsPresContext* presContext = PresContext(); 1.399 + 1.400 + // paint the title 1.401 + nscolor overColor; 1.402 + nscolor underColor; 1.403 + nscolor strikeColor; 1.404 + uint8_t overStyle; 1.405 + uint8_t underStyle; 1.406 + uint8_t strikeStyle; 1.407 + 1.408 + // Begin with no decorations 1.409 + uint8_t decorations = NS_STYLE_TEXT_DECORATION_LINE_NONE; 1.410 + // A mask of all possible decorations. 1.411 + uint8_t decorMask = NS_STYLE_TEXT_DECORATION_LINE_LINES_MASK; 1.412 + 1.413 + nsIFrame* f = this; 1.414 + do { // find decoration colors 1.415 + nsStyleContext* context = f->StyleContext(); 1.416 + if (!context->HasTextDecorationLines()) { 1.417 + break; 1.418 + } 1.419 + const nsStyleTextReset* styleText = context->StyleTextReset(); 1.420 + 1.421 + if (decorMask & styleText->mTextDecorationLine) { // a decoration defined here 1.422 + nscolor color; 1.423 + if (aOverrideColor) { 1.424 + color = *aOverrideColor; 1.425 + } else { 1.426 + bool isForeground; 1.427 + styleText->GetDecorationColor(color, isForeground); 1.428 + if (isForeground) { 1.429 + color = nsLayoutUtils::GetColor(f, eCSSProperty_color); 1.430 + } 1.431 + } 1.432 + uint8_t style = styleText->GetDecorationStyle(); 1.433 + 1.434 + if (NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE & decorMask & 1.435 + styleText->mTextDecorationLine) { 1.436 + underColor = color; 1.437 + underStyle = style; 1.438 + decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; 1.439 + decorations |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; 1.440 + } 1.441 + if (NS_STYLE_TEXT_DECORATION_LINE_OVERLINE & decorMask & 1.442 + styleText->mTextDecorationLine) { 1.443 + overColor = color; 1.444 + overStyle = style; 1.445 + decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERLINE; 1.446 + decorations |= NS_STYLE_TEXT_DECORATION_LINE_OVERLINE; 1.447 + } 1.448 + if (NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH & decorMask & 1.449 + styleText->mTextDecorationLine) { 1.450 + strikeColor = color; 1.451 + strikeStyle = style; 1.452 + decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH; 1.453 + decorations |= NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH; 1.454 + } 1.455 + } 1.456 + } while (0 != decorMask && 1.457 + (f = nsLayoutUtils::GetParentOrPlaceholderFor(f))); 1.458 + 1.459 + nsRefPtr<nsFontMetrics> fontMet; 1.460 + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); 1.461 + 1.462 + nscoord offset; 1.463 + nscoord size; 1.464 + nscoord ascent = fontMet->MaxAscent(); 1.465 + 1.466 + nscoord baseline = 1.467 + presContext->RoundAppUnitsToNearestDevPixels(aTextRect.y + ascent); 1.468 + nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext(); 1.469 + gfxPoint pt(presContext->AppUnitsToGfxUnits(aTextRect.x), 1.470 + presContext->AppUnitsToGfxUnits(aTextRect.y)); 1.471 + gfxFloat width = presContext->AppUnitsToGfxUnits(aTextRect.width); 1.472 + gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent); 1.473 + gfxFloat xInFrame = PresContext()->AppUnitsToGfxUnits(mTextDrawRect.x); 1.474 + gfxRect dirtyRect(presContext->AppUnitsToGfxUnits(aDirtyRect)); 1.475 + 1.476 + // Underlines are drawn before overlines, and both before the text 1.477 + // itself, per http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1. 1.478 + // (We don't apply this rule to the access-key underline because we only 1.479 + // find out where that is as a side effect of drawing the text, in the 1.480 + // general case -- see below.) 1.481 + if (decorations & (NS_FONT_DECORATION_OVERLINE | 1.482 + NS_FONT_DECORATION_UNDERLINE)) { 1.483 + fontMet->GetUnderline(offset, size); 1.484 + gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset); 1.485 + gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size); 1.486 + if ((decorations & NS_FONT_DECORATION_UNDERLINE) && 1.487 + underStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) { 1.488 + nsCSSRendering::PaintDecorationLine(this, ctx, dirtyRect, underColor, 1.489 + pt, xInFrame, gfxSize(width, sizePixel), 1.490 + ascentPixel, offsetPixel, 1.491 + NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, underStyle); 1.492 + } 1.493 + if ((decorations & NS_FONT_DECORATION_OVERLINE) && 1.494 + overStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) { 1.495 + nsCSSRendering::PaintDecorationLine(this, ctx, dirtyRect, overColor, 1.496 + pt, xInFrame, gfxSize(width, sizePixel), 1.497 + ascentPixel, ascentPixel, 1.498 + NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, overStyle); 1.499 + } 1.500 + } 1.501 + 1.502 + nsRefPtr<nsRenderingContext> refContext = 1.503 + PresContext()->PresShell()->CreateReferenceRenderingContext(); 1.504 + 1.505 + aRenderingContext.SetFont(fontMet); 1.506 + refContext->SetFont(fontMet); 1.507 + 1.508 + CalculateUnderline(*refContext); 1.509 + 1.510 + aRenderingContext.SetColor(aOverrideColor ? *aOverrideColor : StyleColor()->mColor); 1.511 + 1.512 + nsresult rv = NS_ERROR_FAILURE; 1.513 + 1.514 + if (mState & NS_FRAME_IS_BIDI) { 1.515 + presContext->SetBidiEnabled(); 1.516 + nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(StyleContext()); 1.517 + if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { 1.518 + // We let the RenderText function calculate the mnemonic's 1.519 + // underline position for us. 1.520 + nsBidiPositionResolve posResolve; 1.521 + posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex; 1.522 + rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), level, 1.523 + presContext, aRenderingContext, 1.524 + *refContext, 1.525 + aTextRect.x, baseline, 1.526 + &posResolve, 1.527 + 1); 1.528 + mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips; 1.529 + mAccessKeyInfo->mAccessWidth = posResolve.visualWidth; 1.530 + } 1.531 + else 1.532 + { 1.533 + rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), level, 1.534 + presContext, aRenderingContext, 1.535 + *refContext, 1.536 + aTextRect.x, baseline); 1.537 + } 1.538 + } 1.539 + if (NS_FAILED(rv)) { 1.540 + aRenderingContext.SetTextRunRTL(false); 1.541 + 1.542 + if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { 1.543 + // In the simple (non-BiDi) case, we calculate the mnemonic's 1.544 + // underline position by getting the text metric. 1.545 + // XXX are attribute values always two byte? 1.546 + if (mAccessKeyInfo->mAccesskeyIndex > 0) 1.547 + mAccessKeyInfo->mBeforeWidth = 1.548 + refContext->GetWidth(mCroppedTitle.get(), 1.549 + mAccessKeyInfo->mAccesskeyIndex); 1.550 + else 1.551 + mAccessKeyInfo->mBeforeWidth = 0; 1.552 + } 1.553 + 1.554 + fontMet->DrawString(mCroppedTitle.get(), mCroppedTitle.Length(), 1.555 + aTextRect.x, baseline, &aRenderingContext, 1.556 + refContext.get()); 1.557 + } 1.558 + 1.559 + if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { 1.560 + aRenderingContext.FillRect(aTextRect.x + mAccessKeyInfo->mBeforeWidth, 1.561 + aTextRect.y + mAccessKeyInfo->mAccessOffset, 1.562 + mAccessKeyInfo->mAccessWidth, 1.563 + mAccessKeyInfo->mAccessUnderlineSize); 1.564 + } 1.565 + 1.566 + // Strikeout is drawn on top of the text, per 1.567 + // http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1. 1.568 + if ((decorations & NS_FONT_DECORATION_LINE_THROUGH) && 1.569 + strikeStyle != NS_STYLE_TEXT_DECORATION_STYLE_NONE) { 1.570 + fontMet->GetStrikeout(offset, size); 1.571 + gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset); 1.572 + gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size); 1.573 + nsCSSRendering::PaintDecorationLine(this, ctx, dirtyRect, strikeColor, 1.574 + pt, xInFrame, gfxSize(width, sizePixel), ascentPixel, 1.575 + offsetPixel, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, 1.576 + strikeStyle); 1.577 + } 1.578 +} 1.579 + 1.580 +void 1.581 +nsTextBoxFrame::CalculateUnderline(nsRenderingContext& aRenderingContext) 1.582 +{ 1.583 + if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { 1.584 + // Calculate all fields of mAccessKeyInfo which 1.585 + // are the same for both BiDi and non-BiDi frames. 1.586 + const char16_t *titleString = mCroppedTitle.get(); 1.587 + aRenderingContext.SetTextRunRTL(false); 1.588 + mAccessKeyInfo->mAccessWidth = 1.589 + aRenderingContext.GetWidth(titleString[mAccessKeyInfo-> 1.590 + mAccesskeyIndex]); 1.591 + 1.592 + nscoord offset, baseline; 1.593 + nsFontMetrics* metrics = aRenderingContext.FontMetrics(); 1.594 + metrics->GetUnderline(offset, mAccessKeyInfo->mAccessUnderlineSize); 1.595 + baseline = metrics->MaxAscent(); 1.596 + mAccessKeyInfo->mAccessOffset = baseline - offset; 1.597 + } 1.598 +} 1.599 + 1.600 +nscoord 1.601 +nsTextBoxFrame::CalculateTitleForWidth(nsPresContext* aPresContext, 1.602 + nsRenderingContext& aRenderingContext, 1.603 + nscoord aWidth) 1.604 +{ 1.605 + if (mTitle.IsEmpty()) { 1.606 + mCroppedTitle.Truncate(); 1.607 + return 0; 1.608 + } 1.609 + 1.610 + nsRefPtr<nsFontMetrics> fm; 1.611 + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); 1.612 + aRenderingContext.SetFont(fm); 1.613 + 1.614 + // see if the text will completely fit in the width given 1.615 + nscoord titleWidth = nsLayoutUtils::GetStringWidth(this, &aRenderingContext, 1.616 + mTitle.get(), mTitle.Length()); 1.617 + 1.618 + if (titleWidth <= aWidth) { 1.619 + mCroppedTitle = mTitle; 1.620 + if (HasRTLChars(mTitle)) { 1.621 + mState |= NS_FRAME_IS_BIDI; 1.622 + } 1.623 + return titleWidth; // fits, done. 1.624 + } 1.625 + 1.626 + const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis(); 1.627 + // start with an ellipsis 1.628 + mCroppedTitle.Assign(kEllipsis); 1.629 + 1.630 + // see if the width is even smaller than the ellipsis 1.631 + // if so, clear the text (XXX set as many '.' as we can?). 1.632 + aRenderingContext.SetTextRunRTL(false); 1.633 + titleWidth = aRenderingContext.GetWidth(kEllipsis); 1.634 + 1.635 + if (titleWidth > aWidth) { 1.636 + mCroppedTitle.SetLength(0); 1.637 + return 0; 1.638 + } 1.639 + 1.640 + // if the ellipsis fits perfectly, no use in trying to insert 1.641 + if (titleWidth == aWidth) 1.642 + return titleWidth; 1.643 + 1.644 + aWidth -= titleWidth; 1.645 + 1.646 + // XXX: This whole block should probably take surrogates into account 1.647 + // XXX and clusters! 1.648 + // ok crop things 1.649 + switch (mCropType) 1.650 + { 1.651 + case CropNone: 1.652 + case CropRight: 1.653 + { 1.654 + nscoord cwidth; 1.655 + nscoord twidth = 0; 1.656 + int length = mTitle.Length(); 1.657 + int i; 1.658 + for (i = 0; i < length; ++i) { 1.659 + char16_t ch = mTitle.CharAt(i); 1.660 + // still in LTR mode 1.661 + cwidth = aRenderingContext.GetWidth(ch); 1.662 + if (twidth + cwidth > aWidth) 1.663 + break; 1.664 + 1.665 + twidth += cwidth; 1.666 + if (UCS2_CHAR_IS_BIDI(ch) ) { 1.667 + mState |= NS_FRAME_IS_BIDI; 1.668 + } 1.669 + } 1.670 + 1.671 + if (i == 0) 1.672 + return titleWidth; 1.673 + 1.674 + // insert what character we can in. 1.675 + nsAutoString title( mTitle ); 1.676 + title.Truncate(i); 1.677 + mCroppedTitle.Insert(title, 0); 1.678 + } 1.679 + break; 1.680 + 1.681 + case CropLeft: 1.682 + { 1.683 + nscoord cwidth; 1.684 + nscoord twidth = 0; 1.685 + int length = mTitle.Length(); 1.686 + int i; 1.687 + for (i=length-1; i >= 0; --i) { 1.688 + char16_t ch = mTitle.CharAt(i); 1.689 + cwidth = aRenderingContext.GetWidth(ch); 1.690 + if (twidth + cwidth > aWidth) 1.691 + break; 1.692 + 1.693 + twidth += cwidth; 1.694 + if (UCS2_CHAR_IS_BIDI(ch) ) { 1.695 + mState |= NS_FRAME_IS_BIDI; 1.696 + } 1.697 + } 1.698 + 1.699 + if (i == length-1) 1.700 + return titleWidth; 1.701 + 1.702 + nsAutoString copy; 1.703 + mTitle.Right(copy, length-1-i); 1.704 + mCroppedTitle += copy; 1.705 + } 1.706 + break; 1.707 + 1.708 + case CropCenter: 1.709 + { 1.710 + nscoord stringWidth = 1.711 + nsLayoutUtils::GetStringWidth(this, &aRenderingContext, 1.712 + mTitle.get(), mTitle.Length()); 1.713 + if (stringWidth <= aWidth) { 1.714 + // the entire string will fit in the maximum width 1.715 + mCroppedTitle.Insert(mTitle, 0); 1.716 + break; 1.717 + } 1.718 + 1.719 + // determine how much of the string will fit in the max width 1.720 + nscoord charWidth = 0; 1.721 + nscoord totalWidth = 0; 1.722 + char16_t ch; 1.723 + int leftPos, rightPos; 1.724 + nsAutoString leftString, rightString; 1.725 + 1.726 + rightPos = mTitle.Length() - 1; 1.727 + aRenderingContext.SetTextRunRTL(false); 1.728 + for (leftPos = 0; leftPos <= rightPos;) { 1.729 + // look at the next character on the left end 1.730 + ch = mTitle.CharAt(leftPos); 1.731 + charWidth = aRenderingContext.GetWidth(ch); 1.732 + totalWidth += charWidth; 1.733 + if (totalWidth > aWidth) 1.734 + // greater than the allowable width 1.735 + break; 1.736 + leftString.Insert(ch, leftString.Length()); 1.737 + 1.738 + if (UCS2_CHAR_IS_BIDI(ch)) 1.739 + mState |= NS_FRAME_IS_BIDI; 1.740 + 1.741 + // look at the next character on the right end 1.742 + if (rightPos > leftPos) { 1.743 + // haven't looked at this character yet 1.744 + ch = mTitle.CharAt(rightPos); 1.745 + charWidth = aRenderingContext.GetWidth(ch); 1.746 + totalWidth += charWidth; 1.747 + if (totalWidth > aWidth) 1.748 + // greater than the allowable width 1.749 + break; 1.750 + rightString.Insert(ch, 0); 1.751 + 1.752 + if (UCS2_CHAR_IS_BIDI(ch)) 1.753 + mState |= NS_FRAME_IS_BIDI; 1.754 + } 1.755 + 1.756 + // look at the next two characters 1.757 + leftPos++; 1.758 + rightPos--; 1.759 + } 1.760 + 1.761 + mCroppedTitle = leftString + kEllipsis + rightString; 1.762 + } 1.763 + break; 1.764 + } 1.765 + 1.766 + return nsLayoutUtils::GetStringWidth(this, &aRenderingContext, 1.767 + mCroppedTitle.get(), mCroppedTitle.Length()); 1.768 +} 1.769 + 1.770 +#define OLD_ELLIPSIS NS_LITERAL_STRING("...") 1.771 + 1.772 +// the following block is to append the accesskey to mTitle if there is an accesskey 1.773 +// but the mTitle doesn't have the character 1.774 +void 1.775 +nsTextBoxFrame::UpdateAccessTitle() 1.776 +{ 1.777 + /* 1.778 + * Note that if you change appending access key label spec, 1.779 + * you need to maintain same logic in following methods. See bug 324159. 1.780 + * toolkit/content/commonDialog.js (setLabelForNode) 1.781 + * toolkit/content/widgets/text.xml (formatAccessKey) 1.782 + */ 1.783 + int32_t menuAccessKey; 1.784 + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); 1.785 + if (!menuAccessKey || mAccessKey.IsEmpty()) 1.786 + return; 1.787 + 1.788 + if (!AlwaysAppendAccessKey() && 1.789 + FindInReadable(mAccessKey, mTitle, nsCaseInsensitiveStringComparator())) 1.790 + return; 1.791 + 1.792 + nsAutoString accessKeyLabel; 1.793 + accessKeyLabel += '('; 1.794 + accessKeyLabel += mAccessKey; 1.795 + ToUpperCase(accessKeyLabel); 1.796 + accessKeyLabel += ')'; 1.797 + 1.798 + if (mTitle.IsEmpty()) { 1.799 + mTitle = accessKeyLabel; 1.800 + return; 1.801 + } 1.802 + 1.803 + const nsDependentString& kEllipsis = nsContentUtils::GetLocalizedEllipsis(); 1.804 + uint32_t offset = mTitle.Length(); 1.805 + if (StringEndsWith(mTitle, kEllipsis)) { 1.806 + offset -= kEllipsis.Length(); 1.807 + } else if (StringEndsWith(mTitle, OLD_ELLIPSIS)) { 1.808 + // Try to check with our old ellipsis (for old addons) 1.809 + offset -= OLD_ELLIPSIS.Length(); 1.810 + } else { 1.811 + // Try to check with 1.812 + // our default ellipsis (for non-localized addons) or ':' 1.813 + const char16_t kLastChar = mTitle.Last(); 1.814 + if (kLastChar == char16_t(0x2026) || kLastChar == char16_t(':')) 1.815 + offset--; 1.816 + } 1.817 + 1.818 + if (InsertSeparatorBeforeAccessKey() && 1.819 + offset > 0 && !NS_IS_SPACE(mTitle[offset - 1])) { 1.820 + mTitle.Insert(' ', offset); 1.821 + offset++; 1.822 + } 1.823 + 1.824 + mTitle.Insert(accessKeyLabel, offset); 1.825 +} 1.826 + 1.827 +void 1.828 +nsTextBoxFrame::UpdateAccessIndex() 1.829 +{ 1.830 + int32_t menuAccessKey; 1.831 + nsMenuBarListener::GetMenuAccessKey(&menuAccessKey); 1.832 + if (menuAccessKey) { 1.833 + if (mAccessKey.IsEmpty()) { 1.834 + if (mAccessKeyInfo) { 1.835 + delete mAccessKeyInfo; 1.836 + mAccessKeyInfo = nullptr; 1.837 + } 1.838 + } else { 1.839 + if (!mAccessKeyInfo) { 1.840 + mAccessKeyInfo = new nsAccessKeyInfo(); 1.841 + if (!mAccessKeyInfo) 1.842 + return; 1.843 + } 1.844 + 1.845 + nsAString::const_iterator start, end; 1.846 + 1.847 + mCroppedTitle.BeginReading(start); 1.848 + mCroppedTitle.EndReading(end); 1.849 + 1.850 + // remember the beginning of the string 1.851 + nsAString::const_iterator originalStart = start; 1.852 + 1.853 + bool found; 1.854 + if (!AlwaysAppendAccessKey()) { 1.855 + // not appending access key - do case-sensitive search 1.856 + // first 1.857 + found = FindInReadable(mAccessKey, start, end); 1.858 + if (!found) { 1.859 + // didn't find it - perform a case-insensitive search 1.860 + start = originalStart; 1.861 + found = FindInReadable(mAccessKey, start, end, 1.862 + nsCaseInsensitiveStringComparator()); 1.863 + } 1.864 + } else { 1.865 + found = RFindInReadable(mAccessKey, start, end, 1.866 + nsCaseInsensitiveStringComparator()); 1.867 + } 1.868 + 1.869 + if (found) 1.870 + mAccessKeyInfo->mAccesskeyIndex = Distance(originalStart, start); 1.871 + else 1.872 + mAccessKeyInfo->mAccesskeyIndex = kNotFound; 1.873 + } 1.874 + } 1.875 +} 1.876 + 1.877 +NS_IMETHODIMP 1.878 +nsTextBoxFrame::DoLayout(nsBoxLayoutState& aBoxLayoutState) 1.879 +{ 1.880 + if (mNeedsReflowCallback) { 1.881 + nsIReflowCallback* cb = new nsAsyncAccesskeyUpdate(this); 1.882 + if (cb) { 1.883 + PresContext()->PresShell()->PostReflowCallback(cb); 1.884 + } 1.885 + mNeedsReflowCallback = false; 1.886 + } 1.887 + 1.888 + nsresult rv = nsLeafBoxFrame::DoLayout(aBoxLayoutState); 1.889 + 1.890 + CalcDrawRect(*aBoxLayoutState.GetRenderingContext()); 1.891 + 1.892 + const nsStyleText* textStyle = StyleText(); 1.893 + 1.894 + nsRect scrollBounds(nsPoint(0, 0), GetSize()); 1.895 + nsRect textRect = mTextDrawRect; 1.896 + 1.897 + nsRefPtr<nsFontMetrics> fontMet; 1.898 + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); 1.899 + nsBoundingMetrics metrics = 1.900 + fontMet->GetInkBoundsForVisualOverflow(mCroppedTitle.get(), 1.901 + mCroppedTitle.Length(), 1.902 + aBoxLayoutState.GetRenderingContext()); 1.903 + 1.904 + textRect.x -= metrics.leftBearing; 1.905 + textRect.width = metrics.width; 1.906 + // In DrawText() we always draw with the baseline at MaxAscent() (relative to mTextDrawRect), 1.907 + textRect.y += fontMet->MaxAscent() - metrics.ascent; 1.908 + textRect.height = metrics.ascent + metrics.descent; 1.909 + 1.910 + // Our scrollable overflow is our bounds; our visual overflow may 1.911 + // extend beyond that. 1.912 + nsRect visualBounds; 1.913 + visualBounds.UnionRect(scrollBounds, textRect); 1.914 + nsOverflowAreas overflow(visualBounds, scrollBounds); 1.915 + 1.916 + if (textStyle->mTextShadow) { 1.917 + // text-shadow extends our visual but not scrollable bounds 1.918 + nsRect &vis = overflow.VisualOverflow(); 1.919 + vis.UnionRect(vis, nsLayoutUtils::GetTextShadowRectsUnion(mTextDrawRect, this)); 1.920 + } 1.921 + FinishAndStoreOverflow(overflow, GetSize()); 1.922 + 1.923 + return rv; 1.924 +} 1.925 + 1.926 +nsRect 1.927 +nsTextBoxFrame::GetComponentAlphaBounds() 1.928 +{ 1.929 + if (StyleText()->mTextShadow) { 1.930 + return GetVisualOverflowRectRelativeToSelf(); 1.931 + } 1.932 + return mTextDrawRect; 1.933 +} 1.934 + 1.935 +bool 1.936 +nsTextBoxFrame::ComputesOwnOverflowArea() 1.937 +{ 1.938 + return true; 1.939 +} 1.940 + 1.941 +/* virtual */ void 1.942 +nsTextBoxFrame::MarkIntrinsicWidthsDirty() 1.943 +{ 1.944 + mNeedsRecalc = true; 1.945 + nsTextBoxFrameSuper::MarkIntrinsicWidthsDirty(); 1.946 +} 1.947 + 1.948 +void 1.949 +nsTextBoxFrame::GetTextSize(nsPresContext* aPresContext, 1.950 + nsRenderingContext& aRenderingContext, 1.951 + const nsString& aString, 1.952 + nsSize& aSize, nscoord& aAscent) 1.953 +{ 1.954 + nsRefPtr<nsFontMetrics> fontMet; 1.955 + nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); 1.956 + aSize.height = fontMet->MaxHeight(); 1.957 + aRenderingContext.SetFont(fontMet); 1.958 + aSize.width = 1.959 + nsLayoutUtils::GetStringWidth(this, &aRenderingContext, 1.960 + aString.get(), aString.Length()); 1.961 + aAscent = fontMet->MaxAscent(); 1.962 +} 1.963 + 1.964 +void 1.965 +nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState) 1.966 +{ 1.967 + if (mNeedsRecalc) 1.968 + { 1.969 + nsSize size; 1.970 + nsPresContext* presContext = aBoxLayoutState.PresContext(); 1.971 + nsRenderingContext* rendContext = aBoxLayoutState.GetRenderingContext(); 1.972 + if (rendContext) { 1.973 + GetTextSize(presContext, *rendContext, 1.974 + mTitle, size, mAscent); 1.975 + mTextSize = size; 1.976 + mNeedsRecalc = false; 1.977 + } 1.978 + } 1.979 +} 1.980 + 1.981 +void 1.982 +nsTextBoxFrame::CalcDrawRect(nsRenderingContext &aRenderingContext) 1.983 +{ 1.984 + nsRect textRect(nsPoint(0, 0), GetSize()); 1.985 + nsMargin borderPadding; 1.986 + GetBorderAndPadding(borderPadding); 1.987 + textRect.Deflate(borderPadding); 1.988 + 1.989 + // determine (cropped) title and underline position 1.990 + nsPresContext* presContext = PresContext(); 1.991 + // determine (cropped) title which fits in aRect.width and its width 1.992 + nscoord titleWidth = 1.993 + CalculateTitleForWidth(presContext, aRenderingContext, textRect.width); 1.994 + 1.995 +#ifdef ACCESSIBILITY 1.996 + // Make sure to update the accessible tree in case when cropped title is 1.997 + // changed. 1.998 + nsAccessibilityService* accService = GetAccService(); 1.999 + if (accService) { 1.1000 + accService->UpdateLabelValue(PresContext()->PresShell(), mContent, 1.1001 + mCroppedTitle); 1.1002 + } 1.1003 +#endif 1.1004 + 1.1005 + // determine if and at which position to put the underline 1.1006 + UpdateAccessIndex(); 1.1007 + 1.1008 + // make the rect as small as our (cropped) text. 1.1009 + nscoord outerWidth = textRect.width; 1.1010 + textRect.width = titleWidth; 1.1011 + 1.1012 + // Align our text within the overall rect by checking our text-align property. 1.1013 + const nsStyleVisibility* vis = StyleVisibility(); 1.1014 + const nsStyleText* textStyle = StyleText(); 1.1015 + 1.1016 + if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_CENTER) 1.1017 + textRect.x += (outerWidth - textRect.width)/2; 1.1018 + else if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_RIGHT || 1.1019 + (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_DEFAULT && 1.1020 + vis->mDirection == NS_STYLE_DIRECTION_RTL) || 1.1021 + (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_END && 1.1022 + vis->mDirection == NS_STYLE_DIRECTION_LTR)) { 1.1023 + textRect.x += (outerWidth - textRect.width); 1.1024 + } 1.1025 + 1.1026 + mTextDrawRect = textRect; 1.1027 +} 1.1028 + 1.1029 +/** 1.1030 + * Ok return our dimensions 1.1031 + */ 1.1032 +nsSize 1.1033 +nsTextBoxFrame::GetPrefSize(nsBoxLayoutState& aBoxLayoutState) 1.1034 +{ 1.1035 + CalcTextSize(aBoxLayoutState); 1.1036 + 1.1037 + nsSize size = mTextSize; 1.1038 + DISPLAY_PREF_SIZE(this, size); 1.1039 + 1.1040 + AddBorderAndPadding(size); 1.1041 + bool widthSet, heightSet; 1.1042 + nsIFrame::AddCSSPrefSize(this, size, widthSet, heightSet); 1.1043 + 1.1044 + return size; 1.1045 +} 1.1046 + 1.1047 +/** 1.1048 + * Ok return our dimensions 1.1049 + */ 1.1050 +nsSize 1.1051 +nsTextBoxFrame::GetMinSize(nsBoxLayoutState& aBoxLayoutState) 1.1052 +{ 1.1053 + CalcTextSize(aBoxLayoutState); 1.1054 + 1.1055 + nsSize size = mTextSize; 1.1056 + DISPLAY_MIN_SIZE(this, size); 1.1057 + 1.1058 + // if there is cropping our min width becomes our border and padding 1.1059 + if (mCropType != CropNone) 1.1060 + size.width = 0; 1.1061 + 1.1062 + AddBorderAndPadding(size); 1.1063 + bool widthSet, heightSet; 1.1064 + nsIFrame::AddCSSMinSize(aBoxLayoutState, this, size, widthSet, heightSet); 1.1065 + 1.1066 + return size; 1.1067 +} 1.1068 + 1.1069 +nscoord 1.1070 +nsTextBoxFrame::GetBoxAscent(nsBoxLayoutState& aBoxLayoutState) 1.1071 +{ 1.1072 + CalcTextSize(aBoxLayoutState); 1.1073 + 1.1074 + nscoord ascent = mAscent; 1.1075 + 1.1076 + nsMargin m(0,0,0,0); 1.1077 + GetBorderAndPadding(m); 1.1078 + ascent += m.top; 1.1079 + 1.1080 + return ascent; 1.1081 +} 1.1082 + 1.1083 +#ifdef DEBUG_FRAME_DUMP 1.1084 +nsresult 1.1085 +nsTextBoxFrame::GetFrameName(nsAString& aResult) const 1.1086 +{ 1.1087 + MakeFrameName(NS_LITERAL_STRING("TextBox"), aResult); 1.1088 + aResult += NS_LITERAL_STRING("[value=") + mTitle + NS_LITERAL_STRING("]"); 1.1089 + return NS_OK; 1.1090 +} 1.1091 +#endif 1.1092 + 1.1093 +// If you make changes to this function, check its counterparts 1.1094 +// in nsBoxFrame and nsXULLabelFrame 1.1095 +nsresult 1.1096 +nsTextBoxFrame::RegUnregAccessKey(bool aDoReg) 1.1097 +{ 1.1098 + // if we have no content, we can't do anything 1.1099 + if (!mContent) 1.1100 + return NS_ERROR_FAILURE; 1.1101 + 1.1102 + // check if we have a |control| attribute 1.1103 + // do this check first because few elements have control attributes, and we 1.1104 + // can weed out most of the elements quickly. 1.1105 + 1.1106 + // XXXjag a side-effect is that we filter out anonymous <label>s 1.1107 + // in e.g. <menu>, <menuitem>, <button>. These <label>s inherit 1.1108 + // |accesskey| and would otherwise register themselves, overwriting 1.1109 + // the content we really meant to be registered. 1.1110 + if (!mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::control)) 1.1111 + return NS_OK; 1.1112 + 1.1113 + // see if we even have an access key 1.1114 + nsAutoString accessKey; 1.1115 + mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey); 1.1116 + 1.1117 + if (accessKey.IsEmpty()) 1.1118 + return NS_OK; 1.1119 + 1.1120 + // With a valid PresContext we can get the ESM 1.1121 + // and (un)register the access key 1.1122 + EventStateManager* esm = PresContext()->EventStateManager(); 1.1123 + 1.1124 + uint32_t key = accessKey.First(); 1.1125 + if (aDoReg) 1.1126 + esm->RegisterAccessKey(mContent, key); 1.1127 + else 1.1128 + esm->UnregisterAccessKey(mContent, key); 1.1129 + 1.1130 + return NS_OK; 1.1131 +}