/** * Constructor used to read a binTable in from a Word document. */ public CHPBinTable(byte[] documentStream, byte[] tableStream, int offset, int size, CharIndexTranslator translator) { 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; CHPFormattedDiskPage cfkp = new CHPFormattedDiskPage(documentStream, pageOffset, translator); int fkpSize = cfkp.Size(); for (int y = 0; y < fkpSize; y++) { CHPX chpx = cfkp.GetCHPX(y); if (chpx != null) { _textRuns.Add(chpx); } } } }
private static int BinarySearch(List <CHPX> chpxs, int startPosition) { int low = 0; int high = chpxs.Count - 1; while (low <= high) { int mid = (low + high) >> 1; CHPX midVal = chpxs[mid]; int midValue = midVal.Start; if (midValue < startPosition) { low = mid + 1; } else if (midValue > startPosition) { high = mid - 1; } else { return(mid); // key found } } return(-(low + 1)); // key not found. }
public void AdjustForInsert(int listIndex, int Length) { int size = _textRuns.Count; CHPX chpx = _textRuns[listIndex]; chpx.End = (chpx.End + Length); for (int x = listIndex + 1; x < size; x++) { chpx = _textRuns[x]; chpx.Start = (chpx.Start + Length); chpx.End = (chpx.End + Length); } }
/** * This constructs a CHPFormattedDiskPage from a raw fkp (512 byte array * read from a Word file). */ public CHPFormattedDiskPage(byte[] documentStream, 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); CHPX chpx = new CHPX(charStartAt, charEndAt, new SprmBuffer( GetGrpprl(x), 0)); _chpxList.Add(chpx); } }
public void Insert(int listIndex, int cpStart, SprmBuffer buf) { CHPX insertChpx = new CHPX(0, 0, buf); // Ensure character OffSets are really characters insertChpx.Start = (cpStart); insertChpx.End = (cpStart); if (listIndex == _textRuns.Count) { _textRuns.Add(insertChpx); } else { CHPX chpx = _textRuns[listIndex]; if (chpx.Start < cpStart) { // 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 CHPX clone = new CHPX(0, 0, chpx.GetSprmBuf()); // Again ensure Contains character based OffSets no matter what clone.Start = (cpStart); clone.End = (chpx.End); chpx.End = (cpStart); _textRuns.Insert(listIndex + 1, insertChpx); _textRuns.Insert(listIndex + 2, clone); } else { _textRuns.Insert(listIndex, insertChpx); } } }
public void AdjustForDelete(int listIndex, int offset, int Length) { int size = _textRuns.Count; int endMark = offset + Length; int endIndex = listIndex; CHPX chpx = _textRuns[endIndex]; while (chpx.End < endMark) { chpx = _textRuns[++endIndex]; } if (listIndex == endIndex) { chpx = _textRuns[endIndex]; chpx.End = ((chpx.End - endMark) + offset); } else { chpx = _textRuns[listIndex]; chpx.End = (offset); for (int x = listIndex + 1; x < endIndex; x++) { chpx = _textRuns[x]; chpx.Start = (offset); chpx.End = (offset); } chpx = _textRuns[endIndex]; chpx.End = ((chpx.End - endMark) + offset); } for (int x = endIndex + 1; x < size; x++) { chpx = _textRuns[x]; chpx.Start = (chpx.Start - Length); chpx.End = (chpx.End - Length); } }
internal byte[] ToArray(int fcMin) { byte[] buf = new byte[512]; int size = _chpxList.Count; int grpprlOffset = 511; int offsetOffset = 0; int fcOffset = 0; // total size is currently the size of one FC int totalSize = FC_SIZE + 2; int index = 0; for (; index < size; index++) { int grpprlLength = (_chpxList[index]).GetGrpprl().Length; // check to see if we have enough room for an FC, the grpprl offset, // the grpprl size byte and the grpprl. totalSize += (FC_SIZE + 2 + grpprlLength); // 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 -= (FC_SIZE + 2 + grpprlLength); break; } // grpprls must fall on word boundaries if ((1 + grpprlLength) % 2 > 0) { totalSize += 1; } } // see if we couldn't fit some if (index != size) { _overFlow = new List <CHPX>(); _overFlow.AddRange(_chpxList.GetRange(index, size - index)); } // index should equal number of CHPXs that will be in this fkp now. buf[511] = (byte)index; offsetOffset = (FC_SIZE * index) + FC_SIZE; //grpprlOffset = offsetOffset + index + (grpprlOffset % 2); CHPX chpx = null; for (int x = 0; x < index; x++) { chpx = (CHPX)_chpxList[x]; byte[] grpprl = chpx.GetGrpprl(); LittleEndian.PutInt(buf, fcOffset, chpx.StartBytes + fcMin); grpprlOffset -= (1 + grpprl.Length); grpprlOffset -= (grpprlOffset % 2); buf[offsetOffset] = (byte)(grpprlOffset / 2); buf[grpprlOffset] = (byte)grpprl.Length; Array.Copy(grpprl, 0, buf, grpprlOffset + 1, grpprl.Length); offsetOffset += 1; fcOffset += FC_SIZE; } // put the last chpx's end in LittleEndian.PutInt(buf, fcOffset, chpx.EndBytes + fcMin); return(buf); }
public void Rebuild(ComplexFileTable complexFileTable) { long start = DateTime.Now.Ticks; if (complexFileTable != null) { SprmBuffer[] sprmBuffers = complexFileTable.GetGrpprls(); // adding CHPX 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 hasChp = false; SprmBuffer sprmBuffer = sprmBuffers[igrpprl]; for (SprmIterator iterator = sprmBuffer.Iterator(); ; iterator .HasNext()) { SprmOperation sprmOperation = iterator.Next(); if (sprmOperation.Type == SprmOperation.TYPE_CHP) { hasChp = true; break; } } if (hasChp) { SprmBuffer newSprmBuffer; newSprmBuffer = (SprmBuffer)sprmBuffer.Clone(); CHPX chpx = new CHPX(textPiece.Start, textPiece.End, newSprmBuffer); _textRuns.Add(chpx); } } logger.Log(POILogger.DEBUG, "Merged with CHPX from complex file table in ", DateTime.Now.Ticks - start, " ms (", _textRuns.Count, " elements in total)"); start = DateTime.Now.Ticks; } List <CHPX> oldChpxSortedByStartPos = new List <CHPX>(_textRuns); oldChpxSortedByStartPos.Sort( (IComparer <CHPX>)PropertyNode.CHPXComparator.instance); logger.Log(POILogger.DEBUG, "CHPX sorted by start position in ", DateTime.Now.Ticks - start, " ms"); start = DateTime.Now.Ticks; Dictionary <CHPX, int> chpxToFileOrder = new Dictionary <CHPX, int>(); int counter = 0; foreach (CHPX chpx in _textRuns) { chpxToFileOrder.Add(chpx, counter++); } logger.Log(POILogger.DEBUG, "CHPX's order map created in ", DateTime.Now.Ticks - start, " ms"); start = DateTime.Now.Ticks; List <int> textRunsBoundariesList; List <int> textRunsBoundariesSet = new List <int>(); foreach (CHPX chpx in _textRuns) { textRunsBoundariesSet.Add(chpx.Start); textRunsBoundariesSet.Add(chpx.End); } textRunsBoundariesSet.Remove(0); textRunsBoundariesList = new List <int>( textRunsBoundariesSet); textRunsBoundariesList.Sort(); logger.Log(POILogger.DEBUG, "Texts CHPX boundaries collected in ", DateTime.Now.Ticks - start, " ms"); start = DateTime.Now.Ticks; List <CHPX> newChpxs = new List <CHPX>(); int lastTextRunStart = 0; foreach (int objBoundary in textRunsBoundariesList) { int boundary = objBoundary; int startInclusive = lastTextRunStart; int endExclusive = boundary; lastTextRunStart = endExclusive; int startPosition = BinarySearch(oldChpxSortedByStartPos, boundary); startPosition = Math.Abs(startPosition); while (startPosition >= oldChpxSortedByStartPos.Count) { startPosition--; } while (startPosition > 0 && oldChpxSortedByStartPos[startPosition].Start >= boundary) { startPosition--; } List <CHPX> chpxs = new List <CHPX>(); for (int c = startPosition; c < oldChpxSortedByStartPos.Count; c++) { CHPX chpx = oldChpxSortedByStartPos[c]; if (boundary < chpx.Start) { break; } int left = Math.Max(startInclusive, chpx.Start); int right = Math.Min(endExclusive, chpx.End); if (left < right) { chpxs.Add(chpx); } } if (chpxs.Count == 0) { logger.Log(POILogger.WARN, "Text piece [", startInclusive, "; ", endExclusive, ") has no CHPX. Creating new one."); // create it manually CHPX chpx = new CHPX(startInclusive, endExclusive, new SprmBuffer(0)); newChpxs.Add(chpx); continue; } if (chpxs.Count == 1) { // can we reuse existing? CHPX existing = chpxs[0]; if (existing.Start == startInclusive && existing.End == endExclusive) { newChpxs.Add(existing); continue; } } CHPXToFileComparer chpxFileOrderComparator = new CHPXToFileComparer(chpxToFileOrder); chpxs.Sort(chpxFileOrderComparator); SprmBuffer sprmBuffer = new SprmBuffer(0); foreach (CHPX chpx in chpxs) { sprmBuffer.Append(chpx.GetGrpprl(), 0); } CHPX newChpx = new CHPX(startInclusive, endExclusive, sprmBuffer); newChpxs.Add(newChpx); continue; } this._textRuns = new List <CHPX>(newChpxs); logger.Log(POILogger.DEBUG, "CHPX rebuilded in ", DateTime.Now.Ticks - start, " ms (", _textRuns.Count, " elements)"); start = DateTime.Now.Ticks; CHPX previous = null; for (int iterator = _textRuns.Count; iterator != 0;) { CHPX current = previous; previous = _textRuns[--iterator]; if (current == null) { continue; } if (previous.End == current.Start && Arrays .Equals(previous.GetGrpprl(), current.GetGrpprl())) { previous.End = current.End; _textRuns.Remove(current); continue; } previous = current; } logger.Log(POILogger.DEBUG, "CHPX compacted in ", DateTime.Now.Ticks - start, " ms (", _textRuns.Count, " elements)"); }
/** * * @param chpx The chpx this object is based on. * @param ss The stylesheet for the document this run belongs to. * @param istd The style index if this Run's base style. * @param parent The parent range of this character run (usually a paragraph). */ internal CharacterRun(CHPX chpx, StyleSheet ss, short istd, Range parent) : base(Math.Max(parent._start, chpx.Start), Math.Min(parent._end, chpx.End), parent) { _props = chpx.GetCharacterProperties(ss, istd); _chpx = chpx.GetSprmBuf(); }