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