using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using VBASync.Localization;
namespace VBASync.Model.FrxObjects
{
internal class FrxReader : IDisposable
{
private static readonly Guid StdFontGuid = new Guid(0x0BE35203, 0x8F91, 0x11CE,
0x9D, 0xE3, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51);
public FrxReader(Stream st)
{
Unaligned = new BinaryReader(st);
}
public Stream BaseStream => Unaligned.BaseStream;
public BinaryReader Unaligned { get; }
public void AlignTo(ushort alignment)
{
var rem = BaseStream.Position % alignment;
if (rem == 0)
{
return;
}
BaseStream.Seek(alignment - rem, SeekOrigin.Current);
}
public void Dispose() => Unaligned.Dispose();
public bool GetFontIsStdFont() => new Guid(Unaligned.ReadBytes(16)) == StdFontGuid;
public string[] ReadArrayStrings(uint cbArrayString)
{
if (cbArrayString == 0)
{
return new string[0];
}
var startPos = Unaligned.BaseStream.Position;
var endPos = startPos + cbArrayString;
var ret = new List<string>();
while (Unaligned.BaseStream.Position < endPos)
{
ret.Add(ReadStringFromCcb(ReadCcbWithDoubleSizeIfUncompressed()));
}
if (Unaligned.BaseStream.Position != endPos)
{
throw new ApplicationException(string.Format(VBASyncResources.ErrorFrxStreamSizeMismatch,
"o", "cbArrayString", BaseStream.Position - startPos, cbArrayString));
}
return ret.ToArray();
}
public BorderStyle ReadBorderStyle() => (BorderStyle)ReadByte();
public byte ReadByte() => Unaligned.ReadByte();
public Tuple<int, bool> ReadCcb()
{
AlignTo(4);
var i = Unaligned.ReadInt32();
return i < 0 ? Tuple.Create(unchecked((int)(i ^ 0x80000000)), true) : Tuple.Create(i, false);
}
public Tuple<int, bool> ReadCcbWithDoubleSizeIfUncompressed()
{
AlignTo(4);
var i = Unaligned.ReadInt32();
return i < 0 ? Tuple.Create(unchecked((int)(i ^ 0x80000000)), true) : Tuple.Create(i * 2, false);
}
public Tuple<int, int> ReadCoords()
{
AlignTo(4);
return Tuple.Create(Unaligned.ReadInt32(), Unaligned.ReadInt32());
}
public Cycle ReadCycle() => (Cycle)ReadByte();
public byte[] ReadGuidAndPicture()
{
BaseStream.Seek(20, SeekOrigin.Current);
return Unaligned.ReadBytes(Unaligned.ReadInt32());
}
public short ReadInt16()
{
AlignTo(2);
return Unaligned.ReadInt16();
}
public int ReadInt32()
{
AlignTo(4);
return Unaligned.ReadInt32();
}
public MousePointer ReadMousePointer() => (MousePointer)ReadByte();
public OleColor ReadOleColor()
{
AlignTo(4);
return new OleColor(Unaligned.ReadBytes(4));
}
public PictureAlignment ReadPictureAlignment() => (PictureAlignment)ReadByte();
public PicturePosition ReadPicturePosition() => (PicturePosition)ReadUInt32();
public PictureSizeMode ReadPictureSizeMode() => (PictureSizeMode)ReadByte();
public SpecialEffect ReadSpecialEffect() => (SpecialEffect)ReadByte();
public SpecialEffect ReadSpecialEffect2() => (SpecialEffect)ReadUInt16();
public SpecialEffect ReadSpecialEffect4() => (SpecialEffect)ReadUInt32();
public Tuple<short, byte, short, uint, string> ReadStdFont()
{
BaseStream.Seek(1, SeekOrigin.Current);
return Tuple.Create(Unaligned.ReadInt16(), Unaligned.ReadByte(), Unaligned.ReadInt16(), Unaligned.ReadUInt32(),
Encoding.ASCII.GetString(Unaligned.ReadBytes(Unaligned.ReadByte())));
}
public string ReadStringFromCcb(Tuple<int, bool> ccb)
{
if (ccb.Item1 == 0)
{
return "";
}
AlignTo(4);
var s = (ccb.Item2 ? Encoding.UTF8 : Encoding.Unicode).GetString(Unaligned.ReadBytes(ccb.Item1));
AlignTo(4);
return s;
}
public TextProps ReadTextProps()
{
BaseStream.Seek(2, SeekOrigin.Current);
var cbTextProps = Unaligned.ReadUInt16();
BaseStream.Seek(-4, SeekOrigin.Current);
return cbTextProps > 0 ? new TextProps(Unaligned.ReadBytes(cbTextProps + 4)) : null;
}
public ushort ReadUInt16()
{
AlignTo(2);
return Unaligned.ReadUInt16();
}
public uint ReadUInt32()
{
AlignTo(4);
return Unaligned.ReadUInt32();
}
public ulong ReadUInt64()
{
AlignTo(4);
return Unaligned.ReadUInt64();
}
public string ReadWChar()
{
AlignTo(2);
return Encoding.Unicode.GetString(Unaligned.ReadBytes(2));
}
public void Skip2Bytes()
{
AlignTo(2);
BaseStream.Seek(2, SeekOrigin.Current);
}
}
}