/// <summary> /// Parses the given StreamReader to retrieve a LVL struct /// </summary> /// <param name="bytes"></param> public ListLevel(VirtualStreamReader reader, int length) : base(reader, length) { long startPos = _reader.BaseStream.Position; //parse the fix part this.iStartAt = _reader.ReadInt32(); this.nfc = _reader.ReadByte(); int flag = _reader.ReadByte(); this.jc = (byte)(flag & 0x03); this.fLegal = Utils.BitmaskToBool(flag, 0x04); this.fNoRestart = Utils.BitmaskToBool(flag, 0x08); this.fPrev = Utils.BitmaskToBool(flag, 0x10); this.fPrevSpace = Utils.BitmaskToBool(flag, 0x20); this.fWord6 = Utils.BitmaskToBool(flag, 0x40); this.rgbxchNums = new byte[9]; for (int i = 0; i < 9; i++) { rgbxchNums[i] = _reader.ReadByte(); } this.ixchFollow = (FollowingChar)_reader.ReadByte(); this.dxaSpace = _reader.ReadInt32(); this.dxaIndent = _reader.ReadInt32(); this.cbGrpprlChpx = _reader.ReadByte(); this.cbGrpprlPapx = _reader.ReadByte(); this.ilvlRestartLim = _reader.ReadByte(); this.grfhic = _reader.ReadByte(); //parse the variable part //read the group of papx sprms //this papx has no istd, so use PX to parse it PropertyExceptions px = new PropertyExceptions(_reader.ReadBytes(this.cbGrpprlPapx)); this.grpprlPapx = new ParagraphPropertyExceptions(); this.grpprlPapx.grpprl = px.grpprl; //read the group of chpx sprms this.grpprlChpx = new CharacterPropertyExceptions(_reader.ReadBytes(this.cbGrpprlChpx)); //read the number text Int16 strLen = _reader.ReadInt16(); this.xst = Encoding.Unicode.GetString(_reader.ReadBytes(strLen * 2)); long endPos = _reader.BaseStream.Position; _reader.BaseStream.Seek(startPos, System.IO.SeekOrigin.Begin); _rawBytes = _reader.ReadBytes((int)(endPos - startPos)); }
/// <summary> /// Extracts the TAPX SPRMs out of a PAPX /// </summary> /// <param name="papx"></param> public TablePropertyExceptions(ParagraphPropertyExceptions papx, VirtualStream dataStream) { this.grpprl = new List <SinglePropertyModifier>(); foreach (SinglePropertyModifier sprm in papx.grpprl) { if (sprm.Type == SinglePropertyModifier.SprmType.TAP) { this.grpprl.Add(sprm); } else if ((int)sprm.OpCode == 0x646b) { IStreamReader reader = new VirtualStreamReader(dataStream); //there is a native TAP in the data stream UInt32 fc = System.BitConverter.ToUInt32(sprm.Arguments, 0); //get the size of the following grpprl //byte[] sizebytes = new byte[2]; //dataStream.Read(sizebytes, 2, (int)fc); byte[] sizebytes = reader.ReadBytes(fc, 2); UInt16 grpprlSize = System.BitConverter.ToUInt16(sizebytes, 0); //read the grpprl //byte[] grpprlBytes = new byte[grpprlSize]; //dataStream.Read(grpprlBytes); byte[] grpprlBytes = reader.ReadBytes(grpprlSize); //parse the grpprl PropertyExceptions externalPx = new PropertyExceptions(grpprlBytes); foreach (SinglePropertyModifier sprmExternal in externalPx.grpprl) { if (sprmExternal.Type == SinglePropertyModifier.SprmType.TAP) { this.grpprl.Add(sprmExternal); } } } } }
/// <summary> /// Builds a CHP based on a CHPX /// </summary> /// <param name="styles">The stylesheet</param> /// <param name="chpx">The CHPX</param> public CharacterProperties(CharacterPropertyExceptions chpx, ParagraphPropertyExceptions parentPapx, WordDocument parentDocument) { setDefaultValues(); //get all CHPX in the hierarchy List <CharacterPropertyExceptions> chpxHierarchy = new List <CharacterPropertyExceptions>(); chpxHierarchy.Add(chpx); //add parent character styles buildHierarchy(chpxHierarchy, parentDocument.Styles, (UInt16)getIsdt(chpx)); //add parent paragraph styles buildHierarchy(chpxHierarchy, parentDocument.Styles, parentPapx.istd); chpxHierarchy.Reverse(); //apply the CHPX hierarchy to this CHP foreach (CharacterPropertyExceptions c in chpxHierarchy) { applyChpx(c, parentDocument); } }
/// <summary> /// Parses the bytes to retrieve a StyleSheetDescription /// </summary> /// <param name="bytes">The bytes</param> /// <param name="cbStdBase"></param> /// <param name="dataStream">The "Data" stream (optional, can be null)</param> public StyleSheetDescription(byte[] bytes, int cbStdBase, VirtualStream dataStream) { BitArray bits = new BitArray(bytes); //parsing the base (fix part) if (cbStdBase >= 2) { //sti BitArray stiBits = Utils.BitArrayCopy(bits, 0, 12); this.sti = (StyleIdentifier)Utils.BitArrayToUInt32(stiBits); //flags this.fScratch = bits[12]; this.fInvalHeight = bits[13]; this.fHasUpe = bits[14]; this.fMassCopy = bits[15]; } if (cbStdBase >= 4) { //stk BitArray stkBits = Utils.BitArrayCopy(bits, 16, 4); this.stk = (StyleKind)Utils.BitArrayToUInt32(stkBits); //istdBase BitArray istdBits = Utils.BitArrayCopy(bits, 20, 12); this.istdBase = (UInt32)Utils.BitArrayToUInt32(istdBits); } if (cbStdBase >= 6) { //cupx BitArray cupxBits = Utils.BitArrayCopy(bits, 32, 4); this.cupx = (UInt16)Utils.BitArrayToUInt32(cupxBits); //istdNext BitArray istdNextBits = Utils.BitArrayCopy(bits, 36, 12); this.istdNext = (UInt32)Utils.BitArrayToUInt32(istdNextBits); } if (cbStdBase >= 8) { //bchUpe BitArray bchBits = Utils.BitArrayCopy(bits, 48, 16); this.bchUpe = (UInt16)Utils.BitArrayToUInt32(bchBits); } if (cbStdBase >= 10) { //flags this.fAutoRedef = bits[64]; this.fHidden = bits[65]; this.f97LidsSet = bits[66]; this.fCopyLang = bits[67]; this.fPersonalCompose = bits[68]; this.fPersonalReply = bits[69]; this.fPersonal = bits[70]; this.fNoHtmlExport = bits[71]; this.fSemiHidden = bits[72]; this.fLocked = bits[73]; this.fInternalUse = bits[74]; } if (cbStdBase >= 12) { //istdLink BitArray istdLinkBits = Utils.BitArrayCopy(bits, 80, 12); this.istdLink = (UInt32)Utils.BitArrayToUInt32(istdLinkBits); //fHasOriginalStyle this.fHasOriginalStyle = bits[92]; } if (cbStdBase >= 16) { //rsid BitArray rsidBits = Utils.BitArrayCopy(bits, 96, 32); this.rsid = Utils.BitArrayToUInt32(rsidBits); } //parsing the variable part //xstz byte characterCount = bytes[cbStdBase]; //characters are zero-terminated, so 1 char has 2 bytes: byte[] name = new byte[characterCount * 2]; Array.Copy(bytes, cbStdBase + 2, name, 0, name.Length); //remove zero-termination this.xstzName = Encoding.Unicode.GetString(name); //parse the UPX structs int upxOffset = cbStdBase + 1 + (characterCount * 2) + 2; for (int i = 0; i < this.cupx; i++) { //find the next even byte border if (upxOffset % 2 != 0) { upxOffset++; } //get the count of bytes for UPX UInt16 cbUPX = System.BitConverter.ToUInt16(bytes, upxOffset); if (cbUPX > 0) { //copy the bytes byte[] upxBytes = new byte[cbUPX]; Array.Copy(bytes, upxOffset + 2, upxBytes, 0, upxBytes.Length); if (this.stk == StyleKind.table) { //first upx is TAPX; second PAPX, third CHPX switch (i) { case 0: this.tapx = new TablePropertyExceptions(upxBytes); break; case 1: this.papx = new ParagraphPropertyExceptions(upxBytes, dataStream); break; case 2: this.chpx = new CharacterPropertyExceptions(upxBytes); break; } } else if (this.stk == StyleKind.paragraph) { //first upx is PAPX, second CHPX switch (i) { case 0: this.papx = new ParagraphPropertyExceptions(upxBytes, dataStream); break; case 1: this.chpx = new CharacterPropertyExceptions(upxBytes); break; } } else if (this.stk == StyleKind.list) { //list styles have only one PAPX switch (i) { case 0: this.papx = new ParagraphPropertyExceptions(upxBytes, dataStream); break; } } else if (this.stk == StyleKind.character) { //character styles have only one CHPX switch (i) { case 0: this.chpx = new CharacterPropertyExceptions(upxBytes); break; } } } //increase the offset for the next run upxOffset += (2 + cbUPX); } }