lineLayout.SetColumn(column);
lineLayout.SetColumn(textData.mColumn);
nsTextFrame::Reflow(nsIPresContext* aPresContext,                    nsHTMLReflowMetrics& aMetrics,                    const nsHTMLReflowState& aReflowState,                    nsReflowStatus& aStatus){#ifdef NOISY_REFLOW  ListTag(stdout);  printf(": BeginReflow: availableSize=%d,%d\n",         aReflowState.availableWidth, aReflowState.availableHeight);#endif  // XXX If there's no line layout, we shouldn't even have created this  // frame. This may happen if, for example, this is text inside a table  // but not inside a cell. For now, just don't reflow.  if (nsnull == aReflowState.mLineLayout) {    // XXX Add a method to aMetrics that does this; we do it several places    aMetrics.width = 0;    aMetrics.height = 0;    aMetrics.ascent = 0;    aMetrics.descent = 0;    if (nsnull != aMetrics.maxElementSize) {      aMetrics.maxElementSize->width = 0;      aMetrics.maxElementSize->height = 0;    }#ifdef MOZ_MATHML    if (NS_REFLOW_CALC_BOUNDING_METRICS & aMetrics.mFlags)      aMetrics.mBoundingMetrics.Clear();#endif    return NS_OK;  }  // Get starting offset into the content  PRInt32 startingOffset = 0;  nsIFrame* prevInFlow;  GetPrevInFlow(&prevInFlow);  if (nsnull != prevInFlow) {    nsTextFrame* prev = (nsTextFrame*)prevInFlow;    startingOffset = prev->mContentOffset + prev->mContentLength;    // If our starting offset doesn't agree with mContentOffset, then our    // prev-in-flow has changed the number of characters it maps and so we    // need to measure text and not try and optimize a resize reflow    if (startingOffset != mContentOffset) {      mState &= ~TEXT_OPTIMIZE_RESIZE;    }  }  nsLineLayout& lineLayout = *aReflowState.mLineLayout;  TextStyle ts(aPresContext, *aReflowState.rendContext, mStyleContext);  // Clear out the reflow state flags in mState (without destroying  // the TEXT_BLINK_ON bit).  PRBool lastTimeWeSkippedLeadingWS = 0 != (mState & TEXT_SKIP_LEADING_WS);  mState &= ~TEXT_REFLOW_FLAGS;  if (ts.mFont->mFont.decorations & NS_STYLE_TEXT_DECORATION_BLINK) {    if (0 == (mState & TEXT_BLINK_ON)) {      mState |= TEXT_BLINK_ON;      gTextBlinker->AddFrame(aPresContext, this);    }  }  else {    if (0 != (mState & TEXT_BLINK_ON)) {      mState &= ~TEXT_BLINK_ON;      gTextBlinker->RemoveFrame(this);    }  }  PRBool wrapping = (NS_STYLE_WHITESPACE_NORMAL == ts.mText->mWhiteSpace) ||    (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == ts.mText->mWhiteSpace);  // Set whitespace skip flag  PRBool skipWhitespace = PR_FALSE;  if (!ts.mPreformatted) {    if (lineLayout.GetEndsInWhiteSpace()) {      skipWhitespace = PR_TRUE;    }  }  nscoord maxWidth = aReflowState.availableWidth;  // Setup text transformer to transform this frames text content  nsCOMPtr<nsIDocument> doc;  mContent->GetDocument(*getter_AddRefs(doc));  if (NS_WARN_IF_FALSE(doc, "Content has no document.")) {     return NS_ERROR_FAILURE;   }  nsCOMPtr<nsILineBreaker> lb;  doc->GetLineBreaker(getter_AddRefs(lb));  nsTextTransformer tx(lb, nsnull);  nsresult rv = tx.Init(this, mContent, startingOffset);  if (NS_OK != rv) {    return rv;  }  PRInt32 contentLength = tx.GetContentLength();  // Loop over words and whitespace in content and measure. Set inWord  // to true if we are part of a previous piece of text's word. This  // is only valid for one pass through the measuring loop.  PRBool inWord = lineLayout.InWord() || ((nsnull != prevInFlow) && (((nsTextFrame*)prevInFlow)->mState & TEXT_FIRST_LETTER));  if (inWord) {    mState |= TEXT_IN_WORD;  }  mState &= ~TEXT_FIRST_LETTER;    PRInt32 column = lineLayout.GetColumn();  PRInt32 prevColumn = mColumn;  mColumn = column;  PRBool measureText = PR_TRUE;    // We can avoid actually measuring the text if:  // - this is a resize reflow  // - we're not dirty (see ContentChanged() function)  // - we don't have a next in flow  // - the previous reflow successfully reflowed all text in the  //   available space  // - we aren't computing the max element size (that requires we measure  //   text)  // - skipping leading whitespace is the same as it was the last time  // - we're wrapping text and the available width is at least as big as our  //   current frame width -or-  //   we're not wrapping text and we're at the same column as before (this is  //   an issue for preformatted tabbed text only)  if ((eReflowReason_Resize == aReflowState.reason) &&      (0 == (mState & NS_FRAME_IS_DIRTY))) {    nscoord realWidth = mRect.width;    if (mState & TEXT_TRIMMED_WS) {      realWidth += ts.mSpaceWidth;    }    if (!mNextInFlow &&        (mState & TEXT_OPTIMIZE_RESIZE) &&        !aMetrics.maxElementSize &&        (lastTimeWeSkippedLeadingWS == skipWhitespace) &&        ((wrapping && (maxWidth >= realWidth)) ||         (!wrapping && (prevColumn == column)))) {      // We can skip measuring of text and use the value from our      // previous reflow      measureText = PR_FALSE;#ifdef NOISY_REFLOW      printf("  => measureText=%s wrapping=%s skipWhitespace=%s",             measureText ? "yes" : "no",             wrapping ? "yes" : "no",             skipWhitespace ? "yes" : "no");      printf(" realWidth=%d maxWidth=%d\n",             realWidth, maxWidth);#endif    }  }  // Local state passed to the routines that do the actual text measurement  TextReflowData  textData(startingOffset, column, wrapping, skipWhitespace,                            measureText, inWord, lineLayout.GetFirstLetterStyleOK(),                           lineLayout.LineIsBreakable());    // Measure the inidvidual words  MeasureIndividualWords(aPresContext, aReflowState, tx, ts, textData);  if (tx.HasMultibyte()) {    mState |= TEXT_HAS_MULTIBYTE;  }  // If we didn't actually measure any text, then make sure it looks  // like we did  if (!measureText) {    textData.mX = mRect.width;    if (mState & TEXT_TRIMMED_WS) {      // Add back in the width of a space since it was trimmed away last time      textData.mX += ts.mSpaceWidth;    }  }  mState &= ~TEXT_TRIMMED_WS;  // Post processing logic to deal with word-breaking that spans  // multiple frames.  if (lineLayout.InWord()) {    // We are already in a word. This means a text frame prior to this    // one had a fragment of a nbword that is joined with this    // frame. It also means that the prior frame already found this    // frame and recorded it as part of the word.#ifdef DEBUG_WORD_WRAPPING    ListTag(stdout);    printf(": in word; skipping\n");#endif    lineLayout.ForgetWordFrame(this);  }  if (!lineLayout.InWord()) {    // There is no currently active word. This frame may contain the    // start of one.    if (textData.mEndsInWhitespace) {      // Nope, this frame doesn't start a word.      lineLayout.ForgetWordFrames();    }    else if ((textData.mOffset == contentLength) && (textData.mPrevOffset >= 0)) {      // Force breakable to false when we aren't wrapping (this      // guarantees that the combined word will stay together)      if (!wrapping) {        textData.mIsBreakable = PR_FALSE;      }      // This frame does start a word. However, there is no point      // messing around with it if we are already out of room. We      // always have room if we are not breakable.      if (!textData.mIsBreakable || (textData.mX <= maxWidth)) {        // There is room for this word fragment. It's possible that        // this word fragment is the end of the text-run. If it's not        // then we continue with the look-ahead processing.        nsIFrame* next = lineLayout.FindNextText(this);        if (nsnull != next) {#ifdef DEBUG_WORD_WRAPPING          nsAutoString tmp(tx.GetWordBuffer(), lastWordLen);          ListTag(stdout);          printf(": start='");          fputs(tmp, stdout);          printf("' lastWordLen=%d baseWidth=%d prevOffset=%d offset=%d next=",                 lastWordLen, lastWordWidth, prevOffset, offset);          ListTag(stdout, next);          printf("\n");#endif          PRUnichar* pWordBuf = tx.GetWordBuffer();          PRUint32   wordBufLen = tx.GetWordBufferLength();          // Look ahead in the text-run and compute the final word          // width, taking into account any style changes and stopping          // at the first breakable point.          if (!measureText) {            // We didn't measure any text so we don't know lastWordWidth.            // We have to compute it now            if (textData.mPrevOffset == startingOffset) {              // There's only one word, so we don't have to measure after all              textData.mLastWordWidth = textData.mX;            }            else if (ts.mSmallCaps) {              MeasureSmallCapsText(aReflowState, ts, tx.GetWordBuffer(),                                   textData.mLastWordLen, &textData.mLastWordWidth);            }            else {              aReflowState.rendContext->GetWidth(tx.GetWordBuffer(),                                                 textData.mLastWordLen, textData.mLastWordWidth);              if (ts.mLetterSpacing) {                textData.mLastWordWidth += ts.mLetterSpacing * textData.mLastWordLen;              }            }          }          nscoord wordWidth = ComputeTotalWordWidth(aPresContext, lb,                                                    lineLayout,                                                    aReflowState, next,                                                    textData.mLastWordWidth,                                                    pWordBuf,                                                    textData.mLastWordLen,                                                    wordBufLen);          if (!textData.mIsBreakable || (textData.mX - textData.mLastWordWidth + wordWidth <= maxWidth)) {            // The fully joined word has fit. Account for the joined            // word's affect on the max-element-size here (since the            // joined word is large than it's pieces, the right effect            // will occur from the perspective of the container            // reflowing this frame)            if (wordWidth > textData.mMaxWordWidth) {              textData.mMaxWordWidth = wordWidth;            }          }          else {#ifdef NOISY_REFLOW            ListTag(stdout);            printf(": look-ahead (didn't fit) x=%d wordWidth=%d lastWordWidth=%d\n",                   x, wordWidth, lastWordWidth);#endif            // The fully joined word won't fit. We need to reduce our            // size by the lastWordWidth.            textData.mX -= textData.mLastWordWidth;            textData.mMaxWordWidth = textData.mPrevMaxWordWidth;            textData.mOffset = textData.mPrevOffset;            textData.mColumn = textData.mPrevColumn;#ifdef DEBUG_WORD_WRAPPING            printf("  x=%d maxWordWidth=%d len=%d\n", textData.mX, textData.mMaxWordWidth,                   textData.mOffset - startingOffset);#endif            lineLayout.ForgetWordFrames();          }        }      }    }  }  lineLayout.SetColumn(column);  // Inform line layout of how this piece of text ends in whitespace  // (only text objects do this). Note that if x is zero then this  // text object collapsed into nothingness which means it shouldn't  // effect the current setting of the ends-in-whitespace flag.  lineLayout.SetUnderstandsWhiteSpace(PR_TRUE);  lineLayout.SetTextStartsWithNBSP(textData.mTextStartsWithNBSP);  if (0 != textData.mX) {    lineLayout.SetEndsInWhiteSpace(textData.mEndsInWhitespace);  }  if (textData.mJustDidFirstLetter) {    lineLayout.SetFirstLetterFrame(this);    lineLayout.SetFirstLetterStyleOK(PR_FALSE);    mState |= TEXT_FIRST_LETTER;  }  // Setup metrics for caller; store final max-element-size information  aMetrics.width = textData.mX;  if ((0 == textData.mX) && !ts.mPreformatted) {    aMetrics.height = 0;    aMetrics.ascent = 0;    aMetrics.descent = 0;  }  else {    ts.mNormalFont->GetHeight(aMetrics.height);    ts.mNormalFont->GetMaxAscent(aMetrics.ascent);    ts.mNormalFont->GetMaxDescent(aMetrics.descent);  }  if (!wrapping) {    textData.mMaxWordWidth = textData.mX;  }  if (nsnull != aMetrics.maxElementSize) {    aMetrics.maxElementSize->width = textData.mMaxWordWidth;    aMetrics.maxElementSize->height = aMetrics.height;  }  // Set content offset and length  mContentOffset = startingOffset;  mContentLength = textData.mOffset - startingOffset;#ifdef MOZ_MATHML  // Simple minded code to also return the bounding metrics if the caller wants it...  // More consolidation is needed -- a better approach is to follow what is done by  // the other routines that are doing measurements.  if (NS_REFLOW_CALC_BOUNDING_METRICS & aMetrics.mFlags) {    rv = NS_ERROR_UNEXPECTED; // initialize with an error; it is reset if things turn out well    aMetrics.mBoundingMetrics.Clear();    // Get the text to measure.     nsCOMPtr<nsIDOMText> domText(do_QueryInterface(mContent));    if (domText.get()) {      nsAutoString aData;      domText->GetData(aData);      // Extract the piece of text relevant to us -- XXX whitespace cause a mess here        nsAutoString aText;      aData.Mid(aText, mContentOffset, mContentLength);      // Set the font      nsStyleFont font;      mStyleContext->GetStyle(eStyleStruct_Font, font);      aReflowState.rendContext->SetFont(font.mFont);      // Now get the exact bounding metrics of the text      nsBoundingMetrics bm;      rv = aReflowState.rendContext->GetBoundingMetrics(aText.GetUnicode(), PRUint32(mContentLength), bm);      if (NS_SUCCEEDED(rv)) aMetrics.mBoundingMetrics = bm;    }    if (NS_FAILED(rv)) {       // Things didn't turn out well, just return the reflow metrics.      aMetrics.mBoundingMetrics.ascent  = aMetrics.ascent;      aMetrics.mBoundingMetrics.descent = aMetrics.descent;      aMetrics.mBoundingMetrics.width   = aMetrics.width;#ifdef MOZ_MATHML_BOUNDINGMETRICS      printf("nsTextFrame: could not perform GetBoundingMetrics()\n");#endif    }  }#endif  // If it's an incremental reflow command, then invalidate our existing  // bounds.  // XXX We need a finer granularity than this, but it isn't clear what  // has actually changed...  if (eReflowReason_Incremental == aReflowState.reason ||      eReflowReason_Dirty == aReflowState.reason) {    Invalidate(aPresContext, mRect);  }  nsReflowStatus rs = (textData.mOffset == contentLength)    ? NS_FRAME_COMPLETE    : NS_FRAME_NOT_COMPLETE;  if (textData.mEndsInNewline) {    rs = NS_INLINE_LINE_BREAK_AFTER(rs);  }  else if ((textData.mOffset != contentLength) && (textData.mOffset == startingOffset)) {    // Break-before a long-word that doesn't fit here    rs = NS_INLINE_LINE_BREAK_BEFORE();  }  aStatus = rs;  // For future resize reflows we would like to avoid measuring the text.  // We can only do this if after this reflow we're:  // - complete. If we're not complete then our desired width doesn't  //   represent our total size  // - we fit in the available space. We may be complete, but if we  //   return a larger desired width than is available we may get pushed  //   and our frame width won't get set  if ((NS_FRAME_COMPLETE == aStatus) && (aMetrics.width <= maxWidth)) {    mState |= TEXT_OPTIMIZE_RESIZE;    mRect.width = aMetrics.width;  }  else {    mState &= ~TEXT_OPTIMIZE_RESIZE;  }#ifdef NOISY_REFLOW  ListTag(stdout);  printf(": desiredSize=%d,%d(a=%d/d=%d) status=%x\n",         aMetrics.width, aMetrics.height, aMetrics.ascent, aMetrics.descent,         aStatus);#endif  return NS_OK;}