NS_IMETHODIMP nsPlaceholderFrame::List(FILE* out, int32_t aIndent, uint32_t aFlags) const { IndentBy(out, aIndent); ListTag(out); if (HasView()) { fprintf(out, " [view=%p]", (void*)GetView()); } fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height); if (0 != mState) { fprintf(out, " [state=%016llx]", (unsigned long long)mState); } nsIFrame* prevInFlow = GetPrevInFlow(); nsIFrame* nextInFlow = GetNextInFlow(); if (prevInFlow) { fprintf(out, " prev-in-flow=%p", static_cast<void*>(prevInFlow)); } if (nextInFlow) { fprintf(out, " next-in-flow=%p", static_cast<void*>(nextInFlow)); } if (mContent) { fprintf(out, " [content=%p]", static_cast<void*>(mContent)); } if (mStyleContext) { fprintf(out, " [sc=%p]", static_cast<void*>(mStyleContext)); } if (mOutOfFlowFrame) { fprintf(out, " outOfFlowFrame="); nsFrame::ListTag(out, mOutOfFlowFrame); } fputs("\n", out); return NS_OK; }
NS_IMETHODIMP nsPlaceholderFrame::List(FILE* out, PRInt32 aIndent) const { IndentBy(out, aIndent); ListTag(out); #ifdef DEBUG_waterson fprintf(out, " [parent=%p]", static_cast<void*>(mParent)); #endif if (HasView()) { fprintf(out, " [view=%p]", (void*)GetView()); } fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height); if (0 != mState) { fprintf(out, " [state=%08x]", mState); } nsIFrame* prevInFlow = GetPrevInFlow(); nsIFrame* nextInFlow = GetNextInFlow(); if (nsnull != prevInFlow) { fprintf(out, " prev-in-flow=%p", static_cast<void*>(prevInFlow)); } if (nsnull != nextInFlow) { fprintf(out, " next-in-flow=%p", static_cast<void*>(nextInFlow)); } if (mOutOfFlowFrame) { fprintf(out, " outOfFlowFrame="); nsFrame::ListTag(out, mOutOfFlowFrame); } fputs("\n", out); return NS_OK; }
void nsPopupSetFrame::List(FILE* out, int32_t aIndent, uint32_t aFlags) const { ListGeneric(out, aIndent, aFlags); // Output the children bool outputOneList = false; ChildListIterator lists(this); for (; !lists.IsDone(); lists.Next()) { if (outputOneList) { IndentBy(out, aIndent); } outputOneList = true; fprintf(out, "%s<\n", mozilla::layout::ChildListName(lists.CurrentID())); nsFrameList::Enumerator childFrames(lists.CurrentList()); for (; !childFrames.AtEnd(); childFrames.Next()) { nsIFrame* kid = childFrames.get(); // Verify the child frame's parent frame pointer is correct NS_ASSERTION(kid->GetParent() == this, "bad parent frame pointer"); // Have the child frame list kid->List(out, aIndent + 1, aFlags); } IndentBy(out, aIndent); fputs(">\n", out); } // XXXmats the above is copy-pasted from nsContainerFrame::List which is lame, // clean this up after bug 399111 is implemented. if (!mPopupList.IsEmpty()) { fputs("<\n", out); ++aIndent; IndentBy(out, aIndent); fputs(mozilla::layout::ChildListName(kPopupList), out); fputs(" for ", out); ListTag(out); fputs(" <\n", out); ++aIndent; for (nsFrameList::Enumerator e(mPopupList); !e.AtEnd(); e.Next()) { e.get()->List(out, aIndent, aFlags); } --aIndent; IndentBy(out, aIndent); fputs(">\n", out); --aIndent; IndentBy(out, aIndent); fputs(">\n", out); outputOneList = true; } if (!outputOneList) { fputs("<>\n", out); } }
NS_IMETHODIMP nsPlaceholderFrame::List(nsPresContext* aPresContext, FILE* out, PRInt32 aIndent) const { IndentBy(out, aIndent); ListTag(out); #ifdef DEBUG_waterson fprintf(out, " [parent=%p]", NS_STATIC_CAST(void*, mParent)); #endif if (HasView()) { fprintf(out, " [view=%p]", (void*)GetView()); } fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height); if (0 != mState) { fprintf(out, " [state=%08x]", mState); } nsIFrame* prevInFlow = GetPrevInFlow(); nsIFrame* nextInFlow = GetNextInFlow(); if (nsnull != prevInFlow) { fprintf(out, " prev-in-flow=%p", NS_STATIC_CAST(void*, prevInFlow)); }
NS_IMETHODIMP nsPopupSetFrame::List(FILE* out, PRInt32 aIndent) const { IndentBy(out, aIndent); ListTag(out); #ifdef DEBUG_waterson fprintf(out, " [parent=%p]", static_cast<void*>(mParent)); #endif if (HasView()) { fprintf(out, " [view=%p]", static_cast<void*>(GetView())); } if (nsnull != mNextSibling) { fprintf(out, " next=%p", static_cast<void*>(mNextSibling)); } if (nsnull != GetPrevContinuation()) { fprintf(out, " prev-continuation=%p", static_cast<void*>(GetPrevContinuation())); } if (nsnull != GetNextContinuation()) { fprintf(out, " next-continuation=%p", static_cast<void*>(GetNextContinuation())); } fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height); if (0 != mState) { fprintf(out, " [state=%08x]", mState); } fprintf(out, " [content=%p]", static_cast<void*>(mContent)); nsPopupSetFrame* f = const_cast<nsPopupSetFrame*>(this); if (f->HasOverflowRect()) { nsRect overflowArea = f->GetOverflowRect(); fprintf(out, " [overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y, overflowArea.width, overflowArea.height); } fprintf(out, " [sc=%p]", static_cast<void*>(mStyleContext)); nsIAtom* pseudoTag = mStyleContext->GetPseudoType(); if (pseudoTag) { nsAutoString atomString; pseudoTag->ToString(atomString); fprintf(out, " pst=%s", NS_LossyConvertUTF16toASCII(atomString).get()); } // Output the children nsIAtom* listName = nsnull; PRInt32 listIndex = 0; PRBool outputOneList = PR_FALSE; do { nsIFrame* kid = GetFirstChild(listName); if (nsnull != kid) { if (outputOneList) { IndentBy(out, aIndent); } outputOneList = PR_TRUE; nsAutoString tmp; if (nsnull != listName) { listName->ToString(tmp); fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out); } fputs("<\n", out); while (nsnull != kid) { // Verify the child frame's parent frame pointer is correct NS_ASSERTION(kid->GetParent() == (nsIFrame*)this, "bad parent frame pointer"); // Have the child frame list nsIFrameDebug* frameDebug = do_QueryFrame(kid); if (frameDebug) { frameDebug->List(out, aIndent + 1); } kid = kid->GetNextSibling(); } IndentBy(out, aIndent); fputs(">\n", out); } listName = GetAdditionalChildListName(listIndex++); } while(nsnull != listName); // XXXmats the above is copy-pasted from nsContainerFrame::List which is lame, // clean this up after bug 399111 is implemented. if (mPopupList) { fputs("<\n", out); ++aIndent; IndentBy(out, aIndent); nsAutoString tmp; nsGkAtoms::popupList->ToString(tmp); fputs(NS_LossyConvertUTF16toASCII(tmp).get(), out); fputs(" for ", out); ListTag(out); fputs(" <\n", out); ++aIndent; for (nsPopupFrameList* l = mPopupList; l; l = l->mNextPopup) { nsIFrameDebug* frameDebug = do_QueryFrame(l->mPopupFrame); if (frameDebug) { frameDebug->List(out, aIndent); } } --aIndent; IndentBy(out, aIndent); fputs(">\n", out); --aIndent; IndentBy(out, aIndent); fputs(">\n", out); outputOneList = PR_TRUE; } if (!outputOneList) { fputs("<>\n", out); } return NS_OK; }
nsresult nsInlineFrame::ReflowFrames(nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, InlineReflowState& irs, nsHTMLReflowMetrics& aMetrics, nsReflowStatus& aStatus) { nsresult rv = NS_OK; aStatus = NS_FRAME_COMPLETE; nsLineLayout* lineLayout = aReflowState.mLineLayout; PRBool ltr = (NS_STYLE_DIRECTION_LTR == aReflowState.mStyleVisibility->mDirection); nscoord leftEdge = 0; // Don't offset by our start borderpadding if we have a prev continuation or // if we're in the last part of an {ib} split. if (!GetPrevContinuation() && !nsLayoutUtils::FrameIsInLastPartOfIBSplit(this)) { leftEdge = ltr ? aReflowState.mComputedBorderPadding.left : aReflowState.mComputedBorderPadding.right; } nscoord availableWidth = aReflowState.availableWidth; NS_ASSERTION(availableWidth != NS_UNCONSTRAINEDSIZE, "should no longer use available widths"); // Subtract off left and right border+padding from availableWidth availableWidth -= leftEdge; availableWidth -= ltr ? aReflowState.mComputedBorderPadding.right : aReflowState.mComputedBorderPadding.left; lineLayout->BeginSpan(this, &aReflowState, leftEdge, leftEdge + availableWidth); // First reflow our current children nsIFrame* frame = mFrames.FirstChild(); PRBool done = PR_FALSE; while (nsnull != frame) { PRBool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK(); // Check if we should lazily set the child frame's parent pointer if (irs.mSetParentPointer) { PRBool havePrevBlock = irs.mLineContainer && irs.mLineContainer->GetPrevContinuation(); // If our block is the first in flow, then any floats under the pulled // frame must already belong to our block. if (havePrevBlock) { // This has to happen before we update frame's parent; we need to // know frame's ancestry under its old block. // The blockChildren.ContainsFrame check performed by // ReparentFloatsForInlineChild here may be slow, but we can't // easily avoid it because we don't know where 'frame' originally // came from. If we really really have to optimize this we could // cache whether frame->GetParent() is under its containing blocks // overflowList or not. ReparentFloatsForInlineChild(irs.mLineContainer, frame, PR_FALSE); } frame->SetParent(this); // We also need to check if frame has a next-in-flow. If it does, then set // its parent frame pointer, too. Otherwise, if we reflow frame and it's // complete we'll fail when deleting its next-in-flow which is no longer // needed. This scenario doesn't happen often, but it can happen nsIFrame* nextInFlow = frame->GetNextInFlow(); for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) { // Since we only do lazy setting of parent pointers for the frame's // initial reflow, this frame can't have a next-in-flow. That means // the continuing child frame must be in our child list as well. If // not, then something is wrong NS_ASSERTION(mFrames.ContainsFrame(nextInFlow), "unexpected flow"); if (havePrevBlock) { ReparentFloatsForInlineChild(irs.mLineContainer, nextInFlow, PR_FALSE); } nextInFlow->SetParent(this); } // Fix the parent pointer for ::first-letter child frame next-in-flows, // so nsFirstLetterFrame::Reflow can destroy them safely (bug 401042). nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(frame); if (realFrame->GetType() == nsGkAtoms::letterFrame) { nsIFrame* child = realFrame->GetFirstChild(nsnull); if (child) { NS_ASSERTION(child->GetType() == nsGkAtoms::textFrame, "unexpected frame type"); nsIFrame* nextInFlow = child->GetNextInFlow(); for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) { NS_ASSERTION(nextInFlow->GetType() == nsGkAtoms::textFrame, "unexpected frame type"); if (mFrames.ContainsFrame(nextInFlow)) { nextInFlow->SetParent(this); } else { #ifdef DEBUG // Once we find a next-in-flow that isn't ours none of the // remaining next-in-flows should be either. for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) { NS_ASSERTION(!mFrames.ContainsFrame(nextInFlow), "unexpected letter frame flow"); } #endif break; } } } } } rv = ReflowInlineFrame(aPresContext, aReflowState, irs, frame, aStatus); if (NS_FAILED(rv)) { done = PR_TRUE; break; } if (NS_INLINE_IS_BREAK(aStatus) || (!reflowingFirstLetter && NS_FRAME_IS_NOT_COMPLETE(aStatus))) { done = PR_TRUE; break; } irs.mPrevFrame = frame; frame = frame->GetNextSibling(); } // Attempt to pull frames from our next-in-flow until we can't if (!done && (nsnull != GetNextInFlow())) { while (!done) { PRBool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK(); PRBool isComplete; if (!frame) { // Could be non-null if we pulled a first-letter frame and // it created a continuation, since we don't push those. frame = PullOneFrame(aPresContext, irs, &isComplete); } #ifdef NOISY_PUSHING printf("%p pulled up %p\n", this, frame); #endif if (nsnull == frame) { if (!isComplete) { aStatus = NS_FRAME_NOT_COMPLETE; } break; } rv = ReflowInlineFrame(aPresContext, aReflowState, irs, frame, aStatus); if (NS_FAILED(rv)) { done = PR_TRUE; break; } if (NS_INLINE_IS_BREAK(aStatus) || (!reflowingFirstLetter && NS_FRAME_IS_NOT_COMPLETE(aStatus))) { done = PR_TRUE; break; } irs.mPrevFrame = frame; frame = frame->GetNextSibling(); } } #ifdef DEBUG if (NS_FRAME_IS_COMPLETE(aStatus)) { // We can't be complete AND have overflow frames! NS_ASSERTION(!GetOverflowFrames(), "whoops"); } #endif // If after reflowing our children they take up no area then make // sure that we don't either. // // Note: CSS demands that empty inline elements still affect the // line-height calculations. However, continuations of an inline // that are empty we force to empty so that things like collapsed // whitespace in an inline element don't affect the line-height. aMetrics.width = lineLayout->EndSpan(this); // Compute final width. // Make sure to not include our start border and padding if we have a prev // continuation or if we're in the last part of an {ib} split. if (!GetPrevContinuation() && !nsLayoutUtils::FrameIsInLastPartOfIBSplit(this)) { aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.left : aReflowState.mComputedBorderPadding.right; } /* * We want to only apply the end border and padding if we're the last * continuation and not in the first part of an {ib} split. To be the last * continuation we have to be complete (so that we won't get a next-in-flow) * and have no non-fluid continuations on our continuation chain. */ if (NS_FRAME_IS_COMPLETE(aStatus) && !GetLastInFlow()->GetNextContinuation() && !nsLayoutUtils::FrameIsInFirstPartOfIBSplit(this)) { aMetrics.width += ltr ? aReflowState.mComputedBorderPadding.right : aReflowState.mComputedBorderPadding.left; } nsLayoutUtils::SetFontFromStyle(aReflowState.rendContext, mStyleContext); nsCOMPtr<nsIFontMetrics> fm; aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm)); if (fm) { // Compute final height of the frame. // // Do things the standard css2 way -- though it's hard to find it // in the css2 spec! It's actually found in the css1 spec section // 4.4 (you will have to read between the lines to really see // it). // // The height of our box is the sum of our font size plus the top // and bottom border and padding. The height of children do not // affect our height. fm->GetMaxAscent(aMetrics.ascent); fm->GetHeight(aMetrics.height); } else { NS_WARNING("Cannot get font metrics - defaulting sizes to 0"); aMetrics.ascent = aMetrics.height = 0; } aMetrics.ascent += aReflowState.mComputedBorderPadding.top; aMetrics.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom; // For now our overflow area is zero. The real value will be // computed in |nsLineLayout::RelativePositionFrames|. aMetrics.mOverflowArea.SetRect(0, 0, 0, 0); #ifdef NOISY_FINAL_SIZE ListTag(stdout); printf(": metrics=%d,%d ascent=%d\n", aMetrics.width, aMetrics.height, aMetrics.ascent); #endif return rv; }
NS_IMETHODIMP nsPopupSetFrame::List(FILE* out, int32_t aIndent, uint32_t aFlags) const { IndentBy(out, aIndent); ListTag(out); #ifdef DEBUG_waterson fprintf(out, " [parent=%p]", static_cast<void*>(mParent)); #endif if (HasView()) { fprintf(out, " [view=%p]", static_cast<void*>(GetView())); } if (GetNextSibling()) { fprintf(out, " next=%p", static_cast<void*>(GetNextSibling())); } if (nullptr != GetPrevContinuation()) { fprintf(out, " prev-continuation=%p", static_cast<void*>(GetPrevContinuation())); } if (nullptr != GetNextContinuation()) { fprintf(out, " next-continuation=%p", static_cast<void*>(GetNextContinuation())); } fprintf(out, " {%d,%d,%d,%d}", mRect.x, mRect.y, mRect.width, mRect.height); if (0 != mState) { fprintf(out, " [state=%016llx]", (unsigned long long)mState); } fprintf(out, " [content=%p]", static_cast<void*>(mContent)); nsPopupSetFrame* f = const_cast<nsPopupSetFrame*>(this); if (f->HasOverflowAreas()) { nsRect overflowArea = f->GetVisualOverflowRect(); fprintf(out, " [vis-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y, overflowArea.width, overflowArea.height); overflowArea = f->GetScrollableOverflowRect(); fprintf(out, " [scr-overflow=%d,%d,%d,%d]", overflowArea.x, overflowArea.y, overflowArea.width, overflowArea.height); } fprintf(out, " [sc=%p]", static_cast<void*>(mStyleContext)); nsIAtom* pseudoTag = mStyleContext->GetPseudo(); if (pseudoTag) { nsAutoString atomString; pseudoTag->ToString(atomString); fprintf(out, " pst=%s", NS_LossyConvertUTF16toASCII(atomString).get()); } // Output the children bool outputOneList = false; ChildListIterator lists(this); for (; !lists.IsDone(); lists.Next()) { if (outputOneList) { IndentBy(out, aIndent); } outputOneList = true; fprintf(out, "%s<\n", mozilla::layout::ChildListName(lists.CurrentID())); nsFrameList::Enumerator childFrames(lists.CurrentList()); for (; !childFrames.AtEnd(); childFrames.Next()) { nsIFrame* kid = childFrames.get(); // Verify the child frame's parent frame pointer is correct NS_ASSERTION(kid->GetParent() == this, "bad parent frame pointer"); // Have the child frame list kid->List(out, aIndent + 1, aFlags); } IndentBy(out, aIndent); fputs(">\n", out); } // XXXmats the above is copy-pasted from nsContainerFrame::List which is lame, // clean this up after bug 399111 is implemented. if (!mPopupList.IsEmpty()) { fputs("<\n", out); ++aIndent; IndentBy(out, aIndent); fputs(mozilla::layout::ChildListName(kPopupList), out); fputs(" for ", out); ListTag(out); fputs(" <\n", out); ++aIndent; for (nsFrameList::Enumerator e(mPopupList); !e.AtEnd(); e.Next()) { e.get()->List(out, aIndent, aFlags); } --aIndent; IndentBy(out, aIndent); fputs(">\n", out); --aIndent; IndentBy(out, aIndent); fputs(">\n", out); outputOneList = true; } if (!outputOneList) { fputs("<>\n", out); } return NS_OK; }
NS_IMETHODIMP CVE_2013_1732_firefox12_0_nsBlockFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aMetrics, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsBlockFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus); #ifdef DEBUG if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); ListTag(stdout); printf(": begin reflow availSize=%d,%d computedSize=%d,%d\n", aReflowState.availableWidth, aReflowState.availableHeight, aReflowState.ComputedWidth(), aReflowState.ComputedHeight()); } AutoNoisyIndenter indent(gNoisy); PRTime start = LL_ZERO; // Initialize these variablies to silence the compiler. PRInt32 ctc = 0; // We only use these if they are set (gLameReflowMetrics). if (gLameReflowMetrics) { start = PR_Now(); ctc = nsLineBox::GetCtorCount(); } #endif const nsHTMLReflowState *reflowState = &aReflowState; nsAutoPtr<nsHTMLReflowState> mutableReflowState; // If we have non-auto height, we're clipping our kids and we fit, // make sure our kids fit too. if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE && aReflowState.ComputedHeight() != NS_AUTOHEIGHT && ApplyOverflowClipping(this, aReflowState.mStyleDisplay)) { nsMargin heightExtras = aReflowState.mComputedBorderPadding; if (GetSkipSides() & NS_SIDE_TOP) { heightExtras.top = 0; } else { // Bottom margin never causes us to create continuations, so we // don't need to worry about whether it fits in its entirety. heightExtras.top += aReflowState.mComputedMargin.top; } if (GetEffectiveComputedHeight(aReflowState) + heightExtras.TopBottom() <= aReflowState.availableHeight) { mutableReflowState = new nsHTMLReflowState(aReflowState); mutableReflowState->availableHeight = NS_UNCONSTRAINEDSIZE; reflowState = mutableReflowState; } } // See comment below about oldSize. Use *only* for the // abs-pos-containing-block-size-change optimization! nsSize oldSize = GetSize(); // Should we create a float manager? nsAutoFloatManager autoFloatManager(const_cast<nsHTMLReflowState&>(*reflowState)); // XXXldb If we start storing the float manager in the frame rather // than keeping it around only during reflow then we should create it // only when there are actually floats to manage. Otherwise things // like tables will gain significant bloat. bool needFloatManager = nsBlockFrame::BlockNeedsFloatManager(this); if (needFloatManager) autoFloatManager.CreateFloatManager(aPresContext); // OK, some lines may be reflowed. Blow away any saved line cursor // because we may invalidate the nondecreasing // overflowArea.VisualOverflow().y/yMost invariant, and we may even // delete the line with the line cursor. ClearLineCursor(); if (IsFrameTreeTooDeep(*reflowState, aMetrics, aStatus)) { return NS_OK; } bool marginRoot = BlockIsMarginRoot(this); nsBlockReflowState state(*reflowState, aPresContext, this, aMetrics, marginRoot, marginRoot, needFloatManager); #ifdef IBMBIDI if (GetStateBits() & NS_BLOCK_NEEDS_BIDI_RESOLUTION) static_cast<nsBlockFrame*>(GetFirstContinuation())->ResolveBidi(); #endif // IBMBIDI if (RenumberLists(aPresContext)) { AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN); } nsresult rv = NS_OK; // ALWAYS drain overflow. We never want to leave the previnflow's // overflow lines hanging around; block reflow depends on the // overflow line lists being cleared out between reflow passes. DrainOverflowLines(); // Handle paginated overflow (see nsContainerFrame.h) nsOverflowAreas ocBounds; nsReflowStatus ocStatus = NS_FRAME_COMPLETE; if (GetPrevInFlow()) { ReflowOverflowContainerChildren(aPresContext, *reflowState, ocBounds, 0, ocStatus); } // Now that we're done cleaning up our overflow container lists, we can // give |state| its nsOverflowContinuationTracker. nsOverflowContinuationTracker tracker(aPresContext, this, false); state.mOverflowTracker = &tracker; // Drain & handle pushed floats DrainPushedFloats(state); nsOverflowAreas fcBounds; nsReflowStatus fcStatus = NS_FRAME_COMPLETE; rv = ReflowPushedFloats(state, fcBounds, fcStatus); NS_ENSURE_SUCCESS(rv, rv); // If we're not dirty (which means we'll mark everything dirty later) // and our width has changed, mark the lines dirty that we need to // mark dirty for a resize reflow. if (reflowState->mFlags.mHResize) PrepareResizeReflow(state); mState &= ~NS_FRAME_FIRST_REFLOW; // Now reflow... rv = ReflowDirtyLines(state); NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed"); if (NS_FAILED(rv)) return rv; NS_MergeReflowStatusInto(&state.mReflowStatus, ocStatus); NS_MergeReflowStatusInto(&state.mReflowStatus, fcStatus); // If we end in a BR with clear and affected floats continue, // we need to continue, too. if (NS_UNCONSTRAINEDSIZE != reflowState->availableHeight && NS_FRAME_IS_COMPLETE(state.mReflowStatus) && state.mFloatManager->ClearContinues(FindTrailingClear())) { NS_FRAME_SET_INCOMPLETE(state.mReflowStatus); } if (!NS_FRAME_IS_FULLY_COMPLETE(state.mReflowStatus)) { if (GetOverflowLines() || GetPushedFloats()) { state.mReflowStatus |= NS_FRAME_REFLOW_NEXTINFLOW; } #ifdef DEBUG_kipp ListTag(stdout); printf(": block is not fully complete\n"); #endif } CheckFloats(state); // Place the "marker" (bullet) frame if it is placed next to a block // child. // // According to the CSS2 spec, section 12.6.1, the "marker" box // participates in the height calculation of the list-item box's // first line box. // // There are exactly two places a bullet can be placed: near the // first or second line. It's only placed on the second line in a // rare case: an empty first line followed by a second line that // contains a block (example: <LI>\n<P>... ). This is where // the second case can happen. if (mBullet && HaveOutsideBullet() && !mLines.empty() && (mLines.front()->IsBlock() || (0 == mLines.front()->mBounds.height && mLines.front() != mLines.back() && mLines.begin().next()->IsBlock()))) { // Reflow the bullet nsHTMLReflowMetrics metrics; // XXX Use the entire line when we fix bug 25888. nsLayoutUtils::LinePosition position; bool havePosition = nsLayoutUtils::GetFirstLinePosition(this, &position); nscoord lineTop = havePosition ? position.mTop : reflowState->mComputedBorderPadding.top; ReflowBullet(state, metrics, lineTop); NS_ASSERTION(!BulletIsEmpty() || metrics.height == 0, "empty bullet took up space"); if (havePosition && !BulletIsEmpty()) { // We have some lines to align the bullet with. // Doing the alignment using the baseline will also cater for // bullets that are placed next to a child block (bug 92896) // Tall bullets won't look particularly nice here... nsRect bbox = mBullet->GetRect(); bbox.y = position.mBaseline - metrics.ascent; mBullet->SetRect(bbox); } // Otherwise just leave the bullet where it is, up against our top padding. } // Compute our final size nscoord bottomEdgeOfChildren; ComputeFinalSize(*reflowState, state, aMetrics, &bottomEdgeOfChildren); nsRect areaBounds = nsRect(0, 0, aMetrics.width, aMetrics.height); ComputeOverflowAreas(areaBounds, reflowState->mStyleDisplay, bottomEdgeOfChildren, aMetrics.mOverflowAreas); // Factor overflow container child bounds into the overflow area aMetrics.mOverflowAreas.UnionWith(ocBounds); // Factor pushed float child bounds into the overflow area aMetrics.mOverflowAreas.UnionWith(fcBounds); // Let the absolutely positioned container reflow any absolutely positioned // child frames that need to be reflowed, e.g., elements with a percentage // based width/height // We want to do this under either of two conditions: // 1. If we didn't do the incremental reflow above. // 2. If our size changed. // Even though it's the padding edge that's the containing block, we // can use our rect (the border edge) since if the border style // changed, the reflow would have been targeted at us so we'd satisfy // condition 1. // XXX checking oldSize is bogus, there are various reasons we might have // reflowed but our size might not have been changed to what we // asked for (e.g., we ended up being pushed to a new page) // When WillReflowAgainForClearance is true, we will reflow again without // resetting the size. Because of this, we must not reflow our abs-pos children // in that situation --- what we think is our "new size" // will not be our real new size. This also happens to be more efficient. if (HasAbsolutelyPositionedChildren()) { nsAbsoluteContainingBlock* absoluteContainer = GetAbsoluteContainingBlock(); bool haveInterrupt = aPresContext->HasPendingInterrupt(); if (reflowState->WillReflowAgainForClearance() || haveInterrupt) { // Make sure that when we reflow again we'll actually reflow all the abs // pos frames that might conceivably depend on our size (or all of them, // if we're dirty right now and interrupted; in that case we also need // to mark them all with NS_FRAME_IS_DIRTY). Sadly, we can't do much // better than that, because we don't really know what our size will be, // and it might in fact not change on the followup reflow! if (haveInterrupt && (GetStateBits() & NS_FRAME_IS_DIRTY)) { absoluteContainer->MarkAllFramesDirty(); } else { absoluteContainer->MarkSizeDependentFramesDirty(); } } else { nsSize containingBlockSize = CalculateContainingBlockSizeForAbsolutes(*reflowState, nsSize(aMetrics.width, aMetrics.height)); // Mark frames that depend on changes we just made to this frame as dirty: // Now we can assume that the padding edge hasn't moved. // We need to reflow the absolutes if one of them depends on // its placeholder position, or the containing block size in a // direction in which the containing block size might have // changed. bool cbWidthChanged = aMetrics.width != oldSize.width; bool isRoot = !GetContent()->GetParent(); // If isRoot and we have auto height, then we are the initial // containing block and the containing block height is the // viewport height, which can't change during incremental // reflow. bool cbHeightChanged = !(isRoot && NS_UNCONSTRAINEDSIZE == reflowState->ComputedHeight()) && aMetrics.height != oldSize.height; absoluteContainer->Reflow(this, aPresContext, *reflowState, state.mReflowStatus, containingBlockSize.width, containingBlockSize.height, true, cbWidthChanged, cbHeightChanged, &aMetrics.mOverflowAreas); //XXXfr Why isn't this rv (and others in this file) checked/returned? } } // Determine if we need to repaint our border, background or outline CheckInvalidateSizeChange(aMetrics); FinishAndStoreOverflow(&aMetrics); // Clear the float manager pointer in the block reflow state so we // don't waste time translating the coordinate system back on a dead // float manager. if (needFloatManager) state.mFloatManager = nsnull; aStatus = state.mReflowStatus; #ifdef DEBUG // Between when we drain pushed floats and when we complete reflow, // we're allowed to have multiple continuations of the same float on // our floats list, since a first-in-flow might get pushed to a later // continuation of its containing block. But it's not permitted // outside that time. nsLayoutUtils::AssertNoDuplicateContinuations(this, mFloats); if (gNoisyReflow) { IndentBy(stdout, gNoiseIndent); ListTag(stdout); printf(": status=%x (%scomplete) metrics=%d,%d carriedMargin=%d", aStatus, NS_FRAME_IS_COMPLETE(aStatus) ? "" : "not ", aMetrics.width, aMetrics.height, aMetrics.mCarriedOutBottomMargin.get()); if (HasOverflowAreas()) { printf(" overflow-vis={%d,%d,%d,%d}", aMetrics.VisualOverflow().x, aMetrics.VisualOverflow().y, aMetrics.VisualOverflow().width, aMetrics.VisualOverflow().height); printf(" overflow-scr={%d,%d,%d,%d}", aMetrics.ScrollableOverflow().x, aMetrics.ScrollableOverflow().y, aMetrics.ScrollableOverflow().width, aMetrics.ScrollableOverflow().height); } printf("\n"); } if (gLameReflowMetrics) { PRTime end = PR_Now(); PRInt32 ectc = nsLineBox::GetCtorCount(); PRInt32 numLines = mLines.size(); if (!numLines) numLines = 1; PRTime delta, perLineDelta, lines; LL_I2L(lines, numLines); LL_SUB(delta, end, start); LL_DIV(perLineDelta, delta, lines); ListTag(stdout); char buf[400]; PR_snprintf(buf, sizeof(buf), ": %lld elapsed (%lld per line) (%d lines; %d new lines)", delta, perLineDelta, numLines, ectc - ctc); printf("%s\n", buf); } #endif NS_FRAME_SET_TRUNCATION(aStatus, (*reflowState), aMetrics); return rv; }
int main( int argc, char *argv[]) { int iOpt; int argCounter = 0; int ii; char tmp[TMPSIZE]; FILE * fp; struct frameInfo { enum ID3_FrameID id; char *data; } frameList[MAXNOFRAMES]; int frameCounter = 0; while (true) { int option_index = 0; int iLongOpt = 0; int optFrameID = ID3FID_NOFRAME; static struct option long_options[] = { // help and info { "help", no_argument, &iLongOpt, 'h' }, { "list-frames", no_argument, &iLongOpt, 'f' }, { "list-genres", no_argument, &iLongOpt, 'L' }, { "version", no_argument, &iLongOpt, 'v' }, // list / remove / convert { "list", no_argument, &iLongOpt, 'l' }, { "list-rfc822", no_argument, &iLongOpt, 'R' }, { "delete-v2", no_argument, &iLongOpt, 'd' }, { "delete-v1", no_argument, &iLongOpt, 's' }, { "delete-all", no_argument, &iLongOpt, 'D' }, { "convert", no_argument, &iLongOpt, 'C' }, { "id3v1-only", no_argument, &iLongOpt, '1' }, { "id3v2-only", no_argument, &iLongOpt, '2' }, // infomation to tag { "artist", required_argument, &iLongOpt, 'a' }, { "album", required_argument, &iLongOpt, 'A' }, { "song", required_argument, &iLongOpt, 't' }, { "comment", required_argument, &iLongOpt, 'c' }, { "genre", required_argument, &iLongOpt, 'g' }, { "year", required_argument, &iLongOpt, 'y' }, { "track", required_argument, &iLongOpt, 'T' }, { "AENC", required_argument, &optFrameID, ID3FID_AUDIOCRYPTO }, { "APIC", required_argument, &optFrameID, ID3FID_PICTURE }, { "COMM", required_argument, &optFrameID, ID3FID_COMMENT }, /* COMR too complex */ { "ENCR", required_argument, &optFrameID, ID3FID_CRYPTOREG }, { "EQUA", required_argument, &optFrameID, ID3FID_EQUALIZATION }, { "ETCO", required_argument, &optFrameID, ID3FID_EVENTTIMING }, { "GEOB", required_argument, &optFrameID, ID3FID_GENERALOBJECT }, { "GRID", required_argument, &optFrameID, ID3FID_GROUPINGREG }, { "IPLS", required_argument, &optFrameID, ID3FID_INVOLVEDPEOPLE }, { "LINK", required_argument, &optFrameID, ID3FID_LINKEDINFO }, { "MCDI", required_argument, &optFrameID, ID3FID_CDID }, { "MLLT", required_argument, &optFrameID, ID3FID_MPEGLOOKUP }, { "OWNE", required_argument, &optFrameID, ID3FID_OWNERSHIP }, { "PRIV", required_argument, &optFrameID, ID3FID_PRIVATE }, { "PCNT", required_argument, &optFrameID, ID3FID_PLAYCOUNTER }, { "POPM", required_argument, &optFrameID, ID3FID_POPULARIMETER }, { "POSS", required_argument, &optFrameID, ID3FID_POSITIONSYNC }, { "RBUF", required_argument, &optFrameID, ID3FID_BUFFERSIZE }, { "RVAD", required_argument, &optFrameID, ID3FID_VOLUMEADJ }, { "RVRB", required_argument, &optFrameID, ID3FID_REVERB }, { "SYLT", required_argument, &optFrameID, ID3FID_SYNCEDLYRICS }, { "SYTC", required_argument, &optFrameID, ID3FID_SYNCEDTEMPO }, { "TALB", required_argument, &optFrameID, ID3FID_ALBUM }, { "TBPM", required_argument, &optFrameID, ID3FID_BPM }, { "TCOM", required_argument, &optFrameID, ID3FID_COMPOSER }, { "TCON", required_argument, &optFrameID, ID3FID_CONTENTTYPE }, { "TCOP", required_argument, &optFrameID, ID3FID_COPYRIGHT }, { "TDAT", required_argument, &optFrameID, ID3FID_DATE }, { "TDLY", required_argument, &optFrameID, ID3FID_PLAYLISTDELAY }, { "TENC", required_argument, &optFrameID, ID3FID_ENCODEDBY }, { "TEXT", required_argument, &optFrameID, ID3FID_LYRICIST }, { "TFLT", required_argument, &optFrameID, ID3FID_FILETYPE }, { "TIME", required_argument, &optFrameID, ID3FID_TIME }, { "TIT1", required_argument, &optFrameID, ID3FID_CONTENTGROUP }, { "TIT2", required_argument, &optFrameID, ID3FID_TITLE }, { "TIT3", required_argument, &optFrameID, ID3FID_SUBTITLE }, { "TKEY", required_argument, &optFrameID, ID3FID_INITIALKEY }, { "TLAN", required_argument, &optFrameID, ID3FID_LANGUAGE }, { "TLEN", required_argument, &optFrameID, ID3FID_SONGLEN }, { "TMED", required_argument, &optFrameID, ID3FID_MEDIATYPE }, { "TOAL", required_argument, &optFrameID, ID3FID_ORIGALBUM }, { "TOFN", required_argument, &optFrameID, ID3FID_ORIGFILENAME }, { "TOLY", required_argument, &optFrameID, ID3FID_ORIGLYRICIST }, { "TOPE", required_argument, &optFrameID, ID3FID_ORIGARTIST }, { "TORY", required_argument, &optFrameID, ID3FID_ORIGYEAR }, { "TOWN", required_argument, &optFrameID, ID3FID_FILEOWNER }, { "TPE1", required_argument, &optFrameID, ID3FID_LEADARTIST }, { "TPE2", required_argument, &optFrameID, ID3FID_BAND }, { "TPE3", required_argument, &optFrameID, ID3FID_CONDUCTOR }, { "TPE4", required_argument, &optFrameID, ID3FID_MIXARTIST }, { "TPOS", required_argument, &optFrameID, ID3FID_PARTINSET }, { "TPUB", required_argument, &optFrameID, ID3FID_PUBLISHER }, { "TRCK", required_argument, &optFrameID, ID3FID_TRACKNUM }, { "TRDA", required_argument, &optFrameID, ID3FID_RECORDINGDATES }, { "TRSN", required_argument, &optFrameID, ID3FID_NETRADIOSTATION }, { "TRSO", required_argument, &optFrameID, ID3FID_NETRADIOOWNER }, { "TSIZ", required_argument, &optFrameID, ID3FID_SIZE }, { "TSRC", required_argument, &optFrameID, ID3FID_ISRC }, { "TSSE", required_argument, &optFrameID, ID3FID_ENCODERSETTINGS }, { "TXXX", required_argument, &optFrameID, ID3FID_USERTEXT }, { "TYER", required_argument, &optFrameID, ID3FID_YEAR }, { "UFID", required_argument, &optFrameID, ID3FID_UNIQUEFILEID }, { "USER", required_argument, &optFrameID, ID3FID_TERMSOFUSE }, { "USLT", required_argument, &optFrameID, ID3FID_UNSYNCEDLYRICS }, { "WCOM", required_argument, &optFrameID, ID3FID_WWWCOMMERCIALINFO }, { "WCOP", required_argument, &optFrameID, ID3FID_WWWCOPYRIGHT }, { "WOAF", required_argument, &optFrameID, ID3FID_WWWAUDIOFILE }, { "WOAR", required_argument, &optFrameID, ID3FID_WWWARTIST }, { "WOAS", required_argument, &optFrameID, ID3FID_WWWAUDIOSOURCE }, { "WORS", required_argument, &optFrameID, ID3FID_WWWRADIOPAGE }, { "WPAY", required_argument, &optFrameID, ID3FID_WWWPAYMENT }, { "WPUB", required_argument, &optFrameID, ID3FID_WWWPUBLISHER }, { "WXXX", required_argument, &optFrameID, ID3FID_WWWUSER }, { 0, 0, 0, 0 } }; iOpt = getopt_long (argc, argv, "12hfLvlRdsDCa:A:t:c:g:y:T:", long_options, &option_index); if (iOpt == -1 && argCounter == 0) { PrintUsage(argv[0]); exit(0); } else if (iOpt == -1) break; argCounter++; if (iOpt == 0) iOpt = iLongOpt; // if (iOpt == 0) iOpt = optFrameID; #ifdef SORT_RUNTIME InitGenres(); #endif // SORT_RUNTIME switch (iOpt) { case 0: frameList[frameCounter].id = (enum ID3_FrameID)optFrameID; frameList[frameCounter].data = optarg; frameCounter++; break; case '?': case 'h': PrintUsage(argv[0]); exit (0); case 'f': PrintFrameHelp(argv[0]);exit (0); case 'L': PrintGenreList(); exit (0); case 'v': PrintVersion(argv[0]); exit (0); // listing / remove / convert -- see list.cpp and convert.cpp case 'l': ListTag(argc, argv, optind, 0); exit (0); case 'R': ListTag(argc, argv, optind, 1); exit (0); case 'd': DeleteTag(argc, argv, optind, 2); exit (0); case 's': DeleteTag(argc, argv, optind, 1); exit (0); case 'D': DeleteTag(argc, argv, optind, 0); exit (0); case 'C': ConvertTag(argc, argv, optind); exit (0); case '1': UpdFlags = ID3TT_ID3V1; break; case '2': UpdFlags = ID3TT_ID3V2; break; // Tagging stuff case 'a': frameList[frameCounter].id = ID3FID_LEADARTIST; frameList[frameCounter].data = optarg; frameCounter++; break; case 'A': frameList[frameCounter].id = ID3FID_ALBUM; frameList[frameCounter].data = optarg; frameCounter++; break; case 't': frameList[frameCounter].id = ID3FID_TITLE; frameList[frameCounter].data = optarg; frameCounter++; break; case 'c': frameList[frameCounter].id = ID3FID_COMMENT; frameList[frameCounter].data = optarg; frameCounter++; break; case 'g': { int genre_id = 255; char *genre_str; sscanf(optarg, "%d", &genre_id); if (genre_id == 255) genre_id = GetNumFromGenre(optarg); if (genre_id == 255) genre_str = optarg; else { sprintf(tmp, "(%d)", genre_id); genre_str = tmp; } frameList[frameCounter].id = ID3FID_CONTENTTYPE; frameList[frameCounter].data = genre_str; frameCounter++; } break; case 'y': frameList[frameCounter].id = ID3FID_YEAR; frameList[frameCounter].data = optarg; frameCounter++; break; case 'T': frameList[frameCounter].id = ID3FID_TRACKNUM; frameList[frameCounter].data = optarg; frameCounter++; break; // other tags default: std::cerr << "This isn't supposed to happen" << std::endl; exit(1); } } // loop thru the files if (optind == argc) { std::cerr << "No file to work on." << std::endl; exit(1); } for (size_t nIndex = optind; (unsigned int) nIndex < argc; nIndex++) { ID3_Tag myTag; struct stat filestat; // std::cout << "Tagging " << argv[nIndex] << ": "; // fix me - not checking to see if we can link to it if (stat(argv[nIndex], &filestat)) { std::cerr << "Couldn't stat file '" << argv[nIndex] << "'\n"; break; } /* cludgy to check if we have the proper perms */ fp = fopen(argv[nIndex], "r+"); if (fp == NULL) { /* file didn't open */ fprintf(stderr, "fopen: %s: ", argv[nIndex]); perror("id3v2"); continue; } fclose(fp); size_t ret; ret = myTag.Link(argv[nIndex] /*, ID3TT_ID3V2 */); // loop thru the frames we need to add/modify for (ii = 0; ii < frameCounter; ii++) { ID3_Frame *myFrame; myFrame = new ID3_Frame; if (NULL == myFrame) { std::cout << "\nOut of memory\n" << std::endl; exit(1); } myFrame->SetID(frameList[ii].id); ID3_Frame *pFrame; pFrame = myTag.Find(frameList[ii].id); switch (frameList[ii].id) { // strings case ID3FID_ALBUM: case ID3FID_BPM: case ID3FID_COMPOSER: case ID3FID_CONTENTTYPE: case ID3FID_COPYRIGHT: case ID3FID_DATE: case ID3FID_PLAYLISTDELAY: case ID3FID_ENCODEDBY: case ID3FID_LYRICIST: case ID3FID_FILETYPE: case ID3FID_TIME: case ID3FID_CONTENTGROUP: case ID3FID_TITLE: case ID3FID_SUBTITLE: case ID3FID_INITIALKEY: case ID3FID_LANGUAGE: case ID3FID_SONGLEN: case ID3FID_MEDIATYPE: case ID3FID_ORIGALBUM: case ID3FID_ORIGFILENAME: case ID3FID_ORIGLYRICIST: case ID3FID_ORIGARTIST: case ID3FID_ORIGYEAR: case ID3FID_FILEOWNER: case ID3FID_LEADARTIST: case ID3FID_BAND: case ID3FID_CONDUCTOR: case ID3FID_MIXARTIST: case ID3FID_PARTINSET: case ID3FID_PUBLISHER: case ID3FID_RECORDINGDATES: case ID3FID_NETRADIOSTATION: case ID3FID_NETRADIOOWNER: case ID3FID_SIZE: case ID3FID_ISRC: case ID3FID_ENCODERSETTINGS: case ID3FID_YEAR: { if (pFrame != NULL) { myTag.RemoveFrame(pFrame); } if (strlen(frameList[ii].data) > 0) { myFrame->Field(ID3FN_TEXT) = frameList[ii].data; myTag.AttachFrame(myFrame); } break; } case ID3FID_TRACKNUM: { // this ought to check if there is a total track number and // combine it with the given track number, but it doesn't. char *currentTrackNum = NULL; char *newTrackNum = NULL; if (pFrame != NULL) { currentTrackNum = ID3_GetString(pFrame, ID3FN_TEXT); if (*currentTrackNum == '/') { newTrackNum = (char *)malloc(strlen(currentTrackNum) + strlen(frameList[ii].data)); strcpy(newTrackNum, frameList[ii].data); strcat(newTrackNum, currentTrackNum); } else { myTag.RemoveFrame(pFrame); } } myFrame->Field(ID3FN_TEXT) = frameList[ii].data; myTag.AttachFrame(myFrame); free(newTrackNum); break; } case ID3FID_USERTEXT: { if (pFrame != NULL) { myTag.RemoveFrame(pFrame); } // split the string at the ':' remember if no : then leave // descrip empty char *text; text = strchr(frameList[ii].data, ':'); if (text == NULL) { myFrame->Field(ID3FN_TEXT) = frameList[ii].data; } else { *text = '\0'; text++; myFrame->Field(ID3FN_DESCRIPTION) = frameList[ii].data; myFrame->Field(ID3FN_TEXT) = text; } if (strlen(ID3_GetString(myFrame, ID3FN_TEXT)) > 0) { myTag.AttachFrame(myFrame); } break; } case ID3FID_COMMENT: case ID3FID_UNSYNCEDLYRICS: { // split the string at the ':' remember if no : then leave // descrip/lang empty char *text; text = strchr(frameList[ii].data, ':'); if (text == NULL) { myFrame->Field(ID3FN_TEXT) = frameList[ii].data; } else { *text = '\0'; text++; char *lang; lang = strchr(text, ':'); if (lang == NULL) { myFrame->Field(ID3FN_DESCRIPTION) = frameList[ii].data; myFrame->Field(ID3FN_TEXT) = text; } else { *lang = '\0'; lang++; myFrame->Field(ID3FN_DESCRIPTION) = frameList[ii].data; myFrame->Field(ID3FN_TEXT) = text; myFrame->Field(ID3FN_LANGUAGE) = lang; } } /* debug std::cout << ID3_GetString(myFrame, ID3FN_DESCRIPTION) << std::endl << ID3_GetString(myFrame, ID3FN_TEXT) << std::endl << ID3_GetString(myFrame, ID3FN_LANGUAGE) << std::endl; */ // now try and find a comment/lyrics with the same descript // and lang as what we have ID3_Frame *pFirstFrame = NULL; do { // if pFrame is NULL, either there were no comments/lyrics // to begin with, or we removed them all in the process if (pFrame == NULL) break; if (pFirstFrame == NULL) { pFirstFrame = pFrame; } char *tmp_desc = ID3_GetString(pFrame, ID3FN_DESCRIPTION); char *tmp_my_desc = ID3_GetString(myFrame, ID3FN_DESCRIPTION); char *tmp_lang = ID3_GetString(pFrame, ID3FN_LANGUAGE); char *tmp_my_lang = ID3_GetString(myFrame, ID3FN_LANGUAGE); if ((strcmp(tmp_desc, tmp_my_desc) == 0) && (strcmp(tmp_lang, tmp_my_lang) == 0)) { myTag.RemoveFrame(pFrame); if (pFrame == pFirstFrame) { pFirstFrame = NULL; } } delete [] tmp_desc; delete [] tmp_my_desc; delete [] tmp_lang; delete [] tmp_my_lang; // get the next frame until it wraps around } while ((pFrame = myTag.Find(frameList[ii].id)) != pFirstFrame); if (strlen(ID3_GetString(myFrame, ID3FN_TEXT)) > 0) { myTag.AttachFrame(myFrame); } break; } case ID3FID_WWWAUDIOFILE: case ID3FID_WWWARTIST: case ID3FID_WWWAUDIOSOURCE: case ID3FID_WWWCOMMERCIALINFO: case ID3FID_WWWCOPYRIGHT: case ID3FID_WWWPUBLISHER: case ID3FID_WWWPAYMENT: case ID3FID_WWWRADIOPAGE: { if (pFrame != NULL) { char *sURL = ID3_GetString(pFrame, ID3FN_URL); if (strcmp(frameList[ii].data, sURL) == 0) myTag.RemoveFrame(pFrame); } if (strlen(frameList[ii].data) > 0) { myFrame->Field(ID3FN_URL) = frameList[ii].data; myTag.AttachFrame(myFrame); } break; } case ID3FID_WWWUSER: { char *sURL = ID3_GetString(myFrame, ID3FN_URL), *sDesc = ID3_GetString(myFrame, ID3FN_DESCRIPTION); std::cout << "(" << sDesc << "): " << sURL << std::endl; delete [] sURL; delete [] sDesc; break; } case ID3FID_INVOLVEDPEOPLE: { // This isn't the right way to do it---will only get first person size_t nItems = myFrame->Field(ID3FN_TEXT).GetNumTextItems(); for (size_t nIndex = 1; nIndex <= nItems; nIndex++) { char *sPeople = ID3_GetString(myFrame, ID3FN_TEXT, nIndex); std::cout << sPeople; delete [] sPeople; if (nIndex < nItems) { std::cout << ", "; } } std::cout << std::endl; break; } case ID3FID_PICTURE: { myFrame->Field(ID3FN_DATA).FromFile(frameList[ii].data); myTag.AttachFrame(myFrame); break; } case ID3FID_GENERALOBJECT: { char *sMimeType = ID3_GetString(myFrame, ID3FN_TEXT), *sDesc = ID3_GetString(myFrame, ID3FN_DESCRIPTION), *sFileName = ID3_GetString(myFrame, ID3FN_FILENAME); size_t nDataSize = myFrame->Field(ID3FN_DATA).Size(); std::cout << "(" << sDesc << ")[" << sFileName << "]: " << sMimeType << ", " << nDataSize << " bytes" << std::endl; delete [] sMimeType; delete [] sDesc; delete [] sFileName; break; } case ID3FID_UNIQUEFILEID: { if (pFrame != NULL) { char *sOwner = ID3_GetString(pFrame, ID3FN_TEXT); size_t nDataSize = pFrame->Field(ID3FN_DATA).Size(); std::cout << sOwner << ", " << nDataSize << " bytes" << std::endl; delete [] sOwner; } break; } case ID3FID_PLAYCOUNTER: { if (pFrame != NULL) { size_t nCounter = pFrame->Field(ID3FN_COUNTER).Get(); std::cout << nCounter << std::endl; } break; } case ID3FID_POPULARIMETER: { if (pFrame != NULL) { char *sEmail = ID3_GetString(pFrame, ID3FN_EMAIL); size_t nCounter = pFrame->Field(ID3FN_COUNTER).Get(), nRating = pFrame->Field(ID3FN_RATING).Get(); std::cout << sEmail << ", counter=" << nCounter << " rating=" << nRating; delete [] sEmail; } break; } case ID3FID_CRYPTOREG: case ID3FID_GROUPINGREG: { char *sOwner = ID3_GetString(myFrame, ID3FN_OWNER); size_t nSymbol = myFrame->Field(ID3FN_ID).Get(), nDataSize = myFrame->Field(ID3FN_DATA).Size(); std::cout << "(" << nSymbol << "): " << sOwner << ", " << nDataSize << " bytes"; break; } case ID3FID_AUDIOCRYPTO: case ID3FID_EQUALIZATION: case ID3FID_EVENTTIMING: case ID3FID_CDID: case ID3FID_MPEGLOOKUP: case ID3FID_OWNERSHIP: case ID3FID_PRIVATE: case ID3FID_POSITIONSYNC: case ID3FID_BUFFERSIZE: case ID3FID_VOLUMEADJ: case ID3FID_REVERB: case ID3FID_SYNCEDLYRICS: case ID3FID_SYNCEDTEMPO: case ID3FID_METACRYPTO: { std::cout << " (unimplemented)" << std::endl; break; } default: { std::cout << " frame" << std::endl; break; } } } // steping thru frames luint nTags = myTag.Update(UpdFlags); /* update file with old mode */ if (chmod(argv[nIndex], filestat.st_mode)) { std::cerr << "Couldn't reset permissions on '" << argv[nIndex] << "'\n"; } } return 0; }