text: //  Copyright 2004 by Autodesk, Inc.
  //
  // Permission to use, copy, modify, and distribute this software in
  // object code form for any purpose and without fee is hereby granted, 
  // provided that the above copyright notice appears in all copies and 
  // that both that copyright notice and the limited warranty and
  // restricted rights notice below appear in all supporting 
  // documentation.
  //
  // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. 
  // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
  // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC. 
  // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
  // UNINTERRUPTED OR ERROR FREE.
  //
  // Use, duplication, or disclosure by the U.S. Government is subject to 
  // restrictions set forth in FAR 52.227-19 (Commercial Computer
  // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
  // (Rights in Technical Data and Computer Software), as applicable.
  //
  // AcDMMUtils.h
  
  /// <summary>
  /// This file describes the following objects
  /// AcDMMWideString - a simple Unicode string class
  /// AcDMMStringVec - a vector of AcDMMWideStrings
  /// AcDMMNode - which encapsulates a w2d Node
  /// AcDMMResourceInfo - which contains the description of one resource
  /// AcDMMResourceVec - a vector of AcDMMResourceInfo objects
  /// (file) to the added to the DWF page or to the ePlot global section
  /// </summary>
  
  
  
  #ifndef AcDMMUtils_h
  #define AcDMMUtils_h
  
  typedef const wchar_t * PCWIDESTR;
  typedef wchar_t * PWIDESTR;
  
  /////////////////////////////////////////////////////////////////////
  // AcDMMWideString
  /////////////////////////////////////////////////////////////////////
  
  /// <summary>
  /// a simple unicode string class
  /// </summary>
  ///
  /// <remarks>
  /// Cheap Unicode string class.  No fancy use-counting.
  /// Just meant to "look" like CString as far as we use it.
  /// </remarks>
  class AcDMMWideString
  {
  public:
      /// <summary>
      /// default constructor
      /// </summary>
      ///
      AcDMMWideString();
  
      /// <summary>
      /// copy constructor
      /// </summary>
      ///
      /// <param name="ws">
      /// the string to be copied into this
      /// </param>
      ///
      AcDMMWideString(const AcDMMWideString& ws);
  
      /// <summary>
      /// Constructs this from a pointer to a Unicode string
      /// </summary>
      ///
      /// <param name="pwsz">
      /// a pointer to the null terminated Unicode string from which this
      /// object shall be constructed.
      /// </param>
      ///
      AcDMMWideString(PCWIDESTR pwsz);
  
      /// <summary>
      /// destructor
      /// </summary>
      ///
      virtual ~AcDMMWideString();
  
      /// <summary>
      /// operator= for copying another AcDMMWideString
      /// </summary>
      ///
      /// <param name="ws">
      /// a const reference to the AcDMMWideString which is to be
      /// copied to this
      /// </param>
      ///
      /// <returns>
      /// a const reference to this
      /// </returns>
      ///
      const AcDMMWideString& operator= (const AcDMMWideString& ws);
  
      /// <summary>
      /// operator= for copying a null terminated Unicode string into this
      /// </summary>
      ///
      /// <param name ="pwsz">
      /// a const pointer to a null terminated Unicode string to be copied
      /// to this
      /// </param>
      ///
      /// <returns>
      /// a const reference to this
      /// </returns>
      ///
      const AcDMMWideString& operator= (PCWIDESTR pwsz);
  
      /// <summary>
      /// returns a const pointer to the Unicode string contained by this
      /// </summary>
      ///
      /// <returns>
      /// returns a const pointer to the Unicode string contained by this
      /// </returns>
      ///
      operator PCWIDESTR() const;
  
      /// <summary>
      /// deletes the contained Unicode string
      /// </summary>
      ///
      void   Empty();
  
      /// <summary>
      /// tells the caller if this contains an empty string
      /// </summary>
      ///
      /// <returns>
      /// returns true if this contains an empty string
      /// </returns>
      bool   IsEmpty() const;
  
      /// <summary>
      /// get the length of the contained string, in Unicode characters
      /// </summary>
      ///
      /// <returns>
      /// the length of the contained string, in Unicode characters
      /// </returns>
      ///
      size_t GetLength() const;
  
      /// <summary>
      /// concatenates a second AcDMMWideString to this one
      /// </summary>
      ///
      /// <param name="ws">
      /// the AcDMMWideString to concatenate with this one
      /// </param>
      ///
      /// <returns>
      /// a const reference to this
      /// </returns>
      const AcDMMWideString& operator+= (AcDMMWideString ws);
  
      friend AcDMMWideString operator+ 
          (const AcDMMWideString& wsLeft, wchar_t wch);
      friend AcDMMWideString operator+ 
          (wchar_t wch, const AcDMMWideString& wsRight);
      friend AcDMMWideString operator+ 
          (const AcDMMWideString& wsLeft, const AcDMMWideString& wsRight);
  
  private:
      void Alloc(size_t iLen);
      void Alloc(PCWIDESTR pwsz,size_t iLen);
      void Alloc(PCWIDESTR pwsz);
      static void Release(PWIDESTR pwsz);
      void Release();
  
      void MoveChars(int iStartOffset,PCWIDESTR pwsz,size_t iChars);
  
      PWIDESTR  m_pData;
      size_t    m_iLength;
  };
  
  
  inline void AcDMMWideString::MoveChars(int iStartOffset, PCWIDESTR pwsz,
      size_t iChars)
  {
      assert(iStartOffset >=0);
      assert(iStartOffset <= static_cast <int> (m_iLength));
      assert(iStartOffset + iChars <= m_iLength+1);
  
      memmove(m_pData+iStartOffset,
              pwsz,
              iChars * sizeof(wchar_t));
  }
  
  
  
  inline AcDMMWideString operator+ (const AcDMMWideString& wsLeft, wchar_t wch)
  {
      AcDMMWideString wsRet;
  
      wsRet.Alloc(wsLeft.m_pData,wsLeft.GetLength()+1);
      wsRet.m_pData[wsLeft.GetLength()] = wch;
      wsRet.m_pData[wsLeft.GetLength()+1] = 0;
  
      return(wsRet);
  }
  
  
  inline AcDMMWideString operator+ (wchar_t wch, const AcDMMWideString& wsRight)
  {
      AcDMMWideString wsRet;
  
      wsRet.Alloc(wsRight.GetLength()+1);
      wsRet.m_pData[0] = wch;
      wsRet.MoveChars(1,wsRight.m_pData,wsRight.GetLength()+1);
  
      return(wsRet);
  }
  
  inline AcDMMWideString operator+ (const AcDMMWideString& wsLeft, 
      const AcDMMWideString& wsRight)
  {
      AcDMMWideString wsRet(wsLeft);
      wsRet += wsRight;
      return(wsRet);
  }
  
  inline const AcDMMWideString& AcDMMWideString::operator += (AcDMMWideString ws)
  {
      if(!ws.IsEmpty()) {
          AcDMMWideString wsOldThis = *this;
          Empty();
          Alloc(wsOldThis.GetLength() + ws.GetLength());
  
          MoveChars(0,wsOldThis.m_pData,wsOldThis.GetLength());
  
          MoveChars(wsOldThis.GetLength(),ws.m_pData,ws.GetLength()+1);
      }
  
      return(*this);
  }
  
  inline AcDMMWideString::AcDMMWideString()
  : m_pData(NULL),
    m_iLength(0)
  {
  }
  
  inline AcDMMWideString::AcDMMWideString(const AcDMMWideString& ws)
  : m_pData(NULL),
    m_iLength(0)
  {
      Alloc(ws.m_pData? ws.m_pData: L"",ws.m_iLength);
  }
  
  inline AcDMMWideString::AcDMMWideString(PCWIDESTR pwsz)
  : m_pData(NULL),
    m_iLength(0)
  {
      Alloc(pwsz);
  }
  
  inline AcDMMWideString::~AcDMMWideString()
  {
      Empty();
  }
  
  inline bool AcDMMWideString::IsEmpty() const
  {
      return(m_iLength == 0);
  }
  
  inline void AcDMMWideString::Empty()
  {
      if(m_pData)
          Release();
  
      m_iLength = 0;
  }
  
  
  inline AcDMMWideString::operator PCWIDESTR() const
  {
      return(m_pData ? m_pData : L"");
  }
  
  
  inline const AcDMMWideString& AcDMMWideString::operator=
      (const AcDMMWideString& ws)
  {
      Empty();
      m_iLength = ws.m_iLength;
      Alloc(ws.m_pData,ws.m_iLength);
  
      return(*this);
  }
  
  inline const AcDMMWideString& AcDMMWideString::operator= (PCWIDESTR pwsz)
  {
      Empty();
      m_iLength = wcslen(pwsz);
      Alloc(pwsz,m_iLength);
  
      return(*this);
  }
  
  inline size_t AcDMMWideString::GetLength() const
  {
      return(m_iLength);
  }
  
  
  inline void AcDMMWideString::Alloc(size_t iLen)
  // Makes an allocation of the size indicated
  {
      assert(m_pData == NULL);
      assert(iLen >= 0);
      m_iLength = iLen;
      m_pData = new wchar_t[m_iLength+1];
  }
  
  inline void AcDMMWideString::Alloc(PCWIDESTR pwsz,size_t iLen)
  // Makes an allocation of the size indicated, copies that amount
  {
      assert(m_pData == NULL);
      assert(pwsz != NULL);
  
      if(iLen > 0) {
          Alloc(iLen);
          MoveChars(0,pwsz,iLen+1);
      }
  }
  
  inline void AcDMMWideString::Alloc(PCWIDESTR pwsz)
  // Makes an allocation, copies entire string
  {
      assert(m_pData == NULL);
      assert(pwsz != NULL);
  
      Alloc(pwsz,wcslen(pwsz));
  }
  
  
  inline void AcDMMWideString::Release(PWIDESTR pwsz)
  // Static function: deallocates the backing store.
  {
      if (pwsz)
          delete[] pwsz;
  }
  
  
  inline void AcDMMWideString::Release()
  {
      Release(m_pData);
      m_pData = NULL;
      m_iLength = 0;
  }
  
  typedef std::vector<AcDMMWideString> AcDMMStringVec;
  
  ///////////////////////////////////////////////////////////////////////
  /// class AcDMMNode
  ///////////////////////////////////////////////////////////////////////
  /// <summary>
  /// a lightweight object to hold the data needed to describe a Node in
  /// a DWF w2d
  /// </summary>
  class AcDMMNode 
  {
  public:
      /// <summary>
      /// default constructor
      /// </summary>
      ///
      /// <remarks>
      /// creates an empty node with number 0
      /// </remarks>
      AcDMMNode()
      : m_nodeNumber(0),
        m_nodeName(NULL)
      {
      }
  
      /// <summary>
      /// constructs a node from a name and number
      /// </summary>
      ///
      /// <param name="number">
      /// The integer Node number.
      /// </param>
      ///
      /// <param name="name">
      /// a Unicode string defining the Node name
      /// </param>
      ///
      AcDMMNode(int number, wchar_t * name)
      {
          m_nodeNumber = number;
          if (NULL != name) {
              m_nodeName = new wchar_t[::wcslen(name) + 1];
              ::wcscpy(m_nodeName, name);
          } else
              m_nodeName = NULL;
      }
  
      /// <summary>
      /// Copy constructor
      /// </summary>
      ///
      /// <param name="src">
      /// the object to be copied
      /// </param>
      ///
      AcDMMNode(const AcDMMNode &src) 
      : m_nodeName(NULL)
      { 
          *this = src;
      }
  
  
      /// <summary>
      /// destructor
      /// </summary>
      ///
      ~AcDMMNode()
      {
          if (NULL != m_nodeName)
              delete m_nodeName;
      }
  
      /// <summary>
      /// accessor for the Node number
      /// </summary>
      ///
      /// <returns>
      /// the integer Node number
      /// </returns>
      int nodeNumber() {return m_nodeNumber;};
  
      /// <summary>
      /// mutator for the Node number
      /// </summary>
      ///
      /// <param name="number">
      /// the integer value to assign as Node number
      /// </param>
      void SetNodeNumber(int number) {m_nodeNumber = number;};
  
  
      /// <summary>
      /// accessor for the Node name
      /// </summary>
      ///
      /// <returns>
      /// a const pointer to the null terminated Unicode Node name string
      /// </returns>
      const wchar_t * nodeName() {return m_nodeName;};
  
      /// <summary>
      /// mutator for the Node name
      /// </summary>
      ///
      /// <param name="name">
      /// a const pointer to a Unicode string to be assigned as Node name
      /// </param>
      void SetNodeName(const wchar_t * name)
      {
          if (NULL != m_nodeName)
              delete m_nodeName;
          if (NULL != name) {
              m_nodeName = new wchar_t[::wcslen(name) + 1];
              ::wcscpy(m_nodeName, name);
          } else
              m_nodeName = NULL;
      }
  
      /// <summary>
      /// operator= also used by copy constructor
      /// </summary>
      ///
      /// <param name="src">
      /// the object whose values will be copied to this object
      /// </param>
      ///
      /// <returns>
      /// returns this object
      /// </returns>
      AcDMMNode & operator= (const AcDMMNode &src)
      {
          if (this == &src)
              return *this;
  
          SetNodeNumber(src.m_nodeNumber);
          SetNodeName(src.m_nodeName);
          return *this;
      }
  
  private:
      int m_nodeNumber;
      wchar_t * m_nodeName;
  };
  
  /////////////////////////////////////////////////////////////////////////
  // class AcDMMResourceInfo
  /////////////////////////////////////////////////////////////////////////
  
  /// <summary>
  /// This class describes a resource to be added to the DWF page or global 
  /// section
  /// The resource is an existing file which will be added to the zip
  /// file and listed in the page descriptor as a page resource or added
  /// to the ePlot global section as a global resource
  /// </summary>
  class AcDMMResourceInfo
  {
  public:
      /// <summary>
      /// the default constructor, creates an empty object
      /// </summary>
      AcDMMResourceInfo()
      : m_mime(NULL),
        m_role(NULL),
        m_path(NULL)
      {
      }
  
      /// <summary>
      /// creates an AcDMMResourceInfo object from 3 Unicode strings
      /// </summary>
      ///
      /// <param name="role">
      /// a null terminated Unicode string to be assigned to the role attribute
      /// This string describes the resource, e.g, "thumbnail", "font", etc.
      /// </param>
      ///
      /// <param name="mime">
      /// this is a null terminated Unicode strings to be assigned to the mime
      /// type attribute. 
      /// </param>
      ///
      /// <param name="path">
      /// This is a Unicode string holding the full path to the resource file
      /// </param>
      AcDMMResourceInfo(const wchar_t *role, const wchar_t *mime, 
          const wchar_t *path)
      {
          if (NULL != role) {
              m_role = new wchar_t[::wcslen(role) + 1];
              ::wcscpy(m_role, role);
          } else
              m_role = NULL;
  
          if (NULL != mime) {
              m_mime = new wchar_t[::wcslen(mime) + 1];
              ::wcscpy(m_mime, mime);
          } else
              m_mime = NULL;
  
          if (NULL != path) {
              m_path = new wchar_t[::wcslen(path) + 1];
              ::wcscpy(m_path, path);
          } else
              m_path = NULL;
      }
  
      /// <summary>
      /// Copy constructor
      /// </summary>
      ///
      /// <param name="src">
      /// the object to be copied
      /// </param>
      ///
      AcDMMResourceInfo(const AcDMMResourceInfo & src) 
      : m_role(NULL),
        m_mime(NULL),
        m_path(NULL)
      {
          *this = src;
      }
  
  
      /// <summary>
      /// destructor
      /// </summary>    
      ~AcDMMResourceInfo()
      {
          if (NULL != m_role)
              delete m_role;
          if (NULL != m_mime)
              delete m_mime;
          if (NULL != m_path)
              delete m_path;
      }
  
      /// <summary>
      /// mutator for the Role attribute
      /// </summary>
      ///
      /// <param name="role">
      /// a const pointer to a Unicode string to be assigned as role
      /// </param>
      void SetRole(wchar_t * role)
      {
          if (NULL != m_role)
              delete m_role;
          if (NULL != role) {
              m_role = new wchar_t[::wcslen(role) + 1];
              ::wcscpy(m_role, role);
          } else
              m_role = NULL;
      }
  
      /// <summary>
      /// accessor for the Role attribute
      /// </summary>
      ///
      /// <returns>
      /// a const pointer to the null terminated Unicode Node role string
      /// </returns>
      const wchar_t * GetRole() {return m_role;};
  
      /// <summary>
      /// mutator for the Mime attribute
      /// </summary>
      ///
      /// <param name="mime">
      /// a const pointer to a Unicode string to be assigned as mime
      /// </param>
      void SetMime(wchar_t * mime)
      {
          if (NULL != m_mime)
              delete m_mime;
          if (NULL != mime) {
              m_mime = new wchar_t[::wcslen(mime) + 1];
              ::wcscpy(m_mime, mime);
          } else
              m_mime = NULL;
      }
  
      /// <summary>
      /// accessor for the Mime type attribute
      /// </summary>
      ///
      /// <returns>
      /// a const pointer to the null terminated Unicode mime type string
      /// </returns>
      const wchar_t * GetMime() {return m_mime;};
  
      /// <summary>
      /// mutator for the Path attribute
      /// </summary>
      ///
      /// <param name="path">
      /// a const pointer to a Unicode string to be assigned as path to the
      /// resource file
      /// </param>
      void SetPath(wchar_t * path)
      {
          if (NULL != m_path)
              delete m_path;
          if (NULL != path) {
              m_path = new wchar_t[::wcslen(path) + 1];
              ::wcscpy(m_path, path);
          } else
              m_path = NULL;
      }
  
      /// <summary>
      /// accessor for the path to the resource file
      /// </summary>
      ///
      /// <returns>
      /// a const pointer to the null terminated Unicode path string
      /// </returns>
      const wchar_t * GetPath() {return m_path;};
  
      /// <summary>
      /// operator= also used by copy constructor
      /// </summary>
      ///
      /// <param name="src">
      /// the object whose values will be copied to this object
      /// </param>
      ///
      /// <returns>
      /// returns this object
      /// </returns>
      AcDMMResourceInfo& operator= (const AcDMMResourceInfo &src)
      {
          if (this == &src)
              return *this;
  
          SetRole(src.m_role);
          SetMime(src.m_mime);
          SetPath(src.m_path);
          return *this;
      }
  
  private:
      wchar_t * m_role;
      wchar_t * m_mime;
      wchar_t * m_path; // full path to resource file   
  };
  
  typedef std::vector<AcDMMResourceInfo> AcDMMResourceVec;
  
  #endif // AcDMMUtils_h
  