/** * Create a new AnimationInfo, with blank fields */ public AnimationInfo() { // Setup our header block _header = new byte[8]; _header[0] = 0x0f; // We are a Container record LittleEndian.PutShort(_header, 2, (short)RecordType); _children = new Record[1]; _children[0] = animationAtom = new AnimationInfoAtom(); }
/** * Adds a child record, at the very end. * @param newChild The child record to add */ private void AppendChild(Record newChild) { lock (this) { // Copy over, and pop the child in at the end Record[] nc = new Record[(_children.Length + 1)]; Array.Copy(_children, 0, nc, 0, _children.Length); // Switch the arrays nc[_children.Length] = newChild; _children = nc; } }
/* =============================================================== * Internal Move Helpers * =============================================================== */ /** * Finds the location of the given child record */ private int FindChildLocation(Record child) { // Synchronized as we don't want things changing // as we're doing our search lock (this) { for (int i = 0; i < _children.Length; i++) { if (_children[i].Equals(child)) { return i; } } } return -1; }
/** * Create a new Comment2000, with blank fields */ public Comment2000() { _header = new byte[8]; _children = new Record[4]; // Setup our header block _header[0] = 0x0f; // We are a Container record LittleEndian.PutShort(_header, 2, (short)_type); // Setup our child records CString csa = new CString(); CString csb = new CString(); CString csc = new CString(); csa.Options = (0x00); csb.Options = (0x10); csc.Options = (0x20); _children[0] = csa; _children[1] = csb; _children[2] = csc; _children[3] = new Comment2000Atom(); FindInterestingChildren(); }
/** * Default method for Finding child records of a Container record */ public static Record[] FindChildRecords(byte[] b, int start, int len) { List<Record> children = new List<Record>(5); // Jump our little way along, creating records as we go int pos = start; while (pos <= (start + len - 8)) { long type = LittleEndian.GetUShort(b, pos + 2); long rlen = LittleEndian.GetUInt(b, pos + 4); // Sanity check the length int rleni = (int)rlen; if (rleni < 0) { rleni = 0; } // Abort if first record is of type 0000 and length FFFF, // as that's a sign of a screwed up record if (pos == 0 && type == 0L && rleni == 0xffff) { throw new CorruptPowerPointFileException("Corrupt document - starts with record of type 0000 and length 0xFFFF"); } Record r = CreateRecordForType(type, b, pos, 8 + rleni); if (r != null) { children.Add(r); } else { // Record was horribly corrupt } pos += 8; pos += rleni; } // Turn the vector into an array, and return Record[] cRecords = new Record[children.Count]; for (int i = 0; i < children.Count; i++) { cRecords[i] = (Record)children[i]; } return cRecords; }
/** * Adds the given new Child Record at the given location, * shuffling everything from there on down by one * @param newChild * @param position */ private void AddChildAt(Record newChild, int position) { lock (this) { // Firstly, have the child Added in at the end AppendChild(newChild); // Now, have them moved to the right place MoveChildRecords((_children.Length - 1), position, 1); } }
/* =============================================================== * External Serialisation Methods * =============================================================== */ /** * Write out our header, and our children. * @param headerA the first byte of the header * @param headerB the second byte of the header * @param type the record type * @param children our child records * @param out the stream to write to */ public void WriteOut(byte headerA, byte headerB, long type, Record[] children, Stream out1) { // If we have a mutable output stream, take advantage of that if (out1 is MutableMemoryStream) { MutableMemoryStream mout = (MutableMemoryStream)out1; // Grab current size int oldSize = mout.GetBytesWritten(); // Write out our header, less the size mout.Write(new byte[] { headerA, headerB }); byte[] typeB = new byte[2]; LittleEndian.PutShort(typeB, (short)type); mout.Write(typeB); mout.Write(new byte[4]); // Write out the children for (int i = 0; i < children.Length; i++) { children[i].WriteOut(mout); } // Update our header with the size // Don't forget to knock 8 more off, since we don't include the // header in the size int length = mout.GetBytesWritten() - oldSize - 8; byte[] size = new byte[4]; LittleEndian.PutInt(size, 0, length); mout.OverWrite(size, oldSize + 4); } else { // Going to have to do it a slower way, because we have // to update the length come the end // Create a MemoryStream to hold everything in MemoryStream baos = new MemoryStream(); // Write out our header, less the size baos.Write(new byte[] { headerA, headerB }, 0, 2); byte[] typeB = new byte[2]; LittleEndian.PutShort(typeB, (short)type); baos.Write(typeB, 2, 2); baos.Write(new byte[] { 0, 0, 0, 0 }, 4, 4); // Write out our children for (int i = 0; i < children.Length; i++) { children[i].WriteOut(baos); } // Grab the bytes back byte[] toWrite = baos.ToArray(); // Update our header with the size // Don't forget to knock 8 more off, since we don't include the // header in the size LittleEndian.PutInt(toWrite, 4, (toWrite.Length - 8)); // Write out the bytes out1.Write(toWrite, (int)out1.Position, toWrite.Length); } }
/** * Moves the given Child Records to after the supplied record */ public void MoveChildrenAfter(Record firstChild, int number, Record after) { if (number < 1) { return; } lock (this) { // Decide where we're going to put them int newLoc = FindChildLocation(after); if (newLoc == -1) { throw new ArgumentException("Asked to move children before another record, but that record wasn't one of our children!"); } // We actually want after this though newLoc++; // Figure out where they are now int oldLoc = FindChildLocation(firstChild); if (oldLoc == -1) { throw new ArgumentException("Asked to move a record that wasn't a child!"); } // Actually move MoveChildRecords(oldLoc, newLoc, number); } }
/** * Set child records. * * @param records the new child records */ public void SetChildRecord(Record[] records) { this._children = records; }
/** * Moves the given Child Record to before the supplied record */ public void MoveChildBefore(Record child, Record before) { MoveChildrenBefore(child, 1, before); }
/** * Adds the given Child Record before the supplied record * @param newChild * @param before */ public void AddChildBefore(Record newChild, Record before) { lock (this) { // Decide where we're going to put it int loc = FindChildLocation(before); if (loc == -1) { throw new ArgumentException("Asked to add a new child before another record, but that record wasn't one of our children!"); } // Add at the place of the supplied record AddChildAt(newChild, loc); } }
/** * Adds the given Child Record after the supplied record * @param newChild * @param after */ public void AddChildAfter(Record newChild, Record after) { lock (this) { // Decide where we're going to put it int loc = FindChildLocation(after); if (loc == -1) { throw new ArgumentException("Asked to add a new child after another record, but that record wasn't one of our children!"); } // Add one place after the supplied record AddChildAt(newChild, loc + 1); } }
/* =============================================================== * External Move Methods * =============================================================== */ /** * Add a new child record onto a record's list of children. */ public void AppendChildRecord(Record newChild) { lock (this) { AppendChild(newChild); } }
/** * Remove a child record from this record Container * * @param ch the child to remove * @return the Removed record */ public Record RemoveChild(Record ch) { Record rm = null; List<Record> lst = new List<Record>(); foreach (Record r in _children) { if (r != ch) lst.Add(r); else rm = r; } _children = lst.ToArray(); return rm; }