/* libsswf_tag_base.c++ -- written by Alexis WILKE for Made to Order Software Corp. (c) 2002-2008 */

/*

Copyright (c) 2002-2008 Made to Order Software Corp.

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and
associated documentation files (the "Software"), to
deal in the Software without restriction, including
without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the
following conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

*/

/** \file
 *
 * \brief The implementation of the sswf::TagBase and sswf::TagBaseID classes
 *
 * This file declares the body of the functions which are not
 * inline. It is part of the SSWF library.
 */

#include	"sswf/libsswf.h"

using namespace sswf;



/////////////////////////////////////////// TagBase

/** \class sswf::TagBase
 *
 * \brief The base of all the tags
 *
 * The TagBase class is the base class for all the tags. You cannot
 * instantiate a TagBase since it has several pure virtual functions
 * (and it would not make sense.)
 * 
 * The TagBase defines basic functions and functions that the other
 * tags re-implement.
 *
 * There is a set of functions used to manage the tree of tags:
 *
 *	Name		Type of the tag (in a string)
 *	Label		Retrieve the label of the tag
 *	WhichFrame	Frame number where this tag resides
 *	SetLabel	Give a label to the tag
 *	FindLabelledTag	Search the tree for an object with that name
 *	FindTagWithID	Search the tree for an object with that identifier
 *	Children	Get a pointer to all the children of that tag
 *	Next		Get a pointer to the next tag
 *	Previous	Get a pointer to the previous tag
 *	Parent		Get a pointer to the parent
 *	Header		Get a pointer to the header (parent most tag)
 *	TypeFlags	Type of a tag defined with flags
 *
 * The tree is always started with a Header. The header can be the parent
 * of any other tag. Sprites can themselves be composed of a certain number
 * of sub-tags.
 *
 * Tags use the MinimumVersion() and Version() functions to know more about
 * the version of the current movie being saved.
 *
 * The following functions are used to help you save the movie. Mainly the
 * tags when saving themselves use these functions as helpers.
 *	
 *	Save		Save the whole tag and its content
 *	PreSave		Prepare the tag to be saved (usually to determine the
 *			minimum version required to save that tag)
 *	PreSave2ndPass	Prepare the tag once the exact version of the movie
 *			is known (especially used by the TagFont); this may
 *			still generate a fatal error if the tag cannot be
 *			saved properly
 *	SaveString	Save a C string
 *	SaveTag		Save the tag number and size
 *	SIBitSize	Number of bits necessary to save a specified value
 *	UIBitSize	Number of bits necessary to save a specified value
 *	Double2Signed	Transform a double in a fixed value
 *	Signed2Double	Transform a fixed value to a double
 *
 * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference&mdash;swf_tag</a>
 */


/** \typedef sswf::TagBase::swf_type_t
 *
 * \brief An integer holding flags representing the type of a tag.
 *
 * This type is used by the sswf::TagBase::TypeFlags() function.
 * It represents different flags that different tags can set. They
 * are used to determine the generic type of a tag.
 *
 * The two main groups of tags are the CONTROL tags and the DEFINE
 * tags.
 */




/** \typedef sswf::TagBase::swf_tag_t
 *
 * \brief Defines all the tags supported by SSWF.
 *
 * This type lists all the tags supported by SSWF. The numbers are
 * those saved in the final SWF output.
 *
 * The \ref SWF_TAG_UNKNOWN and \ref SWF_TAG_max are only for the
 * SSWF library to declare unknown tags and know what the largest
 * possible value in the current version.
 *
 * The \ref SWF_TAG_END has the special value of zero.
 */


/** \var sswf::TagBase::SWF_TAG_UNKNOWN
 *
 * \brief An undefined or unknown tag
 *
 * This special SSWF tag value is used to mark an unknown or undefined
 * tag number. It cannot be saved in an SWF file.
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_END
 *
 * \brief The last tag in a list of tags.
 *
 * This tag is used to terminate a list of tags. In general you don't
 * need to terminate your lists since the library does it for you.
 *
 * Also, the library will ensure that a \ref SWF_TAG_SHOW_FRAME is included.
 *
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_end">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_SHOW_FRAME
 *
 * \brief This tag marks the end of the current frame.
 *
 * An SWF movie is composed of a set of frames. Each frame is
 * terminated with one %SWF_TAG_SHOW_FRAME tag.
 *
 * Adding multiple %SWF_TAG_SHOW_FRAME tags one after another
 * is a way to slow down the playback at different location in
 * your SWF movie.
 *
 * There should be a show frame tag before any end tag.
 *
 * \sa SWF_TAG_END
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_showframe">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_SHAPE
 *
 * \brief Defines a shape
 *
 * Of the different graphical objects supported by SWF, the shapes
 * are the primary ones. Shapes are vector based objects.
 *
 * \sa SWF_TAG_DEFINE_SHAPE2
 * \sa SWF_TAG_DEFINE_SHAPE3
 * \sa SWF_TAG_DEFINE_SHAPE4
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE2
 * \sa <a href="../SWFalexref.html#tag_defineshape">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_PLACE_OBJECT
 *
 * \brief Place an object in the display list
 *
 * This tag places an object such as a shape or a sprite in the
 * current display list.
 *
 * \sa SWF_TAG_PLACE_OBJECT2
 * \sa SWF_TAG_PLACE_OBJECT3
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_placeobject">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_REMOVE_OBJECT
 *
 * \brief Remove an object from the display list
 *
 * This tag removes an object from the display list. You need to specify the
 * object identifier and the depth at which it was inserted.
 *
 * You can use the SWF_TAG_REMOVE_OBJECT2 to reduce the size of the tag used
 * to remove an object since in that case the identifier is not included. In
 * most cases, the depth is enough since only one object should be inserted
 * at one depth.
 *
 * \sa SWF_TAG_REMOVE_OBJECT2
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_removeobject">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_BITS
 *
 * \brief This tag is deprecated. Please use SWF_TAG_DEFINE_BITS_JPEG instead.
 *
 * \sa SWF_TAG_DEFINE_BITS_JPEG
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_BITS_JPEG
 *
 * \brief Define a JPEG image data.
 *
 * This tag is used to define a 2D image.
 *
 * This is a synonym of SWF_TAG_DEFINE_BITS which is deprecated in the SSWF
 * library.
 *
 * \sa SWF_TAG_DEFINE_BITS_LOSSLESS
 * \sa SWF_TAG_DEFINE_BITS_LOSSLESS2
 * \sa SWF_TAG_JPEG_TABLES
 * \sa SWF_TAG_DEFINE_BITS_JPEG2
 * \sa SWF_TAG_DEFINE_BITS_JPEG3
 * \sa <a href="../SWFalexref.html#tag_definebits">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_BUTTON
 *
 * \brief Define some image data.
 *
 * This tag is used to define a button. This really means an active area (it does
 * not need to react to clicks.)
 *
 * \sa SWF_TAG_DEFINE_BUTTON2
 * \sa SWF_TAG_DEFINE_BUTTON_COLOR_TRANSFORM
 * \sa <a href="../SWFalexref.html#tag_definebutton">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_JPEG_TABLES
 *
 * \brief Define compression tables for JPEG images.
 *
 * To save some space, multiple JPEG images may share the same set of compression
 * tables. In reality, this can result in a high decrease in decompressed image
 * quality and in practice it is rarely used these days.
 *
 * \sa SWF_TAG_DEFINE_BITS_JPEG
 * \sa <a href="../SWFalexref.html#tag_jpegtables">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_SET_BACKGROUND_COLOR
 *
 * \brief Defines the color to use for the animation background.
 *
 * To save some space, multiple JPEG images may share the same set of compression
 * tables. In reality, this can result in a high decrease in decompressed image
 * quality and in practice it is rarely used these days.
 *
 * \sa <a href="../SWFalexref.html#tag_setbackgroundcolor">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_FONT
 *
 * \brief Define a version 1 font
 *
 * This tag is used to declare an internal or external font definition.
 * Fonts are composed of glyphs which happen to be shapes.
 *
 * \warning
 * This font cannot be referenced from an SWF_TAG_TEXT_FIELD tag. Instead,
 * you need to use an SWF_TAG_DEFINE_FONT2.
 *
 * \sa SWF_TAG_DEFINE_FONT2
 * \sa SWF_TAG_DEFINE_FONT3
 * \sa SWF_TAG_TEXT_FIELD
 * \sa SWF_TAG_DEFINE_FONT_ALIGN_ZONES
 * \sa SWF_TAG_CSM_TEXT_SETTINGS
 * \sa <a href="../SWFalexref.html#tag_definefont">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_TEXT
 *
 * \brief Define a graphical object to draw text
 *
 * This tag defines a string to be displayed using a specified font.
 *
 * \sa SWF_TAG_DEFINE_TEXT2
 * \sa SWF_TAG_TEXT_FIELD
 * \sa <a href="../SWFalexref.html#tag_definetext">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DO_ACTION
 *
 * \brief Define an SWF ActionScript
 *
 * This tag is used to execute an ActionScript.
 *
 * \sa SWF_TAG_DO_INIT_ACTION
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa SWF_TAG_ACTIONSCRIPT2
 * \sa SWF_TAG_ACTIONSCRIPT2_DEFINE
 * \sa SWF_TAG_ACTIONSCRIPT2_INSTANTIATE
 * \sa <a href="../SWFalexref.html#tag_doaction">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_FONT_INFO
 *
 * \brief Define font metrics, names, etc.
 *
 * This tag is used to define more details about a font such as its
 * name and whether to try to use the system font if available.
 *
 * \sa SWF_TAG_DEFINE_FONT_INFO2
 * \sa SWF_TAG_DEFINE_TEXT
 * \sa SWF_TAG_TEXT_FIELD
 * \sa <a href="../SWFalexref.html#tag_definefontinfo">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_SOUND
 *
 * \brief Define a sound data block
 *
 * This tag defines a block of data which represent a sound. It
 * can be played with the \ref SWF_TAG_START_SOUND tag.
 *
 * \sa <a href="../SWFalexref.html#tag_definesound">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_START_SOUND
 *
 * \brief Starts playing a sound
 *
 * This tag starts playing a sound previously defined with
 * an \ref SWF_TAG_DEFINE_SOUND tag. The same sound can be
 * played multiple times. Also this tag can be used to stop
 * playing a sound (which is why there are no 'stop sound'
 * tag.)
 *
 * \sa SWF_TAG_DEFINE_SOUND
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_startsound">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_BUTTON_SOUND
 *
 * \brief Attach sound effects to a button
 *
 * This tag attaches sound effects to a button. The
 * sounds will be played whenever a given event occur.
 *
 * \sa <a href="../SWFalexref.html#tag_definebuttonsound">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_SOUND_STREAM_HEAD
 *
 * \brief Header defining a streaming sound
 *
 * This tag initializes a streaming sound effect. The actual data of
 * the sound effect is in the SWF_TAG_SOUND_STREAM_BLOCK tags which
 * follow.
 *
 * \sa SWF_TAG_SOUND_STREAM_BLOCK
 * \sa SWF_TAG_SOUND_STREAM_HEAD2
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_soundstreamhead">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_SOUND_STREAM_BLOCK
 *
 * \brief Block of data of a streaming sound
 *
 * This tag defines data for the streaming sound started with
 * an SWF_TAG_SOUND_STREAM_HEAD or SWF_TAG_SOUND_STREAM_HEAD2 tag.
 *
 * \sa SWF_TAG_SOUND_STREAM_HEAD
 * \sa SWF_TAG_SOUND_STREAM_HEAD2
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_soundstreamblock">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_BITS_LOSSLESS
 *
 * \brief Define a PNG image data.
 *
 * This tag inserts a PNG image. This can be used for much higher image
 * quality, but it is in general larger than a JPEG image.
 *
 * \sa SWF_TAG_DEFINE_BITS_LOSSLESS2
 * \sa SWF_TAG_DEFINE_BITS_JPEG
 * \sa SWF_TAG_DEFINE_BITS_JPEG2
 * \sa SWF_TAG_DEFINE_BITS_JPEG3
 * \sa <a href="../SWFalexref.html#tag_definebitslossless">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */


/** \var sswf::TagBase::SWF_TAG_DEFINE_BITS_JPEG2
 *
 * \brief Define a JPEG image data and tables.
 *
 * This tag inserts a complete JPEG image, meaning the JPEG data and tables
 * are all saved in this tag.
 *
 * \sa SWF_TAG_DEFINE_BITS_JPEG
 * \sa SWF_TAG_DEFINE_BITS_JPEG3
 * \sa SWF_TAG_DEFINE_BITS_LOSSLESS
 * \sa SWF_TAG_DEFINE_BITS_LOSSLESS2
 * \sa <a href="../SWFalexref.html#tag_definebitsjpeg2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */




/** \var sswf::TagBase::SWF_TAG_DEFINE_SHAPE2
 *
 * \brief Define an extended shape.
 *
 * This tag is used to define a shape. This tag extends the SWF_TAG_DEFINE_SHAPE
 * by allowing more vectices within a single shape.
 *
 * \sa SWF_TAG_DEFINE_SHAPE
 * \sa SWF_TAG_DEFINE_SHAPE3
 * \sa SWF_TAG_DEFINE_SHAPE4
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE2
 * \sa <a href="../SWFalexref.html#tag_defineshape2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_BUTTON_COLOR_TRANSFORM
 *
 * \brief Define a simple color transformation for a button.
 *
 * This tag is a button complete used to allow a color transformation of the
 * shape used in a button.
 *
 * If you really need color transformations, it is usually better to use the
 * SWF_TAG_DEFINE_BUTTON2 and get the color transformation on a per state
 * basis.
 *
 * \sa SWF_TAG_DEFINE_BUTTON
 * \sa SWF_TAG_DEFINE_BUTTON2
 * \sa <a href="../SWFalexref.html#tag_definebuttoncxform">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_PROTECT
 *
 * \brief Mark the movie as protected (opposed to open)
 *
 * This precense of this tag marks the entire movie as protected. The concept is
 * that a protected movie cannot be edited by a person other than the author (who
 * has the source file used to generate this movie.)
 *
 * This tag was introducted in version 4 and it 100% protects the movie. That is,
 * even the author cannot re-read the movie (unless you either remove this tag
 * from the movie or you use a tool which ignores the tag.)
 *
 * In order for the authors to be able to re-read the movie later, you need to let
 * the author enter a password. This is done using the SWF_TAG_PROTECT_DEBUG or
 * SWF_TAG_PROTECT_DEBUG2 tag (which tag to use will actually depend on the movie
 * version and not what you want to do with it.)
 *
 * \sa SWF_TAG_PROTECT_DEBUG
 * \sa SWF_TAG_PROTECT_DEBUG2
 * \sa <a href="../SWFalexref.html#tag_protect">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_PLACE_OBJECT2
 *
 * \brief Place or remove an object.
 *
 * This tag lets you place, replace or remove an object at a given depth.
 *
 * \sa SWF_TAG_PLACE_OBJECT
 * \sa SWF_TAG_PLACE_OBJECT3
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_placeobject2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_REMOVE_OBJECT2
 *
 * \brief Remove an object at a specified depth.
 *
 * This tag lets you remove one object at a given depth without having to
 * specify its reference ID.
 *
 * \sa SWF_TAG_REMOVE_OBJECT
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_removeobject2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_SHAPE3
 *
 * \brief Defines a shape which supports transparency.
 *
 * This tag is similar to the SWF_TAG_DEFINE_SHAPE and SWF_TAG_DEFINE_SHAPE2.
 * It adds the capability to define an alpha channel along the shape colors.
 *
 * \sa SWF_TAG_DEFINE_SHAPE
 * \sa SWF_TAG_DEFINE_SHAPE2
 * \sa SWF_TAG_DEFINE_SHAPE4
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE2
 * \sa <a href="../SWFalexref.html#tag_defineshape3">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_TEXT2
 *
 * \brief Defines a text which supports transparency.
 *
 * This tag is similar to the SWF_TAG_DEFINE_TEXT. It adds the capability
 * to define an alpha channel along the glyphs colors.
 *
 * \sa SWF_TAG_DEFINE_TEXT
 * \sa SWF_TAG_TEXT_FIELD
 * \sa SWF_TAG_DEFINE_FONT_INFO
 * \sa SWF_TAG_DEFINE_FONT_INFO2
 * \sa <a href="../SWFalexref.html#tag_definetext2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_BUTTON2
 *
 * \brief Defines a button which reacts upon a set of predefined events.
 *
 * This tag is similar to the SWF_TAG_DEFINE_BUTTON. It adds the capability
 * to define an event which needs to occur for the linked actions to be
 * executed.
 *
 * \sa SWF_TAG_DEFINE_BUTTON
 * \sa <a href="../SWFalexref.html#tag_definebutton2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_BITS_JPEG3
 *
 * \brief Defines a JPEG image with an Alpha channel.
 *
 * This tag is an extension of the SWF_TAG_DEFINE_BITS_JPEG2 which supports
 * an alpha channel. Thus this tag includes a full JPEG definition and a
 * plane compressed with zlib to define an Alpha channel.
 *
 * \sa SWF_TAG_DEFINE_BITS_LOSSLESS
 * \sa SWF_TAG_DEFINE_BITS_LOSSLESS2
 * \sa SWF_TAG_DEFINE_BITS_JPEG
 * \sa SWF_TAG_DEFINE_BITS_JPEG2
 * \sa <a href="../SWFalexref.html#tag_definebitsjpeg3">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_BITS_LOSSLESS2
 *
 * \brief Defines a loss less image with an Alpha channel.
 *
 * This tag is an extension of the SWF_TAG_DEFINE_BITS_LOSSLESS which supports
 * an alpha channel. Thus this tag includes a full JPEG definition and a
 * plane compressed with zlib to define an Alpha channel.
 *
 * \sa SWF_TAG_DEFINE_BITS_LOSSLESS
 * \sa SWF_TAG_DEFINE_BITS_JPEG
 * \sa SWF_TAG_DEFINE_BITS_JPEG2
 * \sa SWF_TAG_DEFINE_BITS_JPEG3
 * \sa <a href="../SWFalexref.html#tag_definebitslossless2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_SPRITE
 *
 * \brief Defines a sprite: an object composed of any number of other objects
 *
 * A sprite is composed of a control list. This means any tag marked as a
 * CONTROL tag such as SWF_TAG_PLACE_OBJECT. You cannot use a definition tag
 * within a sprite. However, you can put a script which creates new objects.
 *
 * \sa SWF_TAG_DO_ACTION
 * \sa SWF_TAG_END
 * \sa SWF_TAG_FRAME_LABEL
 * \sa SWF_TAG_PLACE_OBJECT
 * \sa SWF_TAG_PLACE_OBJECT2
 * \sa SWF_TAG_PLACE_OBJECT3
 * \sa SWF_TAG_REMOVE_OBJECT
 * \sa SWF_TAG_REMOVE_OBJECT2
 * \sa SWF_TAG_SHOW_FRAME
 * \sa SWF_TAG_SOUND_STREAM_BLOCK
 * \sa SWF_TAG_SOUND_STREAM_HEAD
 * \sa SWF_TAG_SOUND_STREAM_HEAD2
 * \sa SWF_TAG_START_SOUND
 * \sa <a href="../SWFalexref.html#tag_definesprite">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */





/** \var sswf::TagBase::SWF_TAG_PRODUCT_INFO
 *
 * \brief Defines the name of the product used to create the SWF file.
 *
 * This tag holds information about the product used to create this SWF file.
 *
 * It is all defined as numbers (Identifiers). It includes many versions and the
 * date when it was compiled.
 *
 * \sa <a href="../SWFalexref.html#tag_productinfo">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_FRAME_LABEL
 *
 * \brief Defines the name of the current frame
 *
 * This tag names a frame in order to allow scripts to jump to that
 * frame by name.
 *
 * A URL can also specify a frame label (since version 6 of SWF).
 *
 * \sa SWF_TAG_DO_ACTION
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_framelabel">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_SOUND_STREAM_HEAD2
 *
 * \brief Initializes the streaming sound effect.
 *
 * This tag initializes a streaming sound effect. The actual data of
 * the sound effect is in the SWF_TAG_SOUND_STREAM_BLOCK tags which
 * follow.
 *
 * \sa SWF_TAG_SOUND_STREAM_BLOCK
 * \sa SWF_TAG_SOUND_STREAM_HEAD
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_soundstreamhead2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_MORPH_SHAPE
 *
 * \brief Defines a set of shapes to morph.
 *
 * This tag is similar to the SWF_TAG_DEFINE_SHAPE tag except that it defines
 * two shapes. When placing this shape with SWF_TAG_PLACE_OBJECT2, you can
 * specify the morphing position (percentage).
 *
 * \sa SWF_TAG_DEFINE_SHAPE
 * \sa SWF_TAG_DEFINE_SHAPE2
 * \sa SWF_TAG_DEFINE_SHAPE3
 * \sa SWF_TAG_DEFINE_SHAPE4
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE2
 * \sa <a href="../SWFalexref.html#tag_definemorphshape">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_FONT2
 *
 * \brief Defines a set of glyphs in a font.
 *
 * This tag is used to declare an internal or external font definition.
 * Internal fonts are composed of glyphs which happen to be shapes.
 *
 * This font (or a newer version) is required if you reference the font
 * from an SWF_TAG_TEXT_FIELD tag.
 *
 * \sa SWF_TAG_DEFINE_FONT
 * \sa SWF_TAG_DEFINE_FONT3
 * \sa SWF_TAG_TEXT_FIELD
 * \sa SWF_TAG_DEFINE_FONT_ALIGN_ZONES
 * \sa SWF_TAG_CSM_TEXT_SETTINGS
 * \sa <a href="../SWFalexref.html#tag_definefont2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DEFINE_INFO
 *
 * \brief Put info in the file.
 *
 * This tag seems to be used by Macromedia Flash MX to insert some sort of
 * a comment in the SWF movies. Do not use unless you know what you're doing!
 *
 * \sa <a href="../SWFalexref.html#tag_defineinfo">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_TEXT_FIELD
 *
 * \brief Defines a field of editable text.
 *
 * This tag is used to create an edit box where end users can type text.
 * You can specify the font, sizes, edit mode (it can even be read-only!)
 *
 * This can be used as a dynamic box to display a string to the user
 * (i.e. an ActionScript can write a string in a text field.)
 *
 * \sa SWF_TAG_DEFINE_TEXT
 * \sa SWF_TAG_DEFINE_TEXT2
 * \sa SWF_TAG_DEFINE_FONT_INFO
 * \sa SWF_TAG_DEFINE_FONT_INFO2
 * \sa SWF_TAG_SET_TAB_INDEX
 * \sa <a href="../SWFalexref.html#tag_defineedittext">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_EXPORT
 *
 * \brief Make objects visible to the external world.
 *
 * This tag lists objects from this SWF movie that you want to be able to
 * used from other SWF movies with the use of the SWF_TAG_IMPORT tag.
 *
 * \sa SWF_TAG_IMPORT
 * \sa SWF_TAG_IMPORT2
 * \sa <a href="../SWFalexref.html#tag_export">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_IMPORT
 *
 * \brief Retrieve objects from another SWF movie.
 *
 * This tag lists the objects from another movie that this SWF movie is
 * interested in. The resulting effect is as if these objects had been
 * defined in this SWF movie. This tag can be used in movies version
 * 5, 6 or 7. Since version 8, use must SWF_TAG_IMPORT2.
 *
 * \sa SWF_TAG_EXPORT
 * \sa SWF_TAG_IMPORT2
 * \sa <a href="../SWFalexref.html#tag_import">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_PROTECT_DEBUG
 *
 * \brief Mark the animation as protected and include a password.
 *
 * This tag is used to add a password to your animation. This in effect
 * protects the movie so you are the only one who can load it (and thus
 * debug it.)
 *
 * This tag is only available in SWF version 5.
 *
 * \warning
 * Of course, tools which ignore this tag will be capable of reading
 * your entire animation since this is just one tag among others and
 * it isn't used to decode the rest of the animation.
 *
 * \sa SWF_TAG_PROTECT
 * \sa SWF_TAG_PROTECT_DEBUG2
 * \sa <a href="../SWFalexref.html#tag_protectdebug">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */



/** \var sswf::TagBase::SWF_TAG_DO_INIT_ACTION
 *
 * \brief Execute actions only once.
 *
 * This tag is like the SWF_TAG_DO_ACTION but it is executed at most
 * once per session even when the display list loops through that tag
 * over and over again.
 *
 * "It is often used to initialize a sprite"&mdash;which means that
 * quite often it will be used to initialize an object class.
 *
 * Note that the tag is not part of the sprite. It references it.
 *
 * \sa SWF_TAG_DO_ACTION
 * \sa SWF_TAG_ACTIONSCRIPT2
 * \sa SWF_TAG_ACTIONSCRIPT2_DEFINE
 * \sa SWF_TAG_ACTIONSCRIPT2_INSTANTIATE
 * \sa <a href="../SWFalexref.html#tag_doinitaction">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */







/** \var sswf::TagBase::SWF_TAG_DEFINE_FONT_INFO2
 *
 * \brief Defines a font including language specifications.
 *
 * This tag declares additional information about a font (i.e. use a corresponding
 * system font name or a list of glyphs to declare an embedded font.)
 *
 * This is similar to the SWF_TAG_DEFINE_FONT_INFO plus the
 * language support.
 *
 * \sa SWF_TAG_DEFINE_FONT_INFO
 * \sa SWF_TAG_DEFINE_TEXT
 * \sa SWF_TAG_TEXT_FIELD
 * \sa <a href="../SWFalexref.html#tag_definefontinfo2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_PROTECT_DEBUG2
 *
 * \brief Mark the animation as protected and include a password.
 *
 * This tag is used to add a password to your animation. This in effect
 * protects the movie so you are the only one who can load it (and thus
 * debug it.)
 *
 * This tag is available since SWF version 6. It includes an additional
 * 2 bytes (compared to SWF_TAG_PROTECT_DEBUG) for what looks like a version
 * or a compression mode for the password.
 *
 * \warning
 * Of course, tools which ignore this tag will be capable of reading
 * your entire animation since this is just one tag among others and
 * it isn't used to decode the rest of the animation.
 *
 * \sa <a href="../SWFalexref.html#tag_protectdebug2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */





/** \var sswf::TagBase::SWF_TAG_SCRIPT_LIMITS
 *
 * \brief Define different limits for script execution.
 *
 * This tag is used to change script limits. For instance, it happens
 * that someone writes a loop which lasts forever (in computer world
 * this means more than one frame). This may be a problem when you are
 * trying to playback streaming sound, a realtime video and complex
 * animated sprites.
 *
 * The default is to stop these scritps after a small amount of time
 * elapsed. If that time is too small, then you can increase it with
 * this tag.
 *
 * \sa <a href="../SWFalexref.html#tag_scriptlimits">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */





/** \var sswf::TagBase::SWF_TAG_SET_TAB_INDEX
 *
 * \brief Define the position or indices of each tab stops
 *
 * This tag is used in link with the HTML support of the SWF_TAG_TEXT_FIELD
 * tag.
 *
 * \sa SWF_TAG_TEXT_FIELD
 * \sa <a href="../SWFalexref.html#tag_settabindex">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_FILE_ATTRIBUTES
 *
 * \brief Define some attributes in regard to the use of the file.
 *
 * This tag must be the very first after the header. It is used to make sure
 * that the player can support the movie. A set of flags are defined to
 * determine whether all the capabilities required by that movie can be met.
 *
 * The library hides this tag within the sswf::TagHeader object.
 *
 * \sa SWF_TAG_TEXT_FIELD
 * \sa <a href="../SWFalexref.html#tag_fileattributes">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_PLACE_OBJECT3
 *
 * \brief Place or remove an object.
 *
 * This place object adds support for blend modes, filters and bitmap caching
 * which the SWF_TAG_PLACE_OBJECT2 does not support.
 *
 * It can be used inside a sprite.
 *
 * \sa SWF_TAG_PLACE_OBJECT
 * \sa SWF_TAG_PLACE_OBJECT2
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa <a href="../SWFalexref.html#tag_placeobject3">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_IMPORT2
 *
 * \brief Retrieve objects from another SWF movie.
 *
 * This tag lists the objects from another movie that this SWF movie is
 * interested in. The resulting effect is as if these objects had been
 * defined in this SWF movie. 
 *
 * Use this tag instead of SWF_TAG_IMPORT in a version 8 or newer of SWF.
 * You must use SWF_TAG_IMPORT for an animation version 5, 6 ot 7.
 *
 * \sa SWF_TAG_IMPORT
 * \sa SWF_TAG_EXPORT
 * \sa <a href="../SWFalexref.html#tag_import2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_DEFINE_FONT_ALIGN_ZONES
 *
 * \brief Define hints on how to align the glyphs of a font.
 *
 * This tag defines a few hints used to know how to place glyphs on the
 * screen. This is useful to avoid glyphs rendered on half pixels and
 * thus getting too blurry. This alignment definition is really only
 * partially useful for italic fonts.
 *
 * \sa SWF_TAG_DEFINE_FONT
 * \sa SWF_TAG_DEFINE_FONT2
 * \sa SWF_TAG_DEFINE_FONT3
 * \sa SWF_TAG_CSM_TEXT_SETTINGS
 * \sa <a href="../SWFalexref.html#tag_definefontalignzones">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_CSM_TEXT_SETTINGS
 *
 * \brief Define hints on how to align and render the glyphs of a font.
 *
 * This tag defines a few hints used to know how to place glyphs on the
 * screen and which renderer to use to draw the font.
 *
 * Note that the selection of the mode is really poor since it gives you
 * a way to force CRT or LCD monitor but nothing dynamic...
 *
 * \sa SWF_TAG_DEFINE_FONT
 * \sa SWF_TAG_DEFINE_FONT2
 * \sa SWF_TAG_DEFINE_FONT3
 * \sa SWF_TAG_DEFINE_FONT_ALIGN_ZONES
 * \sa <a href="../SWFalexref.html#tag_csmtextsettings">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_DEFINE_FONT3
 *
 * \brief Defines a set of glyphs in a font.
 *
 * This tag is used to declare an internal or external font definition.
 * Internal fonts are composed of glyphs which happen to be shapes.
 *
 * The main difference between this font definition and the
 * SWF_TAG_DEFINE_FONT2 is that sub-pixels have an extra 20 sub-divisions.
 *
 * \sa SWF_TAG_DEFINE_FONT
 * \sa SWF_TAG_DEFINE_FONT2
 * \sa SWF_TAG_DEFINE_FONT_ALIGN_ZONES
 * \sa SWF_TAG_CSM_TEXT_SETTINGS
 * \sa <a href="../SWFalexref.html#tag_definefont3">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_METADATA
 *
 * \brief Defines humain readable information about the animation.
 *
 * This tag needs to be defined near the beginning of the movie and it includes
 * a set of humain readable strings saved in a string formatted using some XML.
 * The only purpose of this tag (at this time) is for search engines to reference
 * your animation properly without having to understand the complex format that
 * is SWF.
 *
 * \sa <a href="../SWFalexref.html#tag_metadata">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_DEFINE_SCALING_GRID
 *
 * \brief Defines a grid used to resize an object.
 *
 * This tag defines a rectangle within the specified shape which is fully resized.
 * The top and bottom edges are only stretched horizontally; the left and right edges
 * are only stretched vertically; the corners are never resized.
 *
 * This is quite used by sswf::TagButton and sswf::TagSprite.
 *
 * \sa SWF_TAG_DEFINE_BUTTON
 * \sa SWF_TAG_DEFINE_BUTTON2
 * \sa sswf::TagButton
 * \sa SWF_TAG_DEFINE_SPRITE
 * \sa sswf::TagSprite
 * \sa <a href="../SWFalexref.html#tag_definescalinggrid">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */





/** \var sswf::TagBase::SWF_TAG_DEFINE_SHAPE4
 *
 * \brief Defines a shape with enhanced strokes
 *
 * This shape is similar to all the previous shapes plus it lets you
 * choose which stroke to use. You can select how the strokes are
 * rendered and whether they follow the scaling factor.
 *
 * \sa SWF_TAG_DEFINE_SHAPE
 * \sa SWF_TAG_DEFINE_SHAPE2
 * \sa SWF_TAG_DEFINE_SHAPE3
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE2
 * \sa <a href="../SWFalexref.html#tag_defineshape4">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_DEFINE_MORPH_SHAPE2
 *
 * \brief Defines a morphing shape with enhanced strokes
 *
 * This morphing shape is similar to SWF_TAG_DEFINE_MORPH_SHAPE but
 * it also support a way for the user to choose which stroke to use.
 *
 * \sa SWF_TAG_DEFINE_SHAPE
 * \sa SWF_TAG_DEFINE_SHAPE2
 * \sa SWF_TAG_DEFINE_SHAPE3
 * \sa SWF_TAG_DEFINE_SHAPE4
 * \sa SWF_TAG_DEFINE_MORPH_SHAPE
 * \sa <a href="../SWFalexref.html#tag_definemorphshape2">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_ACTIONSCRIPT2
 *
 * \brief Defines a block of ActionScript version 2
 *
 * This tag defines a list of actions to be executed. This is similar to
 * the SWF_TAG_DOACTION except that it supports a really object oriented
 * definition set.
 *
 * \sa SWF_TAG_DOACTION
 * \sa <a href="../SWFalexref.html#tag_doabc">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */




/** \var sswf::TagBase::SWF_TAG_ACTIONSCRIPT2_INSTANTIATE
 *
 * \brief Instantiate objects from a previously defined ActionScript version 2 block
 *
 * This tag defines a list of objects to create. The objects are defined in the
 * SWF_TAG_ACTIONSCRIPT2_DEFINE referenced by this tag.
 *
 * \sa SWF_TAG_ACTIONSCRIPT2_DEFINE
 * \sa <a href="../SWFalexref.html#tag_symbolclass">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */




/** \var sswf::TagBase::SWF_TAG_ACTIONSCRIPT2_DEFINE
 *
 * \brief Create an ActionScript version 2 which can later be referenced
 *
 * This tag defines a list of classes to instantiate later with the use of an
 * SWF_TAG_ACTIONSCRIPT2_INSTANTIATE.
 *
 * \sa SWF_TAG_ACTIONSCRIPT2_INSTANTIATE
 * \sa <a href="../SWFalexref.html#tag_doabcdefine">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */




/** \var sswf::TagBase::SWF_TAG_SCENE_FRAME_DATA
 *
 * \brief Define raw data for a scene and frame.
 *
 * This tag defines raw data usable by a scene and frame.
 *
 * \sa SWF_TAG_DEFINE_BINARY_DATA
 * \sa <a href="../SWFalexref.html#tag_definesceneandframedata">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */




/** \var sswf::TagBase::SWF_TAG_DEFINE_BINARY_DATA
 *
 * \brief Define binary data a script can use later.
 *
 * This tag defines some user defined binary data.
 *
 * \sa SWF_TAG_SCENE_FRAME_DATA
 * \sa <a href="../SWFalexref.html#tag_definebinarydata">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */





/** \var sswf::TagBase::SWF_TAG_DEFINE_FONT_NAME
 *
 * \brief Define the name and copyright of a font.
 *
 * This tag defines the legal name and copyright of an embedded font.
 *
 * \sa SWF_TAG_DEFINE_FONT
 * \sa SWF_TAG_DEFINE_FONT2
 * \sa SWF_TAG_DEFINE_FONT3
 * \sa SWF_TAG_DEFINE_FONT_INFO
 * \sa SWF_TAG_DEFINE_FONT_INFO2
 * \sa <a href="../SWFalexref.html#tag_definebinarydata">SWF Alexis' Reference</a>
 *
 * <br>
 * <br>
 */






/** \var sswf::TagBase::SWF_TAG_max
 *
 * \brief Mark the end of the list of tags.
 *
 * No tag is defined beyond this point, SWF_TAG_max included, in what the SSWF
 * library supports. Also, new tags may be created by Macromedia beyond this point
 * before SSWF is updated.
 *
 * This can be used for a rather weak test to know whether a tag number is valid.
 * It is a weak test since many values between 0 and SWF_TAG_max are not defined.
 */









/** \brief Initialize the base information of a tag
 *
 * Each tag needs to have a name. The name is actually the type of the
 * tag and not a user name. This is enforced by all the derived tags
 * (i.e. the users of the library cannot themselves define this name.)
 *
 * The parent can be set to NULL (especially if you are creating the
 * TagHeader object). Otherwise it needs to be a tag which supports
 * having children (i.e. TagHeader or TagSprite).
 *
 * \note
 * It is possible to add a TagEnd which is not at the very end of
 * the movie. This is useful in order to test the movie up to that
 * point.
 *
 * \bug
 * When creating a child (i.e. the parent pointer is not null) the
 * new child is linked at the end of the existing list of children.
 * At this time, there is no way to change the order of children
 * other than creating a new parent and add all the children in the
 * new order...
 *
 * The parent is now given a chance to reject a child. When that
 * happens, the constructor \e returns \e normally, but the new
 * tag is not becoming a child of the specified parent. You can
 * test this with the following line of code:
 *
 * \code
 *	if(sswf::TagBase::Parent() != parent) ... // oops!
 * \endcode
 *
 * \param name The type of the tag in the form of a string
 * \param parent The parent tag (a header or a sprite)
 */
TagBase::TagBase(const char *name, TagBase *parent)
{
	register TagBase		*tail;
	ErrorManager::error_code_t	err;

	if(parent != 0) {
		err = parent->OnNewChild(name);
		if(err != ErrorManager::ERROR_CODE_NONE) {
			// that parent did not accept this child
			OnError(err, "the parent tag \"%s\" did not accept the child \"%s\"", parent->Name(), name);
			parent = 0;
		}
	}

	f_userdata = 0;		// by default we initialize to zero

	f_name = name;
	f_label = 0;		// no label by default, use SetLabel() to set it

	f_parent = parent;
	f_next = 0;
	f_previous = 0;
	f_children = 0;

	f_frames = 0;		// should be reset each time it is to be used!

	// link into the parent if there is one
	if(parent != 0) {
		// the order is VERY important so we HAVE to
		// link at the end of the list
		tail = parent->f_children;
		if(tail == 0) {
			parent->f_children = this;
		}
		else {
			while(tail->f_next != 0) {
				tail = tail->f_next;
			}
			// NOTE: if(tail->f_name == 'end') error?
			// at this time, we let people add tags after the end...
			f_previous = tail;
			tail->f_next = this;
		}
	}
}


/** \brief Clean up the base information of a tag
 *
 * This function takes care of deleting all the children
 * of a tag and unlinking the tag from its sibling and/or
 * parent.
 */
TagBase::~TagBase()
{
	// if we are being deleted, we ought to delete our children
	// (we may change that at a later time, but it seems as if it were a valid argument right now)
	while(f_children != 0) {
#if DEBUG
#if 0
// IsBuffer() isn't a valid function at this time
fprintf(stderr, "Delete child [%s] [%s] (%d)\n",
				f_children->f_name,
				f_children->f_label == 0 ? "<no label>" : f_children->f_label,
				Buffer::IsBuffer(f_children));
		assert(Buffer::IsBuffer(f_children) == 0, "a tag object can't be attached to another object (name: \"%s\", label: \"%s\")",
				f_children->f_name,
				f_children->f_label == 0 ? "<no label>" : f_children->f_label);
#endif
#endif
		delete f_children;
	}

	if(f_previous == 0) {
		if(f_parent != 0) {
			f_parent->f_children = f_next;
		}
	}
	else {
		f_previous->f_next = f_next;
	}
	if(f_next != 0) {
		f_next->f_previous = f_previous;
	}
}


/** \brief Check the validity of this child for a parent tag
 *
 * Whenever a tag is added as a child to another tag, the parent has
 * a chance to tell whether it accepts the child.
 *
 * For instance, a sswf::TagHeader cannot be a child of any other tag.
 *
 * The sswf::TagSprite also only accept a small set of the control
 * tags.
 *
 * \warning
 * This function is called from the constructor and thus it cannot
 * use any virtual function on the child. This is why you only
 * receive the name of the child and not a pointer to it.
 *
 * \sa sswf::TagHeader::OnNewChild(const char *child)
 * \sa sswf::TagSprite::OnNewChild(const char *child)
 */
ErrorManager::error_code_t TagBase::OnNewChild(const char *child_name) const
{
	// by default no children allowed in tags
	return ErrorManager::ERROR_CODE_CHILDREN_NOT_SUPPORTED;
}




/** \fn TagBase::Save(Data& data)
 *
 * \brief Pre-save all the children tags of this tag.
 *
 * The Save() function is the one you want to call to save
 * an SWF movie.
 *
 * You may use the Save() on any tag, however, if you do so
 * you need to properly initialize the system. For that
 * purpose, you may want to look at the code in the 
 * TagHeader::Save(Data& data) function.
 *
 * Otherwise, you simply have to call the Save() function of
 * the TagHeader. That will save the entire movie with the
 * smallest possible version (or fail if something cannot be
 * saved with the present parameters.)
 *
 * The TagHeader::Save() function first calls the PreSave()
 * functions, the PreSave2ndPass() and then the Save() functions
 * of all the children.
 *
 * The other tag Save() function simply save the tag within the
 * specified Data buffer. Note however that the TagSprite will
 * also call the Save() function of all of its children. Yet it
 * does not call the PreSave() functions.
 *
 * The Save() function saves the movie in a Data buffer. Later
 * you need to save that buffer on disk or some other medium.
 *
 * \return Zero when the Save() succeeds, non-zero if it fails
 *
 * \sa TagBase::PreSave()
 * \sa TagBase::PreSave2ndPass()
 */

/** \brief Pre-save all the children tags of this tag.
 *
 * This function calls the PreSave() function of all
 * the children unless one returns a non-zero value
 * in which case that value will be returned and the
 * process stopped.
 *
 * This function is aumatically called by the TagHeader
 * and TagSprite in order to pre-save their children.
 *
 * The PreSave() functions are expected to be used to
 * test whether a tag can be saved. Especially, most
 * tags will call the MinimumVersion() function with
 * the version required to save these tags. This
 * ensures that you can save the entire movie in a
 * valid SWF. Please, see the reference of each tag
 * for more information about what their PreSave()
 * function does.
 *
 * You should not have to call this function directly.
 *
 * \result Zero if the PreSave() succeeds; non-zero otherwise
 */
ErrorManager::error_code_t TagBase::PreSave(void)
{
	TagBase				*p;
	ErrorManager::error_code_t	ec;

//printf("--- PreSave %p (%s)\n", this, Name());

	/*
	 * By default we simply call the PreSave() of
	 * every child in this object
	 *
	 * Objects can overload this function and do their own
	 * PreSave() tests.
	 */
	p = Children();
	while(p != 0) {
		ec = p->PreSave();
		if(ec != ErrorManager::ERROR_CODE_NONE) {
			return ec;
		}
		p = p->Next();
	}

	return ErrorManager::ERROR_CODE_NONE;
}



/** \brief Pre-save all the children tags of this tag.
 *
 * The PreSave2ndPass() is the same as the PreSave()
 * function for the TagBase(). It calls the PreSave2ndPass()
 * of all the children unless one returns a non-zero value
 * in which case the process stops and that value is returned.
 *
 * The second pass is used to check more information about the
 * tag and prepare data such as tables. This is especially
 * necessary for the TagFont which needs to create all the
 * character tables to know the offsets to characters, etc.
 * This is important because that tag may be accessed before
 * its Save() function is called and it would still need to
 * know where these characters are!
 *
 * \return Zero when the PreSave2ndPass() successed; non-zero otherwise
 */
ErrorManager::error_code_t TagBase::PreSave2ndPass(void)
{
	TagBase				*p;
	ErrorManager::error_code_t	ec;

//printf("--- PreSave2ndPass %p (%s)\n", this, Name());

	/*
	 * By default we simply call the PreSave2ndPass() of
	 * every child in this object
	 */
	p = Children();
	while(p != 0) {
		ec = p->PreSave2ndPass();
		if(ec != 0) {
			return ec;
		}
		p = p->Next();
	}

	return ErrorManager::ERROR_CODE_NONE;
}


/** \brief Save a C string in a Data buffer
 *
 * Save a C string in the specified Data buffer. This is
 * a simple process since you just have to save the string
 * and then add a null terminator. However, in movies prior
 * version 6, you need to convert the string to some locale
 * encoding specified by the user. This is done transparently
 * whenever this function is called.
 *
 * This function calls the TagHeader::SaveEncodedString()
 * function. Note that the function will fail if the tag was
 * not created in a TagHeader.
 *
 * \return The length of the string not including the null terminator
 * or -1 when an error occured
 *
 * \sa TagHeader::SaveEncodedString(Data& data, const char *string)
 */
ErrorManager::error_code_t TagBase::SaveString(Data& data, const char *string)
{
	TagHeader *header = Header();
	if(header != 0) {
		return header->SaveEncodedString(data, string);
	}
	return ErrorManager::ERROR_CODE_NO_HEADER;
}



/** \brief Frame number of this tag
 *
 * All tags are saved between TagShowFrame tags. The number of
 * TagShowFrame before a tag, not including the current tag,
 * determines the frame number of that tag.
 *
 * This function will count the number of TagShowFrame before
 * 'this' tag. This number is used in different actions to be
 * able to select the frame to go to, which needs to be loaded, etc.
 *
 * The tag needs to have a Header or a Sprite as a parent for
 * this function to work.
 *
 * \return The frame on which this tag is defined
 */
sswf_frame_t TagBase::WhichFrame(void) const
{
	sswf_frame_t	result;
	const TagBase	*p;

	if(strcmp(f_name, "header") == 0 || f_parent == 0) {
		/* there can't really be a frame in a header tag!!! */
		return 0;
	}

	if(strcmp(f_parent->f_name, "header") != 0 && strcmp(f_parent->f_name, "sprite") != 0) {
		/* at this time other possible cases aren't supported... */
		return 0;
	}

	result = 0;
	p = this->f_previous;	/* start with the previous since we don't want to include the current ShowFrame */
	while(p != 0) {
		if(strcmp(p->f_name, "showframe") == 0) {
			result++;
		}
		p = p->f_previous;
	}

	return result;
}


/** \brief Name the tag (user name, internal)
 *
 * Each tag can receive a name. This is used on tags which need
 * to be found later. Mainly, tags which an action script needs
 * to access.
 *
 * This name is NOT saved in the final output. It is only a
 * convenience of the SSWF library. Some tags accept a name
 * which will be saved in the SSWF library.
 *
 * A label name will often be used so you can later search for a
 * tag to go to from within an action script.
 *
 * \note The name can be specified in UTF-8 or any other format. This
 * is specific to your code.
 *
 * \param label The name of this tag
 *
 * \bug The system does not search the existing tree to know whether
 * the specified label is already in use (for speed reasons). It is
 * expected that the developer using the SSWF library knows how to
 * avoid reusing the same name.
 *
 * That developer can test whether the name is already in use by calling
 * the FindLabel() function first. If it returns a non-null pointer,
 * then the specified label is already in use.
 *
 * If the developer has a sorted array with all the names, it will be
 * a lot faster to search than the tree of tags!
 *
 * \sa TagPlace::SetName(const char *name)
 * \sa TagBase::FindLabel(const TagBase *p, const char *label)
 * \sa TagBase::FindLabelledTag(const char *label) const
 */
void TagBase::SetLabel(const char *label)
{
	MemFree(f_label);
	f_label = StrDup(label);
}


/** \brief Return the label of a tag
 *
 * The label of a tag is a user specified name.
 * It can be anything and it is set using
 * TagBase::SetLabel(const char *label).
 *
 * \return A pointer to the label.
 *
 * \bug The pointer returned is the copy kept by the object. DO NOT MODIFY IT!
 */
const char *TagBase::Label(void) const
{
	return f_label;
}


/** \brief Find the tag with the specified user name
 *
 * This function is used to search a tag using the label set using
 * the SetLabel(const char *label) function.
 *
 * All the siblings of the specified tag are search as well as all the
 * children. The pointer of the first object with the same name is
 * returned.
 *
 * The search first check if the first object in the specified tree
 * matches. If not, then its children are searched. If none of its
 * children are searched then the next object is checked. Usually,
 * the pointer to you TagHeader is used.
 *
 * \param p A pointer to a tag, usually the Header()
 * \param label The label to search for
 *
 * \return A pointer to the tag with the specified label or NULL
 *
 * \bug This function is slow.
 *
 * \sa TagBase::SetLabel(const char *label)
 * \sa TagBase::FindLabelledTag(const char *label) const
 */
TagBase *TagBase::FindLabel(const TagBase *p, const char *label) const
{
	const TagBase		*n;

	while(p->f_previous != 0) {	// should always be false!
		p = p->f_previous;
	}
	while(p != 0) {
		if(p->f_label != 0 && strcmp(p->f_label, label) == 0) {
			return const_cast<TagBase *>(p);
		}
		if(p->f_children != 0) {
			n = FindLabel(p->f_children, label);
			if(n != 0) {
				return const_cast<TagBase *>(n);
			}
		}
		p = p->f_next;
	}

	return 0;
}


/** \brief Find a tag in the entire tree
 *
 * This function is the same as the
 * sswf::TagBase::FindLabel(const TagBase *p, const char *label) const
 * but it will always start the search from the Header() tag.
 *
 * If the label is set to NULL or the empty string, then the
 * root tag is returned (i.e. the Header() tag).
 *
 * \param label The label to search for
 *
 * \return A pointer to the tag with the specified label or NULL
 *
 * \sa sswf::TagBase::FindLabel(const TagBase *p, const char *label) const
 * \sa sswf::TagBase::SetLabel(const char *label)
 */
TagBase *TagBase::FindLabelledTag(const char *label) const
{
	// this search looks in the entire tree available
	const TagBase		*p;

	// start searching from the root tag
	p = this;
	if(p == 0) {
		// happens when 'this' is still a null pointer!
		return 0;
	}
	while(p->f_parent != 0) {
		p = p->f_parent;
	}

	if(label == 0 || label[0] == '\0') {
		// return the root in this case
		return const_cast<TagBase *>(p);
	}

	return FindLabel(p, label);
}


/** \brief Find a tag using its identifier
 *
 * Search the tree for a tag with the specified identifier.
 *
 * This function searches for the first tag in the specified
 * list. It then tests that tag with the specified identifier.
 * If it matches, it returns that object. Otherwise it will
 * check all the children of that object. If one of the child
 * matches, then that child is returned. Otherwise the next
 * tag is tested.
 *
 * Each object is expected to have a unique identifier within
 * a single movie. This is enforced by the automatic assignment
 * of identifiers at the time a TagBaseID is created.
 *
 * Note that a tag which has no identifier will never be returned
 * by this function.
 *
 * \note A valid identifier cannot be zero or have bit 15 set.
 *
 * \param p Start with the siblings of this tag
 * \param id The identifier to search for
 * \param search_import Whether to search within TagImport tags
 *
 * \return The pointer of the tag with the specified identifier or NULL
 *
 * \sa TagBase::FindLabel(const TagBase *p, const char *label)
 * \sa TagBase::FindLabelledTag(const char *label) const
 * \sa TagBase::FindTagWithID(sswf_id_t id, bool search_import) const
 */
TagBase *TagBase::FindID(const TagBase *p, sswf_id_t id, bool search_import) const
{
	const TagBase		*n;
	const TagBaseID		*tag_id;

	if(p == 0 || id == SSWF_ID_NONE) {
		return 0;
	}

	while(p->f_previous != 0) {	// should always be false!
		p = p->f_previous;
	}
	// search this level first
	while(p != 0) {
		if((p->TypeFlags() & SWF_TYPE_HAS_ID) != 0) {
			// some additional protection, just in case!
			// it is easy to make a mistake and put the wrong flag somewhere
			tag_id = dynamic_cast<const TagBaseID *>(p);
			assert(tag_id != 0, "A tag with SWF_TYPE_HAS_ID is not derived from TagBaseID");
			if(tag_id && tag_id->HasIdentification()) {
				return const_cast<TagBase *>(p);
			}
		}
		else if(search_import && strcmp(p->Name(), "import") == 0) {
			// import objects can offer multiple IDs
			if(dynamic_cast<const TagImport *>(p)->HasID(id) != 0) {
				return const_cast<TagBase *>(p);
			}
		}
		if(p->f_children != 0) {
			n = FindID(p->f_children, id, search_import);
			if(n != 0) {
				return const_cast<TagBase *>(n);
			}
		}
		p = p->f_next;
	}

	return 0;
}


/** \brief Find a tag anywhere in the tree using its identifier
 *
 * Search the entire tree for a tag with the specified
 * identifier.
 *
 * This function calls
 * TagBase::FindID(const TagBase *p, sswf_id_t id, bool search_import) const
 * with the Header() as the starting point tag.
 *
 * Note that the header has no identifier and thus the header
 * will never be returned.
 *
 * \note A valid identifier cannot be zero or have bit 15 set.
 *
 * \param id The identifier to search for
 * \param search_import Whether to search within TagImport tags
 *
 * \return The pointer of the tag with the specified identifier or NULL
 *
 * \sa TagBase::FindLabel(const TagBase *p, const char *label)
 * \sa TagBase::FindLabelledTag(const char *label) const
 * \sa TagBase::FindID(const TagBase *p, sswf_id_t id, bool search_import) const
 */
TagBase *TagBase::FindTagWithID(sswf_id_t id, bool search_import) const
{
	// this search looks in the entire tree available
	const TagBase		*p;

	// start searching from the root tag
	p = this;
	if(p == 0) {
		return 0;		// works when this is still a nul pointer!
	}
	while(p->f_parent != 0) {
		p = p->f_parent;
	}

	return FindID(p, id, search_import);
}


/** \brief Save a tag in the specified Data buffer
 *
 * This function generates a tag header given a tag and
 * a size. It knows how to handle small (63 bytes or less)
 * tags and large (64 or more) tags.
 *
 * \note
 * The main problem is that you need to know the size of
 * the tag at the time you call this function and the
 * data of the tag have come after.
 *
 * In most cases, this is handled by first saving all the
 * data in a separate buffer, get the size of that buffer,
 * create the tag and then copy the separate buffer in this
 * Data buffer.
 *
 * \param data The buffer where the tag is to be saved
 * \param tag The SWF tag to save
 * \param size The size of the tag
 *
 * \bug This function has no concept of the tag being saved
 * and thus it does not check the validity of the tag nor
 * of the size for that tag.
 *
 * \sa TagBase::SaveString(Data& data, const char *string)
 */
int TagBase::SaveTag(Data& data, swf_tag_t tag, size_t size)
{
	// large tag?
	//
	// Note that Macromedia documented the fact that certain
	// tags just cannot be saved with a small tag. These are
	// tested here. This information is quite well hidden!!!
	// If you look at their docs, it says:
	// 
	//		RECORDHEADER (long)
	//
	// Well... until version 1.8.0 I had not noticed and
	// the other day, when I created very small Lossless images
	// it did not want to work!!!
	if(size >= 63
	|| tag == SWF_TAG_DEFINE_BITS_LOSSLESS
	|| tag == SWF_TAG_DEFINE_BITS_LOSSLESS2
	|| tag == SWF_TAG_DEFINE_BITS_JPEG
	|| tag == SWF_TAG_DEFINE_BITS_JPEG2
	|| tag == SWF_TAG_DEFINE_BITS_JPEG3
	|| tag == SWF_TAG_SOUND_STREAM_BLOCK
	) {
		data.PutShort((tag << 6) + 63);
		data.PutLong(size);
	}
	else {
		data.PutShort((tag << 6) + size);
	}

	return 0;
}




/** \brief Number of bits necessary to save the specified signed value
 *
 * This function counts the number of bits necessary to save the
 * specified signed value in a bit field.
 *
 * This is used by many tags to know what size to use to save
 * a set of values such as the coordinates of a rectangle.
 *
 * The input value is expected to be signed and thus a value such
 * as -1 will get a size of 1 and not 32.
 *
 * \param value The signed value of which the number of bits is to be
 * computed
 *
 * \return The number of bits required to save that value
 *
 * \sa TagBase::UIBitSize(unsigned long value)
 */
long TagBase::SIBitSize(long value)
{
	long	cnt;

	// fix by Adam Polkosnik who has a 64 bit processor
	if(value < 0) {
		value = ~value;
	}

	cnt = 1;
	while(value > 0) {
		cnt++;
		value /= 2;
	}

	return cnt;
}


/** \brief Number of bits necessary to save the specified unsigned value
 *
 * This function counts the number of bits necessary to save the
 * specified unsigned value in a bit field.
 *
 * This is used by many tags to know what size to use to save
 * a set of values such as the coordinates of a rectangle.
 *
 * The input value is expected to not be signed and thus a value such
 * as -1 will get a size of 32.
 *
 * \param value The unsigned value of which the number of bits is to be
 * computed
 *
 * \return The number of bits required to save that value
 *
 * \sa TagBase::SIBitSize(long value)
 */
long TagBase::UIBitSize(unsigned long value)
{
	long	cnt;

	// fix by Adam Polkosnik who has a 64 bit processor
	cnt = 0;
	do {
		cnt++;
		value /= 2;
	} while(value > 0);

	return cnt;
}


/** \brief Converts a double to a 16 bits fixed number
 *
 * This function converts a double to a fixed number defined on 16
 * bits (i.e. 8 bits before and 8 bits after the decimal point.)
 *
 * This function clamps the value between -32768 and +32767.
 *
 * \param value The double to convert to a fixed number of 16 bits
 *
 * \return A signed fixed number of 16 bits (8.8 fixed point)
 *
 * \sa TagBase::Double2Signed(double value)
 * \sa TagBase::Signed2Double(long value)
 */
long TagBase::Double2Signed16(double value)
{
	long		r;

	r = (long) rint(value * 256.0);

	/* clamp the result */
	if(r < (short) 0x8000) {
		return (short) 0x8000;
	}
	if(r > (short) 0x7FFF) {
		return (short) 0x7FFF;
	}
	return r;
}


/** \brief Converts a double to a 32 bits fixed number
 *
 * This function converts a double to a fixed number defined on 32
 * bits.
 *
 * Note that at this time the function does not test for overflow
 * or underflow errors.
 *
 * \param value The double to convert to a fixed number of 32 bits
 *
 * \return Fixed number of 32 bits (16.16 fixed point)
 *
 * \sa TagBase::Double2Signed16(double value)
 * \sa TagBase::Signed2Double(long value)
 */
long TagBase::Double2Signed(double value)
{
	// assert(?, "overflow"); -- should we otherwise have a bound checking mechanism
	return (long) rint(value * 65536.0);
}


/** \brief Converts a 32 bits fixed number to a double
 *
 * This function converts a fixed number defined on 32 bits to
 * a double.
 *
 * \param value The fixed 32 bits fixed number to convert to a double
 *
 * \return The double representation
 *
 * \sa TagBase::Double2Signed(long value)
 */
double TagBase::Signed2Double(long value)
{
	return (double) value / 65536.0;
}


/** \brief Called automatically each time a TagShowFrame is saved
 *
 * This function is automatically called each time a TagShowFrame
 * is saved in the output movie. This is used to know the total
 * number of frames saved in a movie and add that information to
 * the TagHeader.
 *
 * \sa TagShowFrame::Save(Data& data)
 * \sa TagBase::ResetFrames(void)
 * \sa TagBase::FrameCount(void) const
 */
void TagBase::ShowFrame(void)
{
	f_frames++;
}


/** \brief Reset the frames counter
 *
 * This function is called once when the Save() starts to
 * reset the frame counter to zero.
 *
 * \sa TagShowFrame::Save(Data& data)
 * \sa TagBase::ShowFrame(void)
 * \sa TagBase::FrameCount(void) const
 */
void TagBase::ResetFrames(void)
{
	f_frames = 0;
}


/** \brief Returns the current number of frames counted so far
 *
 * This function is called to know how many TagShowFrame have been
 * saved so far (at the end, to know how many frames were saved
 * total.)
 *
 * \sa TagShowFrame::Save(Data& data)
 * \sa TagBase::ShowFrame(void)
 * \sa TagBase::ResetFrames(void)
 */
sswf_frame_t TagBase::FrameCount(void) const
{
	return f_frames;
}




/** \brief Request for a minimum version for this movie
 *
 * This function is to be used within the PreSave() functions.
 *
 * Using this function outside that realm results in an error.
 *
 * Whenever the movie is to be saved, a call to all the tags
 * PreSave() functions is made. If any tag requires a minimum
 * version to be saved (i.e. TagMetadata requires at least version
 * 8 to be legally saved in an SWF movie,) this function is
 * called with that minimum requirement.
 *
 * Note that this function calls the function of the same name
 * in the Header(). Trying to call this function before a save
 * will have no effect. Instead, use the
 * TagHeader::SetMinimumVersion(unsigned char version).
 *
 * \sa TagHeader::MinimumVersion(unsigned char version)
 */
void TagBase::MinimumVersion(unsigned char version)
{
	TagHeader *header = Header();
	if(header != 0) {
		header->MinimumVersion(version);
	}
}



/** \brief Return the current movie version
 *
 * Whenever the movie is being saved, some tag need to know the
 * exact version of the entire movie. This is checked using
 * this function.
 *
 * For instance, the TagImport needs to know whether you are saving
 * a version 7 or earlier or a version 8 or newer to know whether to
 * save the import information in an SWF_TAG_IMPORT or SWF_TAG_IMPORT2
 * respectively.
 *
 * This function returns zero when the specified tag was not correctly
 * initialized. Otherwise it queries the header for a version which
 * should always be at least 1.
 *
 * \return The current movie version or zero if the header is not accessible
 */
unsigned char TagBase::Version(void) const
{
	TagHeader *header = Header();
	if(header != 0) {
		return Header()->Version();
	}
	// a version of 0 represent an error
	return 0;
}


/** \fn TagBase::TypeFlags(void) const
 *
 * \brief Retrieve a set of flags desribing the type of the tag
 *
 * This function returns some flags that can be used to know where
 * to place a tag in a movie, whether a tag is unique, etc.
 *
 * If a tag has specifics which are not described here, it often
 * can be checked using its name and special handling.
 *
 * The existing flags are:
 *
 *	\ref SWF_TYPE_DEFINE	This is a definition tag (Sprite, Shape...)
 *
 *	\ref SWF_TYPE_CONTROL	This is a control tag (ShowFrame,
 *				PlaceObject...)
 *
 *	\ref SWF_TYPE_UNIQUE	This can be used once throughout the
 *				whole movie
 *
 *	\ref SWF_TYPE_START	This tag should be at the start of the movie
 *
 *	\ref SWF_TYPE_ONE	At most one per frame
 *
 *	\ref SWF_TYPE_REFERENCE	This tag references another
 *
 *	\ref SWF_TYPE_HAS_ID	This tag has an identifier
 *
 *	\ref SWF_TYPE_SCRIPT	This object can accept action scripts
 *
 *	\ref SWF_TYPE_SPRITE	This is a sprite (can include other tags)
 *
 *	\ref SWF_TYPE_HEADER	The header object
 *
 * \note	These flags are constant (actually hard coded!) and will not
 *		change between calls. They even rarely change between versions.
 *
 * \return	The set of flags for the given tag
 *
 * \sa sswf::TagBase::Name(void) const
 */


/** \brief Search the TagHeader and return its pointer
 *
 * This function searches for the Header of a movie.
 *
 * It does so by testing 'this' tag name to "header". If
 * it is equal return 'this' tag. Otherwise try again
 * with the parent tag.
 *
 * If the Header is not found, then NULL is returned.
 *
 * \return The Header or NULL
 *
 * \sa TagBase::Parent(void) const
 */
TagHeader *TagBase::Header(void) const
{
	const TagBase		*p;

	// when in the header, we return the header!
	p = this;
	while(p != 0) {
		if(strcmp(p->Name(), "header") == 0) {
			return const_cast<TagHeader *>(dynamic_cast<const TagHeader *>(p));
		}
		p = p->f_parent;
	}

	return 0;
}

/** \brief Call the error manager OnError() function
 *
 * This function calls the
 * sswf::ErrorManager::OnError(error_code_t errcode, const char *message, va_list ap) const
 * whenever possible.
 *
 * The function fails whenever the tag was not correctly initialized with a
 * valid sswf::TagHeader as the root tag.
 *
 * \param errcode	The code of this error
 * \param message	The message for this error
 * \param ap		Arguments for the message
 *
 * \return Usually the input error code; the user may change it
 */
ErrorManager::error_code_t TagBase::OnError(ErrorManager::error_code_t errcode, const char *message, va_list ap) const
{
	TagHeader *header = Header();
	if(header == 0) {
		return errcode;
	}

	return header->OnError(errcode, message, ap);
}


/** \brief Call the error manager OnError() function
 *
 * This function calls the
 * sswf::ErrorManager::OnError(error_code_t errcode, const char *message, va_list ap) const
 * whenever possible.
 *
 * The function fails whenever the tag was not correctly initialized with a
 * valid sswf::TagHeader as the root tag.
 *
 * \param errcode	The code of this error
 * \param message	The message for this error
 * \param ...		Arguments for the message
 *
 * \return Usually the input error code; the user may change it
 */
ErrorManager::error_code_t TagBase::OnError(ErrorManager::error_code_t errcode, const char *message, ...) const
{
	TagHeader *header = Header();
	if(header == 0) {
		return errcode;
	}

	va_list ap;
	va_start(ap, message);
	ErrorManager::error_code_t ec = header->OnError(errcode, message, ap);
	va_end(ap);
	return ec;
}


/** \brief Return the name (i.e. the type) of a tag
 *
 * This function returns the name of this tag.
 *
 * The name of a tag is actually a hard coded type name.
 * For instance, the TagHeader's name is "header".
 *
 * \return The name of this tag
 *
 * \bug The name is not copied. DO NOT MODIFY IT!
 */
const char *TagBase::Name(void) const
{
	return f_name;
}


/** \brief Retrieve the first child
 *
 * The SWF movies are organized as a tree of tags. The top most is the
 * Header. The Header includes many definition and control tags. It
 * can include Sprites. Sprites can themselves include control tags.
 *
 * The pointer returned by this function represents the first
 * child.
 *
 * \return A pointer to a tag or NULL
 *
 * \sa TagBase::Header(void) const
 * \sa TagBase::Parent(void)
 * \sa TagBase::Next(void)
 * \sa TagBase::Previous(void)
 */
TagBase *TagBase::Children(void)
{
	return f_children;
}


/** \brief Retrieve the following tag
 *
 * Tags are defined in a list which includes many siblings. It is
 * possible to walk the list using the Next() and Previous() functions.
 *
 * The last tag of a list has a NULL Next() pointer.
 *
 * \return A pointer to a tag or NULL
 *
 * \sa TagBase::Parent(void)
 * \sa TagBase::Header(void) const
 * \sa TagBase::Previous(void)
 * \sa TagBase::Children(void)
 */
TagBase *TagBase::Next(void)
{
	return f_next;
}


/** \brief Retrieve the preceeding tag
 *
 * Tags are defined in a list which includes many siblings. It is
 * possible to walk the list using the Next() and Previous() functions.
 *
 * The first tag of a list has a NULL Previous() pointer.
 *
 * \return A pointer to a tag or NULL
 *
 * \sa TagBase::Next(void)
 * \sa TagBase::Header(void) const
 * \sa TagBase::Parent(void)
 * \sa TagBase::Children(void)
 */
TagBase *TagBase::Previous(void)
{
	return f_previous;
}


/** \brief Retrieve the parent tag
 *
 * This function returns the parent of a tag. All tags except the
 * Header() will have a parent.
 *
 * At this time, only the Header and a Sprite can be parents.
 *
 * This function is used to find the Header().
 *
 * \sa TagBase::Children(void)
 * \sa TagBase::Next(void)
 * \sa TagBase::Previous(void)
 * \sa TagBase::Header(void) const
 */
TagBase *TagBase::Parent(void)
{
	return f_parent;
}



/////////////////////////////////////////// TagBaseID

/** \class sswf::TagBaseID
 *
 * \brief The base of all the tags with an ID
 *
 * A set of tags have an identifier. They all derive from the TagBaseID
 * class.
 *
 * The TagBaseID class is used to manage the identifiers.
 *
 * It knows how to allocate a new identifier, how to forfeit an identifier,
 * how to save an identifier.
 * 
 * For instance, a TagSprite derives from the TagBaseID()
 *
 * \sa <a href="../SWFalexref.html#swf_tag">SWF Alexis' Reference&mdash;swf_tag</a>
 */



/** \brief Initialize the base information of a tag with an identifier
 *
 * Tag which include an identifier will be derived from this
 * TagBaseID class.
 *
 * Whenever created, they are automatically assigned a unique identifier
 * (see the sswf::TagHeader::NextID(void) function).
 *
 * The TagBaseID is itself derived from the TagBase object. The name and
 * parent parameters are directly passed down to the TagBase constructor.
 *
 * \warning
 * If the tag is created without a parent, or an invalid parent pointer,
 * then the sswf::TagHeader::NextID(void) function cannot be found. The
 * result is that no identifier is assigned this the tag.
 *
 * \param name The type of the tag in the form of a string
 * \param parent The parent tag (a header or a sprite)
 */
TagBaseID::TagBaseID(const char *name, TagBase *parent)
	: TagBase(name, parent)
{
	assert(parent != 0, "a tag with an identification must have a header as its parent");

	TagHeader *header = Header();
	if(header != 0) {
		f_id = header->NextID();
		f_identified = true;
	}
	else {
		f_id = SSWF_ID_NONE;
	}
}


/** \brief Destroys the base information of a tag with an identifier
 *
 * The destructor releases the identification of the object and returns.
 *
 * \note
 * In general, the release of the identification is not required.
 *
 * \warning
 * I added the destructor because it is needed under MinGW when compiling
 * with .dll libraries. Otherwise it does not know what function to call.
 * (an auto-destructor cannot be auto-imported) Otherwise, the functionality
 * of the destructor will usually not be of much necessity.
 */
TagBaseID::~TagBaseID()
{
	// we don't need this object identification anymore
	NoIdentification();
}


/** \brief Return this tag identifier
 *
 * This function returns the identifier which was given to this tag
 * or SSWF_ID_NONE when it was cancelled by a call to
 * TagBaseID::NoIdentification().
 *
 * \return the tag identifier or SSWF_ID_NONE
 */
sswf_id_t TagBaseID::Identification(void) const
{
	return f_id;
}


/** \brief Release the identification for this tag
 *
 * It is possible that a tag which usually has an identifier does not
 * actually need it (at this time this is the case only for Glyphs
 * which are shapes without identification.)
 *
 * This function will release the identification which can then not
 * be used.
 *
 * Whenever possible, the identifier of this object will be returned
 * to the pool of available identifiers.
 */
void TagBaseID::NoIdentification(void)
{
	if(f_identified) {
		TagHeader *header = Header();
		if(header != 0) {
			header->RemoveID(f_id);
		}
		f_id = SSWF_ID_NONE;
		f_identified = false;
	}
}


/** \brief Test whether a tag which should have an ID really has one
 *
 * This function checks whether a tag supposed to have an identifier
 * really has one.
 *
 * \return true when the object is still identified, and false otherwise
 */
bool TagBaseID::HasIdentification(void) const
{
	return f_identified;
}


/** \brief Save the object identifier in a Data buffer
 *
 * This function will save the identifier of 'this' tag in the
 * specified Data buffer.
 *
 * \param data The data buffer used to save the tag
 *
 * \return The function returns 0 when it succeeds and non-zero when it fails
 */
int TagBaseID::SaveID(Data& data) const
{
	assert(f_identified, "the identification of this object was removed or never assigned");

	if(!f_identified) {
		return 1;
	}

	data.PutShort(f_id);

	return 0;
}



/* The following options fold the documentation; use 'zi' to turn on and off
 *
 * vim: foldexpr=getline(v\:lnum)!~'^/\\*\\*'&&getline(v\:lnum)!~'^\ \\*'?0\:1 foldcolumn=2 foldmethod=expr
 */
