123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- /* ====================================================================
- Copyright 2002-2004 Apache Software Foundation
-
- Licensed 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.hwpf.model;
-
- import java.util.ArrayList;
- import java.io.ByteArrayOutputStream;
- import java.io.IOException;
- import java.util.List;
-
- import org.apache.poi.util.LittleEndian;
- import org.apache.poi.hwpf.model.io.*;
-
- /**
- * @author Ryan Ackley
- */
- public class SectionTable
- {
- private static final int SED_SIZE = 12;
-
- protected ArrayList _sections = new ArrayList();
- protected List _text;
-
- public SectionTable()
- {
- }
-
-
- public SectionTable(byte[] documentStream, byte[] tableStream, int offset,
- int size, int fcMin,
- List tpt)
- {
- PlexOfCps sedPlex = new PlexOfCps(tableStream, offset, size, SED_SIZE);
- _text = tpt;
-
- int length = sedPlex.length();
-
- for (int x = 0; x < length; x++)
- {
- GenericPropertyNode node = sedPlex.getProperty(x);
- SectionDescriptor sed = new SectionDescriptor(node.getBytes(), 0);
-
- int fileOffset = sed.getFc();
-
- // check for the optimization
- if (fileOffset == 0xffffffff)
- {
- _sections.add(new SEPX(sed, CPtoFC(node.getStart()), CPtoFC(node.getEnd()), new byte[0]));
- }
- else
- {
- // The first short at the offset is the size of the grpprl.
- int sepxSize = LittleEndian.getShort(documentStream, fileOffset);
- byte[] buf = new byte[sepxSize];
- fileOffset += LittleEndian.SHORT_SIZE;
- System.arraycopy(documentStream, fileOffset, buf, 0, buf.length);
- _sections.add(new SEPX(sed, CPtoFC(node.getStart()), CPtoFC(node.getEnd()), buf));
- }
- }
- }
-
- public void adjustForInsert(int listIndex, int length)
- {
- int size = _sections.size();
- SEPX sepx = (SEPX)_sections.get(listIndex);
- sepx.setEnd(sepx.getEnd() + length);
-
- for (int x = listIndex + 1; x < size; x++)
- {
- sepx = (SEPX)_sections.get(x);
- sepx.setStart(sepx.getStart() + length);
- sepx.setEnd(sepx.getEnd() + length);
- }
- }
-
- // goss version of CPtoFC - this takes into account non-contiguous textpieces
- // that we have come across in real world documents. Tests against the example
- // code in HWPFDocument show no variation to Ryan's version of the code in
- // normal use, but this version works with our non-contiguous test case.
- // So far unable to get this test case to be written out as well due to
- // other issues. - piers
- private int CPtoFC(int CP)
- {
- TextPiece TP = null;
-
- for(int i=_text.size()-1; i>-1; i--)
- {
- TP = (TextPiece)_text.get(i);
-
- if(CP >= TP.getCP()) break;
- }
- int FC = TP.getPieceDescriptor().getFilePosition();
- int offset = CP - TP.getCP();
- if(TP.usesUnicode()) offset*=2;
- FC = FC+offset-((TextPiece)_text.get(0)).getPieceDescriptor().getFilePosition();
- return FC;
- }
-
- // Ryans code
- private int FCtoCP(int fc)
- {
- int size = _text.size();
- int cp = 0;
- for (int x = 0; x < size; x++)
- {
- TextPiece piece = (TextPiece)_text.get(x);
-
- if (fc <= piece.getEnd())
- {
- cp += ((fc - piece.getStart())/ (piece.usesUnicode() ? 2 : 1));
- break;
- }
- else
- {
- cp += ((piece.getEnd() - piece.getStart())/ (piece.usesUnicode() ? 2 : 1));
- }
- }
- return cp;
- }
-
-
- public ArrayList getSections()
- {
- return _sections;
- }
-
- public void writeTo(HWPFFileSystem sys, int fcMin)
- throws IOException
- {
- HWPFOutputStream docStream = sys.getStream("WordDocument");
- HWPFOutputStream tableStream = sys.getStream("1Table");
-
- int offset = docStream.getOffset();
- int len = _sections.size();
- PlexOfCps plex = new PlexOfCps(SED_SIZE);
-
- for (int x = 0; x < len; x++)
- {
- SEPX sepx = (SEPX)_sections.get(x);
- byte[] grpprl = sepx.getGrpprl();
-
- // write the sepx to the document stream. starts with a 2 byte size
- // followed by the grpprl
- byte[] shortBuf = new byte[2];
- LittleEndian.putShort(shortBuf, (short)grpprl.length);
-
- docStream.write(shortBuf);
- docStream.write(grpprl);
-
- // set the fc in the section descriptor
- SectionDescriptor sed = sepx.getSectionDescriptor();
- sed.setFc(offset);
-
- // add the section descriptor bytes to the PlexOfCps.
-
-
- // original line -
- //GenericPropertyNode property = new GenericPropertyNode(sepx.getStart(), sepx.getEnd(), sed.toByteArray());
-
- // Line using Ryan's FCtoCP() conversion method -
- // unable to observe any effect on our testcases when using this code - piers
- GenericPropertyNode property = new GenericPropertyNode(FCtoCP(sepx.getStart()), FCtoCP(sepx.getEnd()), sed.toByteArray());
-
-
- plex.addProperty(property);
-
- offset = docStream.getOffset();
- }
- tableStream.write(plex.toByteArray());
- }
- }
|