/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* $Id$ */

package org.apache.fop.layoutmgr.inline;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.apache.fop.area.Area;
import org.apache.fop.area.LineArea;
import org.apache.fop.area.Trait;
import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.complexscripts.bidi.BidiResolver;
import org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.Numeric;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.flow.Block;
import org.apache.fop.fo.properties.CommonHyphenation;
import org.apache.fop.fo.properties.KeepProperty;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.hyphenation.Hyphenation;
import org.apache.fop.hyphenation.Hyphenator;
import org.apache.fop.layoutmgr.Adjustment;
import org.apache.fop.layoutmgr.BlockLayoutManager;
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.BreakingAlgorithm;
import org.apache.fop.layoutmgr.ElementListObserver;
import org.apache.fop.layoutmgr.FloatContentLayoutManager;
import org.apache.fop.layoutmgr.FootenoteUtil;
import org.apache.fop.layoutmgr.FootnoteBodyLayoutManager;
import org.apache.fop.layoutmgr.InlineKnuthSequence;
import org.apache.fop.layoutmgr.Keep;
import org.apache.fop.layoutmgr.KnuthBlockBox;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthGlue;
import org.apache.fop.layoutmgr.KnuthPenalty;
import org.apache.fop.layoutmgr.KnuthPossPosIter;
import org.apache.fop.layoutmgr.KnuthSequence;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.LeafPosition;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.SpaceSpecifier;
import org.apache.fop.traits.MinOptMax;

/**
 * LayoutManager for lines. It builds one or more lines containing
 * inline areas generated by its sub layout managers.
 * A break is found for each line which may contain one of more
 * breaks from the child layout managers.
 * Once a break is found then it is return for the parent layout
 * manager to handle.
 * When the areas are being added to the page this manager
 * creates a line area to contain the inline areas added by the
 * child layout managers.
 */
public class LineLayoutManager extends InlineStackingLayoutManager
                               implements BlockLevelLayoutManager {

    /**
     * this constant is used to create elements when text-align is center:
     * every TextLM descendant of LineLM must use the same value,
     * otherwise the line breaking algorithm does not find the right
     * break point
     */
    public static final int DEFAULT_SPACE_WIDTH = 3336;

    /**
     * logging instance
     */
    private static Log log = LogFactory.getLog(LineLayoutManager.class);

    private final Block fobj;
    private boolean isFirstInBlock;

    /**
     * Private class to store information about inline breaks.
     * Each value holds the start and end indexes into a List of
     * inline break positions.
     */
    static class LineBreakPosition extends LeafPosition {
        private final int parIndex; // index of the Paragraph this Position refers to
        private final int startIndex; //index of the first element this Position refers to
        private final int availableShrink;
        private final int availableStretch;
        private final int difference;
        private final double dAdjust; // Percentage to adjust (stretch or shrink)
        private final double ipdAdjust; // Percentage to adjust (stretch or shrink)
        private final int startIndent;
        private final int endIndent;
        private final int lineHeight;
        private final int lineWidth;
        private final int spaceBefore;
        private final int spaceAfter;
        private final int baseline;

        LineBreakPosition(LayoutManager lm, int index, int startIndex, int breakIndex,
                int shrink, int stretch, int diff, double ipdA, double adjust, int si,
                int ei, int lh, int lw, int sb, int sa, int bl) {
            super(lm, breakIndex);
            availableShrink = shrink;
            availableStretch = stretch;
            difference = diff;
            parIndex = index;
            this.startIndex = startIndex;
            ipdAdjust = ipdA;
            dAdjust = adjust;
            startIndent = si;
            endIndent = ei;
            lineHeight = lh;
            lineWidth = lw;
            spaceBefore = sb;
            spaceAfter = sa;
            baseline = bl;
        }

    }


    private int bidiLevel = -1;
    private int textAlignment = EN_JUSTIFY;
    private int textAlignmentLast;
    private int effectiveAlignment;
    private Length textIndent;
    private Length lastLineEndIndent;
    private CommonHyphenation hyphenationProperties;
    private Numeric hyphenationLadderCount;
    private int wrapOption = EN_WRAP;
    private int whiteSpaceTreament;
    //private LayoutProps layoutProps;

    private final Length lineHeight;
    private final int lead;
    private final int follow;
    private AlignmentContext alignmentContext;

    private int baselineOffset = -1;

    private List<KnuthSequence> knuthParagraphs;

    private LineLayoutPossibilities lineLayouts;
    private LineLayoutPossibilities[] lineLayoutsList;
    private int ipd;
    /**
     * When layout must be re-started due to a change of IPD, there is no need
     * to perform hyphenation on the remaining Knuth sequence once again.
     */
    private boolean hyphenationPerformed;

    /**
     * This class is used to remember
     * which was the first element in the paragraph
     * returned by each LM.
     */
    private final class Update {
        private final InlineLevelLayoutManager inlineLM;
        private final int firstIndex;

        private Update(InlineLevelLayoutManager lm, int index) {
            inlineLM = lm;
            firstIndex = index;
        }
    }

    // this class represents a paragraph
    private static class Paragraph extends InlineKnuthSequence {

        private static final long serialVersionUID = 5862072380375189105L;

        /** Number of elements to ignore at the beginning of the list. */
        private int ignoreAtStart;
        /** Number of elements to ignore at the end of the list. */
        private int ignoreAtEnd;

        // space at the end of the last line (in millipoints)
        private MinOptMax lineFiller;
        private final int textAlignment;
        private final int textAlignmentLast;
        private final int textIndent;
        private final int lastLineEndIndent;
        // the LM which created the paragraph
        private final LineLayoutManager layoutManager;

        Paragraph(LineLayoutManager llm, int alignment, int alignmentLast,
                         int indent, int endIndent) {
            super();
            layoutManager = llm;
            textAlignment = alignment;
            textAlignmentLast = alignmentLast;
            textIndent = indent;
            lastLineEndIndent = endIndent;
        }

        @Override
        public void startSequence() {
            // set the minimum amount of empty space at the end of the
            // last line
            if (textAlignment == EN_CENTER) {
                lineFiller = MinOptMax.getInstance(lastLineEndIndent);
            } else {
                lineFiller = MinOptMax.getInstance(lastLineEndIndent, lastLineEndIndent,
                        layoutManager.ipd);
            }

            // add auxiliary elements at the beginning of the paragraph
            if (textAlignment == EN_CENTER && textAlignmentLast != EN_JUSTIFY) {
                this.add(new KnuthGlue(0, 3 * DEFAULT_SPACE_WIDTH, 0,
                                       null, false));
                ignoreAtStart++;
            }

            // add the element representing text indentation
            // at the beginning of the first paragraph
            if (layoutManager.isFirstInBlock && layoutManager.knuthParagraphs.size() == 0
                        && textIndent != 0) {
                this.add(new KnuthInlineBox(textIndent, null,
                                      null, false));
                ignoreAtStart++;
            }
        }

        public void endParagraph() {
            KnuthSequence finishedPar = this.endSequence();
            if (finishedPar != null) {
                layoutManager.knuthParagraphs.add(finishedPar);
            }
        }

        @Override
        public KnuthSequence endSequence() {
            if (this.size() > ignoreAtStart) {
                if (textAlignment == EN_CENTER
                    && textAlignmentLast != EN_JUSTIFY) {
                    this.add(new KnuthGlue(0, 3 * DEFAULT_SPACE_WIDTH, 0,
                                           null, false));
                    this.add(new KnuthPenalty(lineFiller.getOpt(), -KnuthElement.INFINITE,
                                              false, null, false));
                    ignoreAtEnd = 2;
                } else if (textAlignmentLast != EN_JUSTIFY) {
                    // add the elements representing the space
                    // at the end of the last line
                    // and the forced break
                    this.add(new KnuthPenalty(0, KnuthElement.INFINITE,
                                              false, null, false));
                    this.add(new KnuthGlue(0,
                            lineFiller.getStretch(),
                            lineFiller.getShrink(), null, false));
                    this.add(new KnuthPenalty(lineFiller.getOpt(), -KnuthElement.INFINITE,
                                              false, null, false));
                    ignoreAtEnd = 3;
                } else {
                    // add only the element representing the forced break
                    this.add(new KnuthPenalty(lineFiller.getOpt(), -KnuthElement.INFINITE,
                                              false, null, false));
                    ignoreAtEnd = 1;
                }
                return this;
            } else {
                this.clear();
                return null;
            }
        }

        /**
         * @return true if the sequence contains a box
         */
        public boolean containsBox() {
            for (Object o : this) {
                KnuthElement el = (KnuthElement) o;
                if (el.isBox()) {
                    return true;
                }
            }
            return false;
        }
    }

    private class LineBreakingAlgorithm extends BreakingAlgorithm {
        private final LineLayoutManager thisLLM;
        private final int pageAlignment;
        private int activePossibility;
        private int addedPositions;
        private final int textIndent;
        private final int lineHeight;
        private final int lead;
        private final int follow;
        private static final double MAX_DEMERITS = 10e6;

        public LineBreakingAlgorithm(int pageAlign, int textAlign, int textAlignLast, int indent, int fillerWidth,
                int lh, int ld, int fl, boolean first, int maxFlagCount, LineLayoutManager llm) {
            super(textAlign, textAlignLast, first, false, maxFlagCount);
            pageAlignment = pageAlign;
            textIndent = indent;
            lineHeight = lh;
            lead = ld;
            follow = fl;
            thisLLM = llm;
            activePossibility = -1;
        }

        @Override
        public void updateData1(int lineCount, double demerits) {
            lineLayouts.addPossibility(lineCount, demerits);
            if (log.isTraceEnabled()) {
                log.trace("Layout possibility in " + lineCount + " lines; break at position:");
            }
        }

        @Override
        public void updateData2(KnuthNode bestActiveNode,
                                KnuthSequence par,
                                int total) {
            // compute indent and adjustment ratio, according to
            // the value of text-align and text-align-last
            int startIndent;
            int endIndent;
            int difference = bestActiveNode.difference;
            int textAlign = (bestActiveNode.line < total) ? alignment : alignmentLast;

            switch (textAlign) {
            case Constants.EN_START:
                startIndent = 0;
                endIndent = difference > 0 ? difference : 0;
                break;
            case Constants.EN_END:
                startIndent = difference;
                endIndent = 0;
                break;
            case Constants.EN_CENTER:
                startIndent = difference / 2;
                endIndent = startIndent;
                break;
            default:
            case Constants.EN_JUSTIFY:
                startIndent = 0;
                endIndent = 0;
                break;
            }

            /*
            startIndent += (textAlign == Constants.EN_CENTER)
                      ? difference / 2 : (textAlign == Constants.EN_END) ? difference : 0;
            */
            startIndent += (bestActiveNode.line == 1 && indentFirstPart && isFirstInBlock)
                      ? textIndent : 0;

            double ratio = (textAlign == Constants.EN_JUSTIFY
                || difference < 0 && -difference <= bestActiveNode.availableShrink)
                        ? bestActiveNode.adjustRatio : 0;

            // add nodes at the beginning of the list, as they are found
            // backwards, from the last one to the first one

            // the first time this method is called, initialize activePossibility
            if (activePossibility == -1) {
                activePossibility = 0;
                addedPositions = 0;
            }

            if (addedPositions == lineLayouts.getLineCount(activePossibility)) {
                activePossibility++;
                addedPositions = 0;
            }

            int lack = difference + bestActiveNode.availableShrink;
            // if this LLM is nested inside a BlockContainerLayoutManager that is constraining
            // the available width and thus responsible for the overflow then we do not issue
            // warning event here and instead let the BCLM handle that at a later stage
            if (lack < 0 && !handleOverflow(-lack)) {
                InlineLevelEventProducer eventProducer
                    = InlineLevelEventProducer.Provider.get(
                        getFObj().getUserAgent().getEventBroadcaster());
                if (curChildLM.getFObj() == null) {
                    eventProducer.lineOverflows(this, getFObj().getName(), bestActiveNode.line,
                            -lack, getFObj().getLocator());
                } else {
                    eventProducer.lineOverflows(this, curChildLM.getFObj().getName(), bestActiveNode.line,
                        -lack, curChildLM.getFObj().getLocator());
                }
            }

            //log.debug("LLM> (" + (lineLayouts.getLineNumber(activePossibility) - addedPositions)
            //    + ") difference = " + difference + " ratio = " + ratio);
            lineLayouts.addBreakPosition(makeLineBreakPosition(par,
                   (bestActiveNode.line > 1 ? bestActiveNode.previous.position + 1 : 0),
                   bestActiveNode.position,
                   bestActiveNode.availableShrink - (addedPositions > 0
                       ? 0 : ((Paragraph) par).lineFiller.getShrink()),
                   bestActiveNode.availableStretch,
                   difference, ratio, startIndent, endIndent), activePossibility);
            addedPositions++;
        }

        /* reset activePossibility, as if breakpoints have not yet been computed
         */
        public void resetAlgorithm() {
            activePossibility = -1;
        }

        private LineBreakPosition makeLineBreakPosition(KnuthSequence par, int firstElementIndex, int lastElementIndex,
                int availableShrink, int availableStretch, int difference, double ratio,
                int startIndent, int endIndent) {
            // line height calculation - spaceBefore may differ from spaceAfter
            // by 1mpt due to rounding
            int spaceBefore = (lineHeight - lead - follow) / 2;
            int spaceAfter = lineHeight - lead - follow - spaceBefore;
            // height before the main baseline
            int lineLead = lead;
            // maximum follow
            int lineFollow = follow;
            // true if this line contains only zero-height, auxiliary boxes
            // and the actual line width is 0; in this case, the line "collapses"
            // i.e. the line area will have bpd = 0
            boolean isZeroHeightLine = (difference == ipd);

            // if line-stacking-strategy is "font-height", the line height
            // is not affected by its content
            if (fobj.getLineStackingStrategy() != EN_FONT_HEIGHT) {
                ListIterator inlineIterator
                    = par.listIterator(firstElementIndex);
                AlignmentContext lastAC = null;
                int maxIgnoredHeight = 0; // See spec 7.13
                for (int j = firstElementIndex;
                     j <= lastElementIndex;
                     j++) {
                    KnuthElement element = (KnuthElement) inlineIterator.next();
                    if (element instanceof KnuthInlineBox) {
                        AlignmentContext ac = ((KnuthInlineBox) element).getAlignmentContext();
                        if (ac != null && lastAC != ac) {
                            if (!ac.usesInitialBaselineTable()
                                || ac.getAlignmentBaselineIdentifier() != EN_BEFORE_EDGE
                                   && ac.getAlignmentBaselineIdentifier() != EN_AFTER_EDGE) {
                                if (fobj.getLineHeightShiftAdjustment() == EN_CONSIDER_SHIFTS
                                    || ac.getBaselineShiftValue() == 0) {
                                    int alignmentOffset = ac.getTotalAlignmentBaselineOffset();
                                    if (alignmentOffset + ac.getAltitude() > lineLead) {
                                        lineLead = alignmentOffset + ac.getAltitude();
                                    }
                                    if (ac.getDepth() - alignmentOffset > lineFollow)  {
                                        lineFollow = ac.getDepth() - alignmentOffset;
                                    }
                                }
                            } else {
                                if (ac.getHeight() > maxIgnoredHeight) {
                                    maxIgnoredHeight = ac.getHeight();
                                }
                            }
                            lastAC = ac;
                        }
                        if (isZeroHeightLine
                            && (!element.isAuxiliary() || ac != null && ac.getHeight() > 0)) {
                            isZeroHeightLine = false;
                        }
                    }
                }

                if (lineFollow < maxIgnoredHeight - lineLead) {
                    lineFollow = maxIgnoredHeight - lineLead;
                }
            }

            constantLineHeight = lineLead + lineFollow;

            if (isZeroHeightLine) {
                return new LineBreakPosition(thisLLM,
                                             knuthParagraphs.indexOf(par),
                                             firstElementIndex, lastElementIndex,
                                             availableShrink, availableStretch,
                                             difference, ratio, 0, startIndent, endIndent,
                                             0, ipd, 0, 0, 0);
            } else {
                return new LineBreakPosition(thisLLM,
                                             knuthParagraphs.indexOf(par),
                                             firstElementIndex, lastElementIndex,
                                             availableShrink, availableStretch,
                                             difference, ratio, 0, startIndent, endIndent,
                                             lineLead + lineFollow,
                                             ipd, spaceBefore, spaceAfter,
                                             lineLead);
            }
        }

        @Override
        protected int filterActiveNodes() {
            KnuthNode bestActiveNode = null;

            if (pageAlignment == EN_JUSTIFY) {
                // leave all active nodes and find the optimum line number
                //log.debug("LBA.filterActiveNodes> " + activeNodeCount + " layouts");
                for (int i = startLine; i < endLine; i++) {
                    for (KnuthNode node = getNode(i); node != null; node = node.next) {
                        //log.debug("                       + lines = "
                        //+ node.line + " demerits = " + node.totalDemerits);
                        bestActiveNode = compareNodes(bestActiveNode, node);
                    }
                }

                // scan the node set once again and remove some nodes
                //log.debug("LBA.filterActiveList> layout selection");
                for (int i = startLine; i < endLine; i++) {
                    for (KnuthNode node = getNode(i); node != null; node = node.next) {
                        //if (Math.abs(node.line - bestActiveNode.line) > maxDiff) {
                        //if (false) {
                        if (node.line != bestActiveNode.line
                            && node.totalDemerits > MAX_DEMERITS) {
                            //log.debug("                     XXX lines = "
                            //+ node.line + " demerits = " + node.totalDemerits);
                            removeNode(i, node);
                        } else {
                            //log.debug("                      ok lines = "
                            //+ node.line + " demerits = " + node.totalDemerits);
                        }
                    }
                }
            } else {
                // leave only the active node with fewest total demerits
                for (int i = startLine; i < endLine; i++) {
                    for (KnuthNode node = getNode(i); node != null; node = node.next) {
                        bestActiveNode = compareNodes(bestActiveNode, node);
                        if (node != bestActiveNode) {
                            removeNode(i, node);
                        }
                    }
                }
            }
            return bestActiveNode.line;
        }
    }


    private int constantLineHeight = 12000;

    /**
     * Create a new Line Layout Manager.
     * This is used by the block layout manager to create
     * line managers for handling inline areas flowing into line areas.
     * @param block the block formatting object
     * @param lh the default line height
     * @param l the default lead, from top to baseline
     * @param f the default follow, from baseline to bottom
     */
    public LineLayoutManager(Block block, Length lh, int l, int f) {
        super(block);
        fobj = block;
        // the child FObj are owned by the parent BlockLM
        // this LM has all its childLMs preloaded
        fobjIter = null;
        lineHeight = lh;
        lead = l;
        follow = f;
    }

    /** {@inheritDoc} */
    @Override
    public void initialize() {
        bidiLevel = fobj.getBidiLevel();
        textAlignment = fobj.getTextAlign();
        textAlignmentLast = fobj.getTextAlignLast();
        textIndent = fobj.getTextIndent();
        lastLineEndIndent = fobj.getLastLineEndIndent();
        hyphenationProperties = fobj.getCommonHyphenation();
        hyphenationLadderCount = fobj.getHyphenationLadderCount();
        wrapOption = fobj.getWrapOption();
        whiteSpaceTreament = fobj.getWhitespaceTreatment();
        //
        effectiveAlignment = getEffectiveAlignment(textAlignment, textAlignmentLast);
        isFirstInBlock = (this == getParent().getChildLMs().get(0));
    }

    private int getEffectiveAlignment(int alignment, int alignmentLast) {
        if (textAlignment != EN_JUSTIFY && textAlignmentLast == EN_JUSTIFY) {
            return 0;
        } else {
            return textAlignment;
        }
    }

    /** {@inheritDoc} */
    @Override
    public List getNextKnuthElements(LayoutContext context, int alignment) {
        if (alignmentContext == null) {
            FontInfo fi = fobj.getFOEventHandler().getFontInfo();
            FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
            Font fs = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
            alignmentContext = new AlignmentContext(fs, lineHeight.getValue(this),
                    context.getWritingMode());
        }
        context.setAlignmentContext(alignmentContext);
        ipd = context.getRefIPD();

        //PHASE 1: Create Knuth elements
        if (knuthParagraphs == null) {
            // it's the first time this method is called
            knuthParagraphs = new ArrayList<KnuthSequence>();

            // here starts Knuth's algorithm
            collectInlineKnuthElements(context);
        } else {
            // this method has been called before
            // all line breaks are already calculated
        }

        // return finished when there's no content
        if (knuthParagraphs.size() == 0) {
            setFinished(true);
            return null;
        }

        //PHASE 2: Create line breaks
        return createLineBreaks(context.getBPAlignment(), context);
    }

    /**
     * Get a sequence of KnuthElements representing the content
     * of the node assigned to the LM.
     * @param context   the LayoutContext used to store layout information
     * @param alignment the desired text alignment
     * @param restartPosition position at restart
     * @return the list of KnuthElements
     * @see LayoutManager#getNextKnuthElements(LayoutContext,int)
     */
    public List getNextKnuthElements(LayoutContext context, int alignment,
            LeafPosition restartPosition) {
        log.trace("Restarting line breaking from index " + restartPosition.getIndex());
        int parIndex = restartPosition.getLeafPos();

        for (int i = 0; i < parIndex; i++) {
            knuthParagraphs.remove(0);
        }
        parIndex = 0;

        KnuthSequence paragraph = knuthParagraphs.get(parIndex);
        if (paragraph instanceof Paragraph) {
            ((Paragraph) paragraph).ignoreAtStart = 0;
            isFirstInBlock = false;
        }
        paragraph.subList(0, restartPosition.getIndex() + 1).clear();
        Iterator<KnuthElement> iter = paragraph.iterator();
        while (iter.hasNext() && !iter.next().isBox()) {
            iter.remove();
        }
        if (!iter.hasNext()) {
            knuthParagraphs.remove(parIndex);
        }

        // return finished when there's no content
        if (knuthParagraphs.size() == 0) {
            setFinished(true);
            return null;
        }

        ipd = context.getRefIPD();
        //PHASE 2: Create line breaks
        return createLineBreaks(context.getBPAlignment(), context);
    }

    /**
     * Phase 1 of Knuth algorithm: Collect all inline Knuth elements before determining line breaks.
     * @param context the LayoutContext
     */
    private void collectInlineKnuthElements(LayoutContext context) {
        LayoutContext inlineLC = LayoutContext.copyOf(context);

        // convert all the text in a sequence of paragraphs made
        // of KnuthBox, KnuthGlue and KnuthPenalty objects
        boolean previousIsBox = false;

        StringBuffer trace = new StringBuffer("LineLM:");

        Paragraph lastPar = null;

        InlineLevelLayoutManager curLM;
        while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
            List inlineElements = curLM.getNextKnuthElements(inlineLC, effectiveAlignment);
            if (inlineElements == null || inlineElements.size() == 0) {
                /* curLM.getNextKnuthElements() returned null or an empty list;
                 * this can happen if there is nothing more to layout,
                 * so just iterate once more to see if there are other children */
                continue;
            }

            if (lastPar != null) {
                KnuthSequence firstSeq = (KnuthSequence) inlineElements.get(0);

                // finish last paragraph before a new block sequence
                if (!firstSeq.isInlineSequence()) {
                    lastPar.endParagraph();
                    ElementListObserver.observe(lastPar, "line", null);
                    lastPar = null;
                    if (log.isTraceEnabled()) {
                        trace.append(" ]");
                    }
                    previousIsBox = false;
                }

                // does the first element of the first paragraph add to an existing word?
                if (lastPar != null) {
                    KnuthElement thisElement;
                    thisElement = (KnuthElement) firstSeq.get(0);
                    if (thisElement.isBox() && !thisElement.isAuxiliary()
                            && previousIsBox) {
                        lastPar.addALetterSpace();
                    }
                }
            }

            // loop over the KnuthSequences (and single KnuthElements) in returnedList
            for (Object inlineElement : inlineElements) {
                KnuthSequence sequence = (KnuthSequence) inlineElement;
                // the sequence contains inline Knuth elements
                if (sequence.isInlineSequence()) {
                    // look at the last element
                    ListElement lastElement = sequence.getLast();
                    assert lastElement != null;
                    previousIsBox = lastElement.isBox()
                            && !((KnuthElement) lastElement).isAuxiliary()
                            && ((KnuthElement) lastElement).getWidth() != 0;

                    // if last paragraph is open, add the new elements to the paragraph
                    // else this is the last paragraph
                    if (lastPar == null) {
                        lastPar = new Paragraph(this,
                                textAlignment, textAlignmentLast,
                                textIndent.getValue(this),
                                lastLineEndIndent.getValue(this));
                        lastPar.startSequence();
                        if (log.isTraceEnabled()) {
                            trace.append(" [");
                        }
                    } else {
                        if (log.isTraceEnabled()) {
                            trace.append(" +");
                        }
                    }
                    lastPar.addAll(sequence);
                    if (log.isTraceEnabled()) {
                        trace.append(" I");
                    }

                    // finish last paragraph if it was closed with a linefeed
                    if (lastElement.isPenalty()
                            && ((KnuthPenalty) lastElement).getPenalty()
                            == -KnuthPenalty.INFINITE) {
                        // a penalty item whose value is -inf
                        // represents a preserved linefeed,
                        // which forces a line break
                        lastPar.removeLast();
                        if (!lastPar.containsBox()) {
                            //only a forced linefeed on this line
                            //-> compensate with an auxiliary glue
                            lastPar.add(new KnuthGlue(ipd, 0, ipd, null, true));
                        }
                        lastPar.endParagraph();
                        ElementListObserver.observe(lastPar, "line", null);
                        lastPar = null;
                        if (log.isTraceEnabled()) {
                            trace.append(" ]");
                        }
                        previousIsBox = false;
                    }
                } else { // the sequence is a block sequence
                    // the positions will be wrapped with this LM in postProcessLineBreaks
                    knuthParagraphs.add(sequence);
                    if (log.isTraceEnabled()) {
                        trace.append(" B");
                    }
                }
            } // end of loop over returnedList
        }

        if (lastPar != null) {
            lastPar.endParagraph();
            ElementListObserver.observe(lastPar, "line", fobj.getId());
            if (log.isTraceEnabled()) {
                trace.append(" ]");
            }
        }
        log.trace(trace);
    }

    /**
     * Phase 2 of Knuth algorithm: find optimal break points.
     * @param alignment alignment in BP direction of the paragraph
     * @param context the layout context
     * @return a list of Knuth elements representing broken lines
     */
    private List<ListElement> createLineBreaks(int alignment, LayoutContext context) {
        // find the optimal line breaking points for each paragraph
        Iterator<KnuthSequence> paragraphsIterator = knuthParagraphs.iterator();
        lineLayoutsList = new LineLayoutPossibilities[knuthParagraphs.size()];
        LineLayoutPossibilities llPoss;
        for (int i = 0; paragraphsIterator.hasNext(); i++) {
            KnuthSequence seq = paragraphsIterator.next();
            if (!seq.isInlineSequence()) {
                // This set of line layout possibilities does not matter;
                // we only need an entry in lineLayoutsList.
                llPoss = new LineLayoutPossibilities();
            } else {
                llPoss = findOptimalBreakingPoints(alignment, (Paragraph) seq,
                                                   !paragraphsIterator.hasNext());
            }
            lineLayoutsList[i] = llPoss;
        }

        setFinished(true);

        //Post-process the line breaks found
        return postProcessLineBreaks(alignment, context);
    }

    /**
     * Find the optimal linebreaks for a paragraph
     * @param alignment alignment of the paragraph
     * @param currPar the Paragraph for which the linebreaks are found
     * @param isLastPar flag indicating whether currPar is the last paragraph
     * @return the line layout possibilities for the paragraph
     */
    private LineLayoutPossibilities findOptimalBreakingPoints(int alignment, Paragraph currPar,
                                                              boolean isLastPar) {
        // use the member lineLayouts, which is read by LineBreakingAlgorithm.updateData1 and 2
        lineLayouts = new LineLayoutPossibilities();
        double maxAdjustment = 1;
        LineBreakingAlgorithm alg = new LineBreakingAlgorithm(alignment,
                                        textAlignment, textAlignmentLast,
                                        textIndent.getValue(this), currPar.lineFiller.getOpt(),
                                        lineHeight.getValue(this), lead, follow,
                                        (knuthParagraphs.indexOf(currPar) == 0),
                                        hyphenationLadderCount.getEnum() == EN_NO_LIMIT
                                            ? 0 : hyphenationLadderCount.getValue(),
                                        this);
        alg.setConstantLineWidth(ipd);
        boolean canWrap = (wrapOption != EN_NO_WRAP);
        boolean canHyphenate = (canWrap && hyphenationProperties.hyphenate.getEnum() == EN_TRUE);

        // find hyphenation points, if allowed and not yet done
        if (canHyphenate && !hyphenationPerformed) {
            // make sure findHyphenationPoints() is bypassed if
            // the method is called twice (e.g. due to changing page-ipd)
            hyphenationPerformed = isLastPar;
            findHyphenationPoints(currPar);
        }

        // first try: do not consider hyphenation points as legal breaks
        int allowedBreaks = (canWrap ? BreakingAlgorithm.NO_FLAGGED_PENALTIES
                : BreakingAlgorithm.ONLY_FORCED_BREAKS);
        int breakingPoints = alg.findBreakingPoints(currPar, maxAdjustment, false, allowedBreaks);

        if (breakingPoints == 0 || alignment == EN_JUSTIFY) {
            // if the first try found a set of breaking points, save them
            if (breakingPoints > 0) {
                alg.resetAlgorithm();
                lineLayouts.savePossibilities(false);
            } else {
                // the first try failed
                log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment);
            }

            // now try something different
            log.debug("Hyphenation possible? " + canHyphenate);
            // Note: if allowedBreaks is guaranteed to be unchanged by alg.findBreakingPoints(),
            // the below check can be simplified to 'if (canHyphenate) ...'
            if (canHyphenate && allowedBreaks != BreakingAlgorithm.ONLY_FORCED_BREAKS) {
                // consider every hyphenation point as a legal break
                allowedBreaks = BreakingAlgorithm.ALL_BREAKS;
            } else {
                // try with a higher threshold
                maxAdjustment = 5;
            }

            breakingPoints = alg.findBreakingPoints(currPar, maxAdjustment, false, allowedBreaks);
            if (breakingPoints == 0) {
                // the second try failed too, try with a huge threshold
                // and force the algorithm to find a set of breaking points
                if (log.isDebugEnabled()) {
                    log.debug("No set of breaking points found with maxAdjustment = "
                            + maxAdjustment + (canHyphenate ? " and hyphenation" : ""));
                }
                maxAdjustment = 20;
                alg.findBreakingPoints(currPar, maxAdjustment, true, allowedBreaks);
            }

            // use non-hyphenated breaks, when possible
            lineLayouts.restorePossibilities();
        }

        return lineLayouts;
    }

    /**
     * Creates the element list in BP direction for the broken lines.
     * @param alignment the currently applicable vertical alignment
     * @param context the layout context
     * @return the newly built element list
     */
    private List<ListElement> postProcessLineBreaks(int alignment, LayoutContext context) {

        List<ListElement> returnList = new LinkedList<ListElement>();

        int endIndex = -1;
        for (int p = 0; p < knuthParagraphs.size(); p++) {
            // penalty between paragraphs
            if (p > 0) {
                Keep keep = getKeepTogether();
                returnList.add(new BreakElement(
                            new Position(this),
                            keep.getPenalty(),
                            keep.getContext(),
                            context));
            }

            LineLayoutPossibilities llPoss = lineLayoutsList[p];
            KnuthSequence seq = knuthParagraphs.get(p);

            if (!seq.isInlineSequence()) {
                List<ListElement> targetList = new LinkedList<ListElement>();
                for (Object aSeq : seq) {
                    ListElement tempElement;
                    tempElement = (ListElement) aSeq;
                    LayoutManager lm = tempElement.getLayoutManager();
                    if (baselineOffset < 0 && lm != null && lm.hasLineAreaDescendant()) {
                        baselineOffset = lm.getBaselineOffset();
                    }
                    if (lm != this) {
                        tempElement.setPosition(notifyPos(new NonLeafPosition(this,
                                tempElement.getPosition())));
                    }
                    targetList.add(tempElement);
                }
                returnList.addAll(targetList);
            } else if (seq.isInlineSequence() && alignment == EN_JUSTIFY) {
                /* justified vertical alignment (not in the XSL FO recommendation):
                   create a multi-layout sequence whose elements will contain
                   a conventional Position */
                Position returnPosition = new LeafPosition(this, p);
                createElements(returnList, llPoss, returnPosition);
            } else {
                /* "normal" vertical alignment: create a sequence whose boxes
                   represent effective lines, and contain LineBreakPositions */
                int startIndex = 0;
                int previousEndIndex = 0;
                for (int i = 0;
                        i < llPoss.getChosenLineCount();
                        i++) {
                    int orphans = fobj.getOrphans();
                    int widows = fobj.getWidows();
                    if (handlingFloat()) {
                        orphans = 1;
                        widows = 1;
                    }
                    if (returnList.size() > 0
                            && i > 0 //if i==0 break generated above already
                            && i >= orphans && i <= llPoss.getChosenLineCount() - widows) {
                        // penalty allowing a page break between lines
                        Keep keep = getKeepTogether();
                        returnList.add(new BreakElement(
                                new LeafPosition(this, p, endIndex),
                                    keep.getPenalty(),
                                    keep.getContext(),
                                    context));
                    }
                    endIndex = llPoss.getChosenPosition(i).getLeafPos();
                    // create a list of the FootnoteBodyLM handling footnotes
                    // whose citations are in this line
                    List<FootnoteBodyLayoutManager> footnoteList = FootenoteUtil.getFootnotes(
                            seq, startIndex, endIndex);
                    List<FloatContentLayoutManager> floats = FloatContentLayoutManager.checkForFloats(seq,
                            startIndex, endIndex);
                    startIndex = endIndex + 1;
                    LineBreakPosition lbp = llPoss.getChosenPosition(i);
                    if (baselineOffset < 0) {
                        baselineOffset = lbp.spaceBefore + lbp.baseline;
                    }
                    if (floats.isEmpty()) {
                        returnList.add(new KnuthBlockBox(lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter,
                                footnoteList, lbp, false));
                    } else {
                        // add a line with height zero and no content and attach float to it
                        returnList.add(new KnuthBlockBox(0, Collections.emptyList(), null, false, floats));
                        // add a break element to signal that we should restart LB at this break
                        Keep keep = getKeepTogether();
                        returnList.add(new BreakElement(new LeafPosition(this, p, previousEndIndex), keep
                                .getPenalty(), keep.getContext(), context));
                        // add the original line where the float was but without the float now
                        returnList.add(new KnuthBlockBox(lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter,
                                footnoteList, lbp, false));
                    }
                    previousEndIndex = endIndex;
                }
            }
        }

        return returnList;
    }

    private void createElements(List<ListElement> list, LineLayoutPossibilities llPoss,
                                Position elementPosition) {
        /* number of normal, inner lines */
        int innerLines = 0;
        /* number of lines that can be used in order to fill more space */
        int optionalLines = 0;
        /* number of lines that can be used in order to fill more space
           only if the paragraph is not parted */
        int conditionalOptionalLines = 0;
        /* number of lines that can be omitted in order to fill less space */
        int eliminableLines = 0;
        /* number of lines that can be omitted in order to fill less space
           only if the paragraph is not parted */
        int conditionalEliminableLines = 0;
        /* number of the first unbreakable lines */
        int firstLines = fobj.getOrphans();
        /* number of the last unbreakable lines */
        int lastLines = fobj.getWidows();
        /* sub-sequence used to separate the elements representing different lines */
        List<KnuthElement> breaker = new LinkedList<KnuthElement>();

        /* comment out the next lines in order to test particular situations */
        if (fobj.getOrphans() + fobj.getWidows() <= llPoss.getMinLineCount()) {
            innerLines = llPoss.getMinLineCount() - (fobj.getOrphans() + fobj.getWidows());
            optionalLines = llPoss.getMaxLineCount() - llPoss.getOptLineCount();
            eliminableLines = llPoss.getOptLineCount() - llPoss.getMinLineCount();
        } else if (fobj.getOrphans() + fobj.getWidows() <= llPoss.getOptLineCount()) {
            optionalLines = llPoss.getMaxLineCount() - llPoss.getOptLineCount();
            eliminableLines = llPoss.getOptLineCount() - (fobj.getOrphans() + fobj.getWidows());
            conditionalEliminableLines
                    = (fobj.getOrphans() + fobj.getWidows()) - llPoss.getMinLineCount();
        } else if (fobj.getOrphans() + fobj.getWidows() <= llPoss.getMaxLineCount()) {
            optionalLines = llPoss.getMaxLineCount() - (fobj.getOrphans() + fobj.getWidows());
            conditionalOptionalLines
                    = (fobj.getOrphans() + fobj.getWidows()) - llPoss.getOptLineCount();
            conditionalEliminableLines = llPoss.getOptLineCount() - llPoss.getMinLineCount();
            firstLines -= conditionalOptionalLines;
        } else {
            conditionalOptionalLines = llPoss.getMaxLineCount() - llPoss.getOptLineCount();
            conditionalEliminableLines = llPoss.getOptLineCount() - llPoss.getMinLineCount();
            firstLines = llPoss.getOptLineCount();
            lastLines = 0;
        }
        /* comment out the previous lines in order to test particular situations */

        /* use these lines to test particular situations
        innerLines = 0;
        optionalLines = 1;
        conditionalOptionalLines = 2;
        eliminableLines = 0;
        conditionalEliminableLines = 0;
        firstLines = 1;
        lastLines = 3;
        */

        if (lastLines != 0
            && (conditionalOptionalLines > 0 || conditionalEliminableLines > 0)) {
            breaker.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false));
            breaker.add(new KnuthGlue(0, -conditionalOptionalLines * constantLineHeight,
                                        -conditionalEliminableLines * constantLineHeight,
                                        Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false));
            breaker.add(new KnuthPenalty(conditionalOptionalLines * constantLineHeight,
                                           0, false, elementPosition, false));
            breaker.add(new KnuthGlue(0, conditionalOptionalLines * constantLineHeight,
                                        conditionalEliminableLines * constantLineHeight,
                                        Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false));
        } else if (lastLines != 0) {
            breaker.add(new KnuthPenalty(0, 0, false, elementPosition, false));
        }

        // creation of the elements:
        // first group of lines
        list.add(new KnuthBox(firstLines * constantLineHeight, elementPosition,
                              (lastLines == 0
                               && conditionalOptionalLines == 0
                               && conditionalEliminableLines == 0)));
        if (conditionalOptionalLines > 0
            || conditionalEliminableLines > 0) {
            list.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false));
            list.add(new KnuthGlue(0, conditionalOptionalLines * constantLineHeight,
                                   conditionalEliminableLines * constantLineHeight,
                                   Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false));
            list.add(new KnuthBox(0, elementPosition, (lastLines == 0)));
        }

        // optional lines
        for (int i = 0; i < optionalLines; i++) {
            list.addAll(breaker);
            list.add(new KnuthBox(0, elementPosition, false));
            list.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false));
            list.add(new KnuthGlue(0, constantLineHeight, 0,
                                   Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false));
            list.add(new KnuthBox(0, elementPosition, false));
        }

        // eliminable lines
        for (int i = 0; i < eliminableLines; i++) {
            list.addAll(breaker);
            list.add(new KnuthBox(constantLineHeight, elementPosition, false));
            list.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false));
            list.add(new KnuthGlue(0, 0, constantLineHeight,
                                   Adjustment.LINE_NUMBER_ADJUSTMENT, elementPosition, false));
            list.add(new KnuthBox(0, elementPosition, false));
        }

        // inner lines
        for (int i = 0; i < innerLines; i++) {
            list.addAll(breaker);
            list.add(new KnuthBox(constantLineHeight, elementPosition, false));
        }

        // last group of lines
        if (lastLines > 0) {
            list.addAll(breaker);
            list.add(new KnuthBox(lastLines * constantLineHeight,
                                  elementPosition, true));
        }
    }

    /** {@inheritDoc} */
    public boolean mustKeepTogether() {
        return ((BlockLevelLayoutManager) getParent()).mustKeepTogether();
    }

    /** {@inheritDoc} */
    public KeepProperty getKeepTogetherProperty() {
        return ((BlockLevelLayoutManager) getParent()).getKeepTogetherProperty();
    }

    /** {@inheritDoc} */
    public KeepProperty getKeepWithPreviousProperty() {
        return ((BlockLevelLayoutManager) getParent()).getKeepWithPreviousProperty();
    }

    /** {@inheritDoc} */
    public KeepProperty getKeepWithNextProperty() {
        return ((BlockLevelLayoutManager) getParent()).getKeepWithNextProperty();
    }

    /** {@inheritDoc} */
    public Keep getKeepTogether() {
        return ((BlockLevelLayoutManager) getParent()).getKeepTogether();
    }

    /** {@inheritDoc} */
    public boolean mustKeepWithPrevious() {
        return !getKeepWithPrevious().isAuto();
    }

    /** {@inheritDoc} */
    public boolean mustKeepWithNext() {
        return !getKeepWithNext().isAuto();
    }

    /** {@inheritDoc} */
    public Keep getKeepWithNext() {
        return Keep.KEEP_AUTO;
    }

    /** {@inheritDoc} */
    public Keep getKeepWithPrevious() {
        return Keep.KEEP_AUTO;
    }

    /** {@inheritDoc} */
    public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) {
        Position lastPos = lastElement.getPosition();
        assert (lastPos instanceof LeafPosition);
        LeafPosition pos = (LeafPosition) lastPos;
        //if (lastElement.isPenalty()) {
        //    totalAdj += lastElement.getWidth();
        //}
        //int lineNumberDifference = (int)((double) totalAdj / constantLineHeight);
        int lineNumberDifference = (int) Math.round((double) adj / constantLineHeight
                                                    + (adj > 0 ? -0.4 : 0.4));
        //log.debug("   LLM> variazione calcolata = " + ((double) totalAdj / constantLineHeight)
        //+ " variazione applicata = " + lineNumberDifference);
        LineLayoutPossibilities llPoss;
        llPoss = lineLayoutsList[pos.getLeafPos()];
        lineNumberDifference = llPoss.applyLineCountAdjustment(lineNumberDifference);
        return lineNumberDifference * constantLineHeight;
    }

    /** {@inheritDoc} */
    public void discardSpace(KnuthGlue spaceGlue) {
    }

    /** {@inheritDoc} */
    @Override
    public List getChangedKnuthElements(List oldList, int alignment, int depth) {
        return getChangedKnuthElements(oldList, alignment);
    }

    /** {@inheritDoc} */
    @Override
    public List getChangedKnuthElements(List oldList, int alignment) {
        List<KnuthElement> returnList = new LinkedList<KnuthElement>();
        for (int p = 0; p < knuthParagraphs.size(); p++) {
            LineLayoutPossibilities llPoss = lineLayoutsList[p];
            //log.debug("demerits of the chosen layout: " + llPoss.getChosenDemerits());
            int orphans = fobj.getOrphans();
            int widows = fobj.getWidows();
            if (handlingFloat()) {
                orphans = 1;
                widows = 1;
            }
            for (int i = 0; i < llPoss.getChosenLineCount(); i++) {
                if (!((BlockLevelLayoutManager) parentLayoutManager).mustKeepTogether() && i >= orphans
                        && i <= llPoss.getChosenLineCount() - widows) {
                    // null penalty allowing a page break between lines
                    returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
                }
                LineBreakPosition lbp = llPoss.getChosenPosition(i);
                //log.debug("LLM.getChangedKnuthElements> lineWidth= "
                // + lbp.lineWidth + " difference= " + lbp.difference);
                //log.debug("                             shrink= "
                // + lbp.availableShrink + " stretch= " + lbp.availableStretch);
                //log.debug("linewidth= " + lbp.lineWidth + " difference= "
                //+ lbp.difference + " indent= " + lbp.startIndent);
                MinOptMax contentIPD;
                if (alignment == EN_JUSTIFY) {
                    contentIPD = MinOptMax.getInstance(
                        lbp.lineWidth - lbp.difference - lbp.availableShrink,
                        lbp.lineWidth - lbp.difference,
                        lbp.lineWidth - lbp.difference + lbp.availableStretch);
                } else if (alignment == EN_CENTER) {
                    contentIPD = MinOptMax.getInstance(lbp.lineWidth - 2 * lbp.startIndent);
                } else if (alignment == EN_END) {
                    contentIPD = MinOptMax.getInstance(lbp.lineWidth - lbp.startIndent);
                } else {
                    contentIPD
                        = MinOptMax.getInstance(lbp.lineWidth - lbp.difference + lbp.startIndent);
                }
                returnList.add(new KnuthBlockBox(lbp.lineHeight, contentIPD, (lbp.ipdAdjust != 0
                        ? lbp.lineWidth - lbp.difference : 0),
                                                 lbp, false));
            }
        }
        return returnList;
    }

    /**
     * Find hyphenation points for every word in the current paragraph.
     *
     * @param currPar the paragraph whose words will be hyphenated
     */
    private void findHyphenationPoints(Paragraph currPar) {
        // hyphenate every word
        ListIterator currParIterator = currPar.listIterator(currPar.ignoreAtStart);
        // list of TLM involved in hyphenation
        List updateList = new LinkedList();
        KnuthElement firstElement;
        KnuthElement nextElement;
        // current InlineLevelLayoutManager
        InlineLevelLayoutManager currLM = null;
        // number of KnuthBox elements containing word fragments
        int boxCount;
        // number of auxiliary KnuthElements between KnuthBoxes
        int auxCount;
        StringBuffer sbChars;

        // find all hyphenation points
        while (currParIterator.hasNext()) {
            firstElement = (KnuthElement) currParIterator.next();
            //
            if (firstElement.getLayoutManager() != currLM) {
                currLM = (InlineLevelLayoutManager) firstElement.getLayoutManager();
                if (currLM != null) {
                    updateList.add(new Update(currLM, currParIterator.previousIndex()));
                } else {
                    break;
                }
            } else if (currLM == null) {
                break;
            }

            // collect word fragments, ignoring auxiliary elements;
            // each word fragment was created by a different TextLM
            if (firstElement.isBox() && !firstElement.isAuxiliary()) {
                boxCount = 1;
                auxCount = 0;
                sbChars = new StringBuffer();
                sbChars.append(currLM.getWordChars(firstElement.getPosition()));
                // look if next elements are boxes too
                while (currParIterator.hasNext()) {
                    nextElement = (KnuthElement) currParIterator.next();
                    if (nextElement.isBox() && !nextElement.isAuxiliary()) {
                        // a non-auxiliary KnuthBox: append word chars
                        if (currLM != nextElement.getLayoutManager()) {
                            currLM = (InlineLevelLayoutManager) nextElement.getLayoutManager();
                            updateList.add(new Update(currLM, currParIterator.previousIndex()));
                        }
                        // append text to recreate the whole word
                        boxCount++;
                        sbChars.append(currLM.getWordChars(nextElement.getPosition()));
                    } else if (!nextElement.isAuxiliary()) {
                        // a non-auxiliary non-box KnuthElement: stop
                        // go back to the last box or auxiliary element
                        currParIterator.previous();
                        break;
                    } else {
                        if (currLM != nextElement.getLayoutManager()) {
                            currLM = (InlineLevelLayoutManager) nextElement.getLayoutManager();
                            updateList.add(new Update(currLM, currParIterator.previousIndex()));
                        }
                        // an auxiliary KnuthElement: simply ignore it
                        auxCount++;
                    }
                }
                if (log.isTraceEnabled()) {
                    log.trace(" Word to hyphenate: " + sbChars);
                }
                // find hyphenation points
                HyphContext hc = getHyphenContext(sbChars);
                // ask each LM to hyphenate its word fragment
                if (hc != null) {
                    KnuthElement element = null;
                    for (int i = 0; i < (boxCount + auxCount); i++) {
                        currParIterator.previous();
                    }
                    for (int i = 0; i < (boxCount + auxCount); i++) {
                        element = (KnuthElement) currParIterator.next();
                        if (element.isBox() && !element.isAuxiliary()) {
                            ((InlineLevelLayoutManager)
                             element.getLayoutManager()).hyphenate(element.getPosition(), hc);
                        } else {
                            // nothing to do, element is an auxiliary KnuthElement
                        }
                    }
                }
            }
        }
        processUpdates(currPar, updateList);
    }

    private void processUpdates(Paragraph par, List updateList) {
        // create iterator for the updateList
        ListIterator updateListIterator = updateList.listIterator();
        Update currUpdate;
        int elementsAdded = 0;

        while (updateListIterator.hasNext()) {
            // ask the LMs to apply the changes and return
            // the new KnuthElements to replace the old ones
            currUpdate = (Update) updateListIterator.next();
            int fromIndex = currUpdate.firstIndex;
            int toIndex;
            if (updateListIterator.hasNext()) {
                Update nextUpdate = (Update) updateListIterator.next();
                toIndex = nextUpdate.firstIndex;
                updateListIterator.previous();
            } else {
                // maybe this is not always correct!
                toIndex = par.size() - par.ignoreAtEnd
                    - elementsAdded;
            }

            // applyChanges() returns true if the LM modifies its data,
            // so it must return new KnuthElements to replace the old ones
            if (currUpdate.inlineLM
                .applyChanges(par.subList(fromIndex + elementsAdded,
                                              toIndex + elementsAdded))) {
                // insert the new KnuthElements
                List newElements = currUpdate.inlineLM.getChangedKnuthElements(
                    par.subList(fromIndex + elementsAdded,
                                     toIndex + elementsAdded),
                     /*flaggedPenalty,*/ effectiveAlignment);
                // remove the old elements
                par.subList(fromIndex + elementsAdded,
                                toIndex + elementsAdded).clear();
                // insert the new elements
                par.addAll(fromIndex + elementsAdded, newElements);
                elementsAdded += newElements.size() - (toIndex - fromIndex);
            }
        }
        updateList.clear();
    }

    /**
     * Line area is always considered to act as a fence.
     * @param isNotFirst ignored
     * @return always true
     */
    @Override
    protected boolean hasLeadingFence(boolean isNotFirst) {
        return true;
    }

    /**
     * Line area is always considered to act as a fence.
     * @param isNotLast ignored
     * @return always true
     */
    @Override
    protected boolean hasTrailingFence(boolean isNotLast) {
        return true;
    }

    private HyphContext getHyphenContext(StringBuffer sbChars) {
        // Find all hyphenation points in this word
        // (get in an array of offsets)
        // hyphenationProperties are from the block level?.
        // Note that according to the spec,
        // they also "apply to" fo:character.
        // I don't know what that means, since
        // if we change language in the middle of a "word",
        // the effect would seem quite strange!
        // Or perhaps in that case, we say that it's several words.
        // We probably should bring the hyphenation props up from the actual
        // TextLM which generate the hyphenation buffer,
        // since these properties inherit and could be specified
        // on an inline or wrapper below the block level.
        Hyphenation hyph = Hyphenator.hyphenate(hyphenationProperties.language.getString(),
                               hyphenationProperties.country.getString(),
                               getFObj().getUserAgent().getHyphenationResourceResolver(),
                               getFObj().getUserAgent().getHyphenationPatternNames(),
                               sbChars.toString(),
                               hyphenationProperties.hyphenationRemainCharacterCount.getValue(),
                               hyphenationProperties.hyphenationPushCharacterCount.getValue(),
                               getFObj().getUserAgent());
        // They hyph structure contains the information we need
        // Now start from prev: reset to that position, ask that LM to get
        // a Position for the first hyphenation offset. If the offset isn't in
        // its characters, it returns null,
        // but must tell how many chars it had.
        // Keep looking at currentBP using next hyphenation point until the
        // returned size is greater than the available size
        // or no more hyphenation points remain. Choose the best break.
        if (hyph != null) {
            return new HyphContext(hyph.getHyphenationPoints());
        } else {
            return null;
        }
    }

    @Override
    public boolean hasLineAreaDescendant() {
        return true;
    }

    @Override
    public int getBaselineOffset() {
        return baselineOffset;
    }

    /**
     * Add the areas with the break points.
     *
     * @param parentIter the iterator of break positions
     * @param context the context for adding areas
     */
    @Override
    public void addAreas(PositionIterator parentIter,
                         LayoutContext context) {
        while (parentIter.hasNext()) {
            Position pos = parentIter.next();
            boolean isLastPosition = !parentIter.hasNext();
            if (pos instanceof LineBreakPosition) {
                addInlineArea(context, (LineBreakPosition) pos, isLastPosition);
            } else if ((pos instanceof NonLeafPosition) && pos.generatesAreas()) {
                addBlockArea(context, pos, isLastPosition);
            } else {
                /*
                 * pos was the Position inside a penalty item, nothing to do;
                 * or Pos does not generate an area,
                 * i.e. it stand for spaces, borders and padding.
                 */
            }
        }
        setCurrentArea(null); // ?? necessary
    }

    /**
     * Add a line with inline content
     * @param context the context for adding areas
     * @param lbp the position for which the line is generated
     * @param isLastPosition true if this is the last position of this LM
     */
    private void addInlineArea(LayoutContext context, LineBreakPosition lbp,
            boolean isLastPosition) {

        KnuthSequence seq = knuthParagraphs.get(lbp.parIndex);
        int startElementIndex = lbp.startIndex;
        int endElementIndex = lbp.getLeafPos();

        LineArea lineArea = new LineArea(
                (lbp.getLeafPos() < seq.size() - 1 ? textAlignment : textAlignmentLast),
                lbp.difference, lbp.availableStretch, lbp.availableShrink);
        lineArea.setChangeBarList(getChangeBarList());

        if (lbp.startIndent != 0) {
            lineArea.addTrait(Trait.START_INDENT, lbp.startIndent);
        }
        if (lbp.endIndent != 0) {
            lineArea.addTrait(Trait.END_INDENT, lbp.endIndent);
        }
        lineArea.setBPD(lbp.lineHeight);
        lineArea.setIPD(lbp.lineWidth);
        lineArea.setBidiLevel(bidiLevel);
        lineArea.addTrait(Trait.SPACE_BEFORE, lbp.spaceBefore);
        lineArea.addTrait(Trait.SPACE_AFTER, lbp.spaceAfter);
        alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline);

        if (seq instanceof Paragraph) {
            Paragraph currPar = (Paragraph) seq;
            // ignore the first elements added by the LineLayoutManager
            startElementIndex += (startElementIndex == 0) ? currPar.ignoreAtStart : 0;

            // if this is the last line area that for this paragraph,
            // ignore the last elements added by the LineLayoutManager and
            // subtract the last-line-end-indent from the area ipd
            if (endElementIndex == (currPar.size() - 1)) {
                endElementIndex -= currPar.ignoreAtEnd;
                lineArea.setIPD(lineArea.getIPD() - lastLineEndIndent.getValue(this));
            }
        }

        // ignore the last element in the line if it is a KnuthGlue object
        ListIterator seqIterator = seq.listIterator(endElementIndex);
        KnuthElement lastElement = (KnuthElement) seqIterator.next();
        // the TLM which created the last KnuthElement in this line
        LayoutManager lastLM = lastElement.getLayoutManager();
        if (lastElement.isGlue()) {
            // Remove trailing spaces if allowed so
            if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED
                    || whiteSpaceTreament == EN_IGNORE
                    || whiteSpaceTreament == EN_IGNORE_IF_BEFORE_LINEFEED) {
                endElementIndex--;
                // this returns the same KnuthElement
                seqIterator.previous();
                if (seqIterator.hasPrevious()) {
                    lastLM = ((KnuthElement) seqIterator.previous()).getLayoutManager();
                }
            }
        }

        // Remove leading spaces if allowed so
        if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED
                || whiteSpaceTreament == EN_IGNORE
                || whiteSpaceTreament == EN_IGNORE_IF_AFTER_LINEFEED) {
            // ignore KnuthGlue and KnuthPenalty objects
            // at the beginning of the line
            seqIterator = seq.listIterator(startElementIndex);
            while (seqIterator.hasNext() && !((KnuthElement) seqIterator.next()).isBox()) {
                startElementIndex++;
            }
        }
        // Add the inline areas to lineArea
        PositionIterator inlinePosIter = new KnuthPossPosIter(seq, startElementIndex,
                endElementIndex + 1);

        LayoutContext lc = LayoutContext.offspringOf(context);
        lc.setAlignmentContext(alignmentContext);
        lc.setSpaceAdjust(lbp.dAdjust);
        lc.setIPDAdjust(lbp.ipdAdjust);
        lc.setLeadingSpace(new SpaceSpecifier(true));
        lc.setTrailingSpace(new SpaceSpecifier(false));
        lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);

        setCurrentArea(lineArea);
        setChildContext(lc);
        LayoutManager childLM;
        while ((childLM = inlinePosIter.getNextChildLM()) != null) {
            lc.setFlags(LayoutContext.LAST_AREA, (childLM == lastLM));
            childLM.addAreas(inlinePosIter, lc);
            lc.setLeadingSpace(lc.getTrailingSpace());
            lc.setTrailingSpace(new SpaceSpecifier(false));
        }

        // if display-align is distribute, add space after
        if (context.getSpaceAfter() > 0
                && (!context.isLastArea() || !isLastPosition)) {
            lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter());
        }
        lineArea.finish();
        if (lineArea.getBidiLevel() >= 0) {
            BidiResolver.reorder(lineArea);
        }
        parentLayoutManager.addChildArea(lineArea);
    }

    /**
     * Add a line with block content
     * @param context the context for adding areas
     * @param pos the position for which the line is generated
     * @param isLastPosition true if this is the last position of this LM
     */
    private void addBlockArea(LayoutContext context, Position pos, boolean isLastPosition) {
        /* Nested block-level content;
         * go down the LM stack again;
         * "unwrap" the positions and put the child positions in a new list.
         * The positionList must contain one area-generating position,
         * which creates one line area.
         */
        List positionList = new ArrayList(1);
        Position innerPosition = pos.getPosition();
        positionList.add(innerPosition);

        // do we have the last LM?
        LayoutManager lastLM = null;
        if (isLastPosition) {
            lastLM = innerPosition.getLM();
        }

        LineArea lineArea = new LineArea();
        lineArea.setChangeBarList(getChangeBarList());
        setCurrentArea(lineArea);
        LayoutContext lc = LayoutContext.newInstance();
        lc.setAlignmentContext(alignmentContext);
        setChildContext(lc);

        PositionIterator childPosIter = new PositionIterator(positionList.listIterator());
        LayoutContext blocklc = LayoutContext.offspringOf(context);
        blocklc.setLeadingSpace(new SpaceSpecifier(true));
        blocklc.setTrailingSpace(new SpaceSpecifier(false));
        blocklc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
        LayoutManager childLM;
        while ((childLM = childPosIter.getNextChildLM()) != null) {
            // set last area flag
            blocklc.setFlags(LayoutContext.LAST_AREA,
                             (context.isLastArea() && childLM == lastLM));
            blocklc.setStackLimitBP(context.getStackLimitBP());
            // Add the line areas to Area
            childLM.addAreas(childPosIter, blocklc);
            blocklc.setLeadingSpace(blocklc.getTrailingSpace());
            blocklc.setTrailingSpace(new SpaceSpecifier(false));
        }
        lineArea.updateExtentsFromChildren();
        if (lineArea.getBidiLevel() >= 0) {
            BidiResolver.reorder(lineArea);
        }
        parentLayoutManager.addChildArea(lineArea);
    }

    /** {@inheritDoc} */
    @Override
    public void addChildArea(Area childArea) {
        // Make sure childArea is inline area
        if (childArea instanceof InlineArea) {
            Area parent = getCurrentArea();
            if (getContext().resolveLeadingSpace()) {
                addSpace(parent, getContext().getLeadingSpace().resolve(false),
                        getContext().getSpaceAdjust());
            }
            parent.addChildArea(childArea);
        }
    }

    // --------- Property Resolution related functions --------- //

    /** {@inheritDoc} */
    @Override
    public boolean getGeneratesBlockArea() {
        return true;
    }

    /** {@inheritDoc} */
    @Override
    public boolean getGeneratesLineArea() {
        return true;
    }

    /** {@inheritDoc} */
    @Override
    public boolean isRestartable() {
        return true;
    }

    /**
     * Whether this LM can handle horizontal overflow error messages (only a BlockContainerLayoutManager can).
     * @param milliPoints horizontal overflow
     * @return true if handled by a BlockContainerLayoutManager
     */
    public boolean handleOverflow(int milliPoints) {
        if (getParent() instanceof BlockLayoutManager) {
            return ((BlockLayoutManager) getParent()).handleOverflow(milliPoints);
        }
        return false;
    }
}
