RagTime5ClusterManager.hxx
Go to the documentation of this file.
00001 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
00002 
00003 /* libmwaw
00004 * Version: MPL 2.0 / LGPLv2+
00005 *
00006 * The contents of this file are subject to the Mozilla Public License Version
00007 * 2.0 (the "License"); you may not use this file except in compliance with
00008 * the License or as specified alternatively below. You may obtain a copy of
00009 * the License at http://www.mozilla.org/MPL/
00010 *
00011 * Software distributed under the License is distributed on an "AS IS" basis,
00012 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013 * for the specific language governing rights and limitations under the
00014 * License.
00015 *
00016 * Major Contributor(s):
00017 * Copyright (C) 2002 William Lachance (wrlach@gmail.com)
00018 * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
00019 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
00020 * Copyright (C) 2006, 2007 Andrew Ziem
00021 * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
00022 *
00023 *
00024 * All Rights Reserved.
00025 *
00026 * For minor contributions see the git repository.
00027 *
00028 * Alternatively, the contents of this file may be used under the terms of
00029 * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
00030 * in which case the provisions of the LGPLv2+ are applicable
00031 * instead of those above.
00032 */
00033 
00034 #ifndef RAG_TIME_5_ZONE_MANAGER
00035 #  define RAG_TIME_5_ZONE_MANAGER
00036 
00037 #include <map>
00038 #include <ostream>
00039 #include <sstream>
00040 #include <string>
00041 #include <vector>
00042 
00043 #include "libmwaw_internal.hxx"
00044 #include "MWAWDebug.hxx"
00045 #include "MWAWEntry.hxx"
00046 
00047 #include "RagTime5StructManager.hxx"
00048 
00049 class RagTime5Parser;
00050 class RagTime5StructManager;
00051 
00052 namespace RagTime5ClusterManagerInternal
00053 {
00054 struct State;
00055 }
00056 
00058 class RagTime5ClusterManager
00059 {
00060 public:
00061   struct Link;
00062 
00063   struct Cluster;
00064   struct ClusterRoot;
00065   struct ClusterParser;
00066 
00067   friend struct ClusterParser;
00068 
00070   RagTime5ClusterManager(RagTime5Parser &parser);
00072   ~RagTime5ClusterManager();
00073 
00075   bool readCluster(RagTime5Zone &zone, ClusterParser &parser, bool warnForUnparsed=true);
00077   bool readCluster(RagTime5Zone &zone, shared_ptr<Cluster> &cluster, int type=-1);
00079   bool readClusterMainList(ClusterRoot &root, std::vector<int> &list, std::vector<int> const &clusterIdList);
00080 
00082   bool readFieldClusters(Link const &link);
00084   bool readUnknownClusterC(Link const &link);
00086   int getClusterFileType(RagTime5Zone &zone);
00088   int getClusterType(RagTime5Zone &zone, int fileType);
00090   bool getClusterBasicHeaderInfo(RagTime5Zone &zone, long &N, long &fSz, long &debHeaderPos);
00091 
00092   // low level
00093 
00095   bool readFieldHeader(RagTime5Zone &zone, long endPos, std::string const &headerName, long &endDataPos, long expectedLVal=-99999);
00097   std::string getClusterName(int id);
00098 
00100   struct Link {
00102     enum Type { L_ClusterLink,
00103                 L_LinkDef,
00104                 L_LongList, L_UnicodeList,
00105                 L_FieldsList, L_List,
00106                 L_UnknownClusterC,
00107                 L_Unknown
00108               };
00110     Link(Type type=L_Unknown) : m_type(type), m_name(""), m_ids(), m_N(0), m_fieldSize(0), m_longList()
00111     {
00112       for (int i=0; i<2; ++i)
00113         m_fileType[i]=0;
00114     }
00116     bool empty() const
00117     {
00118       if (m_type==L_LongList && !m_longList.empty())
00119         return false;
00120       for (size_t i=0; i<m_ids.size(); ++i)
00121         if (m_ids[i]>0) return false;
00122       return true;
00123     }
00125     std::string getZoneName() const
00126     {
00127       switch (m_type) {
00128       case L_ClusterLink:
00129         return "clustLink";
00130       case L_LinkDef:
00131         return "linkDef";
00132       case L_LongList:
00133         if (!m_name.empty())
00134           return m_name;
00135         else {
00136           std::stringstream s;
00137           s << "longList" << m_fieldSize;
00138           return s.str();
00139         }
00140       case L_UnicodeList:
00141         return "unicodeListLink";
00142       case L_UnknownClusterC:
00143         return "unknownClusterC";
00144       case L_FieldsList:
00145         if (!m_name.empty())
00146           return m_name;
00147         return "fieldsList[unkn]";
00148       case L_List:
00149         if (!m_name.empty())
00150           return m_name;
00151         break;
00152       case L_Unknown:
00153       default:
00154         break;
00155       }
00156       std::stringstream s;
00157       if (m_type==L_List)
00158         s << "ListZone";
00159       else
00160         s << "FixZone";
00161       s << std::hex << m_fileType[0] << "_" << m_fileType[1] << std::dec;
00162       if (m_fieldSize)
00163         s << "_" << m_fieldSize;
00164       s << "A";
00165       return s.str();
00166     }
00168     friend std::ostream &operator<<(std::ostream &o, Link const &z)
00169     {
00170       if (z.empty()) return o;
00171       o << z.getZoneName() << ":";
00172       size_t numLinks=z.m_ids.size();
00173       if (numLinks>1) o << "[";
00174       for (size_t i=0; i<numLinks; ++i) {
00175         if (z.m_ids[i]<=0)
00176           o << "_";
00177         else
00178           o << "data" << z.m_ids[i] << "A";
00179         if (i+1!=numLinks) o << ",";
00180       }
00181       if (numLinks>1) o << "]";
00182       if (z.m_fieldSize&0x8000)
00183         o << "[" << std::hex << z.m_fieldSize << std::dec << ":" << z.m_N << "]";
00184       else
00185         o << "[" << z.m_fieldSize << ":" << z.m_N << "]";
00186       return o;
00187     }
00189     Type m_type;
00191     std::string m_name;
00193     std::vector<int> m_ids;
00195     int m_N;
00197     int m_fieldSize;
00199     long m_fileType[2];
00201     std::vector<long> m_longList;
00202   };
00203 
00205   // cluster classes
00207 
00209   struct Cluster {
00211     Cluster() : m_type(C_Unknown), m_zoneId(0), m_hiLoEndian(true), m_dataLink(), m_nameLink(), m_fieldClusterLink(),
00212       m_conditionFormulaLinks(), m_settingLinks(), m_linksList(), m_clusterIdsList()
00213     {
00214     }
00216     virtual ~Cluster() {}
00218     enum Type {
00219       C_ColorPattern, C_Fields, C_Layout, C_Pipeline,
00220       C_Root, C_Script,
00221 
00222       // the styles
00223       C_ColorStyles, C_FormatStyles, C_GraphicStyles, C_TextStyles, C_UnitStyles,
00224       // unknown clusters
00225       C_ClusterB, C_ClusterC,
00226 
00227       C_Unknown
00228     };
00230     Type m_type;
00232     int m_zoneId;
00234     bool m_hiLoEndian;
00236     Link m_dataLink;
00238     Link m_nameLink;
00240     Link m_fieldClusterLink;
00242     std::vector<Link> m_conditionFormulaLinks;
00244     std::vector<Link> m_settingLinks;
00246     std::vector<Link> m_linksList;
00248     std::vector<int> m_clusterIdsList;
00249   };
00250 
00252   struct ClusterLayout : public Cluster {
00254     ClusterLayout() : Cluster(), m_zoneDimensions(), m_pipelineLink(), m_listItemLink()
00255     {
00256     }
00258     virtual ~ClusterLayout() {}
00260     std::vector<MWAWVec2f> m_zoneDimensions;
00262     Link m_pipelineLink;
00264     Link m_listItemLink;
00265   };
00266 
00268   struct ClusterRoot : public Cluster {
00270     ClusterRoot() : Cluster(), m_graphicTypeLink(), m_docInfoLink(),
00271       m_listClusterId(0), m_listClusterName(), m_linkUnknown(), m_fileName("")
00272     {
00273       for (int i=0; i<8; ++i) m_styleClusterIds[i]=0;
00274       for (int i=0; i<1; ++i) m_clusterIds[i]=0;
00275     }
00277     virtual ~ClusterRoot() {}
00279     int m_styleClusterIds[8];
00280 
00282     int m_clusterIds[1];
00283 
00285     Link m_graphicTypeLink;
00286 
00288     Link m_docInfoLink;
00289 
00291     int m_listClusterId;
00293     Link m_listClusterName;
00295     Link m_listClusterLink[2];
00296 
00298     Link m_linkUnknown;
00299 
00301     librevenge::RVNGString m_fileName;
00302   };
00303 
00305   struct ClusterScript : public Cluster {
00307     ClusterScript() : Cluster(), m_scriptComment(), m_scriptName("")
00308     {
00309     }
00311     virtual ~ClusterScript() {}
00313     Link m_scriptComment;
00315     librevenge::RVNGString m_scriptName;
00316   };
00317 
00319   // parser class
00321 
00323   struct ClusterParser {
00325     ClusterParser(RagTime5ClusterManager &parser, int type, std::string const &zoneName) :
00326       m_parser(parser), m_type(type), m_hiLoEndian(true), m_name(zoneName), m_dataId(0), m_link()
00327     {
00328     }
00330     virtual ~ClusterParser() {}
00332     virtual shared_ptr<Cluster> getCluster()=0;
00334     virtual std::string getZoneName() const
00335     {
00336       return m_name;
00337     }
00339     virtual std::string getZoneName(int n, int m=-1) const
00340     {
00341       std::stringstream s;
00342       s << m_name << "-" << n;
00343       if (m>=0)
00344         s << "-B" << m;
00345       return s.str();
00346     }
00348     virtual void startZone()
00349     {
00350     }
00352     virtual bool parseZone(MWAWInputStreamPtr &/*input*/, long /*fSz*/, int /*N*/, int /*flag*/, libmwaw::DebugStream &/*f*/)
00353     {
00354       return false;
00355     }
00357     virtual void endZone()
00358     {
00359     }
00361     virtual bool parseField(RagTime5StructManager::Field const &/*field*/, int /*m*/, libmwaw::DebugStream &/*f*/)
00362     {
00363       return false;
00364     }
00365 
00366     //
00367     // some tools
00368     //
00369 
00371     bool isANameHeader(long N) const
00372     {
00373       return (m_hiLoEndian && N==int(0x80000000)) || (!m_hiLoEndian && N==0x8000);
00374     }
00375 
00377     bool readLinkHeader(MWAWInputStreamPtr &input, long fSz, Link &link, long(&values)[4], std::string &message);
00379     std::string getClusterName(int id);
00381     RagTime5ClusterManager &m_parser;
00383     int m_type;
00385     bool m_hiLoEndian;
00387     std::string m_name;
00389     int m_dataId;
00391     Link m_link;
00392   private:
00393     ClusterParser(ClusterParser const &orig);
00394     ClusterParser &operator=(ClusterParser const &orig);
00395   };
00396 protected:
00398   shared_ptr<RagTime5ClusterManagerInternal::State> m_state;
00400   RagTime5Parser &m_mainParser;
00402   shared_ptr<RagTime5StructManager> m_structManager;
00403 private:
00404   RagTime5ClusterManager(RagTime5ClusterManager const &orig);
00405   RagTime5ClusterManager operator=(RagTime5ClusterManager const &orig);
00406 };
00407 
00408 #endif
00409 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: