public PAPBinTable(byte[] documentStream, byte[] tableStream, byte[] dataStream, int offset, int size, CharIndexTranslator charIndexTranslator) { PlexOfCps binTable = new PlexOfCps(tableStream, offset, size, 4); int length = binTable.Length; for (int x = 0; x < length; x++) { GenericPropertyNode node = binTable.GetProperty(x); int pageNum = LittleEndian.GetInt(node.Bytes); int pageOffset = POIFSConstants.SMALLER_BIG_BLOCK_SIZE * pageNum; PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage(documentStream, dataStream, pageOffset, charIndexTranslator); int fkpSize = pfkp.Size(); for (int y = 0; y < fkpSize; y++) { PAPX papx = pfkp.GetPAPX(y); _paragraphs.Add(papx); } } _dataStream = dataStream; }
public OldPAPBinTable(byte[] documentStream, int OffSet, int size, int fcMin, TextPieceTable tpt) { PlexOfCps binTable = new PlexOfCps(documentStream, OffSet, size, 2); int length = binTable.Length; for (int x = 0; x < length; x++) { GenericPropertyNode node = binTable.GetProperty(x); int pageNum = LittleEndian.GetShort(node.Bytes); int pageOffset = POIFSConstants.SMALLER_BIG_BLOCK_SIZE * pageNum; PAPFormattedDiskPage pfkp = new PAPFormattedDiskPage(documentStream, documentStream, pageOffset, tpt); int fkpSize = pfkp.Size(); for (int y = 0; y < fkpSize; y++) { PAPX papx = pfkp.GetPAPX(y); _paragraphs.Add(papx); } } _paragraphs.Sort((IComparer <PAPX>)PropertyNode.PAPXComparator.instance); }
public void AdjustForInsert(int listIndex, int Length) { int size = _paragraphs.Count; PAPX papx = (PAPX)_paragraphs[listIndex]; papx.End = (papx.End + Length); for (int x = listIndex + 1; x < size; x++) { papx = (PAPX)_paragraphs[x]; papx.Start = (papx.Start + Length); papx.End = (papx.End + Length); } }
internal ListEntry(PAPX papx, Range parent, ListTables tables) : base(papx, parent) { if (tables != null) { ListFormatOverride override1 = tables.GetOverride(_props.GetIlfo()); _overrideLevel = override1.GetOverrideLevel(_props.GetIlvl()); _level = tables.GetLevel(override1.GetLsid(), _props.GetIlvl()); } else { //log.log(POILogger.WARN, "No ListTables found for ListEntry - document probably partly corrupt, and you may experience problems"); } }
/** * Creates a PAPFormattedDiskPage from a 512 byte array */ public PAPFormattedDiskPage(byte[] documentStream, byte[] dataStream, int offset, CharIndexTranslator translator) : base(documentStream, offset) { for (int x = 0; x < _crun; x++) { int bytesStartAt = GetStart(x); int bytesEndAt = GetEnd(x); int charStartAt = translator.GetCharIndex(bytesStartAt); int charEndAt = translator.GetCharIndex(bytesEndAt, charStartAt); PAPX papx = new PAPX(charStartAt, charEndAt, GetGrpprl(x), GetParagraphHeight(x), dataStream); _papxList.Add(papx); } _fkp = null; }
/** * Creates a PAPFormattedDiskPage from a 512 byte array */ public PAPFormattedDiskPage(byte[] documentStream, byte[] dataStream, int offset, CharIndexTranslator translator) :base(documentStream, offset) { for (int x = 0; x < _crun; x++) { int bytesStartAt = GetStart(x); int bytesEndAt = GetEnd(x); int charStartAt = translator.GetCharIndex(bytesStartAt); int charEndAt = translator.GetCharIndex(bytesEndAt, charStartAt); PAPX papx = new PAPX(charStartAt, charEndAt, GetGrpprl(x), GetParagraphHeight(x), dataStream); _papxList.Add(papx); } _fkp = null; }
public void Insert(int listIndex, int cpStart, SprmBuffer buf) { PAPX forInsert = new PAPX(0, 0, buf); // Ensure character OffSets are really characters forInsert.Start = cpStart; forInsert.End = cpStart; if (listIndex == _paragraphs.Count) { _paragraphs.Add(forInsert); } else { PAPX currentPap = _paragraphs[listIndex]; if (currentPap != null && currentPap.Start < cpStart) { SprmBuffer ClonedBuf = null; ClonedBuf = (SprmBuffer)currentPap.GetSprmBuf().Clone(); // Copy the properties of the one before to afterwards // Will go: // Original, until insert at point // New one // Clone of original, on to the old end PAPX clone = new PAPX(0, 0, ClonedBuf); // Again ensure Contains character based OffSets no matter what clone.Start = (cpStart); clone.End = (currentPap.End); currentPap.End = cpStart; _paragraphs.Insert(listIndex + 1, forInsert); _paragraphs.Insert(listIndex + 2, clone); } else { _paragraphs.Insert(listIndex, forInsert); } } }
public void AdjustForDelete(int listIndex, int offset, int Length) { int size = _paragraphs.Count; int endMark = offset + Length; int endIndex = listIndex; PAPX papx = _paragraphs[endIndex]; while (papx.End < endMark) { papx = _paragraphs[++endIndex]; } if (listIndex == endIndex) { papx = _paragraphs[endIndex]; papx.End = ((papx.End - endMark) + offset); } else { papx = _paragraphs[listIndex]; papx.End = (offset); for (int x = listIndex + 1; x < endIndex; x++) { papx = _paragraphs[x]; papx.Start = (offset); papx.End = (offset); } papx = _paragraphs[endIndex]; papx.End = ((papx.End - endMark) + offset); } for (int x = endIndex + 1; x < size; x++) { papx = _paragraphs[x]; papx.Start = (papx.Start - Length); papx.End = (papx.End - Length); } }
public PAPXTreeNode(PAPX papx) { this.Record = papx; }
/** * 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); }
internal Paragraph(PAPX papx, Range parent) : base(Math.Max(parent._start, papx.Start), Math.Min(parent._end, papx.End), parent) { _props = papx.GetParagraphProperties(_doc.GetStyleSheet()); _papx = papx.GetSprmBuf(); _istd = papx.GetIstd(); }
public void Rebuild(StringBuilder docText, ComplexFileTable complexFileTable) { long start = DateTime.Now.Ticks; if (complexFileTable != null) { SprmBuffer[] sprmBuffers = complexFileTable.GetGrpprls(); // adding PAPX from fast-saved SPRMs foreach (TextPiece textPiece in complexFileTable.GetTextPieceTable() .TextPieces) { PropertyModifier prm = textPiece.PieceDescriptor.Prm; if (!prm.IsComplex()) { continue; } int igrpprl = prm.GetIgrpprl(); if (igrpprl < 0 || igrpprl >= sprmBuffers.Length) { logger.Log(POILogger.WARN, textPiece + "'s PRM references to unknown grpprl"); continue; } bool hasPap = false; SprmBuffer sprmBuffer = sprmBuffers[igrpprl]; for (SprmIterator iterator = sprmBuffer.Iterator(); iterator .HasNext();) { SprmOperation sprmOperation = iterator.Next(); if (sprmOperation.Type == SprmOperation.TYPE_PAP) { hasPap = true; break; } } if (hasPap) { SprmBuffer newSprmBuffer = new SprmBuffer(2); newSprmBuffer.Append(sprmBuffer.ToByteArray()); PAPX papx = new PAPX(textPiece.Start, textPiece.End, newSprmBuffer); _paragraphs.Add(papx); } } logger.Log(POILogger.DEBUG, "Merged (?) with PAPX from complex file table in ", DateTime.Now.Ticks - start, " ms (", _paragraphs.Count, " elements in total)"); start = DateTime.Now.Ticks; } List <PAPX> oldPapxSortedByEndPos = new List <PAPX>(_paragraphs); oldPapxSortedByEndPos.Sort( (IComparer <PAPX>)PropertyNode.PAPXComparator.instance); logger.Log(POILogger.DEBUG, "PAPX sorted by end position in ", DateTime.Now.Ticks - start, " ms"); start = DateTime.Now.Ticks; Dictionary <PAPX, int> papxToFileOrder = new Dictionary <PAPX, int>(); int counter = 0; foreach (PAPX papx in _paragraphs) { papxToFileOrder[papx] = counter++; } logger.Log(POILogger.DEBUG, "PAPX's order map created in ", DateTime.Now.Ticks - start, " ms"); start = DateTime.Now.Ticks; List <PAPX> newPapxs = new List <PAPX>(); int lastParStart = 0; int lastPapxIndex = 0; for (int charIndex = 0; charIndex < docText.Length; charIndex++) { char c = docText[charIndex]; if (c != 13 && c != 7 && c != 12) { continue; } int startInclusive = lastParStart; int endExclusive = charIndex + 1; bool broken = false; List <PAPX> papxs = new List <PAPX>(); for (int papxIndex = lastPapxIndex; papxIndex < oldPapxSortedByEndPos .Count; papxIndex++) { broken = false; PAPX papx = oldPapxSortedByEndPos[papxIndex]; if (papx.End - 1 > charIndex) { lastPapxIndex = papxIndex; broken = true; break; } papxs.Add(papx); } if (!broken) { lastPapxIndex = oldPapxSortedByEndPos.Count - 1; } if (papxs.Count == 0) { logger.Log(POILogger.WARN, "Paragraph [", startInclusive, "; ", endExclusive, ") has no PAPX. Creating new one."); // create it manually PAPX papx = new PAPX(startInclusive, endExclusive, new SprmBuffer(2)); newPapxs.Add(papx); lastParStart = endExclusive; continue; } if (papxs.Count == 1) { // can we reuse existing? PAPX existing = papxs[0]; if (existing.Start == startInclusive && existing.End == endExclusive) { newPapxs.Add(existing); lastParStart = endExclusive; continue; } } PAPXToFileComparer papxFileOrderComparator = new PAPXToFileComparer(papxToFileOrder); // restore file order of PAPX papxs.Sort(papxFileOrderComparator); SprmBuffer sprmBuffer = null; foreach (PAPX papx in papxs) { if (sprmBuffer == null) { sprmBuffer = (SprmBuffer)papx.GetSprmBuf().Clone(); } else { sprmBuffer.Append(papx.GetGrpprl(), 2); } } PAPX newPapx = new PAPX(startInclusive, endExclusive, sprmBuffer); newPapxs.Add(newPapx); lastParStart = endExclusive; continue; } this._paragraphs = new List <PAPX>(newPapxs); logger.Log(POILogger.DEBUG, "PAPX rebuilded from document text in ", DateTime.Now.Ticks - start, " ms (", _paragraphs.Count, " elements)"); start = DateTime.Now.Ticks; }