001: /* ====================================================================
002: Licensed to the Apache Software Foundation (ASF) under one or more
003: contributor license agreements. See the NOTICE file distributed with
004: this work for additional information regarding copyright ownership.
005: The ASF licenses this file to You under the Apache License, Version 2.0
006: (the "License"); you may not use this file except in compliance with
007: the License. You may obtain a copy of the License at
008:
009: http://www.apache.org/licenses/LICENSE-2.0
010:
011: Unless required by applicable law or agreed to in writing, software
012: distributed under the License is distributed on an "AS IS" BASIS,
013: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: See the License for the specific language governing permissions and
015: limitations under the License.
016: ==================================================================== */
017:
018: package org.apache.poi.hwpf.model;
019:
020: import java.util.List;
021: import java.util.ArrayList;
022: import java.io.OutputStream;
023: import java.io.IOException;
024:
025: import org.apache.poi.poifs.common.POIFSConstants;
026: import org.apache.poi.util.LittleEndian;
027: import org.apache.poi.hwpf.model.io.*;
028: import org.apache.poi.hwpf.sprm.SprmBuffer;
029:
030: /**
031: * This class holds all of the character formatting properties.
032: *
033: * @author Ryan Ackley
034: */
035: public class CHPBinTable {
036: /** List of character properties.*/
037: protected ArrayList _textRuns = new ArrayList();
038:
039: public CHPBinTable() {
040: }
041:
042: /**
043: * Constructor used to read a binTable in from a Word document.
044: *
045: * @param documentStream
046: * @param tableStream
047: * @param offset
048: * @param size
049: * @param fcMin
050: */
051: public CHPBinTable(byte[] documentStream, byte[] tableStream,
052: int offset, int size, int fcMin) {
053: PlexOfCps binTable = new PlexOfCps(tableStream, offset, size, 4);
054:
055: int length = binTable.length();
056: for (int x = 0; x < length; x++) {
057: GenericPropertyNode node = binTable.getProperty(x);
058:
059: int pageNum = LittleEndian.getInt(node.getBytes());
060: int pageOffset = POIFSConstants.BIG_BLOCK_SIZE * pageNum;
061:
062: CHPFormattedDiskPage cfkp = new CHPFormattedDiskPage(
063: documentStream, pageOffset, fcMin);
064:
065: int fkpSize = cfkp.size();
066:
067: for (int y = 0; y < fkpSize; y++) {
068: _textRuns.add(cfkp.getCHPX(y));
069: }
070: }
071: }
072:
073: public void adjustForDelete(int listIndex, int offset, int length) {
074: int size = _textRuns.size();
075: int endMark = offset + length;
076: int endIndex = listIndex;
077:
078: CHPX chpx = (CHPX) _textRuns.get(endIndex);
079: while (chpx.getEnd() < endMark) {
080: chpx = (CHPX) _textRuns.get(++endIndex);
081: }
082: if (listIndex == endIndex) {
083: chpx = (CHPX) _textRuns.get(endIndex);
084: chpx.setEnd((chpx.getEnd() - endMark) + offset);
085: } else {
086: chpx = (CHPX) _textRuns.get(listIndex);
087: chpx.setEnd(offset);
088: for (int x = listIndex + 1; x < endIndex; x++) {
089: chpx = (CHPX) _textRuns.get(x);
090: chpx.setStart(offset);
091: chpx.setEnd(offset);
092: }
093: chpx = (CHPX) _textRuns.get(endIndex);
094: chpx.setEnd((chpx.getEnd() - endMark) + offset);
095: }
096:
097: for (int x = endIndex + 1; x < size; x++) {
098: chpx = (CHPX) _textRuns.get(x);
099: chpx.setStart(chpx.getStart() - length);
100: chpx.setEnd(chpx.getEnd() - length);
101: }
102: }
103:
104: public void insert(int listIndex, int cpStart, SprmBuffer buf) {
105: CHPX insertChpx = new CHPX(cpStart, cpStart, buf);
106: if (listIndex == _textRuns.size()) {
107: _textRuns.add(insertChpx);
108: } else {
109: CHPX chpx = (CHPX) _textRuns.get(listIndex);
110: if (chpx.getStart() < cpStart) {
111: CHPX clone = new CHPX(cpStart, chpx.getEnd(), chpx
112: .getSprmBuf());
113: chpx.setEnd(cpStart);
114:
115: _textRuns.add(listIndex + 1, insertChpx);
116: _textRuns.add(listIndex + 2, clone);
117: } else {
118: _textRuns.add(listIndex, insertChpx);
119: }
120: }
121: }
122:
123: public void adjustForInsert(int listIndex, int length) {
124: int size = _textRuns.size();
125: CHPX chpx = (CHPX) _textRuns.get(listIndex);
126: chpx.setEnd(chpx.getEnd() + length);
127:
128: for (int x = listIndex + 1; x < size; x++) {
129: chpx = (CHPX) _textRuns.get(x);
130: chpx.setStart(chpx.getStart() + length);
131: chpx.setEnd(chpx.getEnd() + length);
132: }
133: }
134:
135: public List getTextRuns() {
136: return _textRuns;
137: }
138:
139: public void writeTo(HWPFFileSystem sys, int fcMin)
140: throws IOException {
141:
142: HWPFOutputStream docStream = sys.getStream("WordDocument");
143: OutputStream tableStream = sys.getStream("1Table");
144:
145: PlexOfCps binTable = new PlexOfCps(4);
146:
147: // each FKP must start on a 512 byte page.
148: int docOffset = docStream.getOffset();
149: int mod = docOffset % POIFSConstants.BIG_BLOCK_SIZE;
150: if (mod != 0) {
151: byte[] padding = new byte[POIFSConstants.BIG_BLOCK_SIZE
152: - mod];
153: docStream.write(padding);
154: }
155:
156: // get the page number for the first fkp
157: docOffset = docStream.getOffset();
158: int pageNum = docOffset / POIFSConstants.BIG_BLOCK_SIZE;
159:
160: // get the ending fc
161: int endingFc = ((PropertyNode) _textRuns
162: .get(_textRuns.size() - 1)).getEnd();
163: endingFc += fcMin;
164:
165: ArrayList overflow = _textRuns;
166: do {
167: PropertyNode startingProp = (PropertyNode) overflow.get(0);
168: int start = startingProp.getStart() + fcMin;
169:
170: CHPFormattedDiskPage cfkp = new CHPFormattedDiskPage();
171: cfkp.fill(overflow);
172:
173: byte[] bufFkp = cfkp.toByteArray(fcMin);
174: docStream.write(bufFkp);
175: overflow = cfkp.getOverflow();
176:
177: int end = endingFc;
178: if (overflow != null) {
179: end = ((PropertyNode) overflow.get(0)).getStart()
180: + fcMin;
181: }
182:
183: byte[] intHolder = new byte[4];
184: LittleEndian.putInt(intHolder, pageNum++);
185: binTable.addProperty(new GenericPropertyNode(start, end,
186: intHolder));
187:
188: } while (overflow != null);
189: tableStream.write(binTable.toByteArray());
190: }
191:
192: }
|