From dc9f2947a777a5f4dc96a8d8af23f187e87c15da Mon Sep 17 00:00:00 2001 From: "erik%netscape.com" Date: Fri, 9 Mar 2001 03:29:00 +0000 Subject: [PATCH] bug 71370; author=simon@softel.co.il; r=attinasi; sr=erik; implement bidi (bidirectional text) for languages such as Arabic and Hebrew; from IBM bidi project; not part of build yet (due to #ifdef IBMBIDI) git-svn-id: svn://10.0.0.236/trunk@89069 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsFrameManager.cpp | 23 ++ mozilla/layout/base/nsPresShell.cpp | 69 +++++ mozilla/layout/generic/nsBlockFrame.cpp | 112 +++++++- mozilla/layout/generic/nsBlockReflowState.cpp | 112 +++++++- mozilla/layout/generic/nsBlockReflowState.h | 112 +++++++- mozilla/layout/generic/nsBulletFrame.cpp | 111 ++++++++ mozilla/layout/generic/nsContainerFrame.cpp | 9 + mozilla/layout/generic/nsFrame.cpp | 247 ++++++++++++++++-- mozilla/layout/generic/nsFrame.h | 9 + mozilla/layout/generic/nsHTMLReflowState.cpp | 30 +++ mozilla/layout/generic/nsInlineFrame.cpp | 15 ++ mozilla/layout/generic/nsLineBox.cpp | 184 ++++++++++++- mozilla/layout/generic/nsLineBox.h | 10 +- mozilla/layout/html/base/src/nsBlockFrame.cpp | 112 +++++++- .../html/base/src/nsBlockReflowState.cpp | 112 +++++++- .../layout/html/base/src/nsBlockReflowState.h | 112 +++++++- .../layout/html/base/src/nsBulletFrame.cpp | 111 ++++++++ .../layout/html/base/src/nsContainerFrame.cpp | 9 + mozilla/layout/html/base/src/nsFrame.cpp | 247 ++++++++++++++++-- mozilla/layout/html/base/src/nsFrame.h | 9 + .../layout/html/base/src/nsFrameManager.cpp | 23 ++ .../html/base/src/nsHTMLReflowState.cpp | 30 +++ .../layout/html/base/src/nsInlineFrame.cpp | 15 ++ mozilla/layout/html/base/src/nsLineBox.cpp | 184 ++++++++++++- mozilla/layout/html/base/src/nsLineBox.h | 10 +- mozilla/layout/html/base/src/nsPresShell.cpp | 69 +++++ 26 files changed, 2044 insertions(+), 42 deletions(-) diff --git a/mozilla/layout/base/nsFrameManager.cpp b/mozilla/layout/base/nsFrameManager.cpp index 594c671f614..2987f7da417 100644 --- a/mozilla/layout/base/nsFrameManager.cpp +++ b/mozilla/layout/base/nsFrameManager.cpp @@ -805,6 +805,20 @@ FrameManager::InsertFrames(nsIPresContext* aPresContext, return rv; } +#ifdef IBMBIDI + if (aPrevFrame) { + // Insert aFrameList after the last bidi continuation of aPrevFrame. + nsIFrame* nextBidi; + for (; ;) { + GetFrameProperty(aPrevFrame, nsLayoutAtoms::nextBidi, 0, (void**) &nextBidi); + if (!nextBidi) { + break; + } + aPrevFrame = nextBidi; + } + } +#endif // IBMBIDI + return aParentFrame->InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); } @@ -822,6 +836,15 @@ FrameManager::RemoveFrame(nsIPresContext* aPresContext, if (insertionPoint) return insertionPoint->RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); +#ifdef IBMBIDI + // Don't let the parent remove next bidi. In the other cases the it should NOT be removed. + nsIFrame* nextBidi; + GetFrameProperty(aOldFrame, nsLayoutAtoms::nextBidi, 0, (void**) &nextBidi); + if (nextBidi) { + RemoveFrame(aPresContext, aPresShell, aParentFrame, aListName, nextBidi); + } +#endif // IBMBIDI + return aParentFrame->RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); } diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 1bab0d8f383..3e18cf18117 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -135,6 +135,10 @@ // SubShell map #include "nsDST.h" +#ifdef IBMBIDI +#include "nsIBidiKeyboard.h" +#endif // IBMBIDI + #include "nsContentCID.h" static NS_DEFINE_CID(kCSSStyleSheetCID, NS_CSS_STYLESHEET_CID); static NS_DEFINE_CID(kStyleSetCID, NS_STYLESET_CID); @@ -886,6 +890,12 @@ public: NS_IMETHOD GetEventTargetFrame(nsIFrame** aFrame); NS_IMETHOD IsReflowLocked(PRBool* aIsLocked); +#ifdef IBMBIDI + NS_IMETHOD SetCursorBidiLevel(PRUint8 aLevel); + NS_IMETHOD GetCursorBidiLevel(PRUint8 *aOutLevel); + NS_IMETHOD UndefineCursorBidiLevel(); + NS_IMETHOD BidiStyleChangeReflow(); +#endif //nsIViewObserver interface @@ -1022,6 +1032,10 @@ protected: PRBool IsDragInProgress ( ) const ; PRBool mCaretEnabled; +#ifdef IBMBIDI + PRUint8 mBidiLevel; // The Bidi level of the cursor + nsCOMPtr mBidiKeyboard; +#endif // IBMBIDI #ifdef NS_DEBUG PRBool VerifyIncrementalReflow(); PRBool mInVerifyReflow; @@ -1246,6 +1260,9 @@ PresShell::PresShell():mAnonymousContentTable(nsnull), mReflowCountMgr->SetPresContext(mPresContext); mReflowCountMgr->SetPresShell(this); #endif +#ifdef IBMBIDI + mBidiLevel = BIDI_LEVEL_UNDEFINED; +#endif } NS_IMPL_ADDREF(PresShell) @@ -1479,6 +1496,9 @@ PresShell::Init(nsIDocument* aDocument, // cache the drag service so we can check it during reflows mDragService = do_GetService("@mozilla.org/widget/dragservice;1"); +#ifdef IBMBIDI + mBidiKeyboard = do_GetService("@mozilla.org/widget/bidikeyboard;1"); +#endif // setup the preference style rules up (no forced reflow) SetPreferenceStyleRules(PR_FALSE); @@ -4535,6 +4555,55 @@ PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame, return rv; } +#ifdef IBMBIDI +NS_IMETHODIMP +PresShell::SetCursorBidiLevel(PRUint8 aLevel) +{ + // If the current level is undefined, we have just inserted new text. + // In this case, we don't want to reset the keyboard language + PRBool afterInsert = mBidiLevel & BIDI_LEVEL_UNDEFINED; + mBidiLevel = aLevel; + +// PRBool parityChange = ((mBidiLevel ^ aLevel) & 1); // is the parity of the new level different from the current level? +// if (parityChange) // if so, change the keyboard language + if (mBidiKeyboard && !afterInsert) + mBidiKeyboard->SetLangFromBidiLevel(aLevel); + return NS_OK; +} + +NS_IMETHODIMP +PresShell::GetCursorBidiLevel(PRUint8 *aOutLevel) +{ + if (!aOutLevel) { return NS_ERROR_INVALID_ARG; } + *aOutLevel = mBidiLevel; + return NS_OK; +} + +NS_IMETHODIMP +PresShell::UndefineCursorBidiLevel() +{ + mBidiLevel |= BIDI_LEVEL_UNDEFINED; + return NS_OK; +} + +NS_IMETHODIMP +PresShell::BidiStyleChangeReflow() +{ + // Have the root frame's style context remap its style + nsIFrame* rootFrame; + mFrameManager->GetRootFrame(&rootFrame); + + if (rootFrame) { + nsIStyleContext* rootStyleContext; + rootFrame->GetStyleContext(&rootStyleContext); + rootStyleContext->RemapStyle(mPresContext.get() ); + NS_RELEASE(rootStyleContext); + + ReconstructFrames(); + } + return NS_OK; +} +#endif // IBMBIDI //nsIViewObserver diff --git a/mozilla/layout/generic/nsBlockFrame.cpp b/mozilla/layout/generic/nsBlockFrame.cpp index c244cac0576..459675b04ba 100644 --- a/mozilla/layout/generic/nsBlockFrame.cpp +++ b/mozilla/layout/generic/nsBlockFrame.cpp @@ -58,6 +58,10 @@ #include "prenv.h" #include "plstr.h" +#ifdef IBMBIDI +#include "nsBidiPresUtils.h" +#endif // IBMBIDI + #include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLHtmlElement.h" @@ -1619,6 +1623,27 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, NS_BLOCK_MARGIN_ROOT & mState); if (eReflowReason_Resize != aReflowState.reason) { +#ifdef IBMBIDI + if (mLines) { + PRBool bidiEnabled; + aPresContext->BidiEnabled(bidiEnabled); + if (bidiEnabled) { + nsBidiPresUtils* bidiUtils; + aPresContext->GetBidiUtils(&bidiUtils); + if (bidiUtils) { + PRBool forceReflow; + nsresult rc = bidiUtils->Resolve(aPresContext, this, + mLines->mFirstChild, forceReflow); + if (NS_SUCCEEDED(rc) && forceReflow) { + // Mark everything dirty + for (nsLineBox* line = mLines; line; line = line->mNext) { + line->MarkDirty(); + } + } + } + } + } +#endif // IBMBIDI RenumberLists(aPresContext); } @@ -4247,6 +4272,15 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, if (aUpdateMaximumWidth) { availWidth = NS_UNCONSTRAINEDSIZE; } +#ifdef IBMBIDI + else { + nscoord rightEdge = aState.mReflowState.mRightEdge; + if ( (rightEdge != NS_UNCONSTRAINEDSIZE) + && (availWidth < rightEdge) ) { + availWidth = rightEdge; + } + } +#endif // IBMBIDI aLineLayout.BeginLineReflow(x, aState.mY, availWidth, availHeight, impactedByFloaters, @@ -4735,14 +4769,55 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, mStyleContext->GetStyleData(eStyleStruct_Text); PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign && !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine); +#ifdef IBMBIDI + nsRect bounds(aLine->mBounds); + + if (mRect.x) { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + + if (NS_STYLE_DIRECTION_RTL == display->mDirection) { + bounds.x += mRect.x; + } + } + PRBool successful = aLineLayout.HorizontalAlignFrames(bounds, allowJustify, + aState.GetFlag(BRS_SHRINKWRAPWIDTH)); + // XXX: not only bidi: right alignment can be broken after RelativePositionFrames!!! +#else PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify, aState.GetFlag(BRS_SHRINKWRAPWIDTH)); +#endif // IBMBIDI if (!successful) { // Mark the line dirty and then later once we've determined the width // we can do the horizontal alignment aLine->MarkDirty(); aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE); } +#ifdef IBMBIDI + else { + PRBool bidiEnabled; + aState.mPresContext->BidiEnabled(bidiEnabled); + + if (bidiEnabled) { + PRBool isVisual; + aState.mPresContext->IsVisualMode(isVisual); + if (!isVisual) { + nsBidiPresUtils* bidiUtils; + aState.mPresContext->GetBidiUtils(&bidiUtils); + + if (bidiUtils && bidiUtils->IsSuccessful() ) { + nsIFrame* nextInFlow = (aLine->mNext) + ? aLine->mNext->mFirstChild : nsnull; + + bidiUtils->ReorderFrames(aState.mPresContext, + aState.mReflowState.rendContext, + aLine->mFirstChild, nextInFlow, + aLine->GetChildCount() ); + } // bidiUtils + } // not visual mode + } // bidi enabled + } // successful +#endif // IBMBIDI nsRect combinedArea; aLineLayout.RelativePositionFrames(combinedArea); @@ -5263,6 +5338,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, mFloaters.AppendFrames(nsnull, aFrameList); return NS_OK; } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) {} +#endif // IBMBIDI else if (nsnull != aListName) { return NS_ERROR_INVALID_ARG; } @@ -5278,6 +5356,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, printf("\n"); #endif nsresult rv = AddFrames(aPresContext, aFrameList, aPrevFrame); +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5441,6 +5522,11 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, line = line->mNext; } } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) { + rv = DoRemoveFrame(aPresContext, aOldFrame); + } +#endif // IBMBIDI else if (nsnull != aListName) { rv = NS_ERROR_INVALID_ARG; } @@ -5448,6 +5534,9 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, rv = DoRemoveFrame(aPresContext, aOldFrame); } +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5628,12 +5717,21 @@ nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext* aPresContext, nsIFrame* nextInFlow; aChild->GetNextInFlow(&nextInFlow); NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow"); +#ifdef IBMBIDI + nsIFrame* nextBidi; + aChild->GetBidiProperty(aPresContext, nsLayoutAtoms::nextBidi, + (void**) &nextBidi); + if (nextBidi != nextInFlow) { +#endif // IBMBIDI nsBlockFrame* parent; nextInFlow->GetParent((nsIFrame**)&parent); NS_PRECONDITION(nsnull != parent, "next-in-flow with no parent"); NS_PRECONDITION(nsnull != parent->mLines, "next-in-flow with weird parent"); // NS_PRECONDITION(nsnull == parent->mOverflowLines, "parent with overflow"); parent->DoRemoveFrame(aPresContext, nextInFlow); +#ifdef IBMBIDI + } +#endif // IBMBIDI } //////////////////////////////////////////////////////////////////////// @@ -7206,9 +7304,21 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, mBullet->WillReflow(aState.mPresContext); mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status); +#ifdef IBMBIDI + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); +#endif // IBMBIDI // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line - nscoord x = - reflowState.mComputedMargin.right - aMetrics.width; + nscoord x = +#ifdef IBMBIDI + // For direction RTL: set x to the right margin for now. + // This value will be used to indent the bullet from the right most + // egde of the previous frame in nsLineLayout::HorizontalAlignFrames. + (NS_STYLE_DIRECTION_RTL == display->mDirection) + ? reflowState.mComputedMargin.right : +#endif // IBMBIDI + - reflowState.mComputedMargin.right - aMetrics.width; // Approximate the bullets position; vertical alignment will provide // the final vertical location. diff --git a/mozilla/layout/generic/nsBlockReflowState.cpp b/mozilla/layout/generic/nsBlockReflowState.cpp index c244cac0576..459675b04ba 100644 --- a/mozilla/layout/generic/nsBlockReflowState.cpp +++ b/mozilla/layout/generic/nsBlockReflowState.cpp @@ -58,6 +58,10 @@ #include "prenv.h" #include "plstr.h" +#ifdef IBMBIDI +#include "nsBidiPresUtils.h" +#endif // IBMBIDI + #include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLHtmlElement.h" @@ -1619,6 +1623,27 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, NS_BLOCK_MARGIN_ROOT & mState); if (eReflowReason_Resize != aReflowState.reason) { +#ifdef IBMBIDI + if (mLines) { + PRBool bidiEnabled; + aPresContext->BidiEnabled(bidiEnabled); + if (bidiEnabled) { + nsBidiPresUtils* bidiUtils; + aPresContext->GetBidiUtils(&bidiUtils); + if (bidiUtils) { + PRBool forceReflow; + nsresult rc = bidiUtils->Resolve(aPresContext, this, + mLines->mFirstChild, forceReflow); + if (NS_SUCCEEDED(rc) && forceReflow) { + // Mark everything dirty + for (nsLineBox* line = mLines; line; line = line->mNext) { + line->MarkDirty(); + } + } + } + } + } +#endif // IBMBIDI RenumberLists(aPresContext); } @@ -4247,6 +4272,15 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, if (aUpdateMaximumWidth) { availWidth = NS_UNCONSTRAINEDSIZE; } +#ifdef IBMBIDI + else { + nscoord rightEdge = aState.mReflowState.mRightEdge; + if ( (rightEdge != NS_UNCONSTRAINEDSIZE) + && (availWidth < rightEdge) ) { + availWidth = rightEdge; + } + } +#endif // IBMBIDI aLineLayout.BeginLineReflow(x, aState.mY, availWidth, availHeight, impactedByFloaters, @@ -4735,14 +4769,55 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, mStyleContext->GetStyleData(eStyleStruct_Text); PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign && !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine); +#ifdef IBMBIDI + nsRect bounds(aLine->mBounds); + + if (mRect.x) { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + + if (NS_STYLE_DIRECTION_RTL == display->mDirection) { + bounds.x += mRect.x; + } + } + PRBool successful = aLineLayout.HorizontalAlignFrames(bounds, allowJustify, + aState.GetFlag(BRS_SHRINKWRAPWIDTH)); + // XXX: not only bidi: right alignment can be broken after RelativePositionFrames!!! +#else PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify, aState.GetFlag(BRS_SHRINKWRAPWIDTH)); +#endif // IBMBIDI if (!successful) { // Mark the line dirty and then later once we've determined the width // we can do the horizontal alignment aLine->MarkDirty(); aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE); } +#ifdef IBMBIDI + else { + PRBool bidiEnabled; + aState.mPresContext->BidiEnabled(bidiEnabled); + + if (bidiEnabled) { + PRBool isVisual; + aState.mPresContext->IsVisualMode(isVisual); + if (!isVisual) { + nsBidiPresUtils* bidiUtils; + aState.mPresContext->GetBidiUtils(&bidiUtils); + + if (bidiUtils && bidiUtils->IsSuccessful() ) { + nsIFrame* nextInFlow = (aLine->mNext) + ? aLine->mNext->mFirstChild : nsnull; + + bidiUtils->ReorderFrames(aState.mPresContext, + aState.mReflowState.rendContext, + aLine->mFirstChild, nextInFlow, + aLine->GetChildCount() ); + } // bidiUtils + } // not visual mode + } // bidi enabled + } // successful +#endif // IBMBIDI nsRect combinedArea; aLineLayout.RelativePositionFrames(combinedArea); @@ -5263,6 +5338,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, mFloaters.AppendFrames(nsnull, aFrameList); return NS_OK; } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) {} +#endif // IBMBIDI else if (nsnull != aListName) { return NS_ERROR_INVALID_ARG; } @@ -5278,6 +5356,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, printf("\n"); #endif nsresult rv = AddFrames(aPresContext, aFrameList, aPrevFrame); +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5441,6 +5522,11 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, line = line->mNext; } } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) { + rv = DoRemoveFrame(aPresContext, aOldFrame); + } +#endif // IBMBIDI else if (nsnull != aListName) { rv = NS_ERROR_INVALID_ARG; } @@ -5448,6 +5534,9 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, rv = DoRemoveFrame(aPresContext, aOldFrame); } +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5628,12 +5717,21 @@ nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext* aPresContext, nsIFrame* nextInFlow; aChild->GetNextInFlow(&nextInFlow); NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow"); +#ifdef IBMBIDI + nsIFrame* nextBidi; + aChild->GetBidiProperty(aPresContext, nsLayoutAtoms::nextBidi, + (void**) &nextBidi); + if (nextBidi != nextInFlow) { +#endif // IBMBIDI nsBlockFrame* parent; nextInFlow->GetParent((nsIFrame**)&parent); NS_PRECONDITION(nsnull != parent, "next-in-flow with no parent"); NS_PRECONDITION(nsnull != parent->mLines, "next-in-flow with weird parent"); // NS_PRECONDITION(nsnull == parent->mOverflowLines, "parent with overflow"); parent->DoRemoveFrame(aPresContext, nextInFlow); +#ifdef IBMBIDI + } +#endif // IBMBIDI } //////////////////////////////////////////////////////////////////////// @@ -7206,9 +7304,21 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, mBullet->WillReflow(aState.mPresContext); mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status); +#ifdef IBMBIDI + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); +#endif // IBMBIDI // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line - nscoord x = - reflowState.mComputedMargin.right - aMetrics.width; + nscoord x = +#ifdef IBMBIDI + // For direction RTL: set x to the right margin for now. + // This value will be used to indent the bullet from the right most + // egde of the previous frame in nsLineLayout::HorizontalAlignFrames. + (NS_STYLE_DIRECTION_RTL == display->mDirection) + ? reflowState.mComputedMargin.right : +#endif // IBMBIDI + - reflowState.mComputedMargin.right - aMetrics.width; // Approximate the bullets position; vertical alignment will provide // the final vertical location. diff --git a/mozilla/layout/generic/nsBlockReflowState.h b/mozilla/layout/generic/nsBlockReflowState.h index c244cac0576..459675b04ba 100644 --- a/mozilla/layout/generic/nsBlockReflowState.h +++ b/mozilla/layout/generic/nsBlockReflowState.h @@ -58,6 +58,10 @@ #include "prenv.h" #include "plstr.h" +#ifdef IBMBIDI +#include "nsBidiPresUtils.h" +#endif // IBMBIDI + #include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLHtmlElement.h" @@ -1619,6 +1623,27 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, NS_BLOCK_MARGIN_ROOT & mState); if (eReflowReason_Resize != aReflowState.reason) { +#ifdef IBMBIDI + if (mLines) { + PRBool bidiEnabled; + aPresContext->BidiEnabled(bidiEnabled); + if (bidiEnabled) { + nsBidiPresUtils* bidiUtils; + aPresContext->GetBidiUtils(&bidiUtils); + if (bidiUtils) { + PRBool forceReflow; + nsresult rc = bidiUtils->Resolve(aPresContext, this, + mLines->mFirstChild, forceReflow); + if (NS_SUCCEEDED(rc) && forceReflow) { + // Mark everything dirty + for (nsLineBox* line = mLines; line; line = line->mNext) { + line->MarkDirty(); + } + } + } + } + } +#endif // IBMBIDI RenumberLists(aPresContext); } @@ -4247,6 +4272,15 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, if (aUpdateMaximumWidth) { availWidth = NS_UNCONSTRAINEDSIZE; } +#ifdef IBMBIDI + else { + nscoord rightEdge = aState.mReflowState.mRightEdge; + if ( (rightEdge != NS_UNCONSTRAINEDSIZE) + && (availWidth < rightEdge) ) { + availWidth = rightEdge; + } + } +#endif // IBMBIDI aLineLayout.BeginLineReflow(x, aState.mY, availWidth, availHeight, impactedByFloaters, @@ -4735,14 +4769,55 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, mStyleContext->GetStyleData(eStyleStruct_Text); PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign && !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine); +#ifdef IBMBIDI + nsRect bounds(aLine->mBounds); + + if (mRect.x) { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + + if (NS_STYLE_DIRECTION_RTL == display->mDirection) { + bounds.x += mRect.x; + } + } + PRBool successful = aLineLayout.HorizontalAlignFrames(bounds, allowJustify, + aState.GetFlag(BRS_SHRINKWRAPWIDTH)); + // XXX: not only bidi: right alignment can be broken after RelativePositionFrames!!! +#else PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify, aState.GetFlag(BRS_SHRINKWRAPWIDTH)); +#endif // IBMBIDI if (!successful) { // Mark the line dirty and then later once we've determined the width // we can do the horizontal alignment aLine->MarkDirty(); aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE); } +#ifdef IBMBIDI + else { + PRBool bidiEnabled; + aState.mPresContext->BidiEnabled(bidiEnabled); + + if (bidiEnabled) { + PRBool isVisual; + aState.mPresContext->IsVisualMode(isVisual); + if (!isVisual) { + nsBidiPresUtils* bidiUtils; + aState.mPresContext->GetBidiUtils(&bidiUtils); + + if (bidiUtils && bidiUtils->IsSuccessful() ) { + nsIFrame* nextInFlow = (aLine->mNext) + ? aLine->mNext->mFirstChild : nsnull; + + bidiUtils->ReorderFrames(aState.mPresContext, + aState.mReflowState.rendContext, + aLine->mFirstChild, nextInFlow, + aLine->GetChildCount() ); + } // bidiUtils + } // not visual mode + } // bidi enabled + } // successful +#endif // IBMBIDI nsRect combinedArea; aLineLayout.RelativePositionFrames(combinedArea); @@ -5263,6 +5338,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, mFloaters.AppendFrames(nsnull, aFrameList); return NS_OK; } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) {} +#endif // IBMBIDI else if (nsnull != aListName) { return NS_ERROR_INVALID_ARG; } @@ -5278,6 +5356,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, printf("\n"); #endif nsresult rv = AddFrames(aPresContext, aFrameList, aPrevFrame); +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5441,6 +5522,11 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, line = line->mNext; } } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) { + rv = DoRemoveFrame(aPresContext, aOldFrame); + } +#endif // IBMBIDI else if (nsnull != aListName) { rv = NS_ERROR_INVALID_ARG; } @@ -5448,6 +5534,9 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, rv = DoRemoveFrame(aPresContext, aOldFrame); } +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5628,12 +5717,21 @@ nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext* aPresContext, nsIFrame* nextInFlow; aChild->GetNextInFlow(&nextInFlow); NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow"); +#ifdef IBMBIDI + nsIFrame* nextBidi; + aChild->GetBidiProperty(aPresContext, nsLayoutAtoms::nextBidi, + (void**) &nextBidi); + if (nextBidi != nextInFlow) { +#endif // IBMBIDI nsBlockFrame* parent; nextInFlow->GetParent((nsIFrame**)&parent); NS_PRECONDITION(nsnull != parent, "next-in-flow with no parent"); NS_PRECONDITION(nsnull != parent->mLines, "next-in-flow with weird parent"); // NS_PRECONDITION(nsnull == parent->mOverflowLines, "parent with overflow"); parent->DoRemoveFrame(aPresContext, nextInFlow); +#ifdef IBMBIDI + } +#endif // IBMBIDI } //////////////////////////////////////////////////////////////////////// @@ -7206,9 +7304,21 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, mBullet->WillReflow(aState.mPresContext); mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status); +#ifdef IBMBIDI + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); +#endif // IBMBIDI // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line - nscoord x = - reflowState.mComputedMargin.right - aMetrics.width; + nscoord x = +#ifdef IBMBIDI + // For direction RTL: set x to the right margin for now. + // This value will be used to indent the bullet from the right most + // egde of the previous frame in nsLineLayout::HorizontalAlignFrames. + (NS_STYLE_DIRECTION_RTL == display->mDirection) + ? reflowState.mComputedMargin.right : +#endif // IBMBIDI + - reflowState.mComputedMargin.right - aMetrics.width; // Approximate the bullets position; vertical alignment will provide // the final vertical location. diff --git a/mozilla/layout/generic/nsBulletFrame.cpp b/mozilla/layout/generic/nsBulletFrame.cpp index 099372f554e..ad864fa323e 100644 --- a/mozilla/layout/generic/nsBulletFrame.cpp +++ b/mozilla/layout/generic/nsBulletFrame.cpp @@ -37,6 +37,9 @@ #include "nsLayoutAtoms.h" #include "prprf.h" #include "nsIImage.h" +#ifdef IBMBIDI +#include "nsBidiPresUtils.h" +#endif // IBMBIDI nsBulletFrame::nsBulletFrame() { @@ -145,6 +148,14 @@ nsBulletFrame::Paint(nsIPresContext* aCX, nsCOMPtr fm; aRenderingContext.SetColor(myColor->mColor); +#ifdef IBMBIDI + nsCharType charType = eCharType_LeftToRight; + PRUint8 level = 0; + PRBool isBidiSystem = PR_FALSE; + const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); + PRUint32 hints = 0; +#endif // IBMBIDI + nsAutoString text; switch (listStyleType) { case NS_STYLE_LIST_STYLE_NONE: @@ -173,6 +184,33 @@ nsBulletFrame::Paint(nsIPresContext* aCX, case NS_STYLE_LIST_STYLE_DECIMAL: case NS_STYLE_LIST_STYLE_OLD_DECIMAL: case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO: +#ifdef IBMBIDI + GetListItemText(aCX, *myList, text); + charType = eCharType_EuropeanNumber; + break; + + case NS_STYLE_LIST_STYLE_ARABIC_INDIC: + GetListItemText(aCX, *myList, text); + charType = eCharType_ArabicNumber; + break; + + case NS_STYLE_LIST_STYLE_HEBREW: + aRenderingContext.GetHints(hints); + isBidiSystem = (hints & NS_RENDERING_HINT_BIDI_REORDERING); + if (!isBidiSystem) { + charType = eCharType_RightToLeft; + level = 1; + GetListItemText(aCX, *myList, text); + + if (NS_STYLE_DIRECTION_RTL == disp->mDirection) { + nsStr::Delete(text, 0, 1); + text.AppendWithConversion("."); + } + break; + } + // else fall through +#endif // IBMBIDI + case NS_STYLE_LIST_STYLE_LOWER_ROMAN: case NS_STYLE_LIST_STYLE_UPPER_ROMAN: case NS_STYLE_LIST_STYLE_LOWER_ALPHA: @@ -182,7 +220,9 @@ nsBulletFrame::Paint(nsIPresContext* aCX, case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA: case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA: case NS_STYLE_LIST_STYLE_LOWER_GREEK: +#ifndef IBMBIDI case NS_STYLE_LIST_STYLE_HEBREW: +#endif case NS_STYLE_LIST_STYLE_ARMENIAN: case NS_STYLE_LIST_STYLE_GEORGIAN: case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC: @@ -198,7 +238,9 @@ nsBulletFrame::Paint(nsIPresContext* aCX, case NS_STYLE_LIST_STYLE_JAPANESE_FORMAL: case NS_STYLE_LIST_STYLE_CJK_HEAVENLY_STEM: case NS_STYLE_LIST_STYLE_CJK_EARTHLY_BRANCH: +#ifndef IBMBIDI case NS_STYLE_LIST_STYLE_ARABIC_INDIC: +#endif case NS_STYLE_LIST_STYLE_PERSIAN: case NS_STYLE_LIST_STYLE_URDU: case NS_STYLE_LIST_STYLE_DEVANAGARI: @@ -220,6 +262,31 @@ nsBulletFrame::Paint(nsIPresContext* aCX, aRenderingContext.DrawString(text, mPadding.left, mPadding.top); break; } +#ifdef IBMBIDI + if (charType != eCharType_LeftToRight) { + aCX->GetMetricsFor(myFont->mFont, getter_AddRefs(fm)); + aRenderingContext.SetFont(fm); + + nsBidiPresUtils* bidiUtils; + aCX->GetBidiUtils(&bidiUtils); + if (bidiUtils) { + const PRUnichar* buffer = text.GetUnicode(); + PRInt32 textLength = text.Length(); + if (eCharType_RightToLeft == charType) { + bidiUtils->FormatUnicodeText(aCX, (PRUnichar*)buffer, textLength, + charType, level, PR_FALSE); + } + else { +//Mohamed + aRenderingContext.GetHints(hints); + isBidiSystem = (hints & NS_RENDERING_HINT_ARABIC_SHAPING); + bidiUtils->FormatUnicodeText(aCX, (PRUnichar*)buffer, textLength, + charType, level, isBidiSystem);//Mohamed + } + } + aRenderingContext.DrawString(text, mPadding.left, mPadding.top); + } +#endif // IBMBIDI } return NS_OK; } @@ -590,12 +657,21 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) { PRBool outputSep = PR_FALSE; PRUnichar buf[NUM_BUF_SIZE]; +#ifdef IBMBIDI + // Changes: 1) don't reverse the text; 2) don't insert geresh/gershayim. + PRInt32 idx = 0; +#else PRInt32 idx = NUM_BUF_SIZE; +#endif // IBMBIDI PRUnichar digit; do { PRInt32 n3 = ordinal % 1000; if(outputSep) +#ifdef IBMBIDI + buf[idx++] = HEBREW_THROSAND_SEP; // output thousand seperator +#else buf[--idx] = HEBREW_THROSAND_SEP; // output thousand seperator +#endif // IBMBIDI outputSep = ( n3 > 0); // request to output thousand seperator next time. PRInt32 d = 0; // we need to keep track of digit got output per 3 digits, @@ -611,10 +687,17 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) digit = gHebrewDigit[(n1/100)-1+18]; if( n3 > 0) { +#ifdef IBMBIDI + buf[idx++] = digit; +#else buf[--idx] = digit; +#endif // IBMBIDI d++; } else { // if this is the last digit +#ifdef IBMBIDI + buf[idx++] = digit; +#else if (d > 0) { buf[--idx] = HEBREW_GERSHAYIM; @@ -623,6 +706,7 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) buf[--idx] = digit; buf[--idx] = HEBREW_GERESH; } // if +#endif // IBMBIDI } // if } else { n1 -= 100; @@ -648,10 +732,17 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) n3 -= n2; if( n3 > 0) { +#ifdef IBMBIDI + buf[idx++] = digit; +#else buf[--idx] = digit; +#endif // IBMBIDI d++; } else { // if this is the last digit +#ifdef IBMBIDI + buf[idx++] = digit; +#else if (d > 0) { buf[--idx] = HEBREW_GERSHAYIM; @@ -660,6 +751,7 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) buf[--idx] = digit; buf[--idx] = HEBREW_GERESH; } // if +#endif // IBMBIDI } // if } // if @@ -668,6 +760,9 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) { digit = gHebrewDigit[n3-1]; // must be the last digit +#ifdef IBMBIDI + buf[idx++] = digit; +#else if (d > 0) { buf[--idx] = HEBREW_GERSHAYIM; @@ -676,10 +771,15 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) buf[--idx] = digit; buf[--idx] = HEBREW_GERESH; } // if +#endif // IBMBIDI } // if ordinal /= 1000; } while (ordinal >= 1); +#ifdef IBMBIDI + result.Append(buf, idx); +#else result.Append(buf+idx,NUM_BUF_SIZE-idx); +#endif // IBMBIDI } @@ -747,6 +847,14 @@ nsBulletFrame::GetListItemText(nsIPresContext* aCX, const nsStyleList& aListStyle, nsString& result) { +#ifdef IBMBIDI + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + if (NS_STYLE_DIRECTION_RTL == display->mDirection) { + result.AppendWithConversion("."); + } +#endif // IBMBIDI + switch (aListStyle.mListStyleType) { case NS_STYLE_LIST_STYLE_DECIMAL: case NS_STYLE_LIST_STYLE_OLD_DECIMAL: @@ -904,6 +1012,9 @@ nsBulletFrame::GetListItemText(nsIPresContext* aCX, CharListToText(mOrdinal, result, gCJKEarthlyBranchChars, CJK_EARTHLY_BRANCH_CHARS_SIZE); break; } +#ifdef IBMBIDI + if (NS_STYLE_DIRECTION_RTL != display->mDirection) +#endif // IBMBIDI result.AppendWithConversion("."); } diff --git a/mozilla/layout/generic/nsContainerFrame.cpp b/mozilla/layout/generic/nsContainerFrame.cpp index f14b4ef8cbf..3bf69ab29b3 100644 --- a/mozilla/layout/generic/nsContainerFrame.cpp +++ b/mozilla/layout/generic/nsContainerFrame.cpp @@ -851,6 +851,15 @@ nsContainerFrame::DeleteChildsNextInFlow(nsIPresContext* aPresContext, parent->DeleteChildsNextInFlow(aPresContext, nextInFlow); } +#ifdef IBMBIDI + nsIFrame* nextBidi; + aChild->GetBidiProperty(aPresContext, nsLayoutAtoms::nextBidi, + (void**) &nextBidi); + if (nextBidi == nextInFlow) { + return; + } +#endif // IBMBIDI + // Disconnect the next-in-flow from the flow list nsSplittableFrame::BreakFromPrevFlow(nextInFlow); diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index 6924122b50d..93d608990ed 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -2633,6 +2633,18 @@ nsFrame::SetSelected(nsIPresContext* aPresContext, nsIDOMRange *aRange, PRBool a } } #endif +#ifdef IBMBIDI + PRInt32 start, end; + nsIFrame* frame; + GetNextSibling(&frame); + if (frame){ + GetFirstLeaf(aPresContext, &frame); + GetOffsets(start, end); + if (start && end) { + frame->SetSelected(aPresContext, aRange, aSelected, aSpread); + } + } +#endif // IBMBIDI return NS_OK; } @@ -2776,7 +2788,13 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext, nsIView * view; //used for call of get offset from view aBlockFrame->GetOffsetFromView(aPresContext, offset,&view); nscoord newDesiredX = aPos->mDesiredX - offset.x;//get desired x into blockframe coordinates! +#ifdef IBMBIDI + PRBool bidiEnabled; + aPresContext->BidiEnabled(bidiEnabled); + result = it->FindFrameAt(searchingLine, newDesiredX, bidiEnabled, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame); +#else result = it->FindFrameAt(searchingLine, newDesiredX, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame); +#endif // IBMBIDI if(NS_FAILED(result)) continue; } @@ -3463,28 +3481,63 @@ nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct PRInt32 lineFrameCount; PRUint32 lineFlags; - result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect, - &lineFlags); +#ifdef IBMBIDI + /* Check whether the visual and logical order of the frames are different */ + PRBool lineIsReordered = PR_FALSE; + nsIFrame *firstVisual; + nsIFrame *lastVisual; + PRBool lineIsRTL; + PRBool lineJump = PR_FALSE; + + it->GetDirection(&lineIsRTL); + result = it->CheckLineOrder(thisLine, &lineIsReordered, &firstVisual, &lastVisual); if (NS_FAILED(result)) return result; - lastFrame = firstFrame; - for (;lineFrameCount > 1;lineFrameCount --){ - result = lastFrame->GetNextSibling(&lastFrame); - if (NS_FAILED(result)){ - NS_ASSERTION(0,"should not be reached nsFrame\n"); - return NS_ERROR_FAILURE; + if (lineIsReordered) { + firstFrame = firstVisual; + lastFrame = lastVisual; + } + else +#endif + { + result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect, + &lineFlags); + if (NS_FAILED(result)) + return result; + + lastFrame = firstFrame; + for (;lineFrameCount > 1;lineFrameCount --){ + result = lastFrame->GetNextSibling(&lastFrame); + if (NS_FAILED(result)){ + NS_ASSERTION(0,"should not be reached nsFrame\n"); + return NS_ERROR_FAILURE; + } } } - + GetFirstLeaf(aPresContext, &firstFrame); GetLastLeaf(aPresContext, &lastFrame); //END LINE DATA CODE - if ((aPos->mDirection == eDirNext && lastFrame == this) - ||(aPos->mDirection == eDirPrevious && firstFrame == this)) + if +#ifndef IBMBIDI // jumping lines in RTL paragraphs + ((aPos->mDirection == eDirNext && lastFrame == this) + ||(aPos->mDirection == eDirPrevious && firstFrame == this)) +#else + (((lineIsRTL) && + ((aPos->mDirection == eDirNext && firstFrame == this) + ||(aPos->mDirection == eDirPrevious && lastFrame == this))) + || + ((!lineIsRTL) && + ((aPos->mDirection == eDirNext && lastFrame == this) + ||(aPos->mDirection == eDirPrevious && firstFrame == this)))) +#endif { if (aPos->mJumpLines != PR_TRUE) return NS_ERROR_FAILURE;//we are done. cannot jump lines +#ifdef IBMBIDI + lineJump = PR_TRUE; +#endif if (aPos->mAmount != eSelectWord) { aPos->mPreferLeft = (PRBool)!(aPos->mPreferLeft);//drift to other side @@ -3504,15 +3557,35 @@ nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct if (aPos->mAmount == eSelectDir) aPos->mAmount = eSelectNoAmount;//just get to next frame. nsCOMPtr frameTraversal; +#ifdef IBMBIDI + result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal), + (lineIsReordered) ? VISUAL : LEAF, + aPresContext, + (lineJump && lineIsRTL) + ? (aPos->mDirection == eDirNext) ? lastFrame : firstFrame + : this); +#else result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),LEAF, aPresContext, this); +#endif if (NS_FAILED(result)) return result; nsISupports *isupports = nsnull; - if (aPos->mDirection == eDirNext) - result = frameTraversal->Next(); - else - result = frameTraversal->Prev(); - +#ifdef IBMBIDI + nsIFrame *newFrame; + nsRect testRect; + while (testRect.IsEmpty()) { + if (lineIsRTL && lineJump) + if (aPos->mDirection == eDirPrevious) + result = frameTraversal->Next(); + else + result = frameTraversal->Prev(); + else +#endif + if (aPos->mDirection == eDirNext) + result = frameTraversal->Next(); + else + result = frameTraversal->Prev(); + if (NS_FAILED(result)) return result; result = frameTraversal->CurrentItem(&isupports); @@ -3522,7 +3595,80 @@ nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct return NS_ERROR_NULL_POINTER; //we must CAST here to an nsIFrame. nsIFrame doesnt really follow the rules //for speed reasons +#ifndef IBMBIDI nsIFrame *newFrame = (nsIFrame *)isupports; +#else + newFrame = (nsIFrame *)isupports; + newFrame->GetRect(testRect); + if (testRect.IsEmpty()) { // this must be a non-renderable frame creatd at the end of the line by Bidi reordering + lineJump = PR_TRUE; + aPos->mAmount = eSelectNoAmount; + } + } + PRBool newLineIsRTL = PR_FALSE; + if (lineJump) { + blockFrame = newFrame; + nsresult result = NS_ERROR_FAILURE; + while (NS_FAILED(result) && blockFrame) + { + thisBlock = blockFrame; + result = blockFrame->GetParent(&blockFrame); + if (NS_SUCCEEDED(result) && blockFrame){ + result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it)); + } + else + blockFrame = nsnull; + } + if (!blockFrame || !it) + return NS_ERROR_FAILURE; + result = it->FindLineContaining(thisBlock, &thisLine); + if (NS_FAILED(result)) + return result; + it->GetDirection(&newLineIsRTL); + + result = it->CheckLineOrder(thisLine, &lineIsReordered, &firstVisual, &lastVisual); + if (NS_FAILED(result)) + return result; + + if (lineIsReordered) + { + firstFrame = firstVisual; + lastFrame = lastVisual; + } + else + { + result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect, + &lineFlags); + if (NS_FAILED(result)) + return result; + + lastFrame = firstFrame; + for (;lineFrameCount > 1;lineFrameCount --){ + result = lastFrame->GetNextSibling(&lastFrame); + if (NS_FAILED(result)){ + NS_ASSERTION(0,"should not be reached nsFrame\n"); + return NS_ERROR_FAILURE; + } + } + } + + GetFirstLeaf(aPresContext, &firstFrame); + GetLastLeaf(aPresContext, &lastFrame); + + if (newLineIsRTL) { + if (aPos->mDirection == eDirPrevious) + newFrame = firstFrame; + else + newFrame = lastFrame; + } + else { + if (aPos->mDirection == eDirNext) + newFrame = firstFrame; + else + newFrame = lastFrame; + } + } +#endif // IBMBIDI PRBool selectable; newFrame->IsSelectable(&selectable, nsnull); if (!selectable) @@ -3531,6 +3677,18 @@ nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct aPos->mStartOffset = 0; else aPos->mStartOffset = -1; +#ifdef IBMBIDI + long oldLevel, newLevel, baseLevel; + GetBidiProperty(aPresContext, nsLayoutAtoms::embeddingLevel, (void**)&oldLevel); + newFrame->GetBidiProperty(aPresContext, nsLayoutAtoms::embeddingLevel, (void**)&newLevel); + newFrame->GetBidiProperty(aPresContext, nsLayoutAtoms::baseLevel, (void**)&baseLevel); + if (newLevel & 1) // The new frame is RTL, go to the other end + aPos->mStartOffset = -1 - aPos->mStartOffset; + + if ((aPos->mAmount == eSelectNoAmount) && ((newLevel & 1) != (oldLevel & 1))) { + aPos->mPreferLeft = !(aPos->mPreferLeft); + } +#endif aPos->mResultFrame = newFrame; return NS_OK; } @@ -3771,6 +3929,63 @@ nsFrame::IsMouseCaptured(nsIPresContext* aPresContext) return PR_FALSE; } +#ifdef IBMBIDI +/** + * retrieve Bidi property of this frame + * @lina 5/1/2000 + */ + +nsresult nsFrame::GetBidiProperty(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + void** aPropertyValue, + long aSize) const +{ + if (!aPropertyValue || !aPropertyName) { + return NS_ERROR_NULL_POINTER; + } + if ( (aSize < 1) || (aSize > sizeof(void*) ) ) { + return NS_ERROR_ILLEGAL_VALUE; + } + + nsCRT::zero(aPropertyValue, aSize); + void* val = nsnull; + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell) ); + + if (presShell) { + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager) ); + + if (frameManager) { + frameManager->GetFrameProperty( (nsIFrame*)this, aPropertyName, 0, &val); + if (val) { + nsCRT::memcpy(aPropertyValue, &val, aSize); + } + } + } + return NS_OK; +} + +nsresult nsFrame::SetBidiProperty(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + void* aPropertyValue) const +{ + nsresult rv = NS_ERROR_FAILURE; + + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell) ); + if (shell) { + nsCOMPtr frameManager; + shell->GetFrameManager(getter_AddRefs(frameManager) ); + if (frameManager) { + rv = frameManager->SetFrameProperty( (nsIFrame*) this, aPropertyName, aPropertyValue, nsnull); + } + } + return rv; +} +#endif // IBMBIDI + #ifdef NS_DEBUG static void GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize, diff --git a/mozilla/layout/generic/nsFrame.h b/mozilla/layout/generic/nsFrame.h index 847400cb4fe..a1d592561c0 100644 --- a/mozilla/layout/generic/nsFrame.h +++ b/mozilla/layout/generic/nsFrame.h @@ -368,6 +368,15 @@ public: //Mouse Capturing code used by the frames to tell the view to capture all the following events NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents); PRBool IsMouseCaptured(nsIPresContext* aPresContext); +#ifdef IBMBIDI + NS_IMETHOD GetBidiProperty(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + void** aPropertyValue, + long aSize = sizeof(void*) ) const; + NS_IMETHOD SetBidiProperty(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + void* aPropertyValue) const ; +#endif // IBMBIDI #ifdef NS_DEBUG /** diff --git a/mozilla/layout/generic/nsHTMLReflowState.cpp b/mozilla/layout/generic/nsHTMLReflowState.cpp index ead2b06cfe4..b160002cac3 100644 --- a/mozilla/layout/generic/nsHTMLReflowState.cpp +++ b/mozilla/layout/generic/nsHTMLReflowState.cpp @@ -66,6 +66,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, mLineLayout = nsnull; isTopOfPage = PR_FALSE; Init(aPresContext); +#ifdef IBMBIDI + mRightEdge = NS_UNCONSTRAINEDSIZE; +#endif } // Initialize a root reflow state for an incremental @@ -90,6 +93,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, mLineLayout = nsnull; isTopOfPage = PR_FALSE; Init(aPresContext); +#ifdef IBMBIDI + mRightEdge = NS_UNCONSTRAINEDSIZE; +#endif // IBMBIDI } // Initialize a reflow state for a child frames reflow. Some state @@ -117,6 +123,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, isTopOfPage = aParentReflowState.isTopOfPage; Init(aPresContext); + +#ifdef IBMBIDI + mRightEdge = aParentReflowState.mRightEdge; +#endif // IBMBIDI } // Same as the previous except that the reason is taken from the @@ -140,6 +150,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, isTopOfPage = aParentReflowState.isTopOfPage; Init(aPresContext); + +#ifdef IBMBIDI + mRightEdge = aParentReflowState.mRightEdge; +#endif // IBMBIDI } // Version that species the containing block width and height @@ -164,6 +178,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, isTopOfPage = aParentReflowState.isTopOfPage; Init(aPresContext, aContainingBlockWidth, aContainingBlockHeight); + +#ifdef IBMBIDI + mRightEdge = aParentReflowState.mRightEdge; +#endif // IBMBIDI } void @@ -1833,6 +1851,18 @@ nsHTMLReflowState::ComputeBlockBoxData(nsIPresContext* aPresContext, AdjustComputedWidth(); +#ifdef IBMBIDI + // See what edge the width applies to (the default is the content + // edge) + if (mComputedWidth != NS_UNCONSTRAINEDSIZE) { + if (mStylePosition->mBoxSizing == NS_STYLE_BOX_SIZING_PADDING) { + mComputedWidth -= mComputedPadding.left + mComputedPadding.right; + } else if (mStylePosition->mBoxSizing == NS_STYLE_BOX_SIZING_BORDER) { + mComputedWidth -= mComputedBorderPadding.left + mComputedBorderPadding.right; + } + } +#endif // IBMBIDI + // Now that we have the computed-width, compute the side margins CalculateBlockSideMargins(cbrs->mComputedWidth, mComputedWidth); } diff --git a/mozilla/layout/generic/nsInlineFrame.cpp b/mozilla/layout/generic/nsInlineFrame.cpp index 4b624ed1cc3..ff2b43fbf47 100644 --- a/mozilla/layout/generic/nsInlineFrame.cpp +++ b/mozilla/layout/generic/nsInlineFrame.cpp @@ -122,12 +122,18 @@ nsInlineFrame::InsertFrames(nsIPresContext* aPresContext, nsIFrame* aFrameList) { if (nsnull != aListName) { +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif return NS_ERROR_INVALID_ARG; } if (aFrameList) { // Insert frames after aPrevFrame mFrames.InsertFrames(this, aPrevFrame, aFrameList); +#ifdef IBMBIDI + if (nsnull == aListName) +#endif // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); } @@ -141,6 +147,9 @@ nsInlineFrame::RemoveFrame(nsIPresContext* aPresContext, nsIFrame* aOldFrame) { if (nsnull != aListName) { +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) +#endif return NS_ERROR_INVALID_ARG; } @@ -151,6 +160,9 @@ nsInlineFrame::RemoveFrame(nsIPresContext* aPresContext, aOldFrame->GetParent(&oldFrameParent); nsInlineFrame* parent = (nsInlineFrame*) oldFrameParent; while (nsnull != aOldFrame) { +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) { +#endif // If the frame being removed has zero size then don't bother // generating a reflow command, otherwise make sure we do. nsRect bbox; @@ -158,6 +170,9 @@ nsInlineFrame::RemoveFrame(nsIPresContext* aPresContext, if (bbox.width || bbox.height) { generateReflowCommand = PR_TRUE; } +#ifdef IBMBIDI + } +#endif // When the parent is an inline frame we have a simple task - just // remove the frame from its parents list and generate a reflow diff --git a/mozilla/layout/generic/nsLineBox.cpp b/mozilla/layout/generic/nsLineBox.cpp index 02d3c385924..8ed742dcafb 100644 --- a/mozilla/layout/generic/nsLineBox.cpp +++ b/mozilla/layout/generic/nsLineBox.cpp @@ -653,9 +653,125 @@ nsLineIterator::FindLineAt(nscoord aY, return NS_OK; } +#ifdef IBMBIDI +NS_IMETHODIMP +nsLineIterator::CheckLineOrder(PRInt32 aLine, + PRBool *aIsReordered, + nsIFrame **aFirstVisual, + nsIFrame **aLastVisual) +{ + nsRect checkRect; + PRInt32 currentLine, saveLine, testLine; + nscoord saveX; + nsIFrame *checkFrame; + nsIFrame *firstFrame; + nsIFrame *leftmostFrame; + nsIFrame *rightmostFrame; + nscoord minX, maxX; + PRInt32 lineFrameCount; + PRUint32 lineFlags; + + nsresult result; + + // an RTL paragraph is always considered as reordered + // in an LTR paragraph, find out by examining the coordinates of each frame in the line + if (mRightToLeft) + *aIsReordered = PR_TRUE; + else { + *aIsReordered = PR_FALSE; + + // Check the preceding and following line, since we might be moving into them + for (currentLine = PR_MAX(0, aLine-1); currentLine < aLine+1; currentLine++) { + + nsLineBox* line = mLines[currentLine]; + if (!line) + break; + + checkFrame = line->mFirstChild; + + checkFrame->GetRect(checkRect); + result = FindLineContaining(checkFrame, &saveLine); + if (NS_FAILED(result)) + return result; + saveX = checkRect.x; + lineFrameCount = line->GetChildCount(); + + for (; checkFrame; result = checkFrame->GetNextSibling(&checkFrame)) { + if (NS_FAILED(result)) + break; + result = FindLineContaining(checkFrame, &testLine); + if (NS_FAILED(result)) + return result; + if (testLine != saveLine) { + *aIsReordered = PR_TRUE; + break; + } + + checkFrame->GetRect(checkRect); + // If the origin of any frame is less than the previous frame, the line is reordered + if (checkRect.x < saveX) { + *aIsReordered = PR_TRUE; + break; + } + saveX = checkRect.x; + lineFrameCount--; + if (0 == lineFrameCount) + break; + } + if (*aIsReordered) + break; + } + } + + // If the line is reordered, identify the first and last frames on the line + if (*aIsReordered) { + nsRect nonUsedRect; + result = GetLine(aLine, &firstFrame, &lineFrameCount, nonUsedRect, &lineFlags); + if (NS_FAILED(result)) + return result; + + leftmostFrame = rightmostFrame = firstFrame; + firstFrame->GetRect(checkRect); + maxX = checkRect.x; + minX = checkRect.x; + + for (;lineFrameCount > 1;lineFrameCount--) { + result = firstFrame->GetNextSibling(&firstFrame); + + if (NS_FAILED(result)){ + NS_ASSERTION(0,"should not be reached nsLineBox\n"); + return NS_ERROR_FAILURE; + } + + firstFrame->GetRect(checkRect); + if (checkRect.x > maxX) { + maxX = checkRect.x; + rightmostFrame = firstFrame; + } + if (checkRect.x < minX) { + minX = checkRect.x; + leftmostFrame = firstFrame; + } + } + if (mRightToLeft) { + *aFirstVisual = rightmostFrame; + *aLastVisual = leftmostFrame; + } + else { + *aFirstVisual = leftmostFrame; + *aLastVisual = rightmostFrame; + } + } + return result; +} +#endif // IBMBIDI + NS_IMETHODIMP nsLineIterator::FindFrameAt(PRInt32 aLineNumber, nscoord aX, +#ifdef IBMBIDI + PRBool aCouldBeReordered, +#endif // IBMBIDI nsIFrame** aFrameFound, PRBool* aXIsBeforeFirstFrame, PRBool* aXIsAfterLastFrame) @@ -709,13 +825,51 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber, // when checking. *aXIsBeforeFirstFrame = PR_FALSE; *aXIsAfterLastFrame = PR_FALSE; +#ifdef IBMBIDI + PRBool isReordered = PR_FALSE; + nsIFrame *firstVisual, *lastVisual; + if (aCouldBeReordered) + CheckLineOrder(aLineNumber, &isReordered, &firstVisual, &lastVisual); +#endif nsRect r1, r2; nsIFrame* frame = line->mFirstChild; +#ifdef IBMBIDI + if (isReordered) + frame = firstVisual; +#endif // IBMBIDI PRInt32 n = line->GetChildCount(); if (mRightToLeft) { while (--n >= 0) { nsIFrame* nextFrame; - frame->GetNextSibling(&nextFrame); +#ifdef IBMBIDI + if (isReordered) { + nscoord maxX, limX; + PRInt32 testLine; + nsRect tempRect; + nsIFrame* tempFrame; + + maxX = -0x7fffffff; + frame->GetRect(tempRect); + + limX = tempRect.x; + tempFrame = line->mFirstChild; + nextFrame = nsnull; + + while (tempFrame) { + if (NS_SUCCEEDED(FindLineContaining(tempFrame, &testLine)) + && testLine == aLineNumber) { + tempFrame->GetRect(tempRect); + if (tempRect.x > maxX && tempRect.x < limX) { // we are looking for the highest value less than the current one + maxX = tempRect.x; + nextFrame = tempFrame; + } + } + tempFrame->GetNextSibling(&tempFrame); + } + } + else +#endif // IBMBIDI + frame->GetNextSibling(&nextFrame); frame->GetRect(r1); if (aX > r1.x) { break; @@ -740,6 +894,34 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber, else { while (--n >= 0) { nsIFrame* nextFrame; +#ifdef IBMBIDI + if (isReordered) { + nsRect tempRect; + nsIFrame* tempFrame; + PRInt64 minX, limX; + PRInt32 testLine; + + minX = 0x7fffffff; + frame->GetRect(tempRect); + + limX = tempRect.x; + tempFrame = line->mFirstChild; + nextFrame = nsnull; + + while (tempFrame) { + if (NS_SUCCEEDED(FindLineContaining(tempFrame, &testLine)) + && testLine == aLineNumber) { + tempFrame->GetRect(tempRect); + if (tempRect.x < minX && tempRect.x > limX) { // we are looking for the lowest value greater than the current one + minX = tempRect.x; + nextFrame = tempFrame; + } + } + tempFrame->GetNextSibling(&tempFrame); + } + } + else +#endif // IBMBIDI frame->GetNextSibling(&nextFrame); frame->GetRect(r1); if (aX < r1.XMost()) { diff --git a/mozilla/layout/generic/nsLineBox.h b/mozilla/layout/generic/nsLineBox.h index 11f27d94a69..7bba265a2eb 100644 --- a/mozilla/layout/generic/nsLineBox.h +++ b/mozilla/layout/generic/nsLineBox.h @@ -412,12 +412,20 @@ public: PRInt32* aLineNumberResult); NS_IMETHOD FindFrameAt(PRInt32 aLineNumber, nscoord aX, +#ifdef IBMBIDI + PRBool aCouldBeReordered, +#endif nsIFrame** aFrameFound, PRBool* aXIsBeforeFirstFrame, PRBool* aXIsAfterLastFrame); NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, PRInt32 aLineNumber); - +#ifdef IBMBIDI + NS_IMETHOD CheckLineOrder(PRInt32 aLine, + PRBool *aIsReordered, + nsIFrame **aFirstVisual, + nsIFrame **aLastVisual); +#endif nsresult Init(nsLineBox* aLines, PRBool aRightToLeft); protected: diff --git a/mozilla/layout/html/base/src/nsBlockFrame.cpp b/mozilla/layout/html/base/src/nsBlockFrame.cpp index c244cac0576..459675b04ba 100644 --- a/mozilla/layout/html/base/src/nsBlockFrame.cpp +++ b/mozilla/layout/html/base/src/nsBlockFrame.cpp @@ -58,6 +58,10 @@ #include "prenv.h" #include "plstr.h" +#ifdef IBMBIDI +#include "nsBidiPresUtils.h" +#endif // IBMBIDI + #include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLHtmlElement.h" @@ -1619,6 +1623,27 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, NS_BLOCK_MARGIN_ROOT & mState); if (eReflowReason_Resize != aReflowState.reason) { +#ifdef IBMBIDI + if (mLines) { + PRBool bidiEnabled; + aPresContext->BidiEnabled(bidiEnabled); + if (bidiEnabled) { + nsBidiPresUtils* bidiUtils; + aPresContext->GetBidiUtils(&bidiUtils); + if (bidiUtils) { + PRBool forceReflow; + nsresult rc = bidiUtils->Resolve(aPresContext, this, + mLines->mFirstChild, forceReflow); + if (NS_SUCCEEDED(rc) && forceReflow) { + // Mark everything dirty + for (nsLineBox* line = mLines; line; line = line->mNext) { + line->MarkDirty(); + } + } + } + } + } +#endif // IBMBIDI RenumberLists(aPresContext); } @@ -4247,6 +4272,15 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, if (aUpdateMaximumWidth) { availWidth = NS_UNCONSTRAINEDSIZE; } +#ifdef IBMBIDI + else { + nscoord rightEdge = aState.mReflowState.mRightEdge; + if ( (rightEdge != NS_UNCONSTRAINEDSIZE) + && (availWidth < rightEdge) ) { + availWidth = rightEdge; + } + } +#endif // IBMBIDI aLineLayout.BeginLineReflow(x, aState.mY, availWidth, availHeight, impactedByFloaters, @@ -4735,14 +4769,55 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, mStyleContext->GetStyleData(eStyleStruct_Text); PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign && !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine); +#ifdef IBMBIDI + nsRect bounds(aLine->mBounds); + + if (mRect.x) { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + + if (NS_STYLE_DIRECTION_RTL == display->mDirection) { + bounds.x += mRect.x; + } + } + PRBool successful = aLineLayout.HorizontalAlignFrames(bounds, allowJustify, + aState.GetFlag(BRS_SHRINKWRAPWIDTH)); + // XXX: not only bidi: right alignment can be broken after RelativePositionFrames!!! +#else PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify, aState.GetFlag(BRS_SHRINKWRAPWIDTH)); +#endif // IBMBIDI if (!successful) { // Mark the line dirty and then later once we've determined the width // we can do the horizontal alignment aLine->MarkDirty(); aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE); } +#ifdef IBMBIDI + else { + PRBool bidiEnabled; + aState.mPresContext->BidiEnabled(bidiEnabled); + + if (bidiEnabled) { + PRBool isVisual; + aState.mPresContext->IsVisualMode(isVisual); + if (!isVisual) { + nsBidiPresUtils* bidiUtils; + aState.mPresContext->GetBidiUtils(&bidiUtils); + + if (bidiUtils && bidiUtils->IsSuccessful() ) { + nsIFrame* nextInFlow = (aLine->mNext) + ? aLine->mNext->mFirstChild : nsnull; + + bidiUtils->ReorderFrames(aState.mPresContext, + aState.mReflowState.rendContext, + aLine->mFirstChild, nextInFlow, + aLine->GetChildCount() ); + } // bidiUtils + } // not visual mode + } // bidi enabled + } // successful +#endif // IBMBIDI nsRect combinedArea; aLineLayout.RelativePositionFrames(combinedArea); @@ -5263,6 +5338,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, mFloaters.AppendFrames(nsnull, aFrameList); return NS_OK; } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) {} +#endif // IBMBIDI else if (nsnull != aListName) { return NS_ERROR_INVALID_ARG; } @@ -5278,6 +5356,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, printf("\n"); #endif nsresult rv = AddFrames(aPresContext, aFrameList, aPrevFrame); +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5441,6 +5522,11 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, line = line->mNext; } } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) { + rv = DoRemoveFrame(aPresContext, aOldFrame); + } +#endif // IBMBIDI else if (nsnull != aListName) { rv = NS_ERROR_INVALID_ARG; } @@ -5448,6 +5534,9 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, rv = DoRemoveFrame(aPresContext, aOldFrame); } +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5628,12 +5717,21 @@ nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext* aPresContext, nsIFrame* nextInFlow; aChild->GetNextInFlow(&nextInFlow); NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow"); +#ifdef IBMBIDI + nsIFrame* nextBidi; + aChild->GetBidiProperty(aPresContext, nsLayoutAtoms::nextBidi, + (void**) &nextBidi); + if (nextBidi != nextInFlow) { +#endif // IBMBIDI nsBlockFrame* parent; nextInFlow->GetParent((nsIFrame**)&parent); NS_PRECONDITION(nsnull != parent, "next-in-flow with no parent"); NS_PRECONDITION(nsnull != parent->mLines, "next-in-flow with weird parent"); // NS_PRECONDITION(nsnull == parent->mOverflowLines, "parent with overflow"); parent->DoRemoveFrame(aPresContext, nextInFlow); +#ifdef IBMBIDI + } +#endif // IBMBIDI } //////////////////////////////////////////////////////////////////////// @@ -7206,9 +7304,21 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, mBullet->WillReflow(aState.mPresContext); mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status); +#ifdef IBMBIDI + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); +#endif // IBMBIDI // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line - nscoord x = - reflowState.mComputedMargin.right - aMetrics.width; + nscoord x = +#ifdef IBMBIDI + // For direction RTL: set x to the right margin for now. + // This value will be used to indent the bullet from the right most + // egde of the previous frame in nsLineLayout::HorizontalAlignFrames. + (NS_STYLE_DIRECTION_RTL == display->mDirection) + ? reflowState.mComputedMargin.right : +#endif // IBMBIDI + - reflowState.mComputedMargin.right - aMetrics.width; // Approximate the bullets position; vertical alignment will provide // the final vertical location. diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.cpp b/mozilla/layout/html/base/src/nsBlockReflowState.cpp index c244cac0576..459675b04ba 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.cpp +++ b/mozilla/layout/html/base/src/nsBlockReflowState.cpp @@ -58,6 +58,10 @@ #include "prenv.h" #include "plstr.h" +#ifdef IBMBIDI +#include "nsBidiPresUtils.h" +#endif // IBMBIDI + #include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLHtmlElement.h" @@ -1619,6 +1623,27 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, NS_BLOCK_MARGIN_ROOT & mState); if (eReflowReason_Resize != aReflowState.reason) { +#ifdef IBMBIDI + if (mLines) { + PRBool bidiEnabled; + aPresContext->BidiEnabled(bidiEnabled); + if (bidiEnabled) { + nsBidiPresUtils* bidiUtils; + aPresContext->GetBidiUtils(&bidiUtils); + if (bidiUtils) { + PRBool forceReflow; + nsresult rc = bidiUtils->Resolve(aPresContext, this, + mLines->mFirstChild, forceReflow); + if (NS_SUCCEEDED(rc) && forceReflow) { + // Mark everything dirty + for (nsLineBox* line = mLines; line; line = line->mNext) { + line->MarkDirty(); + } + } + } + } + } +#endif // IBMBIDI RenumberLists(aPresContext); } @@ -4247,6 +4272,15 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, if (aUpdateMaximumWidth) { availWidth = NS_UNCONSTRAINEDSIZE; } +#ifdef IBMBIDI + else { + nscoord rightEdge = aState.mReflowState.mRightEdge; + if ( (rightEdge != NS_UNCONSTRAINEDSIZE) + && (availWidth < rightEdge) ) { + availWidth = rightEdge; + } + } +#endif // IBMBIDI aLineLayout.BeginLineReflow(x, aState.mY, availWidth, availHeight, impactedByFloaters, @@ -4735,14 +4769,55 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, mStyleContext->GetStyleData(eStyleStruct_Text); PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign && !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine); +#ifdef IBMBIDI + nsRect bounds(aLine->mBounds); + + if (mRect.x) { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + + if (NS_STYLE_DIRECTION_RTL == display->mDirection) { + bounds.x += mRect.x; + } + } + PRBool successful = aLineLayout.HorizontalAlignFrames(bounds, allowJustify, + aState.GetFlag(BRS_SHRINKWRAPWIDTH)); + // XXX: not only bidi: right alignment can be broken after RelativePositionFrames!!! +#else PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify, aState.GetFlag(BRS_SHRINKWRAPWIDTH)); +#endif // IBMBIDI if (!successful) { // Mark the line dirty and then later once we've determined the width // we can do the horizontal alignment aLine->MarkDirty(); aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE); } +#ifdef IBMBIDI + else { + PRBool bidiEnabled; + aState.mPresContext->BidiEnabled(bidiEnabled); + + if (bidiEnabled) { + PRBool isVisual; + aState.mPresContext->IsVisualMode(isVisual); + if (!isVisual) { + nsBidiPresUtils* bidiUtils; + aState.mPresContext->GetBidiUtils(&bidiUtils); + + if (bidiUtils && bidiUtils->IsSuccessful() ) { + nsIFrame* nextInFlow = (aLine->mNext) + ? aLine->mNext->mFirstChild : nsnull; + + bidiUtils->ReorderFrames(aState.mPresContext, + aState.mReflowState.rendContext, + aLine->mFirstChild, nextInFlow, + aLine->GetChildCount() ); + } // bidiUtils + } // not visual mode + } // bidi enabled + } // successful +#endif // IBMBIDI nsRect combinedArea; aLineLayout.RelativePositionFrames(combinedArea); @@ -5263,6 +5338,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, mFloaters.AppendFrames(nsnull, aFrameList); return NS_OK; } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) {} +#endif // IBMBIDI else if (nsnull != aListName) { return NS_ERROR_INVALID_ARG; } @@ -5278,6 +5356,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, printf("\n"); #endif nsresult rv = AddFrames(aPresContext, aFrameList, aPrevFrame); +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5441,6 +5522,11 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, line = line->mNext; } } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) { + rv = DoRemoveFrame(aPresContext, aOldFrame); + } +#endif // IBMBIDI else if (nsnull != aListName) { rv = NS_ERROR_INVALID_ARG; } @@ -5448,6 +5534,9 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, rv = DoRemoveFrame(aPresContext, aOldFrame); } +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5628,12 +5717,21 @@ nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext* aPresContext, nsIFrame* nextInFlow; aChild->GetNextInFlow(&nextInFlow); NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow"); +#ifdef IBMBIDI + nsIFrame* nextBidi; + aChild->GetBidiProperty(aPresContext, nsLayoutAtoms::nextBidi, + (void**) &nextBidi); + if (nextBidi != nextInFlow) { +#endif // IBMBIDI nsBlockFrame* parent; nextInFlow->GetParent((nsIFrame**)&parent); NS_PRECONDITION(nsnull != parent, "next-in-flow with no parent"); NS_PRECONDITION(nsnull != parent->mLines, "next-in-flow with weird parent"); // NS_PRECONDITION(nsnull == parent->mOverflowLines, "parent with overflow"); parent->DoRemoveFrame(aPresContext, nextInFlow); +#ifdef IBMBIDI + } +#endif // IBMBIDI } //////////////////////////////////////////////////////////////////////// @@ -7206,9 +7304,21 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, mBullet->WillReflow(aState.mPresContext); mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status); +#ifdef IBMBIDI + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); +#endif // IBMBIDI // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line - nscoord x = - reflowState.mComputedMargin.right - aMetrics.width; + nscoord x = +#ifdef IBMBIDI + // For direction RTL: set x to the right margin for now. + // This value will be used to indent the bullet from the right most + // egde of the previous frame in nsLineLayout::HorizontalAlignFrames. + (NS_STYLE_DIRECTION_RTL == display->mDirection) + ? reflowState.mComputedMargin.right : +#endif // IBMBIDI + - reflowState.mComputedMargin.right - aMetrics.width; // Approximate the bullets position; vertical alignment will provide // the final vertical location. diff --git a/mozilla/layout/html/base/src/nsBlockReflowState.h b/mozilla/layout/html/base/src/nsBlockReflowState.h index c244cac0576..459675b04ba 100644 --- a/mozilla/layout/html/base/src/nsBlockReflowState.h +++ b/mozilla/layout/html/base/src/nsBlockReflowState.h @@ -58,6 +58,10 @@ #include "prenv.h" #include "plstr.h" +#ifdef IBMBIDI +#include "nsBidiPresUtils.h" +#endif // IBMBIDI + #include "nsIDOMHTMLBodyElement.h" #include "nsIDOMHTMLHtmlElement.h" @@ -1619,6 +1623,27 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext, NS_BLOCK_MARGIN_ROOT & mState); if (eReflowReason_Resize != aReflowState.reason) { +#ifdef IBMBIDI + if (mLines) { + PRBool bidiEnabled; + aPresContext->BidiEnabled(bidiEnabled); + if (bidiEnabled) { + nsBidiPresUtils* bidiUtils; + aPresContext->GetBidiUtils(&bidiUtils); + if (bidiUtils) { + PRBool forceReflow; + nsresult rc = bidiUtils->Resolve(aPresContext, this, + mLines->mFirstChild, forceReflow); + if (NS_SUCCEEDED(rc) && forceReflow) { + // Mark everything dirty + for (nsLineBox* line = mLines; line; line = line->mNext) { + line->MarkDirty(); + } + } + } + } + } +#endif // IBMBIDI RenumberLists(aPresContext); } @@ -4247,6 +4272,15 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState, if (aUpdateMaximumWidth) { availWidth = NS_UNCONSTRAINEDSIZE; } +#ifdef IBMBIDI + else { + nscoord rightEdge = aState.mReflowState.mRightEdge; + if ( (rightEdge != NS_UNCONSTRAINEDSIZE) + && (availWidth < rightEdge) ) { + availWidth = rightEdge; + } + } +#endif // IBMBIDI aLineLayout.BeginLineReflow(x, aState.mY, availWidth, availHeight, impactedByFloaters, @@ -4735,14 +4769,55 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState, mStyleContext->GetStyleData(eStyleStruct_Text); PRBool allowJustify = NS_STYLE_TEXT_ALIGN_JUSTIFY == styleText->mTextAlign && !aLineLayout.GetLineEndsInBR() && ShouldJustifyLine(aState, aLine); +#ifdef IBMBIDI + nsRect bounds(aLine->mBounds); + + if (mRect.x) { + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + + if (NS_STYLE_DIRECTION_RTL == display->mDirection) { + bounds.x += mRect.x; + } + } + PRBool successful = aLineLayout.HorizontalAlignFrames(bounds, allowJustify, + aState.GetFlag(BRS_SHRINKWRAPWIDTH)); + // XXX: not only bidi: right alignment can be broken after RelativePositionFrames!!! +#else PRBool successful = aLineLayout.HorizontalAlignFrames(aLine->mBounds, allowJustify, aState.GetFlag(BRS_SHRINKWRAPWIDTH)); +#endif // IBMBIDI if (!successful) { // Mark the line dirty and then later once we've determined the width // we can do the horizontal alignment aLine->MarkDirty(); aState.SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE); } +#ifdef IBMBIDI + else { + PRBool bidiEnabled; + aState.mPresContext->BidiEnabled(bidiEnabled); + + if (bidiEnabled) { + PRBool isVisual; + aState.mPresContext->IsVisualMode(isVisual); + if (!isVisual) { + nsBidiPresUtils* bidiUtils; + aState.mPresContext->GetBidiUtils(&bidiUtils); + + if (bidiUtils && bidiUtils->IsSuccessful() ) { + nsIFrame* nextInFlow = (aLine->mNext) + ? aLine->mNext->mFirstChild : nsnull; + + bidiUtils->ReorderFrames(aState.mPresContext, + aState.mReflowState.rendContext, + aLine->mFirstChild, nextInFlow, + aLine->GetChildCount() ); + } // bidiUtils + } // not visual mode + } // bidi enabled + } // successful +#endif // IBMBIDI nsRect combinedArea; aLineLayout.RelativePositionFrames(combinedArea); @@ -5263,6 +5338,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, mFloaters.AppendFrames(nsnull, aFrameList); return NS_OK; } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) {} +#endif // IBMBIDI else if (nsnull != aListName) { return NS_ERROR_INVALID_ARG; } @@ -5278,6 +5356,9 @@ nsBlockFrame::InsertFrames(nsIPresContext* aPresContext, printf("\n"); #endif nsresult rv = AddFrames(aPresContext, aFrameList, aPrevFrame); +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5441,6 +5522,11 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, line = line->mNext; } } +#ifdef IBMBIDI + else if (nsLayoutAtoms::nextBidi == aListName) { + rv = DoRemoveFrame(aPresContext, aOldFrame); + } +#endif // IBMBIDI else if (nsnull != aListName) { rv = NS_ERROR_INVALID_ARG; } @@ -5448,6 +5534,9 @@ nsBlockFrame::RemoveFrame(nsIPresContext* aPresContext, rv = DoRemoveFrame(aPresContext, aOldFrame); } +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) +#endif // IBMBIDI if (NS_SUCCEEDED(rv)) { // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); @@ -5628,12 +5717,21 @@ nsBlockFrame::DeleteChildsNextInFlow(nsIPresContext* aPresContext, nsIFrame* nextInFlow; aChild->GetNextInFlow(&nextInFlow); NS_PRECONDITION(nsnull != nextInFlow, "null next-in-flow"); +#ifdef IBMBIDI + nsIFrame* nextBidi; + aChild->GetBidiProperty(aPresContext, nsLayoutAtoms::nextBidi, + (void**) &nextBidi); + if (nextBidi != nextInFlow) { +#endif // IBMBIDI nsBlockFrame* parent; nextInFlow->GetParent((nsIFrame**)&parent); NS_PRECONDITION(nsnull != parent, "next-in-flow with no parent"); NS_PRECONDITION(nsnull != parent->mLines, "next-in-flow with weird parent"); // NS_PRECONDITION(nsnull == parent->mOverflowLines, "parent with overflow"); parent->DoRemoveFrame(aPresContext, nextInFlow); +#ifdef IBMBIDI + } +#endif // IBMBIDI } //////////////////////////////////////////////////////////////////////// @@ -7206,9 +7304,21 @@ nsBlockFrame::ReflowBullet(nsBlockReflowState& aState, mBullet->WillReflow(aState.mPresContext); mBullet->Reflow(aState.mPresContext, aMetrics, reflowState, status); +#ifdef IBMBIDI + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); +#endif // IBMBIDI // Place the bullet now; use its right margin to distance it // from the rest of the frames in the line - nscoord x = - reflowState.mComputedMargin.right - aMetrics.width; + nscoord x = +#ifdef IBMBIDI + // For direction RTL: set x to the right margin for now. + // This value will be used to indent the bullet from the right most + // egde of the previous frame in nsLineLayout::HorizontalAlignFrames. + (NS_STYLE_DIRECTION_RTL == display->mDirection) + ? reflowState.mComputedMargin.right : +#endif // IBMBIDI + - reflowState.mComputedMargin.right - aMetrics.width; // Approximate the bullets position; vertical alignment will provide // the final vertical location. diff --git a/mozilla/layout/html/base/src/nsBulletFrame.cpp b/mozilla/layout/html/base/src/nsBulletFrame.cpp index 099372f554e..ad864fa323e 100644 --- a/mozilla/layout/html/base/src/nsBulletFrame.cpp +++ b/mozilla/layout/html/base/src/nsBulletFrame.cpp @@ -37,6 +37,9 @@ #include "nsLayoutAtoms.h" #include "prprf.h" #include "nsIImage.h" +#ifdef IBMBIDI +#include "nsBidiPresUtils.h" +#endif // IBMBIDI nsBulletFrame::nsBulletFrame() { @@ -145,6 +148,14 @@ nsBulletFrame::Paint(nsIPresContext* aCX, nsCOMPtr fm; aRenderingContext.SetColor(myColor->mColor); +#ifdef IBMBIDI + nsCharType charType = eCharType_LeftToRight; + PRUint8 level = 0; + PRBool isBidiSystem = PR_FALSE; + const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); + PRUint32 hints = 0; +#endif // IBMBIDI + nsAutoString text; switch (listStyleType) { case NS_STYLE_LIST_STYLE_NONE: @@ -173,6 +184,33 @@ nsBulletFrame::Paint(nsIPresContext* aCX, case NS_STYLE_LIST_STYLE_DECIMAL: case NS_STYLE_LIST_STYLE_OLD_DECIMAL: case NS_STYLE_LIST_STYLE_DECIMAL_LEADING_ZERO: +#ifdef IBMBIDI + GetListItemText(aCX, *myList, text); + charType = eCharType_EuropeanNumber; + break; + + case NS_STYLE_LIST_STYLE_ARABIC_INDIC: + GetListItemText(aCX, *myList, text); + charType = eCharType_ArabicNumber; + break; + + case NS_STYLE_LIST_STYLE_HEBREW: + aRenderingContext.GetHints(hints); + isBidiSystem = (hints & NS_RENDERING_HINT_BIDI_REORDERING); + if (!isBidiSystem) { + charType = eCharType_RightToLeft; + level = 1; + GetListItemText(aCX, *myList, text); + + if (NS_STYLE_DIRECTION_RTL == disp->mDirection) { + nsStr::Delete(text, 0, 1); + text.AppendWithConversion("."); + } + break; + } + // else fall through +#endif // IBMBIDI + case NS_STYLE_LIST_STYLE_LOWER_ROMAN: case NS_STYLE_LIST_STYLE_UPPER_ROMAN: case NS_STYLE_LIST_STYLE_LOWER_ALPHA: @@ -182,7 +220,9 @@ nsBulletFrame::Paint(nsIPresContext* aCX, case NS_STYLE_LIST_STYLE_OLD_LOWER_ALPHA: case NS_STYLE_LIST_STYLE_OLD_UPPER_ALPHA: case NS_STYLE_LIST_STYLE_LOWER_GREEK: +#ifndef IBMBIDI case NS_STYLE_LIST_STYLE_HEBREW: +#endif case NS_STYLE_LIST_STYLE_ARMENIAN: case NS_STYLE_LIST_STYLE_GEORGIAN: case NS_STYLE_LIST_STYLE_CJK_IDEOGRAPHIC: @@ -198,7 +238,9 @@ nsBulletFrame::Paint(nsIPresContext* aCX, case NS_STYLE_LIST_STYLE_JAPANESE_FORMAL: case NS_STYLE_LIST_STYLE_CJK_HEAVENLY_STEM: case NS_STYLE_LIST_STYLE_CJK_EARTHLY_BRANCH: +#ifndef IBMBIDI case NS_STYLE_LIST_STYLE_ARABIC_INDIC: +#endif case NS_STYLE_LIST_STYLE_PERSIAN: case NS_STYLE_LIST_STYLE_URDU: case NS_STYLE_LIST_STYLE_DEVANAGARI: @@ -220,6 +262,31 @@ nsBulletFrame::Paint(nsIPresContext* aCX, aRenderingContext.DrawString(text, mPadding.left, mPadding.top); break; } +#ifdef IBMBIDI + if (charType != eCharType_LeftToRight) { + aCX->GetMetricsFor(myFont->mFont, getter_AddRefs(fm)); + aRenderingContext.SetFont(fm); + + nsBidiPresUtils* bidiUtils; + aCX->GetBidiUtils(&bidiUtils); + if (bidiUtils) { + const PRUnichar* buffer = text.GetUnicode(); + PRInt32 textLength = text.Length(); + if (eCharType_RightToLeft == charType) { + bidiUtils->FormatUnicodeText(aCX, (PRUnichar*)buffer, textLength, + charType, level, PR_FALSE); + } + else { +//Mohamed + aRenderingContext.GetHints(hints); + isBidiSystem = (hints & NS_RENDERING_HINT_ARABIC_SHAPING); + bidiUtils->FormatUnicodeText(aCX, (PRUnichar*)buffer, textLength, + charType, level, isBidiSystem);//Mohamed + } + } + aRenderingContext.DrawString(text, mPadding.left, mPadding.top); + } +#endif // IBMBIDI } return NS_OK; } @@ -590,12 +657,21 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) { PRBool outputSep = PR_FALSE; PRUnichar buf[NUM_BUF_SIZE]; +#ifdef IBMBIDI + // Changes: 1) don't reverse the text; 2) don't insert geresh/gershayim. + PRInt32 idx = 0; +#else PRInt32 idx = NUM_BUF_SIZE; +#endif // IBMBIDI PRUnichar digit; do { PRInt32 n3 = ordinal % 1000; if(outputSep) +#ifdef IBMBIDI + buf[idx++] = HEBREW_THROSAND_SEP; // output thousand seperator +#else buf[--idx] = HEBREW_THROSAND_SEP; // output thousand seperator +#endif // IBMBIDI outputSep = ( n3 > 0); // request to output thousand seperator next time. PRInt32 d = 0; // we need to keep track of digit got output per 3 digits, @@ -611,10 +687,17 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) digit = gHebrewDigit[(n1/100)-1+18]; if( n3 > 0) { +#ifdef IBMBIDI + buf[idx++] = digit; +#else buf[--idx] = digit; +#endif // IBMBIDI d++; } else { // if this is the last digit +#ifdef IBMBIDI + buf[idx++] = digit; +#else if (d > 0) { buf[--idx] = HEBREW_GERSHAYIM; @@ -623,6 +706,7 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) buf[--idx] = digit; buf[--idx] = HEBREW_GERESH; } // if +#endif // IBMBIDI } // if } else { n1 -= 100; @@ -648,10 +732,17 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) n3 -= n2; if( n3 > 0) { +#ifdef IBMBIDI + buf[idx++] = digit; +#else buf[--idx] = digit; +#endif // IBMBIDI d++; } else { // if this is the last digit +#ifdef IBMBIDI + buf[idx++] = digit; +#else if (d > 0) { buf[--idx] = HEBREW_GERSHAYIM; @@ -660,6 +751,7 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) buf[--idx] = digit; buf[--idx] = HEBREW_GERESH; } // if +#endif // IBMBIDI } // if } // if @@ -668,6 +760,9 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) { digit = gHebrewDigit[n3-1]; // must be the last digit +#ifdef IBMBIDI + buf[idx++] = digit; +#else if (d > 0) { buf[--idx] = HEBREW_GERSHAYIM; @@ -676,10 +771,15 @@ static void HebrewToText(PRInt32 ordinal, nsString& result) buf[--idx] = digit; buf[--idx] = HEBREW_GERESH; } // if +#endif // IBMBIDI } // if ordinal /= 1000; } while (ordinal >= 1); +#ifdef IBMBIDI + result.Append(buf, idx); +#else result.Append(buf+idx,NUM_BUF_SIZE-idx); +#endif // IBMBIDI } @@ -747,6 +847,14 @@ nsBulletFrame::GetListItemText(nsIPresContext* aCX, const nsStyleList& aListStyle, nsString& result) { +#ifdef IBMBIDI + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&) display); + if (NS_STYLE_DIRECTION_RTL == display->mDirection) { + result.AppendWithConversion("."); + } +#endif // IBMBIDI + switch (aListStyle.mListStyleType) { case NS_STYLE_LIST_STYLE_DECIMAL: case NS_STYLE_LIST_STYLE_OLD_DECIMAL: @@ -904,6 +1012,9 @@ nsBulletFrame::GetListItemText(nsIPresContext* aCX, CharListToText(mOrdinal, result, gCJKEarthlyBranchChars, CJK_EARTHLY_BRANCH_CHARS_SIZE); break; } +#ifdef IBMBIDI + if (NS_STYLE_DIRECTION_RTL != display->mDirection) +#endif // IBMBIDI result.AppendWithConversion("."); } diff --git a/mozilla/layout/html/base/src/nsContainerFrame.cpp b/mozilla/layout/html/base/src/nsContainerFrame.cpp index f14b4ef8cbf..3bf69ab29b3 100644 --- a/mozilla/layout/html/base/src/nsContainerFrame.cpp +++ b/mozilla/layout/html/base/src/nsContainerFrame.cpp @@ -851,6 +851,15 @@ nsContainerFrame::DeleteChildsNextInFlow(nsIPresContext* aPresContext, parent->DeleteChildsNextInFlow(aPresContext, nextInFlow); } +#ifdef IBMBIDI + nsIFrame* nextBidi; + aChild->GetBidiProperty(aPresContext, nsLayoutAtoms::nextBidi, + (void**) &nextBidi); + if (nextBidi == nextInFlow) { + return; + } +#endif // IBMBIDI + // Disconnect the next-in-flow from the flow list nsSplittableFrame::BreakFromPrevFlow(nextInFlow); diff --git a/mozilla/layout/html/base/src/nsFrame.cpp b/mozilla/layout/html/base/src/nsFrame.cpp index 6924122b50d..93d608990ed 100644 --- a/mozilla/layout/html/base/src/nsFrame.cpp +++ b/mozilla/layout/html/base/src/nsFrame.cpp @@ -2633,6 +2633,18 @@ nsFrame::SetSelected(nsIPresContext* aPresContext, nsIDOMRange *aRange, PRBool a } } #endif +#ifdef IBMBIDI + PRInt32 start, end; + nsIFrame* frame; + GetNextSibling(&frame); + if (frame){ + GetFirstLeaf(aPresContext, &frame); + GetOffsets(start, end); + if (start && end) { + frame->SetSelected(aPresContext, aRange, aSelected, aSpread); + } + } +#endif // IBMBIDI return NS_OK; } @@ -2776,7 +2788,13 @@ nsFrame::GetNextPrevLineFromeBlockFrame(nsIPresContext* aPresContext, nsIView * view; //used for call of get offset from view aBlockFrame->GetOffsetFromView(aPresContext, offset,&view); nscoord newDesiredX = aPos->mDesiredX - offset.x;//get desired x into blockframe coordinates! +#ifdef IBMBIDI + PRBool bidiEnabled; + aPresContext->BidiEnabled(bidiEnabled); + result = it->FindFrameAt(searchingLine, newDesiredX, bidiEnabled, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame); +#else result = it->FindFrameAt(searchingLine, newDesiredX, &resultFrame, &isBeforeFirstFrame, &isAfterLastFrame); +#endif // IBMBIDI if(NS_FAILED(result)) continue; } @@ -3463,28 +3481,63 @@ nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct PRInt32 lineFrameCount; PRUint32 lineFlags; - result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect, - &lineFlags); +#ifdef IBMBIDI + /* Check whether the visual and logical order of the frames are different */ + PRBool lineIsReordered = PR_FALSE; + nsIFrame *firstVisual; + nsIFrame *lastVisual; + PRBool lineIsRTL; + PRBool lineJump = PR_FALSE; + + it->GetDirection(&lineIsRTL); + result = it->CheckLineOrder(thisLine, &lineIsReordered, &firstVisual, &lastVisual); if (NS_FAILED(result)) return result; - lastFrame = firstFrame; - for (;lineFrameCount > 1;lineFrameCount --){ - result = lastFrame->GetNextSibling(&lastFrame); - if (NS_FAILED(result)){ - NS_ASSERTION(0,"should not be reached nsFrame\n"); - return NS_ERROR_FAILURE; + if (lineIsReordered) { + firstFrame = firstVisual; + lastFrame = lastVisual; + } + else +#endif + { + result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect, + &lineFlags); + if (NS_FAILED(result)) + return result; + + lastFrame = firstFrame; + for (;lineFrameCount > 1;lineFrameCount --){ + result = lastFrame->GetNextSibling(&lastFrame); + if (NS_FAILED(result)){ + NS_ASSERTION(0,"should not be reached nsFrame\n"); + return NS_ERROR_FAILURE; + } } } - + GetFirstLeaf(aPresContext, &firstFrame); GetLastLeaf(aPresContext, &lastFrame); //END LINE DATA CODE - if ((aPos->mDirection == eDirNext && lastFrame == this) - ||(aPos->mDirection == eDirPrevious && firstFrame == this)) + if +#ifndef IBMBIDI // jumping lines in RTL paragraphs + ((aPos->mDirection == eDirNext && lastFrame == this) + ||(aPos->mDirection == eDirPrevious && firstFrame == this)) +#else + (((lineIsRTL) && + ((aPos->mDirection == eDirNext && firstFrame == this) + ||(aPos->mDirection == eDirPrevious && lastFrame == this))) + || + ((!lineIsRTL) && + ((aPos->mDirection == eDirNext && lastFrame == this) + ||(aPos->mDirection == eDirPrevious && firstFrame == this)))) +#endif { if (aPos->mJumpLines != PR_TRUE) return NS_ERROR_FAILURE;//we are done. cannot jump lines +#ifdef IBMBIDI + lineJump = PR_TRUE; +#endif if (aPos->mAmount != eSelectWord) { aPos->mPreferLeft = (PRBool)!(aPos->mPreferLeft);//drift to other side @@ -3504,15 +3557,35 @@ nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct if (aPos->mAmount == eSelectDir) aPos->mAmount = eSelectNoAmount;//just get to next frame. nsCOMPtr frameTraversal; +#ifdef IBMBIDI + result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal), + (lineIsReordered) ? VISUAL : LEAF, + aPresContext, + (lineJump && lineIsRTL) + ? (aPos->mDirection == eDirNext) ? lastFrame : firstFrame + : this); +#else result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),LEAF, aPresContext, this); +#endif if (NS_FAILED(result)) return result; nsISupports *isupports = nsnull; - if (aPos->mDirection == eDirNext) - result = frameTraversal->Next(); - else - result = frameTraversal->Prev(); - +#ifdef IBMBIDI + nsIFrame *newFrame; + nsRect testRect; + while (testRect.IsEmpty()) { + if (lineIsRTL && lineJump) + if (aPos->mDirection == eDirPrevious) + result = frameTraversal->Next(); + else + result = frameTraversal->Prev(); + else +#endif + if (aPos->mDirection == eDirNext) + result = frameTraversal->Next(); + else + result = frameTraversal->Prev(); + if (NS_FAILED(result)) return result; result = frameTraversal->CurrentItem(&isupports); @@ -3522,7 +3595,80 @@ nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct return NS_ERROR_NULL_POINTER; //we must CAST here to an nsIFrame. nsIFrame doesnt really follow the rules //for speed reasons +#ifndef IBMBIDI nsIFrame *newFrame = (nsIFrame *)isupports; +#else + newFrame = (nsIFrame *)isupports; + newFrame->GetRect(testRect); + if (testRect.IsEmpty()) { // this must be a non-renderable frame creatd at the end of the line by Bidi reordering + lineJump = PR_TRUE; + aPos->mAmount = eSelectNoAmount; + } + } + PRBool newLineIsRTL = PR_FALSE; + if (lineJump) { + blockFrame = newFrame; + nsresult result = NS_ERROR_FAILURE; + while (NS_FAILED(result) && blockFrame) + { + thisBlock = blockFrame; + result = blockFrame->GetParent(&blockFrame); + if (NS_SUCCEEDED(result) && blockFrame){ + result = blockFrame->QueryInterface(NS_GET_IID(nsILineIteratorNavigator),getter_AddRefs(it)); + } + else + blockFrame = nsnull; + } + if (!blockFrame || !it) + return NS_ERROR_FAILURE; + result = it->FindLineContaining(thisBlock, &thisLine); + if (NS_FAILED(result)) + return result; + it->GetDirection(&newLineIsRTL); + + result = it->CheckLineOrder(thisLine, &lineIsReordered, &firstVisual, &lastVisual); + if (NS_FAILED(result)) + return result; + + if (lineIsReordered) + { + firstFrame = firstVisual; + lastFrame = lastVisual; + } + else + { + result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect, + &lineFlags); + if (NS_FAILED(result)) + return result; + + lastFrame = firstFrame; + for (;lineFrameCount > 1;lineFrameCount --){ + result = lastFrame->GetNextSibling(&lastFrame); + if (NS_FAILED(result)){ + NS_ASSERTION(0,"should not be reached nsFrame\n"); + return NS_ERROR_FAILURE; + } + } + } + + GetFirstLeaf(aPresContext, &firstFrame); + GetLastLeaf(aPresContext, &lastFrame); + + if (newLineIsRTL) { + if (aPos->mDirection == eDirPrevious) + newFrame = firstFrame; + else + newFrame = lastFrame; + } + else { + if (aPos->mDirection == eDirNext) + newFrame = firstFrame; + else + newFrame = lastFrame; + } + } +#endif // IBMBIDI PRBool selectable; newFrame->IsSelectable(&selectable, nsnull); if (!selectable) @@ -3531,6 +3677,18 @@ nsFrame::GetFrameFromDirection(nsIPresContext* aPresContext, nsPeekOffsetStruct aPos->mStartOffset = 0; else aPos->mStartOffset = -1; +#ifdef IBMBIDI + long oldLevel, newLevel, baseLevel; + GetBidiProperty(aPresContext, nsLayoutAtoms::embeddingLevel, (void**)&oldLevel); + newFrame->GetBidiProperty(aPresContext, nsLayoutAtoms::embeddingLevel, (void**)&newLevel); + newFrame->GetBidiProperty(aPresContext, nsLayoutAtoms::baseLevel, (void**)&baseLevel); + if (newLevel & 1) // The new frame is RTL, go to the other end + aPos->mStartOffset = -1 - aPos->mStartOffset; + + if ((aPos->mAmount == eSelectNoAmount) && ((newLevel & 1) != (oldLevel & 1))) { + aPos->mPreferLeft = !(aPos->mPreferLeft); + } +#endif aPos->mResultFrame = newFrame; return NS_OK; } @@ -3771,6 +3929,63 @@ nsFrame::IsMouseCaptured(nsIPresContext* aPresContext) return PR_FALSE; } +#ifdef IBMBIDI +/** + * retrieve Bidi property of this frame + * @lina 5/1/2000 + */ + +nsresult nsFrame::GetBidiProperty(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + void** aPropertyValue, + long aSize) const +{ + if (!aPropertyValue || !aPropertyName) { + return NS_ERROR_NULL_POINTER; + } + if ( (aSize < 1) || (aSize > sizeof(void*) ) ) { + return NS_ERROR_ILLEGAL_VALUE; + } + + nsCRT::zero(aPropertyValue, aSize); + void* val = nsnull; + + nsCOMPtr presShell; + aPresContext->GetShell(getter_AddRefs(presShell) ); + + if (presShell) { + nsCOMPtr frameManager; + presShell->GetFrameManager(getter_AddRefs(frameManager) ); + + if (frameManager) { + frameManager->GetFrameProperty( (nsIFrame*)this, aPropertyName, 0, &val); + if (val) { + nsCRT::memcpy(aPropertyValue, &val, aSize); + } + } + } + return NS_OK; +} + +nsresult nsFrame::SetBidiProperty(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + void* aPropertyValue) const +{ + nsresult rv = NS_ERROR_FAILURE; + + nsCOMPtr shell; + aPresContext->GetShell(getter_AddRefs(shell) ); + if (shell) { + nsCOMPtr frameManager; + shell->GetFrameManager(getter_AddRefs(frameManager) ); + if (frameManager) { + rv = frameManager->SetFrameProperty( (nsIFrame*) this, aPropertyName, aPropertyValue, nsnull); + } + } + return rv; +} +#endif // IBMBIDI + #ifdef NS_DEBUG static void GetTagName(nsFrame* aFrame, nsIContent* aContent, PRIntn aResultSize, diff --git a/mozilla/layout/html/base/src/nsFrame.h b/mozilla/layout/html/base/src/nsFrame.h index 847400cb4fe..a1d592561c0 100644 --- a/mozilla/layout/html/base/src/nsFrame.h +++ b/mozilla/layout/html/base/src/nsFrame.h @@ -368,6 +368,15 @@ public: //Mouse Capturing code used by the frames to tell the view to capture all the following events NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents); PRBool IsMouseCaptured(nsIPresContext* aPresContext); +#ifdef IBMBIDI + NS_IMETHOD GetBidiProperty(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + void** aPropertyValue, + long aSize = sizeof(void*) ) const; + NS_IMETHOD SetBidiProperty(nsIPresContext* aPresContext, + nsIAtom* aPropertyName, + void* aPropertyValue) const ; +#endif // IBMBIDI #ifdef NS_DEBUG /** diff --git a/mozilla/layout/html/base/src/nsFrameManager.cpp b/mozilla/layout/html/base/src/nsFrameManager.cpp index 594c671f614..2987f7da417 100644 --- a/mozilla/layout/html/base/src/nsFrameManager.cpp +++ b/mozilla/layout/html/base/src/nsFrameManager.cpp @@ -805,6 +805,20 @@ FrameManager::InsertFrames(nsIPresContext* aPresContext, return rv; } +#ifdef IBMBIDI + if (aPrevFrame) { + // Insert aFrameList after the last bidi continuation of aPrevFrame. + nsIFrame* nextBidi; + for (; ;) { + GetFrameProperty(aPrevFrame, nsLayoutAtoms::nextBidi, 0, (void**) &nextBidi); + if (!nextBidi) { + break; + } + aPrevFrame = nextBidi; + } + } +#endif // IBMBIDI + return aParentFrame->InsertFrames(aPresContext, aPresShell, aListName, aPrevFrame, aFrameList); } @@ -822,6 +836,15 @@ FrameManager::RemoveFrame(nsIPresContext* aPresContext, if (insertionPoint) return insertionPoint->RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); +#ifdef IBMBIDI + // Don't let the parent remove next bidi. In the other cases the it should NOT be removed. + nsIFrame* nextBidi; + GetFrameProperty(aOldFrame, nsLayoutAtoms::nextBidi, 0, (void**) &nextBidi); + if (nextBidi) { + RemoveFrame(aPresContext, aPresShell, aParentFrame, aListName, nextBidi); + } +#endif // IBMBIDI + return aParentFrame->RemoveFrame(aPresContext, aPresShell, aListName, aOldFrame); } diff --git a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp index ead2b06cfe4..b160002cac3 100644 --- a/mozilla/layout/html/base/src/nsHTMLReflowState.cpp +++ b/mozilla/layout/html/base/src/nsHTMLReflowState.cpp @@ -66,6 +66,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, mLineLayout = nsnull; isTopOfPage = PR_FALSE; Init(aPresContext); +#ifdef IBMBIDI + mRightEdge = NS_UNCONSTRAINEDSIZE; +#endif } // Initialize a root reflow state for an incremental @@ -90,6 +93,9 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, mLineLayout = nsnull; isTopOfPage = PR_FALSE; Init(aPresContext); +#ifdef IBMBIDI + mRightEdge = NS_UNCONSTRAINEDSIZE; +#endif // IBMBIDI } // Initialize a reflow state for a child frames reflow. Some state @@ -117,6 +123,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, isTopOfPage = aParentReflowState.isTopOfPage; Init(aPresContext); + +#ifdef IBMBIDI + mRightEdge = aParentReflowState.mRightEdge; +#endif // IBMBIDI } // Same as the previous except that the reason is taken from the @@ -140,6 +150,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, isTopOfPage = aParentReflowState.isTopOfPage; Init(aPresContext); + +#ifdef IBMBIDI + mRightEdge = aParentReflowState.mRightEdge; +#endif // IBMBIDI } // Version that species the containing block width and height @@ -164,6 +178,10 @@ nsHTMLReflowState::nsHTMLReflowState(nsIPresContext* aPresContext, isTopOfPage = aParentReflowState.isTopOfPage; Init(aPresContext, aContainingBlockWidth, aContainingBlockHeight); + +#ifdef IBMBIDI + mRightEdge = aParentReflowState.mRightEdge; +#endif // IBMBIDI } void @@ -1833,6 +1851,18 @@ nsHTMLReflowState::ComputeBlockBoxData(nsIPresContext* aPresContext, AdjustComputedWidth(); +#ifdef IBMBIDI + // See what edge the width applies to (the default is the content + // edge) + if (mComputedWidth != NS_UNCONSTRAINEDSIZE) { + if (mStylePosition->mBoxSizing == NS_STYLE_BOX_SIZING_PADDING) { + mComputedWidth -= mComputedPadding.left + mComputedPadding.right; + } else if (mStylePosition->mBoxSizing == NS_STYLE_BOX_SIZING_BORDER) { + mComputedWidth -= mComputedBorderPadding.left + mComputedBorderPadding.right; + } + } +#endif // IBMBIDI + // Now that we have the computed-width, compute the side margins CalculateBlockSideMargins(cbrs->mComputedWidth, mComputedWidth); } diff --git a/mozilla/layout/html/base/src/nsInlineFrame.cpp b/mozilla/layout/html/base/src/nsInlineFrame.cpp index 4b624ed1cc3..ff2b43fbf47 100644 --- a/mozilla/layout/html/base/src/nsInlineFrame.cpp +++ b/mozilla/layout/html/base/src/nsInlineFrame.cpp @@ -122,12 +122,18 @@ nsInlineFrame::InsertFrames(nsIPresContext* aPresContext, nsIFrame* aFrameList) { if (nsnull != aListName) { +#ifdef IBMBIDI + if (aListName != nsLayoutAtoms::nextBidi) +#endif return NS_ERROR_INVALID_ARG; } if (aFrameList) { // Insert frames after aPrevFrame mFrames.InsertFrames(this, aPrevFrame, aFrameList); +#ifdef IBMBIDI + if (nsnull == aListName) +#endif // Ask the parent frame to reflow me. ReflowDirtyChild(&aPresShell, nsnull); } @@ -141,6 +147,9 @@ nsInlineFrame::RemoveFrame(nsIPresContext* aPresContext, nsIFrame* aOldFrame) { if (nsnull != aListName) { +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) +#endif return NS_ERROR_INVALID_ARG; } @@ -151,6 +160,9 @@ nsInlineFrame::RemoveFrame(nsIPresContext* aPresContext, aOldFrame->GetParent(&oldFrameParent); nsInlineFrame* parent = (nsInlineFrame*) oldFrameParent; while (nsnull != aOldFrame) { +#ifdef IBMBIDI + if (nsLayoutAtoms::nextBidi != aListName) { +#endif // If the frame being removed has zero size then don't bother // generating a reflow command, otherwise make sure we do. nsRect bbox; @@ -158,6 +170,9 @@ nsInlineFrame::RemoveFrame(nsIPresContext* aPresContext, if (bbox.width || bbox.height) { generateReflowCommand = PR_TRUE; } +#ifdef IBMBIDI + } +#endif // When the parent is an inline frame we have a simple task - just // remove the frame from its parents list and generate a reflow diff --git a/mozilla/layout/html/base/src/nsLineBox.cpp b/mozilla/layout/html/base/src/nsLineBox.cpp index 02d3c385924..8ed742dcafb 100644 --- a/mozilla/layout/html/base/src/nsLineBox.cpp +++ b/mozilla/layout/html/base/src/nsLineBox.cpp @@ -653,9 +653,125 @@ nsLineIterator::FindLineAt(nscoord aY, return NS_OK; } +#ifdef IBMBIDI +NS_IMETHODIMP +nsLineIterator::CheckLineOrder(PRInt32 aLine, + PRBool *aIsReordered, + nsIFrame **aFirstVisual, + nsIFrame **aLastVisual) +{ + nsRect checkRect; + PRInt32 currentLine, saveLine, testLine; + nscoord saveX; + nsIFrame *checkFrame; + nsIFrame *firstFrame; + nsIFrame *leftmostFrame; + nsIFrame *rightmostFrame; + nscoord minX, maxX; + PRInt32 lineFrameCount; + PRUint32 lineFlags; + + nsresult result; + + // an RTL paragraph is always considered as reordered + // in an LTR paragraph, find out by examining the coordinates of each frame in the line + if (mRightToLeft) + *aIsReordered = PR_TRUE; + else { + *aIsReordered = PR_FALSE; + + // Check the preceding and following line, since we might be moving into them + for (currentLine = PR_MAX(0, aLine-1); currentLine < aLine+1; currentLine++) { + + nsLineBox* line = mLines[currentLine]; + if (!line) + break; + + checkFrame = line->mFirstChild; + + checkFrame->GetRect(checkRect); + result = FindLineContaining(checkFrame, &saveLine); + if (NS_FAILED(result)) + return result; + saveX = checkRect.x; + lineFrameCount = line->GetChildCount(); + + for (; checkFrame; result = checkFrame->GetNextSibling(&checkFrame)) { + if (NS_FAILED(result)) + break; + result = FindLineContaining(checkFrame, &testLine); + if (NS_FAILED(result)) + return result; + if (testLine != saveLine) { + *aIsReordered = PR_TRUE; + break; + } + + checkFrame->GetRect(checkRect); + // If the origin of any frame is less than the previous frame, the line is reordered + if (checkRect.x < saveX) { + *aIsReordered = PR_TRUE; + break; + } + saveX = checkRect.x; + lineFrameCount--; + if (0 == lineFrameCount) + break; + } + if (*aIsReordered) + break; + } + } + + // If the line is reordered, identify the first and last frames on the line + if (*aIsReordered) { + nsRect nonUsedRect; + result = GetLine(aLine, &firstFrame, &lineFrameCount, nonUsedRect, &lineFlags); + if (NS_FAILED(result)) + return result; + + leftmostFrame = rightmostFrame = firstFrame; + firstFrame->GetRect(checkRect); + maxX = checkRect.x; + minX = checkRect.x; + + for (;lineFrameCount > 1;lineFrameCount--) { + result = firstFrame->GetNextSibling(&firstFrame); + + if (NS_FAILED(result)){ + NS_ASSERTION(0,"should not be reached nsLineBox\n"); + return NS_ERROR_FAILURE; + } + + firstFrame->GetRect(checkRect); + if (checkRect.x > maxX) { + maxX = checkRect.x; + rightmostFrame = firstFrame; + } + if (checkRect.x < minX) { + minX = checkRect.x; + leftmostFrame = firstFrame; + } + } + if (mRightToLeft) { + *aFirstVisual = rightmostFrame; + *aLastVisual = leftmostFrame; + } + else { + *aFirstVisual = leftmostFrame; + *aLastVisual = rightmostFrame; + } + } + return result; +} +#endif // IBMBIDI + NS_IMETHODIMP nsLineIterator::FindFrameAt(PRInt32 aLineNumber, nscoord aX, +#ifdef IBMBIDI + PRBool aCouldBeReordered, +#endif // IBMBIDI nsIFrame** aFrameFound, PRBool* aXIsBeforeFirstFrame, PRBool* aXIsAfterLastFrame) @@ -709,13 +825,51 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber, // when checking. *aXIsBeforeFirstFrame = PR_FALSE; *aXIsAfterLastFrame = PR_FALSE; +#ifdef IBMBIDI + PRBool isReordered = PR_FALSE; + nsIFrame *firstVisual, *lastVisual; + if (aCouldBeReordered) + CheckLineOrder(aLineNumber, &isReordered, &firstVisual, &lastVisual); +#endif nsRect r1, r2; nsIFrame* frame = line->mFirstChild; +#ifdef IBMBIDI + if (isReordered) + frame = firstVisual; +#endif // IBMBIDI PRInt32 n = line->GetChildCount(); if (mRightToLeft) { while (--n >= 0) { nsIFrame* nextFrame; - frame->GetNextSibling(&nextFrame); +#ifdef IBMBIDI + if (isReordered) { + nscoord maxX, limX; + PRInt32 testLine; + nsRect tempRect; + nsIFrame* tempFrame; + + maxX = -0x7fffffff; + frame->GetRect(tempRect); + + limX = tempRect.x; + tempFrame = line->mFirstChild; + nextFrame = nsnull; + + while (tempFrame) { + if (NS_SUCCEEDED(FindLineContaining(tempFrame, &testLine)) + && testLine == aLineNumber) { + tempFrame->GetRect(tempRect); + if (tempRect.x > maxX && tempRect.x < limX) { // we are looking for the highest value less than the current one + maxX = tempRect.x; + nextFrame = tempFrame; + } + } + tempFrame->GetNextSibling(&tempFrame); + } + } + else +#endif // IBMBIDI + frame->GetNextSibling(&nextFrame); frame->GetRect(r1); if (aX > r1.x) { break; @@ -740,6 +894,34 @@ nsLineIterator::FindFrameAt(PRInt32 aLineNumber, else { while (--n >= 0) { nsIFrame* nextFrame; +#ifdef IBMBIDI + if (isReordered) { + nsRect tempRect; + nsIFrame* tempFrame; + PRInt64 minX, limX; + PRInt32 testLine; + + minX = 0x7fffffff; + frame->GetRect(tempRect); + + limX = tempRect.x; + tempFrame = line->mFirstChild; + nextFrame = nsnull; + + while (tempFrame) { + if (NS_SUCCEEDED(FindLineContaining(tempFrame, &testLine)) + && testLine == aLineNumber) { + tempFrame->GetRect(tempRect); + if (tempRect.x < minX && tempRect.x > limX) { // we are looking for the lowest value greater than the current one + minX = tempRect.x; + nextFrame = tempFrame; + } + } + tempFrame->GetNextSibling(&tempFrame); + } + } + else +#endif // IBMBIDI frame->GetNextSibling(&nextFrame); frame->GetRect(r1); if (aX < r1.XMost()) { diff --git a/mozilla/layout/html/base/src/nsLineBox.h b/mozilla/layout/html/base/src/nsLineBox.h index 11f27d94a69..7bba265a2eb 100644 --- a/mozilla/layout/html/base/src/nsLineBox.h +++ b/mozilla/layout/html/base/src/nsLineBox.h @@ -412,12 +412,20 @@ public: PRInt32* aLineNumberResult); NS_IMETHOD FindFrameAt(PRInt32 aLineNumber, nscoord aX, +#ifdef IBMBIDI + PRBool aCouldBeReordered, +#endif nsIFrame** aFrameFound, PRBool* aXIsBeforeFirstFrame, PRBool* aXIsAfterLastFrame); NS_IMETHOD GetNextSiblingOnLine(nsIFrame*& aFrame, PRInt32 aLineNumber); - +#ifdef IBMBIDI + NS_IMETHOD CheckLineOrder(PRInt32 aLine, + PRBool *aIsReordered, + nsIFrame **aFirstVisual, + nsIFrame **aLastVisual); +#endif nsresult Init(nsLineBox* aLines, PRBool aRightToLeft); protected: diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 1bab0d8f383..3e18cf18117 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -135,6 +135,10 @@ // SubShell map #include "nsDST.h" +#ifdef IBMBIDI +#include "nsIBidiKeyboard.h" +#endif // IBMBIDI + #include "nsContentCID.h" static NS_DEFINE_CID(kCSSStyleSheetCID, NS_CSS_STYLESHEET_CID); static NS_DEFINE_CID(kStyleSetCID, NS_STYLESET_CID); @@ -886,6 +890,12 @@ public: NS_IMETHOD GetEventTargetFrame(nsIFrame** aFrame); NS_IMETHOD IsReflowLocked(PRBool* aIsLocked); +#ifdef IBMBIDI + NS_IMETHOD SetCursorBidiLevel(PRUint8 aLevel); + NS_IMETHOD GetCursorBidiLevel(PRUint8 *aOutLevel); + NS_IMETHOD UndefineCursorBidiLevel(); + NS_IMETHOD BidiStyleChangeReflow(); +#endif //nsIViewObserver interface @@ -1022,6 +1032,10 @@ protected: PRBool IsDragInProgress ( ) const ; PRBool mCaretEnabled; +#ifdef IBMBIDI + PRUint8 mBidiLevel; // The Bidi level of the cursor + nsCOMPtr mBidiKeyboard; +#endif // IBMBIDI #ifdef NS_DEBUG PRBool VerifyIncrementalReflow(); PRBool mInVerifyReflow; @@ -1246,6 +1260,9 @@ PresShell::PresShell():mAnonymousContentTable(nsnull), mReflowCountMgr->SetPresContext(mPresContext); mReflowCountMgr->SetPresShell(this); #endif +#ifdef IBMBIDI + mBidiLevel = BIDI_LEVEL_UNDEFINED; +#endif } NS_IMPL_ADDREF(PresShell) @@ -1479,6 +1496,9 @@ PresShell::Init(nsIDocument* aDocument, // cache the drag service so we can check it during reflows mDragService = do_GetService("@mozilla.org/widget/dragservice;1"); +#ifdef IBMBIDI + mBidiKeyboard = do_GetService("@mozilla.org/widget/bidikeyboard;1"); +#endif // setup the preference style rules up (no forced reflow) SetPreferenceStyleRules(PR_FALSE); @@ -4535,6 +4555,55 @@ PresShell::GetPlaceholderFrameFor(nsIFrame* aFrame, return rv; } +#ifdef IBMBIDI +NS_IMETHODIMP +PresShell::SetCursorBidiLevel(PRUint8 aLevel) +{ + // If the current level is undefined, we have just inserted new text. + // In this case, we don't want to reset the keyboard language + PRBool afterInsert = mBidiLevel & BIDI_LEVEL_UNDEFINED; + mBidiLevel = aLevel; + +// PRBool parityChange = ((mBidiLevel ^ aLevel) & 1); // is the parity of the new level different from the current level? +// if (parityChange) // if so, change the keyboard language + if (mBidiKeyboard && !afterInsert) + mBidiKeyboard->SetLangFromBidiLevel(aLevel); + return NS_OK; +} + +NS_IMETHODIMP +PresShell::GetCursorBidiLevel(PRUint8 *aOutLevel) +{ + if (!aOutLevel) { return NS_ERROR_INVALID_ARG; } + *aOutLevel = mBidiLevel; + return NS_OK; +} + +NS_IMETHODIMP +PresShell::UndefineCursorBidiLevel() +{ + mBidiLevel |= BIDI_LEVEL_UNDEFINED; + return NS_OK; +} + +NS_IMETHODIMP +PresShell::BidiStyleChangeReflow() +{ + // Have the root frame's style context remap its style + nsIFrame* rootFrame; + mFrameManager->GetRootFrame(&rootFrame); + + if (rootFrame) { + nsIStyleContext* rootStyleContext; + rootFrame->GetStyleContext(&rootStyleContext); + rootStyleContext->RemapStyle(mPresContext.get() ); + NS_RELEASE(rootStyleContext); + + ReconstructFrames(); + } + return NS_OK; +} +#endif // IBMBIDI //nsIViewObserver