<?xml version="1.0" encoding="UTF-8"?>
<!--
  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$ -->
<testcase>
  <info>
    <p>
      This test checks Bug 39414 - Index overflow on long texts
    </p>
  </info>
  <fo>
    <fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:svg="http://www.w3.org/2000/svg">
      <fo:layout-master-set>
        <fo:simple-page-master master-name="normal" page-width="10in" page-height="5in">
          <fo:region-body/>
        </fo:simple-page-master>
      </fo:layout-master-set>
      <fo:page-sequence master-reference="normal" white-space-collapse="true">
        <fo:flow flow-name="xsl-region-body">
          <fo:block font-family="monospace" font-size="8pt" white-space="pre"><![CDATA[
/*
 * Copyright 1999-2006 The Apache Software Foundation.
 * 
 * Licensed 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 org.apache.fop.datatypes.Length;
import org.apache.fop.datatypes.Numeric;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.Block;
import org.apache.fop.fo.properties.CommonHyphenation;
import org.apache.fop.hyphenation.Hyphenation;
import org.apache.fop.hyphenation.Hyphenator;
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.InlineKnuthSequence;
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.area.Area;
import org.apache.fop.area.LineArea;
import org.apache.fop.area.inline.InlineArea;

import java.util.ListIterator;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
import org.apache.fop.area.Trait;
import org.apache.fop.fonts.Font;

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 {

    private Block fobj;
    private boolean isFirstInBlock;
    
    /** @see org.apache.fop.layoutmgr.LayoutManager#initialize() */
    public void initialize() {
        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;
        }
    }
    
    /**
     * Private class to store information about inline breaks.
     * Each value holds the start and end indexes into a List of
     * inline break positions.
     */
    private static class LineBreakPosition extends LeafPosition {
        private int iParIndex; // index of the Paragraph this Position refers to
        private int iStartIndex; //index of the first element this Position refers to
        private int availableShrink;
        private int availableStretch;
        private int difference;
        private double dAdjust; // Percentage to adjust (stretch or shrink)
        private double ipdAdjust; // Percentage to adjust (stretch or shrink)
        private int startIndent;
        private int lineHeight;
        private int lineWidth;
        private int spaceBefore;
        private int spaceAfter;
        private int baseline;

        LineBreakPosition(LayoutManager lm, int index, int iStartIndex, int iBreakIndex,
                          int shrink, int stretch, int diff,
                          double ipdA, double adjust, int ind,
                          int lh, int lw, int sb, int sa, int bl) {
            super(lm, iBreakIndex);
            availableShrink = shrink;
            availableStretch = stretch;
            difference = diff;
            iParIndex = index;
            this.iStartIndex = iStartIndex;
            ipdAdjust = ipdA;
            dAdjust = adjust;
            startIndent = ind;
            lineHeight = lh;
            lineWidth = lw;
            spaceBefore = sb;
            spaceAfter = sa;
            baseline = bl;
        }
        
    }


    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 Length lineHeight;
    private int lead;
    private int follow;
    private AlignmentContext alignmentContext = null;

    private List knuthParagraphs = null;
    private int iReturnedLBP = 0;

    //     parameters of Knuth's algorithm:
    // penalty value for flagged penalties
    private int flaggedPenalty = 50;

    private LineLayoutPossibilities lineLayouts;
    private List lineLayoutsList;
    private int iLineWidth = 0;

    /**
     * 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;


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

        public Update(InlineLevelLayoutManager lm, int index) {
            inlineLM = lm;
            iFirstIndex = index;
        }
    }

    // this class represents a paragraph
    private class Paragraph extends InlineKnuthSequence {
        /** Number of elements to ignore at the beginning of the list. */ 
        private int ignoreAtStart = 0;
        /** Number of elements to ignore at the end of the list. */
        private int ignoreAtEnd = 0;

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

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

        public void startParagraph(int lw) {
            lineWidth = lw;
            startSequence();
        }

        public void startSequence() {
            // set the minimum amount of empty space at the end of the
            // last line
            if (textAlignment == EN_CENTER) {
                lineFiller = new MinOptMax(lastLineEndIndent); 
            } else {
                lineFiller = new MinOptMax(lastLineEndIndent, lastLineEndIndent, lineWidth); 
            }

            // 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 (isFirstInBlock && knuthParagraphs.size() == 0
                        && textIndent != 0) {
                this.add(new KnuthInlineBox(textIndent, null, 
                                      null, false));
                ignoreAtStart++;
            }
        }

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

        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.opt, -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.max - lineFiller.opt, 
                            lineFiller.opt - lineFiller.min, null, false));
                    this.add(new KnuthPenalty(lineFiller.opt, -KnuthElement.INFINITE,
                                              false, null, false));
                    ignoreAtEnd = 3;
                } else {
                    // add only the element representing the forced break
                    this.add(new KnuthPenalty(lineFiller.opt, -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 (int i = 0; i < this.size(); i++) {
                KnuthElement el = (KnuthElement)this.get(i);
                if (el.isBox()) {
                    return true;
                }
            }
            return false;
        }
    }

    private class LineBreakingAlgorithm extends BreakingAlgorithm {
        private LineLayoutManager thisLLM;
        private int pageAlignment;
        private int activePossibility;
        private int addedPositions;
        private int textIndent;
        private int fillerMinWidth;
        private int lineHeight;
        private int lead;
        private int follow;
        private int maxDiff;
        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;
            fillerMinWidth = fillerWidth;
            lineHeight = lh;
            lead = ld;
            follow = fl;
            thisLLM = llm;
            activePossibility = -1;
            maxDiff = fobj.getWidows() >= fobj.getOrphans() 
                    ? fobj.getWidows()
                    : fobj.getOrphans();
        }

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

        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 indent = 0;
            int difference = bestActiveNode.difference;
            int textAlign = (bestActiveNode.line < total) ? alignment : alignmentLast;
            indent += (textAlign == Constants.EN_CENTER)
                      ? difference / 2 : (textAlign == Constants.EN_END) ? difference : 0;
            indent += (bestActiveNode.line == 1 && bFirst && 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;
            }

            if (difference + bestActiveNode.availableShrink < 0) {
                if (log.isWarnEnabled()) {
                    log.warn(FONode.decorateWithContextInfo(
                            "Line " + (addedPositions + 1) 
                            + " of a paragraph overflows the available area.", getFObj()));
                }
            }
            
            //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.opt - ((Paragraph)par).lineFiller.min), 
                   bestActiveNode.availableStretch, 
                   difference, ratio, indent), 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 indent) {
            // 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 bZeroHeightLine = (difference == iLineWidth);

            // 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) {
                                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 (bZeroHeightLine
                            && (!element.isAuxiliary() || ac != null && ac.getHeight() > 0)) {
                            bZeroHeightLine = false;
                        }
                    }
                }

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

            constantLineHeight = lineLead + lineFollow;

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

        public int findBreakingPoints(Paragraph par, /*int lineWidth,*/
                                      double threshold, boolean force,
                                      int allowedBreaks) {
            return super.findBreakingPoints(par, /*lineWidth,*/ 
                    threshold, force, allowedBreaks);
        }

        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;
    }

    /** @see org.apache.fop.layoutmgr.LayoutManager */
    public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
        Font fs = fobj.getCommonFont().getFontState(fobj.getFOEventHandler().getFontInfo(), this);
        alignmentContext
          = new AlignmentContext(fs, lineHeight.getValue(this), context.getWritingMode());
        context.setAlignmentContext(alignmentContext);
        // Get a break from currently active child LM
        // Set up constraints for inline level managers

        // IPD remaining in line
        MinOptMax availIPD = context.getStackLimit();

        clearPrevIPD();

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

            // here starts Knuth's algorithm
            //TODO availIPD should not really be used here, so we can later support custom line
            //widths for for each line (side-floats, differing available IPD after page break)
            collectInlineKnuthElements(context, availIPD);
        } 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);
        /*
        LineBreakPosition lbp = null;
        if (breakpoints == null) {
            // find the optimal line breaking points for each paragraph
            breakpoints = new ArrayList();
            ListIterator paragraphsIterator
                = knuthParagraphs.listIterator(knuthParagraphs.size());
            Paragraph currPar = null;
            while (paragraphsIterator.hasPrevious()) {
                currPar = (Paragraph) paragraphsIterator.previous();
                findBreakingPoints(currPar, context.getStackLimit().opt);
            }
        }*/

        //PHASE 3: Return lines

        /*
        // get a break point from the list
        lbp = (LineBreakPosition) breakpoints.get(iReturnedLBP ++);
        if (iReturnedLBP == breakpoints.size()) {
            setFinished(true);
        }

        BreakPoss curLineBP = new BreakPoss(lbp);
        curLineBP.setFlag(BreakPoss.ISLAST, isFinished());
        curLineBP.setStackingSize(new MinOptMax(lbp.lineHeight));
        return curLineBP;
        */
    }

    /**
     * Phase 1 of Knuth algorithm: Collect all inline Knuth elements before determining line breaks.
     * @param context the LayoutContext
     * @param availIPD available IPD for line (should be removed!) 
     */
    private void collectInlineKnuthElements(LayoutContext context, MinOptMax availIPD) {
        LayoutContext inlineLC = new LayoutContext(context);
        
        InlineLevelLayoutManager curLM;
        LinkedList returnedList = null;
        iLineWidth = context.getStackLimit().opt;
        
        // convert all the text in a sequence of paragraphs made
        // of KnuthBox, KnuthGlue and KnuthPenalty objects
        boolean bPrevWasKnuthBox = false;
        
        StringBuffer trace = new StringBuffer("LineLM:");
        
        Paragraph lastPar = null;
        
        while ((curLM = (InlineLevelLayoutManager) getChildLM()) != null) {
            returnedList = curLM.getNextKnuthElements(inlineLC, effectiveAlignment);
            if (returnedList == null) {
                // curLM returned null; this can happen
                // if it has nothing more to layout,
                // so just iterate once more to see
                // if there are other children
                continue;
            }
            if (returnedList.size() == 0) {
                continue;
            }
            
            if (lastPar != null) {
                KnuthSequence firstSeq = (KnuthSequence) returnedList.getFirst();
                
                // 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(" ]");
                    }
                    bPrevWasKnuthBox = 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()
                            && bPrevWasKnuthBox) {
                        lastPar.addALetterSpace();
                    }
                }
            }
            
            // loop over the KnuthSequences (and single KnuthElements) in returnedList
            ListIterator iter = returnedList.listIterator();
            while (iter.hasNext()) {
                KnuthSequence sequence = (KnuthSequence) iter.next();
                // the sequence contains inline Knuth elements
                if (sequence.isInlineSequence()) {
                    // look at the last element 
                    ListElement lastElement;
                    lastElement = sequence.getLast();
                    if (lastElement == null) {
                        throw new NullPointerException(
                        "Sequence was empty! lastElement is null");
                    }
                    bPrevWasKnuthBox = lastElement.isBox() && ((KnuthElement) lastElement).getW() != 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.startParagraph(availIPD.opt);
                        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).getP()
                            == -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 a zero width box
                            lastPar.add(new KnuthInlineBox(0, null, null, false));
                        }
                        lastPar.endParagraph();
                        ElementListObserver.observe(lastPar, "line", null);
                        lastPar = null;
                        if (log.isTraceEnabled()) {
                            trace.append(" ]");
                        }
                        bPrevWasKnuthBox = 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);
    }
    
    /**
     * Find a set of breaking points.
     * This method is called only once by getNextBreakPoss, and it 
     * subsequently calls the other findBreakingPoints() method with 
     * different parameters, until a set of breaking points is found.
     *
     * @param par       the list of elements that must be parted
     *                  into lines
     * @param lineWidth the desired length ot the lines
     */
    /*
    private void findBreakingPoints(Paragraph par, int lineWidth) {
        // maximum adjustment ratio permitted
        float maxAdjustment = 1;

        // first try
        if (!findBreakingPoints(par, lineWidth, maxAdjustment, false)) {
            // the first try failed, now try something different
            log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment);
            if (hyphenationProperties.hyphenate == Constants.EN_TRUE) {
                // consider every hyphenation point as a legal break
                findHyphenationPoints(par);
            } else {
                // try with a higher threshold
                maxAdjustment = 5;
            }

            if (!findBreakingPoints(par, lineWidth, maxAdjustment, false)) {
                // the second try failed too, try with a huge threshold;
                // if this fails too, use a different algorithm
                log.debug("No set of breaking points found with maxAdjustment = " + maxAdjustment
                          + (hyphenationProperties.hyphenate == Constants.EN_TRUE ? " and hyphenation" : ""));
                maxAdjustment = 20;
                if (!findBreakingPoints(par, lineWidth, maxAdjustment, true)) {
                    log.debug("No set of breaking points found, using first-fit algorithm");
                }
            }
        }
    }
    
    private boolean findBreakingPoints(Paragraph par, int lineWidth,
            double threshold, boolean force) {
        KnuthParagraph knuthPara = new KnuthParagraph(par);
        int lines = knuthPara.findBreakPoints(lineWidth, threshold, force);
        if (lines == 0) {
            return false;
        }
        
        for (int i = lines-1; i >= 0; i--) {
            int line = i+1;
            if (log.isTraceEnabled()) {
                log.trace("Making line from " + knuthPara.getStart(i) + " to " + 
                           knuthPara.getEnd(i));
            }
            // compute indent and adjustment ratio, according to
            // the value of text-align and text-align-last

            int difference = knuthPara.getDifference(i);
            if (line == lines) {
                difference += par.lineFillerWidth;
            }    
            int textAlign = (line < lines)
                ? textAlignment : textAlignmentLast;
            int indent = (textAlign == EN_CENTER)
                ? difference / 2
                : (textAlign == EN_END) ? difference : 0;
            indent += (line == 1 && knuthParagraphs.indexOf(par) == 0)
                ? textIndent.getValue(this) : 0;
            double ratio = (textAlign == EN_JUSTIFY)
                ? knuthPara.getAdjustRatio(i) : 0;

            int start = knuthPara.getStart(i);
            int end = knuthPara.getEnd(i);
            makeLineBreakPosition(par, start, end, 0, ratio, indent);
        }
        return true;        
    }

    private void makeLineBreakPosition(Paragraph par,
                                       int firstElementIndex, int lastElementIndex,
                                       int insertIndex, double ratio, int indent) {
        // line height calculation

        int halfLeading = (lineHeight - lead - follow) / 2;
        // height above the main baseline
        int lineLead = lead + halfLeading;
        // maximum size of top and bottom alignment
        int lineFollow = follow + halfLeading;

        ListIterator inlineIterator
            = par.listIterator(firstElementIndex);
        for (int j = firstElementIndex;
             j <= lastElementIndex;
             j++) {
            KnuthElement element = (KnuthElement) inlineIterator.next();
            if (element.isBox()) {
                KnuthInlineBox box = (KnuthInlineBox)element;
                if (box.getLead() > lineLead) {
                    lineLead = box.getLead();
                }
                if (box.getTotal() > lineFollow) {
                    lineFollow = box.getTotal();
                }
                if (box.getMiddle() > lineLead + middleShift) {
                    lineLead += box.getMiddle()
                                - lineLead - middleShift;
                }
                if (box.getMiddle() > middlefollow - middleShift) {
                    middlefollow += box.getMiddle()
                                    - middlefollow + middleShift;
                }
            }
        }

        if (lineFollow - lineLead > middlefollow) {
                    middlefollow = lineFollow - lineLead;
        }

        breakpoints.add(insertIndex,
                        new LineBreakPosition(this,
                                              knuthParagraphs.indexOf(par),
                                              lastElementIndex ,
                                              ratio, 0, indent,
                                              lineLead + middlefollow,
                                              lineLead));
    }*/

    
    /**
     * 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 LinkedList createLineBreaks(int alignment, LayoutContext context) {

        // find the optimal line breaking points for each paragraph
        ListIterator paragraphsIterator
            = knuthParagraphs.listIterator(knuthParagraphs.size());
        lineLayoutsList = new ArrayList(knuthParagraphs.size());
        LineLayoutPossibilities llPoss;
        while (paragraphsIterator.hasPrevious()) {
            KnuthSequence seq = (KnuthSequence) paragraphsIterator.previous();
            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);
            }
            lineLayoutsList.add(0, llPoss);
        }
        
        setFinished(true);
    
        //Post-process the line breaks found
        return postProcessLineBreaks(alignment, context);
    }

    /**
     * Fint the optimal linebreaks for a paragraph
     * @param alignment alignment of the paragraph
     * @param currPar the Paragraph for which the linebreaks are found
     * @return the line layout possibilities for the paragraph
     */
    private LineLayoutPossibilities findOptimalBreakingPoints(int alignment, Paragraph currPar) {
        // use the member lineLayouts, which is read by LineBreakingAlgorithm.updateData1 and 2
        lineLayouts = new LineLayoutPossibilities();
        double maxAdjustment = 1;
        int iBPcount = 0;
        LineBreakingAlgorithm alg = new LineBreakingAlgorithm(alignment,
                                        textAlignment, textAlignmentLast,
                                        textIndent.getValue(this), currPar.lineFiller.opt,
                                        lineHeight.getValue(this), lead, follow,
                                        (knuthParagraphs.indexOf(currPar) == 0),
                                        hyphenationLadderCount.getEnum() == EN_NO_LIMIT
                                        ? 0 : hyphenationLadderCount.getValue(),
                                        this);
   
        if (hyphenationProperties.hyphenate == EN_TRUE 
                && fobj.getWrapOption() != EN_NO_WRAP) {
            findHyphenationPoints(currPar);
        }
   
        // first try
        int allowedBreaks;
        if (wrapOption == EN_NO_WRAP) {
            allowedBreaks = BreakingAlgorithm.ONLY_FORCED_BREAKS;
        } else {
            allowedBreaks = BreakingAlgorithm.NO_FLAGGED_PENALTIES;
        }
        alg.setConstantLineWidth(iLineWidth);
        iBPcount = alg.findBreakingPoints(currPar,
                                          maxAdjustment, false, allowedBreaks);
        if (iBPcount == 0 || alignment == EN_JUSTIFY) {
            // if the first try found a set of breaking points, save them
            if (iBPcount > 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? " + (hyphenationProperties.hyphenate == EN_TRUE));
            if (hyphenationProperties.hyphenate == EN_TRUE
                && !(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;
            }
   
            if ((iBPcount
                 = alg.findBreakingPoints(currPar,
                                          maxAdjustment, false, allowedBreaks)) == 0) {
                // the second try failed too, try with a huge threshold
                // and force the algorithm to find
                // a set of breaking points
                log.debug("No set of breaking points found with maxAdjustment = "
                          + maxAdjustment
                          + (hyphenationProperties.hyphenate == EN_TRUE
                                  ? " and hyphenation" : ""));
                maxAdjustment = 20;
                iBPcount
                    = alg.findBreakingPoints(currPar,
                                             maxAdjustment, true, allowedBreaks);
            }
   
            // use non-hyphenated breaks, when possible
            lineLayouts.restorePossibilities();
   
            /* extension (not in the XSL FO recommendation): if vertical alignment
               is justify and the paragraph has only one layout, try using 
               shorter or longer lines */
            //TODO This code snippet is disabled. Reenable?
            if (false && alignment == EN_JUSTIFY && textAlignment == EN_JUSTIFY) {
                //log.debug("LLM.getNextKnuthElements> layouts with more lines? " + lineLayouts.canUseMoreLines());
                //log.debug("                          layouts with fewer lines? " + lineLayouts.canUseLessLines());
                if (!lineLayouts.canUseMoreLines()) {
                    alg.resetAlgorithm();
                    lineLayouts.savePossibilities(true);
                    // try with shorter lines
                    int savedLineWidth = iLineWidth;
                    iLineWidth = (int) (iLineWidth * 0.95);
                    iBPcount = alg.findBreakingPoints(currPar,
                             maxAdjustment, true, allowedBreaks);
                    // use normal lines, when possible
                    lineLayouts.restorePossibilities();
                    iLineWidth = savedLineWidth;
                }
                if (!lineLayouts.canUseLessLines()) {
                    alg.resetAlgorithm();
                    lineLayouts.savePossibilities(true);
                    // try with longer lines
                    int savedLineWidth = iLineWidth;
                    iLineWidth = (int) (iLineWidth * 1.05);
                    alg.setConstantLineWidth(iLineWidth);
                    iBPcount = alg.findBreakingPoints(currPar,
                            maxAdjustment, true, allowedBreaks);
                    // use normal lines, when possible
                    lineLayouts.restorePossibilities();
                    iLineWidth = savedLineWidth;
                }
                //log.debug("LLM.getNextKnuthElements> now, layouts with more lines? " + lineLayouts.canUseMoreLines());
                //log.debug("                          now, layouts with fewer lines? " + lineLayouts.canUseLessLines());
            }
        }
        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 LinkedList postProcessLineBreaks(int alignment, LayoutContext context) {
    
        LinkedList returnList = new LinkedList();
        
        for (int p = 0; p < knuthParagraphs.size(); p++) {
            // null penalty between paragraphs
            if (p > 0 && !((BlockLevelLayoutManager) parentLM).mustKeepTogether()) {
                returnList.add(new BreakElement(
                        new Position(this), 0, context));
                //returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
            }
        
            LineLayoutPossibilities llPoss;
            llPoss = (LineLayoutPossibilities) lineLayoutsList.get(p);
            KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(p);

            if (!seq.isInlineSequence()) {
                LinkedList targetList = new LinkedList();
                ListIterator listIter = seq.listIterator();
                while (listIter.hasNext()) {
                    ListElement tempElement;
                    tempElement = (ListElement) listIter.next();
                    if (tempElement.getLayoutManager() != 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 */
                Position returnPosition = new LeafPosition(this, p);
                int startIndex = 0;
                for (int i = 0;
                        i < llPoss.getChosenLineCount();
                        i++) {
                    if (!((BlockLevelLayoutManager) parentLM).mustKeepTogether()
                            && i >= fobj.getOrphans()
                            && i <= llPoss.getChosenLineCount() - fobj.getWidows()
                            && returnList.size() > 0) {
                        // null penalty allowing a page break between lines
                        returnList.add(new BreakElement(
                                returnPosition, 0, context));
                        //returnList.add(new KnuthPenalty(0, 0, false, returnPosition, false));
                    }
                    int endIndex
                      = ((LineBreakPosition) llPoss.getChosenPosition(i)).getLeafPos();
                    // create a list of the FootnoteBodyLM handling footnotes 
                    // whose citations are in this line
                    LinkedList footnoteList = new LinkedList();
                    ListIterator elementIterator = seq.listIterator(startIndex);
                    while (elementIterator.nextIndex() <= endIndex) {
                        KnuthElement element = (KnuthElement) elementIterator.next();
                        if (element instanceof KnuthInlineBox
                            && ((KnuthInlineBox) element).isAnchor()) {
                            footnoteList.add(((KnuthInlineBox) element).getFootnoteBodyLM());
                        } else if (element instanceof KnuthBlockBox) {
                            footnoteList.addAll(((KnuthBlockBox) element).getFootnoteBodyLMs());
                        }
                    }
                    startIndex = endIndex + 1;
                    LineBreakPosition lbp
                      = (LineBreakPosition) llPoss.getChosenPosition(i);
                    returnList.add(new KnuthBlockBox
                                   (lbp.lineHeight + lbp.spaceBefore + lbp.spaceAfter,
                                    footnoteList, lbp, false));
                    /* // add stretch and shrink to the returnlist
                    if (!seq.isInlineSequence()
                            && lbp.availableStretch != 0 || lbp.availableShrink != 0) {
                        returnList.add(new KnuthPenalty(0, -KnuthElement.INFINITE,
                                false, new Position(this), false));
                        returnList.add(new KnuthGlue(0, lbp.availableStretch, lbp.availableShrink,
                                new Position(this), false));
                    }
                    */
                }
            }
        }
        
        return returnList;
    }


    private void createElements(List list, LineLayoutPossibilities llPoss,
                                Position elementPosition) {
        /* number of normal, inner lines */
        int nInnerLines = 0;
        /* number of lines that can be used in order to fill more space */
        int nOptionalLines = 0;
        /* number of lines that can be used in order to fill more space
           only if the paragraph is not parted */
        int nConditionalOptionalLines = 0;
        /* number of lines that can be omitted in order to fill less space */
        int nEliminableLines = 0;
        /* number of lines that can be omitted in order to fill less space
           only if the paragraph is not parted */
        int nConditionalEliminableLines = 0;
        /* number of the first unbreakable lines */
        int nFirstLines = fobj.getOrphans();
        /* number of the last unbreakable lines */
        int nLastLines = fobj.getWidows();
        /* sub-sequence used to separate the elements representing different lines */
        List breaker = new LinkedList();

        /* comment out the next lines in order to test particular situations */
        if (fobj.getOrphans() + fobj.getWidows() <= llPoss.getMinLineCount()) {
            nInnerLines = llPoss.getMinLineCount()
                          - (fobj.getOrphans() + fobj.getWidows());
            nOptionalLines = llPoss.getMaxLineCount()
                             - llPoss.getOptLineCount();
            nEliminableLines = llPoss.getOptLineCount()
                               - llPoss.getMinLineCount();
        } else if (fobj.getOrphans() + fobj.getWidows() <= llPoss.getOptLineCount()) {
            nOptionalLines = llPoss.getMaxLineCount()
                             - llPoss.getOptLineCount();
            nEliminableLines = llPoss.getOptLineCount()
                               - (fobj.getOrphans() + fobj.getWidows());
            nConditionalEliminableLines = (fobj.getOrphans() + fobj.getWidows())
                                          - llPoss.getMinLineCount();
        } else if (fobj.getOrphans() + fobj.getWidows() <= llPoss.getMaxLineCount()) {
            nOptionalLines = llPoss.getMaxLineCount()
                             - (fobj.getOrphans() + fobj.getWidows());
            nConditionalOptionalLines = (fobj.getOrphans() + fobj.getWidows())
                                        - llPoss.getOptLineCount();
            nConditionalEliminableLines = llPoss.getOptLineCount()
                                          - llPoss.getMinLineCount();
            nFirstLines -= nConditionalOptionalLines;
        } else {
            nConditionalOptionalLines = llPoss.getMaxLineCount()
                                        - llPoss.getOptLineCount();
            nConditionalEliminableLines = llPoss.getOptLineCount()
                                          - llPoss.getMinLineCount();
            nFirstLines = llPoss.getOptLineCount();
            nLastLines = 0;
        }
        /* comment out the previous lines in order to test particular situations */

        /* use these lines to test particular situations
        nInnerLines = 0;
        nOptionalLines = 1;
        nConditionalOptionalLines = 2;
        nEliminableLines = 0;
        nConditionalEliminableLines = 0;
        nFirstLines = 1;
        nLastLines = 3;
        */

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

        //log.debug("first=" + nFirstLines + " inner=" + nInnerLines
        //                   + " optional=" + nOptionalLines + " eliminable=" + nEliminableLines
        //                   + " last=" + nLastLines
        //                   + " (condOpt=" + nConditionalOptionalLines + " condEl=" + nConditionalEliminableLines + ")");

        // creation of the elements:
        // first group of lines
        list.add(new KnuthBox(nFirstLines * constantLineHeight, elementPosition,
                              (nLastLines == 0
                               && nConditionalOptionalLines == 0
                               && nConditionalEliminableLines == 0 ? true : false)));
        if (nConditionalOptionalLines > 0
            || nConditionalEliminableLines > 0) {
            list.add(new KnuthPenalty(0, KnuthElement.INFINITE, false, elementPosition, false));
            list.add(new KnuthGlue(0, nConditionalOptionalLines * constantLineHeight,
                                   nConditionalEliminableLines * constantLineHeight,
                                   LINE_NUMBER_ADJUSTMENT, elementPosition, false));
            list.add(new KnuthBox(0, elementPosition,
                                  (nLastLines == 0 ? true : false)));
        }

        // optional lines
        for (int i = 0; i < nOptionalLines; 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, 1 * constantLineHeight, 0,
                                   LINE_NUMBER_ADJUSTMENT, elementPosition, false));
            list.add(new KnuthBox(0, elementPosition, false));
        }

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

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

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

    /**
     * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepTogether
     */
    public boolean mustKeepTogether() {
        return ((BlockLevelLayoutManager) getParent()).mustKeepTogether();
    }

    /**
     * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithPrevious
     */
    public boolean mustKeepWithPrevious() {
        return false;
    }

    /**
     * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#mustKeepWithNext
     */
    public boolean mustKeepWithNext() {
        return false;
    }

    /**
     * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#negotiateBPDAdjustment(int, org.apache.fop.layoutmgr.KnuthElement)
     */
    public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) {
        LeafPosition pos = (LeafPosition)lastElement.getPosition();
        int totalAdj = adj;
        //if (lastElement.isPenalty()) {
        //    totalAdj += lastElement.getW();
        //}
        //int lineNumberDifference = (int)((double) totalAdj / constantLineHeight);
        int lineNumberDifference = (int) Math.round((double) totalAdj / constantLineHeight
                                                    + (adj > 0 ? - 0.4 : 0.4));
        //log.debug("   LLM> variazione calcolata = " + ((double) totalAdj / constantLineHeight) + " variazione applicata = " + lineNumberDifference);
        LineLayoutPossibilities llPoss;
        llPoss = (LineLayoutPossibilities) lineLayoutsList.get(pos.getLeafPos());
        lineNumberDifference = llPoss.applyLineCountAdjustment(lineNumberDifference);
        return lineNumberDifference * constantLineHeight;
    }

    /**
     * @see org.apache.fop.layoutmgr.BlockLevelLayoutManager#discardSpace(KnuthGlue)
     */
    public void discardSpace(KnuthGlue spaceGlue) {
    }

    /**
     * @see org.apache.fop.layoutmgr.LayoutManager#getChangedKnuthElements(List, int)
     */
    public LinkedList getChangedKnuthElements(List oldList, int alignment) {
        LinkedList returnList = new LinkedList();
        for (int p = 0; p < knuthParagraphs.size(); p++) {
            LineLayoutPossibilities llPoss;
            llPoss = (LineLayoutPossibilities)lineLayoutsList.get(p);
            //log.debug("demerits of the chosen layout: " + llPoss.getChosenDemerits());
            for (int i = 0; i < llPoss.getChosenLineCount(); i++) {
                if (!((BlockLevelLayoutManager) parentLM).mustKeepTogether()
                    && i >= fobj.getOrphans()
                    && i <= llPoss.getChosenLineCount() - fobj.getWidows()) {
                    // null penalty allowing a page break between lines
                    returnList.add(new KnuthPenalty(0, 0, false, new Position(this), false));
                }
                LineBreakPosition lbp = (LineBreakPosition) 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 = new MinOptMax(
                        lbp.lineWidth - lbp.difference - lbp.availableShrink, 
                        lbp.lineWidth - lbp.difference, 
                        lbp.lineWidth - lbp.difference + lbp.availableStretch);
                } else if (alignment == EN_CENTER) {
                    contentIPD = new MinOptMax(lbp.lineWidth - 2 * lbp.startIndent);
                } else if (alignment == EN_END) {
                    contentIPD = new MinOptMax(lbp.lineWidth - lbp.startIndent);
                } else {
                    contentIPD = new MinOptMax(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 int 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
        LinkedList updateList = new LinkedList();
        KnuthElement firstElement = null;
        KnuthElement nextElement = null;
        // current InlineLevelLayoutManager
        InlineLevelLayoutManager currLM = null;
        // number of KnuthBox elements containing word fragments
        int boxCount;
        // number of auxiliary KnuthElements between KnuthBoxes
        int auxCount;
        StringBuffer sbChars = null;

        // 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;
            }
            //TODO Something's not right here. See block_hyphenation_linefeed_preserve.xml
            
            // 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();
                currLM.getWordChars(sbChars, 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++;
                        currLM.getWordChars(sbChars, 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++;
                    }
                }
                log.trace(" Word to hyphenate: " + sbChars.toString());
                // 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
                        }
                    }
                }
            }
        }

        // create iterator for the updateList
        ListIterator updateListIterator = updateList.listIterator();
        Update currUpdate = null;
        //int iPreservedElements = 0;
        int iAddedElements = 0;
        //int iRemovedElements = 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.iFirstIndex;
            int toIndex;
            if (updateListIterator.hasNext()) {
                Update nextUpdate = (Update) updateListIterator.next();
                toIndex = nextUpdate.iFirstIndex;
                updateListIterator.previous();
            } else {
                // maybe this is not always correct!
                toIndex = currPar.size() - currPar.ignoreAtEnd
                    - iAddedElements;
            }

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

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

    /**
     * Line area is always considered to act as a fence.
     * @param isNotLast ignored
     * @return always true
     */
    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,
                               hyphenationProperties.country,
                               getFObj().getUserAgent().getFactory().getHyphenationTreeResolver(),
                               sbChars.toString(),
                               hyphenationProperties.hyphenationRemainCharacterCount,
                               hyphenationProperties.hyphenationPushCharacterCount);
        // 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;
        }
    }

    /**
     * Reset the positions to the given position.
     *
     * @param resetPos the position to reset to
     */
    public void resetPosition(Position resetPos) {
        if (resetPos == null) {
            setFinished(false);
            iReturnedLBP = 0;
        } else {
            if (isFinished()) {
                // if isFinished is true, iReturned LBP == breakpoints.size()
                // and breakpoints.get(iReturnedLBP) would generate
                // an IndexOutOfBoundException
                setFinished(false);
                iReturnedLBP--;
            }
            // It is not clear that the member lineLayouts has the correct value;
            // because the method is not called, this cannot be checked.
            while ((LineBreakPosition) lineLayouts.getChosenPosition(iReturnedLBP)
                   != (LineBreakPosition) resetPos) {
                iReturnedLBP--;
            }
            iReturnedLBP++;
        }
    }

    /**
     * Add the areas with the break points.
     *
     * @param parentIter the iterator of break positions
     * @param context the context for adding areas
     */
    public void addAreas(PositionIterator parentIter,
                         LayoutContext context) {
        while (parentIter.hasNext()) {
            Position pos = (Position) parentIter.next();
            boolean isLastPosition = !parentIter.hasNext();
            if (pos instanceof LineBreakPosition) {
                addInlineArea(context, 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 pos 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, Position pos, boolean isLastPosition) {
            ListIterator seqIterator = null;
            KnuthElement tempElement = null;
            // the TLM which created the last KnuthElement in this line
            LayoutManager lastLM = null;
            
            LineBreakPosition lbp = (LineBreakPosition) pos;
            int iCurrParIndex;
            iCurrParIndex = lbp.iParIndex;
            KnuthSequence seq = (KnuthSequence) knuthParagraphs.get(iCurrParIndex);
            int iStartElement = lbp.iStartIndex;
            int iEndElement = lbp.getLeafPos();
            
            LineArea lineArea
              = new LineArea((lbp.getLeafPos() < seq.size() - 1
                              ? textAlignment : textAlignmentLast),
                              lbp.difference, lbp.availableStretch, lbp.availableShrink);
            if (lbp.startIndent != 0) {
                lineArea.addTrait(Trait.START_INDENT, new Integer(lbp.startIndent));
            }
            lineArea.setBPD(lbp.lineHeight);
            lineArea.setIPD(lbp.lineWidth);
            lineArea.addTrait(Trait.SPACE_BEFORE, new Integer(lbp.spaceBefore));
            lineArea.addTrait(Trait.SPACE_AFTER, new Integer(lbp.spaceAfter));
            alignmentContext.resizeLine(lbp.lineHeight, lbp.baseline);
            
            if (seq instanceof Paragraph) {
                Paragraph currPar = (Paragraph) seq;
                // ignore the first elements added by the LineLayoutManager
                iStartElement += (iStartElement == 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 (iEndElement == (currPar.size() - 1)) {
                    iEndElement -= currPar.ignoreAtEnd;
                    lineArea.setIPD(lineArea.getIPD() - lastLineEndIndent.getValue(this));
                }
            }
            
            // Remove trailing spaces if allowed so
            if (whiteSpaceTreament == EN_IGNORE_IF_SURROUNDING_LINEFEED
                || whiteSpaceTreament == EN_IGNORE 
                || whiteSpaceTreament == EN_IGNORE_IF_BEFORE_LINEFEED) {
                // ignore the last element in the line if it is a KnuthGlue object
                seqIterator = seq.listIterator(iEndElement);
                tempElement = (KnuthElement) seqIterator.next();
                if (tempElement.isGlue()) {
                    iEndElement--;
                    // this returns the same KnuthElement
                    seqIterator.previous();
                    if (seqIterator.hasPrevious()) {
                        tempElement = (KnuthElement) seqIterator.previous();
                    } else {
                        tempElement = null;
                    }
                }
                if (tempElement != null) {
                    lastLM = tempElement.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(iStartElement);
                tempElement = (KnuthElement) seqIterator.next();
                while (!tempElement.isBox() && seqIterator.hasNext()) {
                    tempElement = (KnuthElement) seqIterator.next();
                    iStartElement++;
                }
            }
            // Add the inline areas to lineArea
            PositionIterator inlinePosIter
              = new KnuthPossPosIter(seq, iStartElement, iEndElement + 1);
            
            iStartElement = lbp.getLeafPos() + 1;
            if (iStartElement == seq.size()) {
                // advance to next paragraph
                iStartElement = 0;
            }
            
            LayoutContext lc = new LayoutContext(0);
            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);
            
            /*
             * extension (not in the XSL FO recommendation): if the left and right margins
             * have been optimized, recompute indents and / or adjust ratio, according
             * to the paragraph horizontal alignment
             */
            if (false && textAlignment == EN_JUSTIFY) {
                // re-compute space adjust ratio
                int updatedDifference = context.getStackLimit().opt
                                        - lbp.lineWidth + lbp.difference;
                double updatedRatio = 0.0;
                if (updatedDifference > 0) {
                    updatedRatio = (float) updatedDifference / lbp.availableStretch;
                } else if (updatedDifference < 0) {
                    updatedRatio = (float) updatedDifference / lbp.availableShrink;
                }
                lc.setIPDAdjust(updatedRatio);
                //log.debug("LLM.addAreas> old difference = " + lbp.difference + " new difference = " + updatedDifference);
                //log.debug("              old ratio = " + lbp.ipdAdjust + " new ratio = " + updatedRatio);
            } else if (false && textAlignment == EN_CENTER) {
                // re-compute indent
                int updatedIndent = lbp.startIndent
                                    + (context.getStackLimit().opt - lbp.lineWidth) / 2;
                lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent));
            } else if (false && textAlignment == EN_END) {
                // re-compute indent
                int updatedIndent = lbp.startIndent 
                                    + (context.getStackLimit().opt - lbp.lineWidth);
                lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent));
            }
            
            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));
            }
            
            // when can this be null?
            // if display-align is distribute, add space after 
            if (context.getSpaceAfter() > 0
                    && (!context.isLastArea() || !isLastPosition)) {
                lineArea.setBPD(lineArea.getBPD() + context.getSpaceAfter());
            }
            lineArea.finalise();
            parentLM.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;
        innerPosition = ((NonLeafPosition) pos).getPosition();
        positionList.add(innerPosition);

        // do we have the last LM?
        LayoutManager lastLM = null;
        if (isLastPosition) {
            lastLM = innerPosition.getLM();
        }
        
        LineArea lineArea = new LineArea();
        setCurrentArea(lineArea);
        LayoutContext lc = new LayoutContext(0);
        lc.setAlignmentContext(alignmentContext);
        setChildContext(lc);
        
        PositionIterator childPosIter = new StackingIter(positionList.listIterator());
        LayoutContext blocklc = new LayoutContext(0);
        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.setStackLimit(context.getStackLimit());
            // Add the line areas to Area
            childLM.addAreas(childPosIter, blocklc);
            blocklc.setLeadingSpace(blocklc.getTrailingSpace());
            blocklc.setTrailingSpace(new SpaceSpecifier(false));
        }
        lineArea.updateExtentsFromChildren();
        parentLM.addChildArea(lineArea);
    }

    /**
     * @see org.apache.fop.layoutmgr.LayoutManager#addChildArea(Area)
     */
    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 --------- //
    
    /**
     * @see org.apache.fop.layoutmgr.LayoutManager#getGeneratesBlockArea
     */
    public boolean getGeneratesBlockArea() {
        return true;
    }
   
    /**
     * @see org.apache.fop.layoutmgr.LayoutManager#getGeneratesLineArea
     */
    public boolean getGeneratesLineArea() {
        return true;
    }
}   
]]>
          </fo:block>
        </fo:flow>
      </fo:page-sequence>
    </fo:root>
  </fo>
  <checks>
    <!-- Not a proper test !! -->
    <eval expected="0 0 720000 360000" xpath="/areaTree/pageSequence/pageViewport/@bounds" desc="page size"/>
  </checks>
</testcase>
