(root)/
libredwg-0.13/
src/
print.c
       1  /*****************************************************************************/
       2  /*  LibreDWG - free implementation of the DWG file format                    */
       3  /*                                                                           */
       4  /*  Copyright (C) 2010-2019 Free Software Foundation, Inc.                   */
       5  /*                                                                           */
       6  /*  This library is free software, licensed under the terms of the GNU       */
       7  /*  General Public License as published by the Free Software Foundation,     */
       8  /*  either version 3 of the License, or (at your option) any later version.  */
       9  /*  You should have received a copy of the GNU General Public License        */
      10  /*  along with this program.  If not, see <http://www.gnu.org/licenses/>.    */
      11  /*****************************************************************************/
      12  
      13  /*
      14   * print.c: print helper functions
      15   * written by Rodrigo Rodrigues da Silva
      16   * modified by Reini Urban
      17   */
      18  
      19  #include "config.h"
      20  #include <stdio.h>
      21  #include <stdlib.h>
      22  #include <string.h>
      23  #include <assert.h>
      24  
      25  #include "common.h"
      26  #include "bits.h"
      27  #include "dwg.h"
      28  #include "decode.h"
      29  #include "print.h"
      30  
      31  #define DWG_LOGLEVEL DWG_LOGLEVEL_TRACE
      32  #include "logging.h"
      33  
      34  /* the current version per spec block */
      35  static unsigned int cur_ver = 0;
      36  static BITCODE_BL rcount1, rcount2;
      37  
      38  /*--------------------------------------------------------------------------------
      39   * MACROS
      40   */
      41  
      42  #define ACTION print
      43  #define IS_PRINT
      44  #undef USE_WRITE
      45  
      46  #define FIELD(nam, type) FIELD_TRACE (nam, type)
      47  #define FIELDG(nam, type, dxf) FIELD_G_TRACE (nam, type, dxf)
      48  #define FIELD_TRACE(nam, type)                                                \
      49    LOG_TRACE (#nam ": " FORMAT_##type " [" #type "]\n", _obj->nam)
      50  #define FIELD_G_TRACE(nam, type, dxf)                                         \
      51    LOG_TRACE (#nam ": " FORMAT_##type " [" #type " " #dxf "]\n", _obj->nam)
      52  #define FIELD_CAST(nam, type, cast, dxf)                                      \
      53    LOG_TRACE (#nam ": " FORMAT_##type " [" #type " " #dxf "]\n",               \
      54               (BITCODE_##type)_obj->nam)
      55  #define SUB_FIELD(o, nam, type, dxf) FIELDG (o.nam, type, dxf)
      56  #define SUB_FIELD_CAST(o, nam, type, cast, dxf)                               \
      57    FIELD_G_TRACE (o.nam, cast, dxf)
      58  
      59  #define LOG_INSANE_TF(var, len)
      60  #define FIELD_VALUE(name) _obj->name
      61  #define FIELD_2PT_TRACE(name, type, dxf)                                      \
      62    {                                                                           \
      63      LOG_TRACE (#name ": (" FORMAT_BD ", " FORMAT_BD ") [" #type " %d]\n",     \
      64                 _obj->name.x, _obj->name.y, dxf);                              \
      65    }
      66  #define FIELD_3PT_TRACE(name, type, dxf)                                      \
      67    {                                                                           \
      68      LOG_TRACE (#name ": (" FORMAT_BD ", " FORMAT_BD ", " FORMAT_BD            \
      69                       ") [" #type " %d]\n",                                    \
      70                 _obj->name.x, _obj->name.y, _obj->name.z, dxf);                \
      71    }
      72  
      73  #define ANYCODE -1
      74  #define VALUE_HANDLE(handleptr, name, handle_code, dxf)                       \
      75    if (handleptr)                                                              \
      76      {                                                                         \
      77        LOG_TRACE (#name ": HANDLE" FORMAT_REF " [%d]\n", ARGS_REF (handleptr), \
      78                   dxf);                                                        \
      79      }
      80  #define FIELD_HANDLE(nam, handle_code, dxf)                                   \
      81    VALUE_HANDLE (_obj->nam, nam, handle_code, dxf)
      82  #define SUB_FIELD_HANDLE(o, nam, handle_code, dxf)                            \
      83    VALUE_HANDLE (_obj->o.nam, nam, handle_code, dxf)
      84  #define FIELD_DATAHANDLE(nam, code, dxf) FIELD_HANDLE (nam, code, dxf)
      85  #define VALUE_HANDLE_N(handleptr, name, vcount, handle_code, dxf)             \
      86    if (handleptr)                                                              \
      87      {                                                                         \
      88        LOG_TRACE (#name "[%d]: HANDLE" FORMAT_REF " [%d]\n", (int)vcount,      \
      89                   ARGS_REF (handleptr), dxf);                                  \
      90      }
      91  #define FIELD_HANDLE_N(name, vcount, handle_code, dxf)                        \
      92    VALUE_HANDLE_N (_obj->name, name, vcount, handle_code, dxf)
      93  
      94  #define FIELD_B(name, dxf) FIELDG (name, B, dxf);
      95  #define FIELD_BB(name, dxf) FIELDG (name, BB, dxf);
      96  #define FIELD_3B(name, dxf) FIELDG (name, 3B, dxf);
      97  #define FIELD_BS(name, dxf) FIELDG (name, BS, dxf);
      98  #define FIELD_BL(name, dxf) FIELDG (name, BL, dxf);
      99  #define FIELD_BLL(name, dxf) FIELDG (name, BLL, dxf);
     100  #define FIELD_BD(name, dxf)                                                   \
     101    {                                                                           \
     102      if (bit_isnan (_obj->name))                                               \
     103        {                                                                       \
     104          LOG_ERROR ("Invalid BD " #name);                                      \
     105          return DWG_ERR_VALUEOUTOFBOUNDS;                                      \
     106        }                                                                       \
     107      FIELDG (name, BD, dxf);                                                   \
     108    }
     109  #define FIELD_RC(name, dxf) FIELDG (name, RC, dxf);
     110  #define FIELD_RS(name, dxf) FIELDG (name, RS, dxf);
     111  #define FIELD_RD(name, dxf)                                                   \
     112    {                                                                           \
     113      if (bit_isnan (_obj->name))                                               \
     114        {                                                                       \
     115          LOG_ERROR ("Invalid BD " #name);                                      \
     116          return DWG_ERR_VALUEOUTOFBOUNDS;                                      \
     117        }                                                                       \
     118      FIELDG (name, RD, dxf);                                                   \
     119    }
     120  #define FIELD_RL(name, dxf) FIELDG (name, RL, dxf);
     121  #define FIELD_RLL(name, dxf) FIELDG (name, RLL, dxf);
     122  #define FIELD_RLx(name, dxf)                                                  \
     123    LOG_TRACE (#name ": %x [RL " #dxf "]\n", _obj->name)
     124  #define FIELD_MC(name, dxf) FIELDG (name, MC, dxf);
     125  #define FIELD_MS(name, dxf) FIELDG (name, MS, dxf);
     126  #define FIELD_TF(name, len, dxf)                                              \
     127    {                                                                           \
     128      LOG_TRACE (#name ": [%d TF " #dxf "]\n", len);                            \
     129      LOG_INSANE_TF (FIELD_VALUE (name), (int)len);                             \
     130    }
     131  #define FIELD_TFF(name, len, dxf)                                             \
     132    {                                                                           \
     133      LOG_TRACE (#name ": [%d TFF " #dxf "]\n", len);                           \
     134      LOG_INSANE_TF (FIELD_VALUE (name), (int)len);                             \
     135    }
     136  
     137  #define FIELD_TV(name, dxf) FIELDG (name, TV, dxf);
     138  #define FIELD_TU(name, dxf) LOG_TRACE_TU (#name, (BITCODE_TU)_obj->name, dxf)
     139  #define FIELD_T FIELD_TV /*TODO: implement version dependent string fields */
     140  #define FIELD_BT(name, dxf) FIELDG (name, BT, dxf);
     141  #define FIELD_4BITS(nam, dxf)                                                 \
     142    {                                                                           \
     143      int _b = _obj->nam;                                                       \
     144      LOG_TRACE (#nam ": b%d%d%d%d [4BITS %d]\n", _b & 8, _b & 4, _b & 2,       \
     145                 _b & 1, dxf);                                                  \
     146    }
     147  #define FIELD_BE(name, dxf) FIELD_3RD (name, dxf)
     148  #define FIELD_DD(name, _default, dxf)
     149  #define FIELD_2DD(name, def, dxf) FIELD_2PT_TRACE (name, DD, dxf)
     150  #define FIELD_3DD(name, def, dxf) FIELD_3PT_TRACE (name, DD, dxf)
     151  #define FIELD_2RD(name, dxf) FIELD_2PT_TRACE (name, RD, dxf)
     152  #define FIELD_2BD(name, dxf) FIELD_2PT_TRACE (name, BD, dxf)
     153  #define FIELD_2BD_1(name, dxf) FIELD_2PT_TRACE (name, BD, dxf)
     154  #define FIELD_3RD(name, dxf) FIELD_3PT_TRACE (name, RD, dxf)
     155  #define FIELD_3BD(name, dxf) FIELD_3PT_TRACE (name, BD, dxf)
     156  #define FIELD_3BD_1(name, dxf) FIELD_3PT_TRACE (name, BD, dxf)
     157  #define FIELD_3DPOINT(name, dxf) FIELD_3BD (name, dxf)
     158  #define FIELD_CMC(color, dxf)                                                 \
     159    {                                                                           \
     160      LOG_TRACE (#color ".index: %d [CMC.BS %d]\n", _obj->color.index, dxf)     \
     161      if (dat->version >= R_2004)                                               \
     162        {                                                                       \
     163          LOG_TRACE (#color ".rgb: 0x%06x [CMC.BL %d]\n",                       \
     164                     (unsigned)_obj->color.rgb, dxf + 420 - 62);                \
     165          LOG_TRACE (#color ".flag: 0x%x [CMC.RC]\n",                           \
     166                     (unsigned)_obj->color.flag);                               \
     167          if (_obj->color.flag & 1)                                             \
     168            LOG_TRACE (#color ".name: %s [CMC.TV]\n", _obj->color.name);        \
     169          if (_obj->color.flag & 2)                                             \
     170            LOG_TRACE (#color ".bookname: %s [CMC.TV]\n",                       \
     171                       _obj->color.book_name);                                  \
     172        }                                                                       \
     173    }
     174  #define SUB_FIELD_CMC(o, color, dxf)                                          \
     175    {                                                                           \
     176      LOG_TRACE (#color ".index: %d [CMC.BS %d]\n", _obj->o.color.index, dxf)   \
     177      if (dat->version >= R_2004)                                               \
     178        {                                                                       \
     179          LOG_TRACE (#color ".rgb: 0x%06x [CMC.BL %d]\n",                       \
     180                     (unsigned)_obj->o.color.rgb, dxf + 420 - 62);              \
     181          LOG_TRACE (#color ".flag: 0x%x [CMC.RC]\n",                           \
     182                     (unsigned)_obj->o.color.flag);                             \
     183          if (_obj->o.color.flag & 1)                                           \
     184            LOG_TRACE (#color ".name: %s [CMC.TV]\n", _obj->o.color.name);      \
     185          if (_obj->o.color.flag & 2)                                           \
     186            LOG_TRACE (#color ".bookname: %s [CMC.TV]\n",                       \
     187                       _obj->o.color.book_name);                                \
     188        }                                                                       \
     189    }
     190  #define FIELD_ENC(color, dxf1, dxf2)                                          \
     191    {                                                                           \
     192      LOG_TRACE (#color ".index: %d [ENC.BS %d]\n", _obj->color.index, dxf1);   \
     193      if (dat->version >= R_2004)                                               \
     194        {                                                                       \
     195          if (_obj->color.flag)                                                 \
     196            LOG_TRACE (#color ".flag: 0x%x\n", (unsigned)_obj->color.flag);     \
     197          if (_obj->color.flag & 0x20)                                          \
     198            LOG_TRACE (#color ".alpha: 0%d [ENC.BL %d]\n",                      \
     199                       (int)_obj->color.alpha, dxf + 440 - 62);                 \
     200          if (_obj->color.flag & 0x40)                                          \
     201            LOG_TRACE (#color ".handle: " FORMAT_REF " [ENC.H %d]\n",           \
     202                       ARGS_REF (_obj->color.handle), dxf + 430 - 62);          \
     203          if (_obj->color.flag & 0x80)                                          \
     204            LOG_TRACE (#color ".rgb: 0x%06x [ENC.BL %d]\n",                     \
     205                       (unsigned)_obj->color.rgb, dxf + 420 - 62);              \
     206        }                                                                       \
     207    }
     208  
     209  #define FIELD_TIMEBLL(name, dxf)                                              \
     210    LOG_TRACE (#name " " #dxf ": " FORMAT_BL "." FORMAT_BL "\n",                \
     211               _obj->name.days, _obj->name.ms)
     212  
     213  #define VALUE(value, type, dxf)                                               \
     214    LOG_TRACE (FORMAT_##type " [" #type " " #dxf "]\n", value)
     215  #define VALUE_RC(value, dxf) VALUE (value, RC, dxf)
     216  #define VALUE_RS(value, dxf) VALUE (value, RS, dxf)
     217  #define VALUE_RL(value, dxf) VALUE (value, RL, dxf)
     218  #define VALUE_RLx(value, dxf)                                                 \
     219    LOG_TRACE (FORMAT_RLx " [RL " #dxf "]\n", (BITCODE_RL)value)
     220  #define VALUE_RD(value, dxf) VALUE (value, RD, dxf)
     221  #define VALUE_BD(value, dxf) VALUE (value, BD, dxf)
     222  
     223  // FIELD_VECTOR_N(name, type, size):
     224  // reads data of the type indicated by 'type' 'size' times and stores
     225  // it all in the vector called 'name'.
     226  #define FIELD_VECTOR_N(name, type, size, dxf)                                 \
     227    if (size > 0 && _obj->name != NULL)                                         \
     228      {                                                                         \
     229        for (vcount = 0; vcount < (BITCODE_BL)size; vcount++)                   \
     230          {                                                                     \
     231            LOG_TRACE (#name "[%ld]: " FORMAT_##type "\n", (long)vcount,        \
     232                       _obj->name[vcount])                                      \
     233          }                                                                     \
     234      }
     235  #define FIELD_VECTOR_T(name, type, size, dxf)                                 \
     236    if (_obj->size > 0 && _obj->name != NULL)                                   \
     237      {                                                                         \
     238        for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++)             \
     239          {                                                                     \
     240            PRE (R_2007)                                                        \
     241            {                                                                   \
     242              LOG_TRACE (#name "[%ld]: %s\n", (long)vcount, _obj->name[vcount]) \
     243            }                                                                   \
     244            else                                                                \
     245            {                                                                   \
     246              LOG_TRACE_TU (#name, _obj->name[vcount], dxf)                     \
     247            }                                                                   \
     248          }                                                                     \
     249      }
     250  
     251  #define FIELD_VECTOR(name, type, size, dxf)                                   \
     252    FIELD_VECTOR_N (name, type, _obj->size, dxf)
     253  
     254  #define FIELD_2RD_VECTOR(name, size, dxf)                                     \
     255    if (_obj->name)                                                             \
     256      {                                                                         \
     257        for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++)             \
     258          {                                                                     \
     259            FIELD_2RD (name[vcount], dxf);                                      \
     260          }                                                                     \
     261      }
     262  
     263  #define FIELD_2DD_VECTOR(name, size, dxf)                                     \
     264    if (_obj->name)                                                             \
     265      {                                                                         \
     266        FIELD_2RD (name[0], 0);                                                 \
     267        for (vcount = 1; vcount < (BITCODE_BL)_obj->size; vcount++)             \
     268          {                                                                     \
     269            FIELD_2DD (name[vcount], name[vcount - 1], dxf);                    \
     270          }                                                                     \
     271      }
     272  
     273  #define FIELD_3DPOINT_VECTOR(name, size, dxf)                                 \
     274    if (_obj->name)                                                             \
     275      {                                                                         \
     276        for (vcount = 0; vcount < (BITCODE_BL)_obj->size; vcount++)             \
     277          {                                                                     \
     278            FIELD_3DPOINT (name[vcount], dxf);                                  \
     279          }                                                                     \
     280      }
     281  
     282  #define HANDLE_VECTOR_N(name, size, code, dxf)                                \
     283    if (_obj->name)                                                             \
     284      {                                                                         \
     285        for (vcount = 0; vcount < (BITCODE_BL)size; vcount++)                   \
     286          {                                                                     \
     287            FIELD_HANDLE_N (name[vcount], vcount, code, dxf);                   \
     288          }                                                                     \
     289      }
     290  
     291  #define HANDLE_VECTOR(name, sizefield, code, dxf)                             \
     292    HANDLE_VECTOR_N (name, FIELD_VALUE (sizefield), code, dxf)
     293  
     294  #define FIELD_NUM_INSERTS(num_inserts, type, dxf)                             \
     295    FIELD_G_TRACE (num_inserts, type, dxf)
     296  
     297  #define FIELD_XDATA(name, size)
     298  
     299  #define REACTORS(code)                                                        \
     300    if (dat->version >= R_2000 && obj->tio.object->num_reactors > 0x1000)       \
     301      {                                                                         \
     302        LOG_ERROR ("Invalid num_reactors: %ld\n",                               \
     303                   (long)obj->tio.object->num_reactors);                        \
     304        return DWG_ERR_VALUEOUTOFBOUNDS;                                        \
     305      }                                                                         \
     306    if (obj->tio.object->reactors)                                              \
     307      {                                                                         \
     308        for (vcount = 0; vcount < obj->tio.object->num_reactors; vcount++)      \
     309          {                                                                     \
     310            VALUE_HANDLE_N (obj->tio.object->reactors[vcount], reactors,        \
     311                            vcount, code, -5);                                  \
     312          }                                                                     \
     313      }
     314  
     315  #define XDICOBJHANDLE(code)                                                   \
     316    SINCE (R_2004)                                                              \
     317    {                                                                           \
     318      if (!obj->tio.object->is_xdic_missing)                                    \
     319        VALUE_HANDLE (obj->tio.object->xdicobjhandle, xdicobjhandle, code, 0);  \
     320    }                                                                           \
     321    PRIOR_VERSIONS                                                              \
     322    {                                                                           \
     323      VALUE_HANDLE (obj->tio.object->xdicobjhandle, xdicobjhandle, code, 0);    \
     324    }
     325  
     326  #define COMMON_ENTITY_HANDLE_DATA /*  Empty */
     327  #define SECTION_STRING_STREAM                                                 \
     328    {                                                                           \
     329      Bit_Chain sav_dat = *dat;                                                 \
     330      dat = str_dat;
     331  #define START_STRING_STREAM                                                   \
     332    obj->has_strings = bit_read_B (dat);                                        \
     333    if (obj->has_strings)                                                       \
     334      {                                                                         \
     335        Bit_Chain sav_dat = *dat;                                               \
     336        obj_string_stream (dat, obj, dat);
     337  #define END_STRING_STREAM                                                     \
     338    *dat = sav_dat;                                                             \
     339    }
     340  #define START_HANDLE_STREAM                                                   \
     341    *hdl_dat = *dat;                                                            \
     342    if (dat->version >= R_2007)                                                 \
     343    bit_set_position (hdl_dat, obj->hdlpos)
     344  
     345  #define DWG_ENTITY(token)                                                     \
     346    static int dwg_print_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat, \
     347                                            Bit_Chain *str_dat,                 \
     348                                            const Dwg_Object *restrict obj)     \
     349    {                                                                           \
     350      return 0;                                                                 \
     351    }                                                                           \
     352    static int dwg_print_##token (Bit_Chain *restrict dat,                      \
     353                                  const Dwg_Object *restrict obj)               \
     354    {                                                                           \
     355      BITCODE_BL vcount, rcount3, rcount4;                                      \
     356      Dwg_Entity_##token *ent, *_obj;                                           \
     357      Dwg_Object_Entity *_ent;                                                  \
     358      Bit_Chain *hdl_dat = dat;                                                 \
     359      Bit_Chain *str_dat = dat;                                                 \
     360      Dwg_Data *dwg = obj->parent;                                              \
     361      int error = 0;                                                            \
     362      LOG_INFO ("Entity " #token ":\n")                                         \
     363      _ent = obj->tio.entity;                                                   \
     364      _obj = ent = _ent->tio.token;                                             \
     365      dwg_print_##token##_private (dat, hdl_dat, str_dat, obj);                 \
     366      LOG_TRACE ("Entity handle: " FORMAT_H "\n", ARGS_H (obj->handle))
     367  
     368  #define DWG_ENTITY_END                                                        \
     369    return 0;                                                                   \
     370    }
     371  
     372  #define DWG_OBJECT(token)                                                     \
     373    static int dwg_print_##token##_private (Bit_Chain *dat, Bit_Chain *hdl_dat, \
     374                                            Bit_Chain *str_dat,                 \
     375                                            const Dwg_Object *restrict obj)     \
     376    {                                                                           \
     377      return 0;                                                                 \
     378    }                                                                           \
     379    static int dwg_print_##token (Bit_Chain *restrict dat,                      \
     380                                  const Dwg_Object *restrict obj)               \
     381    {                                                                           \
     382      BITCODE_BL vcount, rcount3, rcount4;                                      \
     383      Dwg_Object_##token *_obj;                                                 \
     384      Bit_Chain *hdl_dat = dat;                                                 \
     385      Bit_Chain *str_dat = dat;                                                 \
     386      Dwg_Data *dwg = obj->parent;                                              \
     387      int error = 0;                                                            \
     388      LOG_INFO ("Object " #token ":\n")                                         \
     389      dwg_print_##token##_private (dat, hdl_dat, str_dat, obj);                 \
     390      _obj = obj->tio.object->tio.token;                                        \
     391      LOG_TRACE ("Object handle: " FORMAT_H "\n", ARGS_H (obj->handle))
     392  
     393  #define DWG_OBJECT_END                                                        \
     394    return 0;                                                                   \
     395    }
     396  
     397  #include "dwg.spec"
     398  
     399  /* Returns 0 on success
     400     Dispatches on the variable types.
     401   */
     402  static int
     403  dwg_print_variable_type (Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
     404                           Dwg_Object *restrict obj)
     405  {
     406    int i;
     407    int is_entity;
     408    Dwg_Class *klass;
     409  
     410    i = obj->type - 500;
     411    if (i < 0 || i > (int)dwg->num_classes)
     412      return DWG_ERR_INVALIDTYPE;
     413  
     414    klass = &dwg->dwg_class[i];
     415    if (!klass || !klass->dxfname)
     416      return DWG_ERR_INTERNALERROR;
     417    // almost always false
     418    is_entity = dwg_class_is_entity (klass);
     419  
     420  // clang-format off
     421    #include "classes.inc"
     422    // clang-format on
     423  
     424    return DWG_ERR_UNHANDLEDCLASS;
     425  }
     426  
     427  /* prints to logging.h OUTPUT (ie stderr). Returns 0 on success
     428     Dispatches on the fixed types.
     429  */
     430  int
     431  dwg_print_object (Bit_Chain *restrict dat, Dwg_Object *restrict obj)
     432  {
     433    int error = 0;
     434    unsigned int type;
     435  
     436    if (!obj || !obj->parent)
     437      return DWG_ERR_INTERNALERROR;
     438    type = dat->version < R_13b1 ? (unsigned int)obj->fixedtype : obj->type;
     439    // Bit_Chain * dat = (Bit_Chain *)obj->parent->bit_chain;
     440    // Bit_Chain *hdl_dat = dat;
     441    switch (obj->type)
     442      {
     443      case DWG_TYPE_TEXT:
     444        return dwg_print_TEXT (dat, obj);
     445      case DWG_TYPE_ATTRIB:
     446        return dwg_print_ATTRIB (dat, obj);
     447      case DWG_TYPE_ATTDEF:
     448        return dwg_print_ATTDEF (dat, obj);
     449      case DWG_TYPE_BLOCK:
     450        return dwg_print_BLOCK (dat, obj);
     451      case DWG_TYPE_ENDBLK:
     452        return dwg_print_ENDBLK (dat, obj);
     453      case DWG_TYPE_SEQEND:
     454        return dwg_print_SEQEND (dat, obj);
     455      case DWG_TYPE_INSERT:
     456        return dwg_print_INSERT (dat, obj);
     457      case DWG_TYPE_MINSERT:
     458        return dwg_print_MINSERT (dat, obj);
     459      case DWG_TYPE_VERTEX_2D:
     460        return dwg_print_VERTEX_2D (dat, obj);
     461      case DWG_TYPE_VERTEX_3D:
     462        return dwg_print_VERTEX_3D (dat, obj);
     463      case DWG_TYPE_VERTEX_MESH:
     464        return dwg_print_VERTEX_MESH (dat, obj);
     465      case DWG_TYPE_VERTEX_PFACE:
     466        return dwg_print_VERTEX_PFACE (dat, obj);
     467      case DWG_TYPE_VERTEX_PFACE_FACE:
     468        return dwg_print_VERTEX_PFACE_FACE (dat, obj);
     469      case DWG_TYPE_POLYLINE_2D:
     470        return dwg_print_POLYLINE_2D (dat, obj);
     471      case DWG_TYPE_POLYLINE_3D:
     472        return dwg_print_POLYLINE_3D (dat, obj);
     473      case DWG_TYPE_ARC:
     474        return dwg_print_ARC (dat, obj);
     475      case DWG_TYPE_CIRCLE:
     476        return dwg_print_CIRCLE (dat, obj);
     477      case DWG_TYPE_LINE:
     478        return dwg_print_LINE (dat, obj);
     479      case DWG_TYPE_DIMENSION_ORDINATE:
     480        return dwg_print_DIMENSION_ORDINATE (dat, obj);
     481      case DWG_TYPE_DIMENSION_LINEAR:
     482        return dwg_print_DIMENSION_LINEAR (dat, obj);
     483      case DWG_TYPE_DIMENSION_ALIGNED:
     484        return dwg_print_DIMENSION_ALIGNED (dat, obj);
     485      case DWG_TYPE_DIMENSION_ANG3PT:
     486        return dwg_print_DIMENSION_ANG3PT (dat, obj);
     487      case DWG_TYPE_DIMENSION_ANG2LN:
     488        return dwg_print_DIMENSION_ANG2LN (dat, obj);
     489      case DWG_TYPE_DIMENSION_RADIUS:
     490        return dwg_print_DIMENSION_RADIUS (dat, obj);
     491      case DWG_TYPE_DIMENSION_DIAMETER:
     492        return dwg_print_DIMENSION_DIAMETER (dat, obj);
     493      case DWG_TYPE_POINT:
     494        return dwg_print_POINT (dat, obj);
     495      case DWG_TYPE__3DFACE:
     496        return dwg_print__3DFACE (dat, obj);
     497      case DWG_TYPE_POLYLINE_PFACE:
     498        return dwg_print_POLYLINE_PFACE (dat, obj);
     499      case DWG_TYPE_POLYLINE_MESH:
     500        return dwg_print_POLYLINE_MESH (dat, obj);
     501      case DWG_TYPE_SOLID:
     502        return dwg_print_SOLID (dat, obj);
     503      case DWG_TYPE_TRACE:
     504        return dwg_print_TRACE (dat, obj);
     505      case DWG_TYPE_SHAPE:
     506        return dwg_print_SHAPE (dat, obj);
     507      case DWG_TYPE_VIEWPORT:
     508        return dwg_print_VIEWPORT (dat, obj);
     509      case DWG_TYPE_ELLIPSE:
     510        return dwg_print_ELLIPSE (dat, obj);
     511      case DWG_TYPE_SPLINE:
     512        return dwg_print_SPLINE (dat, obj);
     513      case DWG_TYPE_REGION:
     514        return dwg_print_REGION (dat, obj);
     515      case DWG_TYPE__3DSOLID:
     516        return dwg_print__3DSOLID (dat, obj);
     517        /* Check the type of the object? */
     518      case DWG_TYPE_BODY:
     519        return dwg_print_BODY (dat, obj);
     520      case DWG_TYPE_RAY:
     521        return dwg_print_RAY (dat, obj);
     522      case DWG_TYPE_XLINE:
     523        return dwg_print_XLINE (dat, obj);
     524      case DWG_TYPE_DICTIONARY:
     525        return dwg_print_DICTIONARY (dat, obj);
     526      case DWG_TYPE_MTEXT:
     527        return dwg_print_MTEXT (dat, obj);
     528      case DWG_TYPE_LEADER:
     529        return dwg_print_LEADER (dat, obj);
     530      case DWG_TYPE_TOLERANCE:
     531        return dwg_print_TOLERANCE (dat, obj);
     532      case DWG_TYPE_MLINE:
     533        return dwg_print_MLINE (dat, obj);
     534      case DWG_TYPE_BLOCK_CONTROL:
     535        return dwg_print_BLOCK_CONTROL (dat, obj);
     536      case DWG_TYPE_BLOCK_HEADER:
     537        return dwg_print_BLOCK_HEADER (dat, obj);
     538      case DWG_TYPE_LAYER_CONTROL:
     539        return dwg_print_LAYER_CONTROL (dat, obj);
     540      case DWG_TYPE_LAYER:
     541        return dwg_print_LAYER (dat, obj);
     542      case DWG_TYPE_STYLE_CONTROL:
     543        return dwg_print_STYLE_CONTROL (dat, obj);
     544      case DWG_TYPE_STYLE:
     545        return dwg_print_STYLE (dat, obj);
     546      case DWG_TYPE_LTYPE_CONTROL:
     547        return dwg_print_LTYPE_CONTROL (dat, obj);
     548      case DWG_TYPE_LTYPE:
     549        return dwg_print_LTYPE (dat, obj);
     550      case DWG_TYPE_VIEW_CONTROL:
     551        return dwg_print_VIEW_CONTROL (dat, obj);
     552      case DWG_TYPE_VIEW:
     553        return dwg_print_VIEW (dat, obj);
     554      case DWG_TYPE_UCS_CONTROL:
     555        return dwg_print_UCS_CONTROL (dat, obj);
     556      case DWG_TYPE_UCS:
     557        return dwg_print_UCS (dat, obj);
     558      case DWG_TYPE_VPORT_CONTROL:
     559        return dwg_print_VPORT_CONTROL (dat, obj);
     560      case DWG_TYPE_VPORT:
     561        return dwg_print_VPORT (dat, obj);
     562      case DWG_TYPE_APPID_CONTROL:
     563        return dwg_print_APPID_CONTROL (dat, obj);
     564      case DWG_TYPE_APPID:
     565        return dwg_print_APPID (dat, obj);
     566      case DWG_TYPE_DIMSTYLE_CONTROL:
     567        return dwg_print_DIMSTYLE_CONTROL (dat, obj);
     568      case DWG_TYPE_DIMSTYLE:
     569        return dwg_print_DIMSTYLE (dat, obj);
     570      case DWG_TYPE_VX_CONTROL:
     571        return dwg_print_VX_CONTROL (dat, obj);
     572      case DWG_TYPE_VX_TABLE_RECORD:
     573        return dwg_print_VX_TABLE_RECORD (dat, obj);
     574      case DWG_TYPE_GROUP:
     575        return dwg_print_GROUP (dat, obj);
     576      case DWG_TYPE_MLINESTYLE:
     577        return dwg_print_MLINESTYLE (dat, obj);
     578      case DWG_TYPE_OLE2FRAME:
     579        return dwg_print_OLE2FRAME (dat, obj);
     580      case DWG_TYPE_DUMMY:
     581        return dwg_print_DUMMY (dat, obj);
     582      case DWG_TYPE_LONG_TRANSACTION:
     583        return dwg_print_LONG_TRANSACTION (dat, obj);
     584      case DWG_TYPE_LWPOLYLINE:
     585        return dwg_print_LWPOLYLINE (dat, obj);
     586      case DWG_TYPE_HATCH:
     587        return dwg_print_HATCH (dat, obj);
     588      case DWG_TYPE_XRECORD:
     589        return dwg_print_XRECORD (dat, obj);
     590      case DWG_TYPE_PLACEHOLDER:
     591        return dwg_print_PLACEHOLDER (dat, obj);
     592      case DWG_TYPE_OLEFRAME:
     593        return dwg_print_OLEFRAME (dat, obj);
     594      case DWG_TYPE_VBA_PROJECT:
     595        LOG_ERROR ("Unhandled Object VBA_PROJECT. Has its own section\n");
     596        // dwg_print_VBA_PROJECT(dat, obj);
     597        break;
     598      case DWG_TYPE_LAYOUT:
     599        return dwg_print_LAYOUT (dat, obj);
     600      case DWG_TYPE_PROXY_ENTITY:
     601        return dwg_print_PROXY_ENTITY (dat, obj);
     602      case DWG_TYPE_PROXY_OBJECT: // DXF name: PROXY
     603        return dwg_print_PROXY_OBJECT (dat, obj);
     604      case DWG_TYPE_REPEAT:
     605        return dwg_print_REPEAT (dat, obj);
     606      case DWG_TYPE_ENDREP:
     607        return dwg_print_ENDREP (dat, obj);
     608      case DWG_TYPE__3DLINE:
     609        return dwg_print__3DLINE (dat, obj);
     610      case DWG_TYPE_LOAD:
     611        return dwg_print_LOAD (dat, obj);
     612      case DWG_TYPE_JUMP:
     613        return dwg_print_JUMP (dat, obj);
     614      default:
     615        if (obj->type == obj->parent->layout_type)
     616          {
     617            return dwg_print_LAYOUT (dat, obj);
     618          }
     619        /* > 500 */
     620        else if ((error = dwg_print_variable_type (obj->parent, dat, obj))
     621                 & DWG_ERR_UNHANDLEDCLASS)
     622          {
     623            Dwg_Data *dwg = obj->parent;
     624            int is_entity = 0;
     625            int i = obj->type - 500;
     626            Dwg_Class *klass = NULL;
     627  
     628            if (i > 0 && i < (int)dwg->num_classes)
     629              {
     630                klass = &dwg->dwg_class[i];
     631                is_entity = klass ? dwg_class_is_entity (klass) : 0;
     632              }
     633            // properly dwg_decode_object/_entity for eed, reactors, xdic
     634            if (klass && !is_entity)
     635              {
     636                return dwg_print_UNKNOWN_OBJ (dat, obj);
     637              }
     638            else if (klass)
     639              {
     640                return dwg_print_UNKNOWN_ENT (dat, obj);
     641              }
     642            else // not a class
     643              {
     644                LOG_WARN ("Unknown object, skipping eed/reactors/xdic");
     645                SINCE (R_2000)
     646                {
     647                  LOG_INFO ("Object bitsize: %u\n", obj->bitsize);
     648                }
     649                LOG_INFO ("Object handle: " FORMAT_H "\n", ARGS_H (obj->handle));
     650                return error | DWG_ERR_INVALIDTYPE;
     651              }
     652          }
     653      }
     654    return DWG_ERR_UNHANDLEDCLASS;
     655  }
     656  
     657  #undef IS_PRINT