Index: src/java/org/apache/fop/render/AbstractRenderer.java
===================================================================
--- src/java/org/apache/fop/render/AbstractRenderer.java	(revision 1078951)
+++ src/java/org/apache/fop/render/AbstractRenderer.java	(working copy)
@@ -28,6 +28,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.Vector;
 
 import org.w3c.dom.Document;
 
@@ -68,7 +69,9 @@
 import org.apache.fop.area.inline.Viewport;
 import org.apache.fop.area.inline.WordArea;
 import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.flow.ChangeBar;
 import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.traits.BorderProps;
 
 /**
  * Abstract base class for all renderers. The Abstract renderer does all the
@@ -108,6 +111,51 @@
      */
     protected int containingIPPosition = 0;
 
+    /**
+     * The "start edge" IP Position of the current column (for change bars)
+     */
+    protected int columnStartIPPosition = 0;
+    
+    /**
+     * The "end edge" IP Position of the current column (for change bars)
+     */
+    protected int columnEndIPPosition = 0;
+    
+    /**
+     * The "left" position of the current column (for change bars)
+     */
+    protected int columnLeftIPPosition = 0;
+    
+    /**
+     * The "right" position of the current column (for change bars)
+     */
+    protected int columnRightIPPosition = 0;
+    
+    /**
+     * The number of columns in the span (for change bars)
+     */
+    protected int columnCount = 0;
+    
+    /**
+     * The index number of the current column (for change bars)
+     */
+    protected int columnNumber = 0;
+    
+    /**
+     * Is binding on start edge of column?
+     */
+    protected boolean bindingOnStartEdge = false;
+    
+    /**
+     * Is binding on end edge of column?
+     */
+    protected boolean bindingOnEndEdge = false;
+    
+    /**
+     * The IP begin offset of coordinate 0
+     */
+    private int beginOffset  = 0;
+    
     /** the currently active PageViewport */
     protected PageViewport currentPageViewport;
 
@@ -406,10 +454,60 @@
         int saveSpanBPPos = saveBPPos;
         for (int count = 0; count < spans.size(); count++) {
             span = (Span) spans.get(count);
+            columnCount = span.getColumnCount();
+            
             for (int c = 0; c < span.getColumnCount(); c++) {
+                columnNumber = c;
+                
                 NormalFlow flow = span.getNormalFlow(c);
 
+                int writingMode = mr.getParent().getWritingMode();
+                int referenceOrientation = mr.getParent().getReferenceOrientation();
+                
+                
+
                 if (flow != null) {
+                    columnStartIPPosition = currentIPPosition;
+                    columnEndIPPosition = currentIPPosition + flow.getIPD() + mr.getColumnGap();
+                    
+                    // if direction is right to left, then end is left, else end is right edge
+                    // if orientation is portrait, then binding edge is on left edge for odd pages
+                    // and on right edge for even pages
+                    int pageIndex = currentPageViewport.getPageIndex();
+                    CTM trans = currentPageViewport.getBodyRegion().getCTM();
+                    
+                    bindingOnStartEdge = false;
+                    bindingOnEndEdge = false;
+                    
+                    if (writingMode == Constants.EN_RL_TB) {
+                        columnLeftIPPosition = columnEndIPPosition;
+                        columnRightIPPosition = columnStartIPPosition;
+                        if (0 == referenceOrientation) {
+                            if (pageIndex % 2 == 0 ) {
+                                bindingOnEndEdge = true;
+                            }
+                            else {
+                                bindingOnStartEdge = true;
+                            }
+                        }
+                    }
+                    else {
+                        columnLeftIPPosition = columnStartIPPosition;
+                        columnRightIPPosition = columnEndIPPosition;
+                        if (0 == referenceOrientation) {
+                            if (pageIndex % 2 == 0 ) {
+                                bindingOnStartEdge = true;
+                            }
+                            else {
+                                bindingOnEndEdge = true;
+                            }
+                        }
+                    }
+                    
+
+ 
+                    
+                    
                     currentBPPosition = saveSpanBPPos;
                     renderFlow(flow);
                     currentIPPosition += flow.getIPD();
@@ -558,6 +656,19 @@
      * @param block  The block area
      */
     protected void renderBlock(Block block) {
+        Vector changeBars = block.getChangeBars();
+        
+        if (null != changeBars && !changeBars.isEmpty()) {
+            // this block has change bars attached to it
+            int saveIP = currentIPPosition;
+            int saveBP = currentBPPosition;
+            
+            drawChangeBars(block, changeBars);
+            
+            currentIPPosition = saveIP;
+            currentBPPosition = saveBP;
+        }
+        
         List children = block.getChildAreas();
         if (block instanceof BlockViewport) {
             if (children != null) {
@@ -619,6 +730,13 @@
      * @param inlineArea inline area text to render
      */
     protected void renderInlineArea(InlineArea inlineArea) {
+        Vector changeBars = inlineArea.getChangeBars();
+        
+        if (null != changeBars && !changeBars.isEmpty()) {
+            // area has change bar, handle
+            drawChangeBars(inlineArea, changeBars);
+        }
+        
         if (inlineArea instanceof TextArea) {
             renderText((TextArea) inlineArea);
         //} else if (inlineArea instanceof Character) {
@@ -674,6 +792,19 @@
      * @param text the text to render
      */
     protected void renderText(TextArea text) {
+      Vector changeBars = text.getChangeBars();
+        
+        if (null != changeBars && !changeBars.isEmpty()) {
+            // this block has change bars attached to it
+            int saveIP = currentIPPosition;
+            int saveBP = currentBPPosition;
+            
+            drawChangeBars(text, changeBars);
+            
+            currentIPPosition = saveIP;
+            currentBPPosition = saveBP;
+        }
+        
         int saveIP = currentIPPosition;
         int saveBP = currentBPPosition;
         Iterator iter = text.getChildAreas().iterator();
@@ -761,6 +892,12 @@
      * (todo) Make renderImage() protected
      */
     public void renderImage(Image image, Rectangle2D pos) {
+        // handle change bars
+        Vector changeBars = image.getChangeBars();
+        
+        if (null != changeBars && !changeBars.isEmpty()) {
+            drawChangeBars(image, changeBars);
+        }
         // Default: do nothing.
         // Some renderers (ex. Text) don't support images.
     }
@@ -787,6 +924,13 @@
      * (todo) Make renderForeignObject() protected
      */
     protected void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
+        // handle change bars
+        Vector changeBars = fo.getChangeBars();
+        
+        if (null != changeBars && !changeBars.isEmpty()) {
+            drawChangeBars(fo, changeBars);
+        }
+        
         // Default: do nothing.
         // Some renderers (ex. Text) don't support foreign objects.
     }
@@ -859,4 +1003,141 @@
         matrix[5] = Math.round(matrix[5] * 1000);
         return new AffineTransform(matrix);
     }
+    
+    /**
+     * Draw all change bars associated with an area
+     * 
+     * @param block  The area to draw change bars for
+     * @param changeBars The list of change bars affecting the area
+     */
+    private void drawChangeBars(Area block, Vector changeBars) {
+        Block cbArea;
+        
+        int saveIP = currentIPPosition;
+        int saveBP = currentBPPosition;
+        
+        for (int idx = 0; idx < changeBars.size(); idx++) {
+            ChangeBar bar = (ChangeBar)changeBars.get(idx);
+            cbArea = new Block();
+
+            currentIPPosition = 0;
+            currentBPPosition = saveBP;
+            
+            // offset by default is negative width for change bars placed on the start edge
+            // this will be overriden if placement is at the end edge
+            // xScale is for adding or subtracting the offset of the change bar depending on
+            //  placing the bar towards or away from the edge it is bound to
+            int xOffset = -bar.getWidth().getValue();
+            int xScale = 1;
+            
+            // determine currentIPPosition based on placement
+            switch (bar.getPlacement()) {
+            case EN_START:
+                xOffset += columnStartIPPosition;
+                xScale = -1;
+                break;
+            case EN_END:
+                xOffset = columnEndIPPosition;
+                break;
+            case EN_LEFT:
+                xOffset += columnLeftIPPosition;
+                xScale = -1;
+                break;
+            case EN_RIGHT:
+                xOffset = columnRightIPPosition;
+                break;
+            case EN_INSIDE:
+                if (bindingOnStartEdge) {
+                    xOffset += columnStartIPPosition;
+                    xScale = -1;
+                }
+                else if (bindingOnEndEdge) {
+                    xOffset = columnEndIPPosition;
+                }
+                else {
+                    xOffset += columnStartIPPosition;
+                    xScale = -1;
+                }
+                break;
+            case EN_OUTSIDE:
+                if (bindingOnStartEdge) {
+                    xOffset = columnEndIPPosition;
+                }
+                else if (bindingOnEndEdge) {
+                    xOffset += columnStartIPPosition;
+                    xScale = -1;
+                }
+                else {
+                    xOffset += columnStartIPPosition;
+                    xScale = -1;
+                }               
+                break;
+            case EN_ALTERNATE:
+                if (2 == columnCount) {
+                    if ( 0 == columnNumber) {
+                        xOffset += columnStartIPPosition;
+                        xScale = -1;
+                    }
+                    else {
+                        xOffset = columnEndIPPosition;
+                    }
+                }
+                else {
+                    if (bindingOnStartEdge) {
+                        xOffset = columnEndIPPosition;
+                    }
+                    else if (bindingOnEndEdge) {
+                        xOffset += columnStartIPPosition;
+                        xScale = -1;
+                    }
+                    else {
+                        xOffset = columnStartIPPosition;
+                        xScale = -1;
+                    }   
+                }
+                break;
+            default:
+                break;
+            }
+
+            xOffset += getBeginOffset();
+            
+            // Change bar area has 0 ipd, class xsl-absolute, no margin or padding
+            cbArea.setAreaClass(Area.CLASS_ABSOLUTE);
+            cbArea.setIPD(0);
+            cbArea.setPositioning(Block.ABSOLUTE);
+            cbArea.setBPD(block.getBPD());
+            BorderProps props = new BorderProps(bar.getStyle(), bar.getWidth().getValue(),
+                    bar.getColor(), BorderProps.SEPARATE);
+
+            cbArea.addTrait(Trait.BORDER_END, props);
+ 
+            cbArea.setXOffset(xOffset + xScale * bar.getOffset().getValue());
+            cbArea.setYOffset(block.getSpaceBefore());
+
+            renderBlock(cbArea);
+
+            // restore position on page
+            currentIPPosition = saveIP;
+            currentBPPosition = saveBP;
+                       
+        }
+    }
+    
+    /**
+     * return the begin offset of the inline begin (changes by reference area transforms)
+     * @return the offset from current coordinate system 0 that the IP begin is at
+     */
+    protected int getBeginOffset() {
+        return beginOffset;
+    }
+    
+    /**
+     * Set the begin offset for inline progression begin (changes by reference area tranforms)
+     * @param offset the new offset from IPP 0 that true IP start is at
+     */
+    protected void setBeginOffset(int offset) {
+        beginOffset = offset;
+    }
+    
 }
Index: src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/LayoutManagerMapping.java	(working copy)
@@ -38,6 +38,8 @@
 import org.apache.fop.fo.flow.BidiOverride;
 import org.apache.fop.fo.flow.Block;
 import org.apache.fop.fo.flow.BlockContainer;
+import org.apache.fop.fo.flow.ChangeBarBegin;
+import org.apache.fop.fo.flow.ChangeBarEnd;
 import org.apache.fop.fo.flow.Character;
 import org.apache.fop.fo.flow.ExternalGraphic;
 import org.apache.fop.fo.flow.Footnote;
@@ -140,6 +142,8 @@
         registerMaker(TableHeader.class, new Maker());
         registerMaker(Wrapper.class, new WrapperLayoutManagerMaker());
         registerMaker(Title.class, new InlineLayoutManagerMaker());
+        registerMaker(ChangeBarBegin.class, new Maker());
+        registerMaker(ChangeBarEnd.class, new Maker());
     }
 
     /**
Index: src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java	(working copy)
@@ -86,6 +86,7 @@
         // get breaks then add areas to title
         this.parentLM = pslm;
         holder = new LineArea();
+        holder.setChangeBars(getChangeBars());
 
         //        setUserAgent(foTitle.getUserAgent());
 
Index: src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java	(working copy)
@@ -205,9 +205,11 @@
         InlineArea area;
         if (hasInlineParent) {
             area = new InlineParent();
+            area.setChangeBars(getChangeBars());
             area.setOffset(0);
         } else {
             area = new InlineBlockParent();
+            area.setChangeBars(getChangeBars());
         }
         if (fobj instanceof Inline) {
             TraitSetter.setProducerID(area, getInlineFO().getId());
Index: src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java	(working copy)
@@ -68,10 +68,12 @@
             if (parentLayoutManager instanceof BlockStackingLayoutManager
                     && !(parentLayoutManager instanceof BlockLayoutManager)) {
                 Block helperBlock = new Block();
+                helperBlock.setChangeBars(getChangeBars());
                 TraitSetter.setProducerID(helperBlock, fobj.getId());
                 parentLayoutManager.addChildArea(helperBlock);
             } else {
                 InlineArea area = getEffectiveArea();
+                area.setChangeBars(getChangeBars());
                 parentLayoutManager.addChildArea(area);
             }
         }
Index: src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java	(working copy)
@@ -69,6 +69,8 @@
             int width = getStringWidth(str);
             text.setIPD(width);
         }
+
+        text.setChangeBars(getChangeBars());
         updateTextAreaTraits(text);
 
         return text;
Index: src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/ExternalGraphicLayoutManager.java	(working copy)
@@ -42,8 +42,10 @@
 
     /** {@inheritDoc} */
     protected Area getChildArea() {
-        return new Image(((ExternalGraphic) fobj).getSrc());
-    }
+        Image im = new Image(((ExternalGraphic) fobj).getSrc());
+        im.setChangeBars(getChangeBars());
+        return im;
+     }
 
 }
 
Index: src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/InstreamForeignObjectLM.java	(working copy)
@@ -46,7 +46,9 @@
         org.w3c.dom.Document doc = child.getDOMDocument();
         String ns = child.getNamespaceURI();
 
-        return new ForeignObject(doc, ns);
+        ForeignObject obj = new ForeignObject(doc, ns);
+        obj.setChangeBars(getChangeBars());
+        return obj;
     }
 
 }
Index: src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java	(working copy)
@@ -23,6 +23,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.Vector;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -363,7 +364,8 @@
 
         TextArea textArea = new TextAreaBuilder(realWidth, totalAdjust, context, firstAreaInfoIndex,
                 lastAreaInfoIndex, context.isLastArea(), areaInfo.font).build();
-
+        textArea.setChangeBars(getChangeBars());
+        
         // wordSpaceDim is computed in relation to wordSpaceIPD.opt
         // but the renderer needs to know the adjustment in relation
         // to the size of the space character in the current font;
@@ -455,6 +457,8 @@
                 textArea = new TextArea(width.getStretch(), width.getShrink(),
                         adjust);
             }
+            
+            textArea.setChangeBars(getChangeBars());
         }
 
         private void setInlineProgressionDimension() {
@@ -1341,4 +1345,13 @@
 
     }
 
+    @Override
+    public Vector/*<ChangeBar>*/ getChangeBars() {
+       if (null == foText) {
+               return null;
+       }
+       else {
+               return foText.getChangeBars();
+       }
+    }
 }
Index: src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java	(working copy)
@@ -77,6 +77,8 @@
     public InlineArea get(LayoutContext context) {
         // get page string from parent, build area
         TextArea text = new TextArea();
+        text.setChangeBars(getChangeBars());
+        
         String str = getCurrentPV().getPageNumberString();
         int width = getStringWidth(str);
         text.addWord(str, 0);
@@ -98,6 +100,8 @@
         //TODO or even better: delay area creation until addAreas() stage
         //TextArea is cloned because the LM is reused in static areas and the area can't be.
         TextArea ta = new TextArea();
+        ta.setChangeBars(getChangeBars());
+        
         TraitSetter.setProducerID(ta, fobj.getId());
         ta.setIPD(baseArea.getIPD());
         ta.setBPD(baseArea.getBPD());
Index: src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java	(working copy)
@@ -1425,6 +1425,8 @@
         LineArea lineArea = new LineArea(
                 (lbp.getLeafPos() < seq.size() - 1 ? textAlignment : textAlignmentLast),
                 lbp.difference, lbp.availableStretch, lbp.availableShrink);
+        lineArea.setChangeBars(getChangeBars());
+        
         if (lbp.startIndent != 0) {
             lineArea.addTrait(Trait.START_INDENT, new Integer(lbp.startIndent));
         }
@@ -1533,6 +1535,8 @@
         }
 
         LineArea lineArea = new LineArea();
+        lineArea.setChangeBars(getChangeBars());
+        
         setCurrentArea(lineArea);
         LayoutContext lc = new LayoutContext(0);
         lc.setAlignmentContext(alignmentContext);
Index: src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java	(working copy)
@@ -76,6 +76,8 @@
 
     private TextArea getCharacterInlineArea(Character node) {
         TextArea text = new TextArea();
+        text.setChangeBars(getChangeBars());
+        
         char ch = node.getCharacter();
         if (CharUtilities.isAnySpace(ch)) {
             // add space unless it's zero-width:
Index: src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java	(working copy)
@@ -201,6 +201,9 @@
                 leaderArea.setBPD(fobj.getRuleThickness().getValue(this));
             }
         }
+        
+       leaderArea.setChangeBars(getChangeBars());
+       
         TraitSetter.setProducerID(leaderArea, fobj.getId());
         return leaderArea;
      }
Index: src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java	(working copy)
@@ -179,6 +179,7 @@
             if (iAdjust != 0) {
                 //getLogger().debug("Add leading space: " + iAdjust);
                 Space ls = new Space();
+                ls.setChangeBars(getChangeBars());
                 ls.setIPD(iAdjust);
                 parentArea.addChildArea(ls);
             }
Index: src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java	(working copy)
@@ -110,6 +110,8 @@
             String str = page.getPageNumberString();
             // get page string from parent, build area
             text = new TextArea();
+            text.setChangeBars(getChangeBars());
+            
             int width = getStringWidth(str);
             text.addWord(str, 0);
             text.setIPD(width);
@@ -117,6 +119,8 @@
         } else {
             resolved = false;
             text = new UnresolvedPageNumber(fobj.getRefId(), font);
+            text.setChangeBars(getChangeBars());
+            
             String str = "MMM"; // reserve three spaces for page number
             int width = getStringWidth(str);
             text.setIPD(width);
Index: src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java	(working copy)
@@ -75,6 +75,7 @@
             resolved = true;
         }
 
+        text.setChangeBars(getChangeBars());
         updateTextAreaTraits(text);
 
         return text;
Index: src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java	(working copy)
@@ -833,6 +833,8 @@
             boolean allowBPDUpdate = autoHeight && !switchedProgressionDirection;
 
             viewportBlockArea = new BlockViewport(allowBPDUpdate);
+            viewportBlockArea.setChangeBars(getChangeBars());
+            
             viewportBlockArea.addTrait(Trait.IS_VIEWPORT_AREA, Boolean.TRUE);
 
             viewportBlockArea.setIPD(getContentAreaIPD());
@@ -868,6 +870,8 @@
             }
 
             referenceArea = new Block();
+            referenceArea.setChangeBars(getChangeBars());
+            
             referenceArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
             TraitSetter.setProducerID(referenceArea, getBlockContainerFO().getId());
 
Index: src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/ExternalDocumentLayoutManager.java	(working copy)
@@ -177,6 +177,8 @@
         Dimension imageSize = this.imageLayout.getViewportSize();
 
         Block blockArea = new Block();
+        blockArea.setChangeBars(getChangeBars());
+        
         blockArea.setIPD(imageSize.width);
         LineArea lineArea = new LineArea();
 
@@ -245,7 +247,8 @@
         rv.setClip(true);
 
         BodyRegion body = new BodyRegion(Constants.FO_REGION_BODY,
-                "fop-image-region", rv, 1, 0);
+                "fop-image-region", rv, 1, 0, pageSeq.getReferenceOrientation(),
+                pageSeq.getReferenceOrientation());
         body.setIPD(imageSize.width);
         body.setBPD(imageSize.height);
         body.setCTM(pageCTM);
Index: src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java	(working copy)
@@ -357,6 +357,7 @@
     public Area getParentArea(Area childArea) {
         if (curBlockArea == null) {
             curBlockArea = new Block();
+           curBlockArea.setChangeBars(getChangeBars());
 
             curBlockArea.setIPD(super.getContentAreaIPD());
 
Index: src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java	(working copy)
@@ -218,6 +218,7 @@
     public Area getParentArea(Area childArea) {
         if (curBlockArea == null) {
             curBlockArea = new Block();
+            curBlockArea.setChangeBars(getChangeBars());
 
             // Set up dimensions
             // Must get dimensions from parent area
Index: src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java	(working copy)
@@ -586,6 +586,7 @@
     public Area getParentArea(Area childArea) {
         if (curBlockArea == null) {
             curBlockArea = new Block();
+            curBlockArea.setChangeBars(getChangeBars());
 
             // Set up dimensions
             /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea);
Index: src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java	(working copy)
@@ -173,6 +173,8 @@
     public Area getParentArea(Area childArea) {
         if (curBlockArea == null) {
             curBlockArea = new Block();
+            curBlockArea.setChangeBars(getChangeBars());
+            
             curBlockArea.setPositioning(Block.ABSOLUTE);
             // set position
             curBlockArea.setXOffset(xoffset);
Index: src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java	(working copy)
@@ -124,6 +124,8 @@
         int sp = TraitSetter.getEffectiveSpace(adjust, minoptmax);
         if (sp != 0) {
             Block spacer = new Block();
+           spacer.setChangeBars(getChangeBars());
+           
             spacer.setBPD(sp);
             parentLayoutManager.addChildArea(spacer);
         }
Index: src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java	(working copy)
@@ -398,10 +398,14 @@
         if (usedBPD < cellBPD) {
             if (getTableCell().getDisplayAlign() == EN_CENTER) {
                 Block space = new Block();
+                space.setChangeBars(getChangeBars());
+                
                 space.setBPD((cellBPD - usedBPD) / 2);
                 curBlockArea.addBlock(space);
             } else if (getTableCell().getDisplayAlign() == EN_AFTER) {
                 Block space = new Block();
+                space.setChangeBars(getChangeBars());
+                
                 space.setBPD(cellBPD - usedBPD);
                 curBlockArea.addBlock(space);
             }
@@ -456,6 +460,8 @@
             boolean outer) {
         if (blocks[i][j] == null) {
             blocks[i][j] = new Block();
+            blocks[i][j].setChangeBars(getChangeBars());
+            
             blocks[i][j].addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
             blocks[i][j].setPositioning(Block.ABSOLUTE);
         }
@@ -486,6 +492,8 @@
         int paddingEnd = padding.getPaddingEnd(false, this);
 
         Block block = new Block();
+        block.setChangeBars(getChangeBars());
+        
         TraitSetter.setProducerID(block, getTable().getId());
         block.setPositioning(Block.ABSOLUTE);
         block.setIPD(cellIPD + paddingStart + paddingEnd);
@@ -511,6 +519,8 @@
     public Area getParentArea(Area childArea) {
         if (curBlockArea == null) {
             curBlockArea = new Block();
+            curBlockArea.setChangeBars(getChangeBars());
+            
             curBlockArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
             TraitSetter.setProducerID(curBlockArea, getTableCell().getId());
             curBlockArea.setPositioning(Block.ABSOLUTE);
Index: src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java	(working copy)
@@ -420,6 +420,8 @@
     public Area getParentArea(Area childArea) {
         if (curBlockArea == null) {
             curBlockArea = new Block();
+            curBlockArea.setChangeBars(getChangeBars());
+            
             // Set up dimensions
             // Must get dimensions from parent area
             /*Area parentArea =*/ parentLayoutManager.getParentArea(curBlockArea);
Index: src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java	(working copy)
@@ -179,6 +179,8 @@
     public Area getParentArea(Area childArea) {
         if (curBlockArea == null) {
             curBlockArea = new Block();
+           curBlockArea.setChangeBars(getChangeBars());
+ 
             // Set up dimensions
             // Must get dimensions from parent area
             Area parentArea = parentLayoutManager.getParentArea(curBlockArea);
Index: src/java/org/apache/fop/layoutmgr/table/RowPainter.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/table/RowPainter.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/table/RowPainter.java	(working copy)
@@ -465,6 +465,8 @@
 
         //generate the block area
         Block block = new Block();
+        block.setChangeBars(tclm.getTableLM().getFObj().getChangeBars());
+        
         block.setPositioning(Block.ABSOLUTE);
         block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
         block.setIPD(ipd);
Index: src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java	(working copy)
@@ -175,6 +175,8 @@
     public Area getParentArea(Area childArea) {
         if (curBlockArea == null) {
             curBlockArea = new Block();
+            curBlockArea.setChangeBars(getChangeBars());
+            
             // Set up dimensions
             // Must get dimensions from parent area
             Area parentArea = parentLayoutManager.getParentArea(curBlockArea);
Index: src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java
===================================================================
--- src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java	(revision 1078951)
+++ src/java/org/apache/fop/layoutmgr/AbstractBaseLayoutManager.java	(working copy)
@@ -21,6 +21,7 @@
 
 import java.util.List;
 import java.util.Stack;
+import java.util.Vector;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -257,6 +258,21 @@
         return fobj;
     }
 
+    /**
+     * Obtain vector of change bars affecting object in this layout.
+     * @return Vector of all change bars affecting this or null
+     */
+    public Vector/*<ChangeBar>*/ getChangeBars() {
+       if (null == fobj) {
+               return null;
+       }
+       else {
+               return fobj.getChangeBars();
+       }
+    }
+
+
+
     /** {@inheritDoc} */
     public void reset() {
         throw new UnsupportedOperationException("Not implemented");
Index: src/java/org/apache/fop/apps/FOUserAgent.java
===================================================================
--- src/java/org/apache/fop/apps/FOUserAgent.java	(revision 1078951)
+++ src/java/org/apache/fop/apps/FOUserAgent.java	(working copy)
@@ -24,6 +24,8 @@
 import java.net.MalformedURLException;
 import java.util.Date;
 import java.util.Map;
+import java.util.TreeMap;
+import java.util.Vector;
 
 import javax.xml.transform.Source;
 import javax.xml.transform.TransformerException;
@@ -47,6 +49,7 @@
 import org.apache.fop.events.FOPEventListenerProxy;
 import org.apache.fop.events.LoggingEventListener;
 import org.apache.fop.fo.FOEventHandler;
+import org.apache.fop.fo.flow.ChangeBar;
 import org.apache.fop.fonts.FontManager;
 import org.apache.fop.render.Renderer;
 import org.apache.fop.render.RendererFactory;
@@ -83,7 +86,14 @@
 
     private FopFactory factory;
 
+       
     /**
+     * The change bars encountered
+     */
+    private static Vector stackedChangeBars = new Vector();
+
+    
+    /**
      *  The base URL for all URL resolutions, especially for
      *  external-graphics.
      */
@@ -693,5 +703,52 @@
     public StructureTree getStructureTree() {
         return this.structureTree;
     }
+    
+    /**
+     * Add another change bar to the stack of active change bars
+     * @param bar The change bar top add
+     */
+    public void pushChangeBar(ChangeBar bar) {
+        stackedChangeBars.addElement(bar);
+    }
+    
+    
+    /**
+     * Remove top level change bar from stack
+     */
+    public void popChangeBar() {
+        stackedChangeBars.removeElementAt(stackedChangeBars.size() - 1);
+    }
+    
+    /**
+     * Return top-most changebar from stack of nested change bars
+     *
+     * @return change bar that is the top most changebar or null
+     */
+    public ChangeBar topChangeBar() {
+        if (stackedChangeBars.isEmpty()) {
+            return null;
+        }
+        else {
+            return (ChangeBar)stackedChangeBars.lastElement();
+        }
+    }
+    
+    /**
+     * Return the list of change bars in effect currently
+     * @return The vector of change bars in effect currently
+     */
+    public Vector getChangeBars() {
+        return stackedChangeBars;
+    }
+    
+
+    /**
+     * Copy the change bars in affect currently 
+     * @return A copy of the change bars in effect currently
+     */
+    public  Vector copyChangeBars() {
+        return (Vector)(stackedChangeBars.clone());        
+    }
 }
 
Index: src/java/org/apache/fop/fo/FOText.java
===================================================================
--- src/java/org/apache/fop/fo/FOText.java	(revision 1078951)
+++ src/java/org/apache/fop/fo/FOText.java	(working copy)
@@ -28,6 +28,7 @@
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.datatypes.Length;
 import org.apache.fop.fo.flow.Block;
+import org.apache.fop.fo.flow.ChangeBar;
 import org.apache.fop.fo.properties.CommonFont;
 import org.apache.fop.fo.properties.CommonHyphenation;
 import org.apache.fop.fo.properties.CommonTextDecoration;
@@ -90,6 +91,11 @@
      */
     public FOText(FONode parent) {
         super(parent);
+        // check if we are under the influence of change bars
+        if (null != getUserAgent().topChangeBar()) {
+            // OK, so copy over the stack of change bars
+            affectedByChangeBars = getUserAgent().copyChangeBars();
+        }
     }
 
     /** {@inheritDoc} */
Index: src/java/org/apache/fop/fo/FONode.java
===================================================================
--- src/java/org/apache/fop/fo/FONode.java	(revision 1078951)
+++ src/java/org/apache/fop/fo/FONode.java	(working copy)
@@ -22,6 +22,7 @@
 // Java
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.Vector;
 
 import org.xml.sax.Attributes;
 import org.xml.sax.Locator;
@@ -59,6 +60,12 @@
     /** pointer to the sibling nodes */
     protected FONode[] siblings;
 
+    /** change bars affecting this */
+    protected Vector affectedByChangeBars = null;
+    
+    /** change bars at start of element */
+    protected Vector affectedByChangeBarsStart = null;
+    
     /**
      * Marks the location of this object from the input FO
      *   <br>Call <code>locator.getSystemId()</code>,
@@ -170,6 +177,18 @@
     }
 
     /**
+     * Convenience function to check if this element is a change bar element
+     * @param namespaceURI  The name space of the element
+     * @param localName  The local name of the element
+     * @return true if a member, false if not
+     */
+    public boolean isChangeBarElement(String namespaceURI, String localName) {
+        return FO_URI.equals(namespaceURI) 
+                   && ( "change-bar-begin".equals(localName) 
+                        || "change-bar-end".equals(localName) );
+    }
+    
+    /**
      * Returns the user agent that is associated with the
      * tree's <code>FOEventHandler</code>.
      *
@@ -912,4 +931,14 @@
 
     }
 
+    /**
+     * Return the change bars that affect this element 
+     *
+     * @return vector of change bars elements affecting this element 
+     */
+    public Vector/*<ChangeBar>*/getChangeBars() {
+        return affectedByChangeBars;
+    }
+    
+    
 }
Index: src/java/org/apache/fop/fo/FObj.java
===================================================================
--- src/java/org/apache/fop/fo/FObj.java	(revision 1078951)
+++ src/java/org/apache/fop/fo/FObj.java	(working copy)
@@ -26,6 +26,7 @@
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Set;
+import java.util.Vector;
 
 import org.xml.sax.Attributes;
 import org.xml.sax.Locator;
@@ -36,6 +37,7 @@
 import org.apache.fop.fo.extensions.ExtensionAttachment;
 import org.apache.fop.fo.flow.Marker;
 import org.apache.fop.fo.properties.PropertyMaker;
+import org.apache.fop.fo.flow.ChangeBar;
 
 /**
  * Base class for representation of formatting objects and their processing.
@@ -153,9 +155,50 @@
         if (id != null) {
             checkId(id);
         }
+        // check if we are under the influence of change bars
+        if (null != getUserAgent().topChangeBar()) {
+            // OK, so copy over the stack of change bars
+            affectedByChangeBarsStart = getUserAgent().copyChangeBars();
+        }
     }
 
     /**
+     * {@inheritDoc}
+     * @throws FOPException FOP Exception
+     */
+     protected void endOfNode() throws FOPException {
+         // now take all change bars that are active now and were active at the start
+         //  of node and put them into the affectedByChangeBars
+         Vector nowChangeBars = getUserAgent().copyChangeBars();
+     
+ 
+         if (null != affectedByChangeBarsStart && null != nowChangeBars) {
+                 // to save memory, we first try to match all elements to the start
+                 if (affectedByChangeBarsStart.containsAll(nowChangeBars)
+                       && nowChangeBars.containsAll(affectedByChangeBarsStart)) {
+                         affectedByChangeBars = affectedByChangeBarsStart;
+                 }
+                 else {
+                         affectedByChangeBars = new Vector();
+
+                         for (int idx = 0; idx < nowChangeBars.size(); idx++) {
+                                 if (affectedByChangeBarsStart.contains(nowChangeBars.get(idx))) {
+                                     affectedByChangeBars.add(nowChangeBars.get(idx));
+                                 }
+                         }
+    
+                         if (0 == affectedByChangeBars.size()) {
+                                 affectedByChangeBars = null;
+                         }
+                 }
+
+                 affectedByChangeBarsStart = null;
+         }
+
+        super.endOfNode();
+    }
+
+    /**
      * Setup the id for this formatting object.
      * Most formatting objects can have an id that can be referenced.
      * This methods checks that the id isn't already used by another FO
Index: src/java/org/apache/fop/fo/flow/ChangeBar.java
===================================================================
--- src/java/org/apache/fop/fo/flow/ChangeBar.java	(revision 0)
+++ src/java/org/apache/fop/fo/flow/ChangeBar.java	(revision 0)
@@ -0,0 +1,196 @@
+/*
+ * 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.fo.flow;
+
+import java.awt.Color;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Vector;
+import java.util.TreeMap;
+    
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOTreeBuilderContext;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.FObjMixed;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.PropertyListMaker;
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.Property;
+import org.apache.fop.fo.properties.PropertyCache;
+import org.apache.fop.datatypes.Length;
+
+/** Common change bar base class. Handles properties and local child validation */
+public abstract class ChangeBar extends FObj {
+
+    
+    /**
+     * Construct a ChangeBar element, common parts for start and end
+     *
+     * @param parent the parent element, containing the change bars start/end
+     */
+    public ChangeBar(FONode parent) {
+        super(parent);
+
+        
+    }
+
+    
+    /**
+     * The class of the change bar, must be provided
+     */
+    protected String cbClass = null;
+    
+    /**
+     * The color of the change bar
+     */
+    protected Color color = null;
+    
+    /**
+     * The offset of the bar from the column
+     */
+    protected Length offset = null;
+    
+    /**
+     * The placement of the bar
+     */
+    protected int placement = -1;
+    
+    /**
+     * The style of the bar
+     */
+    protected int style = -1;
+    
+    /**
+     * The width of the bar
+     */
+    protected Length width = null;
+    
+    
+    /** {@inheritDoc} */
+    public void bind(PropertyList pList) throws FOPException {
+        super.bind(pList);
+                    
+        cbClass = pList.get(PR_CHANGE_BAR_CLASS).getString();
+        color = pList.get(PR_CHANGE_BAR_COLOR).getColor(getUserAgent());
+        offset = pList.get(PR_CHANGE_BAR_OFFSET).getLength(); 
+        placement = pList.get(PR_CHANGE_BAR_PLACEMENT).getEnum();
+        style = pList.get(PR_CHANGE_BAR_STYLE).getEnum();
+        width = pList.get(PR_CHANGE_BAR_WIDTH).getLength();
+    }
+    
+    /**
+     * Return the class of the change bar.
+     * @return the class of the change bar as a string
+     */
+    public String getCBClass() {
+        return cbClass;
+    }
+
+    /** {@inheritDoc} */
+    protected void validateChildNode(
+            Locator loc,
+            String namespaceURI,
+            String localName)
+   throws ValidationException {
+        // no children allowed
+        invalidChildError(loc, namespaceURI, localName);
+    }
+
+    /** {@inheritDoc} */
+    public void processNode(String elementName, Locator locator, 
+                            Attributes attlist, PropertyList pList) throws FOPException {
+        super.processNode(elementName, locator, attlist, pList);
+        if (cbClass == null || "".equals(cbClass)) {
+            missingPropertyError("change-bar-class");
+        }
+        
+        if ( -1 == findAncestor(FO_FLOW)
+             && -1 == findAncestor(FO_STATIC_CONTENT) ) {
+            getFOValidationEventProducer().changeBarWrongAncestor(this, getName(), locator);
+          }
+    }
+    
+ 
+    
+    
+    /**
+     * Push the current change bar on the stack
+     */
+    protected void push() {
+        getUserAgent().pushChangeBar(this);
+    }
+    
+    /**
+     * Remove top level change bar from stack
+     */
+    protected void pop() {
+        getUserAgent().popChangeBar();
+ 
+    }
+    
+    /**
+     * Return top-most change bar from the stack of nested change bars.
+     *
+     * @return the topmost changebar or null
+     */
+    protected ChangeBar top() {
+        return getUserAgent().topChangeBar();
+    }
+
+    /**
+     * @return the color
+     */
+    public Color getColor() {
+        return color;
+    }
+
+    /**
+     * @return the offset
+     */
+    public Length getOffset() {
+        return offset;
+    }
+
+    /**
+     * @return the placement
+     */
+    public int getPlacement() {
+        return placement;
+    }
+
+    /**
+     * @return the style
+     */
+    public int getStyle() {
+        return style;
+    }
+
+    /**
+     * @return the width
+     */
+    public Length getWidth() {
+        return width;
+    }
+}
Index: src/java/org/apache/fop/fo/flow/ChangeBarEnd.java
===================================================================
--- src/java/org/apache/fop/fo/flow/ChangeBarEnd.java	(revision 0)
+++ src/java/org/apache/fop/fo/flow/ChangeBarEnd.java	(revision 0)
@@ -0,0 +1,87 @@
+/*
+ * 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.fo.flow;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOTreeBuilderContext;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.FObjMixed;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.PropertyListMaker;
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.Property;
+import org.apache.fop.fo.properties.PropertyCache;
+
+/**
+ * End of a change bar element. Notes the end of the affected objects of a change bar.
+ *  */
+public class ChangeBarEnd extends ChangeBar {
+
+    /**
+     * Construct a new ChangeBarEnd element
+     * @param parent the parent of the element
+     */
+    public ChangeBarEnd(FONode parent) {
+        super(parent);
+    }
+
+    /** {@inheritDoc} */
+    public String getLocalName() {
+        return "change-bar-end";
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @return {@link org.apache.fop.fo.Constants#FO_CHANGE_BAR_END}
+     */
+    public int getNameId() {
+        return FO_CHANGE_BAR_END;
+    }
+    
+    /** {@inheritDoc} */
+    public void processNode(String elementName, Locator locator,
+                            Attributes attlist, PropertyList pList) throws FOPException {
+        super.processNode(elementName, locator, attlist, pList);
+        
+        // check if we have an element on the stack at all
+        ChangeBar topElement = top();
+        
+        if (null == topElement) {
+            getFOValidationEventProducer().changeBarNoBegin(this, getName(), locator);
+        } else {
+            if (!topElement.cbClass.equals(cbClass)) {
+                getFOValidationEventProducer().changeBarWrongStacking(this,
+                        getName(), topElement.cbClass, cbClass, locator);
+            }
+            pop();
+        }
+        
+        
+    }
+    
+}
Index: src/java/org/apache/fop/fo/flow/ChangeBarBegin.java
===================================================================
--- src/java/org/apache/fop/fo/flow/ChangeBarBegin.java	(revision 0)
+++ src/java/org/apache/fop/fo/flow/ChangeBarBegin.java	(revision 0)
@@ -0,0 +1,77 @@
+/*
+ * 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.fo.flow;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.FOTreeBuilderContext;
+import org.apache.fop.fo.FObj;
+import org.apache.fop.fo.FObjMixed;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.PropertyListMaker;
+import org.apache.fop.fo.ValidationException;
+import org.apache.fop.fo.properties.Property;
+import org.apache.fop.fo.properties.PropertyCache;
+
+/**
+ * Change bar begin element. Notes the beginning of change bar of a certain class.
+ * 
+ */
+public class ChangeBarBegin extends ChangeBar {
+
+    
+    /**
+     * Construct a new ChangeBarEnd element
+     *
+     * @param parent the parent element of the new change bar end element
+     */
+    public ChangeBarBegin(FONode parent) {
+        super(parent);
+    }
+
+    /** {@inheritDoc} */
+    public String getLocalName() {
+        return "change-bar-begin";
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @return {@link org.apache.fop.fo.Constants#FO_CHANGE_BAR_BEGIN}
+     */
+    public int getNameId() {
+        return FO_CHANGE_BAR_BEGIN;
+    }
+    
+    /** {@inheritDoc} */
+    public void processNode(String elementName, Locator locator,
+                            Attributes attlist, PropertyList pList) throws FOPException {
+        super.processNode(elementName, locator, attlist, pList);
+
+        push();
+
+    }
+}
Index: src/java/org/apache/fop/fo/FOElementMapping.java
===================================================================
--- src/java/org/apache/fop/fo/FOElementMapping.java	(revision 1078951)
+++ src/java/org/apache/fop/fo/FOElementMapping.java	(working copy)
@@ -136,6 +136,10 @@
             foObjs.put("marker", new MarkerMaker());
             foObjs.put("retrieve-marker", new RetrieveMarkerMaker());
             foObjs.put("retrieve-table-marker", new RetrieveTableMarkerMaker());
+            
+            // change bars
+            foObjs.put("change-bar-begin", new ChangeBarBeginMaker());
+            foObjs.put("change-bar-end", new ChangeBarEndMaker());
         }
     }
 
@@ -520,4 +524,17 @@
             return new org.apache.fop.fo.flow.RetrieveTableMarker(parent);
         }
     }
+    
+    static class ChangeBarBeginMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new org.apache.fop.fo.flow.ChangeBarBegin(parent);
+        }
+    }
+    
+    static class ChangeBarEndMaker extends ElementMapping.Maker {
+        public FONode make(FONode parent) {
+            return new org.apache.fop.fo.flow.ChangeBarEnd(parent);
+        }
+    }  
+    
 }
Index: src/java/org/apache/fop/fo/FOValidationEventProducer.java
===================================================================
--- src/java/org/apache/fop/fo/FOValidationEventProducer.java	(revision 1078951)
+++ src/java/org/apache/fop/fo/FOValidationEventProducer.java	(working copy)
@@ -357,6 +357,47 @@
             QName offendingNode, Locator loc);
 
     /**
+     * A class for change bars is not unique.
+     * @param source the event source
+     * @param elementName the name of the context node
+     * @param name the class name
+     * @param loc the location of the error or null
+     * @event.severity FATAL
+     */
+    void changeBarClassNotUnique(Object source, String elementName, String name,
+            Locator loc);
+    
+    /**
+     * Change bars were not stacked correctly
+     * @param source the event source
+     * @param elementName the name of the context node
+     * @param beginName the class name of the beginning change bar
+     * @param endName the class name of the ending change bar
+     * @param loc the location of the error or null
+     * @event.severity FATAL
+     */
+    void changeBarWrongStacking(Object source, String elementName, String beginName,
+            String endName, Locator loc);
+    
+    /**
+     * Change bar ended without a start of bar occurred
+     * @param source the event source
+     * @param elementName the name of the context node
+     * @param loc the location of the error or null
+     * @event.severity FATAL
+     */
+    void changeBarNoBegin(Object source, String elementName, 
+            Locator loc);
+    /**
+     * Change bar not descendant of fo:flow or fo:static-content
+     * @param source the event source
+     * @param elementName the name of the context node
+     * @param loc the location of the error or null
+     * @event.severity FATAL
+     */
+    void changeBarWrongAncestor(Object source, String elementName, Locator loc);
+
+    /**
      * Alternate text is missing for a graphic element.
      *
      * @param source the event source
Index: src/java/org/apache/fop/fo/FOPropertyMapping.java
===================================================================
--- src/java/org/apache/fop/fo/FOPropertyMapping.java	(revision 1078951)
+++ src/java/org/apache/fop/fo/FOPropertyMapping.java	(working copy)
@@ -318,6 +318,7 @@
             gp.createTableProperties();
             gp.createWritingModeProperties();
             gp.createMiscProperties();
+            gp.createChangeBarProperties();
 
             // Hardcode the subproperties.
             addSubpropMakerName("length", CP_LENGTH);
@@ -2518,6 +2519,62 @@
         addPropertyMaker("writing-mode", m);
     }
 
+    private void createChangeBarProperties() {
+        PropertyMaker m;
+        
+        // change-bar-class
+        m = new StringProperty.Maker(PR_CHANGE_BAR_CLASS);
+        m.setInherited(false);
+        m.setDefault("");
+        addPropertyMaker("change-bar-class", m);
+        
+        // change-bar-color
+        m  = new ColorProperty.Maker(PR_CHANGE_BAR_COLOR);
+        
+        m.setInherited(true);
+        // TODO: fall back to "color" property
+        m.setDefault("black");
+        addPropertyMaker("change-bar-color", m);
+        
+        // change-bar-offset
+        m  = new LengthProperty.Maker(PR_CHANGE_BAR_OFFSET);
+        m.setInherited(true);
+        m.setDefault("6pt");
+        addPropertyMaker("change-bar-offset", m);      
+        
+        // change-bar-placement
+        m = new EnumProperty.Maker(PR_CHANGE_BAR_PLACEMENT);
+        m.setInherited(true);
+        m.setDefault("start");
+        m.addEnum("start", getEnumProperty(EN_START, "START"));
+        m.addEnum("end", getEnumProperty(EN_END, "END"));
+        m.addEnum("left", getEnumProperty(EN_LEFT, "LEFT"));
+        m.addEnum("right", getEnumProperty(EN_RIGHT, "RIGHT"));
+        m.addEnum("inside", getEnumProperty(EN_INSIDE, "INSIDE"));
+        m.addEnum("outside", getEnumProperty(EN_OUTSIDE, "OUTSIDE"));
+        m.addEnum("alternate", getEnumProperty(EN_ALTERNATE, "ALTERNATE"));
+        addPropertyMaker("change-bar-placement", m);
+        
+        // change-bar-style
+        m = new EnumProperty.Maker(PR_CHANGE_BAR_STYLE);
+        m.useGeneric(genericBorderStyle);      
+        m.setInherited(true); 
+        m.setDefault("solid");
+        addPropertyMaker("change-bar-style", m);
+        
+        // change-bar-width
+        m  = new LengthProperty.Maker(PR_CHANGE_BAR_WIDTH);
+        m.setInherited(true);
+        m.setDefault("6pt");
+        addPropertyMaker("change-bar-width", m); 
+
+        // change-bar-offset
+        m  = new LengthProperty.Maker(PR_CHANGE_BAR_OFFSET);
+        m.setInherited(true);
+        m.setDefault("6pt");
+        addPropertyMaker("change-bar-offset", m);      
+    }
+    
     private void createMiscProperties() {
         PropertyMaker m;
 
Index: src/java/org/apache/fop/fo/FOTreeBuilder.java
===================================================================
--- src/java/org/apache/fop/fo/FOTreeBuilder.java	(revision 1078951)
+++ src/java/org/apache/fop/fo/FOTreeBuilder.java	(working copy)
@@ -264,7 +264,9 @@
             } else { // check that incoming node is valid for currentFObj
                 if (currentFObj.getNamespaceURI().equals(FOElementMapping.URI)
                     || currentFObj.getNamespaceURI().equals(ExtensionElementMapping.URI)) {
-                    currentFObj.validateChildNode(locator, namespaceURI, localName);
+                    if (!currentFObj.isChangeBarElement(namespaceURI, localName)) {
+                        currentFObj.validateChildNode(locator, namespaceURI, localName);
+                    }
                 }
             }
 
Index: src/java/org/apache/fop/area/BodyRegion.java
===================================================================
--- src/java/org/apache/fop/area/BodyRegion.java	(revision 1078951)
+++ src/java/org/apache/fop/area/BodyRegion.java	(working copy)
@@ -46,7 +46,8 @@
      * @param parent the parent region viewport
      */
     public BodyRegion(RegionBody rb, RegionViewport parent) {
-        this(rb.getNameId(), rb.getRegionName(), parent, rb.getColumnCount(), rb.getColumnGap());
+        this(rb.getNameId(), rb.getRegionName(), parent, rb.getColumnCount(), rb.getColumnGap(),
+                rb.getWritingMode(), rb.getReferenceOrientation());
     }
 
     /**
@@ -57,10 +58,13 @@
      * @param parent the parent region viewport
      * @param columnCount the number of columns
      * @param columnGap the gap between columns
+     * @param wrMode writing Mode
+     * @param refOrient reference orientation
      */
     public BodyRegion(int regionClass, String regionName, RegionViewport parent,
-            int columnCount, int columnGap) {
-        super(regionClass, regionName, parent);
+            int columnCount, int columnGap, int wrMode, int refOrient) {
+        super(regionClass, regionName, parent, wrMode, refOrient);
+        
         this.columnCount = columnCount;
         this.columnGap = columnGap;
         mainReference = new MainReference(this);
@@ -146,7 +150,7 @@
      */
     public Object clone() {
         BodyRegion br = new BodyRegion(getRegionClass(), getRegionName(), regionViewport,
-                getColumnCount(), getColumnGap());
+                getColumnCount(), getColumnGap(), getWritingMode(), getReferenceOrientation());
         br.setCTM(getCTM());
         br.setIPD(getIPD());
         br.beforeFloat = beforeFloat;
Index: src/java/org/apache/fop/area/MainReference.java
===================================================================
--- src/java/org/apache/fop/area/MainReference.java	(revision 1078951)
+++ src/java/org/apache/fop/area/MainReference.java	(working copy)
@@ -124,5 +124,9 @@
         return parent.getColumnGap();
     }
 
+    /** @return the parent region of this area */
+    public BodyRegion getParent() {
+        return parent;
+    }
 }
 
Index: src/java/org/apache/fop/area/AreaTreeParser.java
===================================================================
--- src/java/org/apache/fop/area/AreaTreeParser.java	(revision 1078951)
+++ src/java/org/apache/fop/area/AreaTreeParser.java	(working copy)
@@ -95,6 +95,7 @@
 import static org.apache.fop.fo.Constants.FO_REGION_BODY;
 import static org.apache.fop.fo.Constants.FO_REGION_END;
 import static org.apache.fop.fo.Constants.FO_REGION_START;
+import static org.apache.fop.fo.Constants.EN_LR_TB;
 
 /**
  * This is a parser for the area tree XML (intermediate format) which is used to reread an area
@@ -582,8 +583,12 @@
                 String regionName = attributes.getValue("name");
                 int columnCount = XMLUtil.getAttributeAsInt(attributes, "columnCount", 1);
                 int columnGap = XMLUtil.getAttributeAsInt(attributes, "columnGap", 0);
+                int wrMode = XMLUtil.getAttributeAsInt(attributes, "writingMode",
+                        EN_LR_TB);
+                int refOrient = XMLUtil.getAttributeAsInt(attributes, "referenceOrientation", 0);
                 RegionViewport rv = getCurrentRegionViewport();
-                body = new BodyRegion(FO_REGION_BODY, regionName, rv, columnCount, columnGap);
+                body = new BodyRegion(FO_REGION_BODY,
+                        regionName, rv, columnCount, columnGap, wrMode, refOrient);
                 transferForeignObjects(attributes, body);
                 body.setCTM(getAttributeAsCTM(attributes, "ctm"));
                 setAreaAttributes(attributes, body);
@@ -1028,7 +1033,8 @@
             String regionName = attributes.getValue("name");
             RegionViewport rv = getCurrentRegionViewport();
             RegionReference reg = new RegionReference(side,
-                    regionName, rv);
+                    regionName, rv, Integer.parseInt(attributes.getValue("writingMode")),
+                    Integer.parseInt(attributes.getValue("referenceOrientation")));
             transferForeignObjects(attributes, reg);
             reg.setCTM(getAttributeAsCTM(attributes, "ctm"));
             setAreaAttributes(attributes, reg);
Index: src/java/org/apache/fop/area/inline/TextArea.java
===================================================================
--- src/java/org/apache/fop/area/inline/TextArea.java	(revision 1078951)
+++ src/java/org/apache/fop/area/inline/TextArea.java	(working copy)
@@ -69,6 +69,8 @@
      */
     public void addWord(String word, int offset, int[] letterAdjust) {
         WordArea wordArea = new WordArea(word, offset, letterAdjust);
+        wordArea.setChangeBars(getChangeBars());
+        
         addChildArea(wordArea);
         wordArea.setParentArea(this);
     }
@@ -82,6 +84,8 @@
      */
     public void addSpace(char space, int offset, boolean adjustable) {
         SpaceArea spaceArea = new SpaceArea(space, offset, adjustable);
+       spaceArea.setChangeBars(getChangeBars());
+       
         addChildArea(spaceArea);
         spaceArea.setParentArea(this);
     }
Index: src/java/org/apache/fop/area/RegionReference.java
===================================================================
--- src/java/org/apache/fop/area/RegionReference.java	(revision 1078951)
+++ src/java/org/apache/fop/area/RegionReference.java	(working copy)
@@ -23,6 +23,7 @@
 import java.util.List;
 
 import org.apache.fop.fo.pagination.Region;
+import org.apache.fop.fo.Constants;
 
 /**
  * This is a region reference area for a page regions.
@@ -36,6 +37,8 @@
     private int regionClass;
     private String regionName;
     private CTM ctm;
+    private int writingMode;
+    private int referenceOrientation;
 
     // the list of block areas from the static flow
     private ArrayList<Area> blocks = new ArrayList<Area>();
@@ -50,7 +53,8 @@
      * @param parent the viewport for this region.
      */
     public RegionReference(Region regionFO, RegionViewport parent) {
-        this(regionFO.getNameId(), regionFO.getRegionName(), parent);
+        this(regionFO.getNameId(), regionFO.getRegionName(), parent,
+                Constants.EN_LR_TB, 0);
     }
 
     /**
@@ -59,10 +63,16 @@
      * @param regionClass the region class (as returned by Region.getNameId())
      * @param regionName the name of the region (as returned by Region.getRegionName())
      * @param parent the viewport for this region.
+     * @param wrMode writing mode
+     * @param refOrient reference orientation
      */
-    public RegionReference(int regionClass, String regionName, RegionViewport parent) {
+    public RegionReference(int regionClass, String regionName, RegionViewport parent,
+            int wrMode, int refOrient) {
         this.regionClass = regionClass;
         this.regionName = regionName;
+        this.writingMode = wrMode;
+        this.referenceOrientation = refOrient;
+        
         addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
         regionViewport = parent;
     }
@@ -141,7 +151,8 @@
      * @return a copy of this region reference area
      */
     public Object clone() {
-        RegionReference rr = new RegionReference(regionClass, regionName, regionViewport);
+        RegionReference rr = new RegionReference(regionClass, regionName, regionViewport,
+                                                 writingMode, referenceOrientation);
         rr.ctm = ctm;
         rr.setIPD(getIPD());
         rr.blocks = (ArrayList<Area>)blocks.clone();
@@ -158,4 +169,16 @@
         sb.append("}");
         return sb.toString();
     }
+    
+    
+    /** @return the writing mode of this region */
+    public int getWritingMode() {
+        return writingMode;
+    }
+    
+    /** @return the reference orientation of this region */
+    public int getReferenceOrientation() {
+        return referenceOrientation;
+    }
+    
 }
Index: src/java/org/apache/fop/area/Area.java
===================================================================
--- src/java/org/apache/fop/area/Area.java	(revision 1078951)
+++ src/java/org/apache/fop/area/Area.java	(working copy)
@@ -21,6 +21,7 @@
 
 import java.io.Serializable;
 import java.util.Map;
+import java.util.Vector;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -141,6 +142,28 @@
 
 
     /**
+     * The vector of change bars this arrea is affected by
+     */
+    private Vector/*<ChangeBar>*/ changeBars = null;
+    
+    /**
+     * Return the vector of change bars this area is affected by
+     * @return Vector of change bars or null
+     */
+    public Vector/*<ChangeBar>*/ getChangeBars()   {
+        return changeBars;
+    }
+    
+    /**
+     * Set the vector of change bars affecting this area
+     * 
+     * @param cbs the vector of change bars affecting the area
+     */
+    public void setChangeBars(Vector/*<ChangeBar>*/ cbs)   {
+        changeBars = cbs;
+    }
+    
+    /**
      * Get the area class of this area.
      *
      * @return the area class
