]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla #43825:
authorJeremias Maerki <jeremias@apache.org>
Sun, 6 Jul 2008 16:40:08 +0000 (16:40 +0000)
committerJeremias Maerki <jeremias@apache.org>
Sun, 6 Jul 2008 16:40:08 +0000 (16:40 +0000)
leader supports fixed percent values for leader-length, most other properties
use-content, leader-pattern-width not implemented
Submitted by: Maximilan Aster <maximilian.aster.at.boc-eu.com>

Changes to the patch by Jeremias:
- Adjustments for FOP code conventions

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/fop-0_95@674314 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/render/rtf/RTFHandler.java
src/java/org/apache/fop/render/rtf/TextAttributesConverter.java
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLeader.java [new file with mode: 0644]
src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfTextrun.java
status.xml

index dd7a9bb3fffbbe3db2b1cfdb565559de8602cbf8..d023e1fe4f04ecd3e64be5b981b8d6786c31452e 100644 (file)
@@ -1299,6 +1299,26 @@ public class RTFHandler extends FOEventHandler {
 
     /** {@inheritDoc} */
     public void leader(Leader l) {
+        if (bDefer) {
+            return;
+        }
+
+        try {
+            percentManager.setDimension(l);
+            RtfAttributes rtfAttr = TextAttributesConverter.convertLeaderAttributes(
+                    l, percentManager);
+
+            IRtfTextrunContainer container
+                  = (IRtfTextrunContainer)builderContext.getContainer(
+                      IRtfTextrunContainer.class, true, this);
+            RtfTextrun textrun = container.getTextrun();
+
+            textrun.addLeader(rtfAttr);
+
+        } catch (Exception e) {
+            log.error("startLeader: " + e.getMessage());
+            throw new RuntimeException(e.getMessage());
+        }
     }
 
     /**
@@ -1558,6 +1578,10 @@ public class RTFHandler extends FOEventHandler {
             } else {
                 endCell( (TableCell) foNode);
             }
+        } else if (foNode instanceof Leader) {
+            if (bStart) {
+                leader((Leader) foNode);
+            }
         } else if (foNode instanceof PageNumberCitation) {
             if (bStart) {
                 startPageNumberCitation((PageNumberCitation) foNode);
index d40c6a826c206265924fa23ac713d2766d56e16c..63c470b5db9e3e4d39fd8715862a72fc3babd1d5 100644 (file)
@@ -5,9 +5,9 @@
  * 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.
@@ -21,25 +21,30 @@ package org.apache.fop.render.rtf;
 
 import java.awt.Color;
 
-//FOP
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import org.apache.fop.apps.FOPException;
 import org.apache.fop.datatypes.Length;
+import org.apache.fop.datatypes.PercentBaseContext;
 import org.apache.fop.fo.Constants;
 import org.apache.fop.fo.FONode;
 import org.apache.fop.fo.FOText;
 import org.apache.fop.fo.flow.Block;
 import org.apache.fop.fo.flow.BlockContainer;
 import org.apache.fop.fo.flow.Inline;
+import org.apache.fop.fo.flow.Leader;
 import org.apache.fop.fo.flow.PageNumber;
 import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
 import org.apache.fop.fo.properties.CommonFont;
 import org.apache.fop.fo.properties.CommonMarginBlock;
 import org.apache.fop.fo.properties.CommonTextDecoration;
-import org.apache.fop.render.rtf.BorderAttributesConverter;
+import org.apache.fop.fo.properties.PercentLength;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.IBorderAttributes;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfAttributes;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfColorTable;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfFontManager;
+import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfLeader;
 import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfText;
 
 /**  Converts FO properties to RtfAttributes
@@ -52,13 +57,15 @@ import org.apache.fop.render.rtf.rtflib.rtfdoc.RtfText;
  *  @author rmarra
  */
 final class TextAttributesConverter {
-    
+
+    private static Log log = LogFactory.getLog(TextAttributesConverter.class);
+
     /**
      * Constructor is private, because it's just a utility class.
      */
     private TextAttributesConverter() {
     }
-    
+
     /**
      * Converts all known text FO properties to RtfAttributes
      * @param props list of FO properites, which are to be converted
@@ -106,7 +113,7 @@ final class TextAttributesConverter {
         attrBaseLineShift(fobj.getBaseLineShift(), attrib);
         return attrib;
     }
-    
+
     /**
      * Converts all character related FO properties to RtfAttributes.
      * @param fobj FObj whose properties are to be converted
@@ -137,6 +144,131 @@ final class TextAttributesConverter {
         return attrib;
     }
 
+
+    /**
+     * Converts FO properties used by RtfLeader to RtfAttributes.
+     * @param fobj Leader
+     * @param context PercentBaseContext
+     * @return RtfAttributes
+     * @throws FOPException
+     */
+    public static RtfAttributes convertLeaderAttributes(Leader fobj, PercentBaseContext context)
+                throws FOPException {
+        boolean tab = false;
+        FOPRtfAttributes attrib = new FOPRtfAttributes();
+        attrib.set(RtfText.ATTR_FONT_FAMILY,
+        RtfFontManager.getInstance().getFontNumber(fobj.getCommonFont().getFirstFontFamily()));
+
+        if (fobj.getLeaderLength() != null) {
+            attrib.set(RtfLeader.LEADER_WIDTH, convertMptToTwips(fobj.getLeaderLength().getMaximum(
+                    context).getLength().getValue(context)));
+
+            if (fobj.getLeaderLength().getMaximum(context) instanceof PercentLength) {
+                if (((PercentLength)fobj.getLeaderLength().getMaximum(context)).getString().equals(
+                            "100.0%")) {
+                    // Use Tab instead of white spaces
+                    attrib.set(RtfLeader.LEADER_USETAB, 1);
+                    tab = true;
+                }
+            }
+        }
+
+        attrFontColor(fobj.getColor(), attrib);
+
+        if (fobj.getLeaderPatternWidth() != null) {
+            //TODO calculate pattern width not possible for white spaces, because its using
+            //underlines for tab it would work with LEADER_PATTERN_WIDTH (expndtw)
+        }
+
+        switch(fobj.getLeaderPattern()) {
+        case Constants.EN_DOTS:
+            if (tab) {
+                attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_DOTTED);
+            } else {
+                attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_DOTTED);
+            }
+            break;
+        case Constants.EN_SPACE:
+            //nothing has to be set for spaces
+            break;
+        case Constants.EN_RULE:
+            //Things like start-indent, space-after, ... not supported?
+            //Leader class does not offer these properties
+            //TODO aggregate them with the leader width or
+            // create a second - blank leader - before
+
+            if (fobj.getRuleThickness() != null) {
+                //TODO See inside RtfLeader, better calculation for
+                //white spaces would be necessary
+                //attrib.set(RtfLeader.LEADER_RULE_THICKNESS,
+                //    fobj.getRuleThickness().getValue(context));
+                log.warn("RTF: fo:leader rule-thickness not supported");
+            }
+
+            switch (fobj.getRuleStyle()) {
+            case Constants.EN_SOLID:
+                if (tab) {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_THICK);
+                } else {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_THICK);
+                }
+                break;
+            case Constants.EN_DASHED:
+                if (tab) {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_MIDDLEDOTTED);
+                } else {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_MIDDLEDOTTED);
+                }
+                break;
+            case Constants.EN_DOTTED:
+                if (tab) {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_DOTTED);
+                } else {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_DOTTED);
+                }
+                break;
+            case Constants.EN_DOUBLE:
+                if (tab) {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_EQUAL);
+                } else {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_EQUAL);
+                }
+                break;
+            case Constants.EN_GROOVE:
+                if (tab) {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_HYPHENS);
+                } else {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_HYPHENS);
+                }
+                break;
+            case Constants.EN_RIDGE:
+                if (tab) {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_TAB_UNDERLINE);
+                } else {
+                    attrib.set(RtfLeader.LEADER_TABLEAD, RtfLeader.LEADER_UNDERLINE);
+                }
+                break;
+            default:
+                break;
+            }
+            break;
+        case Constants.EN_USECONTENT:
+            log.warn("RTF: fo:leader use-content not supported");
+            break;
+        default:
+            break;
+        }
+
+        if (fobj.getLeaderAlignment() == Constants.EN_REFERENCE_AREA) {
+            log.warn("RTF: fo:leader reference-area not supported");
+        }
+        return attrib;
+    }
+
+    private static int convertMptToTwips(int mpt) {
+        return Math.round(FoUnitsConverter.getInstance().convertMptToTwips(mpt));
+    }
+
     private static void attrFont(CommonFont font, FOPRtfAttributes rtfAttr) {
         rtfAttr.set(RtfText.ATTR_FONT_FAMILY,
                 RtfFontManager.getInstance().getFontNumber(font.getFirstFontFamily()));
@@ -150,7 +282,7 @@ final class TextAttributesConverter {
         } else {
             rtfAttr.set("b", 0);
         }
-        
+
         if (font.getFontStyle() == Constants.EN_ITALIC) {
             rtfAttr.set(RtfText.ATTR_ITALIC, 1);
         } else {
@@ -176,20 +308,20 @@ final class TextAttributesConverter {
 
 
 
-    private static void attrTextDecoration(CommonTextDecoration textDecoration, 
+    private static void attrTextDecoration(CommonTextDecoration textDecoration,
                 RtfAttributes rtfAttr) {
         if (textDecoration == null) {
             rtfAttr.set(RtfText.ATTR_UNDERLINE, 0);
             rtfAttr.set(RtfText.ATTR_STRIKETHROUGH, 0);
             return;
         }
-                
+
         if (textDecoration.hasUnderline()) {
             rtfAttr.set(RtfText.ATTR_UNDERLINE, 1);
         } else {
             rtfAttr.set(RtfText.ATTR_UNDERLINE, 0);
         }
-        
+
         if (textDecoration.hasLineThrough()) {
             rtfAttr.set(RtfText.ATTR_STRIKETHROUGH, 1);
         } else {
@@ -198,9 +330,9 @@ final class TextAttributesConverter {
     }
 
     private static void attrBlockMargin(CommonMarginBlock cmb, FOPRtfAttributes rtfAttr) {
-        rtfAttr.setTwips(RtfText.SPACE_BEFORE, 
+        rtfAttr.setTwips(RtfText.SPACE_BEFORE,
                 cmb.spaceBefore.getOptimum(null).getLength());
-        rtfAttr.setTwips(RtfText.SPACE_AFTER, 
+        rtfAttr.setTwips(RtfText.SPACE_AFTER,
                 cmb.spaceAfter.getOptimum(null).getLength());
         rtfAttr.setTwips(RtfText.LEFT_INDENT_BODY, cmb.startIndent);
         rtfAttr.setTwips(RtfText.RIGHT_INDENT_BODY, cmb.endIndent);
@@ -283,20 +415,20 @@ final class TextAttributesConverter {
             CommonBorderPaddingBackground commonBorderPaddingBackground = null;
             if (node instanceof Block) {
                 Block block = (Block) node;
-                commonBorderPaddingBackground = block.getCommonBorderPaddingBackground(); 
-            } else if (node instanceof BlockContainer) { 
+                commonBorderPaddingBackground = block.getCommonBorderPaddingBackground();
+            } else if (node instanceof BlockContainer) {
                 BlockContainer container = (BlockContainer) node;
                 commonBorderPaddingBackground = container.getCommonBorderPaddingBackground();
-            } 
+            }
 
-            if (commonBorderPaddingBackground != null 
+            if (commonBorderPaddingBackground != null
                     && commonBorderPaddingBackground.hasBorder()) {
                 return true;
             }
 
             node = node.getParent();
         }
-        return false; 
+        return false;
     }
 
     /** Adds inline border information from <code>bpb</code> to <code>rtrAttr</code>. */
@@ -313,7 +445,7 @@ final class TextAttributesConverter {
      * @param bl the Block object the properties are read from
      * @param rtfAttr the RtfAttributes object the attributes are written to
      */
-    private static void attrBackgroundColor(CommonBorderPaddingBackground bpb, 
+    private static void attrBackgroundColor(CommonBorderPaddingBackground bpb,
                 RtfAttributes rtfAttr) {
         Color fopValue = bpb.backgroundColor;
         int rtfColor = 0;
@@ -334,11 +466,11 @@ final class TextAttributesConverter {
 
         rtfAttr.set(RtfText.ATTR_BACKGROUND_COLOR, rtfColor);
    }
-    
+
    private static void attrBaseLineShift(Length baselineShift, RtfAttributes rtfAttr) {
-       
+
        int s = baselineShift.getEnum();
-       
+
        if (s == Constants.EN_SUPER) {
            rtfAttr.set(RtfText.ATTR_SUPERSCRIPT);
        } else if (s == Constants.EN_SUB) {
diff --git a/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLeader.java b/src/java/org/apache/fop/render/rtf/rtflib/rtfdoc/RtfLeader.java
new file mode 100644 (file)
index 0000000..b3f11bc
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * 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.render.rtf.rtflib.rtfdoc;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Iterator;
+
+/**
+ * Generates the leader in RTF.
+ */
+public class RtfLeader extends RtfContainer {
+
+    /*
+     * Format : \tqr \style \tx## { \pard \format \tab }
+     *  ## represents the width \style represents the style (tldot, tlth, ...)
+     * \format represents standard formats (color, fontsize, ...)
+     *
+     *
+     * \pard \zwnj {\fsxx <format> } \zwnj
+     *
+     * <format>: \\ulcN Underline color. \\uld Dotted underline. \\uldash Dashed
+     * underline. \\uldashd Dash-dotted underline. \\uldashdd Dash-dot-dotted
+     * underline. \\uldb Double underline. \\ulhwave Heavy wave underline.
+     * \\ulldash Long dashed underline. \\ulnone Stops all underlining. \\ulth
+     * Thick underline. \\ulthd Thick dotted underline. \\ulthdash Thick dashed
+     * underline. \\ulthdashd Thick dash-dotted underline. \\ulthdashdd Thick
+     * dash-dot-dotted underline. \\ulthldash Thick long dashed underline.
+     * \\ululdbwave Double wave underline.
+     */
+
+    private RtfAttributes attrs = null;
+
+    /** Private attribute: tab style */
+    public static final String LEADER_TABLEAD = "tablead";
+
+    /** Private attribute: tab usage indicator */
+    public static final String LEADER_USETAB = "tabuse";
+
+    /** Private attribute: leader width */
+    public static final String LEADER_WIDTH = "lwidth";
+
+    // +++++++++++++++ Styles Underline ++++++++++++++++++++++
+
+    /** Dotted underline */
+    public static final String LEADER_DOTTED = "uld"; // dotted
+
+    /** Dashed underline */
+    public static final String LEADER_MIDDLEDOTTED = "uldash"; // dashed
+
+    /** Heavy wave underline */
+    public static final String LEADER_HYPHENS = "ulhwave"; // groove
+
+    /** Dash-dot-dotted underline */
+    public static final String LEADER_UNDERLINE = "ulthdashdd"; // ridge
+
+    /** Double underline */
+    public static final String LEADER_EQUAL = "uldb"; // double
+
+    /** Thick underline */
+    public static final String LEADER_THICK = "ulth"; // solid
+
+    // +++++++++++++++ Styles Tabulator +++++++++++++++++++++++
+
+    /** Leader dots */
+    public static final String LEADER_TAB_DOTTED = "tldot"; // dotted
+
+    /** Leader middle dots */
+    public static final String LEADER_TAB_MIDDLEDOTTED = "tlmdot"; // dashed
+
+    /** Leader hyphens */
+    public static final String LEADER_TAB_HYPHENS = "tlhyph"; // groove
+
+    /** Leader underline */
+    public static final String LEADER_TAB_UNDERLINE = "tlul"; // ridge
+
+    /** Leader equal sign */
+    public static final String LEADER_TAB_EQUAL = "tleq"; // double
+
+    /** Leader thick line */
+    public static final String LEADER_TAB_THICK = "tlth"; // solid
+
+    // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+    /** Resets to default properties */
+    public static final String LEADER_IGNORE_STYLE = "pard";
+
+    /** Font size determines rule thickness */
+    public static final String LEADER_RULE_THICKNESS = "fs"; // thickness = fontsize
+
+    /** Expansion or compression of the space between characters in twips */
+    public static final String LEADER_PATTERN_WIDTH = "expndtw";
+
+    /** Zero-width break opportunity */
+    public static final String LEADER_ZERO_WIDTH = "zwbo";
+
+    /** Standard leader width */
+    public static final int LEADER_STANDARD_WIDTH = 30;
+
+    /** Move up 4 half-points */
+    public static final String LEADER_UP = "up4";
+
+    /** Negative expansion */
+    public static final String LEADER_EXPAND = "expnd-2"; // negative value
+                                                            // for compression
+
+    /** Tab */
+    public static final String LEADER_TAB_VALUE = "tab";
+
+    /** Right-aligned tab */
+    public static final String LEADER_TAB_RIGHT = "tqr";
+
+    /** Tab width */
+    public static final String LEADER_TAB_WIDTH = "tx";
+
+    RtfLeader(RtfContainer parent, Writer w, RtfAttributes attrs) throws IOException {
+        super(parent, w);
+        this.attrs = attrs;
+    }
+
+    /** {@inheritDoc} */
+    protected void writeRtfContent() throws IOException {
+
+        int thickness = LEADER_STANDARD_WIDTH;
+        String tablead = null;
+        String tabwidth = null;
+        for (Iterator it = attrs.nameIterator(); it.hasNext();) {
+            final String name = (String)it.next();
+            if (attrs.isSet(name)) {
+                if (name.equals(LEADER_TABLEAD)) {
+                    tablead = attrs.getValue(LEADER_TABLEAD).toString();
+                } else if (name.equals(LEADER_WIDTH)) {
+                    tabwidth = attrs.getValue(LEADER_WIDTH).toString();
+                }
+            }
+        }
+
+        if (attrs.getValue(LEADER_RULE_THICKNESS) != null) {
+            thickness += Integer.parseInt(attrs.getValue(LEADER_RULE_THICKNESS).toString())
+                            / 1000 * 2;
+            attrs.unset(LEADER_RULE_THICKNESS);
+        }
+
+        //Remove private attributes
+        attrs.unset(LEADER_WIDTH);
+        attrs.unset(LEADER_TABLEAD);
+
+        // If leader is 100% we use a tabulator, because its more
+        // comfortable, specially for the table of content
+        if (attrs.getValue(LEADER_USETAB) != null) {
+            attrs.unset(LEADER_USETAB);
+            writeControlWord(LEADER_TAB_RIGHT);
+
+            if (tablead != null) {
+                writeControlWord(tablead);
+            }
+            writeControlWord(LEADER_TAB_WIDTH + tabwidth);
+
+            writeGroupMark(true);
+
+            writeControlWord(LEADER_IGNORE_STYLE);
+            writeAttributes(attrs, null);
+            writeControlWord(LEADER_EXPAND);
+            writeControlWord(LEADER_TAB_VALUE);
+
+            writeGroupMark(false);
+
+        }
+        // Using white spaces with different underline formats
+        else {
+            writeControlWord(LEADER_IGNORE_STYLE);
+            writeControlWord(LEADER_ZERO_WIDTH);
+            writeGroupMark(true);
+
+            writeControlWord(LEADER_RULE_THICKNESS + thickness);
+
+            writeControlWord(LEADER_UP);
+
+            super.writeAttributes(attrs, null);
+            if (tablead != null) {
+                writeControlWord(tablead);
+            }
+
+            // Calculation for the necessary amount of white spaces
+            // Depending on font-size 15 -> 1cm = 7,5 spaces
+            // TODO for rule-thickness this has to be done better
+
+            for (double d = (Integer.parseInt(tabwidth) / 560) * 7.5; d >= 1; d--) {
+                RtfStringConverter.getInstance().writeRtfString(writer, " ");
+            }
+
+            writeGroupMark(false);
+            writeControlWord(LEADER_ZERO_WIDTH);
+        }
+    }
+
+    /** {@inheritDoc} */
+    public boolean isEmpty() {
+        return false;
+    }
+
+}
index b0db4576b489b439826ea02e2401462b42d3a857..49148c40736a8f25272480bb4c903580d396fd2a 100644 (file)
@@ -248,6 +248,15 @@ public class RtfTextrun extends RtfContainer {
         }
     }
 
+    /**
+     * Inserts a leader.
+     * @param attrs Attributes for the leader
+     * @throws IOException for I/O problems
+     */
+    public void addLeader(RtfAttributes attrs) throws IOException {
+        new RtfLeader(this, writer, attrs);
+    }
+
     /**
      * Inserts a page number.
      * @param attr Attributes for the page number to insert.
index 5367daf3fb924b43747d5ea76549b89d1d3a6b50..752e2f1cad6fdaf19fec62eef4e5d21920aea4d1 100644 (file)
       -->
     <!--/release-->
     <release version="0.95" date="TBD">
+      <action context="Renderers" dev="JM" type="add" fixes-bug="43825" due-to="Maximilian Aster">
+        Added support for fo:leader for RTF output (no full support!). Fixes problems with empty leaders
+        being used to force empty lines among other issues.
+      </action>
       <action context="Renderers" dev="JM" type="add" fixes-bug="43824" due-to="Maximilian Aster">
         Added support for page-number-citation for RTF output.
       </action>