/************************************************************************ * * BlockConverter.java * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * Copyright: 2002-2009 by Henrik Just * * All Rights Reserved. * * Version 1.2 (2009-04-30) * */ package writer2latex.latex; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import writer2latex.latex.util.BeforeAfter; import writer2latex.latex.util.Context; //import writer2latex.latex.util.HeadingMap; import writer2latex.latex.util.StyleMap; import writer2latex.office.ListStyle; import writer2latex.office.OfficeReader; //import writer2latex.office.TableReader; import writer2latex.office.XMLString; import writer2latex.util.Misc; /** *

This class handles basic block content, including the main text body, * sections, tables, lists, headings and paragraphs.

*/ public class BlockConverter extends ConverterHelper { public BlockConverter(OfficeReader ofr, LaTeXConfig config, ConverterPalette palette) { super(ofr,config,palette); } public void appendDeclarations(LaTeXDocumentPortion pack, LaTeXDocumentPortion decl) { // currently do nothing.. } /**

Traverse block text (eg. content of body, section, list item). * This is traversed in logical order and dedicated handlers take care of * each block element.

*

(Note: As a rule, all handling of block level elements should add a * newline to the LaTeX document at the end of the block)

* @param node The element containing the block text * @param ldp the LaTeXDocumentPortion to which * LaTeX code should be added * @param oc the current context */ public void traverseBlockText(Element node, LaTeXDocumentPortion ldp, Context oc) { Context ic = (Context) oc.clone(); // The current paragraph block: StyleMap blockMap = config.getParBlockStyleMap(); String sBlockName = null; if (node.hasChildNodes()) { NodeList list = node.getChildNodes(); int nLen = list.getLength(); for (int i = 0; i < nLen; i++) { Node childNode = list.item(i); if (childNode.getNodeType() == Node.ELEMENT_NODE) { Element child = (Element)childNode; String sTagName = child.getTagName(); // Start/End a paragraph block (not in tables) if (!ic.isInTable()) { if (sTagName.equals(XMLString.TEXT_P)) { String sStyleName = ofr.getParStyles().getDisplayName(child.getAttribute(XMLString.TEXT_STYLE_NAME)); if (sBlockName!=null && !blockMap.isNext(sBlockName,sStyleName)) { // end current block String sAfter = blockMap.getAfter(sBlockName); if (sAfter.length()>0) ldp.append(sAfter).nl(); sBlockName = null; ic.setVerbatim(false); } if (sBlockName==null && blockMap.contains(sStyleName)) { // start a new block sBlockName = sStyleName; String sBefore = blockMap.getBefore(sBlockName); if (sBefore.length()>0) ldp.append(sBefore).nl(); ic.setVerbatim(blockMap.getVerbatim(sStyleName)); } } else if (sBlockName!=null) { // non-paragraph: end current block String sAfter = blockMap.getAfter(sBlockName); if (sAfter.length()>0) ldp.append(sAfter).nl(); sBlockName = null; ic.setVerbatim(false); } } palette.getFieldCv().flushReferenceMarks(ldp,ic); palette.getIndexCv().flushIndexMarks(ldp,ic); palette.getInfo().addDebugInfo(child,ldp); // Basic block content; handle by this class if (sTagName.equals(XMLString.TEXT_P)) { // is this a caption? String sSequence = ofr.getSequenceName(child); if (ofr.isFigureSequenceName(sSequence)) { palette.getDrawCv().handleCaption(child,ldp,ic); } else if (ofr.isTableSequenceName(sSequence)) { // Next node *should* be a table if (i+10) ldp.append(sAfter).nl(); sBlockName = null; } palette.getFieldCv().flushReferenceMarks(ldp,ic); palette.getIndexCv().flushIndexMarks(ldp,ic); } /**

Process a list (text:ordered-lst or text:unordered-list tag)

* @param node The element containing the list * @param ldp the LaTeXDocumentPortion to which * LaTeX code should be added * @param oc the current context */ public void handleList(Element node, LaTeXDocumentPortion ldp, Context oc) { // Set up new context Context ic = (Context) oc.clone(); ic.incListLevel(); if ("true".equals(node.getAttribute(XMLString.TEXT_CONTINUE_NUMBERING))) { ic.setInContinuedList(true); } // Get the style name, if we don't know it already if (ic.getListStyleName()==null) { ic.setListStyleName(node.getAttribute(XMLString.TEXT_STYLE_NAME)); } // Use the style to determine the type of list ListStyle style = ofr.getListStyle(ic.getListStyleName()); boolean bOrdered = style!=null && style.isNumber(ic.getListLevel()); // If the list contains headings, ignore it! if (ic.isIgnoreLists() || listContainsHeadings(node)) { ic.setIgnoreLists(true); traverseList(node,ldp,ic); return; } // Apply the style BeforeAfter ba = new BeforeAfter(); palette.getListSc().applyListStyle(bOrdered,ba,ic); // Export the list if (ba.getBefore().length()>0) { ldp.append(ba.getBefore()).nl(); } traverseList(node,ldp,ic); if (ba.getAfter().length()>0) { ldp.append(ba.getAfter()).nl(); } } /* * Process the contents of a list */ private void traverseList (Element node, LaTeXDocumentPortion ldp, Context oc) { if (node.hasChildNodes()) { NodeList list = node.getChildNodes(); int nLen = list.getLength(); for (int i = 0; i < nLen; i++) { Node child = list.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { String nodeName = child.getNodeName(); palette.getInfo().addDebugInfo((Element)child,ldp); if (nodeName.equals(XMLString.TEXT_LIST_ITEM)) { handleListItem((Element)child,ldp,oc); } if (nodeName.equals(XMLString.TEXT_LIST_HEADER)) { handleListItem((Element)child,ldp,oc); } } } } } private void handleListItem(Element node, LaTeXDocumentPortion ldp, Context oc) { // Are we ignoring this list? if (oc.isIgnoreLists()) { traverseBlockText(node,ldp,oc); return; } // Apply the style BeforeAfter ba = new BeforeAfter(); palette.getListSc().applyListItemStyle( oc.getListStyleName(), oc.getListLevel(), node.getNodeName().equals(XMLString.TEXT_LIST_HEADER), "true".equals(node.getAttribute(XMLString.TEXT_RESTART_NUMBERING)), Misc.getPosInteger(node.getAttribute(XMLString.TEXT_START_VALUE),1)-1, ba,oc); // export the list item (note the special treatment of lists in tables) if (ba.getBefore().length()>0) { ldp.append(ba.getBefore()); if (config.formatting()>=LaTeXConfig.CONVERT_MOST && !oc.isInTable()) { ldp.nl(); } } traverseBlockText(node,ldp,oc); if (ba.getAfter().length()>0 || oc.isInTable()) { ldp.append(ba.getAfter()).nl(); } } /* * Helper: Check to see, if this list contains headings * (in that case we will ignore the list!) */ private boolean listContainsHeadings (Node node) { if (node.hasChildNodes()) { NodeList nList = node.getChildNodes(); int len = nList.getLength(); for (int i = 0; i < len; i++) { Node child = nList.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { String nodeName = child.getNodeName(); if (nodeName.equals(XMLString.TEXT_LIST_ITEM)) { if (listItemContainsHeadings(child)) return true; } if (nodeName.equals(XMLString.TEXT_LIST_HEADER)) { if (listItemContainsHeadings(child)) return true; } } } } return false; } private boolean listItemContainsHeadings(Node node) { if (node.hasChildNodes()) { NodeList nList = node.getChildNodes(); int len = nList.getLength(); for (int i = 0; i < len; i++) { Node child = nList.item(i); if (child.getNodeType() == Node.ELEMENT_NODE) { String nodeName = child.getNodeName(); if(nodeName.equals(XMLString.TEXT_H)) { return true; } if (nodeName.equals(XMLString.TEXT_LIST)) { if (listContainsHeadings(child)) return true; } if (nodeName.equals(XMLString.TEXT_ORDERED_LIST)) { if (listContainsHeadings(child)) return true; } if (nodeName.equals(XMLString.TEXT_UNORDERED_LIST)) { if (listContainsHeadings(child)) return true; } } } } return false; } }