### Eclipse Workspace Patch 1.0
#P fop_trunk
Index: src/java/org/apache/fop/render/rtf/RTFHandler.java
===================================================================
--- src/java/org/apache/fop/render/rtf/RTFHandler.java	(revision 1087675)
+++ src/java/org/apache/fop/render/rtf/RTFHandler.java	(working copy)
@@ -117,6 +117,7 @@
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfList;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfListItem;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfPage;
+import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfParagraphBreak;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfSection;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTable;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfTableCell;
@@ -434,8 +435,14 @@
                     true, this);
 
             RtfTextrun textrun = container.getTextrun();
-
-            textrun.addParagraphBreak();
+            RtfParagraphBreak par = textrun.addParagraphBreak();
+            
+            RtfTableCell cellParent = (RtfTableCell)textrun.getParentOfClass(RtfTableCell.class);
+            if (cellParent != null && par != null) {
+                int iDepth = cellParent.findChildren(textrun);
+                cellParent.setLastParagraph(par, iDepth);
+            }
+            
             int breakValue = toRtfBreakValue(bl.getBreakAfter());
             textrun.popBlockAttributes(breakValue);
 
@@ -882,7 +889,15 @@
         if (bDefer) {
             return;
         }
-
+        try {
+            RtfTableCell cell = (RtfTableCell)builderContext.getContainer(RtfTableCell.class, false, this);
+            cell.finish();
+            
+        } catch (Exception e) {
+            log.error("endCell: " + e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
+        
         builderContext.popContainer();
         builderContext.getTableContext().selectNextColumn();
     }
Index: src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfContainer.java
===================================================================
--- src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfContainer.java	(revision 1087675)
+++ src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfContainer.java	(working copy)
@@ -108,6 +108,31 @@
     public int getChildCount() {
         return children.size();
     }
+    
+    private int findChildren(RtfElement aChild, int iStart) {
+        for (Iterator it = this.getChildren().iterator(); it.hasNext();) {
+          final RtfElement e = (RtfElement)it.next();
+          if (aChild == e) {
+              return iStart;
+          }
+          else if (e instanceof RtfContainer) {
+              int iFound = ((RtfContainer)e).findChildren(aChild, (iStart + 1));
+              if (iFound != -1) {
+                  return iFound;
+              }
+          }
+        }
+        return -1;
+    }
+    
+    /**
+     * Find the passed child in the current container
+     * @param aChild the child element
+     * @return the depth (nested level) inside the current container
+     */
+    public int findChildren(RtfElement aChild) {
+        return findChildren(aChild, 0); 
+    }
 
     /**
      * Add by Boris Poudérous on 07/22/2002
Index: src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraphBreak.java
===================================================================
--- src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraphBreak.java	(revision 0)
+++ src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfParagraphBreak.java	(revision 0)
@@ -0,0 +1,52 @@
+package org.apache.fop.render.rtf.rtflib.rtfdoc;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**  Class which represents a paragraph break.*/
+
+public class RtfParagraphBreak extends RtfElement {
+    private final String DEFAULT_PARAGRAPH = "par";
+    
+    private String sControlWord = DEFAULT_PARAGRAPH;
+    
+    RtfParagraphBreak(RtfContainer parent, Writer w)
+            throws IOException {
+        super(parent, w);
+    }
+
+    /**
+     * @return true if this element would generate no "useful" RTF content
+     */
+    public boolean isEmpty() {
+        return false;
+    }
+
+    /**
+     * write RTF code of all our children
+     * @throws IOException for I/O problems
+     */
+    protected void writeRtfContent() throws IOException {
+        if (sControlWord != null ) {
+            writeControlWord(sControlWord);
+        }
+    }
+    
+    /**
+     * Whether or not the break can be skipped.
+     * If the paragraph marks a table cell end it is not possible
+     * @return boolean
+     */
+    public boolean canHide() {
+        return this.sControlWord == DEFAULT_PARAGRAPH;
+    }
+    
+    /**
+     * Sets a different control word for this paragraph. If this method
+     * is used the paragraph will always be displayed (@see canHide))
+     * @param sControlWord the new control word
+     */
+    public void switchControlWord(String sControlWord) {
+        this.sControlWord = sControlWord;
+    }
+}
\ No newline at end of file
Index: src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableCell.java
===================================================================
--- src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableCell.java	(revision 1087675)
+++ src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTableCell.java	(working copy)
@@ -46,6 +46,11 @@
     private boolean setCenter;
     private boolean setRight;
     private int id;
+    private RtfParagraphBreak lastBreak = null;
+    private int lastBreakDepth = Integer.MIN_VALUE;
+    
+    private final String TABLE_CELL_PARAGRAPH = "cell";
+    private final String TABLE_CELL_NESTED_PARAGRAPH = "nestcell";
 
     /** default cell width (in twips ??) */
     public static final int DEFAULT_CELL_WIDTH = 2000;
@@ -310,7 +315,9 @@
 
         if (getRow().getTable().isNestedTable()) {
             //nested table
-            writeControlWordNS("nestcell");
+            if (lastBreak == null) {
+                writeControlWordNS("nestcell");
+            }
             writeGroupMark(true);
             writeControlWord("nonesttables");
             writeControlWord("par");
@@ -350,7 +357,9 @@
                 //writeControlWord("par");
             }
 
-            writeControlWord("cell");
+            if (lastBreak == null) {
+                writeControlWord("cell");
+            }
         }
     }
 
@@ -533,4 +542,39 @@
 
         return null;
     }
+    
+    /**
+     * The table cell decides whether or not a newly added paragraph break
+     * will be used to write the cell-end control word.
+     * For nested tables it is not necessary.
+     * 
+     * @param parBreak the paragraph break element
+     * @param breakDepth The depth is necessary for picking the correct break element.
+     * If it is deeper inside the whole cell it will be used, and if there is something on
+     * the same level (depth) it is also set because the method is called for all breaks
+     * in the correct order.
+     */
+    public void setLastParagraph(RtfParagraphBreak parBreak, int breakDepth) {
+        if (parBreak != null && breakDepth >= lastBreakDepth) {
+            lastBreak = parBreak;
+            lastBreakDepth = breakDepth;
+        }
+    }
+    
+    /**
+     * The last paragraph break was just stored before,
+     * now the control word is really switched
+     */
+    public void finish() {
+      //If it is nested and contains another table do not set it
+      if (getRow().getTable().isNestedTable() && table != null) {
+          lastBreak = null;
+      }
+      else if (lastBreak != null) {
+              lastBreak.switchControlWord(
+                                          getRow().getTable().isNestedTable()
+                                          ? TABLE_CELL_NESTED_PARAGRAPH
+                                          : TABLE_CELL_PARAGRAPH);
+      }
+    }
 }
Index: src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfElement.java
===================================================================
--- src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfElement.java	(revision 1087675)
+++ src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfElement.java	(working copy)
@@ -298,7 +298,7 @@
     /** find the first parent where c.isAssignableFrom(parent.getClass()) is true
      *  @return null if not found
      */
-    RtfElement getParentOfClass(Class c) {
+    public RtfElement getParentOfClass(Class c) {
         RtfElement result = null;
         RtfElement current = this;
         while (current.parent != null) {
Index: src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java
===================================================================
--- src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java	(revision 1087675)
+++ src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java	(working copy)
@@ -143,30 +143,6 @@
         }
     }
 
-    /**  Class which represents a paragraph break.*/
-    private class RtfParagraphBreak extends RtfElement {
-
-        RtfParagraphBreak(RtfContainer parent, Writer w)
-                throws IOException {
-            super(parent, w);
-        }
-
-        /**
-         * @return true if this element would generate no "useful" RTF content
-         */
-        public boolean isEmpty() {
-            return false;
-        }
-
-        /**
-         * write RTF code of all our children
-         * @throws IOException for I/O problems
-         */
-        protected void writeRtfContent() throws IOException {
-            writeControlWord("par");
-        }
-    }
-
     /** Create an RTF container as a child of given container */
     RtfTextrun(RtfContainer parent, Writer w, RtfAttributes attrs) throws IOException {
         super(parent, w, attrs);
@@ -290,33 +266,36 @@
      * Inserts paragraph break before all close group marks.
      *
      * @throws IOException  for I/O problems
+     * @return The paragraph break element
      */
-    public void addParagraphBreak() throws IOException {
-      // get copy of children list
-      List children = getChildren();
-      Stack tmp = new Stack();
+    public RtfParagraphBreak addParagraphBreak() throws IOException {
+        // get copy of children list
+        List children = getChildren();
+        Stack tmp = new Stack();
+        RtfParagraphBreak par = null;
+        
+        // delete all previous CloseGroupMark
+        int deletedCloseGroupCount = 0;
 
-      // delete all previous CloseGroupMark
-      int deletedCloseGroupCount = 0;
+        ListIterator lit = children.listIterator(children.size());
+        while (lit.hasPrevious()
+                && (lit.previous() instanceof RtfCloseGroupMark)) {
+            tmp.push(Integer.valueOf(((RtfCloseGroupMark)lit.next()).getBreakType()));
+            lit.remove();
+            deletedCloseGroupCount++;
+        }
 
-      ListIterator lit = children.listIterator(children.size());
-      while (lit.hasPrevious()
-              && (lit.previous() instanceof RtfCloseGroupMark)) {
-          tmp.push(Integer.valueOf(((RtfCloseGroupMark)lit.next()).getBreakType()));
-          lit.remove();
-          deletedCloseGroupCount++;
-      }
+        if (children.size() != 0) {
+            // add paragraph break and restore all deleted close group marks
+            setChildren(children);
+            par = new RtfParagraphBreak(this, writer);
+            for (int i = 0; i < deletedCloseGroupCount; i++) {
+                addCloseGroupMark(((Integer)tmp.pop()).intValue());
+            }
+        }
+        return par;
+    }
 
-      if (children.size() != 0) {
-          // add paragraph break and restore all deleted close group marks
-          setChildren(children);
-          new RtfParagraphBreak(this, writer);
-          for (int i = 0; i < deletedCloseGroupCount; i++) {
-              addCloseGroupMark(((Integer)tmp.pop()).intValue());
-          }
-      }
-  }
-
     /**
      * Inserts a leader.
      * @param attrs Attributes for the leader
@@ -477,6 +456,8 @@
              * child.
              * -If the RtfTextrun is the last child of its parent, write a
              * RtfParagraphBreak only, if it is not the last child.
+             * -If the RtfParagraphBreak can not be hidden (e.g. a table cell requires it)
+             * it is also written
              */
             boolean bHide = false;
             bHide = bRtfParagraphBreak;
@@ -484,7 +465,9 @@
                 && (bPrevPar
                     || bFirst
                     || (bSuppressLastPar && bLast && lastParagraphBreak != null
-                        && e == lastParagraphBreak));
+                        && e == lastParagraphBreak))
+                    && ((RtfParagraphBreak)e).canHide();
+                    
 
             if (!bHide) {
                 newLine();
