Skip to content

Commit

Permalink
Some refactoring around the FRX objects
Browse files Browse the repository at this point in the history
  • Loading branch information
chelh committed Aug 7, 2016
1 parent 14bd241 commit ee0033e
Show file tree
Hide file tree
Showing 8 changed files with 553 additions and 272 deletions.
72 changes: 20 additions & 52 deletions VbaSyncLib/FrxObjects/CommandButtonControl.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
using static VbaSync.FrxObjects.AlignmentHelpers;
using static VbaSync.FrxObjects.StreamDataHelpers;

namespace VbaSync.FrxObjects {
class CommandButtonControl {
class CommandButtonControl : FrxCommon {
public byte MinorVersion { get; }
public byte MajorVersion { get; }
public CommandButtonPropMask PropMask { get; }
Expand All @@ -31,57 +29,27 @@ public CommandButtonControl(byte[] b) {
var cbCommandButton = r.ReadUInt16();
PropMask = new CommandButtonPropMask(r.ReadUInt32());

// DataBlock
ushort dataBlockBytes = 0;
if (PropMask.HasForeColor) {
ForeColor = new OleColor(r.ReadBytes(4));
dataBlockBytes += 4;
}
if (PropMask.HasBackColor) {
BackColor = new OleColor(r.ReadBytes(4));
dataBlockBytes += 4;
}
if (PropMask.HasVariousPropertyBits) {
VariousPropertyBits = r.ReadUInt32();
dataBlockBytes += 4;
}
var captionLength = 0;
var captionCompressed = false;
if (PropMask.HasCaption) {
captionLength = CcbToLength(r.ReadInt32(), out captionCompressed);
dataBlockBytes += 4;
}
if (PropMask.HasPicturePosition) {
PicturePosition = (PicturePosition)r.ReadUInt32();
dataBlockBytes += 4;
}
if (PropMask.HasMousePointer) {
MousePointer = (MousePointer)r.ReadByte();
dataBlockBytes += 1;
}
AlignTo(4, st, ref dataBlockBytes);
if (PropMask.HasPicture) IgnoreNext(2, st, ref dataBlockBytes);
AlignTo(4, st, ref dataBlockBytes);
if (PropMask.HasAccelerator) {
Accelerator = Encoding.Unicode.GetString(r.ReadBytes(2));
dataBlockBytes += 2;
}
AlignTo(4, st, ref dataBlockBytes);
if (PropMask.HasMouseIcon) IgnoreNext(2, st, ref dataBlockBytes);
AlignTo(4, st, ref dataBlockBytes);
BeginDataBlock();
ForeColor = ReadAlignedOleColorIf(PropMask.HasForeColor, r);
BackColor = ReadAlignedOleColorIf(PropMask.HasBackColor, r);
VariousPropertyBits = ReadAlignedUInt32If(PropMask.HasVariousPropertyBits, r);
var captionCcb = ReadAlignedCcbIf(PropMask.HasCaption, r);
PicturePosition = (PicturePosition)ReadAlignedUInt32If(PropMask.HasPicturePosition, r);
MousePointer = (MousePointer)ReadByteIf(PropMask.HasMousePointer, r);
Ignore2AlignedBytesIf(PropMask.HasPicture, r);
Accelerator = ReadAlignedWCharIf(PropMask.HasAccelerator, r);
Ignore2AlignedBytesIf(PropMask.HasMouseIcon, r);
EndDataBlock(r);

// ExtraDataBlock
ushort extraDataBlockBytes = 0;
if (captionLength > 0) {
Caption = (captionCompressed ? Encoding.UTF8 : Encoding.Unicode).GetString(r.ReadBytes(captionLength));
extraDataBlockBytes += (ushort)captionLength;
}
AlignTo(4, st, ref extraDataBlockBytes);
if (PropMask.HasSize) {
Size = Tuple.Create(r.ReadInt32(), r.ReadInt32());
extraDataBlockBytes += 4;
}
BeginExtraDataBlock();
Caption = ReadStringFromCcb(captionCcb, r);
Size = ReadAlignedCoordsIf(PropMask.HasSize, r);
EndExtraDataBlock(r);

if (cbCommandButton != 4 + DataBlockBytes + ExtraDataBlockBytes)
throw new ApplicationException("Error reading 'o' stream in .frx data: expected cbCommandButton size "
+ $"{4 + DataBlockBytes + ExtraDataBlockBytes}, but actual size was {cbCommandButton}.");

// StreamData
if (PropMask.HasPicture) {
Picture = ReadGuidAndPicture(r);
Expand Down
191 changes: 150 additions & 41 deletions VbaSyncLib/FrxObjects/Common.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,144 @@
using System;
using System.IO;
using System.Text;
using static VbaSync.FrxObjects.AlignmentHelpers;
using static VbaSync.FrxObjects.StreamDataHelpers;

namespace VbaSync.FrxObjects {
abstract class FrxCommon {
ushort _dBytes;
bool _inD;
bool _inX;
ushort _xBytes;

protected ushort DataBlockBytes => _dBytes;
protected ushort ExtraDataBlockBytes => _xBytes;

protected void BeginDataBlock() {
_dBytes = 0;
_inD = true;
}

protected void BeginExtraDataBlock() {
_xBytes = 0;
_inX = true;
}

protected void EndDataBlock(BinaryReader r) {
AlignTo(4, r.BaseStream);
_inD = false;
}

protected void EndExtraDataBlock(BinaryReader r) {
AlignTo(4, r.BaseStream);
_inX = false;
}

protected byte ReadByteIf(bool b, BinaryReader r, byte ifNot = 0) {
if (!b) return ifNot;
AboutToRead(1);
return r.ReadByte();
}

protected void Ignore2AlignedBytesIf(bool b, BinaryReader r) {
if (!b) return;
AlignTo(2, r.BaseStream);
IgnoreNext(2, r.BaseStream);
}

protected short ReadAlignedInt16If(bool b, BinaryReader r, short ifNot = 0) {
if (!b) return ifNot;
AlignTo(2, r.BaseStream);
AboutToRead(2);
return r.ReadInt16();
}

protected ushort ReadAlignedUInt16If(bool b, BinaryReader r, ushort ifNot = 0) {
if (!b) return ifNot;
AlignTo(2, r.BaseStream);
AboutToRead(2);
return r.ReadUInt16();
}

protected int ReadAlignedInt32If(bool b, BinaryReader r, int ifNot = 0) {
if (!b) return ifNot;
AlignTo(4, r.BaseStream);
AboutToRead(4);
return r.ReadInt32();
}

protected uint ReadAlignedUInt32If(bool b, BinaryReader r, uint ifNot = 0) {
if (!b) return ifNot;
AlignTo(4, r.BaseStream);
AboutToRead(4);
return r.ReadUInt32();
}

protected Tuple<int, int> ReadAlignedCoordsIf(bool b, BinaryReader r) {
if (!b) return Tuple.Create(0, 0);
AlignTo(4, r.BaseStream);
AboutToRead(8);
return Tuple.Create(r.ReadInt32(), r.ReadInt32());
}

protected Tuple<int, bool> ReadAlignedCcbIf(bool b, BinaryReader r) {
if (!b) return Tuple.Create(0, false);
AlignTo(4, r.BaseStream);
AboutToRead(4);
var i = r.ReadInt32();
return i < 0 ? Tuple.Create(unchecked((int)(i ^ 0x80000000)), true) : Tuple.Create(i, false);
}

protected OleColor ReadAlignedOleColorIf(bool b, BinaryReader r) {
if (!b) return null;
AlignTo(4, r.BaseStream);
AboutToRead(4);
return new OleColor(r.ReadBytes(4));
}

protected string ReadAlignedWCharIf(bool b, BinaryReader r) {
if (!b) return "";
AlignTo(2, r.BaseStream);
AboutToRead(2);
return Encoding.Unicode.GetString(r.ReadBytes(2));
}

protected string ReadStringFromCcb(Tuple<int, bool> ccb, BinaryReader r) {
if (ccb.Item1 == 0) return "";
AboutToRead((ushort)ccb.Item1);
var s = (ccb.Item2 ? Encoding.UTF8 : Encoding.Unicode).GetString(r.ReadBytes(ccb.Item1));
AlignTo(4, r.BaseStream);
return s;
}

void AboutToRead(ushort numBytes) {
if (_inD) {
_dBytes += numBytes;
} else if (_inX) {
_xBytes += numBytes;
}
}

void AlignTo(ushort alignment, Stream st) {
if (_inD) {
if (_dBytes%alignment == 0) return;
st.Seek(alignment - _dBytes%alignment, SeekOrigin.Current);
_dBytes += (ushort)(alignment - _dBytes%alignment);
} else if (_inX) {
if (_xBytes%alignment == 0) return;
st.Seek(alignment - _xBytes%alignment, SeekOrigin.Current);
_xBytes += (ushort)(alignment - _xBytes%alignment);
}
}

void IgnoreNext(ushort bytes, Stream st) {
st.Seek(bytes, SeekOrigin.Current);
if (_inD) {
_dBytes += bytes;
} else if (_inX) {
_xBytes += bytes;
}
}
}

class OleColor {
public OleColorType ColorType { get; }
public ushort PaletteIndex { get; }
Expand Down Expand Up @@ -38,7 +172,7 @@ public override int GetHashCode() {
}
}

class TextProps {
class TextProps : FrxCommon {
public byte MinorVersion { get; }
public byte MajorVersion { get; }
public TextPropsPropMask PropMask { get; }
Expand All @@ -59,44 +193,19 @@ public TextProps(byte[] b) {
var cbTextProps = r.ReadUInt16();
PropMask = new TextPropsPropMask(r.ReadUInt32());

// DataBlock
ushort dataBlockBytes = 0;
var fontNameLength = 0;
var fontNameCompressed = false;
if (PropMask.HasFontName) {
fontNameLength = CcbToLength(r.ReadInt32(), out fontNameCompressed);
dataBlockBytes += 4;
}
if (PropMask.HasFontEffects) {
FontEffects = r.ReadUInt32();
dataBlockBytes += 4;
}
if (PropMask.HasFontHeight) {
FontHeight = r.ReadUInt32();
dataBlockBytes += 4;
}
if (PropMask.HasFontCharSet) {
FontCharSet = r.ReadByte();
dataBlockBytes += 4;
}
if (PropMask.HasFontPitchAndFamily) {
FontPitchAndFamily = r.ReadByte();
dataBlockBytes += 1;
}
if (PropMask.HasParagraphAlign) {
ParagraphAlign = r.ReadByte();
dataBlockBytes += 1;
}
AlignTo(4, st, ref dataBlockBytes);
if (PropMask.HasFontWeight) {
FontWeight = r.ReadUInt16();
}
AlignTo(4, st, ref dataBlockBytes);

// ExtraDataBlock
if (fontNameLength > 0) {
FontName = (fontNameCompressed ? Encoding.UTF8 : Encoding.Unicode).GetString(r.ReadBytes(fontNameLength));
}
BeginDataBlock();
var fontNameCcb = ReadAlignedCcbIf(PropMask.HasFontName, r);
FontEffects = ReadAlignedUInt32If(PropMask.HasFontEffects, r);
FontHeight = ReadAlignedUInt32If(PropMask.HasFontHeight, r);
FontCharSet = ReadByteIf(PropMask.HasFontCharSet, r);
FontPitchAndFamily = ReadByteIf(PropMask.HasFontPitchAndFamily, r);
ParagraphAlign = ReadByteIf(PropMask.HasParagraphAlign, r);
FontWeight = ReadAlignedUInt16If(PropMask.HasFontWeight, r);
EndDataBlock(r);

BeginExtraDataBlock();
FontName = ReadStringFromCcb(fontNameCcb, r);
EndExtraDataBlock(r);
}
}

Expand Down
Loading

0 comments on commit ee0033e

Please sign in to comment.