Esempio n. 1
0
        public void TestReadWrite()
        {
            FileInformationBlock fib = _hWPFDocFixture._fib;

            byte[] tableStream = _hWPFDocFixture._tableStream;

            int listOffset = fib.GetFcPlcfLst();
            int lfoOffset  = fib.GetFcPlfLfo();

            if (listOffset != 0 && fib.GetLcbPlcfLst() != 0)
            {
                ListTables listTables = new ListTables(tableStream, fib.GetFcPlcfLst(),
                                                       fib.GetFcPlfLfo());
                HWPFFileSystem fileSys = new HWPFFileSystem();

                HWPFStream tableOut = fileSys.GetStream("1Table");

                listTables.WriteListDataTo(tableOut);
                int offset = tableOut.Offset;
                listTables.WriteListOverridesTo(tableOut);

                ListTables newTables = new ListTables(tableOut.ToArray(), 0, offset);

                Assert.AreEqual(listTables, newTables);
            }
        }
Esempio n. 2
0
        public static int Write(HWPFStream tableStream, String[] entries)
        {
            byte[] header = new byte[6];
            LittleEndian.PutShort(header, 0, unchecked((short)0xffff));

            if (entries == null || entries.Length == 0)
            {
                LittleEndian.PutInt(header, 2, 0);
                tableStream.Write(header);
                return 6;
            }

            LittleEndian.PutInt(header, 2, entries.Length);
            tableStream.Write(header);
            int size = 6;

            foreach (String entry in entries)
            {
                byte[] buf = new byte[entry.Length * 2 + 2];
                LittleEndian.PutShort(buf, 0, (short)entry.Length);
                StringUtil.PutUnicodeLE(entry, buf, 2);
                tableStream.Write(buf);
                size += buf.Length;
            }

            return size;
        }
Esempio n. 3
0
        public void WriteRef(FileInformationBlock fib, HWPFStream tableStream)
        {
            if (descriptors == null || descriptors.Length == 0)
            {
                fib.SetNotesDescriptorsOffset(noteType, tableStream.Offset);
                fib.SetNotesDescriptorsSize(noteType, 0);
                return;
            }

            int start = tableStream.Offset;
            byte[] data = descriptors.ToByteArray();
            tableStream.Write(data);
            int end =tableStream.Offset;

            fib.SetNotesDescriptorsOffset(noteType, start);
            fib.SetNotesDescriptorsSize(noteType, end - start);
        }
Esempio n. 4
0
        public void TestReadWrite()
        {
            FileInformationBlock fib = _hWPFDocFixture._fib;

            byte[] tableStream = _hWPFDocFixture._tableStream;

            int fcSttbfffn  = fib.GetFcSttbfffn();
            int lcbSttbfffn = fib.GetLcbSttbfffn();

            _fontTable = new FontTable(tableStream, fcSttbfffn, lcbSttbfffn);

            HWPFFileSystem fileSys = new HWPFFileSystem();

            _fontTable.WriteTo(fileSys);
            HWPFStream tableOut = fileSys.GetStream("1Table");


            byte[] newTableStream = tableOut.ToArray();


            FontTable newFontTable = new FontTable(newTableStream, 0, newTableStream.Length);

            Assert.IsTrue(_fontTable.Equals(newFontTable));
        }
Esempio n. 5
0
        public void WriteTo(byte[] mainStream, HWPFStream tableStream)
        {
            //HWPFOutputStream mainDocument = sys.GetStream("WordDocument");
            //HWPFOutputStream tableStream = sys.GetStream("1Table");

            base.Serialize(mainStream, 0);

            int size = base.GetSize();
            _shortHandler.Serialize(mainStream);
            _longHandler.Serialize(mainStream, size + _shortHandler.SizeInBytes());
            _fieldHandler.WriteTo(mainStream,
              base.GetSize() + _shortHandler.SizeInBytes() + _longHandler.SizeInBytes(), tableStream);

        }
Esempio n. 6
0
        public void WriteTxt(FileInformationBlock fib, HWPFStream tableStream)
        {
            if (textPositions == null || textPositions.Length == 0)
            {
                fib.SetNotesTextPositionsOffset(noteType, tableStream.Offset);
                fib.SetNotesTextPositionsSize(noteType, 0);
                return;
            }

            int start = tableStream.Offset;
            byte[] data = textPositions.ToByteArray();            
            tableStream.Write(data);
            int end = tableStream.Offset;

            fib.SetNotesTextPositionsOffset(noteType, start);
            fib.SetNotesTextPositionsSize(noteType, end - start);
        }
Esempio n. 7
0
        private int SavePlex(FileInformationBlock fib, FieldsDocumentPart part,
                PlexOfCps plexOfCps, HWPFStream outputStream)
        {
            if (plexOfCps == null || plexOfCps.Length == 0)
            {
                fib.SetFieldsPlcfOffset(part, outputStream.Offset);
                fib.SetFieldsPlcfLength(part, 0);
                return 0;
            }

            byte[] data = plexOfCps.ToByteArray();

            int start = outputStream.Offset;
            int length = data.Length;

            outputStream.Write(data);

            fib.SetFieldsPlcfOffset(part, start);
            fib.SetFieldsPlcfLength(part, length);

            return length;
        }
Esempio n. 8
0
        public void WriteListDataTo(HWPFStream tableStream)
        {
            int listSize = _listMap.Count;

            // use this stream as a buffer for the levels since their size varies.
            MemoryStream levelBuf = new MemoryStream();

            byte[] shortHolder = new byte[2];
            LittleEndian.PutShort(shortHolder, (short)listSize);
            tableStream.Write(shortHolder);
            //TODO:: sort the keys
            foreach (int x in _listMap.Keys)
            {
                ListData lst = _listMap[x];
                tableStream.Write(lst.ToArray());
                ListLevel[] lvls = lst.GetLevels();
                for (int y = 0; y < lvls.Length; y++)
                {
                    byte[] bytes = lvls[y].ToArray();
                    levelBuf.Write(bytes, 0, bytes.Length);
                }
            }
            tableStream.Write(levelBuf.ToArray());
        }
Esempio n. 9
0
        internal void WriteTo(byte[] mainStream, int offset, HWPFStream tableStream)
        {
            int length = _fields.Length / 2;
            LittleEndian.PutShort(mainStream, offset, (short)length);
            offset += LittleEndianConsts.SHORT_SIZE;

            for (int x = 0; x < length; x++)
            {
                UnhandledDataStructure ds = (UnhandledDataStructure)_unknownMap[x];
                if (ds != null)
                {
                    LittleEndian.PutInt(mainStream, offset, tableStream.Offset);
                    offset += LittleEndianConsts.INT_SIZE;
                    byte[] buf = ds.GetBuf();
                    tableStream.Write(buf);
                    LittleEndian.PutInt(mainStream, offset, buf.Length);
                    offset += LittleEndianConsts.INT_SIZE;
                }
                else
                {
                    LittleEndian.PutInt(mainStream, offset, _fields[x * 2]);
                    offset += LittleEndianConsts.INT_SIZE;
                    LittleEndian.PutInt(mainStream, offset, _fields[(x * 2) + 1]);
                    offset += LittleEndianConsts.INT_SIZE;
                }
            }
        }
Esempio n. 10
0
        /**
         * Writes this table to the table stream.
         *
         * @param tableStream the table stream to write to.
         * @throws IOException if an error occurs while writing.
         */
        public void WriteTo(HWPFStream tableStream)
        {
            byte[] header = new byte[6];
            LittleEndian.PutShort(header, 0, unknownValue);
            LittleEndian.PutInt(header, 2, entries.Length * 2);
            tableStream.Write(header);

            for (int i = 0; i < entries.Length; i++)
            {
                WriteStringValue(tableStream, entries[i].GetUserName());
                WriteStringValue(tableStream, entries[i].GetSaveLocation());
            }
        }
Esempio n. 11
0
 private void WriteStringValue(HWPFStream tableStream, String value)
 {
     byte[] buf = new byte[value.Length * 2 + 2];
     LittleEndian.PutShort(buf, 0, (short)value.Length);
     StringUtil.PutUnicodeLE(value, buf, 2);
     tableStream.Write(buf);
 }
        /**
         * Writes this table to the table stream.
         * 
         * @param tableStream  the table stream to write to.
         * @throws IOException  if an error occurs while writing.
         */
        public void WriteTo(HWPFStream tableStream)
        {
            byte[] header = new byte[6];
            LittleEndian.PutShort(header, 0, fExtend);
            LittleEndian.PutShort(header, 2, cData);
            LittleEndian.PutShort(header, 4, cbExtra);
            tableStream.Write(header);

            foreach (String name in entries)
            {
                byte[] buf = new byte[name.Length * 2 + 2];
                LittleEndian.PutShort(buf, 0, (short)name.Length);
                StringUtil.PutUnicodeLE(name, buf, 2);
                tableStream.Write(buf);
            }
        }
Esempio n. 13
0
        public void WriteSttbfBkmk(FileInformationBlock fib,
                HWPFStream tableStream)
        {
            if (names == null || names.Length == 0)
            {
                fib.SetFcSttbfbkmk(0);
                fib.SetLcbSttbfbkmk(0);
                return;
            }

            int start = tableStream.Offset;
            SttbfUtils.Write(tableStream, names);
            int end = tableStream.Offset;

            fib.SetFcSttbfbkmk(start);
            fib.SetLcbSttbfbkmk(end - start);
        }
Esempio n. 14
0
        public void WritePlcfBkmkl(FileInformationBlock fib,
                HWPFStream tableStream)
        {
            if (descriptorsLim == null || descriptorsLim.Length == 0)
            {
                fib.SetFcPlcfbkl(0);
                fib.SetLcbPlcfbkl(0);
                return;
            }

            int start = tableStream.Offset;
            tableStream.Write(descriptorsLim.ToByteArray());
            int end = tableStream.Offset;

            fib.SetFcPlcfbkl(start);
            fib.SetLcbPlcfbkl(end - start);
        }
Esempio n. 15
0
        public void WriteListOverridesTo(HWPFStream tableStream)
        {

            // use this stream as a buffer for the levels since their size varies.
            MemoryStream levelBuf = new MemoryStream();

            int size = _overrideList.Count;

            byte[] intHolder = new byte[4];
            LittleEndian.PutInt(intHolder, size);
            tableStream.Write(intHolder);

            for (int x = 0; x < size; x++)
            {
                ListFormatOverride lfo = _overrideList[x];
                tableStream.Write(lfo.ToArray());
                ListFormatOverrideLevel[] lfolvls = lfo.GetLevelOverrides();
                for (int y = 0; y < lfolvls.Length; y++)
                {
                    byte[] bytes = lfolvls[y].ToArray();
                    levelBuf.Write(bytes, 0, bytes.Length);
                }
            }
            tableStream.Write(levelBuf.ToArray());

        }
Esempio n. 16
0
        /**
         * Writes out the word file that is represented by an instance of this class.
         *
         * @param out The OutputStream to write to.
         * @throws IOException If there is an unexpected IOException from the passed
         *         in OutputStream.
         */
        public override void Write(Stream out1)
        {
            // Initialize our streams for writing.
            HWPFFileSystem docSys      = new HWPFFileSystem();
            HWPFStream     mainStream  = docSys.GetStream("WordDocument");
            HWPFStream     tableStream = docSys.GetStream("1Table");
            //HWPFOutputStream dataStream = docSys.GetStream("Data");
            int tableOffset = 0;

            // FileInformationBlock fib = (FileInformationBlock)_fib.Clone();
            // clear the offSets and sizes in our FileInformationBlock.
            _fib.ClearOffsetsSizes();

            // determine the FileInformationBLock size
            int fibSize = _fib.GetSize();

            fibSize += POIFSConstants.SMALLER_BIG_BLOCK_SIZE -
                       (fibSize % POIFSConstants.SMALLER_BIG_BLOCK_SIZE);

            // preserve space for the FileInformationBlock because we will be writing
            // it after we write everything else.
            byte[] placeHolder = new byte[fibSize];
            mainStream.Write(placeHolder);
            int mainOffset = mainStream.Offset;

            // write out the StyleSheet.
            _fib.SetFcStshf(tableOffset);
            _ss.WriteTo(tableStream);
            _fib.SetLcbStshf(tableStream.Offset - tableOffset);
            tableOffset = tableStream.Offset;

            // get fcMin and fcMac because we will be writing the actual text with the
            // complex table.
            int fcMin = mainOffset;

            // write out the Complex table, includes text.
            _fib.SetFcClx(tableOffset);
            _cft.WriteTo(mainStream, tableStream);
            _fib.SetLcbClx(tableStream.Offset - tableOffset);
            tableOffset = tableStream.Offset;
            int fcMac = mainStream.Offset;

            // write out the CHPBinTable.
            _fib.SetFcPlcfbteChpx(tableOffset);
            _cbt.WriteTo(docSys, fcMin);
            _fib.SetLcbPlcfbteChpx(tableStream.Offset - tableOffset);
            tableOffset = tableStream.Offset;


            // write out the PAPBinTable.
            _fib.SetFcPlcfbtePapx(tableOffset);
            _pbt.WriteTo(mainStream, tableStream, _cft.GetTextPieceTable());
            _fib.SetLcbPlcfbtePapx(tableStream.Offset - tableOffset);
            tableOffset = tableStream.Offset;

            /*
             * plcfendRef (endnote reference position table) Written immediately
             * after the previously recorded table if the document contains endnotes
             *
             * plcfendTxt (endnote text position table) Written immediately after
             * the plcfendRef if the document contains endnotes
             *
             * Microsoft Office Word 97-2007 Binary File Format (.doc)
             * Specification; Page 24 of 210
             */
            _endnotesTables.WriteRef(_fib, tableStream);
            _endnotesTables.WriteTxt(_fib, tableStream);
            tableOffset = tableStream.Offset;


            /*
             * plcffndRef (footnote reference position table) Written immediately
             * after the stsh if the document contains footnotes
             *
             * plcffndTxt (footnote text position table) Written immediately after
             * the plcffndRef if the document contains footnotes
             *
             * Microsoft Office Word 97-2007 Binary File Format (.doc)
             * Specification; Page 24 of 210
             */
            _footnotesTables.WriteRef(_fib, tableStream);
            _footnotesTables.WriteTxt(_fib, tableStream);
            tableOffset = tableStream.Offset;


            // write out the SectionTable.
            _fib.SetFcPlcfsed(tableOffset);
            _st.WriteTo(docSys, fcMin);
            _fib.SetLcbPlcfsed(tableStream.Offset - tableOffset);
            tableOffset = tableStream.Offset;

            // write out the list tables
            if (_lt != null)
            {
                _fib.SetFcPlcfLst(tableOffset);
                _lt.WriteListDataTo(tableStream);
                _fib.SetLcbPlcfLst(tableStream.Offset - tableOffset);
            }

            /*
             * plflfo (more list formats) Written immediately after the end of the
             * plcflst and its accompanying data, if there are any lists defined in
             * the document. This consists first of a PL of LFO records, followed by
             * the allocated data (if any) hanging off the LFOs. The allocated data
             * consists of the array of LFOLVLFs for each LFO (and each LFOLVLF is
             * immediately followed by some LVLs).
             *
             * Microsoft Office Word 97-2007 Binary File Format (.doc)
             * Specification; Page 26 of 210
             */

            if (_lt != null)
            {
                _fib.SetFcPlfLfo(tableStream.Offset);
                _lt.WriteListOverridesTo(tableStream);
                _fib.SetLcbPlfLfo(tableStream.Offset - tableOffset);
                tableOffset = tableStream.Offset;
            }

            /*
             * sttbfBkmk (table of bookmark name strings) Written immediately after
             * the previously recorded table, if the document contains bookmarks.
             *
             * Microsoft Office Word 97-2007 Binary File Format (.doc)
             * Specification; Page 27 of 210
             */
            if (_bookmarksTables != null)
            {
                _bookmarksTables.WriteSttbfBkmk(_fib, tableStream);
                tableOffset = tableStream.Offset;
            }

            // write out the saved-by table.
            if (_sbt != null)
            {
                _fib.SetFcSttbSavedBy(tableOffset);
                _sbt.WriteTo(tableStream);
                _fib.SetLcbSttbSavedBy(tableStream.Offset - tableOffset);

                tableOffset = tableStream.Offset;
            }

            // write out the revision mark authors table.
            if (_rmat != null)
            {
                _fib.SetFcSttbfRMark(tableOffset);
                _rmat.WriteTo(tableStream);
                _fib.SetLcbSttbfRMark(tableStream.Offset - tableOffset);

                tableOffset = tableStream.Offset;
            }

            // write out the FontTable.
            _fib.SetFcSttbfffn(tableOffset);
            _ft.WriteTo(docSys);
            _fib.SetLcbSttbfffn(tableStream.Offset - tableOffset);
            tableOffset = tableStream.Offset;

            // write out the DocumentProperties.
            _fib.SetFcDop(tableOffset);
            byte[] buf = new byte[_dop.GetSize()];
            _fib.SetLcbDop(_dop.GetSize());
            _dop.Serialize(buf, 0);
            tableStream.Write(buf);



            // set some variables in the FileInformationBlock.
            _fib.SetFcMin(fcMin);
            _fib.SetFcMac(fcMac);
            _fib.SetCbMac(mainStream.Offset);

            // make sure that the table, doc and data streams use big blocks.
            byte[] mainBuf = mainStream.ToArray();
            if (mainBuf.Length < 4096)
            {
                byte[] tempBuf = new byte[4096];
                Array.Copy(mainBuf, 0, tempBuf, 0, mainBuf.Length);
                mainBuf = tempBuf;
            }

            // write out the FileInformationBlock.
            //_fib.Serialize(mainBuf, 0);
            _fib.WriteTo(mainBuf, tableStream);

            byte[] tableBuf = tableStream.ToArray();
            if (tableBuf.Length < 4096)
            {
                byte[] tempBuf = new byte[4096];
                Array.Copy(tableBuf, 0, tempBuf, 0, tableBuf.Length);
                tableBuf = tempBuf;
            }

            byte[] dataBuf = _dataStream;
            if (dataBuf == null)
            {
                dataBuf = new byte[4096];
            }
            if (dataBuf.Length < 4096)
            {
                byte[] tempBuf = new byte[4096];
                Array.Copy(dataBuf, 0, tempBuf, 0, dataBuf.Length);
                dataBuf = tempBuf;
            }


            // spit out the Word document.
            POIFSFileSystem pfs = new POIFSFileSystem();

            pfs.CreateDocument(new MemoryStream(mainBuf), "WordDocument");
            pfs.CreateDocument(new MemoryStream(tableBuf), "1Table");
            pfs.CreateDocument(new MemoryStream(dataBuf), "Data");
            WriteProperties(pfs);

            pfs.WriteFileSystem(out1);
        }
Esempio n. 17
0
        public void WriteTo(HWPFStream wordDocumentStream,HWPFStream tableStream)
        {
            tableStream.Write(TEXT_PIECE_TABLE_TYPE);

            byte[] table = _tpt.WriteTo(wordDocumentStream);

            byte[] numHolder = new byte[LittleEndianConsts.INT_SIZE];
            LittleEndian.PutInt(numHolder, table.Length);
            tableStream.Write(numHolder);
            tableStream.Write(table);
        }
Esempio n. 18
0
        public void WriteTo(HWPFStream out1)
        {
            int offset = 0;
            // add two bytes so we can prepend the stylesheet w/ its size
            byte[] buf = new byte[_stshiLength + 2];
            LittleEndian.PutShort(buf, offset, (short)_stshiLength);
            offset += LittleEndianConsts.SHORT_SIZE;
            LittleEndian.PutShort(buf, offset, (short)_styleDescriptions.Length);
            offset += LittleEndianConsts.SHORT_SIZE;
            LittleEndian.PutShort(buf, offset, (short)_baseLength);
            offset += LittleEndianConsts.SHORT_SIZE;
            LittleEndian.PutShort(buf, offset, (short)_flags);
            offset += LittleEndianConsts.SHORT_SIZE;
            LittleEndian.PutShort(buf, offset, (short)_maxIndex);
            offset += LittleEndianConsts.SHORT_SIZE;
            LittleEndian.PutShort(buf, offset, (short)_maxFixedIndex);
            offset += LittleEndianConsts.SHORT_SIZE;
            LittleEndian.PutShort(buf, offset, (short)_stylenameVersion);
            offset += LittleEndianConsts.SHORT_SIZE;

            LittleEndian.PutShort(buf, offset, (short)_rgftc[0]);
            offset += LittleEndianConsts.SHORT_SIZE;
            LittleEndian.PutShort(buf, offset, (short)_rgftc[1]);
            offset += LittleEndianConsts.SHORT_SIZE;
            LittleEndian.PutShort(buf, offset, (short)_rgftc[2]);

            out1.Write(buf);

            byte[] sizeHolder = new byte[2];
            for (int x = 0; x < _styleDescriptions.Length; x++)
            {
                if (_styleDescriptions[x] != null)
                {
                    byte[] std = _styleDescriptions[x].ToArray();

                    // adjust the size so it is always on a word boundary
                    LittleEndian.PutShort(sizeHolder, (short)((std.Length) + (std.Length % 2)));
                    out1.Write(sizeHolder);
                    out1.Write(std);

                    // Must always start on a word boundary.
                    if (std.Length % 2 == 1)
                    {
                        out1.Write('\0');
                    }
                }
                else
                {
                    sizeHolder[0] = 0;
                    sizeHolder[1] = 0;
                    out1.Write(sizeHolder);
                }
            }
        }
Esempio n. 19
0
 public void Write(FileInformationBlock fib, HWPFStream tableStream)
 {
     Array values = Enum.GetValues(typeof(FieldsDocumentPart));
     foreach (FieldsDocumentPart part in values)
     {
         PlexOfCps plexOfCps = _tables[part];
         SavePlex(fib, part, plexOfCps, tableStream);
     }
 }
Esempio n. 20
0
        /**
         * Creates a byte array representation of this data structure. Suitable for
         * writing to a Word document.
         *
         * @param fcMin The file offset in the main stream where text begins.
         * @return A byte array representing this data structure.
         */
        internal byte[] ToByteArray(HWPFStream dataStream,
            CharIndexTranslator translator)
        {
            byte[] buf = new byte[512];
            int size = _papxList.Count;
            int grpprlOffset = 0;
            int bxOffset = 0;
            int fcOffset = 0;
            byte[] lastGrpprl = new byte[0];

            // total size is currently the size of one FC
            int totalSize = FC_SIZE;

            int index = 0;
            for (; index < size; index++)
            {
                byte[] grpprl = ((PAPX)_papxList[index]).GetGrpprl();
                int grpprlLength = grpprl.Length;

                // is grpprl huge?
                if (grpprlLength > 488)
                {
                    grpprlLength = 8; // set equal to size of sprmPHugePapx grpprl
                }

                // check to see if we have enough room for an FC, a BX, and the grpprl
                // and the 1 byte size of the grpprl.
                int addition = 0;
                if (!Arrays.Equals(grpprl, lastGrpprl))
                {
                    addition = (FC_SIZE + BX_SIZE + grpprlLength + 1);
                }
                else
                {
                    addition = (FC_SIZE + BX_SIZE);
                }

                totalSize += addition;

                // if size is uneven we will have to add one so the first grpprl falls
                // on a word boundary
                if (totalSize > 511 + (index % 2))
                {
                    totalSize -= addition;
                    break;
                }

                // grpprls must fall on word boundaries
                if (grpprlLength % 2 > 0)
                {
                    totalSize += 1;
                }
                else
                {
                    totalSize += 2;
                }
                lastGrpprl = grpprl;
            }

            // see if we couldn't fit some
            if (index != size)
            {
                _overFlow = new List<PAPX>();
                _overFlow.AddRange(_papxList.GetRange(index, size-index));
            }

            // index should equal number of papxs that will be in this fkp now.
            buf[511] = (byte)index;

            bxOffset = (FC_SIZE * index) + FC_SIZE;
            grpprlOffset = 511;

            PAPX papx = null;
            lastGrpprl = new byte[0];
            for (int x = 0; x < index; x++)
            {
                papx = _papxList[x];
                byte[] phe = papx.GetParagraphHeight().ToArray();
                byte[] grpprl = papx.GetGrpprl();

                // is grpprl huge?
                if (grpprl.Length > 488)
                {
                    /*
                    // if so do we have storage at GetHugeGrpprloffset()
                    int hugeGrpprlOffset = papx.GetHugeGrpprlOffset();
                    if (hugeGrpprlOffset == -1) // then we have no storage...
                    {
                        throw new InvalidOperationException(
                              "This Paragraph has no dataStream storage.");
                    }
                    // we have some storage...

                    // get the size of the existing storage
                    int maxHugeGrpprlSize = LittleEndian.GetUShort(_dataStream, hugeGrpprlOffset);

                    if (maxHugeGrpprlSize < grpprl.Length - 2)
                    { // grpprl.Length-2 because we don't store the istd
                        throw new InvalidOperationException(
                            "This Paragraph's dataStream storage is too small.");
                    }
                   

                    // store grpprl at hugeGrpprlOffset
                    Array.Copy(grpprl, 2, _dataStream, hugeGrpprlOffset + 2,
                                     grpprl.Length - 2); // grpprl.Length-2 because we don't store the istd
                    LittleEndian.PutUShort(_dataStream, hugeGrpprlOffset, grpprl.Length - 2);
                      */

                    byte[] hugePapx = new byte[grpprl.Length - 2];
                    System.Array.Copy(grpprl, 2, hugePapx, 0, grpprl.Length - 2);
                    int dataStreamOffset = dataStream.Offset;
                    dataStream.Write(hugePapx);

                    // grpprl = grpprl Containing only a sprmPHugePapx2
                    int istd = LittleEndian.GetUShort(grpprl, 0);
                    grpprl = new byte[8];
                    LittleEndian.PutUShort(grpprl, 0, istd);
                    LittleEndian.PutUShort(grpprl, 2, 0x6646); // sprmPHugePapx2
                    LittleEndian.PutInt(grpprl, 4, dataStreamOffset);
                }

                bool same = Arrays.Equals(lastGrpprl, grpprl);
                if (!same)
                {
                    grpprlOffset -= (grpprl.Length + (2 - grpprl.Length % 2));
                    grpprlOffset -= (grpprlOffset % 2);
                }
                LittleEndian.PutInt(buf, fcOffset, translator.GetByteIndex(papx.Start));
                buf[bxOffset] = (byte)(grpprlOffset / 2);
                Array.Copy(phe, 0, buf, bxOffset + 1, phe.Length);

                // refer to the section on PAPX in the spec. Places a size on the front
                // of the PAPX. Has to do with how the grpprl stays on word
                // boundaries.
                if (!same)
                {
                    int copyOffset = grpprlOffset;
                    if ((grpprl.Length % 2) > 0)
                    {
                        buf[copyOffset++] = (byte)((grpprl.Length + 1) / 2);
                    }
                    else
                    {
                        buf[++copyOffset] = (byte)((grpprl.Length) / 2);
                        copyOffset++;
                    }
                    Array.Copy(grpprl, 0, buf, copyOffset, grpprl.Length);
                    lastGrpprl = grpprl;
                }

                bxOffset += BX_SIZE;
                fcOffset += FC_SIZE;

            }

            LittleEndian.PutInt(buf, fcOffset, translator.GetByteIndex(papx.End));
            return buf;
        }