KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > poi > hdf > model > hdftypes > StyleSheet


1
2 /* ====================================================================
3    Copyright 2002-2004 Apache Software Foundation
4
5    Licensed under the Apache License, Version 2.0 (the "License");
6    you may not use this file except in compliance with the License.
7    You may obtain a copy of the License at
8
9        http://www.apache.org/licenses/LICENSE-2.0
10
11    Unless required by applicable law or agreed to in writing, software
12    distributed under the License is distributed on an "AS IS" BASIS,
13    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14    See the License for the specific language governing permissions and
15    limitations under the License.
16 ==================================================================== */

17         
18
19
20 package org.apache.poi.hdf.model.hdftypes;
21
22 import java.util.*;
23 import org.apache.poi.util.LittleEndian;
24 import org.apache.poi.hdf.model.hdftypes.definitions.TCAbstractType;
25
26 /**
27  * Represents a document's stylesheet. A word documents formatting is stored as
28  * compressed styles that are based on styles contained in the stylesheet. This
29  * class also contains static utility functions to uncompress different
30  * formatting properties.
31  *
32  * @author Ryan Ackley
33  */

34
35 public class StyleSheet implements HDFType
36 {
37
38   private static final int NIL_STYLE = 4095;
39   private static final int PAP_TYPE = 1;
40   private static final int CHP_TYPE = 2;
41   private static final int SEP_TYPE = 4;
42   private static final int TAP_TYPE = 5;
43   //Vector _styleDescriptions;
44
StyleDescription _nilStyle = new StyleDescription();
45   StyleDescription[] _styleDescriptions;
46
47   /**
48    * StyleSheet constructor. Loads a document's stylesheet information,
49    *
50    * @param styleSheet A byte array containing a document's raw stylesheet
51    * info. Found by using FileInformationBlock.getFcStshf() and
52    * FileInformationBLock.getLcbStshf()
53    */

54   public StyleSheet(byte[] styleSheet)
55   {
56       int stshiLength = LittleEndian.getShort(styleSheet, 0);
57       int stdCount = LittleEndian.getShort(styleSheet, 2);
58       int baseLength = LittleEndian.getShort(styleSheet, 4);
59       int[] rgftc = new int[3];
60
61       rgftc[0] = LittleEndian.getInt(styleSheet, 14);
62       rgftc[1] = LittleEndian.getInt(styleSheet, 18);
63       rgftc[2] = LittleEndian.getInt(styleSheet, 22);
64
65       int offset = 0;
66       _styleDescriptions = new StyleDescription[stdCount];
67       for(int x = 0; x < stdCount; x++)
68       {
69           int stdOffset = (2 + stshiLength) + offset;
70           int stdSize = LittleEndian.getShort(styleSheet, stdOffset);
71           if(stdSize > 0)
72           {
73               byte[] std = new byte[stdSize];
74
75               //get past the size
76
stdOffset += 2;
77               System.arraycopy(styleSheet, stdOffset, std, 0, stdSize);
78               StyleDescription aStyle = new StyleDescription(std, baseLength, true);
79
80               _styleDescriptions[x] = aStyle;
81           }
82
83
84           offset += stdSize + 2;
85
86       }
87       for(int x = 0; x < _styleDescriptions.length; x++)
88       {
89           if(_styleDescriptions[x] != null)
90           {
91               createPap(x);
92               createChp(x);
93           }
94       }
95   }
96   /**
97    * Creates a PartagraphProperties object from a papx stored in the
98    * StyleDescription at the index istd in the StyleDescription array. The PAP
99    * is placed in the StyleDescription at istd after its been created. Not
100    * every StyleDescription will contain a papx. In these cases this function
101    * does nothing
102    *
103    * @param istd The index of the StyleDescription to create the
104    * ParagraphProperties from (and also place the finished PAP in)
105    */

106   private void createPap(int istd)
107   {
108       StyleDescription sd = _styleDescriptions[istd];
109       ParagraphProperties pap = sd.getPAP();
110       byte[] papx = sd.getPAPX();
111       int baseIndex = sd.getBaseStyle();
112       if(pap == null && papx != null)
113       {
114           ParagraphProperties parentPAP = _nilStyle.getPAP();
115           if(baseIndex != NIL_STYLE)
116           {
117
118               parentPAP = _styleDescriptions[baseIndex].getPAP();
119               if(parentPAP == null)
120               {
121                   createPap(baseIndex);
122                   parentPAP = _styleDescriptions[baseIndex].getPAP();
123               }
124
125           }
126
127           pap = (ParagraphProperties)uncompressProperty(papx, parentPAP, this);
128           sd.setPAP(pap);
129       }
130   }
131   /**
132    * Creates a CharacterProperties object from a chpx stored in the
133    * StyleDescription at the index istd in the StyleDescription array. The
134    * CharacterProperties object is placed in the StyleDescription at istd after
135    * its been created. Not every StyleDescription will contain a chpx. In these
136    * cases this function does nothing.
137    *
138    * @param istd The index of the StyleDescription to create the
139    * CharacterProperties object from.
140    */

141   private void createChp(int istd)
142   {
143       StyleDescription sd = _styleDescriptions[istd];
144       CharacterProperties chp = sd.getCHP();
145       byte[] chpx = sd.getCHPX();
146       int baseIndex = sd.getBaseStyle();
147       if(chp == null && chpx != null)
148       {
149           CharacterProperties parentCHP = _nilStyle.getCHP();
150           if(baseIndex != NIL_STYLE)
151           {
152
153               parentCHP = _styleDescriptions[baseIndex].getCHP();
154               if(parentCHP == null)
155               {
156                   createChp(baseIndex);
157                   parentCHP = _styleDescriptions[baseIndex].getCHP();
158               }
159
160           }
161
162           chp = (CharacterProperties)uncompressProperty(chpx, parentCHP, this);
163           sd.setCHP(chp);
164       }
165   }
166
167   /**
168    * Gets the StyleDescription at index x.
169    *
170    * @param x the index of the desired StyleDescription.
171    */

172   public StyleDescription getStyleDescription(int x)
173   {
174       return _styleDescriptions[x];
175   }
176
177   /**
178    * Used in decompression of a chpx. This performs an operation defined by
179    * a single sprm.
180    *
181    * @param oldCHP The base CharacterProperties.
182    * @param newCHP The current CharacterProperties.
183    * @param operand The operand defined by the sprm (See Word file format spec)
184    * @param param The parameter defined by the sprm (See Word file format spec)
185    * @param varParam The variable length parameter defined by the sprm. (See
186    * Word file format spec)
187    * @param grpprl The entire chpx that this operation is a part of.
188    * @param offset The offset in the grpprl of the next sprm
189    * @param styleSheet The StyleSheet for this document.
190    */

191   static void doCHPOperation(CharacterProperties oldCHP, CharacterProperties newCHP,
192                              int operand, int param,
193                              byte[] varParam, byte[] grpprl, int offset,
194                              StyleSheet styleSheet)
195   {
196       switch(operand)
197       {
198           case 0:
199                newCHP.setFRMarkDel(getFlag(param));
200                break;
201           case 0x1:
202                newCHP.setFRMark(getFlag(param));
203                break;
204           case 0x2:
205                break;
206           case 0x3:
207                newCHP.setFcPic(param);
208                newCHP.setFSpec(true);
209                break;
210           case 0x4:
211                newCHP.setIbstRMark((short)param);
212                break;
213           case 0x5:
214                short[] dttmRMark = new short[2];
215                dttmRMark[0] = LittleEndian.getShort(grpprl, (offset - 4));
216                dttmRMark[1] = LittleEndian.getShort(grpprl, (offset - 2));
217                newCHP.setDttmRMark(dttmRMark);
218                break;
219           case 0x6:
220                newCHP.setFData(getFlag(param));
221                break;
222           case 0x7:
223                //don't care about this
224
break;
225           case 0x8:
226                short chsDiff = (short)((param & 0xff0000) >>> 8);
227                newCHP.setFChsDiff(getFlag(chsDiff));
228                newCHP.setChse((short)(param & 0xffff));
229                break;
230           case 0x9:
231                newCHP.setFSpec(true);
232                newCHP.setFtcSym((short)LittleEndian.getShort(varParam, 0));
233                newCHP.setXchSym((short)LittleEndian.getShort(varParam, 2));
234                break;
235           case 0xa:
236                newCHP.setFOle2(getFlag(param));
237                break;
238           case 0xb:
239                //?
240
break;
241           case 0xc:
242                newCHP.setIcoHighlight((byte)param);
243                newCHP.setFHighlight(getFlag(param));
244                break;
245           case 0xd:
246                break;
247           case 0xe:
248                newCHP.setFcObj(param);
249                break;
250           case 0xf:
251                break;
252           case 0x10:
253                //?
254
break;
255           case 0x11:
256                break;
257           case 0x12:
258                break;
259           case 0x13:
260                break;
261           case 0x14:
262                break;
263           case 0x15:
264                break;
265           case 0x16:
266                break;
267           case 0x17:
268                break;
269           case 0x18:
270                break;
271           case 0x19:
272                break;
273           case 0x1a:
274                break;
275           case 0x1b:
276                break;
277           case 0x1c:
278                break;
279           case 0x1d:
280                break;
281           case 0x1e:
282                break;
283           case 0x1f:
284                break;
285           case 0x20:
286                break;
287           case 0x21:
288                break;
289           case 0x22:
290                break;
291           case 0x23:
292                break;
293           case 0x24:
294                break;
295           case 0x25:
296                break;
297           case 0x26:
298                break;
299           case 0x27:
300                break;
301           case 0x28:
302                break;
303           case 0x29:
304                break;
305           case 0x2a:
306                break;
307           case 0x2b:
308                break;
309           case 0x2c:
310                break;
311           case 0x2d:
312                break;
313           case 0x2e:
314                break;
315           case 0x2f:
316                break;
317           case 0x30:
318                newCHP.setIstd(param);
319                break;
320           case 0x31:
321                //permutation vector for fast saves, who cares!
322
break;
323           case 0x32:
324                newCHP.setFBold(false);
325                newCHP.setFItalic(false);
326                newCHP.setFOutline(false);
327                newCHP.setFStrike(false);
328                newCHP.setFShadow(false);
329                newCHP.setFSmallCaps(false);
330                newCHP.setFCaps(false);
331                newCHP.setFVanish(false);
332                newCHP.setKul((byte)0);
333                newCHP.setIco((byte)0);
334                break;
335           case 0x33:
336                try
337                {
338                    newCHP = (CharacterProperties)oldCHP.clone();
339                }
340                catch(CloneNotSupportedException JavaDoc e)
341                {
342                    //do nothing
343
}
344                return;
345           case 0x34:
346                break;
347           case 0x35:
348                newCHP.setFBold(getCHPFlag((byte)param, oldCHP.isFBold()));
349                break;
350           case 0x36:
351                newCHP.setFItalic(getCHPFlag((byte)param, oldCHP.isFItalic()));
352                break;
353           case 0x37:
354                newCHP.setFStrike(getCHPFlag((byte)param, oldCHP.isFStrike()));
355                break;
356           case 0x38:
357                newCHP.setFOutline(getCHPFlag((byte)param, oldCHP.isFOutline()));
358                break;
359           case 0x39:
360                newCHP.setFShadow(getCHPFlag((byte)param, oldCHP.isFShadow()));
361                break;
362           case 0x3a:
363                newCHP.setFSmallCaps(getCHPFlag((byte)param, oldCHP.isFSmallCaps()));
364                break;
365           case 0x3b:
366                newCHP.setFCaps(getCHPFlag((byte)param, oldCHP.isFCaps()));
367                break;
368           case 0x3c:
369                newCHP.setFVanish(getCHPFlag((byte)param, oldCHP.isFVanish()));
370                break;
371           case 0x3d:
372                newCHP.setFtcAscii((short)param);
373                break;
374           case 0x3e:
375                newCHP.setKul((byte)param);
376                break;
377           case 0x3f:
378                int hps = param & 0xff;
379                if(hps != 0)
380                {
381                   newCHP.setHps(hps);
382                }
383                byte cInc = (byte)(((byte)(param & 0xfe00) >>> 4) >> 1);
384                if(cInc != 0)
385                {
386                   newCHP.setHps(Math.max(newCHP.getHps() + (cInc * 2), 2));
387                }
388                byte hpsPos = (byte)((param & 0xff0000) >>> 8);
389                if(hpsPos != 0x80)
390                {
391                   newCHP.setHpsPos(hpsPos);
392                }
393                boolean fAdjust = (param & 0x0100) > 0;
394                if(fAdjust && hpsPos != 128 && hpsPos != 0 && oldCHP.getHpsPos() == 0)
395                {
396                   newCHP.setHps(Math.max(newCHP.getHps() + (-2), 2));
397                }
398                if(fAdjust && hpsPos == 0 && oldCHP.getHpsPos() != 0)
399                {
400                   newCHP.setHps(Math.max(newCHP.getHps() + 2, 2));
401                }
402                break;
403           case 0x40:
404                newCHP.setDxaSpace(param);
405                break;
406           case 0x41:
407                newCHP.setLidDefault((short)param);
408                break;
409           case 0x42:
410                newCHP.setIco((byte)param);
411                break;
412           case 0x43:
413                newCHP.setHps(param);
414                break;
415           case 0x44:
416                byte hpsLvl = (byte)param;
417                newCHP.setHps(Math.max(newCHP.getHps() + (hpsLvl * 2), 2));
418                break;
419           case 0x45:
420                newCHP.setHpsPos((short)param);
421                break;
422           case 0x46:
423                if(param != 0)
424                {
425                   if(oldCHP.getHpsPos() == 0)
426                   {
427                       newCHP.setHps(Math.max(newCHP.getHps() + (-2), 2));
428                   }
429                }
430                else
431                {
432                   if(oldCHP.getHpsPos() != 0)
433                   {
434                       newCHP.setHps(Math.max(newCHP.getHps() + 2, 2));
435                   }
436                }
437                break;
438           case 0x47:
439                CharacterProperties genCHP = new CharacterProperties();
440                genCHP.setFtcAscii(4);
441                genCHP = (CharacterProperties)uncompressProperty(varParam, genCHP, styleSheet);
442                CharacterProperties styleCHP = styleSheet.getStyleDescription(oldCHP.getBaseIstd()).getCHP();
443                if(genCHP.isFBold() == newCHP.isFBold())
444                {
445                   newCHP.setFBold(styleCHP.isFBold());
446                }
447                if(genCHP.isFItalic() == newCHP.isFItalic())
448                {
449                   newCHP.setFItalic(styleCHP.isFItalic());
450                }
451                if(genCHP.isFSmallCaps() == newCHP.isFSmallCaps())
452                {
453                   newCHP.setFSmallCaps(styleCHP.isFSmallCaps());
454                }
455                if(genCHP.isFVanish() == newCHP.isFVanish())
456                {
457                   newCHP.setFVanish(styleCHP.isFVanish());
458                }
459                if(genCHP.isFStrike() == newCHP.isFStrike())
460                {
461                   newCHP.setFStrike(styleCHP.isFStrike());
462                }
463                if(genCHP.isFCaps() == newCHP.isFCaps())
464                {
465                   newCHP.setFCaps(styleCHP.isFCaps());
466                }
467                if(genCHP.getFtcAscii() == newCHP.getFtcAscii())
468                {
469                   newCHP.setFtcAscii(styleCHP.getFtcAscii());
470                }
471                if(genCHP.getFtcFE() == newCHP.getFtcFE())
472                {
473                   newCHP.setFtcFE(styleCHP.getFtcFE());
474                }
475                if(genCHP.getFtcOther() == newCHP.getFtcOther())
476                {
477                   newCHP.setFtcOther(styleCHP.getFtcOther());
478                }
479                if(genCHP.getHps() == newCHP.getHps())
480                {
481                   newCHP.setHps(styleCHP.getHps());
482                }
483                if(genCHP.getHpsPos() == newCHP.getHpsPos())
484                {
485                   newCHP.setHpsPos(styleCHP.getHpsPos());
486                }
487                if(genCHP.getKul() == newCHP.getKul())
488                {
489                   newCHP.setKul(styleCHP.getKul());
490                }
491                if(genCHP.getDxaSpace() == newCHP.getDxaSpace())
492                {
493                   newCHP.setDxaSpace(styleCHP.getDxaSpace());
494                }
495                if(genCHP.getIco() == newCHP.getIco())
496                {
497                   newCHP.setIco(styleCHP.getIco());
498                }
499                if(genCHP.getLidDefault() == newCHP.getLidDefault())
500                {
501                   newCHP.setLidDefault(styleCHP.getLidDefault());
502                }
503                if(genCHP.getLidFE() == newCHP.getLidFE())
504                {
505                   newCHP.setLidFE(styleCHP.getLidFE());
506                }
507                break;
508           case 0x48:
509                newCHP.setIss((byte)param);
510                break;
511           case 0x49:
512                newCHP.setHps(LittleEndian.getShort(varParam, 0));
513                break;
514           case 0x4a:
515                int increment = LittleEndian.getShort(varParam, 0);
516                newCHP.setHps(Math.max(newCHP.getHps() + increment, 8));
517                break;
518           case 0x4b:
519                newCHP.setHpsKern(param);
520                break;
521           case 0x4c:
522                doCHPOperation(oldCHP, newCHP, 0x47, param, varParam, grpprl, offset, styleSheet);
523                break;
524           case 0x4d:
525                float percentage = (float)param/100.0f;
526                int add = (int)((float)percentage * (float)newCHP.getHps());
527                newCHP.setHps(newCHP.getHps() + add);
528                break;
529           case 0x4e:
530                newCHP.setYsr((byte)param);
531                break;
532           case 0x4f:
533                newCHP.setFtcAscii((short)param);
534                break;
535           case 0x50:
536                newCHP.setFtcFE((short)param);
537                break;
538           case 0x51:
539                newCHP.setFtcOther((short)param);
540                break;
541           case 0x52:
542                break;
543           case 0x53:
544                newCHP.setFDStrike(getFlag(param));
545                break;
546           case 0x54:
547                newCHP.setFImprint(getFlag(param));
548                break;
549           case 0x55:
550                newCHP.setFSpec(getFlag(param));
551                break;
552           case 0x56:
553                newCHP.setFObj(getFlag(param));
554                break;
555           case 0x57:
556                newCHP.setFPropMark(varParam[0]);
557                newCHP.setIbstPropRMark((short)LittleEndian.getShort(varParam, 1));
558                newCHP.setDttmPropRMark(LittleEndian.getInt(varParam, 3));
559                break;
560           case 0x58:
561                newCHP.setFEmboss(getFlag(param));
562                break;
563           case 0x59:
564                newCHP.setSfxtText((byte)param);
565                break;
566           case 0x5a:
567                break;
568           case 0x5b:
569                break;
570           case 0x5c:
571                break;
572           case 0x5d:
573                break;
574           case 0x5e:
575                break;
576           case 0x5f:
577                break;
578           case 0x60:
579                break;
580           case 0x61:
581                break;
582           case 0x62:
583                byte[] xstDispFldRMark = new byte[32];
584                newCHP.setFDispFldRMark(varParam[0]);
585                newCHP.setIbstDispFldRMark((short)LittleEndian.getShort(varParam, 1));
586                newCHP.setDttmDispFldRMark(LittleEndian.getInt(varParam, 3));
587                System.arraycopy(varParam, 7, xstDispFldRMark, 0, 32);
588                newCHP.setXstDispFldRMark(xstDispFldRMark);
589                break;
590           case 0x63:
591                newCHP.setIbstRMarkDel((short)param);
592                break;
593           case 0x64:
594                short[] dttmRMarkDel = new short[2];
595                dttmRMarkDel[0] = LittleEndian.getShort(grpprl, offset - 4);
596                dttmRMarkDel[1] = LittleEndian.getShort(grpprl, offset - 2);
597                newCHP.setDttmRMarkDel(dttmRMarkDel);
598                break;
599           case 0x65:
600                short[] brc = new short[2];
601                brc[0] = (short)LittleEndian.getShort(grpprl, offset - 4);
602                brc[1] = (short)LittleEndian.getShort(grpprl, offset - 2);
603                newCHP.setBrc(brc);
604                break;
605           case 0x66:
606                newCHP.setShd((short)param);
607                break;
608           case 0x67:
609                break;
610           case 0x68:
611                break;
612           case 0x69:
613                break;
614           case 0x6a:
615                break;
616           case 0x6b:
617                break;
618           case 0x6c:
619                break;
620           case 0x6d:
621                newCHP.setLidDefault((short)param);
622                break;
623           case 0x6e:
624                newCHP.setLidFE((short)param);
625                break;
626           case 0x6f:
627                newCHP.setIdctHint((byte)param);
628                break;
629       }
630   }
631
632   /**
633    * Used to uncompress a property stored in a grpprl. These include
634    * CharacterProperties, ParagraphProperties, TableProperties, and
635    * SectionProperties.
636    *
637    * @param grpprl The compressed form of the property.
638    * @param parent The base property of the property.
639    * @param styleSheet The document's stylesheet.
640    *
641    * @return An object that should be casted to the appropriate property.
642    */

643   public static Object JavaDoc uncompressProperty(byte[] grpprl, Object JavaDoc parent, StyleSheet styleSheet)
644   {
645     return uncompressProperty(grpprl, parent, styleSheet, true);
646   }
647
648   /**
649    * Used to uncompress a property stored in a grpprl. These include
650    * CharacterProperties, ParagraphProperties, TableProperties, and
651    * SectionProperties.
652    *
653    * @param grpprl The compressed form of the property.
654    * @param parent The base property of the property.
655    * @param styleSheet The document's stylesheet.
656    *
657    * @return An object that should be casted to the appropriate property.
658    */

659   public static Object JavaDoc uncompressProperty(byte[] grpprl, Object JavaDoc parent, StyleSheet styleSheet, boolean doIstd)
660   {
661       Object JavaDoc newProperty = null;
662       int offset = 0;
663       int propertyType = PAP_TYPE;
664
665
666       if(parent instanceof ParagraphProperties)
667       {
668           try
669           {
670               newProperty = ((ParagraphProperties)parent).clone();
671           }
672           catch(Exception JavaDoc e){}
673           if(doIstd)
674           {
675             ((ParagraphProperties)newProperty).setIstd(LittleEndian.getShort(grpprl, 0));
676
677             offset = 2;
678           }
679       }
680       else if(parent instanceof CharacterProperties)
681       {
682           try
683           {
684               newProperty = ((CharacterProperties)parent).clone();
685               ((CharacterProperties)newProperty).setBaseIstd(((CharacterProperties)parent).getIstd());
686           }
687           catch(Exception JavaDoc e){}
688           propertyType = CHP_TYPE;
689       }
690       else if(parent instanceof SectionProperties)
691       {
692           newProperty = parent;
693           propertyType = SEP_TYPE;
694       }
695       else if(parent instanceof TableProperties)
696       {
697           newProperty = parent;
698           propertyType = TAP_TYPE;
699           offset = 2;//because this is really just a papx
700
}
701       else
702       {
703           return null;
704       }
705
706       while(offset < grpprl.length)
707       {
708           short sprm = LittleEndian.getShort(grpprl, offset);
709           offset += 2;
710
711           byte spra = (byte)((sprm & 0xe000) >> 13);
712           int opSize = 0;
713           int param = 0;
714           byte[] varParam = null;
715
716           switch(spra)
717           {
718               case 0:
719               case 1:
720                    opSize = 1;
721                    param = grpprl[offset];
722                    break;
723               case 2:
724                    opSize = 2;
725                    param = LittleEndian.getShort(grpprl, offset);
726                    break;
727               case 3:
728                    opSize = 4;
729                    param = LittleEndian.getInt(grpprl, offset);
730                    break;
731               case 4:
732               case 5:
733                    opSize = 2;
734                    param = LittleEndian.getShort(grpprl, offset);
735                    break;
736               case 6://variable size
737

738                    //there is one sprm that is a very special case
739
if(sprm != (short)0xd608)
740                    {
741                      opSize = LittleEndian.getUnsignedByte(grpprl, offset);
742                      offset++;
743                    }
744                    else
745                    {
746                      opSize = LittleEndian.getShort(grpprl, offset) - 1;
747                      offset += 2;
748                    }
749                    varParam = new byte[opSize];
750                    System.arraycopy(grpprl, offset, varParam, 0, opSize);
751
752                    break;
753               case 7:
754                    opSize = 3;
755                    byte threeByteInt[] = new byte[4];
756                    threeByteInt[0] = grpprl[offset];
757                    threeByteInt[1] = grpprl[offset + 1];
758                    threeByteInt[2] = grpprl[offset + 2];
759                    threeByteInt[3] = (byte)0;
760                    param = LittleEndian.getInt(threeByteInt, 0);
761                    break;
762               default:
763                   throw new RuntimeException JavaDoc("unrecognized pap opcode");
764           }
765
766           offset += opSize;
767           short operand = (short)(sprm & 0x1ff);
768           byte type = (byte)((sprm & 0x1c00) >> 10);
769           switch(propertyType)
770           {
771               case PAP_TYPE:
772                    if(type == 1)//papx stores TAP sprms along with PAP sprms
773
{
774                      doPAPOperation((ParagraphProperties)newProperty, operand,
775                                     param, varParam, grpprl,
776                                     offset, spra);
777                    }
778                    break;
779               case CHP_TYPE:
780
781                    doCHPOperation((CharacterProperties)parent,
782                                   (CharacterProperties)newProperty,
783                                   operand, param, varParam,
784                                   grpprl, offset, styleSheet);
785                    break;
786               case SEP_TYPE:
787
788                    doSEPOperation((SectionProperties)newProperty, operand, param, varParam);
789                    break;
790               case TAP_TYPE:
791                    if(type == 5)
792                    {
793                      doTAPOperation((TableProperties)newProperty, operand, param, varParam);
794                    }
795                    break;
796           }
797
798
799       }
800       return newProperty;
801
802   }
803   /**
804    * Performs an operation on a ParagraphProperties object. Used to uncompress
805    * from a papx.
806    *
807    * @param newPAP The ParagraphProperties object to perform the operation on.
808    * @param operand The operand that defines the operation.
809    * @param param The operation's parameter.
810    * @param varParam The operation's variable length parameter.
811    * @param grpprl The original papx.
812    * @param offset The current offset in the papx.
813    * @param spra A part of the sprm that defined this operation.
814    */

815   static void doPAPOperation(ParagraphProperties newPAP, int operand, int param,
816                              byte[] varParam, byte[] grpprl, int offset,
817                              int spra)
818   {
819       switch(operand)
820       {
821           case 0:
822                newPAP.setIstd(param);
823                break;
824           case 0x1:
825                //permuteIstd(newPAP, varParam);
826
break;
827           case 0x2:
828                if(newPAP.getIstd() <=9 || newPAP.getIstd() >=1)
829                {
830                   newPAP.setIstd(newPAP.getIstd() + param);
831                   if(param > 0)
832                   {
833                       newPAP.setIstd(Math.max(newPAP.getIstd(), 9));
834                   }
835                   else
836                   {
837                       newPAP.setIstd(Math.min(newPAP.getIstd(), 1));
838                   }
839                }
840                break;
841           case 0x3:
842                newPAP.setJc((byte)param);
843                break;
844           case 0x4:
845                newPAP.setFSideBySide((byte)param);
846                break;
847           case 0x5:
848                newPAP.setFKeep((byte)param);
849                break;
850           case 0x6:
851                newPAP.setFKeepFollow((byte)param);
852                break;
853           case 0x7:
854                newPAP.setFPageBreakBefore((byte)param);
855                break;
856           case 0x8:
857                newPAP.setBrcl((byte)param);
858                break;
859           case 0x9:
860                newPAP.setBrcp((byte)param);
861                break;
862           case 0xa:
863                newPAP.setIlvl((byte)param);
864                break;
865           case 0xb:
866                newPAP.setIlfo(param);
867                break;
868           case 0xc:
869                newPAP.setFNoLnn((byte)param);
870                break;
871           case 0xd:
872                /**@todo handle tabs*/
873                break;
874           case 0xe:
875                newPAP.setDxaRight(param);
876                break;
877           case 0xf:
878                newPAP.setDxaLeft(param);
879                break;
880           case 0x10:
881                newPAP.setDxaLeft(newPAP.getDxaLeft() + param);
882                newPAP.setDxaLeft(Math.max(0, newPAP.getDxaLeft()));
883                break;
884           case 0x11:
885                newPAP.setDxaLeft1(param);
886                break;
887           case 0x12:
888                short[] lspd = newPAP.getLspd();
889                lspd[0] = LittleEndian.getShort(grpprl, offset - 4);
890                lspd[1] = LittleEndian.getShort(grpprl, offset - 2);
891                break;
892           case 0x13:
893                newPAP.setDyaBefore(param);
894                break;
895           case 0x14:
896                newPAP.setDyaAfter(param);
897                break;
898           case 0x15:
899                /**@todo handle tabs*/
900                break;
901           case 0x16:
902                newPAP.setFInTable((byte)param);
903                break;
904           case 0x17:
905                newPAP.setFTtp((byte)param);
906                break;
907           case 0x18:
908                newPAP.setDxaAbs(param);
909                break;
910           case 0x19:
911                newPAP.setDyaAbs(param);
912                break;
913           case 0x1a:
914                newPAP.setDxaWidth(param);
915                break;
916           case 0x1b:
917                /** @todo handle paragraph postioning*/
918                /*byte pcVert = (param & 0x0c) >> 2;
919                byte pcHorz = param & 0x03;
920                if(pcVert != 3)
921                {
922                   newPAP._pcVert = pcVert;
923                }
924                if(pcHorz != 3)
925                {
926                   newPAP._pcHorz = pcHorz;
927                }*/

928                break;
929           case 0x1c:
930                //newPAP.setBrcTop1((short)param);
931
break;
932           case 0x1d:
933                //newPAP.setBrcLeft1((short)param);
934
break;
935           case 0x1e:
936                //newPAP.setBrcBottom1((short)param);
937
break;
938           case 0x1f:
939                //newPAP.setBrcRight1((short)param);
940
break;
941           case 0x20:
942                //newPAP.setBrcBetween1((short)param);
943
break;
944           case 0x21:
945                //newPAP.setBrcBar1((byte)param);
946
break;
947           case 0x22:
948                newPAP.setDxaFromText(param);
949                break;
950           case 0x23:
951                newPAP.setWr((byte)param);
952                break;
953           case 0x24:
954                short[] brcTop = newPAP.getBrcTop();
955                brcTop[0] = (short)LittleEndian.getShort(grpprl, offset - 4);
956                brcTop[1] = (short)LittleEndian.getShort(grpprl, offset - 2);
957                break;
958           case 0x25:
959                short[] brcLeft = newPAP.getBrcLeft();
960                brcLeft[0] = (short)LittleEndian.getShort(grpprl, offset - 4);
961                brcLeft[1] = (short)LittleEndian.getShort(grpprl, offset - 2);
962                break;
963           case 0x26:
964                short[] brcBottom = newPAP.getBrcBottom();
965                brcBottom[0] = (short)LittleEndian.getShort(grpprl, offset - 4);
966                brcBottom[1] = (short)LittleEndian.getShort(grpprl, offset - 2);
967                break;
968           case 0x27:
969                short[] brcRight = newPAP.getBrcRight();
970                brcRight[0] = (short)LittleEndian.getShort(grpprl, offset - 4);
971                brcRight[1] = (short)LittleEndian.getShort(grpprl, offset - 2);
972                break;
973           case 0x28:
974                short[] brcBetween = newPAP.getBrcBetween();
975                brcBetween[0] = (short)LittleEndian.getShort(grpprl, offset - 4);
976                brcBetween[1] = (short)LittleEndian.getShort(grpprl, offset - 2);
977                break;
978           case 0x29:
979                short[] brcBar = newPAP.getBrcBar();
980                brcBar[0] = (short)LittleEndian.getShort(grpprl, offset - 4);
981                brcBar[1] = (short)LittleEndian.getShort(grpprl, offset - 2);
982                break;
983           case 0x2a:
984                newPAP.setFNoAutoHyph((byte)param);
985                break;
986           case 0x2b:
987                newPAP.setDyaHeight(param);
988                break;
989           case 0x2c:
990                newPAP.setDcs((short)param);
991                break;
992           case 0x2d:
993                newPAP.setShd((short)param);
994                break;
995           case 0x2e:
996                newPAP.setDyaFromText(param);
997                break;
998           case 0x2f:
999                newPAP.setDxaFromText(param);
1000               break;
1001          case 0x30:
1002               newPAP.setFLocked((byte)param);
1003               break;
1004          case 0x31:
1005               newPAP.setFWidowControl((byte)param);
1006               break;
1007          case 0x32:
1008               //undocumented
1009
break;
1010          case 0x33:
1011               newPAP.setFKinsoku((byte)param);
1012               break;
1013          case 0x34:
1014               newPAP.setFWordWrap((byte)param);
1015               break;
1016          case 0x35:
1017               newPAP.setFOverflowPunct((byte)param);
1018               break;
1019          case 0x36:
1020               newPAP.setFTopLinePunct((byte)param);
1021               break;
1022          case 0x37:
1023               newPAP.setFAutoSpaceDE((byte)param);
1024               break;
1025          case 0x38:
1026               newPAP.setFAutoSpaceDN((byte)param);
1027               break;
1028          case 0x39:
1029               newPAP.setWAlignFont(param);
1030               break;
1031          case 0x3a:
1032               newPAP.setFontAlign((short)param);
1033               break;
1034          case 0x3b:
1035               //obsolete
1036
break;
1037          case 0x3e:
1038               newPAP.setAnld(varParam);
1039               break;
1040          case 0x3f:
1041               //don't really need this. spec is confusing regarding this
1042
//sprm
1043
break;
1044          case 0x40:
1045               //newPAP._lvl = param;
1046
break;
1047          case 0x41:
1048               //?
1049
break;
1050          case 0x43:
1051               //?
1052
break;
1053          case 0x44:
1054               //?
1055
break;
1056          case 0x45:
1057               if(spra == 6)
1058               {
1059                  newPAP.setNumrm(varParam);
1060               }
1061               else
1062               {
1063                  /**@todo handle large PAPX from data stream*/
1064               }
1065               break;
1066
1067          case 0x47:
1068               newPAP.setFUsePgsuSettings((byte)param);
1069               break;
1070          case 0x48:
1071               newPAP.setFAdjustRight((byte)param);
1072               break;
1073          default:
1074               break;
1075      }
1076  }
1077  /**
1078   * Used to uncompress a table property. Performs an operation defined
1079   * by a sprm stored in a tapx.
1080   *
1081   * @param newTAP The TableProperties object to perform the operation on.
1082   * @param operand The operand that defines this operation.
1083   * @param param The parameter for this operation.
1084   * @param varParam Variable length parameter for this operation.
1085   */

1086  static void doTAPOperation(TableProperties newTAP, int operand, int param, byte[] varParam)
1087  {
1088      switch(operand)
1089      {
1090          case 0:
1091               newTAP.setJc((short)param);
1092               break;
1093          case 0x01:
1094          {
1095               short[] rgdxaCenter = newTAP.getRgdxaCenter();
1096               short itcMac = newTAP.getItcMac();
1097               int adjust = param - (rgdxaCenter[0] + newTAP.getDxaGapHalf());
1098               for(int x = 0; x < itcMac; x++)
1099               {
1100                  rgdxaCenter[x] += adjust;
1101               }
1102               break;
1103          }
1104          case 0x02:
1105          {
1106               short[] rgdxaCenter = newTAP.getRgdxaCenter();
1107               if(rgdxaCenter != null)
1108               {
1109                 int adjust = newTAP.getDxaGapHalf() - param;
1110                 rgdxaCenter[0] += adjust;
1111               }
1112               newTAP.setDxaGapHalf(param);
1113               break;
1114          }
1115          case 0x03:
1116               newTAP.setFCantSplit(getFlag(param));
1117               break;
1118          case 0x04:
1119               newTAP.setFTableHeader(getFlag(param));
1120               break;
1121          case 0x05:
1122          {
1123               short[] brcTop = newTAP.getBrcTop();
1124               short[] brcLeft = newTAP.getBrcLeft();
1125               short[] brcBottom = newTAP.getBrcBottom();
1126               short[] brcRight = newTAP.getBrcRight();
1127               short[] brcVertical = newTAP.getBrcVertical();
1128               short[] brcHorizontal = newTAP.getBrcHorizontal();
1129
1130               brcTop[0] = LittleEndian.getShort(varParam, 0);
1131               brcTop[1] = LittleEndian.getShort(varParam, 2);
1132
1133               brcLeft[0] = LittleEndian.getShort(varParam, 4);
1134               brcLeft[1] = LittleEndian.getShort(varParam, 6);
1135
1136               brcBottom[0] = LittleEndian.getShort(varParam, 8);
1137               brcBottom[1] = LittleEndian.getShort(varParam, 10);
1138
1139               brcRight[0] = LittleEndian.getShort(varParam, 12);
1140               brcRight[1] = LittleEndian.getShort(varParam, 14);
1141
1142               brcHorizontal[0] = LittleEndian.getShort(varParam, 16);
1143               brcHorizontal[1] = LittleEndian.getShort(varParam, 18);
1144
1145               brcVertical[0] = LittleEndian.getShort(varParam, 20);
1146               brcVertical[1] = LittleEndian.getShort(varParam, 22);
1147               break;
1148          }
1149          case 0x06:
1150               //obsolete, used in word 1.x
1151
break;
1152          case 0x07:
1153               newTAP.setDyaRowHeight(param);
1154               break;
1155          case 0x08:
1156          {
1157               short[] rgdxaCenter = new short[varParam[0] + 1];
1158               TableCellDescriptor[] rgtc = new TableCellDescriptor[varParam[0]];
1159               short itcMac = varParam[0];
1160               //I use varParam[0] and newTAP._itcMac interchangably
1161
newTAP.setItcMac(itcMac);
1162               newTAP.setRgdxaCenter(rgdxaCenter) ;
1163               newTAP.setRgtc(rgtc);
1164
1165               for(int x = 0; x < itcMac; x++)
1166               {
1167                 rgdxaCenter[x] = LittleEndian.getShort(varParam , 1 + (x * 2));
1168                 rgtc[x] = TableCellDescriptor.convertBytesToTC(varParam, 1 + ((itcMac + 1) * 2) + (x * 20));
1169               }
1170               rgdxaCenter[itcMac] = LittleEndian.getShort(varParam , 1 + (itcMac * 2));
1171               break;
1172          }
1173          case 0x09:
1174               /** @todo handle cell shading*/
1175               break;
1176          case 0x0a:
1177               /** @todo handle word defined table styles*/
1178               break;
1179          case 0x20:
1180          {
1181               TCAbstractType[] rgtc = newTAP.getRgtc();
1182
1183               for(int x = varParam[0]; x < varParam[1]; x++)
1184               {
1185
1186                 if((varParam[2] & 0x08) > 0)
1187                 {
1188                   short[] brcRight = rgtc[x].getBrcRight();
1189                   brcRight[0] = LittleEndian.getShort(varParam, 6);
1190                   brcRight[1] = LittleEndian.getShort(varParam, 8);
1191                 }
1192                 else if((varParam[2] & 0x04) > 0)
1193                 {
1194                   short[] brcBottom = rgtc[x].getBrcBottom();
1195                   brcBottom[0] = LittleEndian.getShort(varParam, 6);
1196                   brcBottom[1] = LittleEndian.getShort(varParam, 8);
1197                 }
1198                 else if((varParam[2] & 0x02) > 0)
1199                 {
1200                   short[] brcLeft = rgtc[x].getBrcLeft();
1201                   brcLeft[0] = LittleEndian.getShort(varParam, 6);
1202                   brcLeft[1] = LittleEndian.getShort(varParam, 8);
1203                 }
1204                 else if((varParam[2] & 0x01) > 0)
1205                 {
1206                   short[] brcTop = rgtc[x].getBrcTop();
1207                   brcTop[0] = LittleEndian.getShort(varParam, 6);
1208                   brcTop[1] = LittleEndian.getShort(varParam, 8);
1209                 }
1210               }
1211               break;
1212          }
1213          case 0x21:
1214               int index = (param & 0xff000000) >> 24;
1215               int count = (param & 0x00ff0000) >> 16;
1216               int width = (param & 0x0000ffff);
1217               int itcMac = newTAP.getItcMac();
1218
1219               short[] rgdxaCenter = new short[itcMac + count + 1];
1220               TableCellDescriptor[] rgtc = new TableCellDescriptor[itcMac + count];
1221               if(index >= itcMac)
1222               {
1223                 index = itcMac;
1224                 System.arraycopy(newTAP.getRgdxaCenter(), 0, rgdxaCenter, 0, itcMac + 1);
1225                 System.arraycopy(newTAP.getRgtc(), 0, rgtc, 0, itcMac);
1226               }
1227               else
1228               {
1229                 //copy rgdxaCenter
1230
System.arraycopy(newTAP.getRgdxaCenter(), 0, rgdxaCenter, 0, index + 1);
1231                 System.arraycopy(newTAP.getRgdxaCenter(), index + 1, rgdxaCenter, index + count, itcMac - (index));
1232                 //copy rgtc
1233
System.arraycopy(newTAP.getRgtc(), 0, rgtc, 0, index);
1234                 System.arraycopy(newTAP.getRgtc(), index, rgtc, index + count, itcMac - index);
1235               }
1236
1237               for(int x = index; x < index + count; x++)
1238               {
1239                 rgtc[x] = new TableCellDescriptor();
1240                 rgdxaCenter[x] = (short)(rgdxaCenter[x-1] + width);
1241               }
1242               rgdxaCenter[index + count] = (short)(rgdxaCenter[(index + count)-1] + width);
1243               break;
1244          /**@todo handle table sprms from complex files*/
1245          case 0x22:
1246          case 0x23:
1247          case 0x24:
1248          case 0x25:
1249          case 0x26:
1250          case 0x27:
1251          case 0x28:
1252          case 0x29:
1253          case 0x2a:
1254          case 0x2b:
1255          case 0x2c:
1256               break;
1257          default:
1258               break;
1259      }
1260  }
1261  /**
1262   * Used in decompression of a sepx. This performs an operation defined by
1263   * a single sprm.
1264   *
1265   * @param newSEP The SectionProperty to perfrom the operation on.
1266   * @param operand The operation to perform.
1267   * @param param The operation's parameter.
1268   * @param varParam The operation variable length parameter.
1269   */

1270  static void doSEPOperation(SectionProperties newSEP, int operand, int param, byte[] varParam)
1271  {
1272      switch(operand)
1273      {
1274          case 0:
1275               newSEP.setCnsPgn((byte)param);
1276               break;
1277          case 0x1:
1278               newSEP.setIHeadingPgn((byte)param);
1279               break;
1280          case 0x2:
1281               newSEP.setOlstAnm(varParam);
1282               break;
1283          case 0x3:
1284               //not quite sure
1285
break;
1286          case 0x4:
1287               //not quite sure
1288
break;
1289          case 0x5:
1290               newSEP.setFEvenlySpaced(getFlag(param));
1291               break;
1292          case 0x6:
1293               newSEP.setFUnlocked(getFlag(param));
1294               break;
1295          case 0x7:
1296               newSEP.setDmBinFirst((short)param);
1297               break;
1298          case 0x8:
1299               newSEP.setDmBinOther((short)param);
1300               break;
1301          case 0x9:
1302               newSEP.setBkc((byte)param);
1303               break;
1304          case 0xa:
1305               newSEP.setFTitlePage(getFlag(param));
1306               break;
1307          case 0xb:
1308               newSEP.setCcolM1((short)param);
1309               break;
1310          case 0xc:
1311               newSEP.setDxaColumns(param);
1312               break;
1313          case 0xd:
1314               newSEP.setFAutoPgn(getFlag(param));
1315               break;
1316          case 0xe:
1317               newSEP.setNfcPgn((byte)param);
1318               break;
1319          case 0xf:
1320               newSEP.setDyaPgn((short)param);
1321               break;
1322          case 0x10:
1323               newSEP.setDxaPgn((short)param);
1324               break;
1325          case 0x11:
1326               newSEP.setFPgnRestart(getFlag(param));
1327               break;
1328          case 0x12:
1329               newSEP.setFEndNote(getFlag(param));
1330               break;
1331          case 0x13:
1332               newSEP.setLnc((byte)param);
1333               break;
1334          case 0x14:
1335               newSEP.setGrpfIhdt((byte)param);
1336               break;
1337          case 0x15:
1338               newSEP.setNLnnMod((short)param);
1339               break;
1340          case 0x16:
1341               newSEP.setDxaLnn(param);
1342               break;
1343          case 0x17:
1344               newSEP.setDyaHdrTop(param);
1345               break;
1346          case 0x18:
1347               newSEP.setDyaHdrBottom(param);
1348               break;
1349          case 0x19:
1350               newSEP.setFLBetween(getFlag(param));
1351               break;
1352          case 0x1a:
1353               newSEP.setVjc((byte)param);
1354               break;
1355          case 0x1b:
1356               newSEP.setLnnMin((short)param);
1357               break;
1358          case 0x1c:
1359               newSEP.setPgnStart((short)param);
1360               break;
1361          case 0x1d:
1362               newSEP.setDmOrientPage((byte)param);
1363               break;
1364          case 0x1e:
1365               //nothing
1366
break;
1367          case 0x1f:
1368               newSEP.setXaPage(param);
1369               break;
1370          case 0x20:
1371               newSEP.setYaPage(param);
1372               break;
1373          case 0x21:
1374               newSEP.setDxaLeft(param);
1375               break;
1376          case 0x22:
1377               newSEP.setDxaRight(param);
1378               break;
1379          case 0x23:
1380               newSEP.setDyaTop(param);
1381               break;
1382          case 0x24:
1383               newSEP.setDyaBottom(param);
1384               break;
1385          case 0x25:
1386               newSEP.setDzaGutter(param);
1387               break;
1388          case 0x26:
1389               newSEP.setDmPaperReq((short)param);
1390               break;
1391          case 0x27:
1392               newSEP.setFPropMark(getFlag(varParam[0]));
1393               break;
1394          case 0x28:
1395               break;
1396          case 0x29:
1397               break;
1398          case 0x2a:
1399               break;
1400          case 0x2b:
1401               short[] brcTop = newSEP.getBrcTop();
1402               brcTop[0] = (short)(param & 0xffff);
1403               brcTop[1] = (short)((param & 0xffff0000) >> 16);
1404               break;
1405          case 0x2c:
1406               short[] brcLeft = newSEP.getBrcLeft();
1407               brcLeft[0] = (short)(param & 0xffff);
1408               brcLeft[1] = (short)((param & 0xffff0000) >> 16);
1409               break;
1410          case 0x2d:
1411               short[] brcBottom = newSEP.getBrcBottom();
1412               brcBottom[0] = (short)(param & 0xffff);
1413               brcBottom[1] = (short)((param & 0xffff0000) >> 16);
1414               break;
1415          case 0x2e:
1416               short[] brcRight = newSEP.getBrcRight();
1417               brcRight[0] = (short)(param & 0xffff);
1418               brcRight[1] = (short)((param & 0xffff0000) >> 16);
1419               break;
1420          case 0x2f:
1421               newSEP.setPgbProp(param);
1422               break;
1423          case 0x30:
1424               newSEP.setDxtCharSpace(param);
1425               break;
1426          case 0x31:
1427               newSEP.setDyaLinePitch(param);
1428               break;
1429          case 0x33:
1430               newSEP.setWTextFlow((short)param);
1431               break;
1432          default:
1433               break;
1434      }
1435
1436  }
1437  /**
1438   * Converts an byte value into a boolean. The byte parameter can be 1,0, 128,
1439   * or 129. if it is 128, this function returns the same value as oldVal. If
1440   * it is 129, this function returns !oldVal. This is used for certain sprms
1441   *
1442   * @param x The byte value to convert.
1443   * @param oldVal The old boolean value.
1444   *
1445   * @return A boolean whose value depends on x and oldVal.
1446   */

1447  private static boolean getCHPFlag(byte x, boolean oldVal)
1448  {
1449      switch(x)
1450      {
1451          case 0:
1452               return false;
1453          case 1:
1454               return true;
1455          case (byte)0x80:
1456               return oldVal;
1457          case (byte)0x81:
1458               return !oldVal;
1459          default:
1460               return false;
1461      }
1462  }
1463
1464  /**
1465   * Converts an int into a boolean. If the int is non-zero, it returns true.
1466   * Otherwise it returns false.
1467   *
1468   * @param x The int to convert.
1469   *
1470   * @return A boolean whose value depends on x.
1471   */

1472  public static boolean getFlag(int x)
1473  {
1474      if(x != 0)
1475      {
1476          return true;
1477      }
1478      else
1479      {
1480          return false;
1481      }
1482  }
1483}
1484
Popular Tags