You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SectionTable.java 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /* ====================================================================
  2. Copyright 2002-2004 Apache Software Foundation
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ==================================================================== */
  13. package org.apache.poi.hwpf.model;
  14. import java.util.ArrayList;
  15. import java.io.ByteArrayOutputStream;
  16. import java.io.IOException;
  17. import java.util.List;
  18. import org.apache.poi.util.LittleEndian;
  19. import org.apache.poi.hwpf.model.io.*;
  20. /**
  21. * @author Ryan Ackley
  22. */
  23. public class SectionTable
  24. {
  25. private static final int SED_SIZE = 12;
  26. protected ArrayList _sections = new ArrayList();
  27. protected List _text;
  28. public SectionTable()
  29. {
  30. }
  31. public SectionTable(byte[] documentStream, byte[] tableStream, int offset,
  32. int size, int fcMin,
  33. List tpt)
  34. {
  35. PlexOfCps sedPlex = new PlexOfCps(tableStream, offset, size, SED_SIZE);
  36. _text = tpt;
  37. int length = sedPlex.length();
  38. for (int x = 0; x < length; x++)
  39. {
  40. GenericPropertyNode node = sedPlex.getProperty(x);
  41. SectionDescriptor sed = new SectionDescriptor(node.getBytes(), 0);
  42. int fileOffset = sed.getFc();
  43. // check for the optimization
  44. if (fileOffset == 0xffffffff)
  45. {
  46. _sections.add(new SEPX(sed, CPtoFC(node.getStart()), CPtoFC(node.getEnd()), new byte[0]));
  47. }
  48. else
  49. {
  50. // The first short at the offset is the size of the grpprl.
  51. int sepxSize = LittleEndian.getShort(documentStream, fileOffset);
  52. byte[] buf = new byte[sepxSize];
  53. fileOffset += LittleEndian.SHORT_SIZE;
  54. System.arraycopy(documentStream, fileOffset, buf, 0, buf.length);
  55. _sections.add(new SEPX(sed, CPtoFC(node.getStart()), CPtoFC(node.getEnd()), buf));
  56. }
  57. }
  58. }
  59. public void adjustForInsert(int listIndex, int length)
  60. {
  61. int size = _sections.size();
  62. SEPX sepx = (SEPX)_sections.get(listIndex);
  63. sepx.setEnd(sepx.getEnd() + length);
  64. for (int x = listIndex + 1; x < size; x++)
  65. {
  66. sepx = (SEPX)_sections.get(x);
  67. sepx.setStart(sepx.getStart() + length);
  68. sepx.setEnd(sepx.getEnd() + length);
  69. }
  70. }
  71. // goss version of CPtoFC - this takes into account non-contiguous textpieces
  72. // that we have come across in real world documents. Tests against the example
  73. // code in HWPFDocument show no variation to Ryan's version of the code in
  74. // normal use, but this version works with our non-contiguous test case.
  75. // So far unable to get this test case to be written out as well due to
  76. // other issues. - piers
  77. private int CPtoFC(int CP)
  78. {
  79. TextPiece TP = null;
  80. for(int i=_text.size()-1; i>-1; i--)
  81. {
  82. TP = (TextPiece)_text.get(i);
  83. if(CP >= TP.getCP()) break;
  84. }
  85. int FC = TP.getPieceDescriptor().getFilePosition();
  86. int offset = CP - TP.getCP();
  87. if(TP.usesUnicode()) offset*=2;
  88. FC = FC+offset-((TextPiece)_text.get(0)).getPieceDescriptor().getFilePosition();
  89. return FC;
  90. }
  91. // Ryans code
  92. private int FCtoCP(int fc)
  93. {
  94. int size = _text.size();
  95. int cp = 0;
  96. for (int x = 0; x < size; x++)
  97. {
  98. TextPiece piece = (TextPiece)_text.get(x);
  99. if (fc <= piece.getEnd())
  100. {
  101. cp += ((fc - piece.getStart())/ (piece.usesUnicode() ? 2 : 1));
  102. break;
  103. }
  104. else
  105. {
  106. cp += ((piece.getEnd() - piece.getStart())/ (piece.usesUnicode() ? 2 : 1));
  107. }
  108. }
  109. return cp;
  110. }
  111. public ArrayList getSections()
  112. {
  113. return _sections;
  114. }
  115. public void writeTo(HWPFFileSystem sys, int fcMin)
  116. throws IOException
  117. {
  118. HWPFOutputStream docStream = sys.getStream("WordDocument");
  119. HWPFOutputStream tableStream = sys.getStream("1Table");
  120. int offset = docStream.getOffset();
  121. int len = _sections.size();
  122. PlexOfCps plex = new PlexOfCps(SED_SIZE);
  123. for (int x = 0; x < len; x++)
  124. {
  125. SEPX sepx = (SEPX)_sections.get(x);
  126. byte[] grpprl = sepx.getGrpprl();
  127. // write the sepx to the document stream. starts with a 2 byte size
  128. // followed by the grpprl
  129. byte[] shortBuf = new byte[2];
  130. LittleEndian.putShort(shortBuf, (short)grpprl.length);
  131. docStream.write(shortBuf);
  132. docStream.write(grpprl);
  133. // set the fc in the section descriptor
  134. SectionDescriptor sed = sepx.getSectionDescriptor();
  135. sed.setFc(offset);
  136. // add the section descriptor bytes to the PlexOfCps.
  137. // original line -
  138. //GenericPropertyNode property = new GenericPropertyNode(sepx.getStart(), sepx.getEnd(), sed.toByteArray());
  139. // Line using Ryan's FCtoCP() conversion method -
  140. // unable to observe any effect on our testcases when using this code - piers
  141. GenericPropertyNode property = new GenericPropertyNode(FCtoCP(sepx.getStart()), FCtoCP(sepx.getEnd()), sed.toByteArray());
  142. plex.addProperty(property);
  143. offset = docStream.getOffset();
  144. }
  145. tableStream.write(plex.toByteArray());
  146. }
  147. }