using System; using System.Collections.Generic; using System.Text; using System.IO; namespace HH.WMS.Utils.ExcelLibrary.BinaryFileFormat { public class StringDecoder { Record record; BinaryReader reader; int ContinuedIndex = -1; public StringDecoder(Record record, BinaryReader reader) { this.record = record; this.reader = reader; } public string ReadString(int lengthbits) { if (reader.BaseStream.Position == reader.BaseStream.Length) { if (ContinuedIndex < record.ContinuedRecords.Count - 1) { SwitchToContinuedRecord(); } else { return null; } } int stringlength = lengthbits == 8 ? reader.ReadByte() : reader.ReadUInt16(); byte option = reader.ReadByte(); bool compressed = (option & 0x01) == 0; bool phonetic = (option & 0x04) == 0x04; bool richtext = (option & 0x08) == 0x08; int runs = 0; //Number of Rich-Text formatting runs int size = 0; //Size of Asian phonetic settings block in bytes if (richtext) { runs = reader.ReadUInt16(); } if (phonetic) { size = reader.ReadInt32(); } string firstpart = ReadString(stringlength, compressed); StringBuilder text = new StringBuilder(); text.Append(firstpart); if (firstpart.Length < stringlength) { SwitchToContinuedRecord(); text.Append(ReadContinuedString(stringlength - firstpart.Length)); } ReadBytes(4 * runs + size); return text.ToString(); } private string ReadString(int stringlength, bool compressed) { byte[] textData; if (compressed) { byte[] bytes = reader.ReadBytes(stringlength); textData = new byte[bytes.Length * 2]; for (int i = 0; i < bytes.Length; i++) { textData[i * 2] = bytes[i]; textData[i * 2 + 1] = 0; } } else { textData = reader.ReadBytes(stringlength * 2); } return Encoding.Unicode.GetString(textData); } private string ReadContinuedString(int stringlength) { if (reader.BaseStream.Position == reader.BaseStream.Length) return null; byte option = reader.ReadByte(); bool compressed = (option & 0x01) == 0; string firstpart = ReadString(stringlength, compressed); if (firstpart.Length < stringlength) { SwitchToContinuedRecord(); StringBuilder text = new StringBuilder(); text.Append(firstpart); text.Append(ReadContinuedString(stringlength - firstpart.Length)); return text.ToString(); } else { return firstpart; } } private byte[] ReadBytes(int count) { byte[] bytes = reader.ReadBytes(count); int bytesRead = bytes.Length; if (bytesRead < count) { SwitchToContinuedRecord(); byte[] allbytes = new byte[count]; byte[] remainedbytes = ReadBytes(count - bytesRead); bytes.CopyTo(allbytes, 0); remainedbytes.CopyTo(allbytes, bytesRead); return allbytes; } return bytes; } private void SwitchToContinuedRecord() { ContinuedIndex++; MemoryStream stream = new MemoryStream(record.ContinuedRecords[ContinuedIndex].Data); reader = new BinaryReader(stream); } public string ReadString(int lengthbits, out RichTextFormat rtf) { /* BEGIN - SAME AS ReadString() */ if (reader.BaseStream.Position == reader.BaseStream.Length) { if (ContinuedIndex < record.ContinuedRecords.Count - 1) { SwitchToContinuedRecord(); } else { rtf = null; return null; } } int stringlength = lengthbits == 8 ? reader.ReadByte() : reader.ReadUInt16(); byte option = reader.ReadByte(); bool compressed = (option & 0x01) == 0; bool phonetic = (option & 0x04) == 0x04; bool richtext = (option & 0x08) == 0x08; int runs = 0; //Number of Rich-Text formatting runs int size = 0; //Size of Asian phonetic settings block in bytes if (richtext) { runs = reader.ReadUInt16(); } if (phonetic) { size = reader.ReadInt32(); } string firstpart = ReadString(stringlength, compressed); StringBuilder text = new StringBuilder(); text.Append(firstpart); if (firstpart.Length < stringlength) { SwitchToContinuedRecord(); text.Append(ReadContinuedString(stringlength - firstpart.Length)); } /* END - SAME AS ReadString() */ /* * Added, 2-13-2009 * Sunil Shenoi * * Process the rich text formatting information as in Section 2.5.3. */ byte[] richTextBytes = ReadBytes(4 * runs + size); rtf = DecodeRichTextFormatting(richTextBytes, runs); return text.ToString(); } /* * Added, 2-13-2009 * Sunil Shenoi * * Decode the rich text formatting information associated with a given string. */ private RichTextFormat DecodeRichTextFormatting(byte[] richTextBytes, int runs) { RichTextFormat rtf = new RichTextFormat(runs); // process the byte array into pairs of UInt16's for (int i = 0; i < runs; i++) { rtf.CharIndexes.Add(BitConverter.ToUInt16(richTextBytes, (i * 4))); rtf.FontIndexes.Add(BitConverter.ToUInt16(richTextBytes, (i * 4) + 2)); } return rtf; } } }