📄 calloutemitter.java
字号:
try { rtfEmitter.characters(chars, 0, numBlanks); } catch (TransformerException e) { System.out.println("Transformer Exception in formatPad"); } } /** * <p>Add a callout to the global callout array</p> * * <p>This method examines a callout <tt>area</tt> and adds it to * the global callout array if it can be interpreted.</p> * * <p>Only the <tt>linecolumn</tt> and <tt>linerange</tt> units are * supported. If no unit is specifed, <tt>linecolumn</tt> is assumed. * If only a line is specified, the callout decoration appears in * the <tt>defaultColumn</tt>.</p> * * @param coNum The callout number. * @param node The <tt>area</tt>. * @param defaultColumn The default column for callouts. */ protected void addCallout (int coNum, Node node, int defaultColumn) { Element area = (Element) node; String units = null; String coords = null; if (area.hasAttribute("units")) { units = area.getAttribute("units"); } if (area.hasAttribute("coords")) { coords = area.getAttribute("coords"); } if (units != null && !units.equalsIgnoreCase("linecolumn") && !units.equalsIgnoreCase("linerange")) { System.out.println("Only linecolumn and linerange units are supported"); return; } if (coords == null) { System.out.println("Coords must be specified"); return; } // Now let's see if we can interpret the coordinates... StringTokenizer st = new StringTokenizer(coords); int tokenCount = 0; int c1 = 0; int c2 = 0; while (st.hasMoreTokens()) { tokenCount++; if (tokenCount > 2) { System.out.println("Unparseable coordinates"); return; } try { String token = st.nextToken(); int coord = Integer.parseInt(token); c2 = coord; if (tokenCount == 1) { c1 = coord; } } catch (NumberFormatException e) { System.out.println("Unparseable coordinate"); return; } } // Make sure we aren't going to blow past the end of our array if (calloutCount == callout.length) { Callout bigger[] = new Callout[calloutCount+10]; for (int count = 0; count < callout.length; count++) { bigger[count] = callout[count]; } callout = bigger; } // Ok, add the callout if (tokenCount == 2) { if (units != null && units.equalsIgnoreCase("linerange")) { for (int count = c1; count <= c2; count++) { callout[calloutCount++] = new Callout(coNum, area, count, defaultColumn); } } else { // assume linecolumn callout[calloutCount++] = new Callout(coNum, area, c1, c2); } } else { // if there's only one number, assume it's the line callout[calloutCount++] = new Callout(coNum, area, c1, defaultColumn); } } /** Process end element events. */ public void endElement(int nameCode) throws TransformerException { if (!elementStack.empty()) { // if we didn't push the very first element (an fo:block or // pre or div surrounding the whole block), then the stack will // be empty when we get to the end of the first element... elementStack.pop(); } rtfEmitter.endElement(nameCode); } /** Process start element events. */ public void startElement(int nameCode, org.xml.sax.Attributes attributes, int[] namespaces, int nscount) throws TransformerException { if (!skipThisElement(nameCode)) { StartElementInfo sei = new StartElementInfo(nameCode, attributes, namespaces, nscount); elementStack.push(sei); } firstElement = false; rtfEmitter.startElement(nameCode, attributes, namespaces, nscount); } /** * <p>Protect the outer-most block wrapper.</p> * * <p>Open elements in the result tree fragment are closed and reopened * around callouts (so that callouts don't appear inside links or other * environments). But if the result tree fragment is a single block * (a div or pre in HTML, an fo:block in FO), that outer-most block is * treated specially.</p> * * <p>This method returns true if the element in question is that * outermost block.</p> * * @param nameCode The name code for the element * * @return True if the element is the outer-most block, false otherwise. */ protected boolean skipThisElement(int nameCode) { // FIXME: This is such a gross hack... if (firstElement) { int thisFingerprint = namePool.getFingerprint(nameCode); int foBlockFingerprint = namePool.getFingerprint(foURI, "block"); int htmlPreFingerprint = namePool.getFingerprint("", "pre"); int htmlDivFingerprint = namePool.getFingerprint("", "div"); int xhtmlPreFingerprint = namePool.getFingerprint(xhURI, "pre"); int xhtmlDivFingerprint = namePool.getFingerprint(xhURI, "div"); if ((foStylesheet && thisFingerprint == foBlockFingerprint) || (!foStylesheet && (thisFingerprint == htmlPreFingerprint || thisFingerprint == htmlDivFingerprint || thisFingerprint == xhtmlPreFingerprint || thisFingerprint == xhtmlDivFingerprint))) { // Don't push the outer-most wrapping div, pre, or fo:block return true; } } return false; } private void closeOpenElements(Emitter rtfEmitter) throws TransformerException { // Close all the open elements... tempStack = new Stack(); while (!elementStack.empty()) { StartElementInfo elem = (StartElementInfo) elementStack.pop(); rtfEmitter.endElement(elem.getNameCode()); tempStack.push(elem); } } private void openClosedElements(Emitter rtfEmitter) throws TransformerException { // Now "reopen" the elements that we closed... while (!tempStack.empty()) { StartElementInfo elem = (StartElementInfo) tempStack.pop(); AttributeCollection attr = (AttributeCollection) elem.getAttributes(); AttributeCollection newAttr = new AttributeCollection(namePool); for (int acount = 0; acount < attr.getLength(); acount++) { String localName = attr.getLocalName(acount); int nameCode = attr.getNameCode(acount); String type = attr.getType(acount); String value = attr.getValue(acount); String uri = attr.getURI(acount); String prefix = ""; if (localName.indexOf(':') > 0) { prefix = localName.substring(0, localName.indexOf(':')); localName = localName.substring(localName.indexOf(':')+1); } if (uri.equals("") && ((foStylesheet && localName.equals("id")) || (!foStylesheet && (localName.equals("id") || localName.equals("name"))))) { // skip this attribute } else { newAttr.addAttribute(prefix, uri, localName, type, value); } } rtfEmitter.startElement(elem.getNameCode(), newAttr, elem.getNamespaces(), elem.getNSCount()); elementStack.push(elem); } } /** * <p>A private class for maintaining the information required to call * the startElement method.</p> * * <p>In order to close and reopen elements, information about those * elements has to be maintained. This class is just the little record * that we push on the stack to keep track of that info.</p> */ private class StartElementInfo { private int _nameCode; org.xml.sax.Attributes _attributes; int[] _namespaces; int _nscount; public StartElementInfo(int nameCode, org.xml.sax.Attributes attributes, int[] namespaces, int nscount) { _nameCode = nameCode; _attributes = attributes; _namespaces = namespaces; _nscount = nscount; } public int getNameCode() { return _nameCode; } public org.xml.sax.Attributes getAttributes() { return _attributes; } public int[] getNamespaces() { return _namespaces; } public int getNSCount() { return _nscount; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -