123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354 |
- /* ====================================================================
- 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.
- ==================================================================== */
-
- package org.apache.poi.hssf.usermodel;
-
-
- /**
- * Common class for {@link HSSFHeader} and {@link HSSFFooter}.
- */
- public abstract class HeaderFooter implements org.apache.poi.ss.usermodel.HeaderFooter {
-
- protected HeaderFooter() {
- //
- }
-
- /**
- * @return the internal text representation (combining center, left and right parts).
- * Possibly empty string if no header or footer is set. Never <code>null</code>.
- */
- protected abstract String getRawText();
-
- private String[] splitParts() {
- String text = getRawText();
- // default values
- String _left = "";
- String _center = "";
- String _right = "";
-
- // FIXME: replace outer goto. just eww.
- // no unit tests test the goto loop but poi-integration tests hangs if you remove it
- // (some file has an edge case header or footer)
- outer:
- while (text.length() > 1) {
- if (text.charAt(0) != '&') {
- // Mimics the behaviour of Excel, which would put it in the center.
- _center = text;
- break;
- }
- int pos = text.length();
- switch (text.charAt(1)) {
- case 'L':
- if (text.contains("&C")) {
- pos = Math.min(pos, text.indexOf("&C"));
- }
- if (text.contains("&R")) {
- pos = Math.min(pos, text.indexOf("&R"));
- }
- _left = text.substring(2, pos);
- text = text.substring(pos);
- break;
- case 'C':
- if (text.contains("&L")) {
- pos = Math.min(pos, text.indexOf("&L"));
- }
- if (text.contains("&R")) {
- pos = Math.min(pos, text.indexOf("&R"));
- }
- _center = text.substring(2, pos);
- text = text.substring(pos);
- break;
- case 'R':
- if (text.contains("&C")) {
- pos = Math.min(pos, text.indexOf("&C"));
- }
- if (text.contains("&L")) {
- pos = Math.min(pos, text.indexOf("&L"));
- }
- _right = text.substring(2, pos);
- text = text.substring(pos);
- break;
- default:
- // Mimics the behaviour of Excel, which would put it in the center.
- _center = text;
- break outer;
- }
- }
- return new String[] { _left, _center, _right, };
- }
-
- /**
- * @return the left side of the header or footer.
- */
- public final String getLeft() {
- return splitParts()[0];
- }
-
- /**
- * @param newLeft The string to set as the left side.
- */
- public final void setLeft(String newLeft) {
- updatePart(0, newLeft);
- }
-
- /**
- * @return the center of the header or footer.
- */
- public final String getCenter() {
- return splitParts()[1];
- }
-
- /**
- * @param newCenter The string to set as the center.
- */
- public final void setCenter(String newCenter) {
- updatePart(1, newCenter);
- }
-
- /**
- * @return The right side of the header or footer.
- */
- public final String getRight() {
- return splitParts()[2];
- }
-
- /**
- * @param newRight The string to set as the right side.
- */
- public final void setRight(String newRight) {
- updatePart(2, newRight);
- }
-
- private void updatePart(int partIndex, String newValue) {
- String[] parts = splitParts();
- parts[partIndex] = newValue == null ? "" : newValue;
- updateHeaderFooterText(parts);
- }
- /**
- * Creates the complete footer string based on the left, center, and middle
- * strings.
- */
- private void updateHeaderFooterText(String[] parts) {
- String _left = parts[0];
- String _center = parts[1];
- String _right = parts[2];
-
- if (_center.length() < 1 && _left.length() < 1 && _right.length() < 1) {
- setHeaderFooterText("");
- return;
- }
- StringBuilder sb = new StringBuilder(64);
- sb.append("&C");
- sb.append(_center);
- sb.append("&L");
- sb.append(_left);
- sb.append("&R");
- sb.append(_right);
- String text = sb.toString();
- setHeaderFooterText(text);
- }
-
- /**
- * @param text the new header footer text (contains mark-up tags). Possibly
- * empty string never <code>null</code>
- */
- protected abstract void setHeaderFooterText(String text);
-
- /**
- * @param size
- * the new font size
- * @return The mark-up tag representing a new font size
- */
- public static String fontSize(short size) {
- return "&" + size;
- }
-
- /**
- * @param font
- * the new font
- * @param style
- * the fonts style, one of regular, italic, bold, italic bold or
- * bold italic
- * @return The mark-up tag representing a new font size
- */
- public static String font(String font, String style) {
- return "&\"" + font + "," + style + "\"";
- }
-
- /**
- * @return The mark-up tag representing the current page number
- */
- public static String page() {
- return MarkupTag.PAGE_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag representing the number of pages
- */
- public static String numPages() {
- return MarkupTag.NUM_PAGES_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag representing the current date date
- */
- public static String date() {
- return MarkupTag.DATE_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag representing current time
- */
- public static String time() {
- return MarkupTag.TIME_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag representing the current file name
- */
- public static String file() {
- return MarkupTag.FILE_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag representing the current tab (sheet) name
- */
- public static String tab() {
- return MarkupTag.SHEET_NAME_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag for start bold
- */
- public static String startBold() {
- return MarkupTag.BOLD_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag for end bold
- */
- public static String endBold() {
- return MarkupTag.BOLD_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag for start underline
- */
- public static String startUnderline() {
- return MarkupTag.UNDERLINE_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag for end underline
- */
- public static String endUnderline() {
- return MarkupTag.UNDERLINE_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag for start double underline
- */
- public static String startDoubleUnderline() {
- return MarkupTag.DOUBLE_UNDERLINE_FIELD.getRepresentation();
- }
-
- /**
- * @return The mark-up tag for end double underline
- */
- public static String endDoubleUnderline() {
- return MarkupTag.DOUBLE_UNDERLINE_FIELD.getRepresentation();
- }
-
- /**
- * Removes any fields (eg macros, page markers etc) from the string.
- * Normally used to make some text suitable for showing to humans, and the
- * resultant text should not normally be saved back into the document!
- */
- public static String stripFields(String pText) {
- int pos;
-
- // Check we really got something to work on
- if (pText == null || pText.length() == 0) {
- return pText;
- }
-
- String text = pText;
-
- // Firstly, do the easy ones which are static
- for (MarkupTag mt : MarkupTag.values()) {
- String seq = mt.getRepresentation();
- while ((pos = text.indexOf(seq)) >= 0) {
- text = text.substring(0, pos) + text.substring(pos + seq.length());
- }
- }
-
- // Now do the tricky, dynamic ones
- // These are things like font sizes, font names and colours
- text = text.replaceAll("&\\d+", "");
- text = text.replaceAll("&\".*?,.*?\"", "");
- text = text.replaceAll("&K[\\dA-F]{6}", "");
- text = text.replaceAll("&K[\\d]{2}[+][\\d]{3}", "");
-
- text = text.replaceAll("&&", "&");
-
-
- // All done
- return text;
- }
-
- private enum MarkupTag {
- SHEET_NAME_FIELD ("&A", false),
- DATE_FIELD ("&D", false),
- FILE_FIELD ("&F", false),
- FULL_FILE_FIELD ("&Z", false),
- PAGE_FIELD ("&P", false),
- TIME_FIELD ("&T", false),
- NUM_PAGES_FIELD ("&N", false),
-
- PICTURE_FIELD ("&G", false),
-
- BOLD_FIELD ("&B", true),
- ITALIC_FIELD ("&I", true),
- STRIKETHROUGH_FIELD ("&S", true),
- SUBSCRIPT_FIELD ("&Y", true),
- SUPERSCRIPT_FIELD ("&X", true),
- UNDERLINE_FIELD ("&U", true),
- DOUBLE_UNDERLINE_FIELD ("&E", true),
- ;
-
- private final String _representation;
- private final boolean _occursInPairs;
- private MarkupTag(String sequence, boolean occursInPairs) {
- _representation = sequence;
- _occursInPairs = occursInPairs;
- }
- /**
- * @return The character sequence that marks this field
- */
- public String getRepresentation() {
- return _representation;
- }
-
- /**
- * @return true if this markup tag normally comes in a pair, eg turn on
- * underline / turn off underline
- */
- public boolean occursPairs() {
- return _occursInPairs;
- }
- }
- }
|