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.sprm;
019:
020: import org.apache.poi.hwpf.usermodel.ParagraphProperties;
021: import org.apache.poi.hwpf.usermodel.BorderCode;
022: import org.apache.poi.hwpf.usermodel.DateAndTime;
023: import org.apache.poi.hwpf.usermodel.LineSpacingDescriptor;
024: import org.apache.poi.hwpf.usermodel.ShadingDescriptor;
025: import org.apache.poi.hwpf.usermodel.DropCapSpecifier;
026: import org.apache.poi.util.LittleEndian;
027:
028: import java.util.HashMap;
029: import java.util.Set;
030: import java.util.Iterator;
031: import java.util.Collections;
032: import java.util.ArrayList;
033:
034: public class ParagraphSprmUncompressor extends SprmUncompressor {
035: public ParagraphSprmUncompressor() {
036: }
037:
038: public static ParagraphProperties uncompressPAP(
039: ParagraphProperties parent, byte[] grpprl, int offset) {
040: ParagraphProperties newProperties = null;
041: try {
042: newProperties = (ParagraphProperties) parent.clone();
043: } catch (CloneNotSupportedException cnse) {
044: throw new RuntimeException(
045: "There is no way this exception should happen!!");
046: }
047: SprmIterator sprmIt = new SprmIterator(grpprl, offset);
048:
049: while (sprmIt.hasNext()) {
050: SprmOperation sprm = (SprmOperation) sprmIt.next();
051:
052: // PAPXs can contain table sprms if the paragraph marks the end of a
053: // table row
054: if (sprm.getType() == SprmOperation.PAP_TYPE) {
055: unCompressPAPOperation(newProperties, sprm);
056: }
057: }
058:
059: return newProperties;
060: }
061:
062: /**
063: * Performs an operation on a ParagraphProperties object. Used to uncompress
064: * from a papx.
065: *
066: * @param newPAP The ParagraphProperties object to perform the operation on.
067: * @param operand The operand that defines the operation.
068: * @param param The operation's parameter.
069: * @param varParam The operation's variable length parameter.
070: * @param grpprl The original papx.
071: * @param offset The current offset in the papx.
072: * @param spra A part of the sprm that defined this operation.
073: */
074: static void unCompressPAPOperation(ParagraphProperties newPAP,
075: SprmOperation sprm) {
076: switch (sprm.getOperation()) {
077: case 0:
078: newPAP.setIstd(sprm.getOperand());
079: break;
080: case 0x1:
081:
082: // Used only for piece table grpprl's not for PAPX
083: // int istdFirst = LittleEndian.getShort (varParam, 2);
084: // int istdLast = LittleEndian.getShort (varParam, 4);
085: // if ((newPAP.getIstd () > istdFirst) || (newPAP.getIstd () <= istdLast))
086: // {
087: // permuteIstd (newPAP, varParam, opSize);
088: // }
089: break;
090: case 0x2:
091: if (newPAP.getIstd() <= 9 || newPAP.getIstd() >= 1) {
092: byte paramTmp = (byte) sprm.getOperand();
093: newPAP.setIstd(newPAP.getIstd() + paramTmp);
094: newPAP.setLvl((byte) (newPAP.getLvl() + paramTmp));
095:
096: if (((paramTmp >> 7) & 0x01) == 1) {
097: newPAP.setIstd(Math.max(newPAP.getIstd(), 1));
098: } else {
099: newPAP.setIstd(Math.min(newPAP.getIstd(), 9));
100: }
101:
102: }
103: break;
104: case 0x3:
105: newPAP.setJc((byte) sprm.getOperand());
106: break;
107: case 0x4:
108: newPAP.setFSideBySide((byte) sprm.getOperand());
109: break;
110: case 0x5:
111: newPAP.setFKeep((byte) sprm.getOperand());
112: break;
113: case 0x6:
114: newPAP.setFKeepFollow((byte) sprm.getOperand());
115: break;
116: case 0x7:
117: newPAP.setFPageBreakBefore((byte) sprm.getOperand());
118: break;
119: case 0x8:
120: newPAP.setBrcl((byte) sprm.getOperand());
121: break;
122: case 0x9:
123: newPAP.setBrcp((byte) sprm.getOperand());
124: break;
125: case 0xa:
126: newPAP.setIlvl((byte) sprm.getOperand());
127: break;
128: case 0xb:
129: newPAP.setIlfo(sprm.getOperand());
130: break;
131: case 0xc:
132: newPAP.setFNoLnn((byte) sprm.getOperand());
133: break;
134: case 0xd:
135: /**handle tabs . variable parameter. seperate processing needed*/
136: handleTabs(newPAP, sprm);
137: break;
138: case 0xe:
139: newPAP.setDxaRight(sprm.getOperand());
140: break;
141: case 0xf:
142: newPAP.setDxaLeft(sprm.getOperand());
143: break;
144: case 0x10:
145:
146: // sprmPNest is only stored in grpprls linked to a piece table.
147: newPAP.setDxaLeft(newPAP.getDxaLeft() + sprm.getOperand());
148: newPAP.setDxaLeft(Math.max(0, newPAP.getDxaLeft()));
149: break;
150: case 0x11:
151: newPAP.setDxaLeft1(sprm.getOperand());
152: break;
153: case 0x12:
154: newPAP.setLspd(new LineSpacingDescriptor(sprm.getGrpprl(),
155: sprm.getGrpprlOffset()));
156: break;
157: case 0x13:
158: newPAP.setDyaBefore(sprm.getOperand());
159: break;
160: case 0x14:
161: newPAP.setDyaAfter(sprm.getOperand());
162: break;
163: case 0x15:
164: // fast saved only
165: //applySprmPChgTabs (newPAP, varParam, opSize);
166: break;
167: case 0x16:
168: newPAP.setFInTable((byte) sprm.getOperand());
169: break;
170: case 0x17:
171: newPAP.setFTtp((byte) sprm.getOperand());
172: break;
173: case 0x18:
174: newPAP.setDxaAbs(sprm.getOperand());
175: break;
176: case 0x19:
177: newPAP.setDyaAbs(sprm.getOperand());
178: break;
179: case 0x1a:
180: newPAP.setDxaWidth(sprm.getOperand());
181: break;
182: case 0x1b:
183: byte param = (byte) sprm.getOperand();
184: /** @todo handle paragraph postioning*/
185: byte pcVert = (byte) ((param & 0x0c) >> 2);
186: byte pcHorz = (byte) (param & 0x03);
187: if (pcVert != 3) {
188: newPAP.setPcVert(pcVert);
189: }
190: if (pcHorz != 3) {
191: newPAP.setPcHorz(pcHorz);
192: }
193: break;
194:
195: // BrcXXX1 is older Version. Brc is used
196: case 0x1c:
197:
198: //newPAP.setBrcTop1((short)param);
199: break;
200: case 0x1d:
201:
202: //newPAP.setBrcLeft1((short)param);
203: break;
204: case 0x1e:
205:
206: //newPAP.setBrcBottom1((short)param);
207: break;
208: case 0x1f:
209:
210: //newPAP.setBrcRight1((short)param);
211: break;
212: case 0x20:
213:
214: //newPAP.setBrcBetween1((short)param);
215: break;
216: case 0x21:
217:
218: //newPAP.setBrcBar1((byte)param);
219: break;
220: case 0x22:
221: newPAP.setDxaFromText(sprm.getOperand());
222: break;
223: case 0x23:
224: newPAP.setWr((byte) sprm.getOperand());
225: break;
226: case 0x24:
227: newPAP.setBrcTop(new BorderCode(sprm.getGrpprl(), sprm
228: .getGrpprlOffset()));
229: break;
230: case 0x25:
231: newPAP.setBrcLeft(new BorderCode(sprm.getGrpprl(), sprm
232: .getGrpprlOffset()));
233: break;
234: case 0x26:
235: newPAP.setBrcBottom(new BorderCode(sprm.getGrpprl(), sprm
236: .getGrpprlOffset()));
237: break;
238: case 0x27:
239: newPAP.setBrcRight(new BorderCode(sprm.getGrpprl(), sprm
240: .getGrpprlOffset()));
241: break;
242: case 0x28:
243: newPAP.setBrcBetween(new BorderCode(sprm.getGrpprl(), sprm
244: .getGrpprlOffset()));
245: break;
246: case 0x29:
247: newPAP.setBrcBar(new BorderCode(sprm.getGrpprl(), sprm
248: .getGrpprlOffset()));
249: break;
250: case 0x2a:
251: newPAP.setFNoAutoHyph((byte) sprm.getOperand());
252: break;
253: case 0x2b:
254: newPAP.setDyaHeight(sprm.getOperand());
255: break;
256: case 0x2c:
257: newPAP.setDcs(new DropCapSpecifier((short) sprm
258: .getOperand()));
259: break;
260: case 0x2d:
261: newPAP.setShd(new ShadingDescriptor((short) sprm
262: .getOperand()));
263: break;
264: case 0x2e:
265: newPAP.setDyaFromText(sprm.getOperand());
266: break;
267: case 0x2f:
268: newPAP.setDxaFromText(sprm.getOperand());
269: break;
270: case 0x30:
271: newPAP.setFLocked((byte) sprm.getOperand());
272: break;
273: case 0x31:
274: newPAP.setFWidowControl((byte) sprm.getOperand());
275: break;
276: case 0x32:
277:
278: //undocumented
279: break;
280: case 0x33:
281: newPAP.setFKinsoku((byte) sprm.getOperand());
282: break;
283: case 0x34:
284: newPAP.setFWordWrap((byte) sprm.getOperand());
285: break;
286: case 0x35:
287: newPAP.setFOverflowPunct((byte) sprm.getOperand());
288: break;
289: case 0x36:
290: newPAP.setFTopLinePunct((byte) sprm.getOperand());
291: break;
292: case 0x37:
293: newPAP.setFAutoSpaceDE((byte) sprm.getOperand());
294: break;
295: case 0x38:
296: newPAP.setFAutoSpaceDN((byte) sprm.getOperand());
297: break;
298: case 0x39:
299: newPAP.setWAlignFont(sprm.getOperand());
300: break;
301: case 0x3a:
302: newPAP.setFontAlign((short) sprm.getOperand());
303: break;
304: case 0x3b:
305:
306: //obsolete
307: break;
308: case 0x3e: {
309: byte[] buf = new byte[sprm.size() - 3];
310: System.arraycopy(buf, 0, sprm.getGrpprl(), sprm
311: .getGrpprlOffset(), buf.length);
312: newPAP.setAnld(buf);
313: break;
314: }
315: case 0x3f:
316: //don't really need this. spec is confusing regarding this
317: //sprm
318: try {
319: byte[] varParam = sprm.getGrpprl();
320: int offset = sprm.getGrpprlOffset();
321: newPAP.setFPropRMark((int) varParam[offset]);
322: newPAP.setIbstPropRMark((int) LittleEndian.getShort(
323: varParam, offset + 1));
324: newPAP.setDttmPropRMark(new DateAndTime(varParam,
325: offset + 3));
326: } catch (Exception e) {
327: e.printStackTrace();
328: }
329: break;
330: case 0x40:
331:
332: //newPAP._lvl = param;
333: if (newPAP.getIstd() >= 1 && newPAP.getIstd() <= 9) {
334: newPAP.setIlvl((byte) sprm.getOperand());
335: }
336: break;
337: case 0x41:
338:
339: // undocumented
340: break;
341: case 0x43:
342:
343: //pap.fNumRMIns
344: newPAP.setFNumRMIns((byte) sprm.getOperand());
345: break;
346: case 0x44:
347:
348: //undocumented
349: break;
350: case 0x45:
351: if (sprm.getSizeCode() == 6) {
352: byte[] buf = new byte[sprm.size() - 3];
353: System.arraycopy(buf, 0, sprm.getGrpprl(), sprm
354: .getGrpprlOffset(), buf.length);
355: newPAP.setNumrm(buf);
356: } else {
357: /**@todo handle large PAPX from data stream*/
358: }
359: break;
360:
361: case 0x47:
362: newPAP.setFUsePgsuSettings((byte) sprm.getOperand());
363: break;
364: case 0x48:
365: newPAP.setFAdjustRight((byte) sprm.getOperand());
366: break;
367: case 0x49:
368: newPAP.setTableLevel((byte) sprm.getOperand());
369: break;
370: case 0x4b:
371: newPAP.setEmbeddedCellMark((byte) sprm.getOperand());
372: break;
373: case 0x4c:
374: newPAP.setFTtpEmbedded((byte) sprm.getOperand());
375: break;
376: default:
377: break;
378: }
379: }
380:
381: private static void handleTabs(ParagraphProperties pap,
382: SprmOperation sprm) {
383: byte[] grpprl = sprm.getGrpprl();
384: int offset = sprm.getGrpprlOffset();
385: int delSize = grpprl[offset++];
386: int[] tabPositions = pap.getRgdxaTab();
387: byte[] tabDescriptors = pap.getRgtbd();
388:
389: HashMap tabMap = new HashMap();
390: for (int x = 0; x < tabPositions.length; x++) {
391: tabMap.put(new Integer(tabPositions[x]), new Byte(
392: tabDescriptors[x]));
393: }
394:
395: for (int x = 0; x < delSize; x++) {
396: tabMap.remove(new Integer(LittleEndian.getShort(grpprl,
397: offset)));
398: offset += LittleEndian.SHORT_SIZE;
399: }
400:
401: int addSize = grpprl[offset++];
402: int start = offset;
403: for (int x = 0; x < addSize; x++) {
404: Integer key = new Integer(LittleEndian.getShort(grpprl,
405: offset));
406: Byte val = new Byte(grpprl[start
407: + ((LittleEndian.SHORT_SIZE * addSize) + x)]);
408: tabMap.put(key, val);
409: offset += LittleEndian.SHORT_SIZE;
410: }
411:
412: tabPositions = new int[tabMap.size()];
413: tabDescriptors = new byte[tabPositions.length];
414: ArrayList list = new ArrayList();
415:
416: Iterator keyIT = tabMap.keySet().iterator();
417: while (keyIT.hasNext()) {
418: list.add(keyIT.next());
419: }
420: Collections.sort(list);
421:
422: for (int x = 0; x < tabPositions.length; x++) {
423: Integer key = ((Integer) list.get(x));
424: tabPositions[x] = key.intValue();
425: tabDescriptors[x] = ((Byte) tabMap.get(key)).byteValue();
426: }
427:
428: pap.setRgdxaTab(tabPositions);
429: pap.setRgtbd(tabDescriptors);
430: }
431:
432: // private static void handleTabsAgain(ParagraphProperties pap, SprmOperation sprm)
433: // {
434: // byte[] grpprl = sprm.getGrpprl();
435: // int offset = sprm.getGrpprlOffset();
436: // int delSize = grpprl[offset++];
437: // int[] tabPositions = pap.getRgdxaTab();
438: // byte[] tabDescriptors = pap.getRgtbd();
439: //
440: // HashMap tabMap = new HashMap();
441: // for (int x = 0; x < tabPositions.length; x++)
442: // {
443: // tabMap.put(new Integer(tabPositions[x]), new Byte(tabDescriptors[x]));
444: // }
445: //
446: // for (int x = 0; x < delSize; x++)
447: // {
448: // tabMap.remove(new Integer(LittleEndian.getInt(grpprl, offset)));
449: // offset += LittleEndian.INT_SIZE;;
450: // }
451: //
452: // int addSize = grpprl[offset++];
453: // for (int x = 0; x < addSize; x++)
454: // {
455: // Integer key = new Integer(LittleEndian.getInt(grpprl, offset));
456: // Byte val = new Byte(grpprl[(LittleEndian.INT_SIZE * (addSize - x)) + x]);
457: // tabMap.put(key, val);
458: // offset += LittleEndian.INT_SIZE;
459: // }
460: //
461: // tabPositions = new int[tabMap.size()];
462: // tabDescriptors = new byte[tabPositions.length];
463: // ArrayList list = new ArrayList();
464: //
465: // Iterator keyIT = tabMap.keySet().iterator();
466: // while (keyIT.hasNext())
467: // {
468: // list.add(keyIT.next());
469: // }
470: // Collections.sort(list);
471: //
472: // for (int x = 0; x < tabPositions.length; x++)
473: // {
474: // Integer key = ((Integer)list.get(x));
475: // tabPositions[x] = key.intValue();
476: // tabDescriptors[x] = ((Byte)tabMap.get(key)).byteValue();
477: // }
478: //
479: // pap.setRgdxaTab(tabPositions);
480: // pap.setRgtbd(tabDescriptors);
481: // }
482:
483: }
|