1 /*****************************************************************************/
2 /*  LibreDWG - free implementation of the DWG file format                    */
3 /*                                                                           */
4 /*  Copyright (C) 2018-2021 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  * in_dxf.c: read ascii DXF
15  * written by Reini Urban
16  */
17 
18 #include "config.h"
19 #ifdef __STDC_ALLOC_LIB__
20 #  define __STDC_WANT_LIB_EXT2__ 1 /* for strdup */
21 #else
22 #  define _USE_BSD 1
23 #endif
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <limits.h>
29 #include <errno.h>
30 //#include <ctype.h>
31 #include <math.h>
32 // strings.h or string.h
33 #ifdef AX_STRCASECMP_HEADER
34 #  include AX_STRCASECMP_HEADER
35 #endif
36 
37 #define IS_INDXF
38 #include "common.h"
39 #include "importer.h"
40 #include "bits.h"
41 #include "dwg.h"
42 #include "out_dxf.h"
43 #include "decode.h"
44 #include "encode.h"
45 #include "dynapi.h"
46 #include "hash.h"
47 #include "classes.h"
48 #include "free.h"
49 
50 static unsigned int loglevel;
51 #define DWG_LOGLEVEL loglevel
52 #include "logging.h"
53 
54 #include "in_dxf.h"
55 
56 #ifndef _DWG_API_H_
57 Dwg_Object *dwg_obj_generic_to_object (const void *restrict obj,
58                                        int *restrict error);
59 #endif
60 // from dwg.c
61 BITCODE_H
62 dwg_find_tablehandle_silent (Dwg_Data *restrict dwg, const char *restrict name,
63                              const char *restrict table);
64 
65 /* the current version per spec block */
66 static unsigned int cur_ver = 0;
67 static char buf[4096];
68 static long start, end; // stream offsets
69 static array_hdls *header_hdls = NULL;
70 static array_hdls *eed_hdls = NULL;
71 static array_hdls *obj_hdls = NULL;
72 
73 //static long num_dxf_objs;  // how many elements are added
74 //static long size_dxf_objs; // how many elements are allocated
75 //static Dxf_Objs *dxf_objs;
76 
77 #define EXPECT_DXF(nam, field, dxf)                                           \
78   if (pair == NULL || pair->code != dxf)                                      \
79     {                                                                         \
80       LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s", nam,       \
81                  pair ? pair->code : -1, dxf, #field);                        \
82       return pair;                                                            \
83     }
84 #define EXPECT_INT_DXF(field, dxf, type)                                      \
85   EXPECT_DXF (obj->name, #field, dxf);                                        \
86   dwg_dynapi_entity_set_value (o, obj->name, field, &pair->value, 1);         \
87   LOG_TRACE ("%s.%s = %d [" #type " %d]\n", obj->name, field, pair->value.i,  \
88              pair->code);                                                     \
89   dxf_free_pair (pair)
90 #define EXPECT_DBL_DXF(field, dxf, type)                                      \
91   EXPECT_DXF (obj->name, #field, dxf);                                        \
92   dwg_dynapi_entity_set_value (o, obj->name, field, &pair->value, 1);         \
93   LOG_TRACE ("%s.%s = %f [" #type " %d]\n", obj->name, field, pair->value.d,  \
94              pair->code);                                                     \
95   dxf_free_pair (pair)
96 #define EXPECT_H_DXF(field, htype, dxf, type)                                 \
97   EXPECT_DXF (obj->name, #field, dxf);                                        \
98   if (pair->value.u)                                                          \
99     {                                                                         \
100       BITCODE_H hdl = dwg_add_handleref (dwg, htype, pair->value.u, obj);     \
101       dwg_dynapi_entity_set_value (o, obj->name, field, &hdl, 1);             \
102       LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n", obj->name, field,         \
103                  ARGS_REF (hdl), pair->code);                                 \
104     }                                                                         \
105   dxf_free_pair (pair)
106 #define EXPECT_T_DXF(field, dxf)                                              \
107   EXPECT_DXF (obj->name, #field, dxf);                                        \
108   if (pair->value.s)                                                          \
109     {                                                                         \
110       dwg_dynapi_entity_set_value (o, obj->name, field, &pair->value.s, 1);   \
111       LOG_TRACE ("%s.%s = \"%s\" [T %d]\n", obj->name, field, pair->value.s,  \
112                  pair->code);                                                 \
113     }                                                                         \
114   dxf_free_pair (pair)
115 
116 // stricter ordering for special subclasses:
117 #define FIELD_B(field, dxf)                                                   \
118   if (dxf)                                                                    \
119     {                                                                         \
120       pair = dxf_read_pair (dat);                                             \
121       EXPECT_INT_DXF (#field, dxf, B);                                        \
122     }
123 #define FIELD_RC(field, dxf)                                                  \
124   if (dxf)                                                                    \
125     {                                                                         \
126       pair = dxf_read_pair (dat);                                             \
127       EXPECT_INT_DXF (#field, dxf, RC);                                       \
128     }
129 #define FIELD_BS(field, dxf)                                                  \
130   if (dxf)                                                                    \
131     {                                                                         \
132       pair = dxf_read_pair (dat);                                             \
133       EXPECT_INT_DXF (#field, dxf, BS);                                       \
134     }
135 #define FIELD_BLd(field, dxf)                                                 \
136   if (dxf)                                                                    \
137     {                                                                         \
138       pair = dxf_read_pair (dat);                                             \
139       EXPECT_INT_DXF (#field, dxf, BLd);                                      \
140     }
141 #define FIELD_BL(field, dxf)                                                  \
142   if (dxf)                                                                    \
143     {                                                                         \
144       pair = dxf_read_pair (dat);                                             \
145       EXPECT_INT_DXF (#field, dxf, BL);                                       \
146     }
147 #define FIELD_BD(field, dxf)                                                  \
148   if (dxf)                                                                    \
149     {                                                                         \
150       pair = dxf_read_pair (dat);                                             \
151       EXPECT_DBL_DXF (#field, dxf, BD);                                       \
152     }
153 #define FIELD_3BD(field, dxf)                                                 \
154   if (dxf)                                                                    \
155     {                                                                         \
156       BITCODE_3BD pt;                                                         \
157       pair = dxf_read_pair (dat);                                             \
158       EXPECT_DXF (obj->name, #field, dxf);                                    \
159       pt.x = pair->value.d;                                                   \
160       dxf_free_pair (pair);                                                   \
161                                                                               \
162       pair = dxf_read_pair (dat);                                             \
163       EXPECT_DXF (obj->name, #field, dxf + 10);                               \
164       pt.y = pair->value.d;                                                   \
165       dxf_free_pair (pair);                                                   \
166                                                                               \
167       pair = dxf_read_pair (dat);                                             \
168       EXPECT_DXF (obj->name, #field, dxf + 20);                               \
169       pt.z = pair->value.d;                                                   \
170       dwg_dynapi_entity_set_value (o, obj->name, #field, &pt, 1);             \
171       LOG_TRACE ("%s.%s = (%f, %f, %f) [3BD %d]\n", obj->name, #field, pt.x,  \
172                  pt.y, pt.z, pair->code - 20);                                \
173       dxf_free_pair (pair);                                                   \
174     }
175 #define FIELD_3BD_1(field, dxf)                                               \
176   if (dxf)                                                                    \
177     {                                                                         \
178       BITCODE_3BD pt;                                                         \
179       pair = dxf_read_pair (dat);                                             \
180       EXPECT_DXF (obj->name, #field, dxf);                                    \
181       pt.x = pair->value.d;                                                   \
182       dxf_free_pair (pair);                                                   \
183                                                                               \
184       pair = dxf_read_pair (dat);                                             \
185       EXPECT_DXF (obj->name, #field, dxf + 1);                                \
186       pt.y = pair->value.d;                                                   \
187       dxf_free_pair (pair);                                                   \
188                                                                               \
189       pair = dxf_read_pair (dat);                                             \
190       EXPECT_DXF (obj->name, #field, dxf + 2);                                \
191       pt.z = pair->value.d;                                                   \
192       dwg_dynapi_entity_set_value (o, obj->name, #field, &pt, 1);             \
193       LOG_TRACE ("%s.%s = (%f, %f, %f) [3BD_1 %d]\n", obj->name, #field, pt.x,\
194                  pt.y, pt.z, pair->code - 2);                                 \
195       dxf_free_pair (pair);                                                   \
196     }
197 #define FIELD_HANDLE(field, code, dxf)                                        \
198   if (dxf)                                                                    \
199     {                                                                         \
200       pair = dxf_read_pair (dat);                                             \
201       EXPECT_H_DXF (#field, code, dxf, H);                                    \
202     }
203 #define FIELD_T(field, dxf)                                                   \
204   if (dxf)                                                                    \
205     {                                                                         \
206       pair = dxf_read_pair (dat);                                             \
207       EXPECT_T_DXF (#field, dxf);                                             \
208     }
209 
210 static void *
xcalloc(size_t n,size_t s)211 xcalloc (size_t n, size_t s)
212 {
213   void *p;
214   if ((n * s) > INT32_MAX)
215     goto err;
216   p = calloc (n, s);
217   if (!p)
218     {
219     err:
220       LOG_ERROR ("Out of memory with calloc %ld * %ld\n", (long)n, (long)s);
221       return NULL;
222     }
223   return p;
224 }
225 
226 static inline void
dxf_skip_ws(Bit_Chain * dat)227 dxf_skip_ws (Bit_Chain *dat)
228 {
229   const int is_binary = dat->opts & DWG_OPTS_DXFB;
230   if (is_binary)
231     return;
232   if (dat->byte >= dat->size)
233     return;
234   // clang-format off
235   for (; (!dat->chain[dat->byte] ||
236           dat->chain[dat->byte] == ' ' ||
237           dat->chain[dat->byte] == '\t' ||
238           dat->chain[dat->byte] == '\r');
239        )
240     // clang-format on
241     {
242       dat->byte++;
243       if (dat->byte >= dat->size)
244         return;
245     }
246 }
247 
248 #define SAFER_STRTOL(num, rettype, ret)                                       \
249   if (dat->byte + 3 >= dat->size                                              \
250       || !memchr (&dat->chain[dat->byte], '\n', dat->size - dat->byte))       \
251     {                                                                         \
252       LOG_ERROR ("Premature DXF end");                                        \
253       dat->byte = dat->size;                                                  \
254       return (rettype)ret;                                                    \
255     }                                                                         \
256   errno = 0;                                                                  \
257   num = strtol ((char *)&dat->chain[dat->byte], &endptr, 10);                 \
258   if (endptr)                                                                 \
259     {                                                                         \
260       if (endptr == (char *)&dat->chain[dat->byte])                           \
261         {                                                                     \
262           LOG_ERROR ("Expected DXF integer value");                           \
263           dat->byte = dat->size;                                              \
264           return (rettype)ret;                                                \
265         }                                                                     \
266       dat->byte += (unsigned char *)endptr - &dat->chain[dat->byte];          \
267     }                                                                         \
268   if (errno == ERANGE)                                                        \
269     return (rettype)num;                                                      \
270   if (dat->byte + 1 >= dat->size)                                             \
271   return (rettype)num
272 
273 static BITCODE_RC
dxf_read_rc(Bit_Chain * dat)274 dxf_read_rc (Bit_Chain *dat)
275 {
276   const int is_binary = dat->opts & DWG_OPTS_DXFB;
277   if (is_binary)
278     {
279       return bit_read_RC (dat);
280     }
281   else
282     {
283       char *endptr;
284       long num;
285       // avoid overflow over dat->size
286       SAFER_STRTOL (num, BITCODE_RC, 0);
287       if (dat->chain[dat->byte] == '\r')
288         dat->byte++;
289       if (dat->chain[dat->byte] == '\n')
290         dat->byte++;
291       if (num > 65534)
292         LOG_ERROR ("%s: RC overflow %ld (at %lu)", __FUNCTION__, num,
293                    dat->byte);
294       return (BITCODE_RC)num;
295     }
296 }
297 
298 static BITCODE_RS
dxf_read_rs(Bit_Chain * dat)299 dxf_read_rs (Bit_Chain *dat)
300 {
301   const int is_binary = dat->opts & DWG_OPTS_DXFB;
302   if (is_binary)
303     {
304       return bit_read_RS (dat);
305     }
306   else
307     {
308       char *endptr;
309       long num;
310       SAFER_STRTOL (num, BITCODE_RS, 0);
311       if (dat->chain[dat->byte] == '\r')
312         dat->byte++;
313       if (dat->chain[dat->byte] == '\n')
314         dat->byte++;
315       if (num > 65534)
316         LOG_ERROR ("%s: RS overflow %ld (at %lu)", __FUNCTION__, num,
317                    dat->byte);
318       return (BITCODE_RS)num;
319     }
320 }
321 
322 static BITCODE_RL
dxf_read_rl(Bit_Chain * dat)323 dxf_read_rl (Bit_Chain *dat)
324 {
325   const int is_binary = dat->opts & DWG_OPTS_DXFB;
326   if (is_binary)
327     {
328       return bit_read_RL (dat);
329     }
330   else
331     {
332       char *endptr;
333       long num;
334       // avoid overflow over dat->size
335       SAFER_STRTOL (num, BITCODE_RL, 0);
336       if (dat->chain[dat->byte] == '\r')
337         dat->byte++;
338       if (dat->chain[dat->byte] == '\n')
339         dat->byte++;
340       if (num > INT_MAX)
341         LOG_ERROR ("%s: RL overflow %ld (at %lu)", __FUNCTION__, num,
342                    dat->byte);
343       return (BITCODE_RL)num;
344     }
345 }
346 
347 static BITCODE_RLL
dxf_read_rll(Bit_Chain * dat)348 dxf_read_rll (Bit_Chain *dat)
349 {
350   const int is_binary = dat->opts & DWG_OPTS_DXFB;
351   if (is_binary)
352     {
353       return bit_read_RLL (dat);
354     }
355   else
356     {
357       char *endptr;
358       BITCODE_RLL num;
359       // avoid overflow over dat->size (need final "  0\nEOF")
360       SAFER_STRTOL (num, BITCODE_RLL, 0UL);
361       if (dat->chain[dat->byte] == '\r')
362         dat->byte++;
363       if (dat->chain[dat->byte] == '\n')
364         dat->byte++;
365       if ((unsigned long)num > LONG_MAX) // or wrap to negative
366         LOG_ERROR ("%s: long overflow %ld (at %lu)", __FUNCTION__, (long)num,
367                    dat->byte);
368       return num;
369     }
370 }
371 
372 static BITCODE_RD
dxf_read_rd(Bit_Chain * dat)373 dxf_read_rd (Bit_Chain *dat)
374 {
375   const int is_binary = dat->opts & DWG_OPTS_DXFB;
376   if (is_binary)
377     {
378       return bit_read_RD (dat);
379     }
380   else
381     {
382       char *str, *endptr;
383       BITCODE_RD num;
384       dxf_skip_ws (dat);
385       str = (char *)&dat->chain[dat->byte];
386       // avoid overflow over dat->size
387       if (dat->byte + 6 >= dat->size || !memchr (str, '\n', dat->size - dat->byte - 6))
388         {
389           LOG_ERROR ("Premature DXF end");
390           dat->byte = dat->size;
391           return (double)NAN;
392         }
393       else
394         num = strtod (str, &endptr);
395       if (endptr)
396         dat->byte += endptr - str;
397       if (errno == ERANGE)
398         return (double)NAN;
399       return num;
400     }
401 }
402 
403 #if 0
404 // not yet needed. only with write2004
405 // ASCII: series of 310 HEX encoded
406 // BINARY: ??
407 static unsigned char *
408 dxf_read_binary (Bit_Chain *dat, unsigned char **p, int len)
409 {
410   unsigned char *data;
411   const char *pos = (char*)&dat->chain[dat->byte];
412   const int is_binary = dat->opts & DWG_OPTS_DXFB;
413   const unsigned size = len / 2;
414   unsigned read;
415   if (dat->byte + size >= dat->size)
416     return NULL;
417   //if (is_binary)
418   data = p && *p ? (unsigned char *)realloc (*p, size) : (unsigned char *)malloc (size);
419   if (!data)
420     {
421       LOG_ERROR ("Out of memory");
422       return NULL;
423     }
424   LOG_TRACE ("binary[%u]: ", size);
425   if ((read = in_hex2bin (data, pos, size) != size))
426     LOG_ERROR ("in_hex2bin read only %u of %u", read, size);
427   dat->byte += read;
428   if (p)
429     *p = data;
430   return data;
431 }
432 #endif
433 
434 // Unicode strings are UTF-8 with quoted \\U+
435 // BINARY: no length prefixes, just zero-terminated strings
436 static void
dxf_read_string(Bit_Chain * dat,char ** string)437 dxf_read_string (Bit_Chain *dat, char **string)
438 {
439   const int is_binary = dat->opts & DWG_OPTS_DXFB;
440   if (dat->byte >= dat->size)
441     return;
442   if (is_binary)
443     {
444 #if 1
445       int size = strlen ((char*)&dat->chain[dat->byte]) + 1;
446       if (!string)
447         {
448           strncpy (buf, (char*)&dat->chain[dat->byte], 4096);
449           if (size > 4095)
450             buf[4095] = '\0';
451         }
452       else
453         {
454           *string = !*string ? (char *)malloc (size) : (char *)realloc (*string, size);
455           strcpy (*string, (char*)&dat->chain[dat->byte]);
456         }
457       dat->byte += size;
458 #else
459       int size = sscanf ((char*)&dat->chain[dat->byte], "%s", (char*)buf);
460       buf[4095] = '\0';
461       if (size != EOF)
462         size = strlen (buf) + 1;
463       dat->byte += size;
464       if (!string)
465         {
466           if (size > 4096)
467             return;
468           return; // ignore, just advanced dat
469         }
470       *string = !*string ? (char *)malloc (size) : (char *)realloc (*string, size);
471       strcpy (*string, buf);
472 #endif
473     }
474   else
475     {
476       int i;
477       dxf_skip_ws (dat);
478       if (dat->byte >= dat->size || !memchr (&dat->chain[dat->byte], '\n', dat->size - dat->byte))
479         return;
480       for (i = 0;
481            dat->byte < dat->size && dat->chain[dat->byte] != '\n' && i < 4096;
482            dat->byte++)
483         {
484           buf[i++] = dat->chain[dat->byte];
485         }
486       if (dat->byte >= dat->size || i >= 4096)
487         return;
488       if (i && buf[i - 1] == '\r')
489         buf[i - 1] = '\0';
490       else
491         buf[i] = '\0';
492       dat->byte++;
493 
494       // dxf_skip_ws (dat);
495       if (!string)
496         return; // ignore, just advanced dat
497       if (!*string)
498         *string = (char *)malloc (strlen (buf) + 1);
499       else
500         *string = (char *)realloc (*string, strlen (buf) + 1);
501       strcpy (*string, buf);
502     }
503 }
504 
505 static void
dxf_free_pair(Dxf_Pair * pair)506 dxf_free_pair (Dxf_Pair *pair)
507 {
508   if (!pair)
509     return;
510   if (pair->type == DWG_VT_STRING || pair->type == DWG_VT_BINARY)
511     {
512       free (pair->value.s);
513       pair->value.s = NULL;
514     }
515   else if (pair->code == 0 || pair->code == 2)
516     {
517       free (pair->value.s);
518       pair->value.s = NULL;
519     }
520   free (pair);
521   pair = NULL;
522 }
523 
524 static Dxf_Pair *ATTRIBUTE_MALLOC
dxf_read_pair(Bit_Chain * dat)525 dxf_read_pair (Bit_Chain *dat)
526 {
527   Dxf_Pair *pair = (Dxf_Pair *)xcalloc (1, sizeof (Dxf_Pair));
528   const int is_binary = dat->opts & DWG_OPTS_DXFB;
529   if (!pair)
530     return NULL;
531   if (dat->size - dat->byte < 6) // at least 0\nEOF\n
532     {
533     err:
534       LOG_ERROR ("Unexpected DXF end-of-file");
535       free (pair);
536       return NULL;
537     }
538   if (is_binary)
539     LOG_HANDLE ("%4lx: ", dat->byte);
540   pair->code = (short)dxf_read_rs (dat);
541   if (dat->size - dat->byte < 4) // at least EOF\n
542     goto err;
543   pair->type = dwg_resbuf_value_type (pair->code);
544   //if (pair->code == 280) // && strEQc (key, "ENDCAPS")
545   //  pair->type = DWG_VT_INT16; // for HEADER.ENDCAPS - CEPSNTYPE
546   switch (pair->type)
547     {
548     case DWG_VT_STRING:
549       dxf_read_string (dat, &pair->value.s);
550       if (!pair->value.s && pair->code != 0)
551         pair->value.s = calloc(1, 1);
552       LOG_TRACE ("  dxf (%d, \"%s\")\n", (int)pair->code, pair->value.s);
553       // dynapi_set_helper converts from utf-8 to unicode, not here.
554       // we need to know the type of the target field, if TV or T
555       break;
556     case DWG_VT_BOOL:
557     case DWG_VT_INT8:
558       pair->value.i = dxf_read_rc (dat);
559       LOG_TRACE ("  dxf (%d, %d)\n", (int)pair->code, pair->value.i);
560       break;
561     case DWG_VT_INT16:
562       pair->value.i = dxf_read_rs (dat);
563       LOG_TRACE ("  dxf (%d, %d)\n", (int)pair->code, pair->value.i);
564       break;
565     case DWG_VT_INT32:
566       pair->value.l = dxf_read_rl (dat);
567       LOG_TRACE ("  dxf (%d, %ld)\n", (int)pair->code, pair->value.l);
568       break;
569     case DWG_VT_INT64:
570       pair->value.rll = dxf_read_rll (dat);
571       LOG_TRACE ("  dxf (%d, " FORMAT_RLL ")\n", (int)pair->code,
572                  pair->value.rll);
573       break;
574     case DWG_VT_REAL:
575     case DWG_VT_POINT3D:
576       dxf_skip_ws (dat);
577       pair->value.d = dxf_read_rd (dat);
578       LOG_TRACE ("  dxf (%d, %f)\n", pair->code, pair->value.d);
579       break;
580     case DWG_VT_BINARY:
581       // zero-terminated. TODO hex decode here already?
582       dxf_read_string (dat, &pair->value.s);
583       if (!pair->value.s)
584         pair->value.s = calloc(1, 1);
585       LOG_TRACE ("  dxf (%d, %s)\n", (int)pair->code, pair->value.s);
586       break;
587     case DWG_VT_HANDLE:
588     case DWG_VT_OBJECTID:
589       // BINARY: hex string without len
590       dxf_read_string (dat, NULL);
591       sscanf (buf, "%X", &pair->value.u);
592       LOG_TRACE ("  dxf (%d, %X)\n", (int)pair->code, pair->value.u);
593       break;
594     case DWG_VT_INVALID:
595     default:
596       LOG_ERROR ("Invalid DXF group code: %d", pair->code);
597       dxf_free_pair (pair);
598       return NULL;
599     }
600   return pair;
601 }
602 
603 #define DXF_CHECK_EOF                                                         \
604   if (dat->byte >= dat->size || (pair == NULL)                                \
605       || (pair->code == 0 && !pair->value.s)                                  \
606       || (pair->code == 0 && strEQc (pair->value.s, "EOF")))                  \
607     {                                                                         \
608       if (pair)                                                               \
609         dxf_free_pair (pair);                                                 \
610       pair = NULL;                                                            \
611       return 1;                                                               \
612     }
613 #define DXF_RETURN_EOF(what)                                                  \
614   if (dat->byte >= dat->size || (pair == NULL)                                \
615       || (pair->code == 0 && !pair->value.s)                                  \
616       || (pair->code == 0 && strEQc (pair->value.s, "EOF")))                  \
617     {                                                                         \
618       if (pair)                                                               \
619         dxf_free_pair (pair);                                                 \
620       pair = NULL;                                                            \
621       return what;                                                            \
622     }
623 #define DXF_BREAK_EOF                                                         \
624   if (dat->byte >= dat->size || (pair == NULL)                                \
625       || (pair->code == 0 && !pair->value.s)                                  \
626       || (pair->code == 0 && strEQc (pair->value.s, "EOF")))                  \
627   break
628 
629 static Dxf_Pair *
dxf_skip_comment(Bit_Chain * dat,Dxf_Pair * pair)630 dxf_skip_comment (Bit_Chain *dat, Dxf_Pair *pair)
631 {
632   while (pair != NULL && pair->code == 999)
633     {
634       dxf_free_pair (pair);
635       pair = dxf_read_pair (dat);
636       DXF_RETURN_EOF (pair);
637     }
638   return pair;
639 }
640 
641 /*  destlen = strlen(src) / 2;
642     if ((written = in_hex2bin (malloc (destlen), src, destlen)) != destlen)
643       error
644 
645     TODO: optimize for the typical line len 254 (destlen 127)
646 
647     benchmarks:
648       checked hex2bin:   0.624826 sec (if < >)...
649        sscanf hex2bin:	20.150780 sec
650       lookup2 hex2bin:	 0.162167 sec (124x faster)
651  */
in_hex2bin(unsigned char * restrict dest,char * restrict src,unsigned destlen)652 unsigned in_hex2bin (unsigned char *restrict dest, char *restrict src, unsigned destlen)
653 {
654 #if 0
655   char *pos = (char *)src;
656   for (unsigned i = 0; i < destlen; i++)
657     {
658       if (sscanf (pos, SCANF_2X, &dest[i]))
659         pos += 2;
660       else
661         return i;
662     }
663   return destlen;
664 #else
665   char *pos = (char *)src;
666   // 124x faster, but no error checks.
667   // src must consist of valid uppercase hex chars only
668   static const unsigned char h2b_lookup[] = {
669     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567
670     0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?
671     0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG
672     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ...
673   };
674   const char *_end = pos + (destlen << 1);
675   /* slower
676   const char *_end4 = pos + ((destlen << 1) & ~0x3);
677   const int64_t magic = INT64_C(0x1001001000000000);
678   uint32_t *d32 = (uint32_t*)dest;
679   while (pos < _end4) {
680     uint32_t in;
681     uint64_t v, x;
682     memcpy (&in, pos, 4);
683     v = in;
684     x = (((0x00404040 & v) >> 6) * 9) + (v & 0x000F0F0F); // do 3
685     x = (((uint64_t)((int64_t)x * magic)) >> 48) & ~15;   // bswap and pack
686     v = ((v >> 30) * 9) + ((v >> 24) & 0x0F);             // do the 4th
687     *d32++ = (x | v);
688     pos += 4;
689   }*/
690   while (pos < _end) {
691     unsigned char v1 = h2b_lookup[(pos[0] & 0x1F) ^ 0x10];
692     unsigned char v2 = h2b_lookup[(pos[1] & 0x1F) ^ 0x10];
693     *dest++ = (v1 << 4 | v2);
694     pos += 2;
695   }
696   return destlen;
697 #endif
698 }
699 
700 /*--------------------------------------------------------------------------------
701  * MACROS
702  */
703 
704 #define ACTION indxf
705 //#define IS_ENCODER
706 //#define IS_DXF
707 
708 /* Store all handle fieldnames and string values into this flexarray.
709    We need strdup'd copies, the dxf input will be freed.
710  */
711 array_hdls *
array_push(array_hdls * restrict hdls,const char * restrict field,const char * restrict name,const int code)712 array_push (array_hdls *restrict hdls, const char *restrict field,
713             const char *restrict name, const int code)
714 {
715   uint32_t i = hdls->nitems;
716   if (i >= hdls->size)
717     {
718       hdls->size += 16;
719       hdls = (array_hdls *)realloc (
720           hdls, 8 + (hdls->size * sizeof (struct array_hdl)));
721       if (!hdls)
722         {
723           LOG_ERROR ("Out of memory");
724           return NULL;
725         }
726       // memset (hdls, 0, 8 + (hdls->size * sizeof (struct array_hdl));
727     }
728   hdls->nitems = i + 1;
729   hdls->items[i].field = strdup (field);
730   hdls->items[i].name = strdup (name);
731   hdls->items[i].code = code;
732   return hdls;
733 }
734 
735 array_hdls *
new_array_hdls(int size)736 new_array_hdls (int size)
737 {
738   array_hdls *hdls
739       = (array_hdls *)xcalloc (1, 8 + size * sizeof (struct array_hdl));
740   if (!hdls)
741     return NULL;
742   hdls->size = size;
743   return hdls;
744 }
745 
746 void
free_array_hdls(array_hdls * hdls)747 free_array_hdls (array_hdls *hdls)
748 {
749   for (uint32_t i = 0; i < hdls->nitems; i++)
750     {
751       free (hdls->items[i].field);
752       free (hdls->items[i].name);
753     }
754   free (hdls);
755 }
756 
757 #define DXF_CHECK_ENDSEC                                                      \
758   if (pair != NULL                                                            \
759       && (dat->byte >= dat->size || (pair->code == 0 && !pair->value.s)       \
760           || (pair->code == 0 && strEQc (pair->value.s, "ENDSEC"))))          \
761   return 0
762 #define DXF_BREAK_ENDSEC                                                      \
763   if (pair != NULL                                                            \
764       && (dat->byte >= dat->size || (pair->code == 0 && !pair->value.s)       \
765           || (pair->code == 0 && strEQc (pair->value.s, "ENDSEC"))))          \
766   break
767 #define DXF_RETURN_ENDSEC(what)                                               \
768   if (pair != NULL                                                            \
769       && (dat->byte >= dat->size || (pair->code == 0 && !pair->value.s)       \
770           || (pair->code == 0 && strEQc (pair->value.s, "ENDSEC"))))          \
771     {                                                                         \
772       dxf_free_pair (pair);                                                   \
773       return what;                                                            \
774     }
775 
776 static Dxf_Pair *
dxf_expect_code(Bit_Chain * restrict dat,Dxf_Pair * restrict pair,int code)777 dxf_expect_code (Bit_Chain *restrict dat, Dxf_Pair *restrict pair, int code)
778 {
779   while (pair != NULL && pair->code != code)
780     {
781       dxf_free_pair (pair);
782       pair = dxf_read_pair (dat);
783       pair = dxf_skip_comment (dat, pair);
784       DXF_RETURN_EOF (pair);
785       if (pair && pair->code != code)
786         {
787           LOG_ERROR ("Expecting DXF code %d, got %d (at %lu)", code,
788                      pair->code, dat->byte);
789         }
790     }
791   return pair;
792 }
793 
794 static int
matches_type(Dxf_Pair * restrict pair,const Dwg_DYNAPI_field * restrict f)795 matches_type (Dxf_Pair *restrict pair, const Dwg_DYNAPI_field *restrict f)
796 {
797   switch (pair->type)
798     {
799     case DWG_VT_STRING:
800       if (f->is_string)
801         return 1;
802       if (f->type[0] == 'H')
803         return 1; // handles can be just names
804       break;
805     case DWG_VT_INT64:
806       // BLL or RLL
807       if (f->size == 8 && f->type[1] == 'L' && f->type[2] == 'L')
808         return 1;
809       // fall through
810     case DWG_VT_INT32:
811       // BL or RL
812       if (f->size == 4 && f->type[1] == 'L')
813         return 1;
814       // fall through
815     case DWG_VT_INT16:
816       // BS or RS or CMC
817       if (f->size == 2 && f->type[1] == 'S')
818         return 1;
819       if (strEQc (f->type, "CMC"))
820         return 1;
821       if (strEQc (f->type, "BSd"))
822         return 1;
823       // fall through
824     case DWG_VT_INT8:
825       if (strEQc (f->type, "RC"))
826         return 1;
827       // fall through
828     case DWG_VT_BOOL:
829       if (strEQc (f->type, "B"))
830         return 1;
831       break;
832     case DWG_VT_REAL:
833       // BD or RD
834       if (f->size == 8 && f->type[1] == 'D')
835         return 1;
836       if (strEQc (f->type, "TIMEBLL"))
837         return 1;
838       break;
839     case DWG_VT_POINT3D:
840       // 3BD or 3RD or 3DPOINT or BE
841       if (f->size == 24 && (f->type[0] == '3' || strEQc (f->type, "BE")))
842         return 1;
843       // accept 2BD or 2RD or 2DPOINT also
844       if (f->size == 16 && f->type[0] == '2')
845         return 1;
846       break;
847     case DWG_VT_BINARY:
848       if (f->is_string)
849         return 1;
850       break;
851     case DWG_VT_HANDLE:
852     case DWG_VT_OBJECTID:
853       if (f->type[0] == 'H')
854         return 1;
855       break;
856     case DWG_VT_INVALID:
857     default:
858       LOG_ERROR ("Invalid DXF group code: %d", pair->code);
859     }
860   return 0;
861 }
862 
863 /* Also used by in_json */
864 const Dwg_DYNAPI_field *
find_numfield(const Dwg_DYNAPI_field * restrict fields,const char * restrict key)865 find_numfield (const Dwg_DYNAPI_field *restrict fields,
866                const char *restrict key)
867 {
868   const Dwg_DYNAPI_field *f;
869   char s[80];
870   strcpy (s, "num_");
871   strcat (s, key);
872   // see gen-dynapi.pl:1102
873   if (strEQc (key, "attribs"))
874     strcpy (s, "num_owned");
875   else if (strEQc (key, "attribs"))
876     strcpy (s, "num_owned");
877   else if (strEQc (key, "items"))
878     strcpy (s, "numitems");
879   else if (strEQc (key, "entities"))
880     strcpy (s, "num_owned");
881   else if (strEQc (key, "sort_ents"))
882     strcpy (s, "num_ents");
883   else if (strEQc (key, "attr_def_id"))
884     strcpy (s, "num_attr_defs");
885   else if (strEQc (key, "layer_entries"))
886     strcpy (s, "num_entries");
887   else if (strEQc (key, "readdeps"))
888     strcpy (s, "num_deps");
889   else if (strEQc (key, "writedeps"))
890     strcpy (s, "num_deps");
891   else if (strEQc (key, "encr_sat_data"))
892     strcpy (s, "num_blocks");
893   else if (strEQc (key, "styles")) // conflicts? only for LTYPE
894     strcpy (s, "num_dashes");
895   else if (strEQc (key, "cellstyle.borders"))
896     strcpy (s, "cellstyle.num_borders");
897   else if (strEQc (key, "segs") || strEQc (key, "polyline_paths"))
898     strcpy (s, "num_segs_or_paths");
899   else if (strEQc (key, "txt.col_sizes"))
900     strcpy (s, "txt.num_col_sizes");
901 search:
902   for (f = &fields[0]; f->name; f++)
903     {
904       if (strEQ (s, f->name))
905         return f;
906     }
907   // or num_owner
908   if (strEQc (key, "vertex"))
909     {
910       strcpy (s, "num_owned");
911       goto search;
912     }
913   // there are two of them
914   if (strEQc (key, "paths") && strNE (s, "num_segs_or_paths"))
915     {
916       strcpy (s, "num_segs_or_paths");
917       goto search;
918     }
919   return NULL;
920 }
921 
922 /* convert to flag */
923 BITCODE_RC
dxf_find_lweight(const int lw)924 dxf_find_lweight (const int lw)
925 {
926   // See acdb.h: 100th of a mm, enum of
927   const int lweights[] = { 0,
928                            5,
929                            9,
930                            13,
931                            15,
932                            18,
933                            20,
934                            25,
935                            30,
936                            35,
937                            40,
938                            50,
939                            53,
940                            60,
941                            70,
942                            80,
943                            90,
944                            100,
945                            106,
946                            120,
947                            140,
948                            158,
949                            200,
950                            211,
951                            /*illegal/reserved:*/ 0,
952                            0,
953                            0,
954                            0,
955                            0,
956                            /*29:*/ -1, // BYLAYER
957                            -2,         // BYBLOCK
958                            -3 };       // BYLWDEFAULT
959   for (int i = 0; i < 32; i++)
960     {
961       if (lweights[i] == lw)
962         return i;
963     }
964   return 0;
965 }
966 
967 // FIXME: support 430 (name), 440 (alpha)
968 static int
dxf_read_CMC(const Dwg_Data * restrict dwg,Bit_Chain * restrict dat,BITCODE_CMC * restrict color,const char * fieldname,const int dxf)969 dxf_read_CMC (const Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
970               BITCODE_CMC *restrict color, const char *fieldname, const int dxf)
971 {
972   int error = 1;
973   unsigned long pos = bit_position (dat);
974   Dxf_Pair *pair = dxf_read_pair (dat);
975   if (!color)
976     {
977       LOG_ERROR ("empty CMC field %s", fieldname);
978       return 1;
979     }
980   if (pair->code < 90 && dxf == pair->code)
981     {
982       color->index = pair->value.i;
983       if (pair->value.i == 256) // bylayer
984         color->method = 0xc2;
985       if (pair->value.i == 257) // none
986         color->method = 0xc8;
987       else if (dwg->header.version >= R_2004)
988         {
989           color->index = 256;
990           color->rgb = pair->value.l;
991           color->rgb |= 0xc2000000;
992           LOG_TRACE ("%s.rgb = 0x%08x [%s %d]\n", fieldname, color->rgb, "CMC",
993                      pair->code);
994         }
995       LOG_TRACE ("%s.index = %d [%s %d]\n", fieldname, color->index, "CMC",
996                  pair->code);
997       // optional 420, 430, 440 fields
998       pos = bit_position (dat);
999       error = dxf_read_CMC (dwg, dat, color, fieldname, dxf);
1000     }
1001   else if (pair->code < 430 && pair->code == (dxf + 420 - 62)) // truecolor
1002     {
1003       color->rgb = pair->value.l;
1004       color->rgb |= 0xc3000000;
1005       LOG_TRACE ("%s.rgb = 0x%08x [%s %d]\n", fieldname, color->rgb, "CMC",
1006                  pair->code);
1007       error = 0;
1008     }
1009   // TODO 430, 440
1010   else if (pair->code < 440 && pair->code == (dxf + 430 - 62)) // name
1011     {
1012       LOG_WARN ("%s.name %s ignored [%s %d]", fieldname, pair->value.s, "CMC",
1013                  pair->code);
1014       error = 0;
1015     }
1016   else if (pair->code < 450 && pair->code == (dxf + 440 - 62)) // alpha
1017     {
1018       LOG_WARN ("%s.alpha %ld ignored [%s %d]", fieldname, pair->value.l, "CMC",
1019                  pair->code);
1020       error = 0;
1021     }
1022   dxf_free_pair (pair);
1023   if (error)
1024     {
1025       LOG_TRACE ("no optional CMC, backup\n");
1026       bit_set_position (dat, pos);
1027     }
1028   return error;
1029 }
1030 
1031 static int
dxf_header_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1032 dxf_header_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1033 {
1034   Dwg_Header_Variables *_obj = &dwg->header_vars;
1035   Dwg_Object *obj = NULL;
1036   const int is_binary = dat->opts & DWG_OPTS_DXFB;
1037   // const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
1038   int is_tu = 1;
1039   int i = 0;
1040   Dxf_Pair *pair;
1041 
1042   // defaults, not often found in a DXF
1043   _obj->ISOLINES = 4;
1044   _obj->TEXTQLTY = 50;
1045   _obj->FACETRES = 0.5;
1046 
1047   // here SECTION (HEADER) was already consumed
1048   // read the first group 9, $field pair
1049   pair = dxf_read_pair (dat);
1050   while (pair != NULL && pair->code == 9 && pair->value.s)
1051     {
1052       char field[80];
1053       strncpy (field, pair->value.s, 79);
1054       field[79] = '\0';
1055       i = 0;
1056 
1057       // now read the code, value pair. for points it may be multiple (index i)
1058       dxf_free_pair (pair);
1059       pair = dxf_read_pair (dat);
1060       if (!pair)
1061         {
1062           pair = dxf_read_pair (dat);
1063           if (!pair)
1064             return 1;
1065         }
1066       DXF_BREAK_ENDSEC;
1067     next_hdrvalue:
1068       if (is_binary && pair->code == 280 &&
1069           (strEQc (field, "$ENDCAPS") || strEQc (field, "$JOINSTYLE")))
1070         dat->byte++; // B => RS
1071       if (pair->code == 1 && strEQc (field, "$ACADVER")
1072           && pair->value.s != NULL)
1073         {
1074           int vi; // C++ quirks
1075           // Note: Here version is still R_INVALID, thus pair->value.s
1076           // is never TU.
1077           const char *version = pair->value.s;
1078           for (Dwg_Version_Type v = R_INVALID; v <= R_AFTER;
1079                vi = (int)v, vi++, v = (Dwg_Version_Type)vi)
1080             {
1081               if (strEQ (version, version_codes[v]))
1082                 {
1083                   dat->from_version = dwg->header.from_version = v;
1084                   is_tu = dat->version >= R_2007;
1085                   LOG_TRACE ("HEADER.from_version = %s,\tdat->from_version = %s\n",
1086                              version_codes[dwg->header.from_version],
1087                              version_codes[dat->from_version]);
1088                   if (is_tu && dwg->num_objects
1089                       && dwg->object[0].fixedtype == DWG_TYPE_BLOCK_HEADER)
1090                     {
1091                       Dwg_Object_BLOCK_HEADER *o
1092                           = dwg->object[0].tio.object->tio.BLOCK_HEADER;
1093                       free (o->name);
1094                       o->name
1095                         = (char *)bit_utf8_to_TU ((char *)"*Model_Space", 0);
1096                     }
1097                   break;
1098                 }
1099               if (v == R_AFTER)
1100                 LOG_ERROR ("Invalid HEADER: 9 %s, 1 %s", field, version)
1101             }
1102           // currently we can only encode DWGs to r13-r2000, but DXF's to almost everything.
1103           if (dwg->header.from_version >= R_13 && dwg->header.from_version <= R_2000)
1104             dwg->header.version = dat->version = dwg->header.from_version;
1105           LOG_TRACE ("HEADER.version = %s,\tdat->version = %s\n",
1106                      version_codes[dwg->header.version],
1107                      version_codes[dat->version]);
1108         }
1109       else if (field[0] == '$')
1110         {
1111           const Dwg_DYNAPI_field *f = dwg_dynapi_header_field (&field[1]);
1112           if (!f)
1113             {
1114               if (pair->code == 40 && strEQc (field, "$3DDWFPREC"))
1115                 {
1116                   LOG_TRACE ("HEADER.%s [%s %d]\n", &field[1], "BD",
1117                              pair->code);
1118                   dwg->header_vars._3DDWFPREC = pair->value.d;
1119                 }
1120 
1121 #define SUMMARY_T(name)                                                       \
1122   (pair->code == 1 && strEQc (field, "$" #name) && pair->value.s != NULL)     \
1123   {                                                                           \
1124     LOG_TRACE ("SUMMARY.%s = %s [TU16 1]\n", &field[1], pair->value.s);       \
1125     dwg->summaryinfo.name = bit_utf8_to_TU (pair->value.s, 0);                \
1126   }
1127 
1128               else if
1129                 SUMMARY_T (TITLE)
1130               else if
1131                 SUMMARY_T (AUTHOR)
1132               else if
1133                 SUMMARY_T (SUBJECT)
1134               else if
1135                 SUMMARY_T (KEYWORDS)
1136               else if
1137                 SUMMARY_T (COMMENTS)
1138               else if
1139                 SUMMARY_T (LASTSAVEDBY)
1140               else if (pair->code == 1 && strEQc (field, "$CUSTOMPROPERTYTAG")
1141                        && pair->value.s != NULL)
1142                 {
1143                   BITCODE_BL j = dwg->summaryinfo.num_props;
1144                   dwg->summaryinfo.num_props++;
1145                   dwg->summaryinfo.props
1146                     = (Dwg_SummaryInfo_Property*)realloc (dwg->summaryinfo.props,
1147                                  (j + 1) * sizeof (Dwg_SummaryInfo_Property));
1148                   LOG_TRACE ("SUMMARY.props[%u].tag = %s [TU16 1]\n", j,
1149                              pair->value.s);
1150                   dwg->summaryinfo.props[j].tag = bit_utf8_to_TU (pair->value.s, 0);
1151                 }
1152               else if (pair->code == 1 && strEQc (field, "$CUSTOMPROPERTY")
1153                        && pair->value.s != NULL && dwg->summaryinfo.props
1154                        && dwg->summaryinfo.num_props > 0)
1155                 {
1156                   BITCODE_BL j = dwg->summaryinfo.num_props - 1;
1157                   LOG_TRACE ("SUMMARY.props[%u].value = %s [TU16 1]\n", j,
1158                              pair->value.s);
1159                   dwg->summaryinfo.props[j].value = bit_utf8_to_TU (pair->value.s, 0);
1160                 }
1161               else
1162                 LOG_ERROR ("skipping HEADER: 9 %s, unknown field with code %d",
1163                            field, pair->code);
1164             }
1165           else if (!matches_type (pair, f) && strNE (field, "$XCLIPFRAME")
1166                    && strNE (field, "$TIMEZONE"))
1167             {
1168               // XCLIPFRAME is 280 RC or 290 B in dynapi.
1169               // TIMEZONE is BLd (signed)
1170               LOG_ERROR (
1171                   "skipping HEADER: 9 %s, wrong type code %d <=> field %s",
1172                   field, pair->code, f->type);
1173             }
1174           else if (pair->type == DWG_VT_POINT3D)
1175             {
1176               BITCODE_3BD pt = { 0.0, 0.0, 0.0 };
1177               if (i)
1178                 dwg_dynapi_header_value (dwg, &field[1], &pt, NULL);
1179               if (i == 0)
1180                 pt.x = pair->value.d;
1181               else if (i == 1)
1182                 pt.y = pair->value.d;
1183               else if (i == 2)
1184                 pt.z = pair->value.d;
1185               if (i > 2)
1186                 {
1187                   LOG_ERROR ("skipping HEADER: 9 %s, too many point elements",
1188                              field);
1189                 }
1190               else
1191                 {
1192                   // yes, set it 2-3 times
1193                   LOG_TRACE ("HEADER.%s [%s %d][%d] = %f\n", &field[1],
1194                              f->type, pair->code, i, pair->value.d);
1195                   dwg_dynapi_header_set_value (dwg, &field[1], &pt, 1);
1196                   i++;
1197                 }
1198             }
1199           else if (pair->type == DWG_VT_STRING && strEQc (f->type, "H"))
1200             {
1201               char *key, *str;
1202               if (pair->value.s && strlen (pair->value.s))
1203                 {
1204                   LOG_TRACE ("HEADER.%s %s [%s %d] later\n", &field[1],
1205                              pair->value.s, f->type, (int)pair->code);
1206                   // name (which table?) => handle
1207                   // needs to be postponed, because we don't have the tables
1208                   // yet.
1209                   header_hdls = array_push (header_hdls, &field[1],
1210                                             pair->value.s, pair->code);
1211                 }
1212               else
1213                 {
1214                   BITCODE_H hdl = dwg_add_handleref (dwg, 5, 0, NULL);
1215                   LOG_TRACE ("HEADER.%s NULL 5 [H %d]\n", &field[1],
1216                              pair->code);
1217                   dwg_dynapi_header_set_value (dwg, &field[1], &hdl, 1);
1218                 }
1219             }
1220           else if (strEQc (f->type, "H"))
1221             {
1222               BITCODE_H hdl;
1223               hdl = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
1224               LOG_TRACE ("HEADER.%s %X [H %d]\n", &field[1], pair->value.u,
1225                          pair->code);
1226               dwg_dynapi_header_set_value (dwg, &field[1], &hdl, 1);
1227             }
1228           else if (strEQc (f->type, "CMC"))
1229             {
1230               static BITCODE_CMC color = { 0 };
1231               if (pair->code <= 70)
1232                 {
1233                   LOG_TRACE ("HEADER.%s.index %d [CMC %d]\n", &field[1],
1234                              pair->value.i, pair->code);
1235                   color.index = pair->value.i;
1236                   dwg_dynapi_header_set_value (dwg, &field[1], &color, 0);
1237                 }
1238             }
1239           else if (pair->type == DWG_VT_REAL && strEQc (f->type, "TIMEBLL"))
1240             {
1241               static BITCODE_TIMEBLL date = { 0, 0, 0 };
1242               date.value = pair->value.d;
1243               date.days = (BITCODE_BL)trunc (pair->value.d);
1244               date.ms = (BITCODE_BL) (86400000.0 * (date.value - date.days));
1245               LOG_TRACE ("HEADER.%s %.09f (" FORMAT_BL ", " FORMAT_BL
1246                          ") [TIMEBLL %d]\n",
1247                          &field[1], date.value, date.days, date.ms,
1248                          pair->code);
1249               dwg_dynapi_header_set_value (dwg, &field[1], &date, 0);
1250             }
1251           else if (pair->type == DWG_VT_STRING)
1252             {
1253               LOG_TRACE ("HEADER.%s [%s %d]\n", &field[1], f->type,
1254                          pair->code);
1255               dwg_dynapi_header_set_value (dwg, &field[1], &pair->value, 1);
1256             }
1257           else
1258             {
1259               LOG_TRACE ("HEADER.%s [%s %d]\n", &field[1], f->type,
1260                          pair->code);
1261               dwg_dynapi_header_set_value (dwg, &field[1], &pair->value, 1);
1262             }
1263         }
1264       else
1265         {
1266           LOG_ERROR ("skipping HEADER: 9 %s, missing the $", field);
1267         }
1268 
1269       dxf_free_pair (pair);
1270       pair = dxf_read_pair (dat);
1271       if (!pair)
1272         {
1273           pair = dxf_read_pair (dat);
1274           if (!pair)
1275             return 1;
1276         }
1277       DXF_BREAK_ENDSEC;
1278       if (pair->code != 9 /* && pair->code != 0 */)
1279         goto next_hdrvalue; // for mult. 10,20,30 values
1280     }
1281 
1282   SINCE (R_2000)
1283   {
1284     BITCODE_BSd celweight = dxf_revcvt_lweight (_obj->CELWEIGHT);
1285     // clang-format off
1286     _obj->FLAGS = (celweight & 0x1f)       |
1287           (_obj->ENDCAPS     ? 0x60   : 0) |
1288           (_obj->JOINSTYLE   ? 0x180  : 0) |
1289           (_obj->LWDISPLAY   ? 0 : 0x200)  |
1290           (_obj->XEDIT       ? 0 : 0x400)  |
1291           (_obj->EXTNAMES    ? 0x800  : 0) |
1292           (_obj->PSTYLEMODE  ? 0x2000 : 0) |
1293           (_obj->OLESTARTUP  ? 0x4000 : 0);
1294     // clang-format on
1295     LOG_TRACE ("HEADER.%s => 0x%x\n", "FLAGS", (unsigned)_obj->FLAGS);
1296     dwg->Template.MEASUREMENT = _obj->MEASUREMENT;
1297     LOG_TRACE ("TEMPLATE.MEASUREMENT = HEADER.MEASUREMENT %d\n",
1298                (int)_obj->MEASUREMENT);
1299   }
1300 
1301   dxf_free_pair (pair);
1302   return 0;
1303 }
1304 
1305 static void
dxf_fixup_header(Dwg_Data * dwg)1306 dxf_fixup_header (Dwg_Data *dwg)
1307 {
1308   Dwg_Header_Variables *vars = &dwg->header_vars;
1309   Dwg_Header *hdr = &dwg->header;
1310   // Dwg_AuxHeader *aux = &dwg->auxheader;
1311   LOG_TRACE ("dxf_fixup_header\n");
1312 
1313   if (vars->HANDSEED)
1314     vars->HANDSEED->handleref.code = 0;
1315   if (vars->DWGCODEPAGE)
1316     {
1317       if (strEQc (vars->DWGCODEPAGE, "ANSI_1252"))
1318         hdr->codepage = 30;
1319       else if (strEQc (vars->DWGCODEPAGE, "UTF-8"))
1320         hdr->codepage = 30;
1321       else if (strEQc (vars->DWGCODEPAGE, "US_ASCII"))
1322         hdr->codepage = 1;
1323       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-1"))
1324         hdr->codepage = 2;
1325       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-2"))
1326         hdr->codepage = 3;
1327       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-3")) // unused?
1328         hdr->codepage = 4;
1329       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-4"))
1330         hdr->codepage = 5;
1331       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-5"))
1332         hdr->codepage = 6;
1333       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-6"))
1334         hdr->codepage = 7;
1335       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-7"))
1336         hdr->codepage = 8;
1337       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-8"))
1338         hdr->codepage = 9;
1339       else if (strEQc (vars->DWGCODEPAGE, "ISO-8859-9"))
1340         hdr->codepage = 10;
1341       else if (strEQc (vars->DWGCODEPAGE, "CP437"))
1342         hdr->codepage = 11;
1343       else if (strEQc (vars->DWGCODEPAGE, "CP850"))
1344         hdr->codepage = 12;
1345       else if (strEQc (vars->DWGCODEPAGE, "CP852"))
1346         hdr->codepage = 13;
1347       else if (strEQc (vars->DWGCODEPAGE, "CP855"))
1348         hdr->codepage = 14;
1349       else if (strEQc (vars->DWGCODEPAGE, "CP857"))
1350         hdr->codepage = 15;
1351       else if (strEQc (vars->DWGCODEPAGE, "CP860"))
1352         hdr->codepage = 16;
1353       else if (strEQc (vars->DWGCODEPAGE, "CP861"))
1354         hdr->codepage = 17;
1355       else if (strEQc (vars->DWGCODEPAGE, "CP863"))
1356         hdr->codepage = 18;
1357       else if (strEQc (vars->DWGCODEPAGE, "CP864"))
1358         hdr->codepage = 19;
1359       else if (strEQc (vars->DWGCODEPAGE, "CP865"))
1360         hdr->codepage = 20;
1361       else if (strEQc (vars->DWGCODEPAGE, "CP869"))
1362         hdr->codepage = 21;
1363       else if (strEQc (vars->DWGCODEPAGE, "CP932"))
1364         hdr->codepage = 22;
1365       else if (strEQc (vars->DWGCODEPAGE, "MACINTOSH"))
1366         hdr->codepage = 23;
1367       else if (strEQc (vars->DWGCODEPAGE, "BIG5"))
1368         hdr->codepage = 24;
1369       else if (strEQc (vars->DWGCODEPAGE, "CP949"))
1370         hdr->codepage = 25;
1371       else if (strEQc (vars->DWGCODEPAGE, "JOHAB"))
1372         hdr->codepage = 27;
1373       else if (strEQc (vars->DWGCODEPAGE, "CP866"))
1374         hdr->codepage = 27;
1375       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1250"))
1376         hdr->codepage = 28;
1377       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1251"))
1378         hdr->codepage = 29;
1379       else if (strEQc (vars->DWGCODEPAGE, "GB2312"))
1380         hdr->codepage = 31;
1381       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1253"))
1382         hdr->codepage = 32;
1383       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1254"))
1384         hdr->codepage = 33;
1385       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1255"))
1386         hdr->codepage = 34;
1387       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1256"))
1388         hdr->codepage = 35;
1389       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1257"))
1390         hdr->codepage = 36;
1391       else if (strEQc (vars->DWGCODEPAGE, "ANSI_874"))
1392         hdr->codepage = 37;
1393       else if (strEQc (vars->DWGCODEPAGE, "ANSI_932"))
1394         hdr->codepage = 38;
1395       else if (strEQc (vars->DWGCODEPAGE, "ANSI_936"))
1396         hdr->codepage = 39;
1397       else if (strEQc (vars->DWGCODEPAGE, "ANSI_949"))
1398         hdr->codepage = 40;
1399       else if (strEQc (vars->DWGCODEPAGE, "ANSI_950"))
1400         hdr->codepage = 41;
1401       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1258"))
1402         hdr->codepage = 44;
1403       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1361"))
1404         hdr->codepage = 42;
1405       else if (strEQc (vars->DWGCODEPAGE, "UTF-16"))
1406         hdr->codepage = 43;
1407       else if (strEQc (vars->DWGCODEPAGE, "ANSI_1258"))
1408         hdr->codepage = 44;
1409       else
1410         hdr->codepage = 0;
1411     }
1412   LOG_TRACE ("HEADER.codepage = %d [%s]\n", hdr->codepage, vars->DWGCODEPAGE);
1413 
1414   // R_2007:
1415   // is_maint: 0x32 [RC 0]
1416   // zero_one_or_three: 0x3 [RC 0]
1417   // thumbnail_addr: 3360 [RL 0]
1418   // dwg_version: 0x1f [RC 0]
1419   // maint_version: 0x8 [RC 0]
1420   // codepage: 30 [RS 0]
1421   // R_2004+:
1422   // unknown_0: 0x0 [RC 0]
1423   // app_dwg_version: 0x1f [RC 0]
1424   // app_maint_version: 0x8 [RC 0]
1425   // security_type: 0 [RL 0]
1426   // rl_1c_address: 0 [RL 0]
1427   // summary_info_address: 3200 [RL 0]
1428   // vba_proj_address: 0 [RL 0]
1429   // r2004_header_address: 128 [RL 0]
1430 
1431   // R_2000:
1432   // is_maint: 0xf [RC 0]
1433   // zero_one_or_three: 0x1 [RC 0]
1434   // thumbnail_addr: 220 [RL 0]
1435   // dwg_version: 0x1f [RC 0]
1436   // maint_version: 0x8 [RC 0]
1437   // codepage: 30 [RS 0]
1438 
1439   if (hdr->version <= R_14)
1440     hdr->is_maint = 0x0;
1441   else if (hdr->version <= R_2000)
1442     {
1443       hdr->is_maint = 0xf; // 0x6 - 0xf
1444       hdr->zero_one_or_three = 1;
1445       hdr->thumbnail_address = 220;
1446       hdr->dwg_version = 0x21;
1447       hdr->maint_version = 0x8;
1448     }
1449   else if (hdr->version <= R_2004)
1450     hdr->is_maint = 0x68;
1451   else if (hdr->version <= R_2007)
1452     hdr->is_maint = 0x32;
1453   else if (hdr->version <= R_2010)
1454     hdr->is_maint = 0x6d;
1455   else if (hdr->version <= R_2013)
1456     hdr->is_maint = 0x7d;
1457   else if (hdr->version <= R_2018)
1458     hdr->is_maint = 0x4;
1459 
1460   if (!vars->FINGERPRINTGUID)
1461     vars->FINGERPRINTGUID = strdup ("{00000000-0000-0000-0000-000000000000}");
1462   if (!vars->VERSIONGUID)
1463     vars->VERSIONGUID
1464         = strdup ("{DE6A95C3-2D01-4A77-AC28-3C42FCFFF657}"); // R_2000
1465 }
1466 
1467 static int
dxf_classes_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)1468 dxf_classes_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
1469 {
1470   BITCODE_BL i;
1471   Dxf_Pair *pair = dxf_read_pair (dat);
1472   Dwg_Class *klass;
1473   const int is_binary = dat->opts & DWG_OPTS_DXFB;
1474   const char* t_type = dat->version >= R_2007 ? "TU" : "TV";
1475 
1476   while (pair)
1477     { // read next class
1478       // add class (see decode)
1479       i = dwg->num_classes;
1480       if (i == 0)
1481         dwg->dwg_class = (Dwg_Class *)malloc (sizeof (Dwg_Class));
1482       else
1483         dwg->dwg_class = (Dwg_Class *)realloc (dwg->dwg_class,
1484                                                (i + 1) * sizeof (Dwg_Class));
1485       if (!dwg->dwg_class)
1486         {
1487           LOG_ERROR ("Out of memory");
1488           return DWG_ERR_OUTOFMEM;
1489         }
1490     restart:
1491       klass = &dwg->dwg_class[i];
1492       memset (klass, 0, sizeof (Dwg_Class));
1493       if (pair != NULL && pair->code == 0 && pair->value.s
1494           && strEQc (pair->value.s, "CLASS"))
1495         {
1496           dxf_free_pair (pair);
1497           pair = dxf_read_pair (dat);
1498           if (!pair)
1499             return 1;
1500         }
1501       else
1502         {
1503           LOG_ERROR ("2 CLASSES must be followed by 0 CLASS")
1504           DXF_RETURN_EOF (DWG_ERR_INVALIDDWG);
1505           return DWG_ERR_INVALIDDWG;
1506         }
1507       klass->number = 500 + i;
1508       while (pair != NULL && pair->code != 0)
1509         { // read until next 0 CLASS
1510           switch (pair->code)
1511             {
1512             case 1:
1513               if (pair->value.s)
1514                 {
1515                   const char *n = strEQc (pair->value.s, "ACDBDATATABLE")
1516                                       ? "DATATABLE"
1517                                       : pair->value.s;
1518                   if (klass->dxfname)
1519                     {
1520                       LOG_ERROR ("Group 1 for CLASS %s already read",
1521                                  klass->dxfname);
1522                       break;
1523                     }
1524                   STRADD_TV (klass->dxfname, n);
1525                   if (dat->version >= R_2007)
1526                     klass->dxfname_u = bit_utf8_to_TU ((char *)n, 0);
1527                   LOG_TRACE ("CLASS[%d].dxfname = %s [TV 1]\n", i, n);
1528                 }
1529               break;
1530             case 2:
1531               if (klass->cppname)
1532                 {
1533                   LOG_ERROR ("Group 2 for CLASS %s already read",
1534                              klass->dxfname);
1535                   break;
1536                 }
1537               if (pair->value.s)
1538                 {
1539                   STRADD_T (klass->cppname, pair->value.s);
1540                 }
1541               LOG_TRACE ("CLASS[%d].cppname = %s [%s 2]\n", i, pair->value.s,
1542                          t_type);
1543               break;
1544             case 3:
1545               if (klass->appname)
1546                 {
1547                   LOG_ERROR ("Group 3 for CLASS %s already read",
1548                              klass->dxfname);
1549                   break;
1550                 }
1551               if (pair->value.s)
1552                 {
1553                   STRADD_T (klass->appname, pair->value.s);
1554                 }
1555               LOG_TRACE ("CLASS[%d].appname = %s [%s 3]\n", i, pair->value.s,
1556                          t_type);
1557               break;
1558             case 90:
1559               klass->proxyflag = pair->value.l;
1560               LOG_TRACE ("CLASS[%d].proxyflag = %ld [BS 90]\n", i,
1561                          pair->value.l);
1562               break;
1563             case 91:
1564               klass->num_instances = pair->value.l;
1565               LOG_TRACE ("CLASS[%d].num_instances = %ld [BL 91]\n", i,
1566                          pair->value.l);
1567               break;
1568             case 280: // ie was_proxy
1569               klass->is_zombie = (BITCODE_B)pair->value.i;
1570               LOG_TRACE ("CLASS[%d].is_zombie = %d [B 280]\n", i,
1571                          pair->value.i);
1572               if (is_binary)
1573                 dat->byte++; // B => RS
1574               break;
1575             case 281: // ie is_entity
1576               // 1f2 for entities, 1f3 for objects
1577               klass->item_class_id = pair->value.i ? 0x1f2 : 0x1f3;
1578               LOG_TRACE ("CLASS[%d].item_class_id = 0x%x [BSx 281] (%s)\n", i,
1579                          klass->item_class_id,
1580                          pair->value.i ? "is_entity" : "is_object");
1581               if (is_binary)
1582                 dat->byte++; // B => RS
1583               break;
1584             default:
1585               LOG_WARN ("Unknown DXF code for class[%d].%d", i, pair->code);
1586               break;
1587             }
1588           dxf_free_pair (pair);
1589           pair = dxf_read_pair (dat);
1590           if (!pair)
1591             {
1592               pair = dxf_read_pair (dat);
1593               if (!pair)
1594                 return 1;
1595             }
1596         }
1597       if (klass->dxfname && klass->cppname && klass->appname
1598           && klass->item_class_id)
1599         {
1600           dwg->num_classes++;
1601           DXF_RETURN_ENDSEC (0)
1602         }
1603       else
1604         {
1605           DXF_RETURN_ENDSEC (0);
1606           goto restart; // without alloc
1607         }
1608     }
1609   dxf_free_pair (pair);
1610   return 0;
1611 }
1612 
1613 static void
add_eed(Dwg_Object * restrict obj,const char * restrict name,Dxf_Pair * restrict pair)1614 add_eed (Dwg_Object *restrict obj, const char *restrict name,
1615          Dxf_Pair *restrict pair)
1616 {
1617   int code, size = 0, j;
1618   int i, prev = 0;
1619   Dwg_Eed *eed;
1620   Dwg_Data *dwg = obj->parent;
1621 
1622   i = obj->tio.object->num_eed; // same layout for Object and Entity
1623   eed = obj->tio.object->eed;
1624 
1625   // new eed pair
1626   if (pair->code < 1020 || pair->code > 1035) // no followup y and z pairs
1627     {
1628       if (i || eed)
1629         {
1630           eed = (Dwg_Eed *)realloc (eed, (i + 1) * sizeof (Dwg_Eed));
1631           if (!eed)
1632             {
1633               LOG_ERROR ("Out of memory");
1634               dwg_free_eed (obj);
1635               return;
1636             }
1637           if (i)
1638             memset (&eed[i], 0, sizeof (Dwg_Eed));
1639         }
1640       else
1641         {
1642           eed = (Dwg_Eed *)xcalloc (1, sizeof (Dwg_Eed));
1643           if (!eed)
1644             {
1645               LOG_ERROR ("Out of memory");
1646               dwg_free_eed (obj);
1647               return;
1648             }
1649         }
1650       obj->tio.object->eed = eed;
1651       obj->tio.object->num_eed++;
1652     }
1653   else // add to old eed
1654     i--;
1655   // search for previous size index
1656   for (j = i; j >= 0; j--)
1657     if (eed[j].handle.code)
1658       prev = j;
1659   if (!(prev >= 0 && prev <= i))
1660     {
1661       LOG_ERROR ("Invalid EED, no prev %d size 1000 code", prev);
1662       dwg_free_eed (obj);
1663       return;
1664     }
1665   assert (prev >= 0 && prev <= i);
1666   code = pair->code - 1000; // 1000
1667   if (code < 0 || code >= 1000)
1668     {
1669       LOG_ERROR ("Invalid DXF code %d", pair->code);
1670       dwg_free_eed (obj);
1671       return;
1672     }
1673   assert (code >= 0 && code < 100);
1674   LOG_TRACE ("EED[%d] code: %d ", i, code);
1675   switch (code)
1676     {
1677     case 0:
1678       {
1679         int len = pair->value.s ? strlen (pair->value.s) : 0;
1680         if (dwg->header.version < R_2007)
1681           {
1682             /* code [RC] + len [RS] + cp [RS] + str[len] */
1683             size = 1 + 2 + 2 + len;
1684             eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size + 1);
1685             if (!eed[i].data)
1686               {
1687                 LOG_ERROR ("Out of memory");
1688                 dwg_free_eed (obj);
1689                 return;
1690               }
1691             eed[i].data->code = code; // 1000
1692             eed[i].data->u.eed_0.is_tu = 0;
1693             eed[i].data->u.eed_0.length = len;
1694             eed[i].data->u.eed_0.codepage = dwg->header.codepage;
1695             if (len && len < 256)
1696               {
1697                 LOG_TRACE ("string: \"%s\" [TV %d]\n", pair->value.s,
1698                            size - 1);
1699                 memcpy (eed[i].data->u.eed_0.string, pair->value.s, len + 1);
1700               }
1701           }
1702         else
1703           {
1704             /* code [RC] + length [RS] + 2*len [TU] */
1705             if (len && len < 32767)
1706               {
1707                 BITCODE_TU tu = bit_utf8_to_TU (pair->value.s, 0);
1708                 len = bit_wcs2len (tu);
1709                 size = 1 + 2 + 2 + (len * 2); // now with padding
1710                 eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size + 2);
1711                 if (!eed[i].data)
1712                   {
1713                     LOG_ERROR ("Out of memory");
1714                     dwg_free_eed (obj);
1715                     return;
1716                   }
1717                 eed[i].data->code = code;
1718                 eed[i].data->u.eed_0.is_tu = 1;
1719                 eed[i].data->u.eed_0_r2007.length = len;
1720                 LOG_TRACE ("wstring: \"%s\" [TU %d]\n", pair->value.s, len);
1721                 if (len)
1722                   memcpy (eed[i].data->u.eed_0_r2007.string, tu,
1723                           2 * (len + 1));
1724                 free (tu);
1725               }
1726           }
1727         eed[i].size += size;
1728       }
1729       break;
1730     // 1001 is the name of the APPID handle, not part of size nor data
1731     case 1:
1732       obj->tio.object->num_eed--;
1733       prev = i;
1734       if (!pair->value.s || !*pair->value.s)
1735         {
1736           LOG_ERROR ("Invalid empty DXF code 1001");
1737           dwg_free_eed (obj);
1738           return;
1739         }
1740       if (strEQc (pair->value.s, "ACAD"))
1741         {
1742           dwg_add_handle (&eed[i].handle, 5, 0x12, NULL);
1743           LOG_TRACE ("handle: 5.1.12 [H] for APPID.%s\n", pair->value.s);
1744         }
1745       else
1746         {
1747           // search name in APPID table (if already added)
1748           BITCODE_H hdl;
1749           hdl = dwg_find_tablehandle_silent (dwg, pair->value.s, "APPID");
1750           if (hdl)
1751             {
1752               memcpy (&eed[i].handle, &hdl->handleref, sizeof (Dwg_Handle));
1753               eed[i].handle.code = 5;
1754               LOG_TRACE ("handle: %lX [H] for APPID.%s\n", hdl->absolute_ref,
1755                          pair->value.s);
1756             }
1757           // needs to be postponed, because we don't have the tables yet
1758           else
1759             {
1760               char idx[12];
1761               snprintf (idx, 12, "%d", obj->index);
1762               eed[i].handle.code = 5;
1763               eed_hdls = array_push (eed_hdls, idx, pair->value.s, i);
1764               LOG_TRACE ("handle: ? [H} for APPID.%s later\n", pair->value.s);
1765             }
1766         }
1767       break;
1768     case 2: // 1002 . "{" => 0, or 1002 . "}" => 1
1769       /* code [RC] + close [RC] */
1770       size = 1 + 1;
1771       eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1772       if (!eed[i].data)
1773         {
1774           LOG_ERROR ("Out of memory");
1775           dwg_free_eed (obj);
1776           return;
1777         }
1778       eed[i].data->code = code;
1779       eed[i].data->u.eed_2.close = strEQc (pair->value.s, "{") ? 0 : 1;
1780       LOG_TRACE ("close: %d\n", eed[i].data->u.eed_2.close);
1781       eed[i].size += size;
1782       break;
1783     case 4:
1784       {
1785         // BINARY
1786         //const char *pos = pair->value.s;
1787         //const unsigned len = strlen (pair->value.s);
1788         const unsigned blen = strlen (pair->value.s) >> 1;
1789         unsigned read;
1790         /* code [RC] + len+0 + length [RC] */
1791         size = 1 + blen + 1 + 1;
1792         eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1793         if (!eed[i].data)
1794           {
1795             LOG_ERROR ("Out of memory");
1796             dwg_free_eed (obj);
1797             return;
1798           }
1799         eed[i].data->code = code; // 1004
1800         eed[i].data->u.eed_4.length = blen;
1801         LOG_TRACE ("binary[%d]: ", blen);
1802         if ((read = in_hex2bin (eed[i].data->u.eed_4.data, pair->value.s, blen) != blen))
1803           LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
1804         eed[i].size += size;
1805       }
1806       break;
1807     case 10: // DWG_VT_POINT3D
1808     case 11:
1809     case 12:
1810     case 13:
1811     case 14:
1812     case 15:
1813       /* code [RC] + 3*RD */
1814       size = 1 + (3 * 8);
1815       eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1816       if (!eed[i].data)
1817         {
1818           LOG_ERROR ("Out of memory");
1819           dwg_free_eed (obj);
1820           return;
1821         }
1822       eed[i].data->code = code;
1823       eed[i].data->u.eed_10.point.x = pair->value.d;
1824       eed[i].size += size;
1825       break;
1826     case 20:
1827     case 21:
1828     case 22:
1829     case 23:
1830     case 24:
1831     case 25:
1832       if (i < 0)
1833         return;
1834       if (!eed[i].data || eed[i].data->code != code - 10)
1835         {
1836           LOG_ERROR ("Wrong EED DXF code %d, expected %d", code + 1000,
1837                      eed[i].data ? eed[i].data->code + 1010 : 1020)
1838           return;
1839         }
1840       eed[i].data->u.eed_10.point.y = pair->value.d;
1841       break;
1842     case 30:
1843     case 31:
1844     case 32:
1845     case 33:
1846     case 34:
1847     case 35:
1848       if (i < 0)
1849         return;
1850       if (!eed[i].data || eed[i].data->code != code - 20)
1851         {
1852           LOG_ERROR ("Wrong EED DXF code %d, expected %d", code + 1000,
1853                      eed[i].data ? eed[i].data->code + 1020 : 1030)
1854           return;
1855         }
1856       eed[i].data->u.eed_10.point.z = pair->value.d;
1857       LOG_TRACE ("3dpoint: (%f,%f,%f)\n", eed[i].data->u.eed_10.point.x,
1858                  eed[i].data->u.eed_10.point.y, pair->value.d);
1859       break;
1860     case 40:
1861     case 41:
1862     case 42:
1863       /* code [RC] + 3*RD */
1864       size = 1 + 8;
1865       eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1866       if (!eed[i].data)
1867         {
1868           LOG_ERROR ("Out of memory");
1869           dwg_free_eed (obj);
1870           return;
1871         }
1872       eed[i].data->code = code; // 1071
1873       eed[i].data->u.eed_40.real = pair->value.d;
1874       LOG_TRACE ("real: %f\n", pair->value.d);
1875       eed[i].size += size;
1876       break;
1877     case 70:
1878       /* code [RC] + RS */
1879       size = 1 + 2;
1880       eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1881       if (!eed[i].data)
1882         {
1883           LOG_ERROR ("Out of memory");
1884           dwg_free_eed (obj);
1885           return;
1886         }
1887       eed[i].data->code = code; // 1071
1888       eed[i].data->u.eed_70.rs = pair->value.i;
1889       LOG_TRACE ("short: %d\n", pair->value.i);
1890       eed[i].size += size;
1891       break;
1892     case 71:
1893       /* code [RC] + RL */
1894       size = 1 + 4;
1895       eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1896       if (!eed[i].data)
1897         {
1898           LOG_ERROR ("Out of memory");
1899           dwg_free_eed (obj);
1900           return;
1901         }
1902       eed[i].data->code = code; // 1071
1903       eed[i].data->u.eed_71.rl = pair->value.l;
1904       LOG_TRACE ("long: %ld\n", pair->value.l);
1905       eed[i].size += size;
1906       break;
1907     case 5:
1908       {
1909         // HANDLE (absref)
1910         const char *pos = pair->value.s;
1911         unsigned long l = 0;
1912         /* code [RC] + RLL */
1913         size = 1 + 8;
1914         eed[i].data = (Dwg_Eed_Data *)xcalloc (1, size);
1915         if (!eed[i].data)
1916           {
1917             LOG_ERROR ("Out of memory");
1918             dwg_free_eed (obj);
1919             return;
1920           }
1921         eed[i].data->code = code; // 1005
1922         sscanf (pos, "%lX", &l);
1923         eed[i].data->u.eed_5.entity = (BITCODE_RLL)l;
1924         LOG_TRACE ("entity: %lX [RLL]\n", l);
1925         eed[i].size += size;
1926         break;
1927       }
1928     default:
1929       LOG_ERROR ("Not yet implemented EED[%d] code %d", i, pair->code);
1930     }
1931   // new size block or not?
1932   if (!eed[i].handle.code)
1933     {
1934       // add to prev. size
1935       if (i != prev)
1936         {
1937           eed[prev].size += eed[i].size;
1938           eed[i].size = 0;
1939         }
1940       LOG_TRACE ("EED[%d] size: %d\n", prev, eed[prev].size);
1941     }
1942   else if (eed[i].size)
1943     LOG_TRACE ("EED[%d] size: %d\n", i, eed[i].size);
1944   return;
1945 }
1946 
1947 int
is_table_name(const char * restrict name)1948 is_table_name (const char *restrict name)
1949 {
1950   return strEQc (name, "LTYPE") || strEQc (name, "VPORT")
1951          || strEQc (name, "VPORT") || strEQc (name, "APPID")
1952          || strEQc (name, "BLOCK") || strEQc (name, "LAYER")
1953          || strEQc (name, "DIMSTYLE") || strEQc (name, "STYLE")
1954          || strEQc (name, "VIEW") || strEQc (name, "VX")
1955          || strEQc (name, "UCS") || strEQc (name, "BLOCK_RECORD")
1956          || strEQc (name, "BLOCK_HEADER");
1957 }
1958 
1959 #define CHK_array(i, array)                                                   \
1960   if (i < 0 || i >= (int)o->num_##array || !o->array)                         \
1961     return NULL;                                                              \
1962   assert (o->array);                                                          \
1963   assert (i >= 0 && i < (int)o->num_##array)
1964 
1965 static Dxf_Pair *
add_LTYPE_dashes(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)1966 add_LTYPE_dashes (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
1967                   Dxf_Pair *restrict pair)
1968 {
1969   Dwg_Object_LTYPE *o = obj->tio.object->tio.LTYPE;
1970   Dwg_Data *dwg = obj->parent;
1971   int num_dashes = (int)o->num_dashes;
1972   int is_tu = 0;
1973 
1974   o->dashes
1975       = (Dwg_LTYPE_dash *)xcalloc (o->num_dashes, sizeof (Dwg_LTYPE_dash));
1976   if (!o->dashes)
1977     {
1978       o->num_dashes = 0;
1979       return NULL;
1980     }
1981   for (int j = -1; j < num_dashes;)
1982     {
1983       if (!pair || pair->code == 0)
1984         return pair;
1985       else if (pair->code == 49)
1986         {
1987           j++;
1988           CHK_array (j, dashes);
1989           o->dashes[j].length = pair->value.d;
1990           LOG_TRACE ("LTYPE.dashes[%d].length = %f [BD 49]\n", j,
1991                      pair->value.d);
1992           PRE (R_13)
1993             o->pattern_len += pair->value.d;
1994         }
1995       else if (pair->code == 74)
1996         {
1997           CHK_array (j, dashes);
1998           o->dashes[j].shape_flag = pair->value.i;
1999           LOG_TRACE ("LTYPE.dashes[%d].shape_flag = %d [BS 74]\n", j,
2000                      pair->value.i);
2001           if (o->dashes[j].shape_flag & 2)
2002             o->has_strings_area = 1;
2003         }
2004       else if (pair->code == 75)
2005         {
2006           if (j < 0)
2007             j++;
2008           CHK_array (j, dashes);
2009           o->dashes[j].complex_shapecode = pair->value.i;
2010           LOG_TRACE ("LTYPE.dashes[%d].complex_shapecode = %d [BS 75]\n", j,
2011                      pair->value.i);
2012         }
2013       else if (pair->code == 340)
2014         {
2015           if (j < 0)
2016             j++;
2017           CHK_array (j, dashes);
2018           o->dashes[j].style
2019               = dwg_add_handleref (obj->parent, 5, pair->value.u, obj);
2020           LOG_TRACE ("LTYPE.dashes[%d].style = " FORMAT_REF " [H 340]\n", j,
2021                      ARGS_REF (o->dashes[j].style));
2022         }
2023       else if (pair->code == 44)
2024         {
2025           CHK_array (j, dashes);
2026           o->dashes[j].x_offset = pair->value.d;
2027           LOG_TRACE ("LTYPE.dashes[%d].x_offset = %f [BD 44]\n", j,
2028                      pair->value.d);
2029         }
2030       else if (pair->code == 45)
2031         {
2032           CHK_array (j, dashes);
2033           o->dashes[j].y_offset = pair->value.d;
2034           LOG_TRACE ("LTYPE.dashes[%d].y_offset = %f [BD 45]\n", j,
2035                      pair->value.d);
2036         }
2037       else if (pair->code == 46)
2038         {
2039           CHK_array (j, dashes);
2040           o->dashes[j].scale = pair->value.d;
2041           LOG_TRACE ("LTYPE.dashes[%d].scale = %f [BD 46]\n", j,
2042                      pair->value.d);
2043         }
2044       else if (pair->code == 50)
2045         {
2046           CHK_array (j, dashes);
2047           o->dashes[j].rotation = deg2rad (pair->value.d);
2048           LOG_TRACE ("LTYPE.dashes[%d].rotation = %f [BD 50]\n", j,
2049                      o->dashes[j].rotation);
2050         }
2051       else if (pair->code == 9)
2052         {
2053           static int dash_i = 0;
2054           is_tu = obj->parent->header.version >= R_2007;
2055           CHK_array (j, dashes);
2056           o->dashes[j].text = dwg_add_u8_input (obj->parent, pair->value.s);
2057           LOG_TRACE ("LTYPE.dashes[%d].text = %s [T 9]\n", j, pair->value.s);
2058           // write into strings_area
2059           if (!o->strings_area)
2060             o->strings_area = (BITCODE_TF)xcalloc (is_tu ? 512 : 256, 1);
2061           if (is_tu)
2062             {
2063               bit_wcs2cpy ((BITCODE_TU)&o->strings_area[dash_i],
2064                            (BITCODE_TU)o->dashes[j].text);
2065               dash_i += (strlen (pair->value.s) * 2) + 2;
2066             }
2067           else
2068             {
2069               strcpy ((char *)&o->strings_area[dash_i], o->dashes[j].text);
2070               dash_i += strlen (pair->value.s) + 1;
2071             }
2072         }
2073       else
2074         break; // not a Dwg_LTYPE_dash
2075 
2076       dxf_free_pair (pair);
2077       pair = dxf_read_pair (dat);
2078     }
2079   return pair;
2080 }
2081 
2082 static Dxf_Pair *
add_MLINESTYLE_lines(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2083 add_MLINESTYLE_lines (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2084                       Dxf_Pair *restrict pair)
2085 {
2086   int num_lines = pair->value.i;
2087   Dwg_Object_MLINESTYLE *o = obj->tio.object->tio.MLINESTYLE;
2088   Dwg_Data *dwg = obj->parent;
2089   o->num_lines = num_lines;
2090   LOG_TRACE ("MLINESTYLE.num_lines = %d [RC 71]\n", num_lines);
2091   o->lines = (Dwg_MLINESTYLE_line *)xcalloc (num_lines,
2092                                              sizeof (Dwg_MLINESTYLE_line));
2093   if (!o->lines)
2094     {
2095       o->num_lines = 0;
2096       return NULL;
2097     }
2098 
2099   for (int j = -1; j < (int)num_lines;)
2100     {
2101       dxf_free_pair (pair);
2102       pair = dxf_read_pair (dat);
2103       if (pair == NULL || pair->code == 0)
2104         return pair;
2105       else if (pair->code == 49)
2106         {
2107           j++;
2108           CHK_array (j, lines);
2109           o->lines[j].offset = pair->value.d;
2110           LOG_TRACE ("MLINESTYLE.lines[%d].offset = %f [BD 49]\n", j,
2111                      pair->value.d);
2112         }
2113       else if (pair->code == 62)
2114         {
2115           if (j < 0)
2116             j++;
2117           CHK_array (j, lines);
2118           o->lines[j].color.index = pair->value.i;
2119           LOG_TRACE ("MLINESTYLE.lines[%d].color.index = %d [CMC 62]\n", j,
2120                      pair->value.i);
2121         }
2122       else if (pair->code == 420)
2123         {
2124           if (j < 0)
2125             j++;
2126           CHK_array (j, lines);
2127           o->lines[j].color.rgb = pair->value.u;
2128           LOG_TRACE ("MLINESTYLE.lines[%d].color.rgb = %08X [CMC 420]\n", j,
2129                      pair->value.u);
2130         }
2131       else if (pair->code == 6)
2132         {
2133           if (j < 0)
2134             j++;
2135           CHK_array (j, lines);
2136           o->lines[j].lt_index = 0;
2137           o->lines[j].lt_ltype = NULL;
2138           if (strEQc (pair->value.s, "BYLAYER")
2139               || strEQc (pair->value.s, "ByLayer"))
2140             {
2141               // TODO SHRT_MAX, but should be -1 really
2142               o->lines[j].lt_index = 32767;
2143               LOG_TRACE ("MLINESTYLE.lines[%d].lt_index = -1 [BSd 6]\n", j);
2144               if (dwg->header.from_version >= R_2018)
2145                 goto mline_hdl;
2146             }
2147           else if (strEQc (pair->value.s, "BYBLOCK")
2148                    || strEQc (pair->value.s, "ByBlock"))
2149             {
2150               o->lines[j].lt_index = 32766;
2151               LOG_TRACE ("MLINESTYLE.lines[%d].lt_index = -2 [BSd 6]\n", j);
2152               if (dwg->header.from_version >= R_2018)
2153                 goto mline_hdl;
2154             }
2155           else if (strEQc (pair->value.s, "CONTINUOUS")
2156                    || strEQc (pair->value.s, "Continuous"))
2157             {
2158               o->lines[j].lt_index = 0;
2159               LOG_TRACE ("MLINESTYLE.lines[%d].lt_index = 0 [BSd 6]\n", j);
2160               if (dwg->header.from_version >= R_2018)
2161                 goto mline_hdl;
2162             }
2163           else // lookup on LTYPE_CONTROL list
2164           mline_hdl:
2165             {
2166               BITCODE_H hdl;
2167               o->lines[j].lt_index
2168                   = (BITCODE_BSd)strtol (pair->value.s, NULL, 10);
2169               if (o->lines[j].lt_index)
2170                 LOG_TRACE ("MLINESTYLE.lines[%d].lt_index = %d [BSd 6]\n", j,
2171                            (int)o->lines[j].lt_index);
2172               if ((hdl = dwg_find_tablehandle_silent (dwg, pair->value.s,
2173                                                       "LTYPE")))
2174                 {
2175                   hdl->handleref.code = 5;
2176                   o->lines[j].lt_ltype = hdl;
2177                   LOG_TRACE ("MLINESTYLE.lines[%d].lt_ltype %s => " FORMAT_REF
2178                              " [H 6]\n",
2179                              j, pair->value.s, ARGS_REF (hdl));
2180                 }
2181             }
2182         }
2183       else
2184         break; // not a Dwg_MLINESTYLE_line
2185     }
2186   return pair;
2187 }
2188 
2189 static Dxf_Pair *
new_LWPOLYLINE(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2190 new_LWPOLYLINE (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2191                 Dxf_Pair *restrict pair)
2192 {
2193   BITCODE_BL num_points = pair->value.u;
2194   Dwg_Entity_LWPOLYLINE *o = obj->tio.entity->tio.LWPOLYLINE;
2195   int j = -1;
2196 
2197   o->num_points = num_points;
2198   LOG_TRACE ("LWPOLYLINE.num_points = %u [BS 90]\n", num_points);
2199   o->points = (BITCODE_2RD *)xcalloc (num_points, sizeof (BITCODE_2RD));
2200   if (!o->points)
2201     {
2202       o->num_points = 0;
2203       return NULL;
2204     }
2205 
2206   while (pair != NULL && pair->code != 0)
2207     {
2208       dxf_free_pair (pair);
2209       pair = dxf_read_pair (dat);
2210       if (pair == NULL || pair->code == 0)
2211         {
2212           LOG_TRACE ("LWPOLYLINE.flag = %d [BS 70]\n", o->flag);
2213           return pair;
2214         }
2215       else if (pair->code == 43)
2216         {
2217           o->const_width = pair->value.d;
2218           if (pair->value.d != 0.0)
2219             o->flag |= 4;
2220           LOG_TRACE ("LWPOLYLINE.const_width = %f [BD 43]\n", pair->value.d);
2221         }
2222       else if (pair->code == 70)
2223         {
2224           if (pair->value.i & 1) /* only if closed or not */
2225             o->flag |= 512;
2226           else if (pair->value.i & 128) /* plinegen? */
2227             o->flag |= 128;
2228           LOG_TRACE ("LWPOLYLINE.flag = %d [BS 70]\n", o->flag);
2229         }
2230       else if (pair->code == 38)
2231         {
2232           o->elevation = pair->value.d;
2233           if (pair->value.d != 0.0)
2234             o->flag |= 8;
2235           LOG_TRACE ("LWPOLYLINE.elevation = %f [38 BD]\n", pair->value.d);
2236         }
2237       else if (pair->code == 39)
2238         {
2239           o->thickness = pair->value.d;
2240           if (pair->value.d != 0.0)
2241             o->flag |= 2;
2242           LOG_TRACE ("LWPOLYLINE.thickness = %f [BD 39]\n", pair->value.d);
2243         }
2244       else if (pair->code == 210)
2245         {
2246           o->extrusion.x = pair->value.d;
2247         }
2248       else if (pair->code == 220)
2249         {
2250           o->extrusion.y = pair->value.d;
2251         }
2252       else if (pair->code == 230)
2253         {
2254           o->extrusion.z = pair->value.d;
2255           if (o->extrusion.x == 0.0 && o->extrusion.y == 0.0)
2256             o->extrusion.z = (o->extrusion.z <= 0.0) ? -1.0 : 1.0;
2257           if (o->extrusion.x != 0.0 || o->extrusion.y != 0.0
2258               || o->extrusion.z != 1.0)
2259             o->flag |= 1;
2260           LOG_TRACE ("LWPOLYLINE.extrusion = (%f, %f, %f) [BE 210]\n",
2261                      o->extrusion.x, o->extrusion.y, o->extrusion.z);
2262         }
2263       else if (pair->code == 10)
2264         {
2265           j++; // we always start with 10 (I hope)
2266 
2267 #define CHK_points                                                            \
2268   if (j < 0 || j >= (int)o->num_points || !o->points)                         \
2269     return NULL;                                                              \
2270   assert (o->points);                                                         \
2271   assert (o->num_points > 0);                                                 \
2272   assert (j >= 0 && j < (int)o->num_points)
2273 
2274           CHK_points;
2275           o->points[j].x = pair->value.d;
2276         }
2277       else if (pair->code == 20)
2278         {
2279           CHK_points;
2280           LOG_TRACE ("LWPOLYLINE.points[%d] = (%f, %f) [2RD 10]\n", j,
2281                      o->points[j].x, pair->value.d);
2282           o->points[j].y = pair->value.d;
2283         }
2284       else if (pair->code == 42)
2285         {
2286           if (!o->num_bulges)
2287             {
2288               o->bulges
2289                   = (BITCODE_BD *)xcalloc (num_points, sizeof (BITCODE_BD));
2290               if (!o->bulges)
2291                 {
2292                   o->num_bulges = 0;
2293                   return NULL;
2294                 }
2295               o->num_bulges = num_points;
2296               o->flag |= 16;
2297             }
2298           CHK_array (j, bulges);
2299           o->bulges[j] = pair->value.d;
2300           LOG_TRACE ("LWPOLYLINE.bulges[%d] = %f [BD 42]\n", j, pair->value.d);
2301         }
2302       else if (pair->code == 91)
2303         {
2304           if (!j)
2305             {
2306               o->vertexids
2307                   = (BITCODE_BL *)xcalloc (num_points, sizeof (BITCODE_BL));
2308               if (!o->vertexids)
2309                 {
2310                   o->num_vertexids = 0;
2311                   return NULL;
2312                 }
2313               o->num_vertexids = num_points;
2314             }
2315           CHK_array (j, vertexids);
2316           o->vertexids[j] = pair->value.i;
2317           LOG_TRACE ("LWPOLYLINE.vertexids[%d] = %d [BL 91]\n", j,
2318                      pair->value.i);
2319         }
2320       else if (pair->code == 40) // not const_width
2321         {
2322           if (!j)
2323             {
2324               o->widths = (Dwg_LWPOLYLINE_width *)xcalloc (
2325                   num_points, sizeof (Dwg_LWPOLYLINE_width));
2326               if (!o->widths)
2327                 {
2328                   o->num_widths = 0;
2329                   return NULL;
2330                 }
2331               o->flag |= 4;
2332               o->num_widths = num_points;
2333             }
2334           CHK_array (j, widths);
2335           o->widths[j].start = pair->value.d;
2336           LOG_TRACE ("LWPOLYLINE.widths[%d].start = %f [BD 40]\n", j,
2337                      pair->value.d);
2338         }
2339       else if (pair->code == 41 && (o->flag & 4)) // not const_width
2340         {
2341           CHK_array (j, widths);
2342           o->widths[j].end = pair->value.d;
2343           LOG_TRACE ("LWPOLYLINE.widths[%d].end = %f [BD 41]\n", j,
2344                      pair->value.d);
2345         }
2346       else if (pair->code >= 1000 && pair->code < 1999)
2347         {
2348           add_eed (obj, "LWPOLYLINE", pair);
2349         }
2350       else
2351         {
2352           LOG_ERROR ("Invalid DXF code %d for %s", pair->code, "LWPOLYLINE");
2353           return NULL;
2354         }
2355     }
2356   return pair;
2357 }
2358 #undef CHK_points
2359 
2360 // only code 1
2361 static Dxf_Pair *
add_3DSOLID_encr(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2362 add_3DSOLID_encr (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2363                   Dxf_Pair *restrict pair)
2364 {
2365   Dwg_Entity_3DSOLID *o = obj->tio.entity->tio._3DSOLID;
2366   int i = 0, total = 0;
2367   o->num_blocks = 1;
2368   o->encr_sat_data = (char **)xcalloc (2, sizeof (char *));
2369   if (!o->encr_sat_data)
2370     {
2371       o->num_blocks = 0;
2372       return NULL;
2373     }
2374   o->encr_sat_data[0] = NULL;
2375   o->block_size = (BITCODE_BL *)xcalloc (2, sizeof (BITCODE_BL));
2376   if (!o->block_size)
2377     {
2378       o->num_blocks = 0;
2379       return NULL;
2380     }
2381 
2382   while (pair != NULL && (pair->code == 1 || pair->code == 3))
2383     {
2384       int len;
2385       if (!pair->value.s)
2386         {
2387           dxf_free_pair (pair);
2388           pair = dxf_read_pair (dat);
2389           continue;
2390         }
2391       len = strlen (pair->value.s) + 1; // + the \n
2392       if (len > 100000) // chunked into blocks of size 4096
2393         {
2394           LOG_ERROR ("Out of memory");
2395           return NULL;
2396         }
2397       if (!total || !o->encr_sat_data[0])
2398         {
2399           total = len;
2400           o->encr_sat_data[0] = (char *)malloc (total + 1); // + the \0
2401           if (!o->encr_sat_data[0])
2402             {
2403               LOG_ERROR ("Out of memory");
2404               return NULL;
2405             }
2406           // memcpy (o->encr_sat_data[0], pair->value.s, len + 1);
2407           strcpy ((char *)o->encr_sat_data[0], pair->value.s);
2408         }
2409       else
2410         {
2411           total += len;
2412           o->encr_sat_data[0]
2413               = (char *)realloc (o->encr_sat_data[0], total + 1);
2414           if (!o->encr_sat_data[0])
2415             {
2416               LOG_ERROR ("Out of memory");
2417               return NULL;
2418             }
2419           strcat ((char *)o->encr_sat_data[0], pair->value.s);
2420         }
2421       if (pair->code == 1)
2422         {
2423           strcat ((char *)o->encr_sat_data[0], "\n");
2424           // For the replacement of "^ " with "^" see below
2425           i++;
2426         }
2427 
2428       dxf_free_pair (pair);
2429       pair = dxf_read_pair (dat);
2430     }
2431   LOG_TRACE ("%s.block_size[0]: %d\n", obj->name, total);
2432 
2433   if (o->version == 1)
2434     {
2435       int idx = 0;
2436       o->unknown = 1; // ??
2437       o->acis_data = (BITCODE_RC *)xcalloc (1, total + 1);
2438       if (!o->acis_data)
2439         return NULL;
2440       for (i = 0; i < total; i++)
2441         {
2442           if (o->encr_sat_data[0][i] == '^' && i <= total
2443               && o->encr_sat_data[0][i + 1] == ' ')
2444             {
2445               o->acis_data[idx++] = 'A';
2446               i++;
2447             }
2448           else if (o->encr_sat_data[0][i] <= 32)
2449             o->acis_data[idx++] = o->encr_sat_data[0][i];
2450           else
2451             o->acis_data[idx++] = 159 - o->encr_sat_data[0][i];
2452         }
2453       o->acis_data[idx] = '\0';
2454       o->block_size[0] = idx;
2455       LOG_TRACE ("%s.acis_data:\n%s\n", obj->name, o->acis_data);
2456     }
2457 
2458   return pair;
2459 }
2460 
2461 static Dxf_Pair *
add_MESH(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2462 add_MESH (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2463           Dxf_Pair *restrict pair)
2464 {
2465   Dwg_Entity_MESH *o = obj->tio.entity->tio.MESH;
2466   int j = 0;
2467   int vector = 0;
2468 
2469   // valid entry code: 91
2470   if (pair->code == 91)
2471     {
2472       vector = pair->code;
2473       o->num_subdiv_vertex = pair->value.u;
2474       LOG_TRACE ("MESH.num_subdiv_vertex = %u [BL 91]\n", pair->value.u);
2475       if (pair->value.u)
2476         {
2477           o->subdiv_vertex = (BITCODE_3BD *)xcalloc (o->num_subdiv_vertex,
2478                                                      sizeof (BITCODE_3BD));
2479           if (!o->subdiv_vertex)
2480             {
2481               o->num_subdiv_vertex = 0;
2482               return NULL;
2483             }
2484         }
2485     }
2486 
2487   while (pair->code != 0)
2488     {
2489       dxf_free_pair (pair);
2490       pair = dxf_read_pair (dat);
2491 
2492       if (pair == NULL || pair->code == 0)
2493         return pair;
2494       else if (pair->code == 92)
2495         {
2496           j = 0;
2497           vector = pair->code;
2498           o->num_vertex = pair->value.u;
2499           LOG_TRACE ("MESH.num_vertex = %u [BL 92]\n", pair->value.u);
2500           if (pair->value.u)
2501             {
2502               o->vertex = (BITCODE_3BD *)xcalloc (o->num_vertex,
2503                                                   sizeof (BITCODE_3BD));
2504               if (!o->vertex)
2505                 {
2506                   o->num_vertex = 0;
2507                   return NULL;
2508                 }
2509             }
2510         }
2511       else if (pair->code == 93)
2512         {
2513           j = 0;
2514           vector = pair->code;
2515           o->num_faces = pair->value.u;
2516           LOG_TRACE ("MESH.num_faces = %u [BL %d]\n", pair->value.u,
2517                      pair->code);
2518           if (pair->value.u)
2519             {
2520               o->faces
2521                   = (BITCODE_BL *)xcalloc (o->num_faces, sizeof (BITCODE_BL));
2522               if (!o->faces)
2523                 {
2524                   o->num_faces = 0;
2525                   return NULL;
2526                 }
2527             }
2528         }
2529       else if (pair->code == 94)
2530         {
2531           j = 0;
2532           vector = pair->code;
2533           o->num_edges = pair->value.u;
2534           LOG_TRACE ("MESH.num_edges = %u [BL %d]\n", pair->value.u,
2535                      pair->code);
2536           if (pair->value.u) // from face - to face
2537             {
2538               o->edges = (Dwg_MESH_edge *)xcalloc (o->num_edges,
2539                                                    sizeof (Dwg_MESH_edge));
2540               if (!o->edges)
2541                 {
2542                   o->num_edges = 0;
2543                   return NULL;
2544                 }
2545             }
2546         }
2547       else if (pair->code == 95)
2548         {
2549           j = 0;
2550           vector = pair->code;
2551           o->num_crease = pair->value.u;
2552           LOG_TRACE ("MESH.num_crease = %u [BL %d]\n", pair->value.u,
2553                      pair->code);
2554           if (pair->value.u)
2555             {
2556               o->crease
2557                   = (BITCODE_BD *)xcalloc (o->num_crease, sizeof (BITCODE_BD));
2558               if (!o->crease)
2559                 {
2560                   o->num_crease = 0;
2561                   return NULL;
2562                 }
2563             }
2564         }
2565       else if (pair->code == 10)
2566         {
2567           if (vector == 91)
2568             {
2569               CHK_array (j, subdiv_vertex);
2570               o->subdiv_vertex[j].x = pair->value.d;
2571             }
2572           else if (vector == 92)
2573             {
2574               CHK_array (j, vertex);
2575               o->vertex[j].x = pair->value.d;
2576             }
2577           else
2578             goto mesh_error;
2579         }
2580       else if (pair->code == 20)
2581         {
2582           if (vector == 91)
2583             {
2584               CHK_array (j, subdiv_vertex);
2585               o->subdiv_vertex[j].y = pair->value.d;
2586             }
2587           else if (vector == 92)
2588             {
2589               CHK_array (j, vertex);
2590               o->vertex[j].y = pair->value.d;
2591             }
2592           else
2593             goto mesh_error;
2594         }
2595       else if (pair->code == 30)
2596         {
2597           if (vector == 91)
2598             {
2599               CHK_array (j, subdiv_vertex);
2600               o->subdiv_vertex[j].z = pair->value.d;
2601               LOG_TRACE ("MESH.subdiv_vertex[%d] = (%f, %f, %f) [3BD 10]\n", j,
2602                          o->subdiv_vertex[j].x, o->subdiv_vertex[j].y,
2603                          o->subdiv_vertex[j].z);
2604               j++;
2605             }
2606           else if (vector == 92)
2607             {
2608               CHK_array (j, vertex);
2609               o->vertex[j].z = pair->value.d;
2610               LOG_TRACE ("MESH.vertex[%d] = (%f, %f, %f) [3BD 10]\n", j,
2611                          o->vertex[j].x, o->vertex[j].y, o->vertex[j].z);
2612               j++;
2613             }
2614           else
2615             goto mesh_error;
2616         }
2617       else if (pair->code == 90)
2618         {
2619           if (vector == 93)
2620             {
2621               CHK_array (j, faces);
2622               o->faces[j] = pair->value.u;
2623               LOG_TRACE ("MESH.faces[%d] = %u [BL %d]\n", j, pair->value.u,
2624                          pair->code);
2625               j++;
2626             }
2627           else if (vector == 94)
2628             {
2629               int i = j / 2;
2630               CHK_array (i, edges);
2631               assert (j < (int)(2 * o->num_edges));
2632               if (j % 2 == 0)
2633                 {
2634                   o->edges[i].idxfrom = pair->value.u;
2635                 }
2636               else
2637                 {
2638                   o->edges[i].idxto = pair->value.u;
2639                   LOG_TRACE ("MESH.edges[%d] = (%u, %u) [2BL %d]\n", i,
2640                              o->edges[i].idxfrom, pair->value.u, pair->code);
2641                 }
2642               j++;
2643             }
2644           else if (vector == 95)
2645             {
2646               o->num_crease = pair->value.u;
2647               LOG_TRACE ("MESH.num_crease = %u [BL %d]\n", pair->value.u,
2648                          pair->code);
2649               if (pair->value.u) // from face - to face
2650                 {
2651                   o->crease
2652                       = (double *)xcalloc (o->num_crease, sizeof (double));
2653                   if (!o->crease)
2654                     {
2655                       o->num_crease = 0;
2656                       return NULL;
2657                     }
2658                 }
2659             }
2660           else
2661             goto mesh_error;
2662         }
2663       else if (pair->code == 140)
2664         {
2665           if (vector == 95)
2666             {
2667               CHK_array (j, crease);
2668               o->crease[j] = pair->value.u;
2669               LOG_TRACE ("MESH.crease[%d] = %u [BD %d]\n", j, pair->value.u,
2670                          pair->code);
2671               j++;
2672             }
2673           else
2674             goto mesh_error;
2675         }
2676       else if (pair->code >= 1000 && pair->code < 1999)
2677         {
2678           add_eed (obj, "MESH", pair);
2679         }
2680       else
2681         {
2682         mesh_error:
2683           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "MESH");
2684         }
2685     }
2686   return pair;
2687 }
2688 
2689 static Dxf_Pair *
add_HATCH(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)2690 add_HATCH (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
2691            Dxf_Pair *restrict pair)
2692 {
2693   BITCODE_BL num_paths; // 91
2694   Dwg_Entity_HATCH *o = obj->tio.entity->tio.HATCH;
2695   int is_plpath = 0;
2696   int j = -1;
2697   int k = -1;
2698   int l = -1;
2699   int hdl_idx = -1;
2700   bool next_330_boundary_handles = false;
2701 
2702   // valid entry codes
2703   if (pair->code == 91)
2704     {
2705       o->num_paths = pair->value.u;
2706       LOG_TRACE ("HATCH.num_paths = %u [BS 91]\n", o->num_paths);
2707       o->paths
2708           = (Dwg_HATCH_Path *)xcalloc (o->num_paths, sizeof (Dwg_HATCH_Path));
2709       if (!o->paths)
2710         {
2711           o->num_paths = 0;
2712           return NULL;
2713         }
2714     }
2715   else if (pair->code == 78)
2716     {
2717       o->num_deflines = pair->value.l;
2718       LOG_TRACE ("HATCH.num_deflines = %ld [BS 78]\n", pair->value.l);
2719       o->deflines = (Dwg_HATCH_DefLine *)xcalloc (pair->value.l,
2720                                                   sizeof (Dwg_HATCH_DefLine));
2721       if (!o->deflines)
2722         {
2723           o->num_deflines = 0;
2724           return NULL;
2725         }
2726     }
2727   if (pair->code == 453)
2728     {
2729       o->num_colors = pair->value.l;
2730       LOG_TRACE ("HATCH.num_colors = %ld [BL 453]\n", pair->value.l);
2731       o->colors = (Dwg_HATCH_Color *)xcalloc (pair->value.l,
2732                                               sizeof (Dwg_HATCH_Color));
2733       if (!o->colors)
2734         {
2735           o->num_colors = 0;
2736           return NULL;
2737         }
2738     }
2739 
2740   while (pair->code != 0)
2741     {
2742       dxf_free_pair (pair);
2743       pair = dxf_read_pair (dat);
2744 
2745       if (pair == NULL || pair->code == 0 || pair->code == 75)
2746         return pair;
2747       else if (pair->code == 92)
2748         {
2749           j++;
2750 
2751 #define CHK_paths                                                             \
2752   if (!o->paths || j < 0 || j >= (int)o->num_paths)                           \
2753     {                                                                         \
2754       LOG_ERROR ("HATCH no paths or wrong j %u\n", j);                        \
2755       return NULL;                                                            \
2756     }                                                                         \
2757   assert (o->paths);                                                          \
2758   assert (j >= 0);                                                            \
2759   assert (j < (int)o->num_paths)
2760 
2761           CHK_paths;
2762           o->paths[j].flag = pair->value.u;
2763           LOG_TRACE ("HATCH.paths[%d].flag = %u [BL 92]\n", j, pair->value.u);
2764           is_plpath = pair->value.u & 2;
2765           o->has_derived = pair->value.u & 4;
2766           LOG_TRACE ("HATCH.has_derived = %d [B 0]\n", o->has_derived);
2767         }
2768       else if (pair->code == 93)
2769         {
2770           CHK_paths;
2771           o->paths[j].num_segs_or_paths = pair->value.u;
2772           LOG_TRACE ("HATCH.paths[%d].num_segs_or_paths = %u [BL 93]\n", j,
2773                      pair->value.u);
2774           k = -1;
2775           if (pair->value.u && !is_plpath)
2776             { /* segs */
2777               o->paths[j].segs = (Dwg_HATCH_PathSeg *)xcalloc (
2778                   pair->value.u, sizeof (Dwg_HATCH_PathSeg));
2779               if (!o->paths[j].segs)
2780                 {
2781                   o->paths[j].num_segs_or_paths = 0;
2782                   return NULL;
2783                 }
2784             }
2785           else if (pair->value.u)
2786             { /* polyline path */
2787               o->paths[j].polyline_paths = (Dwg_HATCH_PolylinePath *)xcalloc (
2788                   pair->value.u, sizeof (Dwg_HATCH_PolylinePath));
2789               if (!o->paths[j].polyline_paths)
2790                 {
2791                   o->paths[j].num_segs_or_paths = 0;
2792                   return NULL;
2793                 }
2794             }
2795         }
2796       else if (pair->code == 72)
2797         {
2798           CHK_paths;
2799           if (!is_plpath)
2800             {
2801               k++;
2802               assert (k >= 0);
2803               if (j < (int)o->num_paths
2804                   && k < (int)o->paths[j].num_segs_or_paths)
2805                 {
2806                   o->paths[j].segs[k].curve_type = pair->value.i;
2807                   LOG_TRACE (
2808                       "HATCH.paths[%d].segs[%d].curve_type = %d [RC 72]\n", j,
2809                       k, pair->value.i);
2810                 }
2811             }
2812           else
2813             {
2814               o->paths[j].bulges_present = pair->value.i;
2815               LOG_TRACE ("HATCH.paths[%d].bulges_present = %d [RC 72]\n", j,
2816                          pair->value.i);
2817             }
2818         }
2819       else if (pair->code == 73 && is_plpath && pair->value.i)
2820         {
2821           CHK_paths;
2822           o->paths[j].closed = pair->value.i;
2823           LOG_TRACE ("HATCH.paths[%d].closed = %d [RC 73]\n", j,
2824                      pair->value.i);
2825         }
2826       else if (pair->code == 94 && !is_plpath && pair->value.l)
2827         {
2828           CHK_paths;
2829 
2830 #define CHK_segs                                                              \
2831   if (!o->paths[j].segs || k < 0 || k >= (int)o->paths[j].num_segs_or_paths)  \
2832     {                                                                         \
2833       LOG_ERROR ("HATCH no paths[%d].segs or wrong k %d\n", j, k);            \
2834       return NULL;                                                            \
2835     }                                                                         \
2836   assert (o->paths[j].segs);                                                  \
2837   assert (k >= 0);                                                            \
2838   assert (k < (int)o->paths[j].num_segs_or_paths)
2839 
2840           CHK_segs;
2841           o->paths[j].segs[k].degree = pair->value.l;
2842           LOG_TRACE ("HATCH.paths[%d].segs[%d].degree = %ld [BL 94]\n", j, k,
2843                      pair->value.l);
2844         }
2845       else if (pair->code == 74 && !is_plpath)
2846         {
2847           CHK_paths;
2848           CHK_segs;
2849           o->paths[j].segs[k].is_periodic = pair->value.i;
2850           LOG_TRACE ("HATCH.paths[%d].segs[%d].is_periodic = %d [B 74]\n", j,
2851                      k, pair->value.i);
2852         }
2853       else if (pair->code == 95 && !is_plpath)
2854         {
2855           CHK_paths;
2856           CHK_segs;
2857           o->paths[j].segs[k].num_knots = pair->value.l;
2858           LOG_TRACE ("HATCH.paths[%d].segs[%d].num_knots = %ld [BL 95]\n", j,
2859                      k, pair->value.l);
2860           o->paths[j].segs[k].knots
2861               = (double *)xcalloc (pair->value.l, sizeof (double));
2862           if (!o->paths[j].segs[k].knots)
2863             {
2864               o->paths[j].segs[k].num_knots = 0;
2865               return NULL;
2866             }
2867           l = -1;
2868         }
2869       else if (pair->code == 96 && !is_plpath)
2870         {
2871           CHK_paths;
2872           CHK_segs;
2873           o->paths[j].segs[k].num_control_points = pair->value.l;
2874           LOG_TRACE (
2875               "HATCH.paths[%d].segs[%d].num_control_points = %ld [BL 96]\n", j,
2876               k, pair->value.l);
2877           o->paths[j].segs[k].control_points
2878               = (Dwg_HATCH_ControlPoint *)xcalloc (
2879                   pair->value.l, sizeof (Dwg_HATCH_ControlPoint));
2880           if (!o->paths[j].segs[k].control_points)
2881             {
2882               o->paths[j].segs[k].num_control_points = 0;
2883               return NULL;
2884             }
2885           l = -1;
2886         }
2887       else if (pair->code == 10 && !is_plpath && !o->num_seeds)
2888         {
2889           CHK_paths;
2890           CHK_segs;
2891           switch (o->paths[j].segs[k].curve_type)
2892             {
2893             case 1: /* LINE */
2894               o->paths[j].segs[k].first_endpoint.x = pair->value.d;
2895               // LOG_TRACE ("HATCH.paths[%d].segs[%d].first_endpoint.x = %f [10
2896               // 2BD]\n",
2897               //           j, k, pair->value.d);
2898               break;
2899             case 2: /* CIRCULAR ARC */
2900             case 3: /* ELLIPTICAL ARC */
2901               o->paths[j].segs[k].center.x = pair->value.d;
2902               // LOG_TRACE ("HATCH.paths[%d].segs[%d].center.x = %f [10
2903               // 2BD]\n",
2904               //           j, k, pair->value.d);
2905               break;
2906             case 4: /* SPLINE */
2907               l++;
2908 
2909 #define CHK_control_points                                                    \
2910   if (!o->paths[j].segs || l < 0                                              \
2911       || l >= (int)o->paths[j].segs[k].num_control_points)                    \
2912     {                                                                         \
2913       LOG_ERROR ("HATCH no paths[%d].segs or "                                \
2914                  "wrong l %d control_points index\n", j, l);                  \
2915       return NULL;                                                            \
2916     }                                                                         \
2917   assert (l >= 0);                                                            \
2918   assert (l < (int)o->paths[j].segs[k].num_control_points)
2919 
2920               CHK_control_points;
2921               o->paths[j].segs[k].control_points[l].point.x = pair->value.d;
2922               // LOG_TRACE
2923               // ("HATCH.paths[%d].segs[%d].control_points[%d].point.x = %f [10
2924               // 2BD]\n",
2925               //           j, k, l, pair->value.d);
2926               break;
2927             default:
2928               LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
2929                         "for DXF %d",
2930                         j, k, o->paths[j].segs[k].curve_type, pair->code);
2931             }
2932         }
2933       else if (pair->code == 11 && !is_plpath && !o->num_seeds)
2934         {
2935           CHK_paths;
2936           CHK_segs;
2937           switch (o->paths[j].segs[k].curve_type)
2938             {
2939             case 1: /* LINE */
2940               o->paths[j].segs[k].second_endpoint.x = pair->value.d;
2941               // LOG_TRACE ("HATCH.paths[%d].segs[%d].second_endpoint.x = %f
2942               // [2BD 11]\n",
2943               //           j, k, pair->value.d);
2944               break;
2945             case 3: /* ELLIPTICAL ARC */
2946               o->paths[j].segs[k].endpoint.x = pair->value.d;
2947               // LOG_TRACE ("HATCH.paths[%d].segs[%d].endpoint.x = %f [
2948               // 2BD 11]\n",
2949               //           j, k, pair->value.d);
2950               break;
2951             case 4: /* SPLINE */
2952               l++;
2953               CHK_paths;
2954               CHK_segs;
2955               CHK_control_points;
2956               o->paths[j].segs[k].fitpts[l].x = pair->value.d;
2957               // LOG_TRACE ("HATCH.paths[%d].segs[%d].fitpts[%d].x = %f [
2958               // 2RD 11]\n",
2959               //           j, k, l, pair->value.d);
2960               break;
2961             default:
2962               LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
2963                         "for DXF %d",
2964                         j, k, o->paths[j].segs[k].curve_type, pair->code);
2965             }
2966         }
2967       else if (pair->code == 20 && !is_plpath && !o->num_seeds)
2968         {
2969           CHK_paths;
2970           CHK_segs;
2971           switch (o->paths[j].segs[k].curve_type)
2972             {
2973             case 1: /* LINE */
2974               o->paths[j].segs[k].first_endpoint.y = pair->value.d;
2975               LOG_TRACE ("HATCH.paths[%d].segs[%d].first_endpoint = (%f, %f) "
2976                          "[2RD 10]\n",
2977                          j, k, o->paths[j].segs[k].first_endpoint.x,
2978                          pair->value.d);
2979               break;
2980             case 2: /* CIRCULAR ARC */
2981             case 3: /* ELLIPTICAL ARC */
2982               o->paths[j].segs[k].center.y = pair->value.d;
2983               LOG_TRACE (
2984                   "HATCH.paths[%d].segs[%d].center = (%f, %f) [2RD 10]\n", j,
2985                   k, o->paths[j].segs[k].center.x, pair->value.d);
2986               break;
2987             case 4: /* SPLINE */
2988               CHK_control_points;
2989               o->paths[j].segs[k].control_points[l].point.y = pair->value.d;
2990               LOG_TRACE ("HATCH.paths[%d].segs[%d].control_points[%d].point = "
2991                          "(%f, %f) [2RD 10]\n",
2992                          j, k, l,
2993                          o->paths[j].segs[k].control_points[l].point.x,
2994                          pair->value.d);
2995               break;
2996             default:
2997               LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
2998                         "for DXF %d",
2999                         j, k, o->paths[j].segs[k].curve_type, pair->code);
3000             }
3001         }
3002       else if (pair->code == 21 && !is_plpath && !o->num_seeds
3003                && pair->value.d != 0.0)
3004         {
3005           CHK_paths;
3006           CHK_segs;
3007           switch (o->paths[j].segs[k].curve_type)
3008             {
3009             case 1: /* LINE */
3010               o->paths[j].segs[k].second_endpoint.y = pair->value.d;
3011               LOG_TRACE ("HATCH.paths[%d].segs[%d].second_endpoint = (%f, %f) "
3012                          "[2RD 11]\n",
3013                          j, k, o->paths[j].segs[k].second_endpoint.x,
3014                          pair->value.d);
3015               break;
3016             case 3: /* ELLIPTICAL ARC */
3017               o->paths[j].segs[k].endpoint.y = pair->value.d;
3018               LOG_TRACE (
3019                   "HATCH.paths[%d].segs[%d].endpoint = (%f, %f) [2RD 11]\n", j,
3020                   k, o->paths[j].segs[k].endpoint.x, pair->value.d);
3021               break;
3022             case 4: /* SPLINE */
3023               CHK_control_points;
3024               o->paths[j].segs[k].fitpts[l].y = pair->value.d;
3025               LOG_TRACE ("HATCH.paths[%d].segs[%d].fitpts[%d].y = (%f, %f) "
3026                          "[2RD 11]\n",
3027                          j, k, l, o->paths[j].segs[k].fitpts[l].x,
3028                          pair->value.d);
3029               break;
3030             default:
3031               LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
3032                         "for DXF %d",
3033                         j, k, o->paths[j].segs[k].curve_type, pair->code);
3034             }
3035         }
3036       else if (pair->code == 40 && !is_plpath)
3037         {
3038           CHK_paths;
3039           CHK_segs;
3040           switch (o->paths[j].segs[k].curve_type)
3041             {
3042             case 2: /* CIRCULAR ARC */
3043               o->paths[j].segs[k].radius = pair->value.d;
3044               LOG_TRACE ("HATCH.paths[%d].segs[%d].radius = %f [BD 40]\n", j,
3045                          k, pair->value.d);
3046               break;
3047             case 3: /* ELLIPTICAL ARC */
3048               o->paths[j].segs[k].minor_major_ratio = pair->value.d;
3049               LOG_TRACE (
3050                   "HATCH.paths[%d].segs[%d].minor_major_ratio = %f [BD 40]\n",
3051                   j, k, pair->value.d);
3052               break;
3053             case 4: /* SPLINE */
3054               if (l >= 0 && o->paths[j].segs[k].is_rational)
3055                 {
3056                   CHK_control_points;
3057                   o->paths[j].segs[k].control_points[l].weight = pair->value.d;
3058                   LOG_TRACE ("HATCH.paths[%d].segs[%d].control_points[%d]."
3059                              "weight = %f [BD 40]\n",
3060                              j, k, l, pair->value.d);
3061                 }
3062               else
3063                 {
3064 #define CHK_knots                                                             \
3065   if (!o->paths[j].segs ||                                                    \
3066       !o->paths[j].segs[k].knots ||                                           \
3067       l < 0 ||                                                                \
3068       l >= (int)o->paths[j].segs[k].num_knots)                                \
3069     {                                                                         \
3070       LOG_ERROR ("HATCH no paths[%d].segs[%d].knots or "                      \
3071                  "wrong l %d knots index\n", j, k, l);                        \
3072       return NULL;                                                            \
3073     }                                                                         \
3074   assert (l >= 0);                                                            \
3075   assert (l < (int)o->paths[j].segs[k].num_knots)
3076 
3077                   l++;
3078                   CHK_knots;
3079                   o->paths[j].segs[k].knots[l] = pair->value.d;
3080                   LOG_TRACE (
3081                       "HATCH.paths[%d].segs[%d].knots[%d] = %f [BD 40]\n", j,
3082                       k, l, pair->value.d);
3083                   if (l == (int)o->paths[j].segs[k].num_knots - 1) // last 40
3084                     l = -1;
3085                 }
3086               break;
3087             default:
3088               LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
3089                         "for DXF %d",
3090                         j, k, o->paths[j].segs[k].curve_type, pair->code);
3091             }
3092         }
3093       else if (pair->code == 50 && !is_plpath)
3094         {
3095           CHK_paths;
3096           CHK_segs;
3097           switch (o->paths[j].segs[k].curve_type)
3098             {
3099             case 2: /* CIRCULAR ARC */
3100             case 3: /* ELLIPTICAL ARC */
3101               o->paths[j].segs[k].start_angle = deg2rad (pair->value.d);
3102               LOG_TRACE ("HATCH.paths[%d].segs[%d].start_angle = %f [BD 50]\n",
3103                          j, k, pair->value.d);
3104               break;
3105             default:
3106               LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
3107                         "for DXF %d",
3108                         j, k, o->paths[j].segs[k].curve_type, pair->code);
3109             }
3110         }
3111       else if (pair->code == 51 && !is_plpath)
3112         {
3113           CHK_paths;
3114           CHK_segs;
3115           switch (o->paths[j].segs[k].curve_type)
3116             {
3117             case 2: /* CIRCULAR ARC */
3118             case 3: /* ELLIPTICAL ARC */
3119               o->paths[j].segs[k].end_angle = deg2rad (pair->value.d);
3120               LOG_TRACE ("HATCH.paths[%d].segs[%d].end_angle = %f [BD 51]\n",
3121                          j, k, pair->value.d);
3122               break;
3123             default:
3124               LOG_WARN ("Unhandled HATCH.paths[%d].segs[%d].curve_type %d "
3125                         "for DXF %d",
3126                         j, k, o->paths[j].segs[k].curve_type, pair->code);
3127             }
3128         }
3129       else if (pair->code == 73 && !is_plpath)
3130         {
3131           CHK_paths;
3132           CHK_segs;
3133           switch (o->paths[j].segs[k].curve_type)
3134             {
3135             case 2: /* CIRCULAR ARC */
3136             case 3: /* ELLIPTICAL ARC */
3137               o->paths[j].segs[k].is_ccw = pair->value.i;
3138               LOG_TRACE ("HATCH.paths[%d].segs[%d].is_ccw = %d [B 73]\n", j, k,
3139                          pair->value.i);
3140               break;
3141             default: // SPLINE 4
3142               o->paths[j].segs[k].is_rational = pair->value.i;
3143               LOG_TRACE ("HATCH.paths[%d].segs[%d].is_rational = %d [B 73]\n",
3144                          j, k, pair->value.i);
3145             }
3146         }
3147       else if (pair->code == 10 && is_plpath && !o->num_seeds)
3148         {
3149           k++;
3150           CHK_paths;
3151 
3152 #define CHK_polyline_paths                                                    \
3153   if (!o->paths[j].polyline_paths || k < 0                                    \
3154       || k >= (int)o->paths[j].num_segs_or_paths)                             \
3155     {                                                                         \
3156       LOG_ERROR ("HATCH no paths[%d].polyline_paths or wrong k %d\n", j, k);  \
3157       return NULL;                                                            \
3158     }                                                                         \
3159   assert (o->paths[j].polyline_paths);                                        \
3160   assert (k >= 0);                                                            \
3161   assert (k < (int)o->paths[j].num_segs_or_paths)
3162 
3163           CHK_polyline_paths;
3164           o->paths[j].polyline_paths[k].point.x = pair->value.d;
3165           // LOG_TRACE ("HATCH.paths[%d].polyline_paths[%d].point.x = %f [BD 10
3166           // ]\n",
3167           //           j, k, pair->value.d);
3168         }
3169       else if (pair->code == 20 && is_plpath && !o->num_seeds)
3170         {
3171           CHK_paths;
3172           CHK_polyline_paths;
3173           o->paths[j].polyline_paths[k].point.y = pair->value.d;
3174           LOG_TRACE (
3175               "HATCH.paths[%d].polyline_paths[%d].point = (%f, %f) [2RD 10]\n",
3176               j, k, o->paths[j].polyline_paths[k].point.x, pair->value.d);
3177         }
3178       else if (pair->code == 42 && is_plpath)
3179         {
3180           CHK_paths;
3181           CHK_polyline_paths;
3182           o->paths[j].polyline_paths[k].bulge = pair->value.d;
3183           LOG_TRACE ("HATCH.paths[%d].polyline_paths[%d].bulge = %f [BD 42]\n",
3184                      j, k, pair->value.d);
3185         }
3186       else if (pair->code == 97 && !is_plpath)
3187         {
3188           CHK_paths;
3189           CHK_segs;
3190           if (k < 0 || o->paths[j].segs[k].curve_type != 4)
3191             {
3192               next_330_boundary_handles = true;
3193               o->paths[j].num_boundary_handles = pair->value.l;
3194               //o->num_boundary_handles += pair->value.l;
3195               LOG_TRACE ("HATCH.paths[%d].num_boundary_handles = %ld [BL 97]\n",
3196                          j, pair->value.l);
3197               k = 0;
3198             }
3199           else
3200             {
3201               next_330_boundary_handles = false;
3202               o->paths[j].segs[k].num_fitpts = pair->value.l;
3203               LOG_TRACE (
3204                   "HATCH.paths[%d].segs[%d].num_fitpts  = %ld [BL 97]\n", j, k,
3205                   pair->value.l);
3206             }
3207         }
3208       else if (pair->code == 97 && is_plpath)
3209         {
3210           CHK_paths;
3211           o->paths[j].num_boundary_handles = pair->value.l;
3212           next_330_boundary_handles = true;
3213           //o->num_boundary_handles += pair->value.l;
3214           LOG_TRACE ("HATCH.paths[%d].num_boundary_handles = %ld [BL 97] (1)\n", j,
3215                      pair->value.l);
3216           k = 0;
3217         }
3218       else if (pair->code == 78)
3219         {
3220           o->num_deflines = pair->value.l;
3221           LOG_TRACE ("HATCH.num_deflines = %ld [BS 78]\n", pair->value.l);
3222           o->deflines = (Dwg_HATCH_DefLine *)xcalloc (
3223               pair->value.l, sizeof (Dwg_HATCH_DefLine));
3224           if (!o->deflines)
3225             {
3226               o->num_deflines = 0;
3227               return NULL;
3228             }
3229           j = -1;
3230         }
3231       else if (pair->code == 53 && o->num_deflines)
3232         {
3233           j++;
3234 
3235 #define CHK_deflines                                                          \
3236   if (!o->deflines || j < 0 || j >= (int)o->num_deflines)                     \
3237     {                                                                         \
3238       LOG_ERROR ("HATCH no deflines or wrong j %d", j);                       \
3239       return NULL;                                                            \
3240     }                                                                         \
3241   assert (j >= 0);                                                            \
3242   assert (j < (int)o->num_deflines)
3243 
3244           CHK_deflines;
3245           o->deflines[j].angle = deg2rad (pair->value.d);
3246           LOG_TRACE ("HATCH.deflines[%d].angle = %f [BD 53]\n", j,
3247                      o->deflines[j].angle);
3248         }
3249       else if (pair->code == 43 && o->num_deflines)
3250         {
3251           CHK_deflines;
3252           o->deflines[j].pt0.x = pair->value.d;
3253           LOG_TRACE ("HATCH.deflines[%d].pt0.x = %f [BD 43]\n", j,
3254                      pair->value.d);
3255         }
3256       else if (pair->code == 44 && o->num_deflines)
3257         {
3258           CHK_deflines;
3259           o->deflines[j].pt0.y = pair->value.d;
3260           LOG_TRACE ("HATCH.deflines[%d].pt0.y = %f [BD 44]\n", j,
3261                      pair->value.d);
3262         }
3263       else if (pair->code == 45 && o->num_deflines)
3264         {
3265           CHK_deflines;
3266           o->deflines[j].offset.x = pair->value.d;
3267           LOG_TRACE ("HATCH.deflines[%d].offset.x = %f [BD 45]\n", j,
3268                      pair->value.d);
3269         }
3270       else if (pair->code == 46 && o->num_deflines)
3271         {
3272           CHK_deflines;
3273           o->deflines[j].offset.y = pair->value.d;
3274           LOG_TRACE ("HATCH.deflines[%d].offset.y = %f [BD 46]\n", j,
3275                      pair->value.d);
3276         }
3277       else if (pair->code == 79 && o->num_deflines)
3278         {
3279           CHK_deflines;
3280           o->deflines[j].num_dashes = pair->value.u;
3281           LOG_TRACE ("HATCH.deflines[%d].num_dashes = %u [BS 79]\n", j,
3282                      pair->value.u);
3283           if (pair->value.u)
3284             {
3285               o->deflines[j].dashes
3286                   = (BITCODE_BD *)xcalloc (pair->value.u, sizeof (BITCODE_BD));
3287               if (!o->deflines[j].dashes)
3288                 {
3289                   o->deflines[j].num_dashes = 0;
3290                   return NULL;
3291                 }
3292             }
3293           k = -1;
3294         }
3295       else if (pair->code == 49 && o->num_deflines && j >= 0)
3296         {
3297           CHK_deflines;
3298           if (!o->deflines[j].dashes)
3299             {
3300               LOG_ERROR ("DXF 79 num_dashes missing for HATCH.dashes 49")
3301               goto unknown_HATCH;
3302             }
3303           k++;
3304           if (!o->deflines[j].dashes || k < 0
3305               || k >= (int)o->deflines[j].num_dashes)
3306             return NULL;
3307           assert (k >= 0);
3308           assert (k < (int)o->deflines[j].num_dashes);
3309           o->deflines[j].dashes[k] = pair->value.d;
3310           LOG_TRACE ("HATCH.deflines[%d].dashes[%d] = %f [BD 49]\n", j, k,
3311                      pair->value.d);
3312         }
3313       else if (pair->code == 47)
3314         {
3315           o->pixel_size = pair->value.d;
3316           LOG_TRACE ("HATCH.pixel_size = %f [BD 47]\n", pair->value.d);
3317         }
3318       else if (pair->code == 98)
3319         {
3320           o->num_seeds = pair->value.u;
3321           LOG_TRACE ("HATCH.num_seeds = %u [BL 98]\n", pair->value.u);
3322           if (pair->value.u)
3323             {
3324               o->seeds = (BITCODE_2RD *)xcalloc (pair->value.u,
3325                                                  sizeof (BITCODE_2RD));
3326               if (!o->seeds)
3327                 {
3328                   o->num_seeds = 0;
3329                   return NULL;
3330                 }
3331             }
3332           k = -1;
3333         }
3334       else if (pair->code == 10 && o->num_seeds)
3335         {
3336           k++;
3337 
3338 #define CHK_seeds                                                             \
3339   if (!o->seeds || k < 0 || k >= (int)o->num_seeds)                           \
3340     {                                                                         \
3341       LOG_ERROR ("HATCH no seeds or wrong k %d", k);                          \
3342       return NULL;                                                            \
3343     }                                                                         \
3344   assert (k >= 0);                                                            \
3345   assert (k < (int)o->num_seeds)
3346 
3347           CHK_seeds;
3348           o->seeds[k].x = pair->value.d;
3349           // LOG_TRACE ("HATCH.seeds[%d].x = %f [10 2RD]\n",
3350           //           k, pair->value.d);
3351         }
3352       else if (pair->code == 20 && o->num_seeds)
3353         {
3354           CHK_seeds;
3355           o->seeds[k].y = pair->value.d;
3356           LOG_TRACE ("HATCH.seeds[%d] = (%f, %f) [2RD 10]\n", k, o->seeds[k].x,
3357                      pair->value.d);
3358         }
3359       else if (pair->code == 330
3360                && next_330_boundary_handles
3361                && j >= 0 && j < (int)o->num_paths
3362                && o->paths[j].num_boundary_handles
3363                && (hdl_idx + 1) < (int)o->paths[j].num_boundary_handles)
3364         {
3365           BITCODE_H ref
3366               = dwg_add_handleref (obj->parent, 4, pair->value.u, obj);
3367           CHK_paths;
3368           hdl_idx++;
3369           if ((unsigned)hdl_idx > o->paths[j].num_boundary_handles)
3370             o->paths[j].num_boundary_handles = (unsigned)hdl_idx;
3371           if (!o->paths[j].boundary_handles)
3372             o->paths[j].boundary_handles = (BITCODE_H *)xcalloc (o->paths[j].num_boundary_handles, sizeof (BITCODE_H));
3373           else
3374             o->paths[j].boundary_handles = (BITCODE_H *)realloc (o->paths[j].boundary_handles,
3375                                                         o->paths[j].num_boundary_handles * sizeof (BITCODE_H));
3376           LOG_TRACE ("HATCH.paths[%d].num_boundary_handles = %u\n", j,
3377                      (unsigned)o->paths[j].num_boundary_handles);
3378           if (!o->paths[j].boundary_handles)
3379             {
3380               o->paths[j].num_boundary_handles = 0;
3381               LOG_ERROR ("! HATCH.paths[%d].boundary_handles", j);
3382               return NULL;
3383             }
3384           o->paths[j].boundary_handles[hdl_idx] = ref;
3385           LOG_TRACE ("HATCH.paths[%d].boundary_handles[%d] = " FORMAT_REF " [H 330]\n",
3386                      j, hdl_idx, ARGS_REF (ref));
3387         }
3388       else if (pair->code == 453)
3389         {
3390           o->num_colors = pair->value.u;
3391           LOG_TRACE ("HATCH.num_colors = %u [BL 453]\n", pair->value.u);
3392           if (pair->value.u)
3393             {
3394               o->colors = (Dwg_HATCH_Color *)xcalloc (
3395                   pair->value.u, sizeof (Dwg_HATCH_Color));
3396               if (!o->colors)
3397                 {
3398                   o->num_colors = 0;
3399                   return NULL;
3400                 }
3401             }
3402           j = -1;
3403         }
3404       else if (pair->code == 463 && o->num_colors)
3405         {
3406           j++;
3407           if (!o->colors || j < 0 || j >= (int)o->num_colors)
3408             return NULL;
3409           assert (j >= 0);
3410           assert (j < (int)o->num_colors);
3411           o->colors[j].shift_value = pair->value.d;
3412           LOG_TRACE ("HATCH.colors[%d].shift_value = %f [BD 463]\n", j,
3413                      pair->value.d);
3414         }
3415       else if (pair->code == 63 && o->num_colors)
3416         {
3417           if (!o->colors || j < 0 || j >= (int)o->num_colors)
3418             return NULL;
3419           assert (j < (int)o->num_colors);
3420           o->colors[j].color.index = pair->value.i;
3421           LOG_TRACE ("HATCH.colors[%d].color.index = %u [CMC 63]\n", j,
3422                      pair->value.i);
3423         }
3424       else if (pair->code == 421 && o->num_colors)
3425         {
3426           if (!o->colors || j < 0 || j >= (int)o->num_colors)
3427             return NULL;
3428           assert (j >= 0);
3429           assert (j < (int)o->num_colors);
3430           o->colors[j].color.rgb = pair->value.u;
3431           LOG_TRACE ("HATCH.colors[%d].color.rgb = %08X [CMC 421]\n", j,
3432                      pair->value.u);
3433         }
3434       else if (pair->code == 431 && o->num_colors)
3435         {
3436           if (!o->colors || j < 0 || j >= (int)o->num_colors)
3437             return NULL;
3438           assert (j >= 0);
3439           assert (j < (int)o->num_colors);
3440           if (dat->version >= R_2007)
3441             o->colors[j].color.name
3442               = (BITCODE_T)bit_utf8_to_TU (pair->value.s, 0);
3443           else
3444             o->colors[j].color.name = strdup (pair->value.s);
3445           LOG_TRACE ("HATCH.colors[%d].color.name = %s [CMC 431]\n", j,
3446                      pair->value.s);
3447         }
3448       else if (pair->code == 470)
3449         {
3450           dwg_dynapi_entity_set_value (o, "HATCH", "gradient_name",
3451                                        &pair->value, 1);
3452           LOG_TRACE ("HATCH.gradient_name = %s [T 470]\n", pair->value.s);
3453         }
3454       else if (pair->code == 450)
3455         {
3456           o->is_gradient_fill = pair->value.u;
3457           LOG_TRACE ("HATCH.is_gradient_fill = %u [BL 450]\n", pair->value.u);
3458         }
3459       else if (pair->code == 451)
3460         {
3461           o->reserved = pair->value.u;
3462           LOG_TRACE ("HATCH.reserved = %u [BL 451]\n", pair->value.u);
3463         }
3464       else if (pair->code == 460)
3465         {
3466           o->gradient_angle = deg2rad (pair->value.d);
3467           LOG_TRACE ("HATCH.gradient_angle = %f [BD 460]\n", pair->value.d);
3468         }
3469       else if (pair->code == 461)
3470         {
3471           o->gradient_shift = pair->value.d;
3472           LOG_TRACE ("HATCH.gradient_shift = %f [BD 461]\n", pair->value.d);
3473         }
3474       else if (pair->code == 452)
3475         {
3476           o->single_color_gradient = pair->value.u;
3477           LOG_TRACE ("HATCH.single_color_gradient = %u [BL 452]\n",
3478                      pair->value.u);
3479         }
3480       else if (pair->code == 462)
3481         {
3482           o->gradient_tint = pair->value.d;
3483           LOG_TRACE ("HATCH.gradient_tint = %f [BD 462]\n", pair->value.d);
3484         }
3485       else if (pair->code >= 1000 && pair->code < 1999)
3486         {
3487           add_eed (obj, "HATCH", pair);
3488         }
3489       else
3490         {
3491         unknown_HATCH:
3492           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "HATCH");
3493         }
3494     }
3495   return pair;
3496 }
3497 #undef CHK_paths
3498 #undef CHK_polyline_paths
3499 #undef CHK_deflines
3500 #undef CHK_seeds
3501 
3502 static Dxf_Pair *
add_MULTILEADER_lines(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair,Dwg_LEADER_Node * lnode)3503 add_MULTILEADER_lines (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
3504                        Dxf_Pair *restrict pair, Dwg_LEADER_Node *lnode)
3505 {
3506   Dwg_Entity_MULTILEADER *o = obj->tio.entity->tio.MULTILEADER;
3507   if (!lnode)
3508     return NULL;
3509   lnode->num_lines = 0;
3510   if (pair->code == 304 && strEQc (pair->value.s, "LEADER_LINE{"))
3511     {
3512       int i = -1, j = -1, k = -1;
3513       Dwg_MLEADER_AnnotContext *ctx = &o->ctx;
3514       lnode->lines = (Dwg_LEADER_Line *)xcalloc (1, sizeof (Dwg_LEADER_Line));
3515       if (!lnode->lines)
3516         {
3517           lnode->num_lines = 0;
3518           return NULL;
3519         }
3520 
3521       // lines and breaks
3522       while (pair->code != 305 && pair->code != 0)
3523         {
3524           Dwg_LEADER_Line *lline = &lnode->lines[0];
3525           dxf_free_pair (pair);
3526           pair = dxf_read_pair (dat);
3527           if (!pair)
3528             return NULL;
3529           switch (pair->code)
3530             {
3531             case 10:
3532               i++;
3533               lnode->num_lines = i + 1;
3534               LOG_TRACE ("%s.leaders[].num_lines = %d\n", obj->name, i + 1);
3535               if (i > 0)
3536                 {
3537                   lnode->lines = (Dwg_LEADER_Line *)realloc (
3538                       lnode->lines,
3539                       lnode->num_lines * sizeof (Dwg_LEADER_Line));
3540                   if (!lnode->lines)
3541                     {
3542                       lnode->num_lines = 0;
3543                       LOG_ERROR ("Out of memory");
3544                       return NULL;
3545                     }
3546                 }
3547               lline = &lnode->lines[i];
3548               memset (lline, 0, sizeof (Dwg_LEADER_Line));
3549               lline->num_breaks = 0;
3550               j++;
3551               lline->num_points = j + 1;
3552               lline->points = (BITCODE_3BD *)realloc (
3553                   lline->points, lline->num_points * sizeof (BITCODE_3BD));
3554               memset (&lline->points[j], 0, sizeof (BITCODE_3BD));
3555               lline->points[j].x = pair->value.d;
3556               LOG_TRACE ("%s.leaders[].lines[%d].points[%d].x = %f [BD %d]\n",
3557                          obj->name, i, j, pair->value.d, pair->code);
3558               break;
3559             case 20:
3560 #define CHK_points                                                            \
3561   if (j < 0 || j >= (int)lline->num_points)                                   \
3562     {                                                                         \
3563       LOG_ERROR ("MULTILEADER wrong j %d points index", j);                   \
3564       return NULL;                                                            \
3565     }                                                                         \
3566   assert (j >= 0 && j < (int)lline->num_points)
3567 
3568 #define CHK_breaks                                                            \
3569   if (k < 0 || k >= (int)lline->num_breaks)                                   \
3570     {                                                                         \
3571       LOG_ERROR ("MULTILEADER wrong k %d breaks index", j);                   \
3572       return NULL;                                                            \
3573     }                                                                         \
3574   assert (k >= 0 && k < (int)lline->num_breaks)
3575 
3576               CHK_points;
3577               lline->points[j].y = pair->value.d;
3578               LOG_TRACE ("%s.leaders[].lines[%d].points[%d].y = %f [BD %d]\n",
3579                          obj->name, i, j, pair->value.d, pair->code);
3580               break;
3581             case 30:
3582               CHK_points;
3583               lline->points[j].z = pair->value.d;
3584               LOG_TRACE ("%s.leaders[].lines[%d].points[%d].z = %f [BD %d]\n",
3585                          obj->name, i, j, pair->value.d, pair->code);
3586               break;
3587             case 11:
3588               CHK_points;
3589               k++;
3590               lline->num_breaks = k + 1;
3591               lline->breaks = (Dwg_LEADER_Break *)realloc (
3592                   lline->breaks, (k + 1) * sizeof (Dwg_LEADER_Break));
3593               memset (&ctx->leaders[k], 0, sizeof (Dwg_LEADER_Break));
3594               lline->breaks[k].start.x = pair->value.d;
3595               LOG_TRACE (
3596                   "%s.leaders[].lines[%d].breaks[%d].start.x = %f [3BD %d]\n",
3597                   obj->name, i, k, pair->value.d, pair->code);
3598               break;
3599             case 21:
3600               CHK_breaks;
3601               lline->breaks[k].start.y = pair->value.d;
3602               LOG_TRACE (
3603                   "%s.leaders[].lines[%d].breaks[%d].start.y = %f [3BD %d]\n",
3604                   obj->name, i, k, pair->value.d, pair->code);
3605               break;
3606             case 31:
3607               CHK_breaks;
3608               lline->breaks[k].start.z = pair->value.d;
3609               LOG_TRACE (
3610                   "%s.leaders[].lines[%d].breaks[%d].start.z = %f [3BD %d]\n",
3611                   obj->name, i, k, pair->value.d, pair->code);
3612               break;
3613             case 12:
3614               CHK_breaks;
3615               lline->breaks[k].end.x = pair->value.d;
3616               LOG_TRACE (
3617                   "%s.leaders[].lines[%d].breaks[%d].end.x = %f [3BD %d]\n",
3618                   obj->name, i, k, pair->value.d, pair->code);
3619               break;
3620             case 22:
3621               CHK_breaks;
3622               lline->breaks[k].end.y = pair->value.d;
3623               LOG_TRACE (
3624                   "%s.leaders[].lines[%d].breaks[%d].end.y = %f [3BD %d]\n",
3625                   obj->name, i, k, pair->value.d, pair->code);
3626               break;
3627             case 32:
3628               CHK_breaks;
3629               lline->breaks[k].end.z = pair->value.d;
3630               LOG_TRACE (
3631                   "%s.leaders[].lines[%d].breaks[%d].end.z = %f [3BD %d]\n",
3632                   obj->name, i, k, pair->value.d, pair->code);
3633               break;
3634             case 91:
3635               lline->line_index = pair->value.u;
3636               LOG_TRACE ("%s.leaders[].lines[%d].line_index = %u [BL %d]\n",
3637                          obj->name, i, pair->value.u, pair->code);
3638               break;
3639             case 170:
3640               lline->type = pair->value.i;
3641               LOG_TRACE ("%s.leaders[].lines[%d].line_index = %d [BS %d]\n",
3642                          obj->name, i, pair->value.i, pair->code);
3643               break;
3644             case 92:
3645               if (pair->value.u > 256)
3646                 {
3647                   lline->color.index = 256;
3648                   lline->color.rgb = pair->value.u;
3649                   lline->color.method = pair->value.u >> 0x18;
3650                   LOG_TRACE (
3651                       "%s.leaders[].lines[%d].color.rgb = %08X [CMC %d]\n",
3652                       obj->name, i, pair->value.u, pair->code);
3653                 }
3654               else
3655                 {
3656                   lline->color.index = pair->value.i;
3657                   LOG_TRACE (
3658                       "%s.leaders[].lines[%d].color.index = %d [CMC %d]\n",
3659                       obj->name, i, pair->value.i, pair->code);
3660                 }
3661               break;
3662             case 171:
3663               lline->linewt = dxf_find_lweight (pair->value.i);
3664               LOG_TRACE ("%s.leaders[].lines[%d].linewt = %d [BL %d]\n",
3665                          obj->name, i, lline->linewt, pair->code);
3666               break;
3667             case 40:
3668               lline->arrow_size = pair->value.d;
3669               LOG_TRACE ("%s.leaders[].lines[%d].arrow_size = %f [BD %d]\n",
3670                          obj->name, i, pair->value.d, pair->code);
3671               break;
3672             case 93:
3673               lline->flags = pair->value.i;
3674               LOG_TRACE ("%s.leaders[].lines[%d].line_index = %d [BL %d]\n",
3675                          obj->name, i, pair->value.i, pair->code);
3676               break;
3677             case 305: // end
3678               break;
3679             default:
3680               LOG_ERROR (
3681                   "Unknown DXF code %d for MULTILEADER.leaders[].lines[%d]",
3682                   pair->code, i);
3683               return pair;
3684             }
3685         }
3686     }
3687   if (!lnode->num_lines)
3688     {
3689       free (lnode->lines);
3690       lnode->lines = NULL;
3691     }
3692   return pair;
3693 }
3694 
3695 #undef CHK_points
3696 #undef CHK_breaks
3697 
3698 static Dxf_Pair *
add_MULTILEADER_leaders(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)3699 add_MULTILEADER_leaders (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
3700                          Dxf_Pair *restrict pair)
3701 {
3702   Dwg_Entity_MULTILEADER *o = obj->tio.entity->tio.MULTILEADER;
3703   if (pair != NULL && pair->code == 302 && strEQc (pair->value.s, "LEADER{"))
3704     {
3705       int i = -1, j = -1;
3706       Dwg_MLEADER_AnnotContext *ctx = &o->ctx;
3707       ctx->num_leaders = 0;
3708       while (pair != NULL && pair->code != 303 && pair->code != 0)
3709         {
3710           Dwg_LEADER_Node *lnode = i >= 0 ? &ctx->leaders[i] : NULL;
3711           dxf_free_pair (pair);
3712           pair = dxf_read_pair (dat);
3713           if (!pair)
3714             return NULL;
3715           if (!lnode && pair->code != 290 && pair->code != 304
3716               && pair->code != 303)
3717             {
3718               LOG_ERROR ("Missing MULTILEADER.LEADER{ 290 start");
3719               return pair;
3720             }
3721           if (lnode)
3722             lnode->num_breaks = 0;
3723           switch (pair->code)
3724             {
3725             case 290:
3726               i++;
3727               ctx->num_leaders = i + 1;
3728               LOG_TRACE ("%s.ctx.num_leaders = %d\n", obj->name, i + 1);
3729               ctx->leaders = (Dwg_LEADER_Node *)realloc (
3730                   ctx->leaders, (i + 1) * sizeof (Dwg_LEADER_Node));
3731               if (!ctx->leaders)
3732                 return NULL;
3733               memset (&ctx->leaders[i], 0, sizeof (Dwg_LEADER_Node));
3734               ctx->leaders[i].has_lastleaderlinepoint = pair->value.i;
3735               LOG_TRACE (
3736                   "%s.ctx.leaders[%d].has_lastleaderlinepoint = %d [B %d]\n",
3737                   obj->name, i, pair->value.i, pair->code);
3738               break;
3739             case 291:
3740               lnode->has_dogleg = pair->value.i;
3741               LOG_TRACE ("%s.ctx.leaders[%d].has_dogleg = %d [B %d]\n",
3742                          obj->name, i, pair->value.i, pair->code);
3743               break;
3744             case 90:
3745               lnode->branch_index = pair->value.u;
3746               LOG_TRACE ("%s.ctx.leaders[%d].branch_index = %u [BL %d]\n",
3747                          obj->name, i, pair->value.u, pair->code);
3748               break;
3749             case 271:
3750               lnode->attach_dir = pair->value.i;
3751               LOG_TRACE ("%s.ctx.leaders[%d].branch_index = %d [BS %d]\n",
3752                          obj->name, i, pair->value.i, pair->code);
3753               break;
3754             case 40:
3755               lnode->dogleg_length = pair->value.d;
3756               LOG_TRACE ("%s.ctx.leaders[%d].dogleg_length = %f [BD %d]\n",
3757                          obj->name, i, pair->value.d, pair->code);
3758               break;
3759             case 10:
3760               lnode->lastleaderlinepoint.x = pair->value.d;
3761               LOG_TRACE (
3762                   "%s.ctx.leaders[%d].lastleaderlinepoint.x = %f [3BD %d]\n",
3763                   obj->name, i, pair->value.d, pair->code);
3764               break;
3765             case 20:
3766               lnode->lastleaderlinepoint.y = pair->value.d;
3767               LOG_TRACE (
3768                   "%s.ctx.leaders[%d].lastleaderlinepoint.y = %f [3BD %d]\n",
3769                   obj->name, i, pair->value.d, pair->code);
3770               break;
3771             case 30:
3772               lnode->lastleaderlinepoint.z = pair->value.d;
3773               LOG_TRACE (
3774                   "%s.ctx.leaders[%d].lastleaderlinepoint.z = %f [BD %d]\n",
3775                   obj->name, i, pair->value.d, pair->code);
3776               break;
3777             case 11:
3778               if (lnode->has_dogleg)
3779                 {
3780                   lnode->dogleg_vector.x = pair->value.d;
3781                   LOG_TRACE (
3782                       "%s.ctx.leaders[%d].dogleg_vector.x = %f [3BD %d]\n",
3783                       obj->name, i, pair->value.d, pair->code);
3784                 }
3785               else
3786                 {
3787                   j++;
3788                   lnode->num_breaks = j + 1;
3789                   LOG_TRACE ("%s.leaders[%d].num_breaks = %d\n", obj->name, i,
3790                              j + 1);
3791                   lnode->breaks = (Dwg_LEADER_Break *)realloc (
3792                       lnode->breaks, (j + 1) * sizeof (Dwg_LEADER_Break));
3793                   lnode->breaks[j].start.x = pair->value.d;
3794                   LOG_TRACE (
3795                       "%s.ctx.leaders[%d].breaks[%d].start.x = %f [3BD %d]\n",
3796                       obj->name, i, j, pair->value.d, pair->code);
3797                 }
3798               break;
3799             case 21:
3800               if (lnode->has_dogleg)
3801                 {
3802                   lnode->dogleg_vector.y = pair->value.d;
3803                   LOG_TRACE (
3804                       "%s.ctx.leaders[%d].dogleg_vector.y = %f [3BD %d]\n",
3805                       obj->name, i, pair->value.d, pair->code);
3806                 }
3807               else
3808                 {
3809 #define CHK_breaks                                                            \
3810   if (j < 0 || j >= (int)lnode->num_breaks)                                   \
3811     return NULL;                                                              \
3812   assert (j >= 0 && j < (int)lnode->num_breaks)
3813 
3814                   CHK_breaks;
3815                   lnode->breaks[j].start.y = pair->value.d;
3816                   LOG_TRACE (
3817                       "%s.ctx.leaders[%d].breaks[%d].start.y = %f [3BD %d]\n",
3818                       obj->name, i, j, pair->value.d, pair->code);
3819                 }
3820               break;
3821             case 31:
3822               if (lnode->has_dogleg)
3823                 {
3824                   lnode->dogleg_vector.z = pair->value.d;
3825                   LOG_TRACE (
3826                       "%s.ctx.leaders[%d].dogleg_vector.z = %f [3BD %d]\n",
3827                       obj->name, i, pair->value.d, pair->code);
3828                 }
3829               else
3830                 {
3831                   CHK_breaks;
3832                   lnode->breaks[j].start.z = pair->value.d;
3833                   LOG_TRACE (
3834                       "%s.ctx.leaders[%d].breaks[%d].start.z = %f [3BD %d]\n",
3835                       obj->name, i, j, pair->value.d, pair->code);
3836                 }
3837               break;
3838             case 12:
3839               CHK_breaks;
3840               lnode->breaks[j].end.x = pair->value.d;
3841               LOG_TRACE ("%s.ctx.leaders[%d].breaks[%d].end.x = %f [3BD %d]\n",
3842                          obj->name, i, j, pair->value.d, pair->code);
3843               break;
3844             case 22:
3845               CHK_breaks;
3846               lnode->breaks[j].end.y = pair->value.d;
3847               LOG_TRACE ("%s.ctx.leaders[%d].breaks[%d].end.y = %f [3BD %d]\n",
3848                          obj->name, i, j, pair->value.d, pair->code);
3849               break;
3850             case 32:
3851               CHK_breaks;
3852               lnode->breaks[j].end.z = pair->value.d;
3853               LOG_TRACE ("%s.ctx.leaders[%d].breaks[%d].end.z = %f [3BD %d]\n",
3854                          obj->name, i, j, pair->value.d, pair->code);
3855               break;
3856             case 304:
3857               if (strEQc (pair->value.s, "LEADER_LINE{"))
3858                 pair = add_MULTILEADER_lines (obj, dat, pair, lnode);
3859               break;
3860             case 303: // end
3861               break;
3862             default:
3863               LOG_ERROR ("Unknown DXF code %d for MULTILEADER.leaders[]",
3864                          pair->code);
3865               return pair;
3866             }
3867         }
3868     }
3869   return pair;
3870 }
3871 #undef CHK_breaks
3872 
3873 static Dxf_Pair *
add_MULTILEADER(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)3874 add_MULTILEADER (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
3875                  Dxf_Pair *restrict pair)
3876 {
3877   Dwg_Entity_MULTILEADER *o = obj->tio.entity->tio.MULTILEADER;
3878   int i = -1, j = -1;
3879 
3880   if (pair->code == 300 && strEQc (pair->value.s, "CONTEXT_DATA{"))
3881     {
3882       // const Dwg_DYNAPI_field *fields
3883       // = dwg_dynapi_subclass_fields ("MLEADER_AnnotContext");
3884       Dwg_MLEADER_AnnotContext *ctx = &o->ctx;
3885       while (pair != NULL && pair->code != 301 && pair->code != 0)
3886         {
3887           switch (pair->code)
3888             {
3889             case 300:
3890               break;
3891             case 40:
3892               ctx->scale_factor = pair->value.d;
3893               LOG_TRACE ("%s.ctx.scale = %f [BD %d]\n", obj->name,
3894                          pair->value.d, pair->code);
3895               break;
3896             case 10:
3897               ctx->content_base.x = pair->value.d;
3898               break;
3899             case 20:
3900               ctx->content_base.y = pair->value.d;
3901               break;
3902             case 30:
3903               ctx->content_base.z = pair->value.d;
3904               LOG_TRACE ("%s.ctx.content_base = (%f, %f, %f) [10 3BD]\n",
3905                          obj->name, ctx->content_base.x, ctx->content_base.y,
3906                          ctx->content_base.z);
3907               break;
3908             case 41:
3909               ctx->text_height = pair->value.d;
3910               LOG_TRACE ("%s.ctx.text_height = %f [BD %d]\n", obj->name,
3911                          pair->value.d, pair->code);
3912               break;
3913             case 140:
3914               ctx->arrow_size = pair->value.d;
3915               LOG_TRACE ("%s.ctx.arrow_size = %f [BD %d]\n", obj->name,
3916                          pair->value.d, pair->code);
3917               break;
3918             case 145:
3919               ctx->landing_gap = pair->value.d;
3920               LOG_TRACE ("%s.ctx.landing_gap = %f [BD %d]\n", obj->name,
3921                          pair->value.d, pair->code);
3922               break;
3923             case 174:
3924               ctx->text_left = pair->value.i;
3925               LOG_TRACE ("%s.ctx.text_left = %d [BS %d]\n", obj->name,
3926                          pair->value.i, pair->code);
3927               break;
3928             case 175:
3929               ctx->text_right = pair->value.i;
3930               LOG_TRACE ("%s.ctx.text_right = %d [BS %d]\n", obj->name,
3931                          pair->value.i, pair->code);
3932               break;
3933             case 176:
3934               ctx->text_angletype = pair->value.i;
3935               LOG_TRACE ("%s.ctx.text_angletype = %d [BS %d]\n", obj->name,
3936                          pair->value.i, pair->code);
3937               break;
3938             case 177:
3939               ctx->text_alignment = pair->value.i;
3940               LOG_TRACE ("%s.ctx.text_alignment = %d [BS %d]\n", obj->name,
3941                          pair->value.i, pair->code);
3942               break;
3943             case 290:
3944               if (ctx->has_content_blk)
3945                 goto unknown_mleader;
3946               ctx->has_content_txt = pair->value.i;
3947               LOG_TRACE ("%s.ctx.has_content_txt = %d [B %d]\n", obj->name,
3948                          pair->value.i, pair->code);
3949               break;
3950             case 302:
3951               if (strEQc (pair->value.s, "LEADER{"))
3952                 pair = add_MULTILEADER_leaders (obj, dat, pair);
3953               break;
3954             case 304:
3955               if (ctx->has_content_txt)
3956                 {
3957                   if (ctx->has_content_blk)
3958                     goto unknown_mleader;
3959                   if (dat->version >= R_2007)
3960                     ctx->content.txt.default_text
3961                       = (char *)bit_utf8_to_TU (pair->value.s, 0);
3962                   else
3963                     ctx->content.txt.default_text = strdup (pair->value.s);
3964                   LOG_TRACE ("%s.ctx.content.txt.default_text = %s [%d T]\n",
3965                              obj->name, pair->value.s, pair->code);
3966                 }
3967               break;
3968             case 340:
3969               if (ctx->has_content_txt)
3970                 {
3971                   if (ctx->has_content_blk)
3972                     goto unknown_mleader;
3973                   ctx->content.txt.style
3974                       = dwg_add_handleref (obj->parent, 5, pair->value.u, obj);
3975                   LOG_TRACE ("%s.ctx.content.txt.style = " FORMAT_REF
3976                              " [%d H]\n",
3977                              obj->name, ARGS_REF (ctx->content.txt.style),
3978                              pair->code);
3979                 }
3980               break;
3981             case 11:
3982               if (!ctx->has_content_txt)
3983                 goto unknown_mleader;
3984               ctx->content.txt.normal.x = pair->value.d;
3985               break;
3986             case 21:
3987               if (!ctx->has_content_txt)
3988                 goto unknown_mleader;
3989               ctx->content.txt.normal.y = pair->value.d;
3990               break;
3991             case 31:
3992               if (!ctx->has_content_txt)
3993                 goto unknown_mleader;
3994               ctx->content.txt.normal.z = pair->value.d;
3995               LOG_TRACE ("%s.ctx.content.txt.normal = (%f, %f, %f) [11 3BD]\n",
3996                          obj->name, ctx->content.txt.normal.x,
3997                          ctx->content.txt.normal.y, ctx->content.txt.normal.z);
3998               break;
3999             case 12:
4000               if (!ctx->has_content_txt)
4001                 goto unknown_mleader;
4002               ctx->content.txt.location.x = pair->value.d;
4003               break;
4004             case 22:
4005               if (!ctx->has_content_txt)
4006                 goto unknown_mleader;
4007               ctx->content.txt.location.y = pair->value.d;
4008               break;
4009             case 32:
4010               if (!ctx->has_content_txt)
4011                 goto unknown_mleader;
4012               ctx->content.txt.location.z = pair->value.d;
4013               LOG_TRACE (
4014                   "%s.ctx.content.txt.location = (%f, %f, %f) [12 3BD]\n",
4015                   obj->name, ctx->content.txt.location.x,
4016                   ctx->content.txt.location.y, ctx->content.txt.location.z);
4017               break;
4018             case 13:
4019               if (!ctx->has_content_txt)
4020                 goto unknown_mleader;
4021               ctx->content.txt.direction.x = pair->value.d;
4022               break;
4023             case 23:
4024               if (!ctx->has_content_txt)
4025                 goto unknown_mleader;
4026               ctx->content.txt.direction.y = pair->value.d;
4027               break;
4028             case 33:
4029               if (!ctx->has_content_txt)
4030                 goto unknown_mleader;
4031               ctx->content.txt.direction.z = pair->value.d;
4032               LOG_TRACE (
4033                   "%s.ctx.content.txt.direction = (%f, %f, %f) [13 3BD]\n",
4034                   obj->name, ctx->content.txt.direction.x,
4035                   ctx->content.txt.direction.y, ctx->content.txt.direction.z);
4036               break;
4037             case 42:
4038               if (!ctx->has_content_txt)
4039                 goto unknown_mleader;
4040               ctx->content.txt.rotation = deg2rad (pair->value.d);
4041               LOG_TRACE ("%s.ctx.content.txt.rotation = %f [BD %d]\n",
4042                          obj->name, ctx->content.txt.rotation, pair->code);
4043               break;
4044             case 43:
4045               if (!ctx->has_content_txt)
4046                 goto unknown_mleader;
4047               ctx->content.txt.width = pair->value.d;
4048               LOG_TRACE ("%s.ctx.content.txt.width = %f [BD %d]\n", obj->name,
4049                          pair->value.d, pair->code);
4050               break;
4051             case 44:
4052               if (!ctx->has_content_txt)
4053                 goto unknown_mleader;
4054               ctx->content.txt.height = pair->value.d;
4055               LOG_TRACE ("%s.ctx.content.txt.height = %f [BD %d]\n", obj->name,
4056                          pair->value.d, pair->code);
4057               break;
4058             case 45:
4059               if (!ctx->has_content_txt)
4060                 goto unknown_mleader;
4061               ctx->content.txt.line_spacing_factor = pair->value.d;
4062               LOG_TRACE (
4063                   "%s.ctx.content.txt.line_spacing_factor = %f [BD %d]\n",
4064                   obj->name, pair->value.d, pair->code);
4065               break;
4066             case 170:
4067               if (!ctx->has_content_txt)
4068                 goto unknown_mleader;
4069               ctx->content.txt.line_spacing_style = pair->value.i;
4070               LOG_TRACE (
4071                   "%s.ctx.content.txt.line_spacing_style = %d [BS %d]\n",
4072                   obj->name, pair->value.i, pair->code);
4073               break;
4074             case 171:
4075               if (!ctx->has_content_txt)
4076                 goto unknown_mleader;
4077               ctx->content.txt.alignment = pair->value.i;
4078               LOG_TRACE ("%s.ctx.content.txt.alignment = %d [BS %d]\n",
4079                          obj->name, pair->value.i, pair->code);
4080               break;
4081             case 172:
4082               if (!ctx->has_content_txt)
4083                 break;
4084               ctx->content.txt.flow = pair->value.i;
4085               LOG_TRACE ("%s.ctx.content.txt.flow = %d [BS %d]\n", obj->name,
4086                          pair->value.i, pair->code);
4087               break;
4088             case 90:
4089               if (!ctx->has_content_txt)
4090                 goto unknown_mleader;
4091               ctx->content.txt.color.index = pair->value.i;
4092               LOG_TRACE ("%s.ctx.content.txt.color.index = %d [BS %d]\n",
4093                          obj->name, pair->value.i, pair->code);
4094               break;
4095             case 91:
4096               if (!ctx->has_content_txt)
4097                 goto unknown_mleader;
4098               ctx->content.txt.bg_color.index = pair->value.i;
4099               LOG_TRACE ("%s.ctx.content.txt.bg_color.index = %d [BS %d]\n",
4100                          obj->name, pair->value.i, pair->code);
4101               break;
4102             case 141:
4103               if (!ctx->has_content_txt)
4104                 goto unknown_mleader;
4105               ctx->content.txt.bg_scale = pair->value.d;
4106               LOG_TRACE ("%s.ctx.content.txt.bg_scale = %f [BD %d]\n",
4107                          obj->name, pair->value.d, pair->code);
4108               break;
4109             case 142:
4110               if (!ctx->has_content_txt)
4111                 goto unknown_mleader;
4112               ctx->content.txt.col_width = pair->value.d;
4113               LOG_TRACE ("%s.ctx.content.txt.col_width = %f [BD %d]\n",
4114                          obj->name, pair->value.d, pair->code);
4115               break;
4116             case 143:
4117               if (!ctx->has_content_txt)
4118                 goto unknown_mleader;
4119               ctx->content.txt.col_gutter = pair->value.d;
4120               LOG_TRACE ("%s.ctx.content.txt.col_gutter = %f [BD %d]\n",
4121                          obj->name, pair->value.d, pair->code);
4122               break;
4123             case 92:
4124               if (!ctx->has_content_txt)
4125                 goto unknown_mleader;
4126               ctx->content.txt.bg_transparency = pair->value.u;
4127               LOG_TRACE ("%s.ctx.content.txt.bg_transparency = %u [BL %d]\n",
4128                          obj->name, pair->value.u, pair->code);
4129               break;
4130             case 291:
4131               if (!ctx->has_content_txt)
4132                 goto unknown_mleader;
4133               ctx->content.txt.is_bg_fill = pair->value.i;
4134               LOG_TRACE ("%s.ctx.content.txt.is_bg_fill = %i [B %d]\n",
4135                          obj->name, pair->value.i, pair->code);
4136               break;
4137             case 292:
4138               if (!ctx->has_content_txt)
4139                 goto unknown_mleader;
4140               ctx->content.txt.is_bg_mask_fill = pair->value.i;
4141               LOG_TRACE ("%s.ctx.content.txt.is_bg_mask_fill = %i [B %d]\n",
4142                          obj->name, pair->value.i, pair->code);
4143               break;
4144             case 293:
4145               if (!ctx->has_content_txt)
4146                 goto unknown_mleader;
4147               ctx->content.txt.is_height_auto = pair->value.i;
4148               LOG_TRACE ("%s.ctx.content.txt.is_height_auto = %i [B %d]\n",
4149                          obj->name, pair->value.i, pair->code);
4150               break;
4151             case 294:
4152               if (!ctx->has_content_txt)
4153                 goto unknown_mleader;
4154               ctx->content.txt.is_col_flow_reversed = pair->value.i;
4155               LOG_TRACE (
4156                   "%s.ctx.content.txt.is_col_flow_reversed = %i [B %d]\n",
4157                   obj->name, pair->value.i, pair->code);
4158               break;
4159             case 295:
4160               if (!ctx->has_content_txt)
4161                 goto unknown_mleader;
4162               ctx->content.txt.word_break = pair->value.i;
4163               LOG_TRACE ("%s.ctx.content.txt.word_break = %i [B %d]\n",
4164                          obj->name, pair->value.i, pair->code);
4165               break;
4166             case 173:
4167               if (!ctx->has_content_txt)
4168                 goto unknown_mleader;
4169               ctx->content.txt.col_type = pair->value.i;
4170               LOG_TRACE ("%s.ctx.content.txt.col_type = %d [BS %d]\n",
4171                          obj->name, pair->value.i, pair->code);
4172               break;
4173             case 144:
4174               if (!ctx->has_content_txt)
4175                 goto unknown_mleader;
4176               i++;
4177               ctx->content.txt.num_col_sizes = i + 1;
4178               ctx->content.txt.col_sizes = (double *)realloc (
4179                   ctx->content.txt.col_sizes, (i + 1) * sizeof (double));
4180               ctx->content.txt.col_sizes[i] = pair->value.d;
4181               LOG_TRACE ("%s.ctx.content.txt.col_sizes[%d] = %f [BD %d]\n",
4182                          obj->name, i, pair->value.d, pair->code);
4183               break;
4184             case 296:
4185               ctx->has_content_blk = pair->value.i;
4186               LOG_TRACE ("%s.ctx.has_content_blk = %i [B %d]\n", obj->name,
4187                          pair->value.i, pair->code);
4188               break;
4189             case 14: // has_block
4190               if (!ctx->has_content_blk)
4191                 goto unknown_mleader;
4192               ctx->content.blk.normal.x = pair->value.d;
4193               LOG_TRACE ("%s.ctx.content.blk.normal.x = %f [3BD %d]\n",
4194                          obj->name, pair->value.d, pair->code);
4195               break;
4196             case 24:
4197               if (!ctx->has_content_blk)
4198                 goto unknown_mleader;
4199               ctx->content.blk.normal.y = pair->value.d;
4200               LOG_TRACE ("%s.ctx.content.blk.normal.y = %f [3BD %d]\n",
4201                          obj->name, pair->value.d, pair->code);
4202               break;
4203             case 34:
4204               if (!ctx->has_content_blk)
4205                 goto unknown_mleader;
4206               ctx->content.blk.normal.z = pair->value.d;
4207               LOG_TRACE ("%s.ctx.content.blk.normal.z = %f [3BD %d]\n",
4208                          obj->name, pair->value.d, pair->code);
4209               break;
4210             case 341:
4211               if (!ctx->has_content_blk)
4212                 goto unknown_mleader;
4213               ctx->content.blk.block_table
4214                   = dwg_add_handleref (obj->parent, 4, pair->value.u, obj);
4215               LOG_TRACE ("%s.ctx.content.blk.block_table = " FORMAT_REF
4216                          " [%d H]\n",
4217                          obj->name, ARGS_REF (ctx->content.blk.block_table),
4218                          pair->code);
4219               break;
4220             case 15: // has_block
4221               if (!ctx->has_content_blk)
4222                 goto unknown_mleader;
4223               ctx->content.blk.normal.x = pair->value.d;
4224               LOG_TRACE ("%s.ctx.content.blk.normal.x = %f [3BD %d]\n",
4225                          obj->name, pair->value.d, pair->code);
4226               break;
4227             case 25:
4228               if (!ctx->has_content_blk)
4229                 goto unknown_mleader;
4230               ctx->content.blk.location.y = pair->value.d;
4231               break;
4232             case 35:
4233               if (!ctx->has_content_blk)
4234                 goto unknown_mleader;
4235               ctx->content.blk.location.z = pair->value.d;
4236               LOG_TRACE (
4237                   "%s.ctx.content.blk.location = (%f, %f, %f) [3BD %d]\n",
4238                   obj->name, ctx->content.blk.location.x,
4239                   ctx->content.blk.location.y, ctx->content.blk.location.z,
4240                   pair->code);
4241               break;
4242             case 16: // has_block
4243               if (!ctx->has_content_blk)
4244                 goto unknown_mleader;
4245               ctx->content.blk.scale.x = pair->value.d;
4246               break;
4247             case 26:
4248               if (!ctx->has_content_blk)
4249                 goto unknown_mleader;
4250               ctx->content.blk.scale.y = pair->value.d;
4251               break;
4252             case 36:
4253               if (!ctx->has_content_blk)
4254                 goto unknown_mleader;
4255               ctx->content.blk.scale.z = pair->value.d;
4256               LOG_TRACE ("%s.ctx.content.blk.scale = (%f, %f, %f) [3BD %d]\n",
4257                          obj->name, ctx->content.blk.scale.x,
4258                          ctx->content.blk.scale.y, ctx->content.blk.scale.z,
4259                          pair->code);
4260               break;
4261             case 46:
4262               if (!ctx->has_content_blk)
4263                 goto unknown_mleader;
4264               ctx->content.blk.rotation = deg2rad (pair->value.d);
4265               LOG_TRACE ("%s.ctx.content.blk.rotation = %f [BD %d]\n",
4266                          obj->name, pair->value.d, pair->code);
4267               break;
4268             case 93:
4269               if (!ctx->has_content_blk)
4270                 goto unknown_mleader;
4271               if (pair->value.u > 257)
4272                 {
4273                   ctx->content.blk.color.index = 256;
4274                   ctx->content.blk.color.rgb = pair->value.u;
4275                   ctx->content.blk.color.method = pair->value.u >> 0x18;
4276                   LOG_TRACE (
4277                       "%s.leaders[].lines[%d].color.rgb = %08X [CMC %d]\n",
4278                       obj->name, i, pair->value.u, pair->code);
4279                 }
4280               else
4281                 {
4282                   ctx->content.blk.color.index = pair->value.i;
4283                   if (pair->value.i == 257)
4284                     {
4285                       ctx->content.blk.color.method = 0xc8;
4286                       ctx->content.blk.color.rgb = 0xc8000000;
4287                     }
4288                   LOG_TRACE (
4289                       "%s.leaders[].lines[%d].color.index = %d [CMC %d]\n",
4290                       obj->name, i, pair->value.i, pair->code);
4291                 }
4292               break;
4293             case 47:
4294               if (!ctx->has_content_blk)
4295                 goto unknown_mleader;
4296               j++;
4297               if (!j)
4298                 {
4299                   ctx->content.blk.transform
4300                       = (double *)xcalloc (16, sizeof (double));
4301                   if (!ctx->content.blk.transform)
4302                     {
4303                       return NULL;
4304                     }
4305                 }
4306               ctx->content.blk.transform[j] = pair->value.d;
4307               LOG_TRACE ("%s.ctx.content.blk.transform[%d] = %f [BD %d]\n",
4308                          obj->name, j, pair->value.d, pair->code);
4309               break;
4310             case 110:
4311               ctx->base.x = pair->value.d;
4312               break;
4313             case 120:
4314               ctx->base.y = pair->value.d;
4315               break;
4316             case 130:
4317               ctx->base.z = pair->value.d;
4318               LOG_TRACE ("%s.ctx.base = (%f, %f, %f) [3BD %d]\n", obj->name,
4319                          ctx->base.x, ctx->base.y, ctx->base.z, pair->code);
4320               break;
4321             case 111:
4322               ctx->base_dir.x = pair->value.d;
4323               break;
4324             case 121:
4325               ctx->base_dir.y = pair->value.d;
4326               break;
4327             case 131:
4328               ctx->base_dir.z = pair->value.d;
4329               LOG_TRACE ("%s.ctx.base = (%f, %f, %f) [3BD %d]\n", obj->name,
4330                          ctx->base_dir.x, ctx->base_dir.y, ctx->base_dir.z,
4331                          pair->code);
4332               break;
4333             case 112:
4334               ctx->base_vert.x = pair->value.d;
4335               break;
4336             case 122:
4337               ctx->base_vert.y = pair->value.d;
4338               break;
4339             case 132:
4340               ctx->base_vert.z = pair->value.d;
4341               LOG_TRACE ("%s.ctx.base = (%f, %f, %f) [3BD %d]\n", obj->name,
4342                          ctx->base_vert.x, ctx->base_vert.y, ctx->base_vert.z,
4343                          pair->code);
4344               break;
4345             case 297:
4346               ctx->is_normal_reversed = pair->value.i;
4347               LOG_TRACE ("%s.ctx.is_normal_reversed = %i [B %d]\n", obj->name,
4348                          pair->value.i, pair->code);
4349               break;
4350             case 273:
4351               ctx->text_top = pair->value.i;
4352               LOG_TRACE ("%s.ctx.text_top = %i [BS %d]\n", obj->name,
4353                          pair->value.i, pair->code);
4354               break;
4355             case 272:
4356               ctx->text_bottom = pair->value.i;
4357               LOG_TRACE ("%s.ctx.text_bottom = %i [BS %d]\n", obj->name,
4358                          pair->value.i, pair->code);
4359               break;
4360 
4361             case 301: // end ctx
4362               return pair;
4363             default:
4364             unknown_mleader:
4365               LOG_ERROR ("Unknown DXF code %d for %s", pair->code,
4366                          "MULTILEADER");
4367             }
4368           dxf_free_pair (pair);
4369           pair = dxf_read_pair (dat);
4370         }
4371     }
4372   return pair;
4373 }
4374 
4375 // returns with pair if not found, or NULL on error.
4376 // only for geomesh_pts (num 93, 13, 14) and geomesh_faces (num 96, 97-99)
4377 static Dxf_Pair *
add_GEODATA(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)4378 add_GEODATA (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
4379              Dxf_Pair *restrict pair)
4380 {
4381   Dwg_Data *dwg = obj->parent;
4382   Dwg_Object_GEODATA *o = obj->tio.object->tio.GEODATA;
4383   int i = -1;
4384 
4385   while (pair != NULL)
4386     {
4387       switch (pair->code)
4388         {
4389         case 93:
4390           i = -1;
4391           o->num_geomesh_pts = pair->value.u;
4392           o->geomesh_pts = (Dwg_GEODATA_meshpt *)xcalloc (
4393               pair->value.u, sizeof (Dwg_GEODATA_meshpt));
4394           if (!o->geomesh_pts && o->num_geomesh_pts)
4395             return NULL;
4396           LOG_TRACE ("%s.num_geomesh_pts = %u [BL %d]\n", obj->name,
4397                      pair->value.u, pair->code);
4398           break;
4399         case 96:
4400           i = -1;
4401           o->num_geomesh_faces = pair->value.u;
4402           o->geomesh_faces = (Dwg_GEODATA_meshface *)xcalloc (
4403               pair->value.u, sizeof (Dwg_GEODATA_meshface));
4404           if (!o->geomesh_faces && o->num_geomesh_faces)
4405             return NULL;
4406           LOG_TRACE ("%s.num_geomesh_faces = %u [BL %d]\n", obj->name,
4407                      pair->value.u, pair->code);
4408           break;
4409         case 13:
4410           i++;
4411 #define CHK_geomesh_pts                                                       \
4412   if (i < 0 || i >= (int)o->num_geomesh_pts || !o->geomesh_pts)               \
4413     return NULL;                                                              \
4414   assert (i >= 0 && i < (int)o->num_geomesh_pts)
4415 
4416           CHK_geomesh_pts;
4417           o->geomesh_pts[i].source_pt.x = pair->value.d;
4418           break;
4419         case 23:
4420           CHK_geomesh_pts;
4421           o->geomesh_pts[i].source_pt.y = pair->value.d;
4422           LOG_TRACE ("%s.geomesh_pts[%d] = (%f, %f) [2RD %d]\n", obj->name, i,
4423                      o->geomesh_pts[i].source_pt.x, pair->value.d, 13);
4424           break;
4425         case 14:
4426           i++;
4427           CHK_geomesh_pts;
4428           o->geomesh_pts[i].dest_pt.x = pair->value.d;
4429           break;
4430         case 24:
4431           CHK_geomesh_pts;
4432           o->geomesh_pts[i].dest_pt.y = pair->value.d;
4433           LOG_TRACE ("%s.geomesh_pts[%d].dest_pt = (%f, %f) [2RD %d]\n",
4434                      obj->name, i, o->geomesh_pts[i].dest_pt.x, pair->value.d,
4435                      13);
4436           break;
4437         case 97:
4438           i++;
4439 #define CHK_geomesh_faces                                                     \
4440   if (i < 0 || i >= (int)o->num_geomesh_faces || !o->geomesh_faces)           \
4441     return NULL;                                                              \
4442   assert (o->geomesh_faces);                                                  \
4443   assert (i >= 0 && i < (int)o->num_geomesh_faces)
4444 
4445           CHK_geomesh_faces;
4446           o->geomesh_faces[i].face1 = pair->value.u;
4447           break;
4448         case 98:
4449           CHK_geomesh_faces;
4450           o->geomesh_faces[i].face2 = pair->value.u;
4451           break;
4452         case 99:
4453           CHK_geomesh_faces;
4454           o->geomesh_faces[i].face3 = pair->value.u;
4455           LOG_TRACE ("%s.geomesh_faces[%d] = (%u, %u, %u) [3*BL %d]\n",
4456                      obj->name, i, o->geomesh_faces[i].face1,
4457                      o->geomesh_faces[i].face2, pair->value.u, 97);
4458           break;
4459         case 0:
4460         default:
4461           return pair;
4462         }
4463       dxf_free_pair (pair);
4464       pair = dxf_read_pair (dat);
4465     }
4466   return pair;
4467 }
4468 #undef CHK_geomesh_pts
4469 #undef CHK_geomesh_faces
4470 
4471 // returns with 0
4472 // subclass for multiple objects.
4473 // Only handle conflicts?, codes with multiple keys.
4474 // 1, 309
4475 static Dxf_Pair *
add_CellStyle(Dwg_Object * restrict obj,Dwg_CellStyle * o,const char * key,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)4476 add_CellStyle (Dwg_Object *restrict obj, Dwg_CellStyle *o, const char *key,
4477                Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
4478 {
4479   Dwg_Data *dwg = obj->parent;
4480   BITCODE_H hdl;
4481   enum
4482   {
4483     NONE,
4484     TABLEFORMAT,
4485     CONTENTFORMAT,
4486     CELLMARGIN,
4487     GRIDFORMAT,
4488     CELLSTYLE
4489   } mode;
4490   int i = -1, j = -1;
4491   int grid = -1;
4492   mode = NONE;
4493 
4494   while (pair != NULL && pair->code != 0)
4495     {
4496       switch (pair->code)
4497         {
4498         case 0:
4499           break;
4500         case 1:
4501           if (strEQc (pair->value.s, "TABLEFORMAT_BEGIN"))
4502             mode = TABLEFORMAT;
4503           else if (strEQc (pair->value.s, "CONTENTFORMAT_BEGIN"))
4504             mode = CONTENTFORMAT;
4505           else if (strEQc (pair->value.s, "CELLMARGIN_BEGIN"))
4506             mode = CELLMARGIN;
4507           else if (strEQc (pair->value.s, "GRIDFORMAT_BEGIN"))
4508             mode = GRIDFORMAT;
4509           else if (strEQc (pair->value.s, "CELLSTYLE_BEGIN"))
4510             {
4511               dxf_free_pair (pair);
4512               return dxf_read_pair (dat);
4513             }
4514           else
4515             goto unknown_default;
4516           break;
4517         case 300:
4518           if (mode == CONTENTFORMAT)
4519             {
4520               if (obj->parent->header.version >= R_2007)
4521                 o->content_format.value_format_string
4522                   = (BITCODE_T)bit_utf8_to_TU (pair->value.s, 0);
4523               else
4524                 o->content_format.value_format_string = strdup (pair->value.s);
4525               LOG_TRACE (
4526                   "%s.%s.content_format.value_format_string = \"%s\" [T %d]\n",
4527                   obj->name, key, pair->value.s, pair->code);
4528             }
4529           else if (mode == TABLEFORMAT)
4530             {
4531               if (!strEQc (pair->value.s, "CONTENTFORMAT"))
4532                 goto unknown_default;
4533             }
4534           else if (mode == CELLSTYLE)
4535             return pair;
4536           else
4537             goto unknown_default;
4538           break;
4539         case 301:
4540           // ignore MARGIN
4541           if (!strEQc (pair->value.s, "MARGIN"))
4542             goto unknown_default;
4543           break;
4544         case 302:
4545           // ignore GRIDFORMAT
4546           if (!strEQc (pair->value.s, "GRIDFORMAT"))
4547             goto unknown_default;
4548           break;
4549         case 309:
4550           if (strEQc (pair->value.s, "TABLEFORMAT_END")
4551               || strEQc (pair->value.s, "CELLSTYLE_END"))
4552             mode = NONE;
4553           else if (strEQc (pair->value.s, "CONTENTFORMAT_END")
4554                    || strEQc (pair->value.s, "CELLMARGIN_END")
4555                    || strEQc (pair->value.s, "GRIDFORMAT_END"))
4556             mode = TABLEFORMAT;
4557           else
4558             goto unknown_default;
4559           break;
4560         case 90:
4561           if (mode == TABLEFORMAT)
4562             {
4563               o->type = pair->value.u;
4564               LOG_TRACE ("%s.%s.type = " FORMAT_BL " [BL %d]\n", obj->name,
4565                          key, pair->value.u, pair->code);
4566             }
4567           else if (mode == CONTENTFORMAT)
4568             {
4569               o->content_format.property_override_flags = pair->value.u;
4570               LOG_TRACE (
4571                   "%s.%s.content_format.property_override_flags = " FORMAT_BLx
4572                   " [BLx %d]\n",
4573                   obj->name, key, pair->value.u, pair->code);
4574             }
4575           else if (mode == GRIDFORMAT)
4576             {
4577               if (grid < 0 || grid >= (int)o->num_borders)
4578                 return NULL;
4579               o->borders[grid].border_overrides = pair->value.u;
4580               LOG_TRACE ("%s.%s.borders[%d].border_overrides = " FORMAT_BLx
4581                          " [BLx %d]\n",
4582                          obj->name, key, grid, pair->value.u, pair->code);
4583             }
4584           else if (mode == CELLSTYLE)
4585             return pair;
4586           else if (mode == NONE)
4587             return pair;
4588           else
4589             goto unknown_default;
4590           break;
4591         case 91:
4592           if (mode == TABLEFORMAT)
4593             {
4594               o->property_override_flags = pair->value.u;
4595               LOG_TRACE ("%s.%s.property_override_flags = " FORMAT_BLx
4596                          " [BLx %d]\n",
4597                          obj->name, key, pair->value.u, pair->code);
4598             }
4599           else if (mode == CONTENTFORMAT)
4600             {
4601               o->content_format.property_flags = pair->value.u;
4602               LOG_TRACE ("%s.%s.content_format.property_flags = " FORMAT_BLx
4603                          " [BLx %d]\n",
4604                          obj->name, key, pair->value.u, pair->code);
4605             }
4606           else if (mode == GRIDFORMAT)
4607             {
4608               if (grid < 0 || grid >= (int)o->num_borders)
4609                 return NULL;
4610               o->borders[grid].border_type = pair->value.u;
4611               LOG_TRACE ("%s.%s.borders[%d].border_type = " FORMAT_BLx
4612                          " [BLx %d]\n",
4613                          obj->name, key, grid, pair->value.u, pair->code);
4614             }
4615           else if (mode == CELLSTYLE)
4616             return pair;
4617           else if (mode == NONE)
4618             return pair;
4619           else
4620             goto unknown_default;
4621           break;
4622         case 92:
4623           if (mode == TABLEFORMAT)
4624             {
4625               o->merge_flags = pair->value.u;
4626               LOG_TRACE ("%s.%s.merge_flags = " FORMAT_BLx " [BLx %d]\n",
4627                          obj->name, key, pair->value.u, pair->code);
4628             }
4629           else if (mode == CONTENTFORMAT)
4630             {
4631               o->content_format.value_data_type = pair->value.u;
4632               LOG_TRACE ("%s.%s.content_format.value_data_type = " FORMAT_BLx
4633                          " [BLx %d]\n",
4634                          obj->name, key, pair->value.u, pair->code);
4635             }
4636           else if (mode == GRIDFORMAT)
4637             {
4638               if (grid < 0 || grid >= (int)o->num_borders)
4639                 return NULL;
4640               o->borders[grid].linewt = pair->value.i;
4641               LOG_TRACE ("%s.%s.borders[%d].linewt = %d [BSd %d]\n", obj->name,
4642                          key, grid, pair->value.i, pair->code);
4643             }
4644           else
4645             goto unknown_default;
4646           break;
4647         case 93:
4648           if (mode == TABLEFORMAT)
4649             {
4650               o->content_layout = pair->value.u;
4651               LOG_TRACE ("%s.%s.content_layout = " FORMAT_BL " [BL %d]\n",
4652                          obj->name, key, pair->value.u, pair->code);
4653             }
4654           else if (mode == CONTENTFORMAT)
4655             {
4656               o->content_format.value_unit_type = pair->value.u;
4657               LOG_TRACE ("%s.%s.content_format.value_unit_type = " FORMAT_BLx
4658                          " [BLx %d]\n",
4659                          obj->name, key, pair->value.u, pair->code);
4660             }
4661           else if (mode == GRIDFORMAT)
4662             {
4663               if (grid < 0 || grid >= (int)o->num_borders)
4664                 return NULL;
4665               o->borders[grid].visible = pair->value.i;
4666               LOG_TRACE ("%s.%s.borders[%d].visible = %d [BL %d]\n", obj->name,
4667                          key, grid, pair->value.i, pair->code);
4668             }
4669           else
4670             goto unknown_default;
4671           break;
4672         case 94:
4673           if (mode == TABLEFORMAT)
4674             {
4675               o->num_borders = pair->value.u;
4676               j = 0;
4677               LOG_TRACE ("%s.%s.num_borders = " FORMAT_BL " [BL %d]\n",
4678                          obj->name, key, pair->value.u, pair->code);
4679               o->borders = (Dwg_GridFormat *)xcalloc (o->num_borders,
4680                                                       sizeof (Dwg_GridFormat));
4681             }
4682           else if (mode == CONTENTFORMAT)
4683             {
4684               o->content_format.cell_alignment = pair->value.u;
4685               LOG_TRACE ("%s.%s.content_format.cell_alignment = " FORMAT_BL
4686                          " [BL %d]\n",
4687                          obj->name, key, pair->value.u, pair->code);
4688             }
4689           else
4690             goto unknown_default;
4691           break;
4692         case 95:
4693           if (mode == TABLEFORMAT)
4694             {
4695               grid++;
4696               if (grid < 0 || grid >= (int)o->num_borders)
4697                 return NULL;
4698               o->borders[grid].index_mask = pair->value.u;
4699               LOG_TRACE ("%s.%s.borders[%d].index_mask = " FORMAT_BLx
4700                          " [BLx %d]\n",
4701                          obj->name, key, grid, pair->value.u, pair->code);
4702             }
4703           else
4704             goto unknown_default;
4705           break;
4706         case 62:
4707           if (mode == TABLEFORMAT)
4708             {
4709               o->bg_color.rgb = pair->value.u;
4710               o->bg_color.method = pair->value.u >> 0x18;
4711               if (pair->value.u == 257)
4712                 {
4713                   o->bg_color.method = 0xc8;
4714                   o->bg_color.rgb = 0xc8000000;
4715                 }
4716               else
4717                 o->bg_color.index = dwg_find_color_index (pair->value.u);
4718               LOG_TRACE ("%s.%s.bg_color = %08x [CMTC %d]\n", obj->name, key,
4719                          pair->value.u, pair->code);
4720             }
4721           else if (mode == CONTENTFORMAT)
4722             {
4723               o->content_format.content_color.rgb = pair->value.u;
4724               o->content_format.content_color.method = pair->value.u >> 0x18;
4725               if (pair->value.u == 257)
4726                 {
4727                   o->content_format.content_color.method = 0xc8;
4728                   o->content_format.content_color.rgb = 0xc8000000;
4729                 }
4730               else
4731                 o->content_format.content_color.index
4732                     = dwg_find_color_index (pair->value.u);
4733               LOG_TRACE (
4734                   "%s.%s.content_format.content_color = %08x [CMTC %d]\n",
4735                   obj->name, key, pair->value.u, pair->code);
4736             }
4737           else if (mode == GRIDFORMAT)
4738             {
4739               if (grid < 0 || grid >= (int)o->num_borders)
4740                 return NULL;
4741               o->borders[grid].color.rgb = pair->value.d;
4742               o->borders[grid].color.method = pair->value.u >> 0x18;
4743               if (pair->value.u == 257)
4744                 {
4745                   o->borders[grid].color.method = 0xc8;
4746                   o->borders[grid].color.rgb = 0xc8000000;
4747                 }
4748               else
4749                 o->borders[grid].color.index
4750                     = dwg_find_color_index (pair->value.u);
4751               LOG_TRACE ("%s.%s.borders[%d].color = %08x [CMTC %d]\n",
4752                          obj->name, key, grid, pair->value.u, pair->code);
4753             }
4754           else
4755             goto unknown_default;
4756           break;
4757         case 40:
4758           if (mode == CELLMARGIN)
4759             {
4760               i++;
4761               switch (i)
4762                 {
4763                 case 0:
4764                   o->vert_margin = pair->value.d;
4765                   LOG_TRACE ("%s.%s.vert_margin = %f [BD %d]\n", obj->name,
4766                              key, pair->value.d, pair->code);
4767                   break;
4768                 case 1:
4769                   o->horiz_margin = pair->value.d;
4770                   LOG_TRACE ("%s.%s.horiz_margin = %f [BD %d]\n", obj->name,
4771                              key, pair->value.d, pair->code);
4772                   break;
4773                 case 2:
4774                   o->bottom_margin = pair->value.d;
4775                   LOG_TRACE ("%s.%s.bottom_margin = %f [BD %d]\n", obj->name,
4776                              key, pair->value.d, pair->code);
4777                   break;
4778                 case 3:
4779                   o->right_margin = pair->value.d;
4780                   LOG_TRACE ("%s.%s.right_margin = %f [BD %d]\n", obj->name,
4781                              key, pair->value.d, pair->code);
4782                   break;
4783                 case 4:
4784                   o->margin_horiz_spacing = pair->value.d;
4785                   LOG_TRACE ("%s.%s.margin_horiz_spacing = %f [BD %d]\n",
4786                              obj->name, key, pair->value.d, pair->code);
4787                   break;
4788                 case 5:
4789                   o->margin_vert_spacing = pair->value.d;
4790                   LOG_TRACE ("%s.%s.margin_vert_spacing = %f [BD %d]\n",
4791                              obj->name, key, pair->value.d, pair->code);
4792                   break;
4793                 default:
4794                   LOG_ERROR ("Invalid CELLMARGIN 40 index %d", i);
4795                   goto unknown_default;
4796                 }
4797             }
4798           else if (mode == CONTENTFORMAT)
4799             {
4800               o->content_format.rotation = pair->value.d;
4801               LOG_TRACE ("%s.%s.content_format.rotation = %f [BD %d]\n",
4802                          obj->name, key, pair->value.d, pair->code);
4803             }
4804           else if (mode == GRIDFORMAT)
4805             {
4806               if (grid < 0 || grid >= (int)o->num_borders)
4807                 return NULL;
4808               o->borders[grid].double_line_spacing = pair->value.d;
4809               LOG_TRACE (
4810                   "%s.%s.borders[%d].double_line_spacing = %f [BD %d]\n",
4811                   obj->name, key, grid, pair->value.d, pair->code);
4812             }
4813           else
4814             goto unknown_default;
4815           break;
4816         case 140:
4817           if (mode == CONTENTFORMAT)
4818             {
4819               o->content_format.block_scale = pair->value.d;
4820               LOG_TRACE ("%s.%s.content_format.block_scale = %f [BD %d]\n",
4821                          obj->name, key, pair->value.d, pair->code);
4822             }
4823           else
4824             goto unknown_default;
4825           break;
4826         case 144:
4827           if (mode == CONTENTFORMAT)
4828             {
4829               o->content_format.text_height = pair->value.d;
4830               LOG_TRACE ("%s.%s.content_format.text_height = %f [BD %d]\n",
4831                          obj->name, key, pair->value.d, pair->code);
4832             }
4833           else
4834             goto unknown_default;
4835           break;
4836         case 170:
4837           if (mode == TABLEFORMAT)
4838             {
4839               o->data_flags = pair->value.u;
4840               LOG_TRACE ("%s.%s.data_flags = " FORMAT_BSx " [BSx %d]\n",
4841                          obj->name, key, pair->value.i, pair->code);
4842             }
4843           else
4844             goto unknown_default;
4845           break;
4846         case 171:
4847           if (mode == TABLEFORMAT)
4848             {
4849               o->margin_override_flags = pair->value.u;
4850               LOG_TRACE ("%s.%s.margin_override_flags = " FORMAT_BSx
4851                          " [BSx %d]\n",
4852                          obj->name, key, pair->value.u, pair->code);
4853             }
4854           else
4855             goto unknown_default;
4856           break;
4857         case 340:
4858           if (mode == CONTENTFORMAT)
4859             {
4860               o->content_format.text_style
4861                   = dwg_add_handleref (dwg, 3, pair->value.u, NULL);
4862               LOG_TRACE ("%s.%s.content_format.text_style = " FORMAT_REF
4863                          " [H 3 %d]\n",
4864                          obj->name, key,
4865                          ARGS_REF (o->content_format.text_style), pair->code);
4866             }
4867           else if (mode == GRIDFORMAT)
4868             {
4869               if (grid < 0 || grid >= (int)o->num_borders)
4870                 return NULL;
4871               o->borders[grid].ltype
4872                   = dwg_add_handleref (dwg, 3, pair->value.u, NULL);
4873               LOG_TRACE ("%s.%s.borders[%d].ltype = " FORMAT_REF " [H 3 %d]\n",
4874                          obj->name, key, grid,
4875                          ARGS_REF (o->borders[grid].ltype), pair->code);
4876             }
4877           else
4878             goto unknown_default;
4879           break;
4880         /*
4881         case 7:
4882           hdl = find_tablehandle (dwg, pair);
4883           assert (hdl);
4884           CHK_array (i, rowstyles);
4885           o->rowstyles[i].text_style = hdl;
4886           LOG_TRACE ("%s.rowstyles[%d].text_style = " FORMAT_REF " [H %d]\n",
4887                        obj->name, i, ARGS_REF(hdl), pair->code);
4888           break;
4889         case 1:
4890           CHK_array (i, rowstyles);
4891           o->rowstyles[i].format_string = bit_utf8_to_TU (pair->value.s, 0);
4892           LOG_TRACE ("%s.rowstyles[%d].format_string = %s [TU %d]\n",
4893                      obj->name, i, pair->value.s, pair->code);
4894           break;
4895         */
4896         default:
4897         unknown_default:
4898           LOG_ERROR ("Unknown DXF code %d for %s.%s", pair->code, obj->name,
4899                      key);
4900         }
4901       dxf_free_pair (pair);
4902       pair = dxf_read_pair (dat);
4903     }
4904   return pair;
4905 }
4906 
4907 // returns with 0
4908 static Dxf_Pair *
add_TABLESTYLE(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)4909 add_TABLESTYLE (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
4910                 Dxf_Pair *restrict pair)
4911 {
4912   Dwg_Data *dwg = obj->parent;
4913   Dwg_Object_TABLESTYLE *o = obj->tio.object->tio.TABLESTYLE;
4914   BITCODE_H hdl;
4915   int i = -1, j = -1;
4916 
4917 #define CHK_rowstyles                                                         \
4918   if (!(i >= 0 && i < 3) || !o->num_rowstyles || !o->rowstyles)               \
4919     return NULL;                                                              \
4920   assert (i >= 0 && i < 3);                                                   \
4921   assert (o->num_rowstyles);                                                  \
4922   assert (o->rowstyles)
4923 
4924 #define CHK_borders                                                           \
4925   if (!(j >= 0 && j <= 6) || !o->rowstyles[i].num_borders                     \
4926       || !o->rowstyles[i].borders)                                            \
4927     return NULL;                                                              \
4928   assert (j >= 0 && j < 6);                                                   \
4929   assert (o->rowstyles[i].num_borders);                                       \
4930   assert (o->rowstyles[i].borders)
4931 
4932   while (pair != NULL && pair->code != 0)
4933     {
4934       switch (pair->code)
4935         {
4936         case 0:
4937           break;
4938         case 7:
4939           i++;
4940           CHK_rowstyles;
4941           hdl = find_tablehandle (dwg, pair);
4942           if (!hdl)
4943             return NULL;
4944           assert (hdl);
4945           o->rowstyles[i].text_style = hdl;
4946           LOG_TRACE ("%s.rowstyles[%d].text_style = " FORMAT_REF " [H %d]\n",
4947                      obj->name, i, ARGS_REF (hdl), pair->code);
4948           break;
4949         case 140:
4950           CHK_rowstyles;
4951           o->rowstyles[i].text_height = pair->value.d;
4952           LOG_TRACE ("%s.rowstyles[%d].text_height = %f [BD %d]\n", obj->name,
4953                      i, pair->value.d, pair->code);
4954           break;
4955         case 170:
4956           CHK_rowstyles;
4957           o->rowstyles[i].text_alignment = pair->value.i;
4958           LOG_TRACE ("%s.rowstyles[%d].text_alignment = " FORMAT_BS
4959                      " [BS %d]\n",
4960                      obj->name, i, o->rowstyles[i].text_alignment, pair->code);
4961           break;
4962         case 62:
4963           CHK_rowstyles;
4964           o->rowstyles[i].text_color.index = pair->value.i;
4965           // TODO rgb with 420
4966           LOG_TRACE ("%s.rowstyles[%d].text_color.index = %d [CMC %d]\n",
4967                      obj->name, i, pair->value.i, pair->code);
4968           break;
4969         case 63:
4970           CHK_rowstyles;
4971           o->rowstyles[i].fill_color.index = pair->value.i;
4972           LOG_TRACE ("%s.rowstyles[%d].fill_color.index = %d [CMC %d]\n",
4973                      obj->name, i, pair->value.i, pair->code);
4974           break;
4975         case 283:
4976           CHK_rowstyles;
4977           o->rowstyles[i].has_bgcolor = pair->value.i;
4978           LOG_TRACE ("%s.rowstyles[%d].has_bgcolor = %d [B %d]\n", obj->name,
4979                      i, pair->value.i, pair->code);
4980           break;
4981         case 90:
4982           CHK_rowstyles;
4983           o->rowstyles[i].data_type = pair->value.i;
4984           LOG_TRACE ("%s.rowstyles[%d].data_type = %d [BL %d]\n", obj->name, i,
4985                      pair->value.i, pair->code);
4986           break;
4987         case 91:
4988           CHK_rowstyles;
4989           o->rowstyles[i].unit_type = pair->value.i;
4990           LOG_TRACE ("%s.rowstyles[%d].unit_type = %d [BL %d]\n", obj->name, i,
4991                      pair->value.i, pair->code);
4992           break;
4993         case 1:
4994           CHK_rowstyles;
4995           o->rowstyles[i].format_string = bit_utf8_to_TU (pair->value.s, 0);
4996           LOG_TRACE ("%s.rowstyles[%d].format_string = %s [TU %d]\n",
4997                      obj->name, i, pair->value.s, pair->code);
4998           break;
4999         case 274:
5000         case 275:
5001         case 276:
5002         case 277:
5003         case 278:
5004         case 279:
5005           CHK_rowstyles;
5006           j = pair->code - 274;
5007           if (j < 0 || j >= 6)
5008             return NULL;
5009           assert (j >= 0 && j <= 6);
5010           if (!o->rowstyles[i].borders)
5011             {
5012               o->rowstyles[i].borders = (Dwg_TABLESTYLE_border *)xcalloc (
5013                   6, sizeof (Dwg_TABLESTYLE_border));
5014               if (!o->rowstyles[i].borders)
5015                 {
5016                   o->rowstyles[i].num_borders = 0;
5017                   return NULL;
5018                 }
5019               o->rowstyles[i].num_borders = 6;
5020             }
5021           CHK_borders;
5022           assert (o->rowstyles[i].num_borders);
5023           o->rowstyles[i].borders[j].linewt = dxf_find_lweight (pair->value.i);
5024           LOG_TRACE ("%s.rowstyles[%d].borders[%d].linewt = %d [BSd %d]\n",
5025                      obj->name, i, j, o->rowstyles[i].borders[j].linewt,
5026                      pair->code);
5027           break;
5028         case 284:
5029         case 285:
5030         case 286:
5031         case 287:
5032         case 288:
5033         case 289:
5034           CHK_rowstyles;
5035           j = pair->code - 284;
5036           CHK_borders;
5037           o->rowstyles[i].borders[j].visible = pair->value.i;
5038           LOG_TRACE ("%s.rowstyles[%d].borders[%d].visible = %d [B %d]\n",
5039                      obj->name, i, j, pair->value.i, pair->code);
5040           break;
5041         case 64:
5042         case 65:
5043         case 66:
5044         case 67:
5045         case 68:
5046         case 69:
5047           CHK_rowstyles;
5048           j = pair->code - 64;
5049           CHK_borders;
5050           assert (j >= 0 && j <= 6);
5051           o->rowstyles[i].borders[j].color.index = pair->value.i;
5052           LOG_TRACE (
5053               "%s.rowstyles[%d].borders[%d].color.index = %d [CMC %d]\n",
5054               obj->name, i, j, pair->value.i, pair->code);
5055           break;
5056         default:
5057           if (is_type_stable (obj->fixedtype))
5058             LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "TABLESTYLE")
5059           else
5060             LOG_WARN ("Unknown DXF code %d for %s", pair->code, "TABLESTYLE");
5061         }
5062       dxf_free_pair (pair);
5063       pair = dxf_read_pair (dat);
5064     }
5065   return pair;
5066 }
5067 
5068 // returns with 0
5069 static Dxf_Pair *
add_TABLEGEOMETRY_Cell(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5070 add_TABLEGEOMETRY_Cell (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5071                         Dxf_Pair *restrict pair)
5072 {
5073   Dwg_Data *dwg = obj->parent;
5074   Dwg_Object_TABLEGEOMETRY *o = obj->tio.object->tio.TABLEGEOMETRY;
5075   BITCODE_H hdl;
5076   BITCODE_BL num_cells = o->num_cells;
5077   int i = -1, j = -1;
5078 
5079   o->cells = (Dwg_TABLEGEOMETRY_Cell *)xcalloc (
5080       num_cells, sizeof (Dwg_TABLEGEOMETRY_Cell));
5081   if (!o->cells)
5082     {
5083       o->num_cells = 0;
5084       return NULL;
5085     }
5086 
5087   while (pair != NULL && pair->code != 0)
5088     {
5089       switch (pair->code)
5090         {
5091         case 0:
5092           break;
5093         case 93:
5094           i++; // the first
5095 #define CHK_cells                                                             \
5096   if (i < 0 || i >= (int)num_cells || !o->cells)                              \
5097     return NULL;                                                              \
5098   assert (i >= 0 && i < (int)num_cells);                                      \
5099   assert (o->cells)
5100 
5101           CHK_cells;
5102           o->cells[i].geom_data_flag = pair->value.i;
5103           LOG_TRACE ("%s.cells[%d].geom_data_flag = " FORMAT_BL " [BL %d]\n",
5104                      obj->name, i, o->cells[i].geom_data_flag, pair->code);
5105           break;
5106         case 40:
5107           CHK_cells;
5108           o->cells[i].width_w_gap = pair->value.d;
5109           LOG_TRACE ("%s.cells[%d].width_w_gap = %f [BD %d]\n", obj->name, i,
5110                      pair->value.d, pair->code);
5111           break;
5112         case 41:
5113           CHK_cells;
5114           o->cells[i].height_w_gap = pair->value.d;
5115           LOG_TRACE ("%s.cells[%d].height_w_gap = %f [BD %d]\n", obj->name, i,
5116                      pair->value.d, pair->code);
5117           break;
5118         case 330:
5119           CHK_cells;
5120           hdl = find_tablehandle (dwg, pair);
5121           if (hdl)
5122             {
5123               if (hdl->handleref.code != 4) // turn the 5 into a 4
5124                 o->cells[i].tablegeometry
5125                     = dwg_add_handleref (dwg, 4, hdl->handleref.value, NULL);
5126               else
5127                 o->cells[i].tablegeometry = hdl;
5128             }
5129           else
5130             o->cells[i].tablegeometry = dwg_add_handleref (dwg, 4, 0, NULL);
5131           LOG_TRACE ("%s.cells[%d].tablegeometry = " FORMAT_REF " [H %d]\n",
5132                      obj->name, i, ARGS_REF (o->cells[i].tablegeometry),
5133                      pair->code);
5134           break;
5135         case 94:
5136           CHK_cells;
5137           o->cells[i].num_geometry = pair->value.i;
5138           LOG_TRACE ("%s.cells[%d].num_geometry = " FORMAT_BL " [BL %d]\n",
5139                      obj->name, i, o->cells[i].num_geometry, pair->code);
5140           o->cells[i].geometry = (Dwg_CellContentGeometry *)xcalloc (
5141               pair->value.i, sizeof (Dwg_CellContentGeometry));
5142           if (!o->cells[i].geometry)
5143             {
5144               o->cells[i].num_geometry = 0;
5145               return NULL;
5146             }
5147           j = -1;
5148           break;
5149         case 10:
5150           CHK_cells;
5151           j++;
5152 
5153 #define CHK_geometry                                                          \
5154   if (j < 0 || j >= (int)o->cells[i].num_geometry || !o->cells[i].geometry)   \
5155     return NULL;                                                              \
5156   assert (j >= 0 && j < (int)o->cells[i].num_geometry);                       \
5157   assert (o->cells[i].geometry)
5158 
5159           CHK_geometry;
5160           o->cells[i].geometry[j].dist_top_left.x = pair->value.d;
5161           LOG_TRACE (
5162               "%s.cells[%d].geometry[%d].dist_top_left.x = %f [BD %d]\n",
5163               obj->name, i, j, pair->value.d, pair->code);
5164           break;
5165         case 20:
5166           CHK_cells;
5167           CHK_geometry;
5168           o->cells[i].geometry[j].dist_top_left.y = pair->value.d;
5169           break;
5170         case 30:
5171           CHK_cells;
5172           CHK_geometry;
5173           o->cells[i].geometry[j].dist_top_left.z = pair->value.d;
5174           LOG_TRACE ("%s.cells[%d].geometry[%d].dist_top_left = ( %f, %f, %f) "
5175                      "[3BD 10]\n",
5176                      obj->name, i, j, o->cells[i].geometry[j].dist_top_left.x,
5177                      o->cells[i].geometry[j].dist_top_left.y, pair->value.d);
5178           break;
5179         case 11:
5180           CHK_cells;
5181           CHK_geometry;
5182           o->cells[i].geometry[j].dist_center.x = pair->value.d;
5183           LOG_TRACE ("%s.cells[%d].geometry[%d].dist_center.x = %f [BD %d]\n",
5184                      obj->name, i, j, pair->value.d, pair->code);
5185           break;
5186         case 21:
5187           CHK_cells;
5188           CHK_geometry;
5189           o->cells[i].geometry[j].dist_center.y = pair->value.d;
5190           break;
5191         case 31:
5192           CHK_cells;
5193           CHK_geometry;
5194           o->cells[i].geometry[j].dist_center.z = pair->value.d;
5195           LOG_TRACE ("%s.cells[%d].geometry[%d].dist_center = ( %f, %f, %f) "
5196                      "[3BD 10]\n",
5197                      obj->name, i, j, o->cells[i].geometry[j].dist_center.x,
5198                      o->cells[i].geometry[j].dist_center.y, pair->value.d);
5199           break;
5200         case 43:
5201           CHK_cells;
5202           CHK_geometry;
5203           o->cells[i].geometry[j].content_width = pair->value.d;
5204           LOG_TRACE ("%s.cells[%d].geometry[%d].content_width = %f [BD %d]\n",
5205                      obj->name, i, j, pair->value.d, pair->code);
5206           break;
5207         case 44:
5208           CHK_cells;
5209           CHK_geometry;
5210           o->cells[i].geometry[j].content_height = pair->value.d;
5211           LOG_TRACE ("%s.cells[%d].geometry[%d].content_height = %f [BD %d]\n",
5212                      obj->name, i, j, pair->value.d, pair->code);
5213           break;
5214         case 45:
5215           CHK_cells;
5216           CHK_geometry;
5217           o->cells[i].geometry[j].width = pair->value.d;
5218           LOG_TRACE ("%s.cells[%d].geometry[%d].width = %f [BD %d]\n",
5219                      obj->name, i, j, pair->value.d, pair->code);
5220           break;
5221         case 46:
5222           CHK_cells;
5223           CHK_geometry;
5224           o->cells[i].geometry[j].height = pair->value.d;
5225           LOG_TRACE ("%s.cells[%d].geometry[%d].height = %f [BD %d]\n",
5226                      obj->name, i, j, pair->value.d, pair->code);
5227           break;
5228         case 95:
5229           CHK_cells;
5230           CHK_geometry;
5231           o->cells[i].geometry[j].unknown = pair->value.i;
5232           LOG_TRACE ("%s.cells[%d].geometry[%d].unknown = %d [BL %d]\n",
5233                      obj->name, i, j, pair->value.i, pair->code);
5234           break;
5235         default:
5236           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "TABLESTYLE");
5237         }
5238       dxf_free_pair (pair);
5239       pair = dxf_read_pair (dat);
5240     }
5241   return pair;
5242 }
5243 
5244 #undef CHK_cells
5245 #undef CHK_geometry
5246 
5247 // starts with 71 or 75
5248 static Dxf_Pair *
add_DIMASSOC(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5249 add_DIMASSOC (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5250               Dxf_Pair *restrict pair)
5251 {
5252   Dwg_Object_DIMASSOC *o = obj->tio.object->tio.DIMASSOC;
5253   Dwg_Data *dwg = obj->parent;
5254   int i = -1, j = -1;
5255   int have_rotated_type = 0;
5256   o->ref = (Dwg_DIMASSOC_Ref *)xcalloc (4, sizeof (Dwg_DIMASSOC_Ref));
5257   if (!o->ref)
5258     {
5259       return NULL;
5260     }
5261 
5262   while (pair != NULL && pair->code != 0)
5263     {
5264       switch (pair->code)
5265         {
5266         case 0:
5267           break;
5268         case 71: // always before each ref
5269           i++;
5270           while (!(o->associativity & (1 << i)) && i < 4) // popcount x
5271             i++;
5272           if (!(i >= 0 && i <= 3))
5273             {
5274               LOG_ERROR ("Invalid DIMASSOC_Ref index %d", i)
5275               return pair;
5276             }
5277           o->rotated_type = pair->value.i;
5278           have_rotated_type = 1; // early bump
5279           LOG_TRACE ("%s.rotated_type = %d [BS %d]\n", obj->name,
5280                      pair->value.i, pair->code);
5281           break;
5282         case 1:
5283           if (strNE (pair->value.s, "AcDbOsnapPointRef"))
5284             {
5285               LOG_ERROR ("Invalid DIMASSOC subclass %s", pair->value.s);
5286               return pair;
5287             }
5288           if (!(i >= 0 && i <= 3))
5289             {
5290               LOG_ERROR ("Invalid DIMASSOC_Ref index %d", i)
5291               return pair;
5292             }
5293           if (!have_rotated_type) // not already bumped
5294             {
5295               i++;
5296               while (!(o->associativity & (1 << i)) && i < 4) // popcount x
5297                 i++;
5298               if (i > 3)
5299                 i = 3;
5300               assert (i >= 0 && i <= 3);
5301             }
5302           o->ref[i].classname = dwg_add_u8_input (dwg, pair->value.s);
5303           LOG_TRACE ("%s.ref[%d].classname = %s [T %d]\n", obj->name, i,
5304                      pair->value.s, pair->code);
5305           have_rotated_type = 0;
5306           break;
5307         case 72:
5308           if (i < 0 || i > 3)
5309             break;
5310           o->ref[i].osnap_type = pair->value.i;
5311           LOG_TRACE ("%s.ref[%d].osnap_type = %d [RC %d]\n", obj->name, i,
5312                      pair->value.i, pair->code);
5313           break;
5314         // FIXME: 301 xrefpaths[j]
5315         case 331:
5316           {
5317             BITCODE_BS n;
5318             if (i < 0 || i > 3)
5319               break;
5320             n = o->ref[i].num_xrefs;
5321             o->ref[i].xrefs = (BITCODE_H *)realloc (
5322                 o->ref[i].xrefs, (n + 1) * sizeof (BITCODE_H));
5323             o->ref[i].xrefs[n]
5324                 = dwg_add_handleref (dwg, 5, pair->value.u, obj);
5325             LOG_TRACE ("%s.ref[%d].xrefs[%d] = " FORMAT_REF " [H* %d]\n",
5326                        obj->name, i, n, ARGS_REF (o->ref[i].xrefs[n]),
5327                        pair->code);
5328             o->ref[i].num_xrefs++;
5329           }
5330           break;
5331         case 74:
5332           if (i < 0 || i > 3)
5333             break;
5334           o->ref[i].num_intsectobj = pair->value.i;
5335           o->ref[i].intsectobj
5336               = (BITCODE_H *)xcalloc (pair->value.i, sizeof (BITCODE_H));
5337           j = 0;
5338           LOG_TRACE ("%s.ref[%d].num_intsectobj = %d [BS %d]\n", obj->name, i,
5339                      pair->value.i, pair->code);
5340           break;
5341         case 332:
5342           if (i < 0 || j < 0 || i > 3 || j >= (int)o->ref[i].num_intsectobj)
5343             break;
5344           o->ref[i].intsectobj[j]
5345               = dwg_add_handleref (dwg, 5, pair->value.u, obj);
5346           LOG_TRACE ("%s.ref[%d].intsectobj[%d] = " FORMAT_REF " [H %d]\n",
5347                      obj->name, i, j, ARGS_REF (o->ref[i].intsectobj[j]),
5348                      pair->code);
5349           j++;
5350           break;
5351         case 73:
5352           if (i < 0)
5353             break;
5354           o->ref[i].main_subent_type = pair->value.i;
5355           LOG_TRACE ("%s.ref[%d].main_subent_type = %d [BS %d]\n", obj->name,
5356                      i, pair->value.i, pair->code);
5357           break;
5358         case 75:
5359           if (i < 0)
5360             break;
5361           o->ref[i].has_lastpt_ref = pair->value.i;
5362           LOG_TRACE ("%s.ref[%d].has_lastpt_ref = %d [B %d]\n", obj->name, i,
5363                      pair->value.i, pair->code);
5364           break;
5365         case 91:
5366           if (i < 0)
5367             break;
5368           o->ref[i].main_gsmarker = pair->value.i;
5369           LOG_TRACE ("%s.ref[%d].main_gsmarker = %d [BL %d]\n", obj->name, i,
5370                      pair->value.i, pair->code);
5371           break;
5372         case 40:
5373           if (i < 0)
5374             break;
5375           o->ref[i].osnap_dist = pair->value.d;
5376           LOG_TRACE ("%s.ref[%d].osnap_dist = %f [BD %d]\n", obj->name, i,
5377                      pair->value.d, pair->code);
5378           break;
5379         case 10:
5380           if (i < 0)
5381             break;
5382           o->ref[i].osnap_pt.x = pair->value.d;
5383           break;
5384         case 20:
5385           if (i < 0)
5386             break;
5387           o->ref[i].osnap_pt.y = pair->value.d;
5388           break;
5389         case 30:
5390           if (i < 0)
5391             break;
5392           o->ref[i].osnap_pt.z = pair->value.d;
5393           LOG_TRACE ("%s.ref[%d].osnap_pt = (%f, %f, %f) [3BD 10]\n",
5394                      obj->name, i, o->ref[i].osnap_pt.x, o->ref[i].osnap_pt.y,
5395                      pair->value.d);
5396           break;
5397         default:
5398           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "DIMASSOC");
5399         }
5400       dxf_free_pair (pair);
5401       pair = dxf_read_pair (dat);
5402     }
5403   return pair;
5404 }
5405 
5406 // starting with 90 or 8
5407 static Dxf_Pair *
add_LAYER_entry(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5408 add_LAYER_entry (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5409                  Dxf_Pair *restrict pair)
5410 {
5411   Dwg_Object_LAYER_INDEX *o = obj->tio.object->tio.LAYER_INDEX;
5412   Dwg_Data *dwg = obj->parent;
5413   int i = 0;
5414   o->entries = (Dwg_LAYER_entry *)xcalloc (1, sizeof (Dwg_LAYER_entry));
5415   o->num_entries = 1;
5416   if (!o->entries)
5417     {
5418       return NULL;
5419     }
5420   if (pair->code == 90 && !pair->value.i)
5421     {
5422       LOG_TRACE ("skip first %s.entries[%d].numlayers = %d [BL %d]\n",
5423                  obj->name, i, pair->value.i, pair->code);
5424       dxf_free_pair (pair);
5425       pair = dxf_read_pair (dat);
5426     }
5427   while (pair != NULL && pair->code != 0)
5428     {
5429       switch (pair->code)
5430         {
5431         case 0:
5432           break;
5433         case 8:
5434           o->entries[i].name = dwg_add_u8_input (dwg, pair->value.s);
5435           LOG_TRACE ("%s.entries[%d].name = %s [T %d]\n", obj->name, i,
5436                      pair->value.s, pair->code);
5437           break;
5438         case 360:
5439           o->entries[i].handle
5440               = dwg_add_handleref (dwg, 5, pair->value.u, obj);
5441           LOG_TRACE ("%s.entries[%d].handle = " FORMAT_REF " [H %d]\n",
5442                      obj->name, i, ARGS_REF (o->entries[i].handle),
5443                      pair->code);
5444           break;
5445         case 90:
5446           o->entries[i].numlayers = pair->value.i;
5447           LOG_TRACE ("%s.entries[%d].numlayers = %d [BL %d]\n", obj->name, i,
5448                      pair->value.i, pair->code);
5449           o->num_entries++;
5450           i++;
5451           o->entries = (Dwg_LAYER_entry *)realloc (
5452               o->entries, o->num_entries * sizeof (Dwg_LAYER_entry));
5453           if (!o->entries)
5454             return NULL;
5455           break;
5456         default:
5457           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, "LAYER_INDEX");
5458           return NULL;
5459         }
5460       dxf_free_pair (pair);
5461       pair = dxf_read_pair (dat);
5462     }
5463   o->num_entries--;
5464   LOG_TRACE ("%s.num_entries = %d [BL]\n", obj->name, o->num_entries);
5465   return pair;
5466 }
5467 
5468 static Dxf_Pair *
add_EVALVARIANT(Dwg_Data * restrict dwg,Bit_Chain * restrict dat,Dwg_EvalVariant * value)5469 add_EVALVARIANT (Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
5470                  Dwg_EvalVariant *value)
5471 {
5472   Dxf_Pair *pair = dxf_read_pair (dat);
5473   EXPECT_DXF ("EvalVariant", code, 70);
5474   value->code = pair->value.i;
5475   LOG_TRACE ("%s.%s = %d [BL %d]\n", "EvalVariant", "code", pair->value.i,
5476              pair->code);
5477   dxf_free_pair (pair);
5478 
5479   pair = dxf_read_pair (dat);
5480   if (!pair || pair->code == 0)
5481     return pair;
5482   switch (dwg_resbuf_value_type (pair->value.i))
5483     {
5484     case DWG_VT_REAL:
5485       value->u.bd = pair->value.d;
5486       LOG_TRACE ("%s.%s = %f [BD %d]\n", "EvalVariant", "value", pair->value.d,
5487                  pair->code);
5488       break;
5489     case DWG_VT_INT32:
5490       value->u.bl = pair->value.u;
5491       LOG_TRACE ("%s.%s = %u [BL %d]\n", "EvalVariant", "value", pair->value.u,
5492                  pair->code);
5493       break;
5494     case DWG_VT_INT16:
5495       value->u.bs = pair->value.i;
5496       LOG_TRACE ("%s.%s = %d [BS %d]\n", "EvalVariant", "value", pair->value.i,
5497                  pair->code);
5498       break;
5499     case DWG_VT_INT8:
5500       value->u.rc = pair->value.i;
5501       LOG_TRACE ("%s.%s = %d [RC %d]\n", "EvalVariant", "value", pair->value.i,
5502                  pair->code);
5503       break;
5504     case DWG_VT_STRING:
5505       value->u.text = dwg_add_u8_input (dwg, pair->value.s);
5506       LOG_TRACE ("%s.%s = %s [T %d]\n", "EvalVariant", "value", pair->value.s,
5507                  pair->code);
5508       break;
5509     case DWG_VT_HANDLE:
5510       value->u.handle = dwg_add_handleref (dwg, 5, pair->value.u, NULL);
5511       LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n", "EvalVariant", "value",
5512                  ARGS_REF (value->u.handle), pair->code);
5513       break;
5514     case DWG_VT_BINARY:
5515     case DWG_VT_OBJECTID:
5516     case DWG_VT_POINT3D:
5517     case DWG_VT_INVALID:
5518     case DWG_VT_INT64:
5519     case DWG_VT_BOOL:
5520     default:
5521       LOG_ERROR ("Invalid EvalVariant.value.type %d", pair->code)
5522       break;
5523     }
5524   dxf_free_pair (pair);
5525   return NULL;
5526 }
5527 
5528 static int
add_VALUEPARAMs(Dwg_Data * restrict dwg,Bit_Chain * restrict dat,Dwg_VALUEPARAM * value)5529 add_VALUEPARAMs (Dwg_Data *restrict dwg, Bit_Chain *restrict dat,
5530                  Dwg_VALUEPARAM *value)
5531 {
5532   Dxf_Pair *pair = dxf_read_pair (dat);
5533   if (pair == NULL || pair->code != 90)
5534     {
5535       LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5536                  "VALUEPARAM", pair ? pair->code : -1, 90, "class_version");
5537       return 0;
5538     }
5539   value->class_version = pair->value.u;
5540   LOG_TRACE ("%s.%s = %d [BL %d]\n", "VALUEPARAM", "class_version",
5541              pair->value.i, pair->code);
5542   dxf_free_pair (pair);
5543 
5544   pair = dxf_read_pair (dat);
5545   if (pair == NULL || pair->code != 1)
5546     {
5547       LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5548                  "VALUEPARAM", pair ? pair->code : -1, 1, "name");
5549       return 0;
5550     }
5551   value->name = dwg_add_u8_input (dwg, pair->value.s);
5552   LOG_TRACE ("%s.%s = %s [BL %d]\n", "VALUEPARAM", "name", pair->value.s,
5553              pair->code);
5554   dxf_free_pair (pair);
5555 
5556   pair = dxf_read_pair (dat);
5557   if (pair == NULL || pair->code != 90)
5558     {
5559       LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5560                  "VALUEPARAM", pair ? pair->code : -1, 90, "unit_type");
5561       return 0;
5562     }
5563   value->unit_type = pair->value.u;
5564   LOG_TRACE ("%s.%s = %d [BL %d]\n", "VALUEPARAM", "unit_type", pair->value.i,
5565              pair->code);
5566   dxf_free_pair (pair);
5567 
5568   pair = dxf_read_pair (dat);
5569   if (pair == NULL || pair->code != 90)
5570     {
5571       LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5572                  "VALUEPARAM", pair ? pair->code : -1, 90, "num_vars");
5573       return 0;
5574     }
5575   value->num_vars = pair->value.u;
5576   LOG_TRACE ("%s.%s = %d [BL %d]\n", "VALUEPARAM", "num_vars", pair->value.i,
5577              pair->code);
5578   value->vars = (Dwg_VALUEPARAM_vars*)xcalloc (value->num_vars,
5579                                                sizeof (Dwg_VALUEPARAM_vars));
5580   if (!value->vars)
5581     return 0;
5582   for (unsigned j = 0; j < value->num_vars; j++)
5583     {
5584       pair = add_EVALVARIANT (dwg, dat, &value->vars[j].value);
5585       if (pair)
5586         return 0;
5587       pair = dxf_read_pair (dat);
5588       if (pair == NULL || pair->code != 330)
5589         {
5590           LOG_ERROR ("%s: Unexpected DXF code %d, expected %d for %s",
5591                      "VALUEPARAM", pair ? pair->code : -1, 330, "handle");
5592           return 0;
5593         }
5594       value->vars[j].handle = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
5595       LOG_TRACE ("%s.vars[%u].handle = " FORMAT_REF " [H %d]\n", "VALUEPARAM",
5596                  j, ARGS_REF (value->vars[j].handle), pair->code);
5597       dxf_free_pair (pair);
5598     }
5599   return 1;
5600 }
5601 
5602 static Dxf_Pair *
add_EVAL_Edge(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5603 add_EVAL_Edge (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5604                Dxf_Pair *restrict pair)
5605 {
5606   Dwg_Object_EVALUATION_GRAPH *o = obj->tio.object->tio.EVALUATION_GRAPH;
5607   Dwg_Data *dwg = obj->parent;
5608   int i = -1;
5609   o->edges = (Dwg_EVAL_Edge *)xcalloc (1, sizeof (Dwg_EVAL_Edge));
5610   o->num_edges = 0;
5611   if (!o->edges)
5612     return NULL;
5613 
5614   while (pair != NULL && pair->code == 92)
5615     {
5616       i++;
5617       o->edges = (Dwg_EVAL_Edge *)realloc (o->edges, o->num_edges * sizeof (Dwg_EVAL_Edge));
5618       if (!o->edges)
5619         return NULL;
5620       o->num_edges++;
5621       o->edges[i].id = pair->value.i; // 92
5622       LOG_TRACE ("%s.edges[%d].id = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5623       dxf_free_pair (pair);
5624 
5625       pair = dxf_read_pair (dat);
5626       if (!pair || pair->code != 93)
5627         {
5628           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5629           return pair;
5630         }
5631       o->edges[i].nextid = pair->value.i; // 93
5632       LOG_TRACE ("%s.edges[%d].nextid = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5633       dxf_free_pair (pair);
5634 
5635       pair = dxf_read_pair (dat);
5636       if (!pair || pair->code != 94)
5637         {
5638           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5639           return pair;
5640         }
5641       o->edges[i].e1 = pair->value.i; // 94
5642       LOG_TRACE ("%s.edges[%d].e1 = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5643       dxf_free_pair (pair);
5644 
5645       pair = dxf_read_pair (dat);
5646       if (!pair || pair->code != 91)
5647         {
5648           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5649           return pair;
5650         }
5651       o->edges[i].e2 = pair->value.i; // 91
5652       LOG_TRACE ("%s.edges[%d].e2 = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5653       dxf_free_pair (pair);
5654 
5655       pair = dxf_read_pair (dat);
5656       if (!pair || pair->code != 91)
5657         {
5658           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5659           return pair;
5660         }
5661       o->edges[i].e3 = pair->value.i; // 91
5662       LOG_TRACE ("%s.edges[%d].e3 = %d [BL %d]\n", obj->name, i, pair->value.i, pair->code);
5663       dxf_free_pair (pair);
5664 
5665       for (int j = 0; j < 5; j++)
5666         {
5667           pair = dxf_read_pair (dat);
5668           if (!pair || pair->code != 92)
5669             {
5670               LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5671               return pair;
5672             }
5673           o->edges[i].out_edge[j] = pair->value.i; // 92
5674           LOG_TRACE ("%s.edges[%d].out_edge[%d] = %d [BL %d]\n", obj->name, i, j, pair->value.i, pair->code);
5675           dxf_free_pair (pair);
5676         }
5677 
5678       pair = dxf_read_pair (dat);
5679     }
5680   LOG_TRACE ("%s.num_edges = %d [BL]\n", obj->name, o->num_edges);
5681   return pair;
5682 }
5683 
5684 /* Starts with first AcDbEvalGraph 91. FIXME edges */
5685 static Dxf_Pair *
add_EVAL_Node(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5686 add_EVAL_Node (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5687                Dxf_Pair *restrict pair)
5688 {
5689   Dwg_Object_EVALUATION_GRAPH *o = obj->tio.object->tio.EVALUATION_GRAPH;
5690   Dwg_Data *dwg = obj->parent;
5691   int i = -1, j = 0;
5692   o->nodes = (Dwg_EVAL_Node *)xcalloc (1, sizeof (Dwg_EVAL_Node));
5693   o->num_nodes = 1;
5694   if (!o->nodes)
5695     {
5696       return NULL;
5697     }
5698   while (pair != NULL && pair->code != 0)
5699     {
5700       switch (pair->code)
5701         {
5702         case 91:
5703           i++;
5704           o->nodes = (Dwg_EVAL_Node *)realloc (o->nodes, (i + 1) * sizeof (Dwg_EVAL_Node));
5705           if (!o->nodes)
5706             break;
5707           o->num_nodes = i + 1;
5708           o->nodes[i].id = pair->value.i;
5709           LOG_TRACE ("%s.nodes[%d].id = %d [BL %d]\n", obj->name, i,
5710                      pair->value.i, pair->code);
5711           break;
5712         case 93: // must be 32
5713           o->nodes[i].edge_flags = pair->value.i;
5714           LOG_TRACE ("%s.nodes[%d].edge_flags = %d [BL %d]\n", obj->name, i,
5715                      pair->value.i, pair->code);
5716           break;
5717         case 95:
5718           o->nodes[i].edge_flags = pair->value.i;
5719           if (pair->value.i != 32)
5720             LOG_WARN ("%s.nodes[%d].edge_flags = %d [BL %d] != 32\n", obj->name, i,
5721                        pair->value.i, pair->code)
5722           else
5723             LOG_TRACE ("%s.nodes[%d].edge_flags = %d [BL %d]\n", obj->name, i,
5724                        pair->value.i, pair->code)
5725           break;
5726         case 360:
5727           o->nodes[i].evalexpr
5728               = dwg_add_handleref (dwg, 5, pair->value.u, obj);
5729           LOG_TRACE ("%s.nodes[%d].evalexpr = " FORMAT_REF " [H %d]\n",
5730                      obj->name, i, ARGS_REF (o->nodes[i].evalexpr),
5731                      pair->code);
5732           break;
5733         case 92:
5734           if (j > 3) // 0 - 3
5735             { // list of edges
5736               return add_EVAL_Edge (obj, dat, pair);
5737             }
5738           o->nodes[i].node[j] = pair->value.i;
5739           LOG_TRACE ("%s.nodes[%d].edge[%d] = %d [BL %d]\n", obj->name, i, j,
5740                      pair->value.i, pair->code);
5741           j++;
5742           break;
5743         default:
5744           LOG_ERROR ("Unknown DXF code %d for %s", pair->code, obj->name);
5745           return NULL;
5746         }
5747       dxf_free_pair (pair);
5748       pair = dxf_read_pair (dat);
5749     }
5750   LOG_TRACE ("%s.num_nodes = %d [BL]\n", obj->name, o->num_nodes);
5751   return pair;
5752 }
5753 
5754 static Dxf_Pair *
add_ASSOCNETWORK(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5755 add_ASSOCNETWORK (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5756                   Dxf_Pair *restrict pair)
5757 {
5758   Dwg_Object_ASSOCNETWORK *o = obj->tio.object->tio.ASSOCNETWORK;
5759   Dwg_Data *dwg = obj->parent;
5760   BITCODE_BL num;
5761   BITCODE_H *hv = NULL;
5762   Dwg_ASSOCACTION_Deps *deps;
5763 
5764   if (pair == NULL || pair->code != 90)
5765     return pair;
5766   EXPECT_INT_DXF ("network_version", 90, BS);
5767   FIELD_BL (network_action_index, 90);
5768   FIELD_BL (num_actions, 90);
5769   num = o->num_actions;
5770 
5771   deps = (Dwg_ASSOCACTION_Deps*)xcalloc (num, sizeof (Dwg_ASSOCACTION_Deps));
5772   if (!deps)
5773     return NULL;
5774   for (unsigned i = 0; i < num; i++)
5775     {
5776       BITCODE_H hdl;
5777       int is_owned, code;
5778       pair = dxf_read_pair (dat);
5779       if (pair && (pair->code == 360 || pair->code == 330))
5780         deps[i].is_owned = pair->code == 360;
5781       else
5782         {
5783           LOG_ERROR ("Invalid ASSOCACTION.deps[%d].is_owned DXF code %d", i,
5784                      pair ? pair->code : 0);
5785           return NULL;
5786         }
5787       code = deps[i].is_owned ? DWG_HDL_HARDOWN : DWG_HDL_SOFTPTR;
5788       deps[i].dep = dwg_add_handleref (dwg, code, pair->value.u, obj);
5789       LOG_TRACE ("%s.%s[%u] = " FORMAT_REF " [H %d]\n", obj->name, "deps", i,
5790                  ARGS_REF (deps[i].dep), pair->code);
5791       dxf_free_pair (pair);
5792     }
5793   dwg_dynapi_entity_set_value (o, obj->name, "actions", &deps, 1);
5794 
5795   pair = dxf_read_pair (dat);
5796   num = pair ? pair->value.u : 0;
5797   EXPECT_INT_DXF ("num_owned_actions", 90, BL);
5798   if (num)
5799     {
5800       hv = (BITCODE_H*)xcalloc (num, sizeof (BITCODE_H));
5801       if (!hv)
5802         return NULL;
5803     }
5804   for (unsigned i = 0; i < num; i++)
5805     {
5806       BITCODE_H hdl;
5807       pair = dxf_read_pair (dat);
5808       if (!pair || pair->code != 330)
5809         {
5810           LOG_ERROR ("Invalid ASSOCNETWORK.owned_actions[%d] DXF code %d", i,
5811                      pair ? pair->code : 0);
5812           return NULL;
5813         }
5814       hdl = dwg_add_handleref (dwg, 3, pair->value.u, obj);
5815       LOG_TRACE ("%s.%s[%d] = " FORMAT_REF " [H %d]\n", obj->name,
5816                  "owned_actions", i, ARGS_REF (hdl), pair->code);
5817       hv[i] = hdl;
5818       dxf_free_pair (pair);
5819     }
5820   if (num)
5821     dwg_dynapi_entity_set_value (o, obj->name, "owned_actions", &hv, 1);
5822   return NULL;
5823 }
5824 
5825 // with ASSOC2DCONSTRAINTGROUP, ASSOCNETWORK, ASSOCACTION
5826 static Dxf_Pair *
add_ASSOCACTION(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)5827 add_ASSOCACTION (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
5828                  Dxf_Pair *restrict pair)
5829 {
5830   Dwg_Object_ASSOCACTION *o = obj->tio.object->tio.ASSOCACTION;
5831   Dwg_Data *dwg = obj->parent;
5832   BITCODE_BL num;
5833   BITCODE_H *hv = NULL;
5834   Dwg_VALUEPARAM *values = NULL;
5835   Dwg_ASSOCACTION_Deps *deps;
5836   unsigned class_version;
5837 
5838   if (pair == NULL || pair->code != 90)
5839     return pair;
5840   class_version = pair->value.u;
5841   EXPECT_INT_DXF ("class_version", 90, BS);
5842   FIELD_BL (geometry_status, 90);
5843   FIELD_HANDLE (owningnetwork, 4, 330);
5844   FIELD_HANDLE (actionbody, 3, 360);
5845   FIELD_BL (action_index, 90);
5846   FIELD_BL (max_assoc_dep_index, 90);
5847 
5848   FIELD_BL (num_deps, 90);
5849   num = o->num_deps;
5850   deps = (Dwg_ASSOCACTION_Deps*)xcalloc (num, sizeof (Dwg_ASSOCACTION_Deps));
5851   if (!deps)
5852     return NULL;
5853   for (unsigned i = 0; i < num; i++)
5854     {
5855       BITCODE_H hdl;
5856       int is_owned, code;
5857       pair = dxf_read_pair (dat);
5858       if (pair && (pair->code == 360 || pair->code == 330))
5859         deps[i].is_owned = pair->code == 360;
5860       else
5861         {
5862           LOG_ERROR ("Invalid ASSOCACTION.deps[%d].is_owned DXF code %d", i,
5863                      pair ? pair->code : 0);
5864           return NULL;
5865         }
5866       code = deps[i].is_owned ? DWG_HDL_HARDOWN : DWG_HDL_SOFTPTR;
5867       deps[i].dep = dwg_add_handleref (dwg, code, pair->value.u, obj);
5868       LOG_TRACE ("%s.%s[%u] = " FORMAT_REF " [H %d]\n", obj->name, "deps", i,
5869                  ARGS_REF (deps[i].dep), pair->code);
5870       dxf_free_pair (pair);
5871     }
5872   dwg_dynapi_entity_set_value (o, obj->name, "deps", &deps, 1);
5873 
5874   if (class_version > 1)
5875     {
5876       pair = dxf_read_pair (dat);
5877       num = pair ? pair->value.u : 0;
5878       EXPECT_INT_DXF ("num_owned_params", 90, BL);
5879       if (num)
5880         {
5881           hv = (BITCODE_H *)xcalloc (num, sizeof (BITCODE_H));
5882           if (!hv)
5883             return NULL;
5884         }
5885       for (unsigned i = 0; i < num; i++)
5886         {
5887           BITCODE_H hdl;
5888           pair = dxf_read_pair (dat);
5889           if (!pair || pair->type != DWG_VT_HANDLE)
5890             {
5891               LOG_ERROR ("Invalid ASSOCACTION.owned_params[%d] DXF code %d", i,
5892                          pair ? pair->code : 0);
5893               return NULL;
5894             }
5895           hdl = dwg_add_handleref (dwg, 3, pair->value.u, obj);
5896           LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n", obj->name,
5897                      "owned_params", ARGS_REF (hdl), pair->code);
5898           hv[i] = hdl;
5899           dxf_free_pair (pair);
5900         }
5901       if (num)
5902         dwg_dynapi_entity_set_value (o, obj->name, "owned_params", &hv, 1);
5903 
5904       pair = dxf_read_pair (dat);
5905       if (pair == NULL || pair->code != 90)
5906         return pair;
5907       // ignore the ValueParams class_version
5908       dxf_free_pair (pair);
5909 
5910       pair = dxf_read_pair (dat);
5911       num = pair ? pair->value.u : 0;
5912       EXPECT_INT_DXF ("num_values", 90, BL);
5913       if (num)
5914         {
5915           values = (Dwg_VALUEPARAM *)xcalloc (num, sizeof (Dwg_VALUEPARAM *));
5916           if (!values)
5917             return NULL;
5918         }
5919       for (unsigned i = 0; i < num; i++)
5920         {
5921           Dwg_VALUEPARAM *value
5922               = (Dwg_VALUEPARAM *)xcalloc (1, sizeof (Dwg_VALUEPARAM));
5923           int success = add_VALUEPARAMs (dwg, dat, value);
5924           values[i] = *value;
5925           if (!success)
5926             return NULL;
5927         }
5928       if (num)
5929         dwg_dynapi_entity_set_value (o, obj->name, "values", &values, 1);
5930     }
5931 
5932   return NULL;
5933 }
5934 
5935 static Dxf_Pair *
add_RENDERENVIRONMENT(Dwg_Object * restrict obj,Bit_Chain * restrict dat)5936 add_RENDERENVIRONMENT (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
5937 {
5938   Dwg_Object_RENDERENVIRONMENT *o = obj->tio.object->tio.RENDERENVIRONMENT;
5939   Dwg_Data *dwg = obj->parent;
5940   Dxf_Pair *pair;
5941   BITCODE_RC r, g, b;
5942 
5943   FIELD_BL (class_version, 90);
5944   FIELD_B (fog_enabled, 290);
5945   FIELD_B (fog_background_enabled, 290);
5946 
5947   pair = dxf_read_pair (dat);
5948   EXPECT_DXF (obj->name, fog_color, 280);
5949   r = pair->value.u & 0xff;
5950   dxf_free_pair (pair);
5951 
5952   pair = dxf_read_pair (dat);
5953   EXPECT_DXF (obj->name, fog_color, 280);
5954   g = pair->value.u & 0xff;
5955   dxf_free_pair (pair);
5956 
5957   pair = dxf_read_pair (dat);
5958   EXPECT_DXF (obj->name, fog_color, 280);
5959   b = pair->value.u & 0xff;
5960   dxf_free_pair (pair);
5961 
5962   o->fog_color.method = 0xc3;
5963   o->fog_color.rgb = 0xc3000000 | r << 16 | g << 8 | b;
5964   LOG_TRACE ("%s.fog_color.rgb = 0x%x [3x RC 280]\n", obj->name, o->fog_color.rgb)
5965 
5966   FIELD_BD (fog_density_near, 40); /* default 100.0 (opaque fog) */
5967   FIELD_BD (fog_density_far, 40);
5968   FIELD_BD (fog_distance_near, 40); /* default 100.0 (at the far clipping plane) */
5969   FIELD_BD (fog_distance_far, 40);
5970   FIELD_B (environ_image_enabled, 290);
5971   FIELD_T (environ_image_filename, 1);
5972   return NULL;
5973 }
5974 static Dxf_Pair *
add_RENDERSETTINGS(Dwg_Object * restrict obj,Bit_Chain * restrict dat)5975 add_RENDERSETTINGS (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
5976 {
5977   Dwg_Object_RENDERSETTINGS *o = obj->tio.object->tio.RENDERSETTINGS;
5978   Dwg_Data *dwg = obj->parent;
5979   Dxf_Pair *pair;
5980 
5981   FIELD_BL (class_version, 90);
5982   FIELD_T (name, 1);
5983   FIELD_B (fog_enabled, 290);
5984   FIELD_B (fog_background_enabled, 290);
5985   FIELD_B (backfaces_enabled, 290);
5986   FIELD_B (environ_image_enabled, 290);
5987   FIELD_T (environ_image_filename, 1);
5988   FIELD_T (description, 1);
5989   FIELD_BL (display_index, 90);
5990   VERSION (R_2013) {
5991     FIELD_B (has_predefined, 290);
5992   }
5993   return NULL;
5994 }
5995 
5996 static Dxf_Pair *
add_RENDERGLOBAL(Dwg_Object * restrict obj,Bit_Chain * restrict dat)5997 add_RENDERGLOBAL (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
5998 {
5999   Dwg_Object_RENDERGLOBAL *o = obj->tio.object->tio.RENDERGLOBAL;
6000   Dwg_Data *dwg = obj->parent;
6001   Dxf_Pair *pair;
6002 
6003   FIELD_BL (class_version, 90);
6004   FIELD_BL (procedure, 90);         /*!< 0 view, 1 crop, 2 selection */
6005   FIELD_BL (destination, 90);       /*!< 0 window, 1 viewport */
6006   FIELD_B (save_enabled, 290);
6007   FIELD_T (save_filename, 1);
6008   FIELD_BL (image_width, 90);
6009   FIELD_BL (image_height, 90);
6010   FIELD_B (predef_presets_first, 290);
6011   FIELD_B (highlevel_info, 290);
6012   return NULL;
6013 }
6014 
6015 static Dxf_Pair *
add_RENDERENTRY(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6016 add_RENDERENTRY (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6017 {
6018   Dwg_Object_RENDERENTRY *o = obj->tio.object->tio.RENDERENTRY;
6019   Dwg_Data *dwg = obj->parent;
6020   Dxf_Pair *pair;
6021 
6022   FIELD_BL (class_version, 90);
6023   FIELD_T (image_file_name, 1);
6024   FIELD_T (preset_name, 1);
6025   FIELD_T (view_name, 1);
6026   FIELD_BL (dimension_x, 90);
6027   FIELD_BL (dimension_y, 90);
6028   FIELD_BS (start_year, 70);
6029   FIELD_BS (start_month, 70);
6030   FIELD_BS (start_day, 70);
6031   FIELD_BS (start_minute, 70);
6032   FIELD_BS (start_second, 70);
6033   FIELD_BS (start_msec, 70);
6034   FIELD_BD (render_time, 40);
6035   FIELD_BL (memory_amount, 90);
6036   FIELD_BL (material_count, 90);
6037   FIELD_BL (light_count, 90);
6038   FIELD_BL (triangle_count, 90);
6039   FIELD_BL (display_index, 90);
6040   return NULL;
6041 }
6042 // more Dynblocks:
6043 static Dxf_Pair *
add_AcDbBlockParameter(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6044 add_AcDbBlockParameter (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6045 {
6046   Dwg_Object_BLOCKALIGNMENTGRIP *o = obj->tio.object->tio.BLOCKALIGNMENTGRIP;
6047   Dwg_Data *dwg = obj->parent;
6048   Dxf_Pair *pair;
6049   // SUBCLASS (AcDbBlockParameter);
6050   FIELD_B (show_properties, 280);
6051   FIELD_B (chain_actions, 281);
6052   return NULL;
6053 }
6054 #if 0
6055 static Dxf_Pair *
6056 add_AcDbBlockGrip (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6057 {
6058   Dwg_Object_BLOCKALIGNMENTGRIP *o = obj->tio.object->tio.BLOCKALIGNMENTGRIP;
6059   Dwg_Data *dwg = obj->parent;
6060   Dxf_Pair *pair;
6061   // SUBCLASS (AcDbBlockGrip)
6062   FIELD_BL (bg_bl91, 91);
6063   FIELD_BL (bg_bl92, 92);
6064   FIELD_3BD (bg_location, 1010);
6065   FIELD_B (bg_insert_cycling, 280);
6066   FIELD_BLd (bg_insert_cycling_weight, 93);
6067   return NULL;
6068 }
6069 #endif
6070 static Dxf_Pair *
add_AcDbBlockGripExpr(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6071 add_AcDbBlockGripExpr (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6072 {
6073   Dwg_Object_BLOCKALIGNMENTGRIP *o = obj->tio.object->tio.BLOCKALIGNMENTGRIP;
6074   Dwg_Data *dwg = obj->parent;
6075   Dxf_Pair *pair;
6076   // SUBCLASS (AcDbBlockGripExpr)
6077   FIELD_BL (grip_type, 91); /* ?? */
6078   FIELD_T (grip_expr, 300)
6079   return NULL;
6080 }
6081 // also for BLOCKLINEARGRIP
6082 static Dxf_Pair *
add_BLOCKALIGNMENTGRIP(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6083 add_BLOCKALIGNMENTGRIP (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6084 {
6085   Dwg_Object_BLOCKALIGNMENTGRIP *o = obj->tio.object->tio.BLOCKALIGNMENTGRIP;
6086   Dwg_Data *dwg = obj->parent;
6087   Dxf_Pair *pair;
6088   FIELD_3BD_1 (orientation, 140);
6089   return NULL;
6090 }
6091 static Dxf_Pair *
add_BLOCKFLIPGRIP(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6092 add_BLOCKFLIPGRIP (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6093 {
6094   Dwg_Object_BLOCKFLIPGRIP *o = obj->tio.object->tio.BLOCKFLIPGRIP;
6095   Dwg_Data *dwg = obj->parent;
6096   Dxf_Pair *pair;
6097   FIELD_3BD_1 (orientation, 140);
6098   FIELD_BL (combined_state, 93);
6099   return NULL;
6100 }
6101 
6102 static Dxf_Pair *
add_PERSUBENTMGR(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)6103 add_PERSUBENTMGR (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
6104                   Dxf_Pair *restrict pair)
6105 {
6106   Dwg_Object_PERSUBENTMGR *o = obj->tio.object->tio.PERSUBENTMGR;
6107   Dwg_Data *dwg = obj->parent;
6108 
6109   EXPECT_INT_DXF ("class_version", 90, BL);
6110   FIELD_BL (unknown_0, 90);
6111   FIELD_BL (unknown_2, 90);
6112   FIELD_BL (numassocsteps, 90);
6113   FIELD_BL (numassocsubents, 90);
6114   FIELD_BL (num_steps, 90);
6115   if (o->num_steps)
6116     {
6117       o->steps = (BITCODE_BL*)xcalloc (o->num_steps, sizeof (BITCODE_BL));
6118       if (!o->steps)
6119         return pair;
6120       for (unsigned i = 0; i < o->num_steps; i++)
6121         {
6122           pair = dxf_read_pair (dat);
6123           if (pair->code != 90)
6124             return pair;
6125           o->steps[i] = pair->value.u;
6126           LOG_TRACE ("%s.steps[%d] = %u [BL %d]\n", obj->name, i,
6127                      pair->value.u, pair->code);
6128           dxf_free_pair (pair);
6129         }
6130     }
6131   return NULL;
6132 }
6133 
6134 static Dxf_Pair *
add_ASSOCDEPENDENCY(Dwg_Object * restrict obj,Bit_Chain * restrict dat)6135 add_ASSOCDEPENDENCY (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
6136 {
6137   Dwg_Object_ASSOCDEPENDENCY *o = obj->tio.object->tio.ASSOCDEPENDENCY;
6138   Dwg_Data *dwg = obj->parent;
6139   Dxf_Pair *pair;
6140 
6141   FIELD_BL (class_version, 90);
6142   FIELD_BL (status, 90);
6143   FIELD_B (is_read_dep, 290);
6144   FIELD_B (is_write_dep, 290);
6145   FIELD_B (is_attached_to_object, 290);
6146   FIELD_B (is_delegating_to_owning_action, 290);
6147   FIELD_BLd (order, 90); /* -1 or 0 */
6148   FIELD_HANDLE (dep_on, 3, 330);
6149   FIELD_B (has_name, 290);
6150   if (o->has_name)
6151     {
6152       FIELD_T (name, 1);
6153     }
6154   FIELD_HANDLE (readdep, 4, 330);
6155   FIELD_HANDLE (node, 3, 330);
6156   FIELD_HANDLE (dep_body, 4, 360);
6157   FIELD_BLd (depbodyid, 90);
6158   return NULL;
6159 }
6160 
6161 static Dwg_Object *
find_prev_entity(Dwg_Object * obj)6162 find_prev_entity (Dwg_Object *obj)
6163 {
6164   Dwg_Data *dwg = obj->parent;
6165   if (obj->supertype != DWG_SUPERTYPE_ENTITY)
6166     return NULL;
6167   for (BITCODE_BL i = obj->index - 1; i > 0; i--)
6168     {
6169       Dwg_Object *prev = &dwg->object[i];
6170       if (prev->supertype == DWG_SUPERTYPE_ENTITY
6171           && prev->tio.entity->entmode == obj->tio.entity->entmode)
6172         {
6173           if (prev->fixedtype == DWG_TYPE_SEQEND
6174               || prev->fixedtype == DWG_TYPE_ENDBLK)
6175             return NULL;
6176           else
6177             return prev;
6178         }
6179     }
6180   return NULL;
6181 }
6182 
6183 /* if it has an absolute ownerhandle */
6184 static int
is_obj_absowner(Dwg_Object * obj)6185 is_obj_absowner (Dwg_Object *obj)
6186 {
6187   if (obj->supertype == DWG_SUPERTYPE_ENTITY)
6188     return 0;
6189   /* With DICTIONARY it may vary */
6190   if (obj->type < DWG_TYPE_GROUP // needs to be absolute 4.1.X
6191       /* obj->fixedtype != DWG_TYPE_DICTIONARY && */
6192       && obj->fixedtype != DWG_TYPE_XRECORD)
6193     return 1;
6194   if (obj->fixedtype == DWG_TYPE_LAYOUT)
6195     return 1;
6196   else // may have relative ref: 8.0.0
6197     return 0;
6198 }
6199 
6200 static Dxf_Pair *
new_table_control(const char * restrict name,Bit_Chain * restrict dat,Dwg_Data * restrict dwg)6201 new_table_control (const char *restrict name, Bit_Chain *restrict dat,
6202                    Dwg_Data *restrict dwg)
6203 {
6204   // VPORT_CONTROL.num_entries
6205   // VPORT_CONTROL.entries[num_entries] handles
6206   Dwg_Object *obj;
6207   Dxf_Pair *pair = NULL;
6208   Dwg_Object_LTYPE_CONTROL *_obj = NULL; // the largest
6209   int j = 0;
6210   int is_tu = dwg->header.version >= R_2007 ? 1 : 0;
6211   char *fieldname;
6212   char ctrlname[80];
6213   char *dxfname;
6214   BITCODE_B is_xref_ref; // referencable
6215 
6216   NEW_OBJECT (dwg, obj);
6217 
6218   if (strEQc (name, "BLOCK_RECORD"))
6219     strcpy (ctrlname, "BLOCK_CONTROL");
6220   else if (strEQc (name, "VX_TABLE_RECORD"))
6221     strcpy (ctrlname, "VX_CONTROL");
6222   else
6223     {
6224       strncpy (ctrlname, name, 70);
6225       ctrlname[69] = '\0';
6226       strcat (ctrlname, "_CONTROL");
6227     }
6228   LOG_TRACE ("add %s\n", ctrlname);
6229   dxfname = strdup (ctrlname);
6230 
6231   // clang-format off
6232   ADD_TABLE_IF (LTYPE, LTYPE_CONTROL)
6233   else
6234   ADD_TABLE_IF (VPORT, VPORT_CONTROL)
6235   else
6236   ADD_TABLE_IF (APPID, APPID_CONTROL)
6237   else
6238   ADD_TABLE_IF (BLOCK_RECORD, BLOCK_CONTROL)
6239   else
6240   ADD_TABLE_IF (DIMSTYLE, DIMSTYLE_CONTROL)
6241   else
6242   ADD_TABLE_IF (LAYER, LAYER_CONTROL)
6243   else
6244   ADD_TABLE_IF (STYLE, STYLE_CONTROL)
6245   else
6246   ADD_TABLE_IF (UCS, UCS_CONTROL)
6247   else
6248   ADD_TABLE_IF (VIEW, VIEW_CONTROL)
6249   else
6250   ADD_TABLE_IF (VX_TABLE_RECORD, VX_CONTROL)
6251   else
6252   ADD_TABLE_IF (BLOCK_RECORD, BLOCK_CONTROL)
6253   else
6254   // clang-format on
6255   {
6256     // obj->name = "UNKNOWN_OBJ";
6257     obj->fixedtype = DWG_TYPE_UNKNOWN_OBJ;
6258     // undo NEW_OBJECT
6259     free (dxfname);
6260     free (obj->tio.object);
6261     dwg->num_objects--;
6262     LOG_ERROR ("Unknown DXF TABLE %s nor %s_CONTROL", name, name);
6263     return pair;
6264   }
6265   if (!_obj)
6266     {
6267       // obj->name = "UNKNOWN_OBJ";
6268       obj->fixedtype = DWG_TYPE_UNKNOWN_OBJ;
6269       // undo NEW_OBJECT
6270       free (obj->tio.object);
6271       dwg->num_objects--;
6272       LOG_ERROR ("Empty _obj at DXF TABLE %s nor %s_CONTROL", name, name);
6273       return pair;
6274     }
6275   dwg_dynapi_entity_set_value (_obj, obj->name, "objid", &obj->index, 1);
6276   is_xref_ref = 1;
6277   if (dwg_dynapi_entity_field (obj->name, "is_xref_ref"))
6278     dwg_dynapi_entity_set_value (_obj, obj->name, "is_xref_ref", &is_xref_ref,
6279                                  1);
6280   // default is_xdic_missing
6281   if (dwg->header.version >= R_2004)
6282     obj->tio.object->is_xdic_missing = 1;
6283 
6284   pair = dxf_read_pair (dat);
6285   // read common table until next 0 table or endtab
6286   while (pair != NULL && pair->code != 0)
6287     {
6288       switch (pair->code)
6289         {
6290         case 0:
6291           goto do_return;
6292         case 5:
6293         case 105: // for DIMSTYLE
6294           {
6295             Dwg_Object_Ref *ref;
6296             char ctrlobj[80];
6297             dwg_add_handle (&obj->handle, 0, pair->value.u, obj);
6298             ref = dwg_add_handleref (dwg, 3, pair->value.u, obj);
6299             LOG_TRACE ("%s.handle = " FORMAT_H " [H %d]\n", ctrlname,
6300                        ARGS_H (obj->handle), pair->code);
6301             // also set the matching HEADER.*_CONTROL_OBJECT
6302             strncpy (ctrlobj, ctrlname, 70);
6303             ctrlobj[69] = '\0';
6304             strcat (ctrlobj, "_OBJECT");
6305             dwg_dynapi_header_set_value (dwg, ctrlobj, &ref, 0);
6306             LOG_TRACE ("HEADER.%s = " FORMAT_REF " [H 0]\n", ctrlobj,
6307                        ARGS_REF (ref));
6308           }
6309           break;
6310         case 100: // AcDbSymbolTableRecord, ... ignore
6311           break;
6312         case 102: // TODO {ACAD_XDICTIONARY {ACAD_REACTORS {BLKREFS
6313           break;
6314         case 330: // TODO: most likely {ACAD_REACTORS
6315           {
6316             BITCODE_H owh;
6317             if (is_obj_absowner (obj))
6318               owh = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
6319             else // relative
6320               owh = dwg_add_handleref (dwg, 4, pair->value.u, obj);
6321             obj->tio.object->ownerhandle = owh;
6322             LOG_TRACE ("%s.ownerhandle = " FORMAT_REF " [H 330]\n", ctrlname,
6323                        ARGS_REF (owh));
6324           }
6325           break;
6326         case 340:
6327           if (pair->value.u && strEQc (ctrlname, "DIMSTYLE_CONTROL"))
6328             {
6329               Dwg_Object_DIMSTYLE_CONTROL *o
6330                   = (Dwg_Object_DIMSTYLE_CONTROL *)_obj;
6331               if (!o->num_morehandles || j < 0 || j >= o->num_morehandles)
6332                 {
6333                   LOG_ERROR ("Invalid DIMSTYLE_CONTROL.num_morehandles %d or "
6334                              "index %d",
6335                              o->num_morehandles, j)
6336                   break;
6337                 }
6338               assert (o->morehandles);
6339               assert (j >= 0);
6340               assert (j < o->num_morehandles);
6341               o->morehandles[j]
6342                   = dwg_add_handleref (dwg, 5, pair->value.u, NULL);
6343               LOG_TRACE ("%s.morehandles[%d] = " FORMAT_REF " [H 340]\n",
6344                          ctrlname, j, ARGS_REF (o->morehandles[j]));
6345               j++;
6346             }
6347           break;
6348         case 360: // {ACAD_XDICTIONARY TODO
6349           obj->tio.object->xdicobjhandle
6350               = dwg_add_handleref (dwg, 3, pair->value.u, obj);
6351           obj->tio.object->is_xdic_missing = 0;
6352           LOG_TRACE ("%s.xdicobjhandle = " FORMAT_REF " [H 360]\n", ctrlname,
6353                      ARGS_REF (obj->tio.object->xdicobjhandle));
6354           break;
6355         case 70:
6356           if (pair->value.u)
6357             {
6358               BITCODE_H *hdls;
6359               // can be -1
6360               BITCODE_BL num_entries = pair->value.i < 0 ? 0 : pair->value.i;
6361               if (num_entries > 32767 // BS overflow
6362                   && obj->fixedtype != DWG_TYPE_BLOCK_CONTROL
6363                   && obj->fixedtype != DWG_TYPE_LAYER_CONTROL
6364                   && obj->fixedtype != DWG_TYPE_VIEW_CONTROL
6365                   && obj->fixedtype != DWG_TYPE_STYLE_CONTROL)
6366                 {
6367                   LOG_ERROR ("%s.num_entries BS overflow", obj->name);
6368                   num_entries = 0;
6369                 }
6370               hdls = (BITCODE_H *)xcalloc (num_entries, sizeof (BITCODE_H));
6371               if (!hdls)
6372                 num_entries = 0;
6373               dwg_dynapi_entity_set_value (_obj, obj->name, "num_entries",
6374                                            &num_entries, 1);
6375               LOG_TRACE ("%s.num_entries = %u [BL 70]\n", ctrlname,
6376                          num_entries);
6377               dwg_dynapi_entity_set_value (_obj, obj->name, "entries", &hdls,
6378                                            0);
6379               LOG_TRACE ("Add %d %s.%s\n", num_entries, ctrlname, "entries");
6380             }
6381           break;
6382         case 71:
6383           if (strEQc (ctrlname, "DIMSTYLE_CONTROL"))
6384             {
6385               if (pair->value.u)
6386                 {
6387                   BITCODE_H *hdls;
6388                   hdls = (BITCODE_H *)xcalloc (pair->value.u,
6389                                                sizeof (BITCODE_H));
6390                   if (!hdls)
6391                     pair->value.u = 0;
6392                   dwg_dynapi_entity_set_value (
6393                       _obj, obj->name, "num_morehandles", &pair->value, is_tu);
6394                   LOG_TRACE ("%s.num_morehandles = %u [BL 71]\n", ctrlname,
6395                              pair->value.u);
6396                   dwg_dynapi_entity_set_value (_obj, obj->name, "morehandles",
6397                                                &hdls, 0);
6398                   LOG_TRACE ("Add %s.morehandles[%d]\n", ctrlname,
6399                              pair->value.u);
6400                 }
6401               else
6402                 {
6403                   LOG_TRACE ("%s.num_morehandles = %u [BL 71]\n", ctrlname,
6404                              pair->value.u)
6405                 }
6406               break;
6407             }
6408           // fall through
6409         default:
6410           if (pair->code >= 1000 && pair->code < 1999)
6411             {
6412               add_eed (obj, obj->name, pair);
6413             }
6414           else
6415             LOG_ERROR ("Unknown DXF code %d for %s", pair->code, ctrlname);
6416         }
6417       dxf_free_pair (pair);
6418       pair = dxf_read_pair (dat);
6419     }
6420 do_return:
6421   // default NULL handle
6422   if (!obj->tio.object->xdicobjhandle)
6423     {
6424       obj->tio.object->is_xdic_missing = 1;
6425       if (dwg->header.version >= R_13 && dwg->header.version < R_2004)
6426         obj->tio.object->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, obj);
6427     }
6428   return pair;
6429 }
6430 
6431 /* by name or by ref.
6432    Note that we don't get the ref->obj here, as it may still move
6433    by realloc dwg->object[].
6434 */
6435 BITCODE_H
find_tablehandle(Dwg_Data * restrict dwg,Dxf_Pair * restrict pair)6436 find_tablehandle (Dwg_Data *restrict dwg, Dxf_Pair *restrict pair)
6437 {
6438   BITCODE_H ref = NULL;
6439   if (pair->code == 8)
6440     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "LAYER");
6441   else if (pair->code == 1) // $DIMBLK
6442     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "BLOCK");
6443   // some name: $DIMSTYLE, $UCSBASE, $UCSORTHOREF, $CMLSTYLE
6444   // not enough info, decide later
6445   else if (pair->code == 2)
6446     ;
6447   else if (pair->code == 3)
6448     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "DIMSTYLE");
6449   // what is/was 4 and 5? VIEW? VX?
6450   else if (pair->code == 6)
6451     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "LTYPE");
6452   else if (pair->code == 7)
6453     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "STYLE");
6454 
6455   if (ref) // turn a 2 (hardowner) into a 5 (softref)
6456     return dwg_add_handleref (dwg, 5, ref->absolute_ref, NULL);
6457   /* I think all these >300 are given by hex value, not by name */
6458   if (!ref && pair->code > 300)
6459     {
6460       for (BITCODE_BL i = 0; i < dwg->num_object_refs; i++)
6461         {
6462           Dwg_Object_Ref *refi = dwg->object_ref[i];
6463           if (refi->absolute_ref == (BITCODE_BL)pair->value.u)
6464             {
6465               // no relative offset
6466               ref = dwg_add_handleref (dwg, 5, pair->value.u, NULL);
6467               break;
6468             }
6469         }
6470       if (!ref)
6471         {
6472           // no relative offset
6473           ref = dwg_add_handleref (dwg, 5, pair->value.u, NULL);
6474         }
6475     }
6476 #if 0
6477   else if (pair->code == 331)
6478     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "VPORT");
6479   else if (pair->code == 390)
6480     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "PLOTSTYLENAME");
6481   else if (pair->code == 347)
6482     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "MATERIAL");
6483   else if (pair->code == 345 || pair->code == 346)
6484     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "UCS");
6485   else if (pair->code == 361) // SUN
6486     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "SHADOW");
6487   else if (pair->code == 340) // or TABLESTYLE or LAYOUT or MLINESTYLE ...
6488     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "STYLE");
6489   else if (pair->code == 342 || pair->code == 343)
6490     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "STYLE");
6491   else if (pair->code == 348)
6492     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "VISUALSTYLE");
6493   else if (pair->code == 332)
6494     ref = dwg_find_tablehandle_silent (dwg, pair->value.s, "BACKGROUND");
6495 #endif
6496   return ref;
6497 }
6498 
6499 // add pair to XRECORD
6500 static Dxf_Pair *
add_xdata(Bit_Chain * restrict dat,Dwg_Object * restrict obj,Dxf_Pair * restrict pair)6501 add_xdata (Bit_Chain *restrict dat, Dwg_Object *restrict obj,
6502            Dxf_Pair *restrict pair)
6503 {
6504   BITCODE_BL num_xdata, xdata_size;
6505   // add pairs to xdata linked list
6506   Dwg_Resbuf *rbuf;
6507   Dwg_Object_XRECORD *_obj = obj->tio.object->tio.XRECORD;
6508 
6509   num_xdata = _obj->num_xdata;
6510   xdata_size = _obj->xdata_size;
6511   rbuf = (Dwg_Resbuf *)calloc (1, sizeof (Dwg_Resbuf));
6512   if (!rbuf)
6513     {
6514       LOG_ERROR ("Out of memory");
6515       return NULL;
6516     }
6517   if (num_xdata && _obj->xdata)
6518     {
6519       Dwg_Resbuf *xdata, *prev;
6520       // add to end, not front
6521       prev = xdata = _obj->xdata;
6522       while (xdata)
6523         {
6524           prev = xdata;
6525           xdata = xdata->nextrb;
6526         }
6527       prev->nextrb = rbuf;
6528     }
6529   else
6530     _obj->xdata = rbuf;
6531 
6532   xdata_size += 2; // RS
6533   rbuf->type = pair->code;
6534   switch (dwg_resbuf_value_type (rbuf->type))
6535     {
6536     case DWG_VT_STRING:
6537       if (!pair->value.s)
6538         goto invalid;
6539       PRE (R_2007) // TODO: nice would be the proper target version.
6540                    // dat->version
6541       {
6542         Dwg_Data *dwg = obj->parent;
6543         rbuf->value.str.size = strlen (pair->value.s);
6544         rbuf->value.str.codepage = dwg->header.codepage;
6545         rbuf->value.str.is_tu = 0;
6546         rbuf->value.str.u.data = strdup (pair->value.s);
6547         LOG_TRACE ("xdata[%d]: \"%s\" [%d]\n", num_xdata,
6548                    rbuf->value.str.u.data, rbuf->type);
6549         xdata_size += 3 + rbuf->value.str.size;
6550       }
6551       LATER_VERSIONS
6552       {
6553         int length = rbuf->value.str.size = strlen (pair->value.s);
6554         if (length > 0)
6555           rbuf->value.str.u.wdata = bit_utf8_to_TU (pair->value.s, 0);
6556         rbuf->value.str.is_tu = 1;
6557         LOG_TRACE ("xdata[%d]: \"%s\" [TU %d]\n", num_xdata,
6558                    pair->value.s, rbuf->type);
6559         xdata_size += 2 + 2 * rbuf->value.str.size;
6560       }
6561       break;
6562     case DWG_VT_REAL:
6563       rbuf->value.dbl = pair->value.d;
6564       LOG_TRACE ("xdata[%d]: %f [%d]\n", num_xdata, rbuf->value.dbl,
6565                  rbuf->type);
6566       xdata_size += 8;
6567       break;
6568     case DWG_VT_BOOL:
6569     case DWG_VT_INT8:
6570       rbuf->value.i8 = pair->value.i;
6571       LOG_TRACE ("xdata[%d]: %d [%d]\n", num_xdata, (int)rbuf->value.i8,
6572                  rbuf->type);
6573       xdata_size += 1;
6574       break;
6575     case DWG_VT_INT16:
6576       rbuf->value.i16 = pair->value.i;
6577       LOG_TRACE ("xdata[%d]: %d [%d]\n", num_xdata, (int)rbuf->value.i16,
6578                  rbuf->type);
6579       xdata_size += 2;
6580       break;
6581     case DWG_VT_INT32:
6582       rbuf->value.i32 = pair->value.l;
6583       LOG_TRACE ("xdata[%d]: %ld [%d]\n", num_xdata, (long)rbuf->value.i32,
6584                  rbuf->type);
6585       xdata_size += 4;
6586       break;
6587     case DWG_VT_INT64:
6588       rbuf->value.i64 = (BITCODE_BLL)pair->value.rll;
6589       LOG_TRACE ("xdata[%d]: " FORMAT_RLL " [%d]\n", num_xdata,
6590                  rbuf->value.i64, rbuf->type);
6591       xdata_size += 8;
6592       break;
6593     case DWG_VT_POINT3D:
6594       rbuf->value.pt[0] = pair->value.d;
6595       dxf_free_pair (pair);
6596       pair = dxf_read_pair (dat);
6597       if (!pair)
6598         return NULL;
6599       rbuf->value.pt[1] = pair->value.d;
6600       dxf_free_pair (pair);
6601       xdata_size += 24;
6602       { // if 30
6603         long pos = bit_position (dat);
6604         pair = dxf_read_pair (dat);
6605         if (!pair)
6606           return NULL;
6607         if (dwg_resbuf_value_type (pair->code) == DWG_VT_POINT3D)
6608           {
6609             rbuf->value.pt[2] = pair->value.d;
6610             LOG_TRACE ("xdata[%d]: (%f,%f,%f) [%d]\n", num_xdata,
6611                        rbuf->value.pt[0], rbuf->value.pt[1], rbuf->value.pt[2],
6612                        rbuf->type);
6613           }
6614         else
6615           {
6616             bit_set_position (dat, pos); // reset stream
6617             rbuf->value.pt[2] = 0;
6618             LOG_TRACE ("xdata[%d]: (%f,%f) [%d]\n", num_xdata,
6619                        rbuf->value.pt[0], rbuf->value.pt[1], rbuf->type);
6620           }
6621       }
6622       break;
6623     case DWG_VT_BINARY:
6624       // convert from hex
6625       if (!pair->value.s)
6626         goto invalid;
6627       {
6628         unsigned len = strlen (pair->value.s);
6629         unsigned blen = len / 2;
6630         unsigned read;
6631         unsigned char *s = (unsigned char *)malloc (blen);
6632         //const char *pos = pair->value.s;
6633         rbuf->value.str.u.data = (char *)s;
6634         rbuf->value.str.size = blen;
6635         if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
6636           LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
6637         xdata_size += 1 + len;
6638         LOG_TRACE ("xdata[%d]: ", num_xdata);
6639         // LOG_TRACE_TF (rbuf->value.str.u.data, rbuf->value.str.size);
6640       }
6641       break;
6642     case DWG_VT_HANDLE:
6643     case DWG_VT_OBJECTID:
6644       xdata_size += 8;
6645       dwg_add_handle (&rbuf->value.h, 0, pair->value.u, obj);
6646       LOG_TRACE ("xdata[%d]: " FORMAT_H " [H %d]\n", num_xdata,
6647                  ARGS_H (rbuf->value.h), rbuf->type);
6648       break;
6649     case DWG_VT_INVALID:
6650     default:
6651     invalid:
6652       LOG_ERROR ("Invalid group code in rbuf: %d", rbuf->type)
6653     }
6654 
6655   num_xdata++;
6656   _obj->num_xdata = num_xdata;
6657   _obj->xdata_size = xdata_size;
6658   return pair;
6659 }
6660 
6661 // 350 or 360
6662 static void
add_dictionary_itemhandles(Dwg_Object * restrict obj,Dxf_Pair * restrict pair,char * restrict text)6663 add_dictionary_itemhandles (Dwg_Object *restrict obj, Dxf_Pair *restrict pair,
6664                             char *restrict text)
6665 {
6666   // but not DICTIONARYVAR
6667   Dwg_Object_DICTIONARY *_obj
6668       = obj->tio.object->tio.DICTIONARY; // also DICTIONARYWDFLT
6669   Dwg_Data *dwg = obj->parent;
6670   BITCODE_BL num;
6671   BITCODE_H hdl;
6672 
6673   if (pair->code == 360)
6674     _obj->is_hardowner = 1;
6675   num = _obj->numitems;
6676   hdl = dwg_add_handleref (dwg, 2, pair->value.u, obj);
6677   LOG_TRACE ("%s.itemhandles[%d] = " FORMAT_REF " [H* %d]\n", obj->name, num,
6678              ARGS_REF (hdl), pair->code);
6679   _obj->itemhandles = (BITCODE_H *)realloc (_obj->itemhandles,
6680                                             (num + 1) * sizeof (BITCODE_H));
6681   _obj->texts
6682       = (BITCODE_TV *)realloc (_obj->texts, (num + 1) * sizeof (BITCODE_TV));
6683   if (!_obj->itemhandles || !_obj->texts)
6684     {
6685       LOG_ERROR ("Out of memory");
6686       return;
6687     }
6688   _obj->itemhandles[num] = hdl;
6689   _obj->texts[num] = dwg_add_u8_input (dwg, text);
6690   LOG_TRACE ("%s.texts[%d] = %s [T* 3]\n", obj->name, num, text);
6691   _obj->numitems = num + 1;
6692 }
6693 
6694 /* read to ent->preview, r2010+ code 160, earlier code 92.
6695    like WIPEOUT, LIGHT, MULTILEADER, ARC_DIMENSION or PROXY GRAPHICS vector
6696    data.
6697    Also handle empty preview_size, such as with MULTILEADER r2000.
6698 */
6699 static Dxf_Pair *
add_ent_preview(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)6700 add_ent_preview (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
6701                  Dxf_Pair *restrict pair)
6702 {
6703   Dwg_Object_Entity *ent = obj->tio.entity;
6704   unsigned written = 0;
6705 
6706   if (obj->supertype != DWG_SUPERTYPE_ENTITY)
6707     {
6708       LOG_ERROR ("%s is no entity for a preview", obj->name);
6709       return pair;
6710     }
6711   ent->preview_size =
6712     pair->code == 160 ? pair->value.rll :
6713     pair->code == 92 ? pair->value.u : 0;
6714   if (!ent->preview_size && pair->code != 310)
6715     {
6716       dxf_free_pair (pair);
6717       return dxf_read_pair (dat);
6718     }
6719   ent->preview = (BITCODE_TF)calloc (ent->preview_size ? ent->preview_size : 127, 1);
6720   if (!ent->preview)
6721     {
6722       LOG_ERROR ("Out of memory");
6723       return NULL;
6724     }
6725   LOG_TRACE ("%s.preview_size = " FORMAT_BLL " [BLL %d]\n", obj->name,
6726              ent->preview_size, pair->code);
6727 
6728   if (pair->code != 310)
6729     {
6730       dxf_free_pair (pair);
6731       pair = dxf_read_pair (dat);
6732     }
6733   while (pair != NULL && pair->code == 310 && pair->value.s)
6734     {
6735       int read;
6736       unsigned len = strlen (pair->value.s);
6737       unsigned blen = len / 2;
6738       //const char *pos = pair->value.s;
6739       BITCODE_TF s;
6740 
6741       if (!ent->preview_size)
6742         ent->preview = (BITCODE_TF)realloc (ent->preview, written + blen);
6743       else if (blen + written > ent->preview_size)
6744         {
6745           LOG_ERROR ("%s.preview overflow: %u + written %u > size: " FORMAT_BLL,
6746                      obj->name, blen, written, ent->preview_size);
6747           return pair;
6748         }
6749       s = &ent->preview[written];
6750       if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
6751         LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
6752       written += read;
6753       LOG_TRACE ("%s.preview += %u (%u/" FORMAT_BLL ")\n", obj->name, blen,
6754                  written, ent->preview_size);
6755 
6756       dxf_free_pair (pair);
6757       pair = dxf_read_pair (dat);
6758     }
6759   if (!ent->preview_size)
6760     ent->preview_size = written;
6761   if (ent->preview_size)
6762     ent->preview_exists = 1;
6763   return pair;
6764 }
6765 
6766 // read to BLOCK_HEADER.preview (310), filling in the size
6767 static Dxf_Pair *
add_block_preview(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)6768 add_block_preview (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
6769                    Dxf_Pair *restrict pair)
6770 {
6771   Dwg_Object_BLOCK_HEADER *_obj = obj->tio.object->tio.BLOCK_HEADER;
6772   unsigned written = 0;
6773 
6774   if (obj->type != DWG_TYPE_BLOCK_HEADER)
6775     {
6776       LOG_ERROR ("%s is no BLOCK_HEADER for a preview", obj->name);
6777       return pair;
6778     }
6779   if (pair->code != 310)
6780     {
6781       LOG_ERROR ("Invalid %s.preview code %d, need 310", obj->name,
6782                  pair->code);
6783       return pair;
6784     }
6785   while (pair != NULL && pair->code == 310)
6786     {
6787       const char *pos = pair->value.s;
6788       const unsigned len = pos ? strlen (pos) : 0;
6789       const unsigned blen = len / 2;
6790       unsigned read;
6791       BITCODE_TF s;
6792 
6793       if (len)
6794         {
6795           _obj->preview = (BITCODE_TF)realloc (_obj->preview, written + blen);
6796           s = &_obj->preview[written];
6797           if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
6798             LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
6799           written += read;
6800           LOG_TRACE ("BLOCK_HEADER.preview += %u (%u)\n", blen, written);
6801         }
6802       dxf_free_pair (pair);
6803       pair = dxf_read_pair (dat);
6804     }
6805   _obj->preview_size = written;
6806   LOG_TRACE ("BLOCK_HEADER.preview_size = %u [BL 0]\n", written);
6807   return pair;
6808 }
6809 
6810 // only need to process conflicting SPLINE DXF codes here. the rest is done via
6811 // dynapi.
6812 // TODO: also for HELIX (where SPLINE is a subclass), pass obj then.
6813 static int
add_SPLINE(Dwg_Entity_SPLINE * restrict o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair,int * restrict jp,BITCODE_RS * restrict flagp)6814 add_SPLINE (Dwg_Entity_SPLINE *restrict o, Bit_Chain *restrict dat,
6815             Dxf_Pair *restrict pair, int *restrict jp,
6816             BITCODE_RS *restrict flagp)
6817 {
6818   int j = *jp;
6819   if (pair->code == 210 || pair->code == 220 || pair->code == 230)
6820     return 0; // ignore extrusion in the dwg (planar only)
6821   else if (pair->code == 70)
6822     {
6823       BITCODE_RS flag = *flagp;
6824       *flagp = flag = pair->value.i;
6825       o->flag = flag;
6826       LOG_TRACE ("SPLINE.flag = %d [70]\n", flag);
6827       if (flag & 1)
6828         {
6829           o->closed_b = 1;
6830           LOG_TRACE ("=> SPLINE.closed_b = 1 [B 0] (bit 0)\n");
6831         }
6832       if (flag & 2)
6833         {
6834           o->periodic = 1;
6835           LOG_TRACE ("=> SPLINE.periodic = 1 [B 0] (bit 1)\n");
6836         }
6837       if (flag & 4)
6838         {
6839           o->rational = 1;
6840           LOG_TRACE ("=> SPLINE.rational = 1 [B 0] (bit 2)\n");
6841         }
6842       if (flag & 16)
6843         {
6844           o->weighted = 1;
6845           LOG_TRACE ("=> SPLINE.weighted = 1 [B 0] (bit 4)\n");
6846         }
6847       if (flag & 32)
6848         o->scenario = 2; // bezier: planar
6849       else
6850         o->scenario = 1;
6851       LOG_TRACE ("=> SPLINE.scenario = %d [BL 0]\n", o->scenario);
6852       return 1; // found
6853     }
6854   else if (pair->code == 71)
6855     {
6856       o->degree = pair->value.i;
6857       LOG_TRACE ("SPLINE.degree = %d [BL 71]\n", o->degree);
6858       return 1; // found
6859     }
6860   else if (pair->code == 72)
6861     {
6862       o->num_knots = pair->value.i;
6863       *jp = 0;
6864       o->knots = (BITCODE_BD *)xcalloc (o->num_knots, sizeof (BITCODE_BD));
6865       if (!o->knots)
6866         {
6867           o->num_knots = 0;
6868           return 0;
6869         }
6870       LOG_TRACE ("SPLINE.num_knots = %d [BS 72]\n", o->num_knots);
6871       return 1; // found
6872     }
6873   else if (pair->code == 73)
6874     {
6875       o->num_ctrl_pts = pair->value.i;
6876       *jp = 0;
6877       o->ctrl_pts = (Dwg_SPLINE_control_point *)xcalloc (
6878           o->num_ctrl_pts, sizeof (Dwg_SPLINE_control_point));
6879       if (!o->ctrl_pts)
6880         {
6881           o->num_ctrl_pts = 0;
6882           return 0;
6883         }
6884       LOG_TRACE ("SPLINE.num_ctrl_pts = %d [BS 73]\n", o->num_ctrl_pts);
6885       return 1; // found
6886     }
6887   else if (pair->code == 74)
6888     {
6889       o->num_fit_pts = pair->value.i;
6890       *jp = 0;
6891       o->fit_pts
6892           = (BITCODE_3BD *)xcalloc (o->num_fit_pts, sizeof (BITCODE_3BD));
6893       if (!o->fit_pts)
6894         {
6895           o->num_fit_pts = 0;
6896           return 0;
6897         }
6898       j = 0;
6899       // o->scenario = 2;
6900       o->flag |= 1024;
6901       LOG_TRACE ("SPLINE.num_fit_pts = %d [BS 74]\n", o->num_fit_pts);
6902       return 1; // found
6903     }
6904   else if (pair->code == 40) // knots[] BD*
6905     {
6906       if (!o->knots || j >= (int)o->num_knots)
6907         {
6908           LOG_ERROR ("SPLINE.knots[%d] overflow, max %d", *jp, o->num_knots);
6909           return 1; // found
6910         }
6911       o->knots[j] = pair->value.d;
6912       LOG_TRACE ("SPLINE.knots[%d] = %f [BD* 40]\n", *jp, pair->value.d);
6913       j++;
6914       *jp = j;
6915       if (j == (int)o->num_knots)
6916         *jp = 0;
6917       return 1; // found
6918     }
6919   else if (pair->code == 10) // ctrl_pts[].x 3BD
6920     {
6921       if (!o->ctrl_pts || j >= (int)o->num_ctrl_pts)
6922         {
6923           LOG_ERROR ("SPLINE.ctrl_pts[%d] overflow, max %d", *jp,
6924                      o->num_ctrl_pts);
6925           return 1; // found
6926         }
6927       o->ctrl_pts[j].parent = o;
6928       o->ctrl_pts[j].x = pair->value.d;
6929       return 1; // found
6930     }
6931   else if (pair->code == 20) // ctrl_pts[].y 3BD
6932     {
6933       if (!o->ctrl_pts || j >= (int)o->num_ctrl_pts)
6934         {
6935           LOG_ERROR ("SPLINE.ctrl_pts[%d] overflow, max %d", j,
6936                      o->num_ctrl_pts);
6937           return 1; // found
6938         }
6939       o->ctrl_pts[j].y = pair->value.d;
6940       return 1; // found
6941     }
6942   else if (pair->code == 30) // ctrl_pts[].z 3BD
6943     {
6944       if (!o->ctrl_pts || j >= (int)o->num_ctrl_pts)
6945         {
6946           LOG_ERROR ("SPLINE.ctrl_pts[%d] overflow, max %d", j,
6947                      o->num_ctrl_pts);
6948           return 1; // found
6949         }
6950       o->ctrl_pts[j].z = pair->value.d;
6951       LOG_TRACE ("SPLINE.ctrl_pts[%d] = (%f, %f, %f) [3BD* 10]\n", *jp,
6952                  o->ctrl_pts[j].x, o->ctrl_pts[j].y, o->ctrl_pts[j].z);
6953       j++;
6954       *jp = j;
6955       if (j == (int)o->num_ctrl_pts)
6956         *jp = 0;
6957       return 1; // found
6958     }
6959   else if (pair->code == 41) // ctrl_pts[].z 3BD
6960     {
6961       if (!o->ctrl_pts || j >= (int)o->num_ctrl_pts)
6962         {
6963           LOG_ERROR ("SPLINE.ctrl_pts[%d] overflow, max %d", j,
6964                      o->num_ctrl_pts);
6965           return 1; // found
6966         }
6967       o->ctrl_pts[j].w = pair->value.d;
6968       LOG_TRACE ("SPLINE.ctrl_pts[%d].w = %f [BD* 41]\n", *jp,
6969                  o->ctrl_pts[j].w);
6970       j++;
6971       *jp = j;
6972       return 1; // found
6973     }
6974   else if (pair->code == 11) // fit_pts[].x 3BD
6975     {
6976       if (!o->fit_pts || j >= o->num_fit_pts)
6977         {
6978           LOG_ERROR ("SPLINE.fit_pts[%d] overflow, max %d", j, o->num_fit_pts);
6979           return 1; // found
6980         }
6981       o->fit_pts[j].x = pair->value.d;
6982       return 1; // found
6983     }
6984   else if (pair->code == 21) // fit_pts[].y 3BD
6985     {
6986       if (!o->fit_pts || j >= o->num_fit_pts)
6987         {
6988           LOG_ERROR ("SPLINE.fit_pts[%d] overflow, max %d", j, o->num_fit_pts);
6989           return 1; // found
6990         }
6991       o->fit_pts[j].y = pair->value.d;
6992       return 1; // found
6993     }
6994   else if (pair->code == 31) // fit_pts[].z 3BD
6995     {
6996       if (!o->fit_pts || j >= o->num_fit_pts)
6997         {
6998           LOG_ERROR ("SPLINE.fit_pts[%d] overflow, max %d", j, o->num_fit_pts);
6999           return 1; // found
7000         }
7001       o->fit_pts[j].z = pair->value.d;
7002       LOG_TRACE ("SPLINE.fit_pts[%d] = (%f, %f, %f) [3BD* 11]\n", *jp,
7003                  o->fit_pts[j].x, o->fit_pts[j].y, o->fit_pts[j].z);
7004       j++;
7005       *jp = j;
7006       if (j == (int)o->num_fit_pts)
7007         *jp = 0;
7008       return 1; // found
7009     }
7010   return 0;
7011 }
7012 
7013 static int
add_MLINE(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair,int * restrict jp,int * restrict kp,int * restrict lp)7014 add_MLINE (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
7015            Dxf_Pair *restrict pair, int *restrict jp, int *restrict kp,
7016            int *restrict lp)
7017 {
7018   Dwg_Entity_MLINE *o = obj->tio.entity->tio.MLINE;
7019   int found = 1;
7020   int j = *jp;
7021   int k = *kp;
7022   int l = *lp;
7023 
7024   if (pair->code == 72)
7025     {
7026       o->num_verts = pair->value.i;
7027       o->parent = obj->tio.entity;
7028       o->verts = (Dwg_MLINE_vertex *)xcalloc (o->num_verts,
7029                                               sizeof (Dwg_MLINE_vertex));
7030       if (!o->verts)
7031         {
7032           o->num_verts = 0;
7033           return 0;
7034         }
7035       if (o->num_lines)
7036         {
7037           for (int _j = 0; _j < o->num_verts; _j++)
7038             {
7039               o->verts[_j].lines = (Dwg_MLINE_line *)xcalloc (
7040                   o->num_lines, sizeof (Dwg_MLINE_line));
7041               if (!o->verts[_j].lines)
7042                 {
7043                   o->num_lines = 0;
7044                   return 2;
7045                 }
7046             }
7047         }
7048       LOG_TRACE ("MLINE.num_verts = %d [BS 72]\n", o->num_verts);
7049       *jp = 0;
7050     }
7051   else if (pair->code == 73)
7052     {
7053       o->num_lines = pair->value.i;
7054       if (o->num_verts && !o->verts[0].lines)
7055         {
7056           for (int _j = 0; _j < o->num_verts; _j++)
7057             {
7058               o->verts[_j].lines = (Dwg_MLINE_line *)xcalloc (
7059                   o->num_lines, sizeof (Dwg_MLINE_line));
7060               if (!o->verts[_j].lines)
7061                 {
7062                   o->num_lines = 0;
7063                   return 2;
7064                 }
7065             }
7066         }
7067       LOG_TRACE ("MLINE.num_lines = %d [BS 73]\n", o->num_lines);
7068       *kp = 0;
7069     }
7070   else if (pair->code == 11 && o->num_verts)
7071     {
7072 
7073 #define CHK_verts                                                             \
7074   if (!o->verts || j < 0 || j >= o->num_verts)                                \
7075     {                                                                         \
7076       LOG_ERROR ("MLINE.verts[%d] out of bounds", j);                         \
7077       return 2;                                                               \
7078     }                                                                         \
7079   assert (o->verts);                                                          \
7080   assert (j >= 0);                                                            \
7081   assert (j < o->num_verts)
7082 
7083       CHK_verts;
7084       o->verts[j].parent = o;
7085       o->verts[j].vertex.x = pair->value.d;
7086     }
7087   else if (pair->code == 21 && o->num_verts)
7088     {
7089       CHK_verts;
7090       o->verts[j].vertex.y = pair->value.d;
7091     }
7092   else if (pair->code == 31 && o->num_verts)
7093     {
7094       CHK_verts;
7095       o->verts[j].vertex.z = pair->value.d;
7096       LOG_TRACE ("MLINE.verts[%d] = (%f, %f, %f) [3BD* 11]\n", j,
7097                  o->verts[j].vertex.x, o->verts[j].vertex.y,
7098                  o->verts[j].vertex.z);
7099     }
7100   else if (pair->code == 12 && o->num_verts)
7101     {
7102       CHK_verts;
7103       o->verts[j].vertex_direction.x = pair->value.d;
7104     }
7105   else if (pair->code == 22 && o->num_verts)
7106     {
7107       CHK_verts;
7108       o->verts[j].vertex_direction.y = pair->value.d;
7109     }
7110   else if (pair->code == 32 && o->num_verts)
7111     {
7112       CHK_verts;
7113       o->verts[j].vertex_direction.z = pair->value.d;
7114       LOG_TRACE ("MLINE.vertex_direction[%d] = (%f, %f, %f) [3BD* 12]\n", j,
7115                  o->verts[j].vertex_direction.x,
7116                  o->verts[j].vertex_direction.y,
7117                  o->verts[j].vertex_direction.z);
7118     }
7119   else if (pair->code == 13 && o->num_verts)
7120     {
7121       CHK_verts;
7122       o->verts[j].miter_direction.x = pair->value.d;
7123     }
7124   else if (pair->code == 23 && o->num_verts)
7125     {
7126       CHK_verts;
7127       o->verts[j].miter_direction.y = pair->value.d;
7128     }
7129   else if (pair->code == 33 && o->num_verts)
7130     {
7131       CHK_verts;
7132       o->verts[j].miter_direction.z = pair->value.d;
7133       LOG_TRACE ("MLINE.miter_direction[%d] = (%f, %f, %f) [3BD* 13]\n", j,
7134                  o->verts[j].miter_direction.x, o->verts[j].miter_direction.y,
7135                  o->verts[j].miter_direction.z);
7136       // if (j != o->num_verts - 1)
7137       //  j++; // not the last
7138       *kp = 0;
7139     }
7140   else if (pair->code == 74 && o->num_lines)
7141     {
7142       CHK_verts;
7143 
7144 #define CHK_lines                                                             \
7145   if (k < 0 || k >= (int)o->num_lines || !o->verts[j].lines)                  \
7146     {                                                                         \
7147       LOG_ERROR ("MLINE.verts[%d].lines[%d] out of bounds", j, k);            \
7148       return 2;                                                               \
7149     }                                                                         \
7150   assert (o->verts[j].lines);                                                 \
7151   assert (k >= 0 && k < (int)o->num_lines)
7152 
7153       CHK_lines;
7154       o->verts[j].lines[k].parent = &o->verts[j];
7155       o->verts[j].lines[k].num_segparms = pair->value.i;
7156       o->verts[j].lines[k].segparms
7157           = (BITCODE_BD *)xcalloc (pair->value.i, sizeof (BITCODE_BD));
7158       if (!o->verts[j].lines[k].segparms)
7159         {
7160           o->verts[j].lines[k].num_segparms = 0;
7161           return 2;
7162         }
7163       LOG_TRACE ("MLINE.v[%d].l[%d].num_segparms = %d [BS 74]\n", j, k,
7164                  pair->value.i);
7165       *lp = 0;
7166     }
7167   else if (pair->code == 41 && o->num_lines)
7168     {
7169       CHK_verts;
7170       CHK_lines;
7171       if (l < 0 || l >= o->verts[j].lines[k].num_segparms
7172           || !o->verts[j].lines[k].segparms)
7173         return 2;
7174       assert (l >= 0);
7175       assert (o->verts[j].lines);
7176       assert (l < o->verts[j].lines[k].num_segparms);
7177 
7178       o->verts[j].lines[k].segparms[l] = pair->value.d;
7179       LOG_TRACE ("MLINE.v[%d].l[%d].segparms[%d] = %f [BD 41]\n", j, k, l,
7180                  pair->value.d);
7181       l++;
7182       *lp = l;
7183     }
7184   else if (pair->code == 75 && o->num_lines)
7185     {
7186       CHK_verts;
7187       CHK_lines;
7188       o->verts[j].lines[k].num_areafillparms = pair->value.i;
7189       LOG_TRACE ("MLINE.v[%d].l[%d].num_areafillparms = %d [BS 75]\n", j, k,
7190                  pair->value.i);
7191       if (!pair->value.i)
7192         {
7193           k++; // next line
7194           if (k == o->num_lines)
7195             {
7196               j++; // next vertex
7197               *jp = j;
7198               k = 0;
7199             }
7200           *kp = k;
7201         }
7202       *lp = 0;
7203     }
7204   else if (pair->code == 42 && o->num_lines)
7205     {
7206       CHK_verts;
7207       CHK_lines;
7208       if (l < 0 || l >= o->verts[j].lines[k].num_areafillparms
7209           || !o->verts[j].lines[k].areafillparms)
7210         return 2;
7211       assert (l >= 0);
7212       assert (l < o->verts[j].lines[k].num_areafillparms);
7213 
7214       o->verts[j].lines[k].areafillparms[l] = pair->value.d;
7215       LOG_TRACE ("MLINE.v[%d].l[%d].areafillparms[%d] = %f [BD 42]\n", j, k, l,
7216                  pair->value.d);
7217       l++;
7218       *lp = l;
7219       if (l == o->verts[j].lines[k].num_areafillparms)
7220         {
7221           l = 0;
7222           *lp = l;
7223           k++; // next line
7224           if (k == o->num_lines)
7225             {
7226               j++; // next vertex
7227               *jp = j;
7228               k = 0;
7229             }
7230           *kp = k;
7231         }
7232     }
7233   else
7234     found = 0;
7235 
7236   return found;
7237 }
7238 
7239 #undef CHK_verts
7240 #undef CHK_lines
7241 
7242 static Dxf_Pair *
add_AcDbEvalExpr(Dwg_Object * restrict obj,char * _obj,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7243 add_AcDbEvalExpr (Dwg_Object *restrict obj, char *_obj,
7244                   Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7245 {
7246   Dwg_EvalExpr *ee;
7247   const char *const evalexpr = "evalexpr";
7248   Dwg_Data *dwg = obj->parent;
7249   const Dwg_DYNAPI_field *f1 = dwg_dynapi_entity_field (obj->name, evalexpr);
7250   if (!f1)
7251     return pair;
7252   ee = (Dwg_EvalExpr *)&(_obj)[f1->offset];
7253   ee->parentid = -1;
7254   while (pair && pair->code != 100)
7255     {
7256       if (pair->code == 90)
7257         {
7258           ee->nodeid = pair->value.u;
7259           LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", obj->name, evalexpr, "nodeid",
7260                      pair->value.u, pair->code);
7261         }
7262       else if (pair->code == 98)
7263         {
7264           ee->minor = pair->value.u;
7265           LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", obj->name, evalexpr, "major",
7266                      pair->value.u, pair->code);
7267         }
7268       else if (pair->code == 99)
7269         {
7270           ee->minor = pair->value.u;
7271           LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", obj->name, evalexpr, "minor",
7272                      pair->value.u, pair->code);
7273         }
7274       else if (pair->code == 70 && !ee->value_code)
7275         {
7276           ee->value_code = pair->value.i;
7277           LOG_TRACE ("%s.%s.%s = %d [BSd %d]\n", obj->name, evalexpr,
7278                      "value_code", pair->value.i, pair->code);
7279         }
7280       else if (pair->code == 40 || pair->code == 140)
7281         {
7282           ee->value.num40 = pair->value.d;
7283           LOG_TRACE ("%s.%s.%s = %f [BD %d]\n", obj->name, evalexpr,
7284                      "value.num40", pair->value.d, pair->code);
7285         }
7286       else if (pair->code == 10)
7287         {
7288           ee->value.pt2d.x = pair->value.d;
7289         }
7290       else if (pair->code == 20)
7291         {
7292           ee->value.pt2d.y = pair->value.d;
7293           LOG_TRACE ("%s.%s.%s = (%f, %f) [2RD %d]\n", obj->name, evalexpr,
7294                      "value.pt2d", ee->value.pt2d.x, pair->value.d,
7295                      pair->code);
7296         }
7297       else if (pair->code == 11)
7298         {
7299           ee->value.pt3d.x = pair->value.d;
7300         }
7301       else if (pair->code == 21)
7302         {
7303           ee->value.pt3d.y = pair->value.d;
7304         }
7305       else if (pair->code == 31)
7306         {
7307           ee->value.pt3d.z = pair->value.d;
7308           LOG_TRACE ("%s.%s.%s = (%f, %f, %f) [3RD %d]\n", obj->name, evalexpr,
7309                      "value.pt3d", ee->value.pt3d.x, ee->value.pt3d.y,
7310                      pair->value.d, pair->code);
7311         }
7312       else if (pair->code == 1)
7313         {
7314           ee->value.text1 = strdup (pair->value.s);
7315           LOG_TRACE ("%s.%s.%s = %s [T %d]\n", obj->name, evalexpr,
7316                      "value.text1", pair->value.s, pair->code);
7317         }
7318       else if (pair->code == 70 && ee->value_code)
7319         {
7320           ee->value.short70 = pair->value.i;
7321           LOG_TRACE ("%s.%s.%s = %d [BSd %d]\n", obj->name, evalexpr,
7322                      "value.short70", pair->value.i, pair->code);
7323         }
7324       else if (pair->code == 91)
7325         {
7326           ee->value.handle91 = dwg_add_handleref (dwg, 5, pair->value.u, obj);
7327           LOG_TRACE ("%s.%s.%s = " FORMAT_REF " [H %d]\n", obj->name, evalexpr,
7328                      "value.handle91", ARGS_REF (ee->value.handle91),
7329                      pair->code);
7330         }
7331       else
7332         {
7333           LOG_ERROR ("Invalid DXF code %d for %s", pair->code, "AcDbEvalExpr")
7334           return pair;
7335         }
7336       dxf_free_pair (pair);
7337       pair = dxf_read_pair (dat);
7338     }
7339   return pair;
7340 }
7341 
7342 // starts with T 300
7343 // returns NULL on success
7344 static Dxf_Pair *
add_AcDbBlockElement(Dwg_Object * restrict obj,char * o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7345 add_AcDbBlockElement (Dwg_Object *restrict obj, char *o,
7346                       Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7347 {
7348   Dwg_Data *dwg = obj->parent;
7349   EXPECT_T_DXF ("name", 300);
7350   FIELD_BL (be_major, 98);
7351   FIELD_BL (be_minor, 99);
7352   FIELD_BL (eed1071, 1071);
7353   return NULL;
7354 }
7355 
7356 // starts with 100
7357 // returns NULL on success
7358 static Dxf_Pair *
add_AcDbBlockAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7359 add_AcDbBlockAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7360 {
7361   Dwg_Data *dwg = obj->parent;
7362   // all with the same offset
7363   Dwg_Object_BLOCKMOVEACTION *o = obj->tio.object->tio.BLOCKMOVEACTION;
7364   Dxf_Pair *pair;
7365 
7366   FIELD_BL (num_actions, 70);
7367   if (o->num_actions)
7368     {
7369       //FIELD_VECTOR (actions, BL, num_actions, 91);
7370       o->actions = (BITCODE_BL*)xcalloc (o->num_actions, sizeof (BITCODE_BL));
7371       if (!o->actions)
7372         return pair;
7373       for (unsigned i = 0; i < o->num_actions; i++)
7374         {
7375           pair = dxf_read_pair (dat);
7376           EXPECT_DXF (obj->name, o->actions[i], 91);
7377           o->actions[i] = pair->value.u;
7378           LOG_TRACE ("%s.actions[%d] = %u [BL 91]\n", obj->name, i,
7379                      o->actions[i]);
7380           dxf_free_pair (pair);
7381         }
7382     }
7383   FIELD_BL (num_deps, 71);
7384   //HANDLE_VECTOR (deps, num_deps, 5, 330);
7385   if (o->num_deps)
7386     {
7387       o->deps = (BITCODE_H*)xcalloc (o->num_deps, sizeof (BITCODE_H));
7388       if (!o->deps)
7389         return pair;
7390       for (unsigned i = 0; i < o->num_deps; i++)
7391         {
7392           pair = dxf_read_pair (dat);
7393           EXPECT_DXF (obj->name, o->deps[i], 330);
7394           o->deps[i] = dwg_add_handleref (dwg, 5, pair->value.u, obj);
7395           LOG_TRACE ("%s.deps[%d] = " FORMAT_REF " [H 330]\n", obj->name, i,
7396                      ARGS_REF (o->deps[i]));
7397           dxf_free_pair (pair);
7398         }
7399     }
7400   FIELD_3BD (display_location, 1010);
7401   return NULL;
7402 }
7403 
7404 // returns NULL on success
7405 static Dxf_Pair *
add_BlockAction_ConnectionPts(Dwg_Object * restrict obj,Bit_Chain * restrict dat,const int first,const int repeat,const int bl_code,const int t_code)7406 add_BlockAction_ConnectionPts (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
7407                                const int first, const int repeat,
7408                                const int bl_code, const int t_code)
7409 {
7410   Dwg_Data *dwg = obj->parent;
7411   Dwg_Object_BLOCKFLIPACTION *o = obj->tio.object->tio.BLOCKFLIPACTION;
7412   Dxf_Pair *pair;
7413   Dwg_BLOCKACTION_connectionpts conn_pts[6];
7414   const char *const field = "conn_pts";
7415   const Dwg_DYNAPI_field *f = dwg_dynapi_entity_field (obj->name, field);
7416 
7417   if (!f)
7418     return (Dxf_Pair *)-1;
7419   if (first)
7420     dwg_dynapi_field_get_value (o, f, &conn_pts);
7421   for (int i = first; i < (first + repeat); i++)
7422     {
7423       pair = dxf_read_pair (dat);
7424       EXPECT_DXF (obj->name, "conn_pts[i].code", bl_code + i - first);
7425       conn_pts[i].code = pair->value.u;
7426       LOG_TRACE ("%s.conn_pts[%d].code = %u [BL %d]\n", obj->name, i,
7427                  pair->value.u, bl_code + i - first);
7428       dxf_free_pair (pair);
7429     }
7430 
7431   for (int i = first; i < (first + repeat); i++)
7432     {
7433       pair = dxf_read_pair (dat);
7434       EXPECT_DXF (obj->name, "conn_pts[].name", t_code + i - first);
7435       conn_pts[i].name = strdup (pair->value.s);
7436       LOG_TRACE ("%s.conn_pts[%d].name = %s [BL %d]\n", obj->name, i,
7437                  pair->value.s, t_code + i - first);
7438       dxf_free_pair (pair);
7439     }
7440   // memcpy'ing back the content
7441   dwg_dynapi_field_set_value (dwg, o, f, &conn_pts, 0);
7442   return NULL;
7443 }
7444 
7445 // returns NULL on success
7446 static Dxf_Pair *
add_AcDbBlockActionWithBasePt(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7447 add_AcDbBlockActionWithBasePt (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7448 {
7449   Dwg_Data *dwg = obj->parent;
7450   Dwg_Object_BLOCKROTATEACTION *o = obj->tio.object->tio.BLOCKROTATEACTION;
7451   Dxf_Pair *pair;
7452   pair = add_BlockAction_ConnectionPts (obj, dat, 0, 2, 92, 301);
7453   if (pair)
7454     return pair;
7455   FIELD_3BD (offset, 1011);
7456   FIELD_B (dependent, 280);
7457   FIELD_3BD (base_pt, 1012);
7458   return NULL;
7459 }
7460 
7461 // starts with 100
7462 // returns NULL on success
7463 static Dxf_Pair *
add_AcDbBlockFlipAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7464 add_AcDbBlockFlipAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7465 {
7466   Dwg_Data *dwg = obj->parent;
7467   Dxf_Pair *pair;
7468   pair = add_BlockAction_ConnectionPts (obj, dat, 0, 4, 92, 301);
7469   if (pair)
7470     return pair;
7471   return NULL;
7472 }
7473 
7474 // starts with 100
7475 // returns NULL on success
7476 static Dxf_Pair *
add_AcDbBlockRotationAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7477 add_AcDbBlockRotationAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7478 {
7479   Dwg_Data *dwg = obj->parent;
7480   Dxf_Pair *pair;
7481   pair = add_BlockAction_ConnectionPts (obj, dat, 2, 1, 94, 303);
7482   if (pair)
7483     return pair;
7484   return NULL;
7485 }
7486 
7487 // starts with 100
7488 // returns NULL on success
7489 static Dxf_Pair *
add_AcDbBlockScaleAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7490 add_AcDbBlockScaleAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7491 {
7492   Dwg_Data *dwg = obj->parent;
7493   Dxf_Pair *pair;
7494   pair = add_BlockAction_ConnectionPts (obj, dat, 2, 3, 94, 303);
7495   if (pair)
7496     return pair;
7497   return NULL;
7498 }
7499 
7500 // starts with 100
7501 // returns NULL on success
7502 static Dxf_Pair *
add_AcDbBlockMoveAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7503 add_AcDbBlockMoveAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7504 {
7505   Dwg_Data *dwg = obj->parent;
7506   Dwg_Object_BLOCKMOVEACTION *o = obj->tio.object->tio.BLOCKMOVEACTION;
7507   Dxf_Pair *pair;
7508 
7509   pair = dxf_read_pair (dat);
7510   EXPECT_DXF (obj->name, conn_pts[0].code, 92);
7511   o->conn_pts[0].code = pair->value.u;
7512   dxf_free_pair (pair);
7513   pair = dxf_read_pair (dat);
7514   EXPECT_DXF (obj->name, conn_pts[0].name, 301);
7515   o->conn_pts[0].name = strdup (pair->value.s);
7516   LOG_TRACE ("%s.conn_pts[0] = (%u, %s)\n", obj->name,
7517              o->conn_pts[0].code, o->conn_pts[0].name);
7518   dxf_free_pair (pair);
7519   pair = dxf_read_pair (dat);
7520   EXPECT_DXF (obj->name, conn_pts[0].code, 93);
7521   o->conn_pts[1].code = pair->value.u;
7522   dxf_free_pair (pair);
7523   pair = dxf_read_pair (dat);
7524   EXPECT_DXF (obj->name, conn_pts[0].name, 302);
7525   o->conn_pts[1].name = strdup (pair->value.s);
7526   LOG_TRACE ("%s.conn_pts[1] = (%u, %s)\n", obj->name,
7527              o->conn_pts[1].code, o->conn_pts[1].name);
7528   dxf_free_pair (pair);
7529 
7530   // AcDbBlockAction_doubles
7531   FIELD_BD (action_offset_x, 140);
7532   FIELD_BD (action_offset_y, 141);
7533   FIELD_BD (angle_offset, 0);
7534   /* VALUE_RC (1, 280); Action XY type. 1? */
7535   pair = dxf_read_pair (dat);
7536   dxf_free_pair (pair);
7537   return NULL;
7538 }
7539 
7540 // starts with 100
7541 // returns NULL on success
7542 static Dxf_Pair *
add_AcDbBlockStretchAction(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7543 add_AcDbBlockStretchAction (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7544 {
7545   Dwg_Data *dwg = obj->parent;
7546   Dwg_Object_BLOCKSTRETCHACTION *o = obj->tio.object->tio.BLOCKSTRETCHACTION;
7547   Dxf_Pair *pair;
7548 
7549   pair = dxf_read_pair (dat);
7550   EXPECT_DXF (obj->name, conn_pts[0].code, 92);
7551   o->conn_pts[0].code = pair->value.u;
7552   dxf_free_pair (pair);
7553   pair = dxf_read_pair (dat);
7554   EXPECT_DXF (obj->name, conn_pts[0].name, 301);
7555   o->conn_pts[0].name = strdup (pair->value.s);
7556   LOG_TRACE ("%s.conn_pts[0] = (%u, %s)\n", obj->name,
7557              o->conn_pts[0].code, o->conn_pts[0].name);
7558   dxf_free_pair (pair);
7559   pair = dxf_read_pair (dat);
7560   EXPECT_DXF (obj->name, conn_pts[0].code, 93);
7561   o->conn_pts[1].code = pair->value.u;
7562   dxf_free_pair (pair);
7563   pair = dxf_read_pair (dat);
7564   EXPECT_DXF (obj->name, conn_pts[0].name, 302);
7565   o->conn_pts[1].name = strdup (pair->value.s);
7566   LOG_TRACE ("%s.conn_pts[1] = (%u, %s)\n", obj->name,
7567              o->conn_pts[1].code, o->conn_pts[1].name);
7568   dxf_free_pair (pair);
7569 
7570   FIELD_BL (num_pts, 72);
7571   //FIELD_2RD_VECTOR (pts, num_pts, 10);
7572   if (o->num_pts)
7573     {
7574       o->pts = (BITCODE_2RD*)xcalloc (o->num_pts, sizeof (BITCODE_2RD));
7575       if (!o->pts)
7576         return pair;
7577       for (unsigned i = 0; i < o->num_pts; i++)
7578         {
7579           pair = dxf_read_pair (dat);
7580           EXPECT_DXF (obj->name, o->pts[i], 1011);
7581           o->pts[i].x = pair->value.d;
7582           dxf_free_pair (pair);
7583 
7584           pair = dxf_read_pair (dat);
7585           EXPECT_DXF (obj->name, o->pts[i], 1021);
7586           o->pts[i].y = pair->value.d;
7587           dxf_free_pair (pair);
7588           LOG_TRACE ("%s.pts[%d] = (%f, %f) [2RD 1011]\n", obj->name, i,
7589                      o->pts[i].x, o->pts[i].y);
7590         }
7591     }
7592   FIELD_BL (num_hdls, 73);
7593   // TODO one struct
7594   //HANDLE_VECTOR (hdls, num_hdls, 0, 331);
7595   if (o->num_hdls)
7596     {
7597       o->hdls = (BITCODE_H*)xcalloc (o->num_hdls, sizeof (BITCODE_H));
7598       if (!o->hdls)
7599         return pair;
7600       for (unsigned i = 0; i < o->num_hdls; i++)
7601         {
7602           pair = dxf_read_pair (dat);
7603           EXPECT_DXF (obj->name, o->hdls[i], 331);
7604           o->hdls[i] = dwg_add_handleref (dwg, 5, pair->value.u, obj);
7605           LOG_TRACE ("%s.hdls[%d] = " FORMAT_REF " [H 331]\n", obj->name, i,
7606                      ARGS_REF (o->hdls[i]));
7607           dxf_free_pair (pair);
7608         }
7609       //FIELD_VECTOR (shorts, BS, num_hdls, 74);
7610       o->shorts = (BITCODE_BS*)xcalloc (o->num_hdls, sizeof (BITCODE_BS));
7611       if (!o->shorts)
7612         return pair;
7613       for (unsigned i = 0; i < o->num_hdls; i++)
7614         {
7615           pair = dxf_read_pair (dat);
7616           EXPECT_DXF (obj->name, o->shorts[i], 74);
7617           o->shorts[i] = pair->value.i;
7618           LOG_TRACE ("%s.shorts[%d] = %u [BS 74]\n", obj->name, i,
7619                      (unsigned)o->shorts[i]);
7620           dxf_free_pair (pair);
7621         }
7622     }
7623 
7624   FIELD_BL (num_codes, 75);
7625   // FIXME 3x BL?
7626   //FIELD_VECTOR (codes, BL, num_codes, 76);
7627   if (o->num_codes)
7628     {
7629       o->codes = (BITCODE_BL*)xcalloc (o->num_codes, sizeof (BITCODE_BL));
7630       if (!o->codes)
7631         return pair;
7632       for (unsigned i = 0; i < o->num_pts; i++)
7633         {
7634           pair = dxf_read_pair (dat);
7635           EXPECT_DXF (obj->name, o->codes[i], 76);
7636           o->codes[i] = pair->value.i;
7637           LOG_TRACE ("%s.codes[%d] = %d [BL 76]\n", obj->name, i,
7638                      o->codes[i]);
7639           dxf_free_pair (pair);
7640         }
7641     }
7642 
7643   // AcDbBlockAction_doubles
7644   FIELD_BD (action_offset_x, 140);
7645   FIELD_BD (action_offset_y, 141);
7646   FIELD_BD (angle_offset, 0);
7647   /* VALUE_RC (1, 280); Action XY type. 1? */
7648   pair = dxf_read_pair (dat);
7649   dxf_free_pair (pair);
7650   return NULL;
7651 }
7652 
7653 // starts with BL 91
7654 // returns NULL on success
7655 static Dxf_Pair *
add_AcDbBlockGrip(Dwg_Object * restrict obj,char * o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7656 add_AcDbBlockGrip (Dwg_Object *restrict obj, char *o,
7657                    Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7658 {
7659   Dwg_Data *dwg = obj->parent;
7660   EXPECT_INT_DXF ("bg_bl91", 91, BL);
7661   FIELD_BL (bg_bl92, 92);
7662   FIELD_3BD (bg_location, 1010);
7663   FIELD_B (bg_insert_cycling, 280);
7664   FIELD_BLd (bg_insert_cycling_weight, 93);
7665   return NULL;
7666 }
7667 
7668 // starts with BL 93
7669 // returns NULL on success
7670 static Dxf_Pair *
add_AcDbBlockVisibilityParameter(Dwg_Object * restrict obj,Dwg_Object_BLOCKVISIBILITYPARAMETER * o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7671 add_AcDbBlockVisibilityParameter (Dwg_Object *restrict obj,
7672                                   Dwg_Object_BLOCKVISIBILITYPARAMETER *o,
7673                                   Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7674 {
7675   Dwg_Data *dwg = obj->parent;
7676   EXPECT_INT_DXF ("num_blocks", 93, BL);
7677   if (o->num_blocks)
7678     {
7679       o->blocks = (BITCODE_H*)xcalloc (o->num_blocks, sizeof (BITCODE_H));
7680       if (!o->blocks)
7681         return pair;
7682       for (unsigned i = 0; i < o->num_blocks; i++)
7683         {
7684           pair = dxf_read_pair (dat);
7685           EXPECT_DXF (obj->name, o->blocks[i], 331);
7686           o->blocks[i] = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
7687           LOG_TRACE ("%s.blocks[%d] = " FORMAT_REF " [H 331]\n", obj->name, i,
7688                      ARGS_REF (o->blocks[i]));
7689           dxf_free_pair (pair);
7690         }
7691     }
7692 
7693   FIELD_BL (num_states, 92);
7694   if (o->num_states)
7695     {
7696       o->states = (Dwg_BLOCKVISIBILITYPARAMETER_state*)xcalloc (o->num_states,
7697                      sizeof (Dwg_BLOCKVISIBILITYPARAMETER_state));
7698       if (!o->states)
7699         return pair;
7700       for (unsigned i = 0; i < o->num_states; i++)
7701         {
7702           pair = dxf_read_pair (dat);
7703           EXPECT_DXF (obj->name, o->states[i].name, 303);
7704           o->states[i].name = strdup (pair->value.s);
7705           LOG_TRACE ("%s.states[%d].name = %s [T 303]\n", obj->name, i, o->states[i].name);
7706           dxf_free_pair (pair);
7707 
7708           pair = dxf_read_pair (dat);
7709           EXPECT_DXF (obj->name, o->states[i].num_blocks, 94);
7710           o->states[i].num_blocks = pair->value.u;
7711           LOG_TRACE ("%s.states[%d].num_blocks = %u [BL 94]\n", obj->name, i,
7712                      o->states[i].num_blocks);
7713           dxf_free_pair (pair);
7714 
7715           if (o->states[i].num_blocks)
7716             {
7717               o->states[i].blocks = (BITCODE_H*)xcalloc (o->states[i].num_blocks,
7718                                         sizeof (BITCODE_H));
7719               if (!o->states[i].blocks)
7720                 return pair;
7721               for (unsigned j = 0; j < o->states[i].num_blocks; j++)
7722                 {
7723                   pair = dxf_read_pair (dat);
7724                   EXPECT_DXF (obj->name, o->states[i].blocks[j], 332);
7725                   o->states[i].blocks[j]
7726                       = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
7727                   LOG_TRACE (
7728                       "%s.states[%d].blocks[%d] = " FORMAT_REF " [H 332]\n",
7729                       obj->name, i, j, ARGS_REF (o->states[i].blocks[j]));
7730                   dxf_free_pair (pair);
7731                 }
7732             }
7733 
7734           pair = dxf_read_pair (dat);
7735           EXPECT_DXF (obj->name, o->states[i].num_params, 95);
7736           o->states[i].num_params = pair->value.u;
7737           LOG_TRACE ("%s.states[%d].num_params = %u [BL 95]\n", obj->name, i,
7738                      o->states[i].num_params);
7739           dxf_free_pair (pair);
7740 
7741           if (o->states[i].num_params)
7742             {
7743               o->states[i].params = (BITCODE_H*)xcalloc (o->states[i].num_params,
7744                                                          sizeof (BITCODE_H));
7745               if (!o->states[i].params)
7746                 return pair;
7747               for (unsigned j = 0; j < o->states[i].num_params; j++)
7748                 {
7749                   pair = dxf_read_pair (dat);
7750                   EXPECT_DXF (obj->name, o->states[i].params[j], 333);
7751                   o->states[i].params[j]
7752                       = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
7753                   LOG_TRACE (
7754                       "%s.states[%d].params[%d] = " FORMAT_REF " [H 333]\n",
7755                       obj->name, i, j, ARGS_REF (o->states[i].params[j]));
7756                   dxf_free_pair (pair);
7757                 }
7758             }
7759         }
7760     }
7761   return NULL;
7762 }
7763 
7764 // starts empty
7765 // returns NULL on success
7766 static Dxf_Pair *
add_BlockParam_PropInfo(Dwg_Object * restrict obj,Bit_Chain * restrict dat,Dwg_BLOCKPARAMETER_PropInfo * prop,const int i,const int num_code,const int d_code,const int t_code)7767 add_BlockParam_PropInfo (Dwg_Object *restrict obj, Bit_Chain *restrict dat,
7768                          Dwg_BLOCKPARAMETER_PropInfo *prop, const int i,
7769                          const int num_code, const int d_code, const int t_code)
7770 {
7771   Dwg_Data *dwg = obj->parent;
7772   Dxf_Pair *pair;
7773 
7774   pair = dxf_read_pair (dat);
7775   EXPECT_DXF (obj->name, prop->num_connections, num_code);
7776   prop->num_connections = pair->value.u;
7777   LOG_TRACE ("%s.prop%d.num_connections = %u [BL %d]\n", obj->name, i,
7778              pair->value.u, num_code);
7779   dxf_free_pair (pair);
7780   if (prop->num_connections)
7781     {
7782       prop->connections = (Dwg_BLOCKPARAMETER_connection *)xcalloc (
7783           prop->num_connections, sizeof (Dwg_BLOCKPARAMETER_connection));
7784       if (!prop->connections)
7785         return pair;
7786       for (unsigned j = 0; j < prop->num_connections; j++)
7787         {
7788           pair = dxf_read_pair (dat);
7789           EXPECT_DXF (obj->name, prop->connections[j].code, d_code);
7790           prop->connections[j].code = pair->value.u;
7791           LOG_TRACE ("%s.prop[%d].connections[%u].code = %u [BL %d]\n", obj->name, i, j,
7792                      pair->value.u, d_code);
7793           dxf_free_pair (pair);
7794 
7795           pair = dxf_read_pair (dat);
7796           EXPECT_DXF (obj->name, prop->connections[j].name, t_code);
7797           prop->connections[j].name = strdup (pair->value.s);
7798           LOG_TRACE ("%s.prop[%d].connections[%u].name = %s [T %d]\n", obj->name, i, j,
7799                      pair->value.s, t_code);
7800           dxf_free_pair (pair);
7801         }
7802     }
7803   return NULL;
7804 }
7805 
7806 // starts empty (on 100 . subclass)
7807 // returns NULL on success
7808 static Dxf_Pair *
add_AcDbBlock1PtParameter(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7809 add_AcDbBlock1PtParameter (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7810 {
7811   Dwg_Object_BLOCKBASEPOINTPARAMETER *o = obj->tio.object->tio.BLOCKBASEPOINTPARAMETER;
7812   Dwg_Data *dwg = obj->parent;
7813   Dxf_Pair * pair;
7814 
7815   pair = dxf_read_pair (dat);
7816   EXPECT_DXF (obj->name, "def_pt.x", 1010);
7817   o->def_pt.x = pair->value.d;
7818   dxf_free_pair (pair);
7819   pair = dxf_read_pair (dat);
7820   EXPECT_DXF (obj->name, "def_pt.y", 1020);
7821   o->def_pt.y = pair->value.d;
7822   dxf_free_pair (pair);
7823   pair = dxf_read_pair (dat);
7824   EXPECT_DXF (obj->name, "def_pt.z", 1030);
7825   o->def_pt.z = pair->value.d;
7826   LOG_TRACE ("%s.def_pt = (%f, %f, %f) [3BD 1010]\n", obj->name, o->def_pt.x,
7827              o->def_pt.y, pair->value.d);
7828   dxf_free_pair (pair);
7829 
7830   pair = dxf_read_pair (dat);
7831   EXPECT_DXF (obj->name, "num_propinfos", 93); // 2
7832   o->num_propinfos = pair->value.u;
7833   LOG_TRACE ("%s.num_propinfos = %u [BL 93]\n", obj->name, pair->value.u);
7834   dxf_free_pair (pair);
7835 
7836   pair = add_BlockParam_PropInfo (obj, dat, &o->prop1, 1, 170, 91, 301);
7837   if (pair)
7838     return pair;
7839   pair = add_BlockParam_PropInfo (obj, dat, &o->prop2, 2, 171, 92, 302);
7840   if (pair)
7841     return pair;
7842 
7843   return NULL;
7844 }
7845 
7846 // starts empty (on 100 . subclass)
7847 // returns NULL on success
7848 static Dxf_Pair *
add_AcDbBlock2PtParameter(Dwg_Object * restrict obj,Bit_Chain * restrict dat)7849 add_AcDbBlock2PtParameter (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
7850 {
7851   Dwg_Object_BLOCKALIGNMENTPARAMETER *o = obj->tio.object->tio.BLOCKALIGNMENTPARAMETER;
7852   Dwg_Data *dwg = obj->parent;
7853   Dxf_Pair * pair;
7854 
7855   pair = dxf_read_pair (dat);
7856   EXPECT_DXF (obj->name, "def_basept.x", 1010);
7857   o->def_basept.x = pair->value.d;
7858   dxf_free_pair (pair);
7859   pair = dxf_read_pair (dat);
7860   EXPECT_DXF (obj->name, "def_basept.y", 1020);
7861   o->def_basept.y = pair->value.d;
7862   dxf_free_pair (pair);
7863   pair = dxf_read_pair (dat);
7864   EXPECT_DXF (obj->name, "def_basept.z", 1030);
7865   o->def_basept.z = pair->value.d;
7866   LOG_TRACE ("%s.def_basept = (%f, %f, %f) [3BD 1010]\n", obj->name, o->def_basept.x,
7867              o->def_basept.y, pair->value.d);
7868   dxf_free_pair (pair);
7869 
7870   pair = dxf_read_pair (dat);
7871   EXPECT_DXF (obj->name, "def_endpt.x", 1011);
7872   o->def_endpt.x = pair->value.d;
7873   dxf_free_pair (pair);
7874   pair = dxf_read_pair (dat);
7875   EXPECT_DXF (obj->name, "def_endpt.y", 1021);
7876   o->def_endpt.y = pair->value.d;
7877   dxf_free_pair (pair);
7878   pair = dxf_read_pair (dat);
7879   EXPECT_DXF (obj->name, "def_endpt.z", 1031);
7880   o->def_endpt.z = pair->value.d;
7881   LOG_TRACE ("%s.def_endpt = (%f, %f, %f) [3BD 1011]\n", obj->name, o->def_endpt.x,
7882              o->def_endpt.y, pair->value.d);
7883   dxf_free_pair (pair);
7884 
7885   pair = dxf_read_pair (dat);
7886   EXPECT_DXF (obj->name, "num_prop_states", 170);
7887   LOG_TRACE ("%s.num_prop_states = %d [BL 170]\n", obj->name, pair->value.u);
7888   dxf_free_pair (pair);
7889   o->prop_states = (BITCODE_BL *)xcalloc (4, sizeof (BITCODE_BL));
7890   if (!o->prop_states)
7891     return dxf_read_pair (dat);
7892   for (unsigned i = 0; i < 4; i++)
7893     {
7894       pair = dxf_read_pair (dat);
7895       EXPECT_DXF (obj->name, prop_states[i], 91);
7896       o->prop_states[i] = pair->value.u;
7897       LOG_TRACE ("%s.prop_states[%d] = %u [BL 91]\n", obj->name, i, pair->value.u);
7898       dxf_free_pair (pair);
7899     }
7900 
7901   pair = add_BlockParam_PropInfo (obj, dat, &o->prop1, 1, 171, 92, 301);
7902   if (pair)
7903     return pair;
7904   pair = add_BlockParam_PropInfo (obj, dat, &o->prop2, 2, 172, 93, 302);
7905   if (pair)
7906     return pair;
7907   pair = add_BlockParam_PropInfo (obj, dat, &o->prop3, 3, 173, 94, 303);
7908   if (pair)
7909     return pair;
7910   pair = add_BlockParam_PropInfo (obj, dat, &o->prop4, 4, 174, 95, 304);
7911   if (pair)
7912     return pair;
7913 
7914   FIELD_BS (parameter_base_location, 177);
7915   return NULL;
7916 }
7917 
7918 typedef int t_codes[4];
7919 
7920 // varying dxf codes per object
7921 // returns NULL on success
7922 static Dxf_Pair *
add_AcDbBlockParamValueSet(Dwg_Object * restrict obj,Dwg_BLOCKPARAMVALUESET * o,Bit_Chain * restrict dat,Dxf_Pair * restrict pair)7923 add_AcDbBlockParamValueSet (Dwg_Object *restrict obj, Dwg_BLOCKPARAMVALUESET *o,
7924                             Bit_Chain *restrict dat, Dxf_Pair *restrict pair)
7925 {
7926   Dwg_Data *dwg = obj->parent;
7927   // i_code, d_code, s_code, t_code
7928   const t_codes codes[] =
7929     {
7930      { 96, 128, 175, 307 }, // 0 AcDbBlock{Linear,Diametric,Radial,Angular}ConstraintParameter{,Entity}
7931      { 96, 141, 175, 307 }, // 1 BLOCKLINEARPARAMETER.value_set
7932      { 96, 141, 175, 307 }, // 2 BLOCKROTATIONPARAMETER.angle_value_set
7933      { 97, 146, 176, 309 }, // 3 BLOCKXYPARAMETER.y_value_set
7934      { 96, 142, 175, 410 }, // 4 BLOCKXYPARAMETER.x_value_set
7935      { 96, 142, 175, 410 }, // 5 BLOCKPOLARPARAMETER.angle_value_set
7936      { 97, 146, 176, 309 }, // 6 BLOCKPOLARPARAMETER.distance_value_set
7937     };
7938   const t_codes *code = &codes[0]; // AcDbBlock{Linear,Diametric,Radial,Angular}ConstraintParameter{,Entity}
7939 
7940   // T at first
7941   if (pair->code == 307)
7942     {
7943       if (strEQc (obj->name, "BLOCKLINEARPARAMETER"))
7944         code = &codes[1];
7945       else if (strEQc (obj->name, "BLOCKROTATIONPARAMETER"))
7946         code = &codes[2];
7947     }
7948   else if (pair->code == 309)
7949     {
7950       if (strEQc (obj->name, "BLOCKXYPARAMETER"))
7951         code = &codes[3];
7952       else if (strEQc (obj->name, "BLOCKPOLARPARAMETER"))
7953         code = &codes[6];
7954     }
7955   else if (pair->code == 410)
7956     {
7957       if (strEQc (obj->name, "BLOCKXYPARAMETER"))
7958         code = &codes[4];
7959       else if (strEQc (obj->name, "BLOCKPOLARPARAMETER"))
7960         code = &codes[5];
7961     }
7962   // subclass not object
7963   EXPECT_DXF ("BlockParamValueSet", "desc", (*code)[3]); // t_code
7964   o->desc = strdup (pair->value.s);
7965   LOG_TRACE ("%s.value_set.desc = \"%s\"\n", obj->name, pair->value.s);
7966   dxf_free_pair (pair);
7967 
7968   pair = dxf_read_pair (dat);
7969   EXPECT_DXF ("BlockParamValueSet", "flags", (*code)[0]); // i_code
7970   o->flags = pair->value.i;
7971   LOG_TRACE ("%s.value_set.flags = %d\n", obj->name, pair->value.i);
7972   dxf_free_pair (pair);
7973 
7974   pair = dxf_read_pair (dat);
7975   EXPECT_DXF ("BlockParamValueSet", "minimum", (*code)[1]); // d_code
7976   o->minimum = pair->value.d;
7977   LOG_TRACE ("%s.value_set.minimum = %f\n", obj->name, pair->value.d);
7978   dxf_free_pair (pair);
7979 
7980   pair = dxf_read_pair (dat);
7981   EXPECT_DXF ("BlockParamValueSet", "maximum", (*code)[1]+1);
7982   o->maximum = pair->value.d;
7983   LOG_TRACE ("%s.value_set.maximum = %f\n", obj->name, pair->value.d);
7984   dxf_free_pair (pair);
7985 
7986   pair = dxf_read_pair (dat);
7987   EXPECT_DXF ("BlockParamValueSet", "increment", (*code)[1]+2);
7988   o->increment = pair->value.d;
7989   LOG_TRACE ("%s.value_set.increment = %f\n", obj->name, pair->value.d);
7990   dxf_free_pair (pair);
7991 
7992   pair = dxf_read_pair (dat);
7993   EXPECT_DXF ("BlockParamValueSet", "num_valuelist", (*code)[2]); // s_code
7994   o->num_valuelist = pair->value.i;
7995   LOG_TRACE ("%s.value_set.num_valuelist = %d\n", obj->name, pair->value.i);
7996   dxf_free_pair (pair);
7997 
7998   //FIELD_VECTOR (valuelist, num_valuelist, BD, code[1]+3);
7999   if (!o->num_valuelist)
8000     return NULL;
8001   o->valuelist = (double *)xcalloc (o->num_valuelist, sizeof (double));
8002   if (!o->valuelist)
8003     return dxf_read_pair (dat);
8004 
8005   for (unsigned i = 0; i < o->num_valuelist; i++)
8006     {
8007       pair = dxf_read_pair (dat);
8008       EXPECT_DXF ("BLOCKPARAMVALUESET", valuelist[i], (*code)[1]+3);
8009       o->valuelist[i] = pair->value.d;
8010       LOG_TRACE ("%s.value_set.valuelist[%d] = %f [BD %d]\n", obj->name, i,
8011                  pair->value.d, pair->code);
8012       dxf_free_pair (pair);
8013     }
8014   return NULL;
8015 }
8016 
8017 // starts with 100
8018 // returns NULL on success
8019 static Dxf_Pair *
add_AcDbBlockRotationParameter(Dwg_Object * restrict obj,Bit_Chain * restrict dat)8020 add_AcDbBlockRotationParameter (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
8021 {
8022   Dwg_Data *dwg = obj->parent;
8023   Dwg_Object_BLOCKROTATIONPARAMETER *o = obj->tio.object->tio.BLOCKROTATIONPARAMETER;
8024   Dwg_BLOCKPARAMVALUESET *value_set = &o->angle_value_set;
8025   Dxf_Pair *pair;
8026 
8027   FIELD_T (angle_name, 305);
8028   FIELD_T (angle_desc, 306);
8029   FIELD_3BD (def_base_angle_pt, 1011);
8030   FIELD_BD (angle, 140);
8031   pair = dxf_read_pair (dat);
8032   EXPECT_DXF (obj->name, angle_value_set, 307);
8033   pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
8034   if (pair)
8035     return pair;
8036   return NULL;
8037 }
8038 
8039 #define FIELD_CMC(field, dxf)                                                 \
8040   dxf_read_CMC (dwg, dat, &o->field, #field, dxf)
8041 #define FIELD_CMC2004(field, dxf)                                             \
8042   SINCE (R_2004)                                                              \
8043     FIELD_CMC (field, dxf)
8044 
8045 // starts with 71 . 0
8046 // returns NULL on success
8047 static Dxf_Pair *
add_AcDbSectionViewStyle(Dwg_Object * restrict obj,Bit_Chain * restrict dat)8048 add_AcDbSectionViewStyle (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
8049 {
8050   Dwg_Data *dwg = obj->parent;
8051   Dwg_Object_SECTIONVIEWSTYLE *o = obj->tio.object->tio.SECTIONVIEWSTYLE;
8052   BITCODE_BD *av;
8053   // starting with 71 . 0 (skipped)
8054   Dxf_Pair *pair;
8055   FIELD_BL (flags, 90);
8056   pair = dxf_read_pair (dat);              // skip 71 . 1
8057   FIELD_HANDLE (identifier_style, 5, 340); // textstyle
8058   FIELD_CMC2004 (identifier_color, 62);
8059   FIELD_BD (identifier_height, 40); // 5.0
8060   FIELD_HANDLE (arrow_start_symbol, 5, 340);
8061   FIELD_HANDLE (arrow_end_symbol, 5, 340);
8062   FIELD_CMC2004 (arrow_symbol_color, 62);
8063   FIELD_BD (arrow_symbol_size, 40);
8064   FIELD_T (identifier_exclude_characters, 300); // I, O, Q, S, X, Z
8065   // 40 90 40 90 71
8066   FIELD_BD (arrow_symbol_extension_length, 40);
8067   FIELD_BLd (identifier_position, 90);
8068   FIELD_BD (identifier_offset, 40);
8069   FIELD_BLd (arrow_position, 90);
8070   pair = dxf_read_pair (dat);         // skip 71 . 2
8071   FIELD_HANDLE (plane_ltype, 5, 340); // ltype
8072   FIELD_BLd (plane_linewt, 90);
8073   FIELD_CMC2004 (plane_line_color, 62);
8074   FIELD_HANDLE (bend_ltype, 5, 340); // ltype
8075   FIELD_BLd (bend_linewt, 90);
8076   FIELD_CMC2004 (bend_line_color, 62);
8077   FIELD_BD (bend_line_length, 40);
8078   FIELD_BD (end_line_overshoot, 40);
8079   FIELD_BD (end_line_length, 40);
8080   pair = dxf_read_pair (dat);                  // skip 71 . 3
8081   FIELD_HANDLE (viewlabel_text_style, 5, 340); // textstyle
8082   FIELD_CMC2004 (viewlabel_text_color, 62);
8083   FIELD_BD (viewlabel_text_height, 40);
8084   FIELD_BL (viewlabel_attachment, 90);
8085   FIELD_BD (viewlabel_offset, 40); // 5.0
8086   FIELD_BL (viewlabel_alignment, 90);
8087   FIELD_T (viewlabel_pattern, 300);
8088   pair = dxf_read_pair (dat); // skip 71 . 4
8089   FIELD_CMC2004 (hatch_color, 62);
8090   FIELD_CMC2004 (hatch_bg_color, 62);
8091   FIELD_T (hatch_pattern, 300);
8092   FIELD_BD (hatch_scale, 40);
8093   FIELD_BLd (hatch_transparency, 90);
8094   FIELD_B (unknown_b1, 290);
8095   FIELD_B (unknown_b2, 290);
8096   FIELD_BL (num_hatch_angles, 90);
8097   if (o->num_hatch_angles)
8098     {
8099       o->hatch_angles = (BITCODE_BD *)xcalloc (o->num_hatch_angles, 8);
8100       for (unsigned i = 0; i < o->num_hatch_angles; i++)
8101         {
8102           // FIELD_BD (hatch_angles[i], 40);
8103           pair = dxf_read_pair (dat);
8104           EXPECT_DXF (obj->name, hatch_angles, 40);
8105           o->hatch_angles[i] = pair->value.d;
8106           LOG_TRACE ("%s.%s[%d] = %f [BD %d]\n", obj->name, "hatch_angles", i,
8107                      pair->value.d, pair->code);
8108           dxf_free_pair (pair);
8109         }
8110     }
8111   return NULL;
8112 }
8113 
8114 static Dxf_Pair *
add_AcDbDetailViewStyle(Dwg_Object * restrict obj,Bit_Chain * restrict dat)8115 add_AcDbDetailViewStyle (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
8116 {
8117   Dwg_Data *dwg = obj->parent;
8118   Dwg_Object_DETAILVIEWSTYLE *o = obj->tio.object->tio.DETAILVIEWSTYLE;
8119   // starting with 71 . 0
8120   Dxf_Pair *pair;
8121   FIELD_BL (flags, 90);
8122   pair = dxf_read_pair (dat);              // skip 71 . 1
8123   FIELD_HANDLE (identifier_style, 5, 340); // textstyle
8124   FIELD_CMC2004 (identifier_color, 62);
8125   FIELD_BD (identifier_height, 40); // 5.0
8126   FIELD_HANDLE (arrow_symbol, 5, 340);
8127   FIELD_CMC2004 (arrow_symbol_color, 62);
8128   FIELD_BD (arrow_symbol_size, 40);
8129   FIELD_T (identifier_exclude_characters, 300);
8130   FIELD_BD (identifier_offset, 40);
8131   FIELD_RC (identifier_placement, 280);
8132   pair = dxf_read_pair (dat);            // skip 71 . 2
8133   FIELD_HANDLE (boundary_ltype, 5, 340); // ltype
8134   FIELD_BLd (boundary_linewt, 90);
8135   FIELD_CMC2004 (boundary_line_color, 62);
8136   pair = dxf_read_pair (dat);                  // skip 71 . 3
8137   FIELD_HANDLE (viewlabel_text_style, 5, 340); // textstyle
8138   FIELD_CMC2004 (viewlabel_text_color, 62);
8139   FIELD_BD (viewlabel_text_height, 40);
8140   FIELD_BL (viewlabel_attachment, 90);
8141   FIELD_BD (viewlabel_offset, 40); // 5.0
8142   FIELD_BL (viewlabel_alignment, 90);
8143   FIELD_T (viewlabel_pattern, 300);
8144   pair = dxf_read_pair (dat);              // skip 71 . 4
8145   FIELD_HANDLE (connection_ltype, 5, 340); // ltype
8146   FIELD_BLd (connection_linewt, 90);
8147   FIELD_CMC2004 (connection_line_color, 62);
8148   FIELD_HANDLE (borderline_ltype, 5, 340);
8149   FIELD_BLd (borderline_linewt, 90);
8150   FIELD_CMC2004 (borderline_color, 62);
8151   FIELD_RC (model_edge, 280); // type, origin, direction
8152   return NULL;
8153 }
8154 
8155 static Dxf_Pair *
add_VISUALSTYLE_props(Dwg_Object * restrict obj,Bit_Chain * restrict dat)8156 add_VISUALSTYLE_props (Dwg_Object *restrict obj, Bit_Chain *restrict dat)
8157 {
8158   Dwg_Data *dwg = obj->parent;
8159   Dwg_Object_VISUALSTYLE *o = obj->tio.object->tio.VISUALSTYLE;
8160   // starting with 70 . 58 num_props
8161   Dxf_Pair *pair;
8162   FIELD_BS (num_props, 70); // 58
8163   if (o->num_props != 58)
8164     LOG_ERROR ("Invalid VISUALSTYLE.num_props %u != 58", (unsigned)o->num_props);
8165   FIELD_B (b_prop1c, 290);                FIELD_BS (b_prop1c_int, 176);
8166   FIELD_B (b_prop1d, 290);                FIELD_BS (b_prop1d_int, 176);
8167   FIELD_B (b_prop1e, 290);                FIELD_BS (b_prop1e_int, 176);
8168   FIELD_B (b_prop1f, 90);                 FIELD_BS (b_prop1f_int, 176);
8169   FIELD_B (b_prop20, 290);                FIELD_BS (b_prop20_int, 176);
8170   FIELD_B (b_prop21, 90);                 FIELD_BS (b_prop21_int, 176);
8171   FIELD_B (b_prop22, 290);                FIELD_BS (b_prop22_int, 176);
8172   FIELD_B (b_prop23, 290);                FIELD_BS (b_prop23_int, 176);
8173   FIELD_B (b_prop24, 290);                FIELD_BS (b_prop24_int, 176);
8174   FIELD_BL (bl_prop25, 90);               FIELD_BS (bl_prop25_int, 176);
8175   FIELD_BD (bd_prop26, 40);               FIELD_BS (bd_prop26_int, 176);
8176   FIELD_BD (bd_prop27, 40);               FIELD_BS (bd_prop27_int, 176);
8177   FIELD_BL (bl_prop28, 90);               FIELD_BS (bl_prop28_int, 176);
8178   FIELD_CMC (c_prop29, 62);               FIELD_BS (c_prop29_int, 176);
8179   FIELD_BL (bl_prop2a, 90);               FIELD_BS (bl_prop2a_int, 176);
8180   FIELD_BL (bl_prop2b, 90);               FIELD_BS (bl_prop2b_int, 176);
8181   FIELD_CMC (c_prop2c, 62);               FIELD_BS (c_prop2c_int, 176);
8182   /*FIELD_B (b_prop2d, 0);*/              FIELD_BS (b_prop2d_int, 176);
8183   FIELD_BL (bl_prop2e, 290);              FIELD_BS (bl_prop2e_int, 176);
8184   FIELD_BL (bl_prop2f, 90);               FIELD_BS (bl_prop2f_int, 176);
8185   FIELD_BL (bl_prop30, 90);               FIELD_BS (bl_prop30_int, 176);
8186   FIELD_B (b_prop31, 290);                FIELD_BS (b_prop31_int, 176);
8187   FIELD_BL (bl_prop32, 90);               FIELD_BS (bl_prop32_int, 176);
8188   FIELD_CMC (c_prop33, 62);               FIELD_BS (c_prop33_int, 176);
8189   FIELD_BD (bd_prop34, 40);               FIELD_BS (bd_prop34_int, 176);
8190   FIELD_BL (edge_wiggle, 90);             FIELD_BS (edge_wiggle_int, 176);  // prop 0x35
8191   FIELD_T (strokes, 1);                   FIELD_BS (strokes_int, 176);      // prop 0x36
8192   FIELD_B (b_prop37, 290);                FIELD_BS (b_prop37_int, 176);
8193   FIELD_BD (bd_prop38, 40);               FIELD_BS (bd_prop38_int, 176);
8194   FIELD_BD (bd_prop39, 40);               FIELD_BS (bd_prop39_int, 176);
8195   return NULL;
8196 }
8197 
8198 // return a relative softptr (4 handle) to the prev_ref handle, relative to obj.
8199 static Dwg_Object_Ref *
dwg_link_prev(Dwg_Object_Ref * restrict prev_ref,Dwg_Object * restrict obj)8200 dwg_link_prev (Dwg_Object_Ref *restrict prev_ref, Dwg_Object *restrict obj)
8201 {
8202   Dwg_Object *prev;
8203   Dwg_Data *dwg = obj ? obj->parent : NULL;
8204   if (!prev_ref)
8205     return dwg_add_handleref (dwg, 4, 0, NULL);
8206   if (!obj)
8207     return NULL;
8208   prev = dwg_ref_object (dwg, prev_ref);
8209   if (!prev || prev->supertype != DWG_SUPERTYPE_ENTITY)
8210     return NULL;
8211   if (obj && obj->supertype == DWG_SUPERTYPE_ENTITY)
8212     obj->tio.entity->nolinks = 1;
8213   return dwg_add_handleref (dwg, 4, prev->handle.value, obj);
8214 }
8215 
8216 // return a relative softptr (4 handle) to the next_ref handle, relative to obj.
8217 // sets obj nolinks to 1 or 0.
8218 static Dwg_Object_Ref *
dwg_link_next(Dwg_Object_Ref * restrict next_ref,Dwg_Object * restrict obj)8219 dwg_link_next (Dwg_Object_Ref *restrict next_ref, Dwg_Object *restrict obj)
8220 {
8221   Dwg_Object *prev, *next;
8222   Dwg_Object_Ref *prev_ref;
8223   Dwg_Data *dwg = obj ? obj->parent : NULL;
8224   if (!next_ref)
8225     return dwg_add_handleref (dwg, 4, 0, NULL);
8226   if (!obj || obj->supertype != DWG_SUPERTYPE_ENTITY)
8227     return NULL;
8228   next = dwg_ref_object (dwg, next_ref);
8229   if (!next || next->supertype != DWG_SUPERTYPE_ENTITY)
8230     return NULL;
8231   if (next->index == obj->index + 1)
8232     {
8233       prev_ref = obj->tio.entity->prev_entity;
8234       // check if nolinks can be set
8235       if (prev_ref && prev_ref->handleref.code == 8 && prev_ref->handleref.value == 0)
8236         {
8237           obj->tio.entity->nolinks = 1;
8238           LOG_TRACE ("%s.nolinks = 1\n", obj->name);
8239           return NULL;
8240         }
8241     }
8242   obj->tio.entity->nolinks = 0;
8243   return dwg_add_handleref (dwg, 4, next->handle.value, obj);
8244 }
8245 
8246 // Also exported to in_json and dwg_api.
8247 // To set to linked list of children in POLYLINE_*/*INSERT
8248 // similar to dwg_fixup_BLOCKS_entities()
8249 void
in_postprocess_SEQEND(Dwg_Object * restrict obj,BITCODE_BL num_owned,BITCODE_H * owned)8250 in_postprocess_SEQEND (Dwg_Object *restrict obj, BITCODE_BL num_owned,
8251                        BITCODE_H *owned)
8252 {
8253   Dwg_Data *dwg = obj->parent;
8254   Dwg_Entity_SEQEND *o = obj->tio.entity->tio.SEQEND;
8255   Dwg_Object *owner;
8256   Dwg_Entity_POLYLINE_2D *ow;
8257   const char *owhdls; // the name of the H*
8258   const char *firstfield;
8259   const char *lastfield;
8260 
8261   LOG_TRACE ("in_postprocess_SEQEND (%u):\n", (unsigned)num_owned);
8262   if (obj->fixedtype != DWG_TYPE_SEQEND)
8263     return;
8264   owner = dwg_ref_object (dwg, obj->tio.entity->ownerhandle);
8265   if (!owner)
8266     {
8267       if (obj->tio.entity->ownerhandle)
8268         LOG_WARN ("Missing owner from " FORMAT_REF " [H 330]",
8269                   ARGS_REF (obj->tio.entity->ownerhandle))
8270       else
8271         LOG_WARN ("Missing owner")
8272       return;
8273     }
8274 
8275   obj->tio.entity->ownerhandle->obj = NULL;
8276   owhdls = memBEGINc (owner->name, "POLYLINE_") ? "vertex" : "attribs";
8277   // not the same layout for all possible owners
8278   ow = owner->tio.entity->tio.POLYLINE_2D;
8279   if (!num_owned || !owned)
8280     {
8281       dwg_dynapi_entity_value (ow, owner->name, "num_owned", &num_owned, 0);
8282       dwg_dynapi_entity_value (ow, owner->name, owhdls, &owned, 0);
8283     }
8284   if (!num_owned)
8285     return;
8286 
8287   if (memBEGINc (owner->name, "POLYLINE_"))
8288     {
8289       firstfield = "first_vertex";
8290       lastfield = "last_vertex";
8291     }
8292   else
8293     {
8294       firstfield = "first_attrib";
8295       lastfield = "last_attrib";
8296     }
8297   // store all these fields, or just the ones for the requested version?
8298   if ((dwg->header.from_version > R_2000 || dwg->opts & DWG_OPTS_INDXF)
8299       && dwg->header.version <= R_2000
8300       && owned) // if downconvert to r2000
8301     {
8302       Dwg_Object *owned_obj;
8303       Dwg_Object_Entity *ent;
8304       Dwg_Object_Ref *hdl;
8305       // need to turn code 3 into absolute 4.
8306       if (owned[0])
8307         {
8308           hdl = dwg_add_handleref (dwg, 4, owned[0]->handleref.value, NULL);
8309           dwg_dynapi_entity_set_value (ow, owner->name, firstfield, &hdl, 0);
8310           LOG_TRACE ("%s.%s = " FORMAT_REF "[H 0]\n", owner->name, firstfield,
8311                      ARGS_REF (hdl));
8312         }
8313       if (owned[num_owned - 1])
8314         {
8315           hdl = dwg_add_handleref (dwg, 4, owned[num_owned - 1]->handleref.value, NULL);
8316           dwg_dynapi_entity_set_value (ow, owner->name, lastfield,
8317                                        &hdl, 0);
8318           LOG_TRACE ("%s.%s = " FORMAT_REF "[H 0]\n", owner->name, lastfield,
8319                      ARGS_REF (hdl));
8320         }
8321       // link the list, because the children have entmode, different to the
8322       // owner.
8323       owned_obj = dwg_ref_object (dwg, owned[0]);
8324       if (!owned_obj || owned_obj->supertype != DWG_SUPERTYPE_ENTITY)
8325         return;
8326       ent = owned_obj->tio.entity;
8327       ent->prev_entity = dwg_link_prev (NULL, owned_obj);
8328       if (ent->prev_entity)
8329         LOG_TRACE ("%s.prev_entity = " FORMAT_REF "[H 0]\n", owned_obj->name,
8330                    ARGS_REF (ent->prev_entity))
8331       else
8332         ent->nolinks = 0;
8333       ent->next_entity = dwg_link_next (num_owned > 1 ? owned[1] : NULL, owned_obj);
8334       if (ent->next_entity)
8335         LOG_TRACE ("%s.next_entity = " FORMAT_REF "[H 0]\n", owned_obj->name,
8336                    ARGS_REF (ent->next_entity))
8337       else
8338         ent->nolinks = 0;
8339 
8340       for (unsigned i = 1; i < num_owned; i++)
8341         {
8342           owned_obj = dwg_ref_object (dwg, owned[i]);
8343           if (!owned_obj || owned_obj->supertype != DWG_SUPERTYPE_ENTITY)
8344             continue;
8345           ent = owned_obj->tio.entity;
8346           ent->prev_entity = dwg_link_prev (owned[i - 1], owned_obj);
8347           if (ent->prev_entity)
8348             LOG_TRACE ("%s.prev_entity = " FORMAT_REF "[H 0]\n", owned_obj->name,
8349                        ARGS_REF (ent->prev_entity))
8350           else
8351             ent->nolinks = 0;
8352           ent->next_entity = dwg_link_next (
8353               (i < num_owned - 1) ? owned[i + 1] : NULL, owned_obj);
8354           if (ent->next_entity)
8355             LOG_TRACE ("%s.next_entity = " FORMAT_REF "[H 0]\n", owned_obj->name,
8356                        ARGS_REF (ent->next_entity))
8357           else
8358             ent->nolinks = 0;
8359         }
8360     }
8361   else if ((dwg->header.from_version <= R_2000 || dwg->opts & DWG_OPTS_INDXF)
8362            && dwg->header.version > R_2000
8363            && !owned)
8364     {
8365       BITCODE_H first, last, ref;
8366       unsigned i = 0;
8367       owned = (BITCODE_H *)xcalloc (1, sizeof (BITCODE_H));
8368       dwg_dynapi_entity_value (ow, owner->name, firstfield, &first, 0);
8369       dwg_dynapi_entity_value (ow, owner->name, lastfield, &last, 0);
8370       ref = first;
8371       if (!first || !last || !last->absolute_ref)
8372         {
8373           num_owned = 0;
8374           owned[0] = first;
8375         }
8376       else if (first->absolute_ref == last->absolute_ref)
8377         {
8378           num_owned = 1;
8379           owned[0] = first;
8380         }
8381       else
8382         while (ref && ref->absolute_ref && ref->absolute_ref != last->absolute_ref)
8383           {
8384             Dwg_Object *ref_obj  = dwg_ref_object (dwg, ref);
8385             if (!ref_obj || ref_obj->supertype != DWG_SUPERTYPE_ENTITY)
8386               continue;
8387             owned[i] = ref;
8388             if (ref)
8389               LOG_TRACE ("%s.%s[%u] = " FORMAT_REF "[H 0]\n", owner->name,
8390                          owhdls, i, ARGS_REF (ref));
8391             ref = ref_obj->tio.entity->next_entity;
8392             i++;
8393             if (i > 1)
8394               {
8395                 num_owned = i;
8396                 owned = realloc (owned, i * sizeof (BITCODE_H));
8397               }
8398           }
8399       dwg_dynapi_entity_set_value (ow, owner->name, "num_owned", &num_owned, 0);
8400       dwg_dynapi_entity_set_value (ow, owner->name, owhdls, &owned, 0);
8401     }
8402 }
8403 
8404 // see GH #138. add vertices / attribs
8405 static void
dxf_postprocess_SEQEND(Dwg_Object * restrict obj)8406 dxf_postprocess_SEQEND (Dwg_Object *restrict obj)
8407 {
8408   Dwg_Data *dwg = obj->parent;
8409   Dwg_Entity_SEQEND *o = obj->tio.entity->tio.SEQEND;
8410   Dwg_Object *owner = dwg_ref_object (dwg, obj->tio.entity->ownerhandle);
8411   Dwg_Entity_POLYLINE_2D *ow;
8412   BITCODE_BL i, j, num_owned = 0;
8413   BITCODE_H seqend;
8414   BITCODE_H *owned = NULL;
8415   const char *owhdls;
8416 
8417   LOG_TRACE ("dxf_postprocess_SEQEND:\n");
8418   // r12 and earlier: search for owner backwards
8419   if (dwg->header.from_version < R_13 && !owner && !obj->tio.entity->ownerhandle)
8420     {
8421       for (i = obj->index - 1; i > 0; i--)
8422         {
8423           Dwg_Object *_o = &dwg->object[i];
8424           if (_o->type == DWG_TYPE_INSERT || _o->type == DWG_TYPE_MINSERT
8425               || _o->type == DWG_TYPE_POLYLINE_2D
8426               || _o->type == DWG_TYPE_POLYLINE_3D
8427               || _o->type == DWG_TYPE_POLYLINE_PFACE
8428               || _o->type == DWG_TYPE_POLYLINE_MESH)
8429             {
8430               owner = _o;
8431               obj->tio.entity->ownerhandle
8432                   = dwg_add_handleref (dwg, 4, _o->handle.value, obj);
8433               LOG_TRACE ("SEQEND.owner = " FORMAT_H " (%s) [H* 0]\n",
8434                          ARGS_H (_o->handle), _o->name);
8435               break;
8436             }
8437         }
8438     }
8439   if (!owner)
8440     {
8441       if (obj->tio.entity->ownerhandle)
8442         LOG_WARN ("Missing owner from " FORMAT_REF " [H 330]",
8443                   ARGS_REF (obj->tio.entity->ownerhandle))
8444       else
8445         LOG_WARN ("Missing owner")
8446       return;
8447     }
8448   obj->tio.entity->ownerhandle->obj = NULL;
8449   owhdls = memBEGINc (owner->name, "POLYLINE_") ? "vertex" : "attribs";
8450   ow = owner->tio.entity->tio.POLYLINE_2D;
8451 
8452   seqend = dwg_add_handleref (dwg, 3, obj->handle.value, owner);
8453   dwg_dynapi_entity_set_value (ow, owner->name, "seqend", &seqend, 0);
8454   LOG_TRACE ("%s.seqend = " FORMAT_REF " [H 0]\n", owner->name,
8455              ARGS_REF (seqend));
8456   // num_owned is not properly stored in a DXF
8457   // collect children hdls. all objects from owner to here
8458   for (j = 0, i = owner->index + 1; i < obj->index; i++, j++)
8459     {
8460       Dwg_Object *_o = &dwg->object[i];
8461       num_owned = j + 1;
8462       if (dwg->header.from_version >= R_13)
8463         {
8464           owned = (BITCODE_H *)realloc (owned, num_owned * sizeof (BITCODE_H));
8465           owned[j] = dwg_add_handleref (dwg, 3, _o->handle.value, owner);
8466           LOG_TRACE ("%s.%s[%d] = " FORMAT_REF " [H* 0]\n", owner->name,
8467                      owhdls, j, ARGS_REF (owned[j]));
8468         }
8469     }
8470   if (!num_owned)
8471     return;
8472   dwg_dynapi_entity_set_value (ow, owner->name, "num_owned", &num_owned, 0);
8473   LOG_TRACE ("%s.num_owned = " FORMAT_BL " [BL 0]\n", owner->name, num_owned);
8474 
8475   dwg_dynapi_entity_set_value (ow, owner->name, owhdls, &owned, 0);
8476   in_postprocess_SEQEND (obj, num_owned, owned);
8477 }
8478 
8479 static void
dxf_postprocess_LAYOUT(Dwg_Object * restrict obj)8480 dxf_postprocess_LAYOUT (Dwg_Object *restrict obj)
8481 {
8482   Dwg_Data *dwg = obj->parent;
8483   Dwg_Object_LAYOUT *_obj = obj->tio.object->tio.LAYOUT;
8484 
8485   if (dwg->header.version < R_2004)
8486     {
8487       _obj->plotsettings.plotview = dwg_find_tablehandle (
8488           dwg, _obj->plotsettings.plotview_name, "PLOTSETTINGS");
8489       /*
8490       if (!_obj->plotsettings.plotview)
8491         _obj->plotsettings.plotview = dwg_add_handleref (dwg, 0, 0, NULL);
8492       */
8493     }
8494   else
8495     _obj->plotsettings.plotview_name
8496         = dwg_handle_name (dwg, "PLOTSETTINGS", _obj->plotsettings.plotview);
8497 }
8498 
8499 static void
dxf_postprocess_PLOTSETTINGS(Dwg_Object * restrict obj)8500 dxf_postprocess_PLOTSETTINGS (Dwg_Object *restrict obj)
8501 {
8502   Dwg_Data *dwg = obj->parent;
8503   Dwg_Object_PLOTSETTINGS *_obj = obj->tio.object->tio.PLOTSETTINGS;
8504 
8505   if (dwg->header.version < R_2004)
8506     {
8507       _obj->plotview = dwg_find_tablehandle (dwg, _obj->plotview_name, "VIEW");
8508       /*
8509       if (!_obj->plotview)
8510         _obj->plotview = dwg_add_handleref (dwg, 0, 0, NULL);
8511       */
8512     }
8513   else
8514     _obj->plotview_name = dwg_handle_name (dwg, "VIEW", _obj->plotview);
8515 }
8516 
8517 // seperate model_space and paper_space into its own fields, out of entries[]
8518 static int
move_out_BLOCK_CONTROL(Dwg_Object * restrict obj,Dwg_Object_BLOCK_CONTROL * restrict _ctrl,const char * f)8519 move_out_BLOCK_CONTROL (Dwg_Object *restrict obj,
8520                         Dwg_Object_BLOCK_CONTROL *restrict _ctrl,
8521                         const char *f)
8522 {
8523   // move out this entry
8524   for (BITCODE_BL j = 0; j < _ctrl->num_entries; j++)
8525     {
8526       if (_ctrl->entries[j]
8527           && _ctrl->entries[j]->absolute_ref == obj->handle.value)
8528         {
8529           LOG_TRACE ("remove %s from entries[%d]: " FORMAT_H "\n", f, j,
8530                      ARGS_H (obj->handle));
8531           _ctrl->num_entries--;
8532           LOG_TRACE ("BLOCK_CONTROL.num_entries = " FORMAT_BL "\n",
8533                      _ctrl->num_entries);
8534           if (j < _ctrl->num_entries) // if last, skip move, realloc is enough
8535             /* 1 < 4 (was 5, i.e 0-4): 1, 2, 4-1-1: 2 */
8536             memmove (&_ctrl->entries[j], &_ctrl->entries[j + 1],
8537                      (_ctrl->num_entries - j - 1) * sizeof (BITCODE_H));
8538           _ctrl->entries = (BITCODE_H *)realloc (
8539               _ctrl->entries, _ctrl->num_entries * sizeof (BITCODE_H));
8540           return 1;
8541         }
8542     }
8543   return 0;
8544 }
8545 
8546 static int
move_out_LTYPE_CONTROL(Dwg_Object * restrict obj,Dwg_Object_LTYPE_CONTROL * restrict _ctrl,const char * f)8547 move_out_LTYPE_CONTROL (Dwg_Object *restrict obj,
8548                         Dwg_Object_LTYPE_CONTROL *restrict _ctrl,
8549                         const char *f)
8550 {
8551   // move out this entry (byblock, bylayer, continuous)
8552   for (BITCODE_BL j = 0; j < _ctrl->num_entries; j++)
8553     {
8554       if (_ctrl->entries[j]
8555           && _ctrl->entries[j]->absolute_ref == obj->handle.value)
8556         {
8557           LOG_TRACE ("remove %s from entries[%d]: " FORMAT_H "\n", f, j,
8558                      ARGS_H (obj->handle));
8559           _ctrl->num_entries--;
8560           LOG_TRACE ("LTYPE_CONTROL.num_entries = " FORMAT_BL "\n",
8561                      _ctrl->num_entries);
8562           if (j < _ctrl->num_entries)
8563             memmove (&_ctrl->entries[j], &_ctrl->entries[j + 1],
8564                      (_ctrl->num_entries - j - 1) * sizeof (BITCODE_H));
8565           _ctrl->entries = (BITCODE_H *)realloc (
8566               _ctrl->entries, _ctrl->num_entries * sizeof (BITCODE_H));
8567           return 1;
8568         }
8569     }
8570   return 0;
8571 }
8572 
8573 static void
postprocess_TEXTlike(Dwg_Object * obj)8574 postprocess_TEXTlike (Dwg_Object *obj)
8575 {
8576   BITCODE_RC dataflags;
8577   BITCODE_2RD alignment_pt;
8578   BITCODE_RD oblique_angle, rotation, width_factor;
8579   BITCODE_BS generation, horiz_alignment, vert_alignment;
8580   BITCODE_H style;
8581   Dwg_Entity_TEXT *_obj = obj->tio.entity->tio.TEXT;
8582 
8583   dwg_dynapi_entity_value (_obj, obj->name, "dataflags", &dataflags, NULL);
8584   dwg_dynapi_entity_value (_obj, obj->name, "alignment_pt", &alignment_pt,
8585                            NULL);
8586   dwg_dynapi_entity_value (_obj, obj->name, "oblique_angle", &oblique_angle,
8587                            NULL);
8588   dwg_dynapi_entity_value (_obj, obj->name, "rotation", &rotation, NULL);
8589   dwg_dynapi_entity_value (_obj, obj->name, "width_factor", &width_factor,
8590                            NULL);
8591   dwg_dynapi_entity_value (_obj, obj->name, "generation", &generation, NULL);
8592   dwg_dynapi_entity_value (_obj, obj->name, "horiz_alignment",
8593                            &horiz_alignment, NULL);
8594   dwg_dynapi_entity_value (_obj, obj->name, "vert_alignment", &vert_alignment,
8595                            NULL);
8596   dwg_dynapi_entity_value (_obj, obj->name, "style", &style, NULL);
8597 
8598   if (alignment_pt.x == 0.0 && alignment_pt.y == 0.0)
8599     dataflags |= 2;
8600   if (oblique_angle == 0.0)
8601     dataflags |= 4;
8602   if (rotation == 0.0)
8603     dataflags |= 8;
8604   if (width_factor == 1.0)
8605     dataflags |= 0x10;
8606   if (generation == 0)
8607     dataflags |= 0x20;
8608   if (horiz_alignment == 0)
8609     dataflags |= 0x40;
8610   if (vert_alignment == 0)
8611     dataflags |= 0x80;
8612 
8613   if (!style)
8614     {
8615       Dwg_Data *dwg = obj->parent;
8616       // set style to Standard (5.1.11)
8617       style = dwg_find_tablehandle_silent (dwg, "Standard", "STYLE");
8618       if (style)
8619         {
8620           if (style->handleref.code != 5)
8621             style = dwg_add_handleref (dwg, 5, style->absolute_ref, NULL);
8622           dwg_dynapi_entity_set_value (_obj, obj->name, "style", &style, 0);
8623           LOG_TRACE ("%s.style = " FORMAT_REF "\n", obj->name,
8624                      ARGS_REF (style));
8625         }
8626     }
8627   dwg_dynapi_entity_set_value (_obj, obj->name, "dataflags", &dataflags, 0);
8628   LOG_TRACE ("%s.dataflags = 0x%x\n", obj->name, dataflags);
8629 }
8630 
8631 int
is_textlike(Dwg_Object * restrict obj)8632 is_textlike (Dwg_Object *restrict obj)
8633 {
8634   // has dataflags and common text fields
8635   return obj->fixedtype == DWG_TYPE_TEXT || obj->fixedtype == DWG_TYPE_ATTDEF
8636          || obj->fixedtype == DWG_TYPE_ATTRIB;
8637 }
8638 
8639 void
in_postprocess_handles(Dwg_Object * restrict obj)8640 in_postprocess_handles (Dwg_Object *restrict obj)
8641 {
8642   Dwg_Data *dwg = obj->parent;
8643   const char *name = obj->name;
8644   int is_entity = obj->supertype == DWG_SUPERTYPE_ENTITY;
8645 
8646   // common_entity_handle_data:
8647   // set is_xdic_missing and xdicobjhandle if <2004
8648   if (is_entity ? !obj->tio.entity->xdicobjhandle
8649                 : !obj->tio.object->xdicobjhandle)
8650     {
8651       if (dwg->header.version >= R_2004)
8652         {
8653           if (is_entity)
8654             obj->tio.entity->is_xdic_missing = 1;
8655           else
8656             obj->tio.object->is_xdic_missing = 1;
8657         }
8658       else if (dwg->header.version >= R_13 && !is_entity)
8659         obj->tio.object->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, obj);
8660       else if (dwg->header.version >= R_13 && is_entity)
8661         obj->tio.entity->xdicobjhandle = dwg_add_handleref (dwg, 3, 0, obj);
8662     }
8663 
8664   if (is_entity)
8665     {
8666       Dwg_Object_Entity *ent = obj->tio.entity;
8667       if (dwg->header.version >= R_13 && dwg->header.version <= R_14)
8668         {
8669           if (ent->ltype_flags < 3)
8670             ent->isbylayerlt = 1;
8671         }
8672       if (dwg->header.version >= R_13 && dwg->header.version <= R_2000
8673           && obj->type != DWG_TYPE_SEQEND && obj->type != DWG_TYPE_ENDBLK)
8674         {
8675           Dwg_Object *prev = find_prev_entity (obj);
8676           ent->next_entity = NULL; // temp.
8677           if (prev)
8678             {
8679               // if (prev->tio.entity->prev_entity)
8680               //  prev->tio.entity->nolinks = 0;
8681               if (prev->index + 1 != obj->index)
8682                 {
8683                   prev->tio.entity->nolinks = 0;
8684                   prev->tio.entity->next_entity
8685                       = dwg_add_handleref (dwg, 4, obj->handle.value, prev);
8686                   LOG_TRACE ("prev %s(%lX).next_entity = " FORMAT_REF "\n",
8687                              prev->name, prev->handle.value,
8688                              ARGS_REF (prev->tio.entity->next_entity));
8689                   ent->nolinks = 0;
8690                   ent->prev_entity
8691                       = dwg_add_handleref (dwg, 4, prev->handle.value, obj);
8692                   LOG_TRACE ("%s.prev_entity = " FORMAT_REF "\n", name,
8693                              ARGS_REF (ent->prev_entity));
8694                 }
8695               else
8696                 {
8697                   LOG_TRACE ("%s.prev_entity = NULL HANDLE 4\n", name);
8698                   ent->prev_entity = NULL;
8699                   ent->nolinks = 1;
8700                 }
8701             }
8702           else if (obj->type == DWG_TYPE_BLOCK)
8703             {
8704               ent->nolinks = 0;
8705               ent->prev_entity = dwg_add_handleref (dwg, 4, 0, NULL);
8706               ent->next_entity = dwg_add_handleref (dwg, 4, 0, NULL);
8707               LOG_TRACE ("%s.prev_entity = next_entity = " FORMAT_REF "\n",
8708                          name, ARGS_REF (ent->prev_entity));
8709             }
8710           else
8711             {
8712               LOG_TRACE ("%s.prev_entity = NULL HANDLE 4\n", name);
8713               ent->prev_entity = NULL;
8714               ent->nolinks = 1;
8715             }
8716         }
8717       else if (obj->type != DWG_TYPE_SEQEND && obj->type != DWG_TYPE_ENDBLK)
8718         ent->nolinks = 1;
8719     }
8720 }
8721 
8722 #define GET_NUMFIELD(type)                                                    \
8723   {                                                                           \
8724     BITCODE_##type _size;                                                     \
8725     memcpy (&_size, &((char *)_obj)[f->offset], f->size);                     \
8726     LOG_TRACE ("%s = " FORMAT_##type "\n", f->name, _size);                   \
8727     return (long)_size;                                                       \
8728   }                                                                           \
8729   break;
8730 
8731 static long
get_numfield_value(void * restrict _obj,const Dwg_DYNAPI_field * restrict f)8732 get_numfield_value (void *restrict _obj, const Dwg_DYNAPI_field *restrict f)
8733 {
8734   long num = 0;
8735   if (f)
8736     {
8737       switch (f->size)
8738         {
8739         case 1:
8740           GET_NUMFIELD (B)
8741         case 2:
8742           GET_NUMFIELD (BS)
8743         case 4:
8744           GET_NUMFIELD (BL)
8745         case 8:
8746           GET_NUMFIELD (BLL)
8747         default:
8748           LOG_ERROR ("Unknown %s dynapi size %d", f->name, f->size);
8749         }
8750     }
8751   else if (strEQc (f->name, "transmatrix"))
8752     num = 16 * 8; // ignore
8753   else if (strEQc (f->name, "ref"))
8754     {
8755       if (f->size != 4) // fixed size
8756         LOG_WARN ("Need 4 ref array elements, have %ld", num)
8757       else
8758         LOG_TRACE ("Check ref[] 4 ok\n")
8759     }
8760   else
8761     LOG_ERROR ("Unknown num_%s field", f->name);
8762   return 0;
8763 }
8764 #undef GET_NUMFIELD
8765 
8766 /* For tables, entities and objects.
8767  */
8768 static Dxf_Pair *
new_object(char * restrict name,char * restrict dxfname,Bit_Chain * restrict dat,Dwg_Data * restrict dwg,BITCODE_BL ctrl_id,BITCODE_BL * i_p)8769 new_object (char *restrict name, char *restrict dxfname,
8770             Bit_Chain *restrict dat, Dwg_Data *restrict dwg,
8771             BITCODE_BL ctrl_id, BITCODE_BL *i_p)
8772 {
8773   const int is_tu = 1;
8774   Dwg_Object *obj;
8775   Dxf_Pair *pair = dxf_read_pair (dat);
8776   Dwg_Object_APPID *_obj = NULL; // the smallest
8777   // we'd really need a Dwg_Object_TABLE or Dwg_Object_Generic type
8778   char ctrlname[80];
8779   char subclass[80];
8780   char text[256]; // FIXME
8781   int in_xdict = 0;
8782   int in_reactors = 0;
8783   int in_blkrefs = 0;
8784   int in_embedobj = 0;
8785   int is_entity = is_dwg_entity (name) || strEQc (name, "DIMENSION");
8786   // BITCODE_BL rcount1, rcount2, rcount3, vcount;
8787   // Bit_Chain *hdl_dat, *str_dat;
8788   int j = 0, k = 0, l = 0, error = 0;
8789   BITCODE_BL i = i_p ? *i_p : 0;
8790   int cur_cell = -1;
8791   unsigned written = 0;
8792   BITCODE_RL curr_inserts = 0;
8793   BITCODE_RS flag = 0;
8794   BITCODE_BB scale_flag;
8795   BITCODE_3BD pt;
8796   Dwg_Object *ctrl;
8797   const Dwg_DYNAPI_field *prev_vstyle = NULL;
8798   subclass[0] = '\0';
8799 
8800   if (ctrl_id || i)
8801     {
8802       LOG_TRACE ("add %s [%d]\n", name, i)
8803     }
8804   else
8805     {
8806       if (strcmp (name, dxfname) != 0)
8807         LOG_TRACE ("add %s (%s)\n", name, dxfname)
8808       else
8809         LOG_TRACE ("add %s\n", name)
8810     }
8811 
8812   if (is_entity)
8813     {
8814       NEW_ENTITY (dwg, obj);
8815 
8816       obj->tio.entity->is_xdic_missing = 1;
8817       obj->tio.entity->color.index = 256; // ByLayer
8818       obj->tio.entity->ltype_scale = 1.0;
8819       if (strEQc (name, "SEQEND") || memBEGINc (name, "VERTEX"))
8820         obj->tio.entity->linewt = 0x1c;
8821       else
8822         obj->tio.entity->linewt = 0x1d;
8823 
8824       if (*name == '3')
8825         {
8826           // Looks dangerous but name[80] is big enough
8827           memmove (&name[1], &name[0], strlen (name) + 1);
8828           *name = '_';
8829         }
8830       if (strEQc (name, "DIMENSION"))
8831         { // the biggest
8832           ADD_ENTITY (DIMENSION_ANG2LN);
8833         }
8834       // broken (causes acad to hang on audit redraw)
8835       /*
8836       else if (is_class_unstable (name)
8837                && strEQc (name, "WIPEOUT"))
8838         {
8839           LOG_ERROR ("Unhandled DXF entity %s", name);
8840           name = (char*)"UNKNOWN_ENT";
8841           ADD_ENTITY (UNKNOWN_ENT);
8842           return pair;
8843         }
8844       */
8845       else
8846         {
8847           // clang-format off
8848           // ADD_ENTITY by name
8849           // check all objects
8850           #undef DWG_ENTITY
8851           #define DWG_ENTITY(token)             \
8852           if (strEQc (name, #token))            \
8853             {                                   \
8854               ADD_ENTITY (token);               \
8855               goto found_ent;                   \
8856             }                                   \
8857           else
8858 
8859           #include "objects.inc"
8860           //final else
8861           LOG_WARN ("Unknown object %s", name);
8862 
8863           #undef DWG_ENTITY
8864           #define DWG_ENTITY(token)
8865           // clang-format on
8866         found_ent:;
8867         }
8868     }
8869   else
8870     {
8871       NEW_OBJECT (dwg, obj);
8872 
8873       obj->tio.object->is_xdic_missing = 1;
8874       if (!ctrl_id) // no table
8875         {
8876           // clang-format off
8877           // ADD_OBJECT by name
8878           // check all objects
8879           #undef DWG_OBJECT
8880           #define DWG_OBJECT(token)         \
8881               if (strEQc (name, #token))    \
8882                 {                           \
8883                   ADD_OBJECT (token);       \
8884                   goto found_obj;           \
8885                 }
8886 
8887           #include "objects.inc"
8888 
8889           #undef DWG_OBJECT
8890           #define DWG_OBJECT(token)
8891 
8892         found_obj:
8893           ;
8894           // clang-format on
8895         }
8896       else // a table
8897         {
8898           if (strEQc (name, "BLOCK_RECORD"))
8899             {
8900               // strcpy (name, "BLOCK_HEADER");
8901               strcpy (ctrlname, "BLOCK_CONTROL");
8902             }
8903           else
8904             {
8905               strncpy (ctrlname, name, 70);
8906               ctrlname[69] = '\0';
8907               strcat (ctrlname, "_CONTROL");
8908             }
8909 
8910           // clang-format off
8911           ADD_TABLE_IF (LTYPE, LTYPE)
8912           else
8913           ADD_TABLE_IF (VPORT, VPORT)
8914           else
8915           ADD_TABLE_IF (APPID, APPID)
8916           else
8917           ADD_TABLE_IF (DIMSTYLE, DIMSTYLE)
8918           else
8919           ADD_TABLE_IF (LAYER, LAYER)
8920           else
8921           ADD_TABLE_IF (STYLE, STYLE)
8922           else
8923           ADD_TABLE_IF (UCS, UCS)
8924           else
8925           ADD_TABLE_IF (VIEW, VIEW)
8926           else
8927           ADD_TABLE_IF (BLOCK_RECORD, BLOCK_HEADER)
8928           else
8929           ADD_TABLE_IF (VX_TABLE_RECORD, VX_TABLE_RECORD)
8930           else
8931           // clang-format on
8932           {
8933             dwg->num_objects--;
8934             LOG_ERROR ("Unknown DXF AcDbSymbolTableRecord %s, skipping", name);
8935             return pair;
8936           }
8937         }
8938     }
8939 
8940   if (!_obj)
8941     {
8942       dwg->num_objects--;
8943       LOG_ERROR ("Empty _obj at DXF AcDbSymbolTableRecord %s, skipping", name);
8944       return pair;
8945     }
8946   ctrl = &dwg->object[ctrl_id];
8947 
8948   {
8949     const Dwg_DYNAPI_field *f1;
8950     BITCODE_B is_xref_ref = 1;
8951     // set defaults not in dxf:
8952     if (dwg_dynapi_entity_field (obj->name, "is_xref_ref"))
8953       dwg_dynapi_entity_set_value (_obj, obj->name, "is_xref_ref",
8954                                    &is_xref_ref, 0);
8955     if ((f1 = dwg_dynapi_entity_field (obj->name, "scale_flag"))
8956         && (memBEGINc(f1->type, "BB")))
8957       {
8958         scale_flag = 3;
8959         dwg_dynapi_entity_set_value (_obj, obj->name, "scale_flag",
8960                                      &scale_flag, 0);
8961         LOG_TRACE ("%s.scale_flag = 3 (default)\n", obj->name);
8962       }
8963     if ((f1 = dwg_dynapi_entity_field (obj->name, "width_factor"))
8964         && (memBEGINc(f1->type, "RD") || memBEGINc(f1->type, "BD")))
8965       {
8966         BITCODE_BD width_factor = 1.0;
8967         dwg_dynapi_entity_set_value (_obj, obj->name, "width_factor",
8968                                      &width_factor, 0);
8969         LOG_TRACE ("%s.width_factor = 1.0 (default)\n", obj->name);
8970       }
8971     if ((f1 = dwg_dynapi_entity_field (obj->name, "scale"))
8972         && (memBEGINc(f1->type, "3BD")))
8973       {
8974         pt.x = pt.y = pt.z = 1.0;
8975         dwg_dynapi_entity_set_value (_obj, obj->name, "scale", &pt, 0);
8976         LOG_TRACE ("%s.scale = (1,1,1) (default)\n", obj->name);
8977         pt.x = pt.y = pt.z = 0.0;
8978       }
8979     if ((f1 = dwg_dynapi_entity_field (obj->name, "extrusion"))
8980         && (memBEGINc(f1->type, "BE") || memBEGINc(f1->type, "3BD")))
8981       {
8982         pt.x = pt.y = 0.0;
8983         pt.z = 1.0;
8984         dwg_dynapi_entity_set_value (_obj, obj->name, "extrusion", &pt, 0);
8985         LOG_TRACE ("%s.extrusion = (0,0,1) (default)\n", obj->name);
8986         pt.z = 0.0;
8987       }
8988   }
8989   // more DXF defaults
8990   if (obj->fixedtype == DWG_TYPE_LAYOUT)
8991     {
8992       Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
8993       o->plotsettings.paper_units = 1.0; // default
8994     }
8995   else if (obj->fixedtype == DWG_TYPE_PLOTSETTINGS)
8996     {
8997       Dwg_Object_PLOTSETTINGS *o = obj->tio.object->tio.PLOTSETTINGS;
8998       o->paper_units = 1.0; // default
8999     }
9000   else if (obj->fixedtype == DWG_TYPE_DIMSTYLE)
9001     {
9002       Dwg_Object_DIMSTYLE *o = obj->tio.object->tio.DIMSTYLE;
9003       o->DIMSCALE = o->DIMLFAC = o->DIMTFAC = 1.0; // default
9004       o->DIMALTU = o->DIMLUNIT = 2;                // default
9005       o->DIMFIT = 3;
9006       o->DIMLWD = o->DIMLWE = -2;
9007     }
9008   else if (obj->fixedtype == DWG_TYPE_TABLESTYLE)
9009     {
9010       Dwg_Object_TABLESTYLE *o = obj->tio.object->tio.TABLESTYLE;
9011       o->num_rowstyles = 3;
9012       o->rowstyles = (Dwg_TABLESTYLE_rowstyles *)xcalloc (
9013           3, sizeof (Dwg_TABLESTYLE_rowstyles));
9014       if (!o->rowstyles)
9015         {
9016           o->num_rowstyles = 0;
9017           goto invalid_dxf;
9018         }
9019       for (j = 0; j < 3; j++)
9020         {
9021           o->rowstyles[j].borders = (Dwg_TABLESTYLE_border *)xcalloc (
9022               6, sizeof (Dwg_TABLESTYLE_border));
9023           o->rowstyles[j].num_borders = 6;
9024           for (k = 0; k < 3; k++) // defaults: ByLayer
9025             {
9026               o->rowstyles[j].borders[k].visible = 1;
9027               o->rowstyles[j].borders[k].linewt = 29;
9028               o->rowstyles[j].borders[k].color.index = 256;
9029             }
9030         }
9031       k = 0;
9032       j = 0;
9033     }
9034   /*
9035   else if (is_textlike (obj))
9036     {
9037       BITCODE_RC dataflags = 0x2 + 0x4 + 0x8;
9038       dwg_dynapi_entity_set_value (_obj, obj->name, "dataflags",
9039                                    &dataflags, 0);
9040     }
9041   */
9042   else if (obj->fixedtype == DWG_TYPE_MTEXT)
9043     {
9044       BITCODE_H style;
9045       Dwg_Entity_MTEXT *o = obj->tio.entity->tio.MTEXT;
9046       o->x_axis_dir.x = 1.0;
9047       // set style to Standard (5.1.11)
9048       style = dwg_find_tablehandle_silent (dwg, "Standard", "STYLE");
9049       if (style)
9050         {
9051           if (style->handleref.code != 5)
9052             style = dwg_add_handleref (dwg, 5, style->absolute_ref, NULL);
9053           o->style = style;
9054         }
9055     }
9056   // Some objects have various subtypes under one name, like DIMENSION.
9057   // TODO OBJECTCONTEXTDATA, ...
9058 
9059   // read table fields until next 0 table or 0 ENDTAB
9060   while (pair != NULL && pair->code != 0)
9061     {
9062     start_loop:
9063       if (pair == NULL)
9064         {
9065           pair = dxf_read_pair (dat);
9066           DXF_RETURN_EOF (pair);
9067         }
9068 #if 0
9069       // don't set defaults. TODO but needed to reset counters j, k, l
9070       if ((pair->type == DWG_VT_INT8 || pair->type == DWG_VT_INT16 || pair->type == DWG_VT_BOOL) &&
9071           pair->value.i == 0)
9072         goto next_pair;
9073       else if (pair->type == DWG_VT_REAL && pair->value.d == 0.0)
9074         goto next_pair;
9075       else if ((pair->type == DWG_VT_INT32 || pair->type == DWG_VT_INT64) &&
9076                pair->value.l == 0L)
9077         goto next_pair;
9078 #endif
9079       // start_switch:
9080       switch (pair->code)
9081         { // common flags: name, xref
9082         case 0:
9083           if (strEQc (name, "SEQEND"))
9084             dxf_postprocess_SEQEND (obj);
9085           return pair;
9086         case 105: /* DIMSTYLE only for 5 */
9087           if (strNE (name, "DIMSTYLE"))
9088             goto object_default;
9089           // fall through
9090         case 5:
9091           {
9092             obj->handle.value = pair->value.u;
9093             // check for existing BLOCK_HEADER.*Model_Space
9094             if (obj->fixedtype == DWG_TYPE_BLOCK_HEADER
9095                 && dwg->object[0].handle.value == pair->value.u
9096                 && obj->tio.object->tio.BLOCK_HEADER
9097                        != dwg->object[0].tio.object->tio.BLOCK_HEADER
9098                 && dwg->num_objects)
9099               {
9100                 dwg->num_objects--;
9101                 free (obj->tio.object->tio.BLOCK_HEADER);
9102                 obj = &dwg->object[0];
9103                 _obj = obj->tio.object->tio.APPID;
9104                 LOG_TRACE ("Reuse existing BLOCK_HEADER.*Model_Space %X [0]\n",
9105                            pair->value.u)
9106               }
9107             dwg_add_handle (&obj->handle, 0, pair->value.u, obj);
9108             LOG_TRACE ("%s.handle = " FORMAT_H " [H 5]\n", name,
9109                        ARGS_H (obj->handle));
9110             if (ctrl_id)
9111               {
9112                 // add to ctrl "entries" HANDLE_VECTOR
9113                 Dwg_Object_BLOCK_CONTROL *_ctrl
9114                     = dwg->object[ctrl_id].tio.object->tio.BLOCK_CONTROL;
9115                 BITCODE_H *hdls = NULL;
9116                 BITCODE_BL num_entries = 0;
9117 
9118                 if ((int)i < 0)
9119                   i = 0;
9120                 dwg_dynapi_entity_value (_ctrl, ctrlname, "num_entries",
9121                                          &num_entries, NULL);
9122                 if (i >= num_entries)
9123                   {
9124                     // DXF often lies about num_entries, skipping defaults
9125                     // e.g. BLOCK_CONTROL contains mspace+pspace in DXF, but in
9126                     // the DWG they are extra. But this is fixed at case 2, not
9127                     // here.
9128                     LOG_TRACE ("Misleading %s.num_entries %d for %dth entry\n",
9129                                ctrlname, num_entries, i);
9130                     i = num_entries;
9131                     num_entries++;
9132                     dwg_dynapi_entity_set_value (
9133                         _ctrl, ctrlname, "num_entries", &num_entries, 0);
9134                     LOG_TRACE ("%s.num_entries = %d [BL 70]\n", ctrlname,
9135                                num_entries);
9136                   }
9137                 dwg_dynapi_entity_value (_ctrl, ctrlname, "entries", &hdls,
9138                                          NULL);
9139                 if (!hdls)
9140                   hdls = (BITCODE_H *)xcalloc (num_entries,
9141                                                sizeof (Dwg_Object_Ref *));
9142                 else
9143                   hdls = (BITCODE_H *)realloc (
9144                       hdls, num_entries * sizeof (Dwg_Object_Ref *));
9145                 if (pair->value.u && !hdls)
9146                   goto invalid_dxf;
9147                 hdls[i] = dwg_add_handleref (dwg, 2, pair->value.u, obj);
9148                 dwg_dynapi_entity_set_value (_ctrl, ctrlname, "entries", &hdls,
9149                                              0);
9150                 LOG_TRACE ("%s.%s[%d] = " FORMAT_REF " [H* 0]\n", ctrlname,
9151                            "entries", i, ARGS_REF (hdls[i]));
9152               }
9153           }
9154           break;
9155         case 8:
9156           if (is_entity && pair->value.s)
9157             {
9158               BITCODE_H handle = find_tablehandle (dwg, pair);
9159               if (!handle)
9160                 {
9161                   obj_hdls = array_push (obj_hdls, "layer", pair->value.s,
9162                                          obj->tio.object->objid);
9163                   LOG_TRACE ("%s.layer: name %s -> H later\n", obj->name,
9164                              pair->value.s)
9165                 }
9166               else
9167                 {
9168                   dwg_dynapi_common_set_value (_obj, "layer", &handle, 1);
9169                   LOG_TRACE ("%s.layer = %s " FORMAT_REF " [H 8]\n", name,
9170                              pair->value.s, ARGS_REF (handle));
9171                 }
9172               break;
9173             }
9174           // fall through
9175         case 100: // for nested structs
9176           if (pair->code == 100 && pair->value.s)
9177             {
9178               strncpy (subclass, pair->value.s, 79);
9179               subclass[79] = '\0';
9180               // set the real objname
9181               if (strEQc (obj->name, "DIMENSION_ANG2LN")
9182                   || strEQc (obj->name, "DIMENSION"))
9183                 {
9184                   // we rather checked the flag before
9185                   if (strEQc (subclass, "AcDbRotatedDimension"))
9186                     {
9187                       obj->type = obj->fixedtype = DWG_TYPE_DIMENSION_LINEAR;
9188                       obj->name = (char *)"DIMENSION_LINEAR";
9189                       obj->dxfname = strdup (obj->name);
9190                       strcpy (name, obj->name);
9191                       LOG_TRACE ("change type to %s\n", name);
9192                     }
9193                   else if (strEQc (subclass, "AcDbAlignedDimension"))
9194                     {
9195                       // could be DIMENSION_LINEAR also. changed later on those
9196                       // new pairs
9197                       obj->type = obj->fixedtype = DWG_TYPE_DIMENSION_ALIGNED;
9198                       obj->name = (char *)"DIMENSION_ALIGNED";
9199                       obj->dxfname = strdup (obj->name);
9200                       strcpy (name, obj->name);
9201                       LOG_TRACE ("change type to %s\n", name);
9202                     }
9203                   else if (strEQc (subclass, "AcDbOrdinateDimension"))
9204                     {
9205                       obj->type = obj->fixedtype = DWG_TYPE_DIMENSION_ORDINATE;
9206                       obj->name = (char *)"DIMENSION_ORDINATE";
9207                       obj->dxfname = strdup (obj->name);
9208                       strcpy (name, obj->name);
9209                       LOG_TRACE ("change type to %s\n", name);
9210                     }
9211                   else if (strEQc (subclass, "AcDbDiametricDimension"))
9212                     {
9213                       obj->type = obj->fixedtype = DWG_TYPE_DIMENSION_DIAMETER;
9214                       obj->name = (char *)"DIMENSION_DIAMETER";
9215                       obj->dxfname = strdup (obj->name);
9216                       strcpy (name, obj->name);
9217                       LOG_TRACE ("change type to %s\n", name);
9218                     }
9219                   else if (strEQc (subclass, "AcDbRadialDimension"))
9220                     {
9221                       UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_RADIUS)
9222                     }
9223                   else if (strEQc (subclass, "AcDb3PointAngularDimension"))
9224                     {
9225                       UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ANG3PT)
9226                     }
9227                 }
9228               if (strEQc (obj->name, "DIMENSION_ALIGNED")
9229                   && strEQc (subclass, "AcDbRotatedDimension"))
9230                 {
9231                   UPGRADE_ENTITY (DIMENSION_ALIGNED, DIMENSION_LINEAR)
9232                 }
9233               // set the real objname
9234               else if (strEQc (obj->name, "POLYLINE_2D"))
9235                 {
9236                   if (strEQc (subclass, "AcDb3dPolyline"))
9237                     {
9238                       UPGRADE_ENTITY (POLYLINE_2D, POLYLINE_3D)
9239                     }
9240                   else if (strEQc (subclass, "AcDbPolyFaceMesh"))
9241                     {
9242                       UPGRADE_ENTITY (POLYLINE_2D, POLYLINE_PFACE)
9243                     }
9244                   else if (strEQc (subclass, "AcDbPolygonMesh"))
9245                     {
9246                       UPGRADE_ENTITY (POLYLINE_2D, POLYLINE_MESH)
9247                     }
9248                 }
9249               else if (strEQc (obj->name, "VERTEX_2D"))
9250                 {
9251                   if (strEQc (subclass, "AcDb3dPolylineVertex"))
9252                     {
9253                       UPGRADE_ENTITY (VERTEX_2D, VERTEX_3D)
9254                     }
9255                   else if (strEQc (subclass, "AcDbPolyFaceMeshVertex"))
9256                     { // _MESH or _PFACE:
9257                       Dwg_Object_Ref *owner = obj->tio.entity->ownerhandle;
9258                       Dwg_Object *parent = dwg_ref_object (dwg, owner);
9259                       if (parent
9260                           && parent->fixedtype == DWG_TYPE_POLYLINE_PFACE)
9261                         {
9262                           UPGRADE_ENTITY (VERTEX_2D, VERTEX_PFACE)
9263                         }
9264                       else
9265                         { // AcDbPolygonMesh
9266                           UPGRADE_ENTITY (VERTEX_2D, VERTEX_MESH)
9267                         }
9268                     }
9269                   else if (strEQc (subclass, "AcDbFaceRecord"))
9270                     {
9271                       UPGRADE_ENTITY (VERTEX_2D, VERTEX_PFACE_FACE)
9272                     }
9273                 }
9274               else if (strEQc (obj->name, "INSERT")
9275                   && strEQc (subclass, "AcDbMInsertBlock"))
9276                 {
9277                   UPGRADE_ENTITY (INSERT, MINSERT)
9278                 }
9279 
9280               // When we have all proper types, check proper subclasses.
9281               // If the subclass is allowed in this object.
9282               if (!dwg_has_subclass (obj->name, subclass))
9283                 {
9284                   if (is_type_stable (obj->fixedtype))
9285                     {
9286                       LOG_ERROR ("FIXME Unknown subclass %s in object %s", subclass, obj->name);
9287                       return NULL;
9288                     }
9289                   else
9290                     {
9291                       LOG_WARN ("TODO Unknown subclass %s in object %s", subclass, obj->name);
9292                     }
9293                 }
9294               if (strEQc (subclass, "AcDbDetailViewStyle")
9295                   && obj->fixedtype != DWG_TYPE_DETAILVIEWSTYLE)
9296                 {
9297                   LOG_ERROR ("Invalid subclass %s in object %s", subclass, obj->name);
9298                   return NULL;
9299                 }
9300 
9301               // with PERSUBENTMGR
9302               if (obj->fixedtype == DWG_TYPE_PERSUBENTMGR
9303                   && strEQc (subclass, "AcDbPersSubentManager"))
9304                 {
9305                   dxf_free_pair (pair);
9306                   pair = dxf_read_pair (dat);
9307                   pair = add_PERSUBENTMGR (obj, dat, pair); // NULL for success
9308                   if (!pair)
9309                     goto next_pair;
9310                   else
9311                     goto start_loop; /* failure */
9312                 }
9313               // with ASSOCDEPENDENCY or ACDBASSOCGEOMDEPENDENCY
9314               else if (strstr (obj->name, "ASSOC")
9315                        && strstr (obj->name, "DEPENDENCY")
9316                        && strEQc (subclass, "AcDbAssocDependency"))
9317                 {
9318                   dxf_free_pair (pair);
9319                   pair = add_ASSOCDEPENDENCY (obj, dat); // NULL for success
9320                   if (!pair)
9321                     goto next_pair;
9322                   else
9323                     goto start_loop; /* failure */
9324                 }
9325               // with ASSOC2DCONSTRAINTGROUP, ASSOCNETWORK, ASSOCACTION
9326               else if (strstr (obj->name, "ASSOC")
9327                        && strEQc (subclass, "AcDbAssocAction"))
9328                 {
9329                   dxf_free_pair (pair);
9330                   pair = dxf_read_pair (dat);
9331                   pair = add_ASSOCACTION (obj, dat, pair); // NULL for success
9332                   if (!pair)
9333                     {
9334                       // TODO: yet unsupported
9335                       if (strEQc (name, "ASSOC2DCONSTRAINTGROUP"))
9336                         return dxf_read_pair (dat);
9337                       else
9338                         goto next_pair;
9339                     }
9340                   else
9341                     goto start_loop; /* failure */
9342                 }
9343               else if (strstr (obj->name, "ASSOC")
9344                        && strEQc (subclass, "AcDbAssocNetwork"))
9345                 {
9346                   dxf_free_pair (pair);
9347                   pair = dxf_read_pair (dat);
9348                   LOG_TRACE ("add_ASSOCNETWORK\n")
9349                   pair = add_ASSOCNETWORK (obj, dat, pair); // NULL for success
9350                   if (!pair)
9351                     goto next_pair;
9352                   else
9353                     goto start_loop; /* failure */
9354                 }
9355               // strict subclasses (functable?)
9356 #define CHK_SUBCLASS(cppname, addmethod)                                \
9357   if (strEQc (subclass, #cppname))                                      \
9358     {                                                                   \
9359       dxf_free_pair (pair);                                             \
9360       LOG_TRACE ("add_" #addmethod "\n")                                \
9361       pair = add_##addmethod (obj, dat); /* NULL for success */         \
9362       if (!pair)                                                        \
9363         goto next_pair;                                                 \
9364       else                                                              \
9365         goto start_loop; /* failure */                                  \
9366     }
9367               else CHK_SUBCLASS (AcDbBlockParameter, AcDbBlockParameter)
9368               else CHK_SUBCLASS (AcDbBlockGripExpr, AcDbBlockGripExpr)
9369               else CHK_SUBCLASS (AcDbBlockAlignmentGrip, BLOCKALIGNMENTGRIP)
9370               else CHK_SUBCLASS (AcDbBlockLinearGrip, BLOCKALIGNMENTGRIP)
9371               else CHK_SUBCLASS (AcDbBlockFlipGrip, BLOCKFLIPGRIP)
9372               else CHK_SUBCLASS (AcDbRenderEnvironment, RENDERENVIRONMENT)
9373               else CHK_SUBCLASS (AcDbRenderGlobal, RENDERGLOBAL)
9374               else CHK_SUBCLASS (AcDbRenderEntry, RENDERENTRY)
9375               else CHK_SUBCLASS (AcDbRenderSettings, RENDERSETTINGS)
9376               // more DYNBLOCKs
9377 #define else_do_strict_subclass(SUBCLASS)                                     \
9378   else if (strEQc (subclass, #SUBCLASS))                                      \
9379   {                                                                           \
9380     dxf_free_pair (pair);                                                     \
9381     LOG_TRACE ("add_" #SUBCLASS "\n")                                         \
9382     pair = add_##SUBCLASS (obj, dat);                                         \
9383     if (!pair) /* NULL for success */                                         \
9384       goto next_pair;                                                         \
9385     else                                                                      \
9386       goto start_loop; /* failure */                                          \
9387   }
9388 
9389               else_do_strict_subclass (AcDbBlock1PtParameter)
9390               else_do_strict_subclass (AcDbBlock2PtParameter)
9391               else_do_strict_subclass (AcDbBlockAction)
9392               else_do_strict_subclass (AcDbBlockActionWithBasePt)
9393               else_do_strict_subclass (AcDbBlockFlipAction)
9394               else_do_strict_subclass (AcDbBlockMoveAction)
9395               else_do_strict_subclass (AcDbBlockRotationAction)
9396               else_do_strict_subclass (AcDbBlockScaleAction)
9397               else_do_strict_subclass (AcDbBlockStretchAction)
9398               else_do_strict_subclass (AcDbBlockRotationParameter)
9399             }
9400           break;
9401         case 101:
9402           if (pair->value.s && strEQc (pair->value.s, "Embedded Object"))
9403             in_embedobj = 1;
9404           break;
9405         case 102:
9406           if (pair->value.s && strEQc (pair->value.s, "{ACAD_XDICTIONARY"))
9407             in_xdict = 1;
9408           else if (pair->value.s && strEQc (pair->value.s, "{ACAD_REACTORS"))
9409             in_reactors = 1;
9410           else if (ctrl_id && pair->value.s
9411                    && strEQc (pair->value.s, "{BLKREFS"))
9412             in_blkrefs = 1; // unique handle 331
9413           else if (pair->value.s && strEQc (pair->value.s, "}"))
9414             in_reactors = in_xdict = in_blkrefs = 0;
9415           else if (pair->value.s && strEQc (name, "XRECORD"))
9416             pair = add_xdata (dat, obj, pair);
9417           else
9418             LOG_WARN ("Unknown DXF code 102 %s in %s", pair->value.s, name)
9419           break;
9420         case 331:
9421           if (ctrl_id && in_blkrefs) // BLKREFS TODO
9422             {
9423               BITCODE_H *inserts = NULL;
9424               BITCODE_H hdl;
9425               BITCODE_RL num_inserts;
9426               dwg_dynapi_entity_value (_obj, obj->name, "num_inserts",
9427                                        &num_inserts, 0);
9428               if (curr_inserts)
9429                 dwg_dynapi_entity_value (_obj, obj->name, "inserts", &inserts,
9430                                          0);
9431               if (curr_inserts + 1 > num_inserts)
9432                 {
9433                   LOG_HANDLE ("  extending %s.num_inserts %d < %d\n",
9434                               obj->name, num_inserts, curr_inserts + 1);
9435                   num_inserts = curr_inserts + 1;
9436                   dwg_dynapi_entity_set_value (_obj, obj->name, "num_inserts",
9437                                                &num_inserts, 0);
9438                 }
9439               if (inserts)
9440                 inserts = (BITCODE_H *)realloc (
9441                     inserts, num_inserts * sizeof (BITCODE_H));
9442               else
9443                 inserts
9444                     = (BITCODE_H *)xcalloc (num_inserts, sizeof (BITCODE_H));
9445               if (num_inserts && !inserts)
9446                 goto invalid_dxf;
9447               dwg_dynapi_entity_set_value (_obj, obj->name, "inserts",
9448                                            &inserts, 0);
9449               hdl = dwg_add_handleref (dwg, 4, pair->value.u, NULL); // absolute
9450               LOG_TRACE ("%s.inserts[%d] = " FORMAT_REF " [H* 331]\n",
9451                          obj->name, curr_inserts, ARGS_REF (hdl));
9452               inserts[curr_inserts++] = hdl;
9453               break;
9454             }
9455           else if (pair->code == 331 && obj->fixedtype == DWG_TYPE_LAYOUT)
9456             {
9457               Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
9458               o->active_viewport
9459                   = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
9460               LOG_TRACE ("%s.active_viewport = " FORMAT_REF " [H 331]\n",
9461                          obj->name, ARGS_REF (o->active_viewport));
9462               break;
9463             }
9464           // fall through
9465         case 330:
9466           if (in_reactors)
9467             {
9468               BITCODE_BL num = is_entity ? obj->tio.entity->num_reactors
9469                                          : obj->tio.object->num_reactors;
9470               BITCODE_H reactor = dwg_add_handleref (dwg, 4, pair->value.u,
9471                                                      NULL); // always abs
9472               LOG_TRACE ("%s.reactors[%d] = " FORMAT_REF " [H* 330]\n", name,
9473                          num, ARGS_REF (reactor));
9474               if (is_entity)
9475                 {
9476                   obj->tio.entity->reactors
9477                       = (BITCODE_H *)realloc (obj->tio.entity->reactors,
9478                                               (num + 1) * sizeof (BITCODE_H));
9479                   obj->tio.entity->reactors[num] = reactor;
9480                   obj->tio.entity->num_reactors++;
9481                 }
9482               else
9483                 {
9484                   obj->tio.object->reactors
9485                       = (BITCODE_H *)realloc (obj->tio.object->reactors,
9486                                               (num + 1) * sizeof (BITCODE_H));
9487                   obj->tio.object->reactors[num] = reactor;
9488                   obj->tio.object->num_reactors++;
9489                 }
9490             }
9491           else if (pair->code == 330 && obj->fixedtype == DWG_TYPE_LAYOUT
9492                    && obj->tio.object->ownerhandle)
9493             {
9494               Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
9495               o->block_header
9496                   = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
9497               LOG_TRACE ("%s.block_header = " FORMAT_REF " [H 330]\n",
9498                          obj->name, ARGS_REF (o->block_header));
9499             }
9500           // valid ownerhandle, if not XRECORD with an ownerhandle already
9501           else if (pair->code == 330
9502                    && (obj->fixedtype != DWG_TYPE_XRECORD
9503                        || !obj->tio.object->ownerhandle))
9504             {
9505               BITCODE_H owh;
9506               if (is_obj_absowner (obj))
9507                 owh = dwg_add_handleref (dwg, 4, pair->value.u, NULL);
9508               else // relative
9509                 owh = dwg_add_handleref (dwg, 4, pair->value.u, obj);
9510               if (is_entity)
9511                 obj->tio.entity->ownerhandle = owh;
9512               else
9513                 obj->tio.object->ownerhandle = owh;
9514               LOG_TRACE ("%s.ownerhandle = " FORMAT_REF " [H 330]\n", name,
9515                          ARGS_REF (owh));
9516             }
9517           break;
9518         case 350: // DICTIONARY softhandle
9519         case 360: // {ACAD_XDICTIONARY or some hardowner
9520           if (pair->code == 360 && in_xdict)
9521             {
9522               BITCODE_H xdic = dwg_add_handleref (dwg, 3, pair->value.u, obj);
9523               if (is_entity)
9524                 {
9525                   obj->tio.entity->xdicobjhandle = xdic;
9526                   obj->tio.entity->is_xdic_missing = 0;
9527                 }
9528               else
9529                 {
9530                   obj->tio.object->xdicobjhandle = xdic;
9531                   obj->tio.object->is_xdic_missing = 0;
9532                 }
9533               LOG_TRACE ("%s.xdicobjhandle = " FORMAT_REF " [H 360]\n", name,
9534                          ARGS_REF (xdic));
9535               break;
9536             }
9537           // // DICTIONARY or DICTIONARYWDFLT, but not DICTIONARYVAR
9538           else if (memBEGINc (name, "DICTIONARY")
9539                    && strNE (name, "DICTIONARYVAR"))
9540             {
9541               add_dictionary_itemhandles (obj, pair, text);
9542               break;
9543             }
9544           else if (pair->code == 360 && // hardowner, not soft
9545                    (obj->fixedtype == DWG_TYPE_IMAGE
9546                     || obj->fixedtype == DWG_TYPE_WIPEOUT))
9547             {
9548               BITCODE_H ref = dwg_add_handleref (dwg, 3, pair->value.u, obj);
9549               dwg_dynapi_entity_set_value (_obj, obj->name, "imagedefreactor",
9550                                            ref, 0);
9551               LOG_TRACE ("%s.imagedefreactor = " FORMAT_REF " [H %d]\n", name,
9552                          ARGS_REF (ref), pair->code);
9553               break;
9554             }
9555           // fall through
9556         case 340:
9557           if (pair->code == 340 && strEQc (name, "GROUP"))
9558             {
9559               Dwg_Object_GROUP *o = obj->tio.object->tio.GROUP;
9560               BITCODE_H hdl = dwg_add_handleref (dwg, 5, pair->value.u, obj);
9561               LOG_TRACE ("GROUP.groups[%d] = " FORMAT_REF " [H* 340]\n",
9562                          o->num_groups, ARGS_REF (hdl));
9563               o->groups = (BITCODE_H *)realloc (
9564                   o->groups, (o->num_groups + 1) * sizeof (BITCODE_H));
9565               o->groups[o->num_groups] = hdl;
9566               o->num_groups++;
9567               break;
9568             }
9569           // fall through
9570         case 341:
9571           if (pair->code == 341 && strEQc (name, "VIEWPORT"))
9572             {
9573               Dwg_Entity_VIEWPORT *o = obj->tio.entity->tio.VIEWPORT;
9574               int code = dwg->header.version >= R_2004 ? 4 : 5;
9575               BITCODE_H hdl
9576                   = dwg_add_handleref (dwg, code, pair->value.u, obj);
9577               LOG_TRACE ("VIEWPORT.frozen_layers[%d] = " FORMAT_REF
9578                          " [H* 341]\n",
9579                          o->num_frozen_layers, ARGS_REF (hdl));
9580               o->frozen_layers = (BITCODE_H *)realloc (
9581                   o->frozen_layers,
9582                   (o->num_frozen_layers + 1) * sizeof (BITCODE_H));
9583               o->frozen_layers[o->num_frozen_layers] = hdl;
9584               o->num_frozen_layers++;
9585               break;
9586             }
9587           // fall through
9588         case 2:
9589           if (ctrl_id && pair->code == 2)
9590             {
9591               dwg_dynapi_entity_set_value (_obj, obj->name, "name",
9592                                            &pair->value, 1);
9593               LOG_TRACE ("%s.name = %s [T 2]\n", name, pair->value.s);
9594               if (!pair->value.s)
9595                 break;
9596               assert (i_p); // needs ctrl_id
9597               *i_p = i + 1;
9598               if (strEQc (name, "BLOCK_RECORD"))
9599                 {
9600                   // seperate mspace and pspace into its own fields
9601                   Dwg_Object_BLOCK_CONTROL *_ctrl
9602                       = ctrl->tio.object->tio.BLOCK_CONTROL;
9603                   if (!strcasecmp (pair->value.s, "*Paper_Space"))
9604                     {
9605                       const char *f = "paper_space";
9606                       _ctrl->paper_space
9607                           = dwg_add_handleref (dwg, 3, obj->handle.value, obj);
9608                       LOG_TRACE ("%s.%s = " FORMAT_REF " [H 0]\n", ctrlname, f,
9609                                  ARGS_REF (_ctrl->paper_space));
9610                       dwg->header_vars.BLOCK_RECORD_PSPACE
9611                           = dwg_add_handleref (dwg, 5, obj->handle.value, obj);
9612                       // move out of entries
9613                       if (move_out_BLOCK_CONTROL (obj, _ctrl, f))
9614                         *i_p = i;
9615                     }
9616                   else if (!strcasecmp (pair->value.s, "*Model_Space"))
9617                     {
9618                       const char *f = "model_space";
9619                       _ctrl->model_space
9620                           = dwg_add_handleref (dwg, 3, obj->handle.value, obj);
9621                       LOG_TRACE ("%s.%s = " FORMAT_REF " [H 0]\n", ctrlname, f,
9622                                  ARGS_REF (_ctrl->model_space));
9623                       dwg->header_vars.BLOCK_RECORD_MSPACE
9624                           = dwg_add_handleref (dwg, 5, obj->handle.value, obj);
9625                       // move out of entries
9626                       if (move_out_BLOCK_CONTROL (obj, _ctrl, f))
9627                         *i_p = i;
9628                     }
9629                 }
9630               else if (strEQc (name, "LTYPE"))
9631                 {
9632                   // seperate bylayer and byblock into its own fields
9633                   Dwg_Object_LTYPE_CONTROL *_ctrl
9634                       = ctrl->tio.object->tio.LTYPE_CONTROL;
9635                   if (!strcasecmp (pair->value.s, "ByLayer"))
9636                     {
9637                       const char *f = "bylayer";
9638                       _ctrl->bylayer
9639                           = dwg_add_handleref (dwg, 3, obj->handle.value, obj);
9640                       LOG_TRACE ("%s.%s = " FORMAT_REF " [H 0]\n", ctrlname, f,
9641                                  ARGS_REF (_ctrl->bylayer));
9642                       dwg->header_vars.LTYPE_BYLAYER
9643                           = dwg_add_handleref (dwg, 5, obj->handle.value, obj);
9644                       // move out of entries
9645                       if (move_out_LTYPE_CONTROL (obj, _ctrl, f))
9646                         *i_p = i;
9647                     }
9648                   else if (!strcasecmp (pair->value.s, "ByBlock"))
9649                     {
9650                       const char *f = "byblock";
9651                       _ctrl->byblock
9652                           = dwg_add_handleref (dwg, 3, obj->handle.value, obj);
9653                       LOG_TRACE ("%s.%s = " FORMAT_REF " [H 0]\n", ctrlname, f,
9654                                  ARGS_REF (_ctrl->byblock));
9655                       dwg->header_vars.LTYPE_BYBLOCK
9656                           = dwg_add_handleref (dwg, 5, obj->handle.value, obj);
9657                       // move out of entries
9658                       if (move_out_LTYPE_CONTROL (obj, _ctrl, f))
9659                         *i_p = i;
9660                     }
9661                 }
9662               break;
9663             }
9664           if (pair->code == 2 && strEQc (name, "MLINE"))
9665             {
9666               // ignore name of mlinestyle, already set by ->mlinestyle
9667               break;
9668             }
9669           if (pair->code == 2 && dwg_obj_is_3dsolid (obj))
9670             {
9671               BITCODE_BL revision_major;
9672               BITCODE_BS revision_minor1;
9673               BITCODE_BS revision_minor2;
9674               BITCODE_RC revision_bytes[9];
9675               // no malloc, it is copied into the dwg. but it needs to be large
9676               // enough, pair->value.s might be smaller on corrupt DXF's. Also
9677               // we null-terminate it.
9678               char revision_guid[39];
9679               char *p = &revision_guid[0];
9680               unsigned u[3];
9681               if (!pair->value.s)
9682                 {
9683                   LOG_ERROR ("Invalid %s.revision_guid %s", obj->name,
9684                              revision_guid);
9685                   break;
9686                 }
9687               // "{00000100-0100-00CA-D300-80010A7B10C3}"
9688               strncpy (revision_guid, pair->value.s, 38);
9689               revision_guid[38] = '\0';
9690               if (!dwg_dynapi_entity_set_value (
9691                       _obj, obj->name, "revision_guid[39]", revision_guid, 0))
9692                 break;
9693               if (revision_guid[0] != '{' ||  /* 8 */
9694                   revision_guid[9] != '-' ||  /* 4 */
9695                   revision_guid[14] != '-' || /* 4 */
9696                   revision_guid[19] != '-' || /* 4 */
9697                   revision_guid[24] != '-' || /* 12 */
9698                   revision_guid[37] != '}')
9699                 {
9700                   LOG_ERROR ("Invalid %s.revision_guid %s", obj->name,
9701                              revision_guid);
9702                   break;
9703                 }
9704               sscanf (p, "{%8" PRIx32 "-%4X-%4X-%4X-", &revision_major, &u[0],
9705                       &u[1], &u[2]);
9706               revision_minor1 = (BITCODE_BS)u[0];
9707               revision_minor2 = (BITCODE_BS)u[1];
9708               p += 20;
9709               sscanf (p, SCANF_2X, &revision_bytes[0]);
9710               p += 2;
9711               sscanf (p, SCANF_2X, &revision_bytes[1]);
9712               p += 3;
9713               for (int _i = 2; _i < 8; _i++)
9714                 {
9715                   sscanf (p, SCANF_2X, &revision_bytes[_i]);
9716                   p += 2;
9717                 }
9718               revision_bytes[8]
9719                   = '\0'; // insist on an ending 0 byte, even if never used.
9720               dwg_dynapi_entity_set_value (_obj, obj->name, "revision_major",
9721                                            &revision_major, 0);
9722               dwg_dynapi_entity_set_value (_obj, obj->name, "revision_minor1",
9723                                            &revision_minor1, 0);
9724               dwg_dynapi_entity_set_value (_obj, obj->name, "revision_minor2",
9725                                            &revision_minor2, 0);
9726               dwg_dynapi_entity_set_value (
9727                   _obj, obj->name, "revision_bytes[9]", revision_bytes, 0);
9728               break;
9729             }
9730           // fall through
9731         case 70:
9732           if (ctrl_id && pair->code == 70)
9733             {
9734               BITCODE_B bit;
9735               ;
9736               flag = pair->value.i | 64;
9737               dwg_dynapi_entity_set_value (_obj, obj->name, "flag", &flag, 1);
9738               LOG_TRACE ("%s.flag = %d [RC 70]\n", name, pair->value.i);
9739               if (obj->fixedtype == DWG_TYPE_STYLE)
9740                 {
9741 
9742 #define SET_CTRL_BIT(b, bnam)                                                 \
9743   bit = flag & b ? 1 : 0;                                                     \
9744   if (bit)                                                                    \
9745     {                                                                         \
9746       dwg_dynapi_entity_set_value (_obj, obj->name, #bnam, &bit, 1);          \
9747       LOG_TRACE ("%s.%s = %d [B]\n", name, #bnam, bit);                       \
9748     }
9749 
9750                   SET_CTRL_BIT (1, is_vertical);
9751                   SET_CTRL_BIT (4, is_shape);
9752                 }
9753               else if (obj->fixedtype == DWG_TYPE_LAYER)
9754                 {
9755                   SINCE (R_2000)
9756                   {
9757                     SET_CTRL_BIT (1, frozen);
9758                     bit = flag & 2 ? 0 : 1; // reverse
9759                     if (bit)
9760                       {
9761                         dwg_dynapi_entity_set_value (_obj, obj->name, "on",
9762                                                      &bit, 1);
9763                         LOG_TRACE ("%s.%s = %d [B]\n", name, "on", bit);
9764                       }
9765                     SET_CTRL_BIT (4, frozen_in_new);
9766                     SET_CTRL_BIT (8, locked);
9767                     SET_CTRL_BIT (32768, plotflag);
9768                   }
9769                   else
9770                   {
9771                     SET_CTRL_BIT (1, frozen);
9772                     SET_CTRL_BIT (2, frozen_in_new);
9773                     SET_CTRL_BIT (4, locked);
9774                   }
9775                 }
9776               else if (obj->fixedtype == DWG_TYPE_BLOCK_HEADER)
9777                 {
9778                   SET_CTRL_BIT (1, anonymous);
9779                   SET_CTRL_BIT (2, hasattrs);
9780                   SET_CTRL_BIT (4, blkisxref);
9781                   SET_CTRL_BIT (8, xrefoverlaid);
9782                   SET_CTRL_BIT (32, loaded_bit);
9783                 }
9784               else if (obj->fixedtype == DWG_TYPE_VIEW)
9785                 {
9786                   SET_CTRL_BIT (1, is_pspace);
9787                 }
9788               else if (obj->fixedtype == DWG_TYPE_DIMSTYLE)
9789                 {
9790                   SET_CTRL_BIT (1, flag0);
9791                 }
9792               else if (obj->fixedtype == DWG_TYPE_VX_TABLE_RECORD)
9793                 {
9794                   // also set via 290
9795                   SET_CTRL_BIT (2, is_on);
9796                 }
9797               break;
9798             }
9799           else if (pair->code == 70 && obj->fixedtype == DWG_TYPE_LAYOUT)
9800             {
9801               Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
9802               if (strEQc (subclass,
9803                           "AcDbPlotSettings")) // todo: embedded struct
9804                 {
9805                   o->plotsettings.plot_flags = pair->value.i;
9806                   LOG_TRACE ("LAYOUT.plotsettings.plot_flags = 0x%x [BSx 70]",
9807                              pair->value.i);
9808                 }
9809               else if (strEQc (subclass, "AcDbLayout"))
9810                 {
9811                   o->layout_flags = pair->value.u;
9812                   LOG_TRACE ("LAYOUT.layout_flags = 0x%x [BSx 70]",
9813                              pair->value.u);
9814                 }
9815               else
9816                 {
9817                   LOG_WARN ("Unhandled LAYOUT.70 in subclass %s", subclass);
9818                   o->layout_flags = pair->value.u;
9819                   LOG_TRACE ("LAYOUT.layout_flags = 0x%x [BSx 70]",
9820                              pair->value.u);
9821                 }
9822               break;
9823             }
9824           else if (pair->code == 70 && obj->fixedtype == DWG_TYPE_LWPOLYLINE)
9825             {
9826               Dwg_Entity_LWPOLYLINE *o = obj->tio.entity->tio.LWPOLYLINE;
9827               o->flag = pair->value.i;
9828               // 1 => 512 closed
9829               // 128: plinegen
9830               if (o->flag & 1)
9831                 o->flag = (o->flag - 1) + 512;
9832               LOG_TRACE ("LWPOLYLINE.flag => %d [BS 70]\n", flag);
9833               break;
9834             }
9835           else if (pair->code == 70
9836                    && strEQc (subclass, "AcDbModelDocViewStyle"))
9837             {
9838               BITCODE_BS ver = pair->value.i;
9839               LOG_TRACE ("%s.mdoc_class_version = %d [BS %d]\n", name,
9840                          pair->value.i, pair->code);
9841               dwg_dynapi_entity_set_value (_obj, obj->name,
9842                                            "mdoc_class_version", &ver, is_tu);
9843               break;
9844             }
9845           else if (pair->code == 70
9846                    && (strEQc (subclass, "AcDbSectionViewStyle")
9847                        || strEQc (subclass, "AcDbDetailViewStyle")))
9848             {
9849               BITCODE_BS ver = pair->value.i;
9850               LOG_TRACE ("%s.class_version = %d [BS %d]\n", name,
9851                          pair->value.i, pair->code);
9852               dwg_dynapi_entity_set_value (_obj, obj->name, "class_version",
9853                                            &ver, is_tu);
9854               break;
9855             }
9856           else if (pair->code == 70
9857                    && obj->fixedtype == DWG_TYPE_DIMENSION_ANG2LN)
9858             {
9859               Dwg_Entity_DIMENSION_ANG2LN *o
9860                   = obj->tio.entity->tio.DIMENSION_ANG2LN;
9861               o->flag = o->flag1 = pair->value.i;
9862               LOG_TRACE ("DIMENSION.flag = %d [RC 70]\n", pair->value.i);
9863               o->flag1 &= 0xE0; /* clear the upper flag bits, and fix them: */
9864               o->flag1 = (o->flag1 & 0x80) ? o->flag1 & 0x7F : o->flag1 | 1;
9865               o->flag1 = (o->flag1 & 0x20) ? o->flag1 | 2 : o->flag1 & 0xDF;
9866               LOG_TRACE ("DIMENSION.flag1 => %d [RC]\n", o->flag1);
9867               // Skip this flag logic, it is unreliable. Detecting subclasses
9868               // is far better.
9869               switch (o->flag & 31)
9870                 {
9871                 case 0: // rotated, horizontal or vertical
9872                   LOG_TRACE ("Looks like %s\n", "DIMENSION_LINEAR");
9873                   // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_LINEAR);
9874                   break;
9875                 case 1:
9876                   LOG_TRACE ("Looks like %s\n", "DIMENSION_ALIGNED");
9877                   // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ALIGNED);
9878                   break;
9879                 case 2: // already?
9880                   LOG_TRACE ("Looks like %s\n", "DIMENSION_ANG2LN");
9881                   // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ANG2LN);
9882                   break;
9883                 case 3:
9884                   LOG_TRACE ("Looks like %s\n", "DIMENSION_DIAMETER");
9885                   // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_DIAMETER);
9886                   break;
9887                 case 4:
9888                   LOG_TRACE ("Looks like %s\n", "DIMENSION_RADIUS");
9889                   // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_RADIUS);
9890                   break;
9891                 case 5:
9892                   LOG_TRACE ("Looks like %s\n", "DIMENSION_ANG3PT");
9893                   // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ANG3PT);
9894                   break;
9895                 case 6:
9896                   LOG_TRACE ("Looks like DIMENSION_LINEAR\n");
9897                   // UPGRADE_ENTITY (DIMENSION_ANG2LN, DIMENSION_ORDINATE);
9898                   break;
9899                 default:
9900                   LOG_ERROR ("Invalid DIMENSION.flag %d", o->flag & 31);
9901                   error |= DWG_ERR_INVALIDTYPE;
9902                   break;
9903                 }
9904               break;
9905             }
9906           // fall through
9907         case 420: // color.rgb's
9908         case 421:
9909         case 422:
9910         case 423:
9911         case 424:
9912         case 425:
9913         case 426:
9914         case 427:
9915         case 428:
9916           // note that there is a DIMSTYLE.DIMTFILL with rgb 428. so far I only
9917           // found index 70, not rgb 428
9918           if (pair->code >= 420 && pair->code <= 428)
9919             {
9920               const char *fname = NULL;
9921               if (pair->code == 420 && strEQc (name, "LAYER"))
9922                 fname = "color";
9923               else if (pair->code == 421 && strEQc (name, "LIGHT"))
9924                 fname = "color";
9925               else if (pair->code == 421
9926                        && (strEQc (name, "VPORT") || strEQc (name, "VIEWPORT")
9927                            || strEQc (name, "VIEW")))
9928                 fname = "ambient_color";
9929               else if (pair->code == 421 && strEQc (name, "MTEXT"))
9930                 fname = "bg_fill_color";
9931               else if (pair->code == 420 && strEQc (name, "MLINESTYLE"))
9932                 // TODO or lines[].color
9933                 fname = "fill_color";
9934               else if (pair->code == 420 && strEQc (name, "VISUALSTYLE"))
9935                 break; // ignore. always index 5
9936               else if (pair->code == 421 && strEQc (name, "VISUALSTYLE"))
9937                 fname = "face_mono_color";
9938               else if (pair->code == 422 && strEQc (name, "VISUALSTYLE"))
9939                 fname = "edge_intersection_color";
9940               else if (pair->code == 423 && strEQc (name, "VISUALSTYLE"))
9941                 fname = "edge_obscured_color";
9942               else if (pair->code == 424 && strEQc (name, "VISUALSTYLE"))
9943                 fname = "edge_color";
9944               else if (pair->code == 425 && strEQc (name, "VISUALSTYLE"))
9945                 fname = "edge_silhouette_color";
9946               else if (pair->code == 428 && strEQc (name, "DIMSTYLE"))
9947                 fname = "DIMTFILL";
9948               else if (strEQc (name, "TABLE"))
9949                 {
9950                   BITCODE_BL table_flag
9951                       = obj->tio.entity->tio.TABLE->table_flag_override;
9952                   BITCODE_BL border_color = obj->tio.entity->tio.TABLE
9953                                                 ->border_color_overrides_flag;
9954                   if (pair->code == 421)
9955                     {
9956                       if (table_flag & 0x0800)
9957                         fname = "title_row_fill_color";
9958                       else if (table_flag & 0x01000)
9959                         fname = "header_row_fill_color";
9960                       else if (table_flag & 0x02000)
9961                         fname = "data_row_fill_color";
9962                       else if (border_color & 0x0008)
9963                         fname = "title_vert_left_color";
9964                       else if (border_color & 0x0200)
9965                         fname = "header_vert_left_color";
9966                       else if (border_color & 0x8000)
9967                         fname = "data_vert_left_color";
9968                     }
9969                   else if (pair->code == 422)
9970                     {
9971                       if (table_flag & 0x0020)
9972                         fname = "title_row_color";
9973                       else if (table_flag & 0x0040)
9974                         fname = "header_row_color";
9975                       else if (table_flag & 0x0080)
9976                         fname = "data_row_color";
9977                       else if (border_color & 0x0001)
9978                         fname = "title_horiz_top_color";
9979                       else if (border_color & 0x0040)
9980                         fname = "header_horiz_top_color";
9981                       else if (border_color & 0x1000)
9982                         fname = "data_horiz_top_color";
9983                     }
9984                   else if (pair->code == 423)
9985                     {
9986                       if (border_color & 0x0002)
9987                         fname = "title_horiz_ins_color";
9988                       else if (border_color & 0x0080)
9989                         fname = "header_horiz_ins_color";
9990                       else if (border_color & 0x2000)
9991                         fname = "data_horiz_ins_color";
9992                     }
9993                   else if (pair->code == 424)
9994                     {
9995                       if (border_color & 0x0004)
9996                         fname = "title_horiz_bottom_color";
9997                       else if (border_color & 0x0100)
9998                         fname = "header_horiz_bottom_color";
9999                       else if (border_color & 0x4000)
10000                         fname = "data_horiz_bottom_color";
10001                     }
10002                   else if (pair->code == 426)
10003                     {
10004                       if (border_color & 0x0010)
10005                         fname = "title_vert_ins_color";
10006                       else if (border_color & 0x0400)
10007                         fname = "header_vert_ins_color";
10008                       else if (border_color & 0x10000)
10009                         fname = "data_vert_ins_color";
10010                     }
10011                   else if (pair->code == 427)
10012                     {
10013                       if (border_color & 0x0020)
10014                         fname = "title_vert_right_color";
10015                       else if (border_color & 0x0800)
10016                         fname = "header_vert_right_color";
10017                       else if (border_color & 0x20000)
10018                         fname = "data_vert_right_color";
10019                     }
10020                 }
10021 
10022               if (fname)
10023                 {
10024                   BITCODE_CMC color;
10025                   dwg_dynapi_entity_value (_obj, obj->name, fname, &color,
10026                                            NULL);
10027                   color.method = 0xc2;
10028                   color.rgb = pair->value.l;
10029                   color.rgb |= 0xc2000000;
10030                   LOG_TRACE ("%s.%s.rgb = %08X [CMC %d]\n", name, fname,
10031                              color.rgb, pair->code);
10032                   dwg_dynapi_entity_set_value (_obj, obj->name, fname, &color,
10033                                                is_tu);
10034                   break;
10035                 }
10036             }
10037           // fall through
10038         default:
10039         object_default:
10040           if (pair->code >= 1000 && pair->code < 1999)
10041             add_eed (obj, obj->name, pair);
10042           else if (pair->code != 280 && strEQc (name, "XRECORD"))
10043             pair = add_xdata (dat, obj, pair);
10044           else if (pair->code == 310 && strEQc (obj->name, "BLOCK_HEADER"))
10045             {
10046               pair = add_block_preview (obj, dat, pair);
10047               goto start_loop;
10048             }
10049           else if (pair->code == 90 && obj->fixedtype == DWG_TYPE_OLE2FRAME)
10050             {
10051               Dwg_Entity_OLE2FRAME *o = obj->tio.entity->tio.OLE2FRAME;
10052               o->data_size = pair->value.l;
10053               o->data = (BITCODE_RC *)xcalloc (pair->value.l, 1);
10054               if (!o->data)
10055                 {
10056                   o->data_size = 0;
10057                   goto invalid_dxf;
10058                 }
10059               LOG_TRACE ("OLE2FRAME.data_size = %ld [BL 90]\n", pair->value.l);
10060             }
10061           else if (pair->code == 90 && obj->fixedtype == DWG_TYPE_PERSUBENTMGR)
10062             {
10063               pair = add_PERSUBENTMGR (obj, dat, pair); // NULL for success
10064               if (!pair)
10065                 goto next_pair;
10066               else
10067                 goto start_loop; /* failure */
10068             }
10069           else if ((pair->code == 71 || pair->code == 75 || pair->code == 1)
10070                    && obj->fixedtype == DWG_TYPE_DIMASSOC)
10071             {
10072               pair = add_DIMASSOC (obj, dat, pair);
10073               // returns with 0
10074               if (pair != NULL && pair->code == 0)
10075                 goto start_loop;
10076               else
10077                 goto search_field;
10078             }
10079           else if ((pair->code == 8 || pair->code == 90)
10080                    && obj->fixedtype == DWG_TYPE_LAYER_INDEX)
10081             {
10082               pair = add_LAYER_entry (obj, dat, pair);
10083               // returns with 0
10084               if (pair != NULL && pair->code == 0)
10085                 goto start_loop;
10086               else
10087                 goto search_field;
10088             }
10089           else if (pair->code == 91 && obj->fixedtype == DWG_TYPE_EVALUATION_GRAPH)
10090             {
10091               pair = add_EVAL_Node (obj, dat, pair);
10092               // returns with 0
10093               if (pair != NULL && pair->code == 0)
10094                 goto start_loop;
10095               else
10096                 goto search_field;
10097             }
10098           else if (pair->code == 310 && obj->fixedtype == DWG_TYPE_OLE2FRAME)
10099             {
10100               Dwg_Entity_OLE2FRAME *o = obj->tio.entity->tio.OLE2FRAME;
10101               unsigned len = strlen (pair->value.s);
10102               unsigned blen = len / 2;
10103               unsigned read;
10104               //const char *pos = pair->value.s;
10105               unsigned char *s = (unsigned char *)&o->data[written];
10106               assert (o->data);
10107               if (blen + written > o->data_size)
10108                 {
10109                   LOG_ERROR ("OLE2FRAME.data overflow: %u + written %u > "
10110                              "data_size: %u",
10111                              blen, written, o->data_size);
10112                   goto invalid_dxf;
10113                 }
10114               if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
10115                 LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
10116               written += read;
10117               LOG_TRACE ("OLE2FRAME.data += %u (%u/%u) [TF 310]\n", blen,
10118                          written, o->data_size);
10119             }
10120           else if (pair->code == 1
10121                    && ((strEQc (name, "_3DSOLID") || strEQc (name, "BODY")
10122                         || strEQc (name, "REGION"))
10123                        || strEQc (subclass, "AcDbModelerGeometry")))
10124             {
10125               j = 0;
10126               k = 0;
10127               // check if the object is valid
10128               if (!dwg_obj_is_3dsolid (obj))
10129                 {
10130                   LOG_ERROR ("%s not a 3DSOLID", name);
10131                   goto invalid_dxf;
10132                 }
10133               pair = add_3DSOLID_encr (obj, dat, pair);
10134               goto start_loop;
10135             }
10136           else if (pair->code == 1 && obj->fixedtype == DWG_TYPE_LAYOUT)
10137             {
10138               Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
10139               if (strEQc (subclass, "AcDbPlotSettings"))
10140                 {
10141                   const Dwg_DYNAPI_field *f = dwg_dynapi_entity_field (
10142                       "PLOTSETTINGS", "printer_cfg_file");
10143                   dwg_dynapi_field_set_value (dwg, &o->plotsettings, f,
10144                                               &pair->value, 1);
10145                   LOG_TRACE ("%s.plotsettings.printer_cfg_file = %s [T 1]\n",
10146                              obj->name, pair->value.s);
10147                 }
10148               else if (strEQc (subclass, "AcDbLayout"))
10149                 {
10150                   dwg_dynapi_entity_set_value (_obj, obj->name, "layout_name",
10151                                                &pair->value, 1);
10152                   LOG_TRACE ("%s.layout_name = %s [T 1]\n", obj->name,
10153                              pair->value.s);
10154                 }
10155               else
10156                 LOG_WARN ("Unhandled LAYOUT.1 in subclass %s", subclass);
10157               goto next_pair;
10158             }
10159           else if (pair->code == 3 && obj->fixedtype == DWG_TYPE_MTEXT)
10160             {
10161               Dwg_Entity_MTEXT *o = obj->tio.entity->tio.MTEXT;
10162               unsigned len = strlen (pair->value.s);
10163               if (!o->text)
10164                 {
10165                   o->text = strdup (pair->value.s);
10166                   written = len;
10167                   LOG_TRACE ("MTEXT.text = %s (%u) [TV 3]\n", pair->value.s, len);
10168                 }
10169               else
10170                 {
10171                   assert (o->text);
10172                   if (strlen (o->text) < len)
10173                     o->text = realloc (o->text, len + 1);
10174                   strcpy (o->text, pair->value.s);
10175                   written += len;
10176                   LOG_TRACE ("MTEXT.text += %u/%u [TV 3]\n", len, written);
10177                 }
10178             }
10179           /*
10180           else if (pair->code == 2 && obj->fixedtype == DWG_TYPE_LAYOUT)
10181             {
10182               Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
10183               const Dwg_DYNAPI_field *f = dwg_dynapi_entity_field
10184           ("PLOTSETTINGS", "paper_size"); dwg_dynapi_field_set_value (dwg,
10185           &o->plotsettings, f, &pair->value, 1); LOG_TRACE
10186           ("%s.plotsettings.paper_size = %s [T 2]\n", obj->name,
10187           pair->value.s); goto next_pair;
10188             }
10189           */
10190           else if (pair->code == 370 && obj->fixedtype == DWG_TYPE_LAYER)
10191             {
10192               Dwg_Object_LAYER *layer = obj->tio.object->tio.LAYER;
10193               layer->linewt = dxf_find_lweight (pair->value.i);
10194               LOG_TRACE ("LAYER.linewt = %d\n", layer->linewt);
10195               layer->flag |= layer->linewt << 5;
10196               LOG_TRACE ("LAYER.flag = 0x%x [BS 70]\n", layer->flag);
10197               goto next_pair;
10198             }
10199           else if (pair->code == 370 && obj->supertype == DWG_SUPERTYPE_ENTITY
10200                    && strEQc (subclass, "AcDbEntity"))
10201             {
10202               BITCODE_RC linewt = dxf_find_lweight (pair->value.i);
10203               dwg_dynapi_common_set_value (_obj, "linewt", &linewt, 0);
10204               LOG_TRACE ("COMMON.linewt => %d [RC 370]\n", linewt);
10205               goto next_pair;
10206             }
10207           else if (pair->code == 48 && obj->supertype == DWG_SUPERTYPE_ENTITY
10208                    && strEQc (subclass, "AcDbEntity"))
10209             {
10210               dwg_dynapi_common_set_value (_obj, "ltype_scale", &pair->value.d, 0);
10211               LOG_TRACE ("COMMON.ltype_scale = %f [BD 48]\n", pair->value.d);
10212               goto next_pair;
10213             }
10214           else if (pair->code == 49 && obj->fixedtype == DWG_TYPE_LTYPE)
10215             {
10216               pair = add_LTYPE_dashes (obj, dat, pair);
10217               if (pair != NULL && pair->code == 0)
10218                 return pair;
10219               goto next_pair;
10220             }
10221           else if (pair->code == 71 && obj->fixedtype == DWG_TYPE_MLINESTYLE
10222                    && pair->value.i != 0)
10223             {
10224               pair = add_MLINESTYLE_lines (obj, dat, pair);
10225               if (pair != NULL && pair->code == 0)
10226                 return pair;
10227               goto next_pair;
10228             }
10229           else if (pair->code == 65 && obj->fixedtype == DWG_TYPE_VPORT)
10230             {
10231               Dwg_Object_VPORT *o = obj->tio.object->tio.VPORT;
10232               o->UCSVP = pair->value.i;
10233               o->UCSFOLLOW = o->VIEWMODE & 4 ? 1 : 0;
10234               o->VIEWMODE |= o->UCSVP;
10235               LOG_TRACE ("VPORT.UCSVP = %d [B 65]\n", o->UCSVP)
10236               LOG_TRACE ("VPORT.UCSFOLLOW => %d [B 0] (calc)\n", o->UCSFOLLOW)
10237               LOG_TRACE ("VPORT.VIEWMODE => %d [4BITS 71] (calc)\n",
10238                          o->VIEWMODE)
10239               goto next_pair;
10240             }
10241           else if (pair->code == 90 && obj->fixedtype == DWG_TYPE_LWPOLYLINE)
10242             {
10243               pair = new_LWPOLYLINE (obj, dat, pair);
10244               if (pair != NULL && pair->code == 0)
10245                 return pair;
10246               goto next_pair;
10247             }
10248           else if (pair->code == 350 && strEQc (subclass, "AcDb3dSolid")
10249                    && dwg_obj_is_3dsolid (obj))
10250             {
10251               Dwg_Entity__3DSOLID *o = obj->tio.entity->tio._3DSOLID;
10252               BITCODE_H hdl = dwg_add_handleref (dwg, 5, pair->value.u, obj);
10253               LOG_TRACE ("%s.history_id = " FORMAT_REF " [H 350]\n", obj->name,
10254                          ARGS_REF (hdl));
10255               o->history_id = hdl;
10256             }
10257           else if (obj->fixedtype == DWG_TYPE_MLINE)
10258             {
10259               int status = add_MLINE (obj, dat, pair, &j, &k, &l);
10260               if (status == 0)
10261                 goto search_field;
10262               else if (status == 2)
10263                 break;
10264             }
10265           else if (strEQc (name, "VERTEX_PFACE_FACE") && pair->code >= 71
10266                    && pair->code <= 74)
10267             {
10268               Dwg_Entity_VERTEX_PFACE_FACE *o
10269                   = (Dwg_Entity_VERTEX_PFACE_FACE *)_obj;
10270               j = pair->code - 71;
10271               o->vertind[j] = pair->value.i;
10272               LOG_TRACE ("VERTEX_PFACE_FACE.vertind[%d] = %d [BS %d]\n", j,
10273                          pair->value.i, pair->code);
10274             }
10275           else if (obj->fixedtype == DWG_TYPE_SPLINE)
10276             {
10277               if (pair->code == 210 || pair->code == 220 || pair->code == 230)
10278                 break; // ignore extrusion in the dwg (planar only)
10279               if (add_SPLINE (obj->tio.entity->tio.SPLINE, dat, pair, &j,
10280                               &flag))
10281                 goto next_pair;
10282               else
10283                 goto search_field;
10284             }
10285           else if (obj->fixedtype == DWG_TYPE_HATCH)
10286             {
10287               if ((pair->code == 10 || pair->code == 20) && pair->value.d == 0.0)
10288                 break; // elevation
10289               else if (pair->code == 91 || pair->code == 78
10290                        || pair->code == 453)
10291                 {
10292                   pair = add_HATCH (obj, dat, pair);
10293                   if (!pair || pair->code == 0) // end or unknown
10294                     return pair;
10295                   goto search_field;
10296                 }
10297               else
10298                 goto search_field;
10299             }
10300           else if (is_textlike (obj))
10301             {
10302               BITCODE_RC dataflags;
10303               if (pair->code == 10 || pair->code == 20)
10304                 goto search_field;
10305               else if (pair->code == 30 && pair->value.d == 0.0)
10306                 {
10307                   dwg_dynapi_entity_value (_obj, obj->name, "dataflags",
10308                                            &dataflags, NULL);
10309                   dataflags |= 1;
10310                   LOG_TRACE ("%s.elevation 0.0 => dataflags = 0x%x\n",
10311                              obj->name, dataflags);
10312                   dwg_dynapi_entity_set_value (_obj, obj->name, "dataflags",
10313                                                &dataflags, 0);
10314                 }
10315               else
10316                 goto search_field;
10317             }
10318           else if (obj->fixedtype == DWG_TYPE_MESH)
10319             {
10320               if (pair->code == 91)
10321                 {
10322                   pair = add_MESH (obj, dat, pair);
10323                   if (!pair || pair->code == 0) // end or unknown
10324                     return pair;
10325                   goto search_field;
10326                 }
10327               else
10328                 goto search_field;
10329             }
10330           else if (obj->fixedtype == DWG_TYPE_MLEADERSTYLE)
10331             {
10332               Dwg_Object_MLEADERSTYLE *o = obj->tio.object->tio.MLEADERSTYLE;
10333               if (pair->code == 47)
10334                 o->block_scale.x = pair->value.d;
10335               else if (pair->code == 49)
10336                 o->block_scale.y = pair->value.d;
10337               else if (pair->code == 140)
10338                 {
10339                   o->block_scale.z = pair->value.d;
10340                   LOG_TRACE (
10341                       "MLEADERSTYLE.block_scale = (%f, %f, %f) [3BD 47]\n",
10342                       o->block_scale.x, o->block_scale.y, o->block_scale.z);
10343                 }
10344               else if (pair->code == 297 && o->class_version < 2)
10345                 {
10346                   LOG_TRACE ("MLEADERSTYLE.text_always_left = %d [B 297] => "
10347                              "class_version 2\n",
10348                              pair->value.i);
10349                   o->text_always_left = pair->value.i;
10350                   o->class_version = 2;
10351                 }
10352               else
10353                 goto search_field;
10354             }
10355           else if (obj->fixedtype == DWG_TYPE_MTEXT && pair->code == 46)
10356             {
10357               Dwg_Entity_MTEXT *o = obj->tio.entity->tio.MTEXT;
10358               if (!o->num_column_heights)
10359                 o->num_column_heights = 1;
10360               if (!j)
10361                 {
10362                   o->column_heights = (BITCODE_BD *)xcalloc (
10363                       o->num_column_heights, sizeof (BITCODE_BD));
10364                   if (!o->column_heights)
10365                     {
10366                       o->num_column_heights = 0;
10367                       goto invalid_dxf;
10368                     }
10369                 }
10370               if (j < 0 || j >= (int)o->num_column_heights
10371                   || !o->column_heights)
10372                 goto invalid_dxf;
10373               assert (j < (int)o->num_column_heights);
10374               o->column_heights[j] = pair->value.d;
10375               LOG_TRACE ("MTEXT.column_heights[%d] = %f [BD* 46]\n", j,
10376                          pair->value.d);
10377             }
10378           else if (obj->fixedtype == DWG_TYPE_GEODATA)
10379             {
10380               pair = add_GEODATA (obj, dat, pair);
10381               if (pair && pair->code != 0)
10382                 goto search_field;
10383               else
10384                 return pair;
10385             }
10386           else if (pair->code == 300 && obj->fixedtype == DWG_TYPE_CELLSTYLEMAP
10387                    && strEQc (pair->value.s, "CELLSTYLE"))
10388             {
10389               Dwg_Object_CELLSTYLEMAP *o = obj->tio.object->tio.CELLSTYLEMAP;
10390               cur_cell++;
10391               if (cur_cell < 0 || cur_cell >= (int)o->num_cells)
10392                 goto invalid_dxf;
10393             }
10394           else if (pair->code == 1 && pair->value.s
10395                    && strEQc (pair->value.s, "TABLEFORMAT_BEGIN")
10396                    && (obj->fixedtype == DWG_TYPE_CELLSTYLEMAP
10397                        || obj->fixedtype == DWG_TYPE_TABLE
10398                        || obj->fixedtype == DWG_TYPE_TABLESTYLE
10399                        || obj->fixedtype == DWG_TYPE_TABLECONTENT))
10400             {
10401               Dwg_CellStyle *csty = NULL;
10402               Dwg_TABLESTYLE_CellStyle *tbl_sty = NULL;
10403               char key[80];
10404               if (obj->fixedtype == DWG_TYPE_CELLSTYLEMAP)
10405                 {
10406                   Dwg_Object_CELLSTYLEMAP *o
10407                       = obj->tio.object->tio.CELLSTYLEMAP;
10408                   if (cur_cell < 0 || cur_cell >= (int)o->num_cells)
10409                     goto invalid_dxf;
10410                   if (cur_cell == 0 && !o->cells)
10411                     o->cells = (Dwg_TABLESTYLE_CellStyle *)xcalloc (
10412                         o->num_cells, sizeof (Dwg_TABLESTYLE_CellStyle));
10413                   tbl_sty = &o->cells[cur_cell];
10414                   sprintf (key, "cells[%d]", cur_cell);
10415                   csty = &tbl_sty->cellstyle;
10416                 }
10417               else if (obj->fixedtype == DWG_TYPE_TABLESTYLE)
10418                 {
10419                   // TODO ovr
10420                   Dwg_Object_TABLESTYLE *o = obj->tio.object->tio.TABLESTYLE;
10421                   tbl_sty = &o->sty;
10422                   csty = &o->sty.cellstyle;
10423                 }
10424               if (csty)
10425                 pair = add_CellStyle (obj, csty, &key[0], dat, pair);
10426               if (pair && pair->code != 0)
10427                 {
10428                   if (tbl_sty && pair->code == 90)
10429                     {
10430                       tbl_sty->id = pair->value.u;
10431                       LOG_TRACE ("%s.%s.id = " FORMAT_BL " [BL %d]\n",
10432                                  obj->name, key, pair->value.u, pair->code);
10433                       dxf_free_pair (pair);
10434                       pair = dxf_read_pair (dat);
10435                     }
10436                   if (tbl_sty && pair && pair->code == 91)
10437                     {
10438                       tbl_sty->type = pair->value.u;
10439                       LOG_TRACE ("%s.%s.type = " FORMAT_BL " [BL %d]\n",
10440                                  obj->name, key, pair->value.u, pair->code);
10441                       dxf_free_pair (pair);
10442                       pair = dxf_read_pair (dat);
10443                     }
10444                   if (tbl_sty && pair && pair->code == 300)
10445                     {
10446                       tbl_sty->name = dwg_add_u8_input (dwg, pair->value.s);
10447                       LOG_TRACE ("%s.%s.name = \"%s\" [BL %d]\n", obj->name,
10448                                  key, pair->value.s, pair->code);
10449                       dxf_free_pair (pair);
10450                       pair = dxf_read_pair (dat);
10451                     }
10452                   if (tbl_sty && pair && pair->code == 309
10453                       && strEQc (pair->value.s, "CELLSTYLE_END"))
10454                     goto next_pair;
10455                   else
10456                     goto search_field;
10457                 }
10458               else
10459                 return pair;
10460             }
10461           else if (obj->fixedtype == DWG_TYPE_VPORT && pair->code == 41)
10462             {
10463               Dwg_Object_VPORT *o = obj->tio.object->tio.VPORT;
10464               o->aspect_ratio = pair->value.d;
10465               o->view_width = o->aspect_ratio * o->VIEWSIZE;
10466               LOG_TRACE ("VPORT.aspect_ratio = %f [BD 41]\n", o->aspect_ratio);
10467               LOG_TRACE ("VPORT.view_width = %f [BD 0]\n", o->view_width);
10468             }
10469           else if (strEQc (subclass, "AcDbShHistoryNode"))
10470             {
10471               // add_AcDbShHistoryNode (obj, _obj)
10472               Dwg_ACSH_HistoryNode *hn;
10473               const Dwg_DYNAPI_field *f1
10474                   = dwg_dynapi_entity_field (obj->name, "history_node");
10475               if (!f1)
10476                 goto search_field;
10477               hn = (Dwg_ACSH_HistoryNode *)&((char *)_obj)[f1->offset];
10478               if (pair->code == 90)
10479                 {
10480                   hn->major = pair->value.u;
10481                   LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", name, "history_node",
10482                              "major", pair->value.u, pair->code);
10483                 }
10484               else if (pair->code == 91)
10485                 {
10486                   hn->minor = pair->value.u;
10487                   LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", name, "history_node",
10488                              "minor", pair->value.u, pair->code);
10489                 }
10490               else if (pair->code == 92)
10491                 {
10492                   hn->step_id = pair->value.u;
10493                   LOG_TRACE ("%s.%s.%s = %u [BL %d]\n", name, "history_node",
10494                              "step_id", pair->value.u, pair->code);
10495                 }
10496               else if (pair->code == 62)
10497                 {
10498                 hn_color:
10499                   hn->color.index = pair->value.l;
10500                   LOG_TRACE ("%s.%s.%s.index = %u [CMC %d]\n", name,
10501                              "history_node", "color", pair->value.u,
10502                              pair->code);
10503                 }
10504               else if (pair->code == 347)
10505                 {
10506                   hn->material
10507                       = dwg_add_handleref (dwg, 5, pair->value.u, obj);
10508                   LOG_TRACE ("%s.%s.%s = " FORMAT_REF " [H %d]\n", name,
10509                              "history_node", "material",
10510                              ARGS_REF (hn->material), pair->code);
10511                 }
10512               else if (hn && pair->code == 40) // VECTOR_N1
10513                 {
10514                   hn->trans = (BITCODE_BD *)xcalloc (16, sizeof (BITCODE_BD));
10515                   if (!hn->trans)
10516                     return NULL;
10517                   // BD* starting at 40-55
10518                   for (j = 0; j < 16; j++)
10519                     {
10520                       hn->trans[j] = pair->value.d;
10521                       LOG_TRACE ("%s.history_node.trans[%d] = %f [BD %d]\n",
10522                                  obj->name, j, pair->value.d, j + 40);
10523                       dxf_free_pair (pair);
10524                       pair = dxf_read_pair (dat);
10525                       if (!pair || pair->code == 0)
10526                         return pair;
10527                       if (pair->code == 62)
10528                         goto hn_color;
10529                       if (pair->code != j + 41)
10530                         goto search_field;
10531                     }
10532                 }
10533             }
10534           else if (dwg_obj_is_acsh (obj) && memBEGINc (subclass, "AcDbSh")
10535                    && (pair->code == 90 || pair->code == 91))
10536             {
10537               const char *_key = pair->code == 90 ? "major" : "minor";
10538               const Dwg_DYNAPI_field *f1
10539                   = dwg_dynapi_entity_field (obj->name, _key);
10540               if (!f1)
10541                 goto search_field;
10542               dwg_dynapi_field_set_value (dwg, _obj, f1, &pair->value, 0);
10543               LOG_TRACE ("%s.%s = %u [BL %d]\n", name, _key, pair->value.u,
10544                          pair->code);
10545             }
10546           else if (strEQc (subclass, "AcDbEvalExpr"))
10547             {
10548               pair = add_AcDbEvalExpr (obj, (char *)_obj, dat, pair);
10549               if (pair && pair->code == 100) // success
10550                 goto start_loop;
10551               else
10552                 goto search_field;
10553             }
10554           else if (obj->fixedtype == DWG_TYPE_LEADER
10555                    && (pair->code == 10 || pair->code == 20
10556                        || pair->code == 30))
10557             {
10558               Dwg_Entity_LEADER *o = obj->tio.entity->tio.LEADER;
10559               if (!j && pair->code == 10)
10560                 {
10561                   o->points = (BITCODE_3BD *)xcalloc (o->num_points,
10562                                                       sizeof (BITCODE_3BD));
10563                   if (!o->points)
10564                     {
10565                       o->num_points = 0;
10566                       goto invalid_dxf;
10567                     }
10568                 }
10569               if (j < 0 || j >= (int)o->num_points || !o->points)
10570                 goto invalid_dxf;
10571               assert (j >= 0);
10572               assert (j < (int)o->num_points);
10573               assert (o->points);
10574 
10575               if (pair->code == 10)
10576                 o->points[j].x = pair->value.d;
10577               else if (pair->code == 20)
10578                 o->points[j].y = pair->value.d;
10579               else if (pair->code == 30)
10580                 {
10581                   o->points[j].z = pair->value.d;
10582                   LOG_TRACE ("LEADER.points[%d] = (%f, %f, %f) [3BD* 10]\n", j,
10583                              o->points[j].x, o->points[j].y, o->points[j].z);
10584                   j++;
10585                 }
10586             }
10587           else if (pair->code == 71
10588                    && strEQc (subclass, "AcDbSectionViewStyle"))
10589             {
10590               pair = add_AcDbSectionViewStyle (obj, dat);
10591               if (!pair) // success
10592                 goto start_loop;
10593               else
10594                 goto search_field;
10595             }
10596           else if (pair->code == 71
10597                    && strEQc (subclass, "AcDbDetailViewStyle")
10598                    && obj->fixedtype == DWG_TYPE_DETAILVIEWSTYLE)
10599             {
10600               pair = add_AcDbDetailViewStyle (obj, dat);
10601               if (pair && pair->code == 100) // success
10602                 goto start_loop;
10603               else
10604                 goto search_field;
10605             }
10606           else if (pair->code == 300 && strEQc (subclass, "AcDbBlockElement"))
10607             {
10608               pair = add_AcDbBlockElement (obj, (char *)_obj, dat, pair);
10609               if (!pair) // success
10610                 goto start_loop;
10611               else
10612                 goto search_field;
10613             }
10614           else if (pair->code == 91 && strEQc (subclass, "AcDbBlockgrip"))
10615             {
10616               pair = add_AcDbBlockGrip (obj, (char *)_obj, dat, pair);
10617               if (!pair) // success
10618                 goto start_loop;
10619               else
10620                 goto search_field;
10621             }
10622           else if (pair->code == 93 && strEQc (subclass, "AcDbBlockVisibilityParameter"))
10623             {
10624               pair = add_AcDbBlockVisibilityParameter (
10625                   obj, (Dwg_Object_BLOCKVISIBILITYPARAMETER *)_obj, dat, pair);
10626               if (!pair) // success
10627                 goto start_loop;
10628               else
10629                 goto search_field;
10630             }
10631           else if (pair->code == 307
10632                    && strEQc (subclass, "AcDbBlockLinearConstraintParameter"))
10633             {
10634               Dwg_BLOCKPARAMVALUESET *value_set
10635                   = &((Dwg_Object_BLOCKALIGNEDCONSTRAINTPARAMETER *)_obj)
10636                          ->value_set;
10637               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10638               if (!pair) // success
10639                 goto start_loop;
10640               else
10641                 goto search_field;
10642             }
10643           else if (pair->code == 307 && strEQc (obj->name, "BLOCKLINEARPARAMETER"))
10644             {
10645               Dwg_BLOCKPARAMVALUESET *value_set
10646                   = &((Dwg_Object_BLOCKLINEARPARAMETER *)_obj)
10647                          ->value_set;
10648               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10649               if (!pair) // success
10650                 goto start_loop;
10651               else
10652                 goto search_field;
10653             }
10654           else if (pair->code == 307 && strEQc (obj->name, "BLOCKROTATIONPARAMETER"))
10655             {
10656               Dwg_BLOCKPARAMVALUESET *value_set
10657                   = &((Dwg_Object_BLOCKROTATIONPARAMETER *)_obj)
10658                          ->angle_value_set;
10659               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10660               if (!pair) // success
10661                 goto start_loop;
10662               else
10663                 goto search_field;
10664             }
10665           else if (pair->code == 307 && strEQc (obj->name, "BLOCKANGULARCONSTRAINTPARAMETER"))
10666             {
10667               Dwg_BLOCKPARAMVALUESET *value_set
10668                   = &((Dwg_Object_BLOCKANGULARCONSTRAINTPARAMETER *)_obj)
10669                          ->value_set;
10670               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10671               if (!pair) // success
10672                 goto start_loop;
10673               else
10674                 goto search_field;
10675             }
10676           else if (pair->code == 307 && strEQc (obj->name, "BLOCKDIAMETRICCONSTRAINTPARAMETER"))
10677             {
10678               Dwg_BLOCKPARAMVALUESET *value_set
10679                   = &((Dwg_Object_BLOCKDIAMETRICCONSTRAINTPARAMETER *)_obj)
10680                          ->value_set;
10681               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10682               if (!pair) // success
10683                 goto start_loop;
10684               else
10685                 goto search_field;
10686             }
10687           else if (pair->code == 307 && strEQc (obj->name, "BLOCKRADIALCONSTRAINTPARAMETER"))
10688             {
10689               Dwg_BLOCKPARAMVALUESET *value_set
10690                   = &((Dwg_Object_BLOCKRADIALCONSTRAINTPARAMETER *)_obj)
10691                          ->value_set;
10692               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10693               if (!pair) // success
10694                 goto start_loop;
10695               else
10696                 goto search_field;
10697             }
10698           else if (pair->code == 309 && strEQc (obj->name, "BLOCKXYPARAMETER"))
10699             {
10700               Dwg_BLOCKPARAMVALUESET *value_set
10701                   = &((Dwg_Object_BLOCKXYPARAMETER *)_obj)
10702                          ->y_value_set;
10703               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10704               if (!pair) // success
10705                 goto start_loop;
10706               else
10707                 goto search_field;
10708             }
10709           else if (pair->code == 309 && strEQc (obj->name, "BLOCKPOLARPARAMETER"))
10710             {
10711               Dwg_BLOCKPARAMVALUESET *value_set
10712                   = &((Dwg_Object_BLOCKPOLARPARAMETER *)_obj)
10713                          ->distance_value_set;
10714               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10715               if (!pair) // success
10716                 goto start_loop;
10717               else
10718                 goto search_field;
10719             }
10720           else if (pair->code == 410 && strEQc (obj->name, "BLOCKXYPARAMETER"))
10721             {
10722               Dwg_BLOCKPARAMVALUESET *value_set
10723                   = &((Dwg_Object_BLOCKXYPARAMETER *)_obj)
10724                          ->x_value_set;
10725               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10726               if (!pair) // success
10727                 goto start_loop;
10728               else
10729                 goto search_field;
10730             }
10731           else if (pair->code == 410 && strEQc (obj->name, "BLOCKPOLARPARAMETER"))
10732             {
10733               Dwg_BLOCKPARAMVALUESET *value_set
10734                   = &((Dwg_Object_BLOCKPOLARPARAMETER *)_obj)
10735                          ->angle_value_set;
10736               pair = add_AcDbBlockParamValueSet (obj, value_set, dat, pair);
10737               if (!pair) // success
10738                 goto start_loop;
10739               else
10740                 goto search_field;
10741             }
10742           else if (pair->code == 8 && obj->fixedtype == DWG_TYPE_LAYERFILTER
10743                    && strEQc (subclass, "AcDbLayerFilter"))
10744             {
10745               // num_names
10746               Dwg_Object_LAYERFILTER *o = obj->tio.object->tio.LAYERFILTER;
10747               if (!o->names)
10748                 {
10749                   o->names = (BITCODE_T *)xcalloc (1, sizeof (BITCODE_T));
10750                   j = 0;
10751                 }
10752               else
10753                 o->names = (BITCODE_T *)realloc (
10754                     o->names, (o->num_names + 1) * sizeof (BITCODE_T));
10755               if (!o->names || j < 0 || j >= (int)o->num_names)
10756                 goto invalid_dxf;
10757               assert (j >= 0 && j < (int)o->num_names && o->names);
10758               o->names[j] = dwg_add_u8_input (dwg, pair->value.s);
10759               LOG_TRACE ("%s.%s[%d] = %s [%s %d]\n", name, "names", j,
10760                          pair->value.s, "T", pair->code);
10761               j++;
10762               o->num_names = j;
10763               goto next_pair;
10764             }
10765           else
10766           search_field:
10767             { // search all specific fields and common fields for the DXF
10768               const Dwg_DYNAPI_field *f;
10769               const Dwg_DYNAPI_field *fields
10770                   = dwg_dynapi_entity_fields (obj->name);
10771               if (!pair || pair->code == 0)
10772                 break;
10773               if (!fields)
10774                 {
10775                   LOG_ERROR ("Illegal object name %s, no dynapi fields",
10776                              obj->name);
10777                   break;
10778                 }
10779               for (f = &fields[0]; f->name; f++)
10780                 {
10781                   LOG_INSANE ("-%s.%s [%d %s] vs %d\n", obj->name, f->name,
10782                               f->dxf, f->type, pair->code)
10783                   // VECTORs. need to be malloced, and treated specially
10784                   if (pair->code != 3 && f->is_malloc && !f->is_string
10785                       && strNE (f->name, "parent")) // parent set in NEW_OBJECT
10786                     {
10787                       const Dwg_DYNAPI_field *num_f;
10788                       // FIELD_2RD_VECTOR (clip_verts, num_clip_verts, 11|14);
10789                       if (pair->code >= 10 && pair->code <= 24
10790                           && strEQc (f->name, "clip_verts")) // 11 or 14
10791                         {
10792                           BITCODE_BL num_clip_verts = 0;
10793                           BITCODE_2RD *clip_verts;
10794                           // 11 has no num_clip_verts: realloc. clip_inverts
10795                           // has.
10796                           if (pair->code == 14 || pair->code == 24)
10797                             {
10798                               dwg_dynapi_entity_value (_obj, obj->name,
10799                                                        "num_clip_verts",
10800                                                        &num_clip_verts, NULL);
10801                               LOG_INSANE ("%s.num_clip_verts = %d, j = %d\n",
10802                                           name, num_clip_verts, j);
10803                             }
10804                           dwg_dynapi_entity_value (_obj, obj->name,
10805                                                    "clip_verts", &clip_verts,
10806                                                    NULL);
10807                           // assert (j == 0 || j < (int)num_clip_verts);
10808                           if (pair->code < 20)
10809                             {
10810                               // no need to realloc
10811                               if (!j && pair->code == 14)
10812                                 {
10813                                   clip_verts = (BITCODE_2RD *)xcalloc (
10814                                       num_clip_verts, sizeof (BITCODE_2RD));
10815                                   dwg_dynapi_entity_set_value (_obj, obj->name,
10816                                                                f->name,
10817                                                                &clip_verts, 0);
10818                                 }
10819                               else if (pair->code == 11)
10820                                 {
10821                                   clip_verts = (BITCODE_2RD *)realloc (
10822                                       clip_verts,
10823                                       (j + 1) * sizeof (BITCODE_2RD));
10824                                   memset (&clip_verts[j], 0,
10825                                           sizeof (BITCODE_2RD));
10826                                   dwg_dynapi_entity_set_value (_obj, obj->name,
10827                                                                f->name,
10828                                                                &clip_verts, 0);
10829                                 }
10830                               if (j >= 0 && j < (int)num_clip_verts
10831                                   && clip_verts)
10832                                 clip_verts[j].x = pair->value.d;
10833                             }
10834                           else if (pair->code < 30)
10835                             {
10836                               if (j >= 0 && j < (int)num_clip_verts
10837                                   && clip_verts)
10838                                 {
10839                                   clip_verts[j].y = pair->value.d;
10840                                   LOG_TRACE (
10841                                       "%s.%s[%d] = (%f, %f) [2RD* %d]\n", name,
10842                                       "clip_verts", j, clip_verts[j].x,
10843                                       clip_verts[j].y, pair->code - 10);
10844                                   j++;
10845                                 }
10846                               if (pair->code == 21)
10847                                 {
10848                                   dwg_dynapi_entity_set_value (
10849                                       _obj, obj->name, "num_clip_verts", &j,
10850                                       0);
10851                                   LOG_TRACE ("%s.num_clip_verts = %d\n", name,
10852                                              j);
10853                                 }
10854                             }
10855                           goto next_pair;
10856                         }
10857                       // point vectors with known num_field
10858                       else if ((*f->type == '2' || *f->type == '3')
10859                                && (f->type[2] == 'D'
10860                                    || strEQc (&f->type[1], "DPOINT*"))
10861                                && (num_f = find_numfield (fields, f->name)))
10862                         {
10863                           // how many points
10864                           long size = get_numfield_value (_obj, num_f);
10865                           double *pts;
10866                           int is2d = *f->type == '2';
10867                           if (!size)
10868                             {
10869                               LOG_TRACE ("Ignore empty %s.%s VECTOR [%s %d]\n",
10870                                          name, f->name, f->type, pair->code);
10871                               goto next_pair;
10872                             }
10873                           else if (j == 0 && pair->code < 20)
10874                             {
10875                               pts = (double *)xcalloc (size, is2d ? 16 : 24);
10876                               if (!pts)
10877                                 return NULL;
10878                               LOG_TRACE ("%s.%s size: %ld\n", name, f->name,
10879                                          size);
10880                               pts[0] = pair->value.d;
10881                               dwg_dynapi_entity_set_value (_obj, obj->name,
10882                                                            f->name, &pts, 0);
10883                             }
10884                           else if (j > 0 && j < size)
10885                             {
10886                               int _i = is2d ? j * 2 : j * 3;
10887                               dwg_dynapi_entity_value (_obj, obj->name,
10888                                                        f->name, &pts, NULL);
10889                               if (pair->code < 20 && pts != NULL)
10890                                 {
10891                                   pts[_i] = pair->value.d;
10892                                 }
10893                               else if (pair->code < 30 && pts != NULL)
10894                                 {
10895                                   if (is2d)
10896                                     LOG_TRACE (
10897                                         "%s.%s[%d] = (%f, %f) [%s %d]\n", name,
10898                                         f->name, j, pts[_i], pair->value.d,
10899                                         f->type, pair->code);
10900                                   pts[_i + 1] = pair->value.d;
10901                                 }
10902                               else if (*f->type == '3' && pts)
10903                                 {
10904                                   LOG_TRACE (
10905                                       "%s.%s[%d] = (%f, %f, %f) [%s %d]\n",
10906                                       name, f->name, j, pts[_i], pts[_i + 1],
10907                                       pair->value.d, f->type, pair->code);
10908                                   pts[_i + 2] = pair->value.d;
10909                                   if (j == size - 1)
10910                                     j = 0; // restart
10911                                 }
10912                             }
10913                           else if (j > size)
10914                             LOG_ERROR ("%s.%s overflow %d > %ld", name,
10915                                        num_f->name, j, size)
10916                         }
10917                       else if (f->dxf == pair->code)
10918                         {
10919                           LOG_WARN ("Ignore %s.%s VECTOR [%s %d]", name,
10920                                     f->name, f->type, pair->code);
10921                           goto next_pair;
10922                         }
10923                     }
10924                   else if (obj->fixedtype == DWG_TYPE_VISUALSTYLE
10925                            && dwg->header.from_version >= R_2010 && pair->code == 176
10926                            && prev_vstyle)
10927                     {
10928                       // which 176 of the many? the one after the previous
10929                       // field
10930                       char fieldname[40];
10931                       strcpy (fieldname, prev_vstyle->name);
10932                       strcat (fieldname, "_int");
10933                       f = prev_vstyle + 1;
10934                       if (strEQc (fieldname, "display_brightness_bl_int"))
10935                         {
10936                           strcpy (fieldname, "display_brightness_int");
10937                           f++;
10938                         }
10939                       if (strEQ (fieldname, f->name))
10940                         {
10941                           LOG_HANDLE ("found %s.%s:\n", name, fieldname);
10942                           if (strEQc (f->name, "display_shadow_type_int")
10943                               && dwg->header.from_version >= R_2013)
10944                             {
10945                               Dwg_Object_VISUALSTYLE *o = obj->tio.object->tio.VISUALSTYLE;
10946                               o->display_shadow_type_int = pair->value.i;
10947                               pair = add_VISUALSTYLE_props (obj, dat);
10948                               if (!pair) // success
10949                                 goto start_loop;
10950                               else // or better advance to the next 0
10951                                 goto search_field;
10952                             }
10953                           else
10954                             goto matching_pair;
10955                         }
10956                       else
10957                         LOG_WARN ("%s.%s [BS 176] not found in dynapi", name,
10958                                   fieldname);
10959                     }
10960                   else if (f->dxf == pair->code) // matching DXF code
10961                     {
10962                     matching_pair:
10963                       if (obj->fixedtype == DWG_TYPE_VISUALSTYLE
10964                           && dwg->header.from_version >= R_2010 && pair->code != 176)
10965                         {
10966                           prev_vstyle = f;
10967                         }
10968                       // exceptions, where there's another field 92:
10969                       if (pair->code == 92 && is_entity
10970                           && dwg->header.from_version < R_2010
10971                           && strEQc (subclass, "AcDbEntity"))
10972                         // not MULTILEADER.text_color, nor MESH.num_vertex
10973                         {
10974                           pair = add_ent_preview (obj, dat, pair);
10975                           goto start_loop;
10976                         }
10977                       else if (pair->code == 3 && pair->value.s
10978                                && memBEGINc (obj->name, "DICTIONARY")
10979                                && strNE (obj->name, "DICTIONARYVAR"))
10980                         {
10981                           strncpy (text, pair->value.s, 254);
10982                           text[255] = '\0';
10983                           goto next_pair; // skip setting texts TV*
10984                         }
10985                       // convert angle to radians
10986                       else if (pair->code >= 50 && pair->code <= 55)
10987                         {
10988                           BITCODE_BD ang;
10989                           if (pair->value.d == 0.0)
10990                             goto next_pair;
10991                           ang = deg2rad (pair->value.d);
10992                           dwg_dynapi_entity_set_value (_obj, obj->name,
10993                                                        f->name, &ang, 0);
10994                           LOG_TRACE ("%s.%s = %f (from DEG %f°) [%s %d]\n",
10995                                      name, f->name, ang, pair->value.d,
10996                                      f->type, pair->code);
10997                           goto next_pair; // found
10998                         }
10999                       // convert double to text (e.g. ATEXT)
11000                       else if (strEQc (f->type, "D2T")
11001                                && pair->type == DWG_VT_REAL)
11002                         {
11003                           // TODO: for now we need to do double-conversion
11004                           // (str->dbl->str), because we don't have the initial
11005                           // dat->byte position.
11006                           char *d2t = (char *)xcalloc (36, 1);
11007                           sprintf (d2t, "%f", pair->value.d);
11008                           dwg_dynapi_entity_set_value (_obj, obj->name,
11009                                                        f->name, &d2t, 1);
11010                           LOG_TRACE ("%s.%s = %s (from %f°) [%s %d]\n", name,
11011                                      f->name, d2t, pair->value.d, f->type,
11012                                      pair->code);
11013                           free (d2t);
11014                           goto next_pair; // found
11015                         }
11016                       // resolve handle, by name or ref
11017                       else if (strEQc (f->type, "H"))
11018                         {
11019                           BITCODE_H ref = find_tablehandle (dwg, pair);
11020                           if (!ref)
11021                             {
11022                               if (pair->code > 300)
11023                                 {
11024                                   int code = 5; // default: soft pointer
11025                                   if (obj->fixedtype == DWG_TYPE_VIEWPORT)
11026                                     {
11027                                       switch (pair->code)
11028                                         {
11029                                         case 340:
11030                                         case 332:
11031                                         case 333:
11032                                           code = 4;
11033                                           break;
11034                                         case 361:
11035                                           code = 3;
11036                                           break;
11037                                         default:
11038                                           break;
11039                                         }
11040                                     }
11041                                   else if (strEQc (f->name, "history_id"))
11042                                     code = 4;
11043                                   else if (strEQc (f->name, "background"))
11044                                     code = 4;
11045                                   else if (strEQc (f->name, "dimensionobj"))
11046                                     code = 4;
11047                                   else if (strEQc (f->name, "active_viewport")
11048                                            || strEQc (f->name, "host_block"))
11049                                     code = 4;
11050                                   else if (strEQc (f->name, "writedep")
11051                                            || strEQc (f->name, "readdep"))
11052                                     code = 4;
11053                                   else if (strEQc (f->name, "imagedefreactor"))
11054                                     code = 3;
11055                                   else if (strEQc (f->name, "table_style"))
11056                                     code = 3;
11057                                   ref = dwg_add_handleref (dwg, code,
11058                                                            pair->value.u, obj);
11059                                   LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n",
11060                                              name, f->name, ARGS_REF (ref),
11061                                              pair->code);
11062                                 }
11063                               else if (pair->type == DWG_VT_INT32 && pair->value.u)
11064                                 {
11065                                   ref = dwg_add_handleref (dwg, 5,
11066                                                            pair->value.u, obj);
11067                                   LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n",
11068                                              name, f->name, ARGS_REF (ref),
11069                                              pair->code);
11070                                 }
11071                               else if ((pair->type == DWG_VT_STRING
11072                                         || pair->type == DWG_VT_HANDLE)
11073                                        && pair->value.s)
11074                                 {
11075                                   obj_hdls = array_push (
11076                                       obj_hdls, f->name, pair->value.s,
11077                                       obj->tio.object->objid);
11078                                   LOG_TRACE ("%s.%s: name %s -> H for code "
11079                                              "%d later\n",
11080                                              name, f->name, pair->value.s,
11081                                              pair->code);
11082                                 }
11083                             }
11084                           else
11085                             {
11086                               dwg_dynapi_entity_set_value (_obj, obj->name,
11087                                                            f->name, &ref, 1);
11088                               LOG_TRACE ("%s.%s = " FORMAT_REF " [H %d]\n",
11089                                          name, f->name, ARGS_REF (ref),
11090                                          pair->code);
11091                             }
11092                           goto next_pair; // found
11093                         }
11094                       // only 2D or 3D points .x
11095                       else if (f->size > 8
11096                                && (strchr (f->type, '2')
11097                                    || strchr (f->type, '3')
11098                                    || strEQc (f->type, "BE")))
11099                         {
11100                           // pt.x = 0.0;
11101                           // if (pair->value.d == 0.0) // ignore defaults
11102                           //  goto next_pair;
11103                           pt.x = pair->value.d;
11104                           dwg_dynapi_entity_set_value (_obj, obj->name,
11105                                                        f->name, &pt, 1);
11106                           LOG_TRACE ("%s.%s.x = %f [%s %d]\n", name, f->name,
11107                                      pair->value.d, f->type, pair->code);
11108                           goto next_pair; // found
11109                         }
11110                       else if (pair->type == DWG_VT_REAL
11111                                && strEQc (f->type, "TIMEBLL"))
11112                         {
11113                           static BITCODE_TIMEBLL date = { 0, 0, 0 };
11114                           date.value = pair->value.d;
11115                           date.days = (BITCODE_BL)trunc (pair->value.d);
11116                           date.ms = (BITCODE_BL) (86400000.0
11117                                                   * (date.value - date.days));
11118                           LOG_TRACE ("%s.%s %.09f (" FORMAT_BL ", " FORMAT_BL
11119                                      ") [TIMEBLL %d]\n",
11120                                      name, f->name, date.value, date.days,
11121                                      date.ms, pair->code);
11122                           dwg_dynapi_entity_set_value (_obj, obj->name,
11123                                                        f->name, &date, 1);
11124                           goto next_pair;
11125                         }
11126                       else if (f->size > 8 && strEQc (f->type, "CMC"))
11127                         {
11128                           BITCODE_CMC color;
11129                           dwg_dynapi_entity_value (_obj, obj->name, f->name,
11130                                                    &color, NULL);
11131                           if (pair->code < 90)
11132                             {
11133                               color.index = pair->value.i;
11134                               if (pair->value.i == 256)
11135                                 color.method = 0xc2;
11136                               else if (pair->value.i == 257)
11137                                 color.method = 0xc8;
11138                               else if (pair->value.i < 256 && dat->from_version >= R_2004)
11139                                 {
11140                                   color.method = 0xc3;
11141                                   color.rgb = 0xc3000000 | color.index;
11142                                   color.index = 256;
11143                                 }
11144                               LOG_TRACE ("%s.%s.index = %d [%s %d]\n", name,
11145                                          f->name, color.index, "CMC",
11146                                          pair->code);
11147                               if (color.rgb)
11148                                 LOG_TRACE ("%s.%s.rgb = 0x%08x [%s %d]\n", name,
11149                                            f->name, color.rgb, "CMC",
11150                                            pair->code);
11151                             }
11152                           else if (pair->code < 430)
11153                             {
11154                               color.rgb = pair->value.l;
11155                               color.method = pair->value.l >> 0x18;
11156                               if (pair->value.l == 257)
11157                                 {
11158                                   color.method = 0xc8;
11159                                   color.rgb = 0xc8000000;
11160                                 }
11161                               // color.alpha = (pair->value.l & 0xFF000000) >>
11162                               // 24; if (color.alpha)
11163                               //  color.alpha_type = 3;
11164                               LOG_TRACE ("%s.%s.rgb = %08X [%s %d]\n", name,
11165                                          f->name, pair->value.u, "CMC",
11166                                          pair->code);
11167                             }
11168                           else if (pair->code < 440)
11169                             {
11170                               color.flag |= 0x10;
11171                               color.name = dwg_add_u8_input (dwg, pair->value.s);
11172                               LOG_TRACE ("%s.%s.name = %s [%s %d]\n", name,
11173                                          f->name, pair->value.s, "CMC",
11174                                          pair->code);
11175                             }
11176                           else if (pair->code < 450)
11177                             {
11178                               color.alpha = (pair->value.l & 0xFF000000) >> 24;
11179                               if (color.alpha)
11180                                 color.alpha_type = 3;
11181                               LOG_TRACE ("%s.%s.alpha = %08X [%s %d]\n", name,
11182                                          f->name, pair->value.u, "CMC",
11183                                          pair->code);
11184                             }
11185                           dwg_dynapi_entity_set_value (_obj, obj->name,
11186                                                        f->name, &color, 1);
11187                           goto next_pair; // found, early exit
11188                         }
11189                       else
11190                         dwg_dynapi_entity_set_value (_obj, obj->name, f->name,
11191                                                      &pair->value, 1);
11192                       if (f->is_string)
11193                         {
11194                           LOG_TRACE ("%s.%s = %s [%s %d]\n", name, f->name,
11195                                      pair->value.s, f->type, pair->code);
11196                         }
11197                       else if (strchr (&f->type[1], 'D'))
11198                         {
11199                           LOG_TRACE ("%s.%s = %f [%s %d]\n", name, f->name,
11200                                      pair->value.d, f->type, pair->code);
11201                         }
11202                       else
11203                         {
11204                           LOG_TRACE ("%s.%s = %ld [%s %d]\n", name, f->name,
11205                                      pair->value.l, f->type, pair->code);
11206                         }
11207                       j = 0; // not a point nor vector member, so reset
11208                       goto next_pair; // found, early exit
11209                     }
11210                   // wrong code, maybe a point .y or .z
11211                   else if ((*f->type == '3' || *f->type == '2'
11212                             || strEQc (f->type, "BE"))
11213                            && (strstr (f->type, "_1")
11214                                    ? f->dxf + 1 == pair->code // 2BD_1
11215                                    : f->dxf + 10 == pair->code))
11216                     {
11217                       // pt.y = 0.0;
11218                       // if (pair->value.d == 0.0) // ignore defaults
11219                       //  goto next_pair;
11220                       dwg_dynapi_entity_value (_obj, obj->name, f->name, &pt,
11221                                                NULL);
11222                       pt.y = pair->value.d;
11223                       dwg_dynapi_entity_set_value (_obj, obj->name, f->name,
11224                                                    &pt, 1);
11225                       LOG_TRACE ("%s.%s.y = %f [%s %d]\n", name, f->name,
11226                                  pair->value.d, f->type, pair->code);
11227                       goto next_pair; // found, early exit
11228                     }
11229                   else if ((*f->type == '3' || *f->type == '2'
11230                             || strEQc (f->type, "BE"))
11231                            && (strstr (f->type, "_1")
11232                                    ? f->dxf + 2 == pair->code // 2BD_1
11233                                    : f->dxf + 20 == pair->code))
11234                     {
11235                       pt.z = 0.0;
11236                       // can ignore z or 0.0? e.g. no VPORT.view_target
11237                       if (strNE (name, "_3DFACE") && strNE (f->name, "scale")
11238                           && *f->type == '2')
11239                         goto next_pair;
11240                       dwg_dynapi_entity_value (_obj, obj->name, f->name, &pt,
11241                                                NULL);
11242                       pt.z = pair->value.d;
11243                       dwg_dynapi_entity_set_value (_obj, obj->name, f->name,
11244                                                    &pt, 0);
11245                       LOG_TRACE ("%s.%s.z = %f [%s %d]\n", name, f->name,
11246                                  pair->value.d, f->type, pair->code);
11247 
11248                       // 3DD scale
11249                       if (strEQc (f->name, "scale")
11250                           && dwg->header.version >= R_2000
11251                           && dwg_dynapi_entity_field (obj->name, "scale_flag")
11252                           && dwg_dynapi_entity_value (_obj, obj->name,
11253                                                       "scale_flag",
11254                                                       &scale_flag, NULL))
11255                         { // set scale_flag
11256                           scale_flag = 0;
11257                           if (pt.x == 1.0 && pt.y == 1.0 && pt.z == 1.0)
11258                             scale_flag = 3;
11259                           else if (pt.x == 1.0)
11260                             scale_flag = 1;
11261                           else if (pt.x == pt.y && pt.x == pt.z)
11262                             scale_flag = 2;
11263                           dwg_dynapi_entity_set_value (
11264                               _obj, obj->name, "scale_flag", &scale_flag, 0);
11265                           LOG_TRACE ("%s.scale_flag = %d [BB 0]\n", name,
11266                                      scale_flag);
11267                         }
11268                       // 3DFACE.z_is_zero
11269                       else if (strEQc (name, "_3DFACE")
11270                                && strEQc (f->name, "corner1")
11271                                && dwg->header.version >= R_2000 && pt.z == 0.0)
11272                         {
11273                           BITCODE_B z_is_zero = 1;
11274                           dwg_dynapi_entity_set_value (
11275                               _obj, obj->name, "z_is_zero", &z_is_zero, 0);
11276                           LOG_TRACE ("%s.z_is_zero = 1 [B 0]\n", name);
11277                         }
11278 
11279                       goto next_pair; // found, early exit
11280                     }
11281                   // FIELD_VECTOR_N BITCODE_BD transmatrix[16]:
11282                   else if (strEQc (f->type, "BD*")
11283                            && (strEQc (name, "EXTRUDEDSURFACE")
11284                                || strEQc (name, "LOFTEDSURFACE")
11285                                || strEQc (name, "SWEPTSURFACE")
11286                                || strEQc (name, "REVOLVEDSURFACE")
11287                                || strEQc (name, "MATERIAL")
11288                                || strEQc (name, "SPATIAL_FILTER")
11289                                || /* max 12 */
11290                                strEQc (name, "ACSH_SWEEP_CLASS"))
11291                            && ((pair->code >= 40 && pair->code <= 49)
11292                                || (pair->code <= 142 && pair->code <= 147)))
11293                     {
11294                       // 16x BD, via j
11295                       BITCODE_BD *matrix;
11296                       dwg_dynapi_entity_value (_obj, obj->name, f->name,
11297                                                &matrix, NULL);
11298                       if (!matrix)
11299                         {
11300                           matrix = (BITCODE_BD *)xcalloc (16,
11301                                                           sizeof (BITCODE_BD));
11302                           if (!matrix)
11303                             goto invalid_dxf;
11304                           j = 0;
11305                         }
11306                       if (j < 0 || j >= 16 || !matrix)
11307                         goto invalid_dxf;
11308                       assert (j >= 0 && j < 16 && matrix);
11309                       matrix[j] = pair->value.d;
11310                       dwg_dynapi_entity_set_value (_obj, obj->name, f->name,
11311                                                    &matrix, 0);
11312                       LOG_TRACE ("%s.%s[%d] = %f [%s %d]\n", name, f->name, j,
11313                                  pair->value.d, f->type, pair->code);
11314                       j++;
11315                       goto next_pair;
11316                     }
11317                 }
11318               LOG_INSANE ("----\n");
11319               if (*subclass) // embedded subclasses/objects
11320                 {
11321                   if (obj->fixedtype == DWG_TYPE_LAYOUT
11322                       && strEQc (subclass, "AcDbPlotSettings"))
11323                     {
11324                       Dwg_Object_LAYOUT *o = obj->tio.object->tio.LAYOUT;
11325                       int unique;
11326                       static double pt_x;
11327                       static const Dwg_DYNAPI_field *pt_f = NULL;
11328                       if (pair->code == 6 && *pair->value.s)
11329                         {
11330                           if (dwg->header.version < R_2004)
11331                             {
11332                               f = dwg_dynapi_entity_field ("PLOTSETTINGS",
11333                                                            "plotview_name");
11334                               dwg_dynapi_field_set_value (
11335                                   dwg, &o->plotsettings, f, &pair->value, 1);
11336                             }
11337                           else
11338                             {
11339                               BITCODE_H ref = find_tablehandle (dwg, pair);
11340                               f = dwg_dynapi_entity_field ("PLOTSETTINGS",
11341                                                            "plotview");
11342                               dwg_dynapi_field_set_value (
11343                                   dwg, &o->plotsettings, f, &ref, 1);
11344                             }
11345                           goto next_pair;
11346                         }
11347                       fields = dwg_dynapi_entity_fields ("PLOTSETTINGS");
11348                       f = dwg_dynapi_field_dxf (fields, pair->code, &unique);
11349                       if (f && unique)
11350                         {
11351                           if (*f->type == '2') // 2D points
11352                             {
11353                               pt_f = f;
11354                               pt_x = pair->value.d;
11355                               goto next_pair;
11356                             }
11357                           else if (strEQc (f->type, "H"))
11358                             {
11359                               BITCODE_H ref = find_tablehandle (dwg, pair);
11360                               if (!ref)
11361                                 {
11362                                   if (pair->code > 300)
11363                                     {
11364                                       int code = 4;
11365                                       ref = dwg_add_handleref (
11366                                           dwg, code, pair->value.u, obj);
11367                                       LOG_TRACE (
11368                                           "%s.plotsettings.%s = " FORMAT_REF
11369                                           " [H %d]\n",
11370                                           name, f->name, ARGS_REF (ref),
11371                                           pair->code);
11372                                     }
11373                                   goto next_pair; // found
11374                                 }
11375                               else
11376                                 {
11377                                   dwg_dynapi_field_set_value (
11378                                       dwg, &o->plotsettings, f, &ref, 1);
11379                                   LOG_TRACE (
11380                                       "set %s.plotsettings.%s " FORMAT_REF
11381                                       " [H %d]\n",
11382                                       obj->name, f->name, ARGS_REF (ref),
11383                                       pair->code);
11384                                   goto next_pair; // found
11385                                 }
11386                             }
11387                           else
11388                             {
11389                               LOG_TRACE ("set %s.plotsettings.%s [%s %d]\n",
11390                                          obj->name, f->name, f->type,
11391                                          pair->code);
11392                               dwg_dynapi_field_set_value (
11393                                   dwg, &o->plotsettings, f, &pair->value, 1);
11394                               goto next_pair;
11395                             }
11396                         }
11397                       else if (pt_f
11398                                && (pair->code == 47 || pair->code == 49
11399                                    || pair->code == 141 || pair->code == 149))
11400                         {
11401                           BITCODE_2BD pt2;
11402                           pt2.x = pt_x;
11403                           pt2.y = pair->value.d;
11404                           LOG_TRACE ("set %s.plotsettings.%s [%s %d]\n",
11405                                      obj->name, pt_f->name, pt_f->type,
11406                                      pt_f->dxf);
11407                           dwg_dynapi_field_set_value (dwg, &o->plotsettings,
11408                                                       pt_f, &pt2, 1);
11409                           goto next_pair;
11410                         }
11411                       else
11412                         LOG_WARN ("Unknown DXF code %d for %s", pair->code,
11413                                   subclass);
11414                     }
11415                 }
11416               fields = is_entity ? dwg_dynapi_common_entity_fields ()
11417                                  : dwg_dynapi_common_object_fields ();
11418               for (f = &fields[0]; f->name; f++)
11419                 {
11420                   LOG_INSANE ("-%s.%s [%d %s] vs %d\n",
11421                               is_entity ? "ENTITY" : "OBJECT", f->name, f->dxf,
11422                               f->type, pair->code)
11423                   if ((pair->code == 62 || pair->code == 420
11424                        || pair->code == 430 || pair->code == 440)
11425                       && (f->size > 8
11426                           && strEQc (f->type, "CMC"))) // alt. color fields
11427                     {
11428                       BITCODE_CMC color;
11429                       dwg_dynapi_common_value (_obj, f->name, &color, NULL);
11430                       if (pair->code == 62)
11431                         {
11432                           color.index = pair->value.i;
11433                           LOG_TRACE ("COMMON.%s.index = %d [%s %d]\n", f->name,
11434                                      pair->value.i, "CMC", pair->code);
11435                         }
11436                       else if (pair->code == 420)
11437                         {
11438                           color.rgb = pair->value.l;
11439                           color.method = pair->value.l >> 0x18;
11440                           if (pair->value.l == 257)
11441                             {
11442                               color.method = 0xc8;
11443                               color.rgb = 0xc8000000;
11444                             }
11445                           // color.alpha = (pair->value.l & 0xFF000000) >> 24;
11446                           // if (color.alpha)
11447                           //  color.alpha_type = 3;
11448                           LOG_TRACE ("COMMON.%s.rgb = %08X [%s %d]\n", f->name,
11449                                      pair->value.u, "CMC", pair->code);
11450                         }
11451                       else if (pair->code == 440)
11452                         {
11453                           color.flag |= 0x20;
11454                           color.alpha = (pair->value.l & 0xFF000000) >> 24;
11455                           color.alpha_type = pair->value.u >> 8;
11456                           if (color.alpha && !color.alpha_type)
11457                             color.alpha_type = 3;
11458                           LOG_TRACE ("COMMON.%s.alpha = %08X [%s %d]\n",
11459                                      f->name, pair->value.u, "CMC",
11460                                      pair->code);
11461                         }
11462                       else if (pair->code == 430)
11463                         {
11464                           color.flag |= 0x10;
11465                           color.name = dwg_add_u8_input (dwg, pair->value.s);
11466                           // TODO: book_name or name?
11467                           LOG_TRACE ("COMMON.%s.name = %s [%s %d]\n", f->name,
11468                                      pair->value.s, "CMC", pair->code);
11469                         }
11470                       dwg_dynapi_common_set_value (_obj, f->name, &color,
11471                                                    is_tu);
11472                       goto next_pair; // found, early exit
11473                     }
11474                   else if (f->dxf == pair->code)
11475                     {
11476                       /// resolve handle (table entry) given by name or ref
11477                       if (strEQc (f->type, "H"))
11478                         {
11479                           BITCODE_H handle = find_tablehandle (dwg, pair);
11480                           if (!handle)
11481                             {
11482                               if (pair->code > 300)
11483                                 {
11484                                   handle = dwg_add_handleref (
11485                                       dwg, 5, pair->value.u, obj);
11486                                   dwg_dynapi_common_set_value (_obj, f->name,
11487                                                                &handle, 0);
11488                                   LOG_TRACE ("COMMON.%s = %X [H %d]\n",
11489                                              f->name, pair->value.u,
11490                                              pair->code)
11491                                 }
11492                               else
11493                                 {
11494                                   LOG_WARN ("TODO resolve common handle "
11495                                             "name %s %s",
11496                                             f->name, pair->value.s)
11497                                 }
11498                             }
11499                           else
11500                             {
11501                               if (pair->code > 300)
11502                                 LOG_TRACE ("COMMON.%s = %lX [H %d]\n", f->name,
11503                                            pair->value.l, pair->code)
11504                               else
11505                                 LOG_TRACE ("COMMON.%s = %s [H %d]\n", f->name,
11506                                            pair->value.s, pair->code)
11507                               dwg_dynapi_common_set_value (_obj, f->name,
11508                                                            &handle, 0);
11509                             }
11510                           if (is_entity && pair->code == 6 && pair->value.s
11511                               && dwg->header.version >= R_2000)
11512                             {
11513                               BITCODE_BB flags = 3;
11514                               if (!strcasecmp (pair->value.s, "BYLAYER"))
11515                                 flags = 0;
11516                               if (!strcasecmp (pair->value.s, "BYBLOCK"))
11517                                 flags = 1;
11518                               if (!strcasecmp (pair->value.s, "CONTINUOUS"))
11519                                 flags = 2;
11520                               dwg_dynapi_common_set_value (_obj, "ltype_flags",
11521                                                            &flags, 0);
11522                               LOG_TRACE ("COMMON.%s = %d [BB 0]\n",
11523                                          "ltype_flags", flags);
11524                             }
11525                           if (is_entity && pair->code == 390
11526                               && dwg->header.version >= R_2000)
11527                             {
11528                               BITCODE_BB flags = 3;
11529                               /*
11530                               if (!strcasecmp (pair->value.s, "BYLAYER"))
11531                                 flags = 0;
11532                               if (!strcasecmp (pair->value.s, "BYBLOCK"))
11533                                 flags = 1;
11534                               */
11535                               dwg_dynapi_common_set_value (
11536                                   _obj, "plotstyle_flags", &flags, 0);
11537                               LOG_TRACE ("COMMON.%s = %d [BB 0]\n",
11538                                          "plotstyle_flags", flags);
11539                             }
11540                           if (is_entity && pair->code == 347
11541                               && dwg->header.version >= R_2007)
11542                             {
11543                               BITCODE_BB flags = 3;
11544                               /*
11545                               if (!strcasecmp (pair->value.s, "BYLAYER"))
11546                                 flags = 0;
11547                               if (!strcasecmp (pair->value.s, "BYBLOCK"))
11548                                 flags = 1;
11549                               */
11550                               dwg_dynapi_common_set_value (
11551                                   _obj, "material_flags", &flags, 0);
11552                               LOG_TRACE ("COMMON.%s = %d [BB 0]\n",
11553                                          "material_flags", flags);
11554                             }
11555                           goto next_pair; // found, early exit
11556                         }
11557                       else if (pair->code == 310 && is_entity
11558                                && !obj->tio.entity->preview_size
11559                                && obj->fixedtype > DWG_TYPE_LAYOUT
11560                                && strEQc (subclass, "AcDbEntity"))
11561                         {
11562                           pair = add_ent_preview (obj, dat, pair);
11563                           goto start_loop;
11564                         }
11565                       else if (pair->code == 310 && is_entity
11566                                && obj->tio.entity->preview_size
11567                                && obj->fixedtype > DWG_TYPE_LAYOUT
11568                                && strEQc (subclass, "AcDbEntity"))
11569                         {
11570                           // This would corrupt the previous preview chain,
11571                           // don't append
11572                           LOG_ERROR ("Skip duplicate/interrupted %s.preview",
11573                                      obj->name)
11574                           goto next_pair;
11575                         }
11576                       else
11577                         {
11578                           // Don't write a ptr twice. This will fuckup the
11579                           // num_ counter. Just add to 310 preview, when
11580                           // prefixed by 92
11581                           if (f->is_malloc || f->is_string)
11582                             {
11583                               char *ptr = NULL;
11584                               if (dwg_dynapi_common_value (_obj, f->name, &ptr,
11585                                                            NULL)
11586                                   && ptr != NULL)
11587                                 {
11588                                   LOG_ERROR ("Skip duplicate %s.%s [%s %d]",
11589                                              obj->name, f->name, f->type,
11590                                              pair->code)
11591                                   goto next_pair;
11592                                 }
11593                             }
11594                           dwg_dynapi_common_set_value (_obj, f->name,
11595                                                        &pair->value, 1);
11596                           if (f->is_string)
11597                             {
11598                               LOG_TRACE ("COMMON.%s = %s [%s %d]\n", f->name,
11599                                          pair->value.s, f->type, pair->code)
11600                             }
11601                           else
11602                             {
11603                               if (is_entity && pair->code == 160
11604                                   && dwg->header.from_version >= R_2010)
11605                                 {
11606                                   pair = add_ent_preview (obj, dat, pair);
11607                                   goto start_loop; // already fresh pair
11608                                 }
11609                               if (strchr (f->type, 'D'))
11610                                 LOG_TRACE ("COMMON.%s = %f [%s %d]\n", f->name,
11611                                            pair->value.d, f->type, pair->code)
11612                               else
11613                                 LOG_TRACE ("COMMON.%s = %ld [%s %d]\n",
11614                                            f->name, pair->value.l, f->type,
11615                                            pair->code)
11616                             }
11617                           goto next_pair; // found, early exit
11618                         }
11619                     }
11620                 }
11621               LOG_INSANE ("----\n")
11622               // still needed? already handled above
11623               // not in dynapi: 92 as 310 size prefix for PROXY vector preview
11624               // FIXME 92 is just for pre-r2010 entities. r2010+ is 160
11625               if (pair->code == 92 && is_entity && dwg->header.from_version < R_2010
11626                   && (strEQc (subclass, "AcDbEntity")
11627                       || strEQc (subclass, "AcDbProxyEntity")
11628                       || strstr (subclass, "Surface")))
11629                 {
11630                   pair = add_ent_preview (obj, dat, pair);
11631                   goto start_loop;
11632                 }
11633               else if (strEQc (name, "MULTILEADER"))
11634                 {
11635                   // for the unknown subfields: 300, 140, 145, 302, 304, ...
11636                   pair = add_MULTILEADER (obj, dat, pair);
11637                   // returns with 0 or 301
11638                   if (pair && pair->code == 301)
11639                     goto next_pair;
11640                 }
11641               else if (obj->fixedtype == DWG_TYPE_TABLESTYLE)
11642                 {
11643                   // for the unknown subfields: 7, 140, ...
11644                   pair = add_TABLESTYLE (obj, dat, pair);
11645                   // returns with 0
11646                   if (pair && pair->code == 0)
11647                     goto start_loop;
11648                 }
11649               else if (obj->fixedtype == DWG_TYPE_TABLEGEOMETRY)
11650                 {
11651                   // for the unknown subfields: 93, 40, ...
11652                   pair = add_TABLEGEOMETRY_Cell (obj, dat, pair);
11653                   // returns with 0
11654                   if (pair && pair->code == 0)
11655                     goto start_loop;
11656                 }
11657               else if (strEQc (name, "BLOCK")
11658                        && (pair->code == 70 || pair->code == 10
11659                            || pair->code == 20 || pair->code == 30
11660                            || pair->code == 3 || pair->code == 1
11661                            || pair->code == 4))
11662                 ; // ignore those BLOCK fields. DXF artifacts
11663               else if (strEQc (name, "DIMENSION")
11664                        && (pair->code == 2 || pair->code == 210
11665                            || pair->code == 220 || pair->code == 230))
11666                 ; // ignore the POLYLINE elevation.x,y. DXF artifacts
11667               else if (strEQc (name, "HATCH")
11668                        && (pair->code == 10 || pair->code == 20))
11669                 ; // ignore the whole PLINE and VERTEX_PFACE_FACE 3BD 10
11670               else if ((strEQc (name, "VERTEX_PFACE_FACE")
11671                         || strEQc (name, "POLYLINE_3D")
11672                         || strEQc (name, "POLYLINE_2D")
11673                         || strEQc (name, "POLYLINE_MESH")
11674                         || strEQc (name, "POLYLINE_PFACE"))
11675                        && (pair->code == 10 || pair->code == 20
11676                            || pair->code == 30))
11677                 ; // ignore the POLYLINE_PFACE flag 70
11678               else if (pair->code == 70 && strEQc (name, "POLYLINE_PFACE"))
11679                 ;
11680               // always OLE
11681               else if (pair->code == 1 && strEQc (name, "OLE2FRAME")
11682                        && strEQc (pair->value.s, "OLE"))
11683                 ;
11684               // the STYLE name, which is already defined by code 7
11685               else if (pair->code == 2 && strEQc (name, "SHAPE"))
11686                 ;
11687               else if ((pair->code == 290 || pair->code == 2)
11688                        && ((obj->fixedtype == DWG_TYPE_REGION)
11689                            || (obj->fixedtype == DWG_TYPE_BODY)
11690                            || (obj->fixedtype == DWG_TYPE__3DSOLID)))
11691                 LOG_TRACE ("Unknown DXF code %d for %s\n", pair->code, name)
11692               else if (obj->fixedtype == DWG_TYPE_PROXY_ENTITY
11693                        && pair->code == 92)
11694                 {
11695                   pair = add_ent_preview (obj, dat, pair);
11696                   goto start_loop;
11697                 }
11698               else if (obj->fixedtype == DWG_TYPE_PROXY_ENTITY
11699                        && (pair->code == 90 || pair->code == 91
11700                            || pair->code == 71
11701                            || pair->code == 94)) // unknown r14
11702                 {
11703                   Dwg_Entity_PROXY_ENTITY *o
11704                       = obj->tio.entity->tio.PROXY_ENTITY;
11705                   if (dwg->header.version <= R_14)
11706                     {
11707                       if (pair->code == 90)
11708                         o->class_id = pair->value.i;
11709                       else if (pair->code == 91)
11710                         o->version = pair->value.i;
11711                     }
11712                   else if (pair->code == 91)
11713                     o->class_id = pair->value.i;
11714                   else if (pair->code == 71) // r2018+
11715                     o->version = pair->value.i;
11716                 }
11717               else if (obj->fixedtype == DWG_TYPE_LAYER
11718                        && ((pair->code == 348) || (pair->code == 420)
11719                            || (pair->code == 430) | (pair->code == 440)))
11720                 {
11721                   Dwg_Object_LAYER *o = obj->tio.object->tio.LAYER;
11722                   if (pair->code == 420)
11723                     {
11724                       o->color.rgb = pair->value.l;
11725                       o->color.method = pair->value.l >> 0x18;
11726                       if (pair->value.l == 257)
11727                         {
11728                           o->color.method = 0xc8;
11729                           o->color.rgb = 0xc8000000;
11730                         }
11731                       // o->color.alpha = (pair->value.l & 0xFF000000) >> 24;
11732                       // if (o->color.alpha)
11733                       //  o->color.alpha_type = 3;
11734                       LOG_TRACE ("%s.color.rgb = %08X [%s %d]\n", name,
11735                                  pair->value.u, "CMC", pair->code);
11736                     }
11737                   else if (pair->code == 440)
11738                     {
11739                       o->color.flag |= 0x20; // ???
11740                       o->color.alpha = (pair->value.l & 0xFF000000) >> 24;
11741                       o->color.alpha_type = pair->value.u >> 8;
11742                       if (o->color.alpha && !o->color.alpha_type)
11743                         o->color.alpha_type = 3;
11744                       LOG_TRACE ("%s.color.alpha = %08X [%s %d]\n", name,
11745                                  pair->value.u, "CMC", pair->code);
11746                     }
11747                   else if (pair->code == 430)
11748                     {
11749                       char *x;
11750                       o->color.book_name = strdup (pair->value.s);
11751                       x = strchr (o->color.book_name, '$');
11752                       if (!x) // name only
11753                         {
11754                           o->color.name = o->color.book_name;
11755                           o->color.flag = 1;
11756                           LOG_TRACE ("%s.color.name = %s [%s %d]\n", name,
11757                                      pair->value.s, "CMC", pair->code);
11758                           if (dwg->header.version >= R_2007)
11759                             {
11760                               char *tmp = o->color.name;
11761                               o->color.name
11762                                 = (BITCODE_T)bit_utf8_to_TU (o->color.name, 0);
11763                               free (tmp);
11764                             }
11765                         }
11766                       else
11767                         { // book with name
11768                           o->color.flag = 3;
11769                           o->color.name = strdup (x + 1);
11770                           x[0] = '\0';
11771                           if (dwg->header.version >= R_2007)
11772                             {
11773                               char *tmp = o->color.book_name;
11774                               o->color.book_name = (BITCODE_T)bit_utf8_to_TU (
11775                                   o->color.book_name, 0);
11776                               free (tmp);
11777                               tmp = o->color.name;
11778                               o->color.name
11779                                 = (BITCODE_T)bit_utf8_to_TU (o->color.name, 0);
11780                               free (tmp);
11781                             }
11782                           LOG_TRACE ("%s.color.book+name = %s [%s %d]\n", name,
11783                                      pair->value.s, "CMC", pair->code);
11784                         }
11785                     }
11786                   else if (pair->code == 348)
11787                     LOG_TRACE ("Unknown DXF code %d for %s\n", pair->code,
11788                                name);
11789                   goto next_pair;
11790                 }
11791               else if (obj->fixedtype == DWG_TYPE_DIMSTYLE
11792                        && pair->code == 287)
11793                 {
11794                   // <= r14
11795                   Dwg_Object_DIMSTYLE *o = obj->tio.object->tio.DIMSTYLE;
11796                   o->DIMFIT = pair->value.i;
11797                   LOG_TRACE ("%s.DIMFIT = %d [%s %d]\n", name, pair->value.i,
11798                              "RC", pair->code);
11799                 }
11800               else if (obj->fixedtype == DWG_TYPE_DIMENSION_ALIGNED
11801                        && pair->code == 52)
11802                 {
11803                   BITCODE_BD ang = deg2rad (pair->value.d);
11804                   free (obj->dxfname);
11805                   UPGRADE_ENTITY (DIMENSION_ALIGNED, DIMENSION_LINEAR)
11806                   dwg_dynapi_entity_set_value (_obj, "DIMENSION_LINEAR",
11807                                                "ext_line_rotation", &ang, 1);
11808                   LOG_TRACE ("%s.%s = %f (from DEG %f°) [%s %d]\n", name,
11809                              "ext_line_rotation", ang, pair->value.d, "BD",
11810                              52);
11811                 }
11812               else if (obj->fixedtype == DWG_TYPE_DIMENSION_ALIGNED
11813                        && pair->code == 50)
11814                 {
11815                   BITCODE_BD ang = deg2rad (pair->value.d);
11816                   free (obj->dxfname);
11817                   UPGRADE_ENTITY (DIMENSION_ALIGNED, DIMENSION_LINEAR)
11818                   dwg_dynapi_entity_set_value (_obj, "DIMENSION_LINEAR",
11819                                                "dim_rotation", &ang, 1);
11820                   LOG_TRACE ("%s.%s = %f (from DEG %f°) [%s %d]\n", name,
11821                              "dim_rotation", ang, pair->value.d, "BD", 50);
11822                 }
11823               // accept wrong colors
11824               else if (is_class_stable (obj->name) && (pair->code < 60 || pair->code > 68))
11825                 {
11826                   goto invalid_dxf;
11827                 }
11828               else
11829                 LOG_WARN ("Unknown DXF code %d for %s", pair->code, name);
11830             }
11831         }
11832     next_pair:
11833       dxf_free_pair (pair);
11834       pair = dxf_read_pair (dat);
11835       DXF_RETURN_EOF (pair);
11836     }
11837 
11838   if (obj->type == DWG_TYPE_SEQEND)
11839     dxf_postprocess_SEQEND (obj);
11840   else if (obj->type == DWG_TYPE_LAYOUT)
11841     dxf_postprocess_LAYOUT (obj);
11842   else if (obj->type == DWG_TYPE_PLOTSETTINGS)
11843     dxf_postprocess_PLOTSETTINGS (obj);
11844   // set defaults not in dxf:
11845   else if (obj->type == DWG_TYPE__3DFACE && dwg->header.version >= R_2000)
11846     {
11847       Dwg_Entity__3DFACE *o = obj->tio.entity->tio._3DFACE;
11848       o->has_no_flags = 1;
11849       LOG_TRACE ("_3DFACE.has_no_flags = 1 [B]\n");
11850     }
11851   else if (is_textlike (obj))
11852     postprocess_TEXTlike (obj);
11853 
11854   return pair;
11855 
11856 invalid_dxf:
11857   LOG_ERROR ("Invalid DXF code %d for %s", pair->code, name)
11858   dxf_free_pair (pair);
11859   return NULL;
11860 }
11861 
11862 static int
dxf_tables_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)11863 dxf_tables_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
11864 {
11865   char table[80];
11866   Dxf_Pair *pair = dxf_read_pair (dat);
11867 
11868   table[0] = '\0'; // init
11869   while (pair)     // read next 0 TABLE
11870     {
11871       if (pair->code == 0 && pair->value.s) // TABLE or ENDTAB
11872         {
11873           if (strEQc (pair->value.s, "TABLE"))
11874             table[0] = '\0'; // new table coming up
11875           else if (strEQc (pair->value.s, "BLOCK_RECORD"))
11876             {
11877               strncpy (table, pair->value.s, 79);
11878               table[79] = '\0';
11879             }
11880           else if (strEQc (pair->value.s, "ENDTAB"))
11881             table[0] = '\0'; // close table
11882           else if (strEQc (pair->value.s, "ENDSEC"))
11883             {
11884               dxf_free_pair (pair);
11885               return 0;
11886             }
11887           else
11888             {
11889               LOG_ERROR ("Unknown 0 %s (%s)", pair->value.s, "tables");
11890               dxf_free_pair (pair);
11891               return 1;
11892             }
11893         }
11894       else if (pair->code == 2 && pair->value.s && strlen (pair->value.s) < 80
11895                && is_table_name (pair->value.s)) // new table NAME
11896         {
11897           BITCODE_BL i = 0;
11898           BITCODE_BL ctrl_id;
11899           strncpy (table, pair->value.s, 79);
11900           table[79] = '\0';
11901           pair = new_table_control (table, dat, dwg); // until 0 table
11902           ctrl_id = dwg->num_objects - 1;             // dwg->object might move
11903           while (pair && pair->code == 0 && pair->value.s
11904                  && strEQ (pair->value.s, table))
11905             {
11906               char *dxfname = strdup (pair->value.s);
11907               dxf_free_pair (pair);
11908               // until 0 table or 0 ENDTAB
11909               pair = new_object (table, dxfname, dat, dwg, ctrl_id, &i);
11910               if (!pair)
11911                 return DWG_ERR_INVALIDDWG;
11912               // undo BLOCK_CONTROL.entries and LTYPE_CONTROL.entries
11913               if (strEQc (table, "BLOCK_RECORD"))
11914                 {
11915                   Dwg_Object *obj = &dwg->object[dwg->num_objects - 1];
11916                   Dwg_Object *ctrl = &dwg->object[ctrl_id];
11917                   Dwg_Object_BLOCK_CONTROL *_ctrl
11918                       = ctrl->tio.object->tio.BLOCK_CONTROL;
11919                   if (_ctrl->model_space
11920                       && obj->handle.value == _ctrl->model_space->absolute_ref)
11921                     i--;
11922                   else if (_ctrl->paper_space
11923                            && obj->handle.value
11924                                   == _ctrl->paper_space->absolute_ref)
11925                     i--;
11926                 }
11927               else if (strEQc (table, "LTYPE"))
11928                 {
11929                   Dwg_Object *obj = &dwg->object[dwg->num_objects - 1];
11930                   Dwg_Object_LTYPE *_obj = obj->tio.object->tio.LTYPE;
11931                   Dwg_Object *ctrl = &dwg->object[ctrl_id];
11932                   Dwg_Object_LTYPE_CONTROL *_ctrl
11933                       = ctrl->tio.object->tio.LTYPE_CONTROL;
11934                   if (_ctrl->bylayer
11935                       && obj->handle.value == _ctrl->bylayer->absolute_ref)
11936                     i--;
11937                   else if (_ctrl->byblock
11938                            && obj->handle.value
11939                                   == _ctrl->byblock->absolute_ref)
11940                     i--;
11941                   else if (dwg->header.version > R_2004 && _obj->name
11942                            && _obj->has_strings_area)
11943                     {
11944                       _obj->strings_area = (BITCODE_TF)xcalloc (512, 1);
11945                       if (!_obj->strings_area)
11946                         goto outofmem;
11947                     }
11948                   if (dwg->header.version <= R_2004)
11949                     {
11950                       _obj->strings_area = (BITCODE_TF)xcalloc (256, 1);
11951                       if (!_obj->strings_area)
11952                         goto outofmem;
11953                     }
11954                 }
11955             }
11956           // next table
11957           // fixup entries vs num_entries (no NULL entries)
11958           {
11959             Dwg_Object *ctrl = &dwg->object[ctrl_id];
11960             Dwg_Object_BLOCK_CONTROL *_ctrl
11961                 = ctrl->tio.object->tio.BLOCK_CONTROL;
11962             int at_end = 1;
11963             unsigned num_entries = _ctrl->num_entries;
11964             if (_ctrl)
11965               {
11966                 for (int j = num_entries - 1; j >= 0; j--)
11967                   {
11968                     BITCODE_H ref = _ctrl->entries[j];
11969                     if (!ref)
11970                       {
11971                         if (at_end)
11972                           {
11973                             num_entries--;
11974                           }
11975                         else
11976                           {
11977                             _ctrl->entries[j]
11978                                 = dwg_add_handleref (dwg, 2, 0, NULL);
11979                             LOG_TRACE ("%s.entries[%d] = (2.0.0)\n",
11980                                        ctrl->name, j);
11981                           }
11982                       }
11983                     else
11984                       at_end = 0;
11985                   }
11986                 // remove many empty entries at the end at once (avoids DDOS)
11987                 if (num_entries != _ctrl->num_entries)
11988                   {
11989                     _ctrl->entries = (BITCODE_H *)realloc (
11990                         _ctrl->entries, num_entries * sizeof (BITCODE_H));
11991                     if (num_entries && !_ctrl->entries)
11992                       goto outofmem;
11993                     _ctrl->num_entries = num_entries;
11994                     LOG_TRACE ("%s.num_entries => %d\n", ctrl->name,
11995                                _ctrl->num_entries);
11996                   }
11997                 // leave room for one active entry
11998                 if (_ctrl->num_entries == 1 && !_ctrl->entries[0])
11999                   {
12000                     _ctrl->entries[0] = dwg_add_handleref (dwg, 2, 0, NULL);
12001                     LOG_TRACE ("%s.entries[0] = (2.0.0)\n", ctrl->name);
12002                   }
12003               }
12004           }
12005         }
12006       DXF_RETURN_ENDSEC (0) // next TABLE or ENDSEC
12007       dxf_free_pair (pair);
12008       pair = dxf_read_pair (dat);
12009       DXF_CHECK_EOF;
12010     }
12011   dxf_free_pair (pair);
12012   return 0;
12013 
12014 outofmem:
12015   dxf_free_pair (pair);
12016   return DWG_ERR_OUTOFMEM;
12017 }
12018 
12019 static int
dxf_blocks_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12020 dxf_blocks_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12021 {
12022   char name[80];
12023   Dxf_Pair *pair = dxf_read_pair (dat);
12024 
12025   name[0] = '\0'; // init
12026   while (pair)    // read next 0 TABLE
12027     {
12028       if (pair != NULL && pair->code == 0 && pair->value.s)
12029         {
12030           BITCODE_BL i = 0;
12031           BITCODE_BB entmode = 0;
12032           while (pair != NULL && pair->code == 0 && pair->value.s
12033                  && strNE (pair->value.s, "ENDSEC"))
12034             {
12035               Dwg_Object *obj, *blkhdr = NULL;
12036               BITCODE_BL idx = dwg->num_objects;
12037               char *dxfname = strdup (pair->value.s);
12038               strncpy (name, dxfname, 79);
12039               name[79] = '\0';
12040               entity_alias (name);
12041               dxf_free_pair (pair);
12042               pair = new_object (name, dxfname, dat, dwg, 0, &i);
12043               if (!pair)
12044                 return DWG_ERR_INVALIDDWG;
12045               obj = &dwg->object[idx];
12046               if (obj->type == DWG_TYPE_BLOCK)
12047                 {
12048                   Dwg_Object_Entity *ent = obj->tio.entity;
12049                   Dwg_Entity_BLOCK *_obj = obj->tio.entity->tio.BLOCK;
12050                   i = 0;
12051                   if (ent->ownerhandle
12052                       && (blkhdr = dwg_ref_object (dwg, ent->ownerhandle)))
12053                     {
12054                       if (blkhdr->fixedtype == DWG_TYPE_BLOCK_HEADER)
12055                         {
12056                           Dwg_Object_BLOCK_HEADER *_hdr
12057                               = blkhdr->tio.object->tio.BLOCK_HEADER;
12058                           ent->ownerhandle->obj = NULL; // still dirty
12059                           _hdr->block_entity = dwg_add_handleref (
12060                               dwg, 3, obj->handle.value, blkhdr);
12061                           LOG_TRACE ("BLOCK_HEADER.block_entity = " FORMAT_REF
12062                                      " [H] (blocks)\n",
12063                                      ARGS_REF (_hdr->block_entity));
12064                         }
12065                       else if (blkhdr->fixedtype == DWG_TYPE_BLOCK_CONTROL)
12066                         {
12067                           Dwg_Object_BLOCK_CONTROL *_ctrl
12068                               = blkhdr->tio.object->tio.BLOCK_CONTROL;
12069                           ent->ownerhandle->obj = NULL; // still dirty
12070                           if (!_ctrl->model_space && _obj->name
12071                               && bit_eq_T (dat, _obj->name, "*Model_Space"))
12072                             {
12073                               _ctrl->model_space = dwg_add_handleref (
12074                                   dwg, 3, obj->handle.value, blkhdr);
12075                               LOG_TRACE (
12076                                   "BLOCK_CONTROL.model_space = " FORMAT_REF
12077                                   " [H] (blocks)\n",
12078                                   ARGS_REF (_ctrl->model_space));
12079                             }
12080                           else if (!_ctrl->paper_space && _obj->name
12081                                    && bit_eq_T (dat, _obj->name, "*Paper_Space"))
12082                             {
12083                               _ctrl->paper_space = dwg_add_handleref (
12084                                   dwg, 3, obj->handle.value, blkhdr);
12085                               LOG_TRACE (
12086                                   "BLOCK_CONTROL.paper_space = " FORMAT_REF
12087                                   " [H] (blocks)\n",
12088                                   ARGS_REF (_ctrl->paper_space));
12089                             }
12090                         }
12091                     }
12092                   else
12093                     blkhdr = NULL;
12094                   if (!_obj || !_obj->name)
12095                     ;
12096                   else if (bit_eq_T (dat, _obj->name, "*Model_Space"))
12097                     entmode = ent->entmode = 2;
12098                   else if (bit_eq_T (dat, _obj->name, "*Paper_Space"))
12099                     entmode = ent->entmode = 1;
12100                   else
12101                     entmode = 0;
12102                 }
12103               else if (obj->type == DWG_TYPE_ENDBLK)
12104                 {
12105                   Dwg_Object_Entity *ent = obj->tio.entity;
12106                   Dwg_Entity_BLOCK *_obj = obj->tio.entity->tio.BLOCK;
12107                   ent->entmode = entmode;
12108                   LOG_TRACE ("%s.entmode = %d [BB] (blocks)\n", obj->name,
12109                              entmode);
12110                   entmode = 0;
12111                   // set BLOCK_HEADER.endblk_entity handle
12112                   if ((blkhdr = dwg_ref_object (dwg, ent->ownerhandle))
12113                       && blkhdr->fixedtype == DWG_TYPE_BLOCK_HEADER)
12114                     {
12115                       Dwg_Object *prev_entity;
12116                       Dwg_Object_BLOCK_HEADER *_hdr
12117                           = blkhdr->tio.object->tio.BLOCK_HEADER;
12118                       ent->ownerhandle->obj = NULL; // still dirty
12119                       _hdr->endblk_entity = dwg_add_handleref (
12120                           dwg, 3, obj->handle.value, blkhdr);
12121                       LOG_TRACE ("BLOCK_HEADER.endblk_entity = " FORMAT_REF
12122                                  " [H] (blocks)\n",
12123                                  ARGS_REF (_hdr->endblk_entity));
12124 
12125                       if ((prev_entity = find_prev_entity (obj)))
12126                         {
12127                           _hdr->last_entity = dwg_add_handleref (
12128                               dwg, 4, prev_entity->handle.value, NULL);
12129                           LOG_TRACE ("BLOCK_HEADER.last_entity = " FORMAT_REF
12130                                      " [H] (blocks)\n",
12131                                      ARGS_REF (_hdr->last_entity));
12132                         }
12133                     }
12134                 }
12135               // normal entity
12136               else if (obj->supertype == DWG_SUPERTYPE_ENTITY)
12137                 {
12138                   Dwg_Object_Entity *ent = obj->tio.entity;
12139                   Dwg_Object_BLOCK_HEADER *_hdr;
12140                   ent->entmode = entmode;
12141                   LOG_TRACE ("%s.entmode = %d [BB] (blocks)\n", obj->name,
12142                              entmode);
12143                   // add to entities
12144                   if (ent->ownerhandle
12145                       && (blkhdr = dwg_ref_object (dwg, ent->ownerhandle))
12146                       && blkhdr->fixedtype == DWG_TYPE_BLOCK_HEADER
12147                       && (_hdr = blkhdr->tio.object->tio.BLOCK_HEADER))
12148                     {
12149                       BITCODE_H ref = dwg_add_handleref (
12150                           dwg, 3, obj->handle.value, NULL);
12151                       PUSH_HV (_hdr, num_owned, entities, ref)
12152                     }
12153                   if (ent->ownerhandle
12154                       && (dwg->header.version >= R_13
12155                           || dwg->header.version == R_INVALID)
12156                       /* requires target version being set */
12157                       && dwg->header.version < R_2004
12158                       && (blkhdr = dwg_ref_object (dwg, ent->ownerhandle))
12159                       && blkhdr->fixedtype == DWG_TYPE_BLOCK_HEADER
12160                       && (_hdr = blkhdr->tio.object->tio.BLOCK_HEADER)
12161                       && !_hdr->first_entity)
12162                     {
12163                       _hdr->first_entity = dwg_add_handleref (
12164                           dwg, 4, obj->handle.value, NULL);
12165                       LOG_TRACE ("BLOCK_HEADER.first_entity = " FORMAT_REF
12166                                  " [H] (blocks)\n",
12167                                  ARGS_REF (_hdr->first_entity));
12168                     }
12169                 }
12170             }
12171           DXF_RETURN_ENDSEC (0) // next BLOCK or ENDSEC
12172         }
12173       dxf_free_pair (pair);
12174       pair = dxf_read_pair (dat);
12175       DXF_CHECK_EOF;
12176     }
12177   dxf_free_pair (pair);
12178   return 0;
12179 }
12180 
12181 // register this block entity, e.g. ModelSpace with the BLOCK_HEADER
12182 // TODO use this also in the BLOCKS section, not just ENTITIES
12183 static void
add_to_BLOCK_HEADER(Dwg_Object * restrict obj,Dwg_Object_Ref * restrict ownerhandle)12184 add_to_BLOCK_HEADER (Dwg_Object *restrict obj,
12185                      Dwg_Object_Ref *restrict ownerhandle)
12186 {
12187   Dwg_Data *dwg = obj->parent;
12188   Dwg_Object_BLOCK_HEADER *_ctrl;
12189   Dwg_Object *ctrl = dwg_ref_object (dwg, ownerhandle);
12190 
12191   if (!ctrl || ctrl->type != DWG_TYPE_BLOCK_HEADER)
12192     return;
12193   _ctrl = ctrl->tio.object->tio.BLOCK_HEADER;
12194   if (obj->supertype != DWG_SUPERTYPE_ENTITY)
12195     return;
12196   LOG_TRACE ("add_to_BLOCK_HEADER %s: %s [%lX]\n", _ctrl->name, obj->name,
12197              obj->handle.value);
12198   if (obj->type == DWG_TYPE_ENDBLK)
12199     {
12200       if (!_ctrl->endblk_entity)
12201         _ctrl->endblk_entity
12202             = dwg_add_handleref (dwg, 3, obj->handle.value, ctrl);
12203       return;
12204     }
12205   if (obj->type == DWG_TYPE_BLOCK)
12206     {
12207       if (!_ctrl->block_entity)
12208         _ctrl->block_entity
12209             = dwg_add_handleref (dwg, 3, obj->handle.value, ctrl);
12210       return;
12211     }
12212   if (!_ctrl->first_entity)
12213     _ctrl->last_entity = _ctrl->first_entity
12214         = dwg_add_handleref (dwg, 4, obj->handle.value, NULL);
12215   else
12216     // always overwrite. and it is global, so we can reuse it.
12217     _ctrl->last_entity = dwg_add_handleref (dwg, 4, obj->handle.value, NULL);
12218   PUSH_HV (_ctrl, num_owned, entities, _ctrl->last_entity);
12219 }
12220 
12221 static int
dxf_entities_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12222 dxf_entities_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12223 {
12224   Dxf_Pair *pair = dxf_read_pair (dat);
12225   char name[80];
12226   unsigned long mspace
12227       = dwg->header_vars.BLOCK_RECORD_MSPACE
12228             ? dwg->header_vars.BLOCK_RECORD_MSPACE->absolute_ref
12229             : 0x1F;
12230   unsigned long pspace
12231       = dwg->header_vars.BLOCK_RECORD_PSPACE
12232             ? dwg->header_vars.BLOCK_RECORD_PSPACE->absolute_ref
12233             : 0UL;
12234   BITCODE_H mspace_ref = dwg_model_space_ref (dwg);
12235 
12236   while (pair != NULL && pair->code == 0 && pair->value.s)
12237     {
12238       strncpy (name, pair->value.s, 79);
12239       name[79] = '\0';
12240       entity_alias (name);
12241       // until 0 ENDSEC
12242       while (pair != NULL && pair->code == 0 && pair->value.s
12243              && (is_dwg_entity (name) || strEQc (name, "DIMENSION")))
12244         {
12245           char *dxfname = strdup (pair->value.s);
12246           dxf_free_pair (pair);
12247           pair = new_object (name, dxfname, dat, dwg, 0, NULL);
12248           if (!pair)
12249             return DWG_ERR_INVALIDDWG;
12250           if (pair->code == 0 && pair->value.s)
12251             {
12252               Dwg_Object *obj = &dwg->object[dwg->num_objects - 1];
12253               Dwg_Object_Entity *ent = obj->tio.entity;
12254               if (ent->ownerhandle)
12255                 {
12256                   if (ent->ownerhandle->absolute_ref == mspace)
12257                     ent->entmode = 2;
12258                   else if (pspace && ent->ownerhandle->absolute_ref == pspace)
12259                     ent->entmode = 1;
12260                   add_to_BLOCK_HEADER (obj, ent->ownerhandle);
12261                 }
12262               else
12263                 {
12264                   ent->entmode = 2;
12265                   add_to_BLOCK_HEADER (obj, mspace_ref);
12266                 }
12267 
12268               in_postprocess_handles (obj);
12269               strncpy (name, pair->value.s, 79);
12270               name[79] = '\0';
12271               entity_alias (name);
12272             }
12273         }
12274       DXF_RETURN_ENDSEC (0)
12275       else
12276         LOG_WARN ("Unhandled 0 %s (%s)", name, "entities");
12277       dxf_free_pair (pair);
12278       pair = dxf_read_pair (dat);
12279       DXF_CHECK_EOF;
12280     }
12281   dxf_free_pair (pair);
12282   return 0;
12283 }
12284 
12285 static int
dxf_objects_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12286 dxf_objects_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12287 {
12288   char name[80];
12289   Dxf_Pair *pair = dxf_read_pair (dat);
12290   while (pair != NULL)
12291     {
12292       while (pair != NULL && pair->code == 0 && pair->value.s)
12293         {
12294           strncpy (name, pair->value.s, 79);
12295           name[79] = '\0';
12296           object_alias (name);
12297           if (is_dwg_object (name))
12298             {
12299               char *dxfname = strdup (pair->value.s);
12300               dxf_free_pair (pair);
12301               pair = new_object (name, dxfname, dat, dwg, 0, NULL);
12302               if (!pair)
12303                 return DWG_ERR_INVALIDDWG;
12304             }
12305           else
12306             {
12307               DXF_RETURN_ENDSEC (0);
12308               LOG_WARN ("Unhandled 0 %s (%s)", name, "objects");
12309               dxf_free_pair (pair);
12310               pair = dxf_read_pair (dat);
12311               DXF_CHECK_EOF;
12312             }
12313         }
12314       dxf_free_pair (pair);
12315       pair = dxf_read_pair (dat);
12316       DXF_CHECK_EOF;
12317     }
12318   dxf_free_pair (pair);
12319   return 0;
12320 }
12321 
12322 // redirected from ACDSDATA for now
12323 static int
dxf_unknownsection_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12324 dxf_unknownsection_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12325 {
12326   Dxf_Pair *pair = dxf_read_pair (dat);
12327   // until 0 ENDSEC
12328   while (pair)
12329     {
12330       while (pair && pair->code == 0 && pair->value.s)
12331         {
12332           DXF_RETURN_ENDSEC (0);
12333           LOG_WARN ("Unhandled 0 %s (%s)", pair->value.s, "unknownsection");
12334           dxf_free_pair (pair);
12335           pair = dxf_read_pair (dat);
12336           DXF_CHECK_EOF;
12337         }
12338       dxf_free_pair (pair);
12339       pair = dxf_read_pair (dat);
12340       DXF_CHECK_EOF;
12341     }
12342   dxf_free_pair (pair);
12343   return DWG_ERR_INVALIDTYPE;
12344 }
12345 
12346 // read to THUMBNAIL dwg->thumbnail, size 90. not entity->preview
12347 static int
dxf_thumbnail_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12348 dxf_thumbnail_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12349 {
12350   Dxf_Pair *pair = dxf_read_pair (dat);
12351   unsigned written = 0;
12352 
12353   while (pair)
12354     {
12355       switch (pair->code)
12356         {
12357         case 0: // ENDSEC
12358           dxf_free_pair (pair);
12359           return 0;
12360         case 90:
12361           dwg->thumbnail.size = pair->value.l; // INT32 => long
12362           dwg->thumbnail.chain
12363               = (unsigned char *)calloc (dwg->thumbnail.size, 1);
12364           if (!dwg->thumbnail.chain)
12365             {
12366               dxf_free_pair (pair);
12367               LOG_ERROR ("Out of memory");
12368               return DWG_ERR_OUTOFMEM;
12369             }
12370           LOG_TRACE ("PREVIEW.size = %ld\n", dwg->thumbnail.size);
12371           break;
12372         case 310:
12373           if (pair->value.s)
12374             {
12375               unsigned len = strlen (pair->value.s);
12376               unsigned blen = len / 2;
12377               unsigned read;
12378               //const char *pos = pair->value.s;
12379               unsigned char *s = &dwg->thumbnail.chain[written];
12380               if (blen + written > dwg->thumbnail.size)
12381                 {
12382                   dxf_free_pair (pair);
12383                   LOG_ERROR ("PREVIEW.size overflow: %u + written %u > "
12384                              "size: %lu",
12385                              blen, written, dwg->thumbnail.size);
12386                   return 1;
12387                 }
12388               if ((read = in_hex2bin (s, pair->value.s, blen) != blen))
12389                 LOG_ERROR ("in_hex2bin read only %u of %u", read, blen);
12390               written += read;
12391               LOG_TRACE ("PREVIEW.chain += %u (%u/%lu)\n", blen, written,
12392                          dwg->thumbnail.size);
12393             }
12394           break;
12395         default:
12396           LOG_ERROR ("Unknown DXF code %d for %s", pair->code,
12397                      "THUMBNAILIMAGE");
12398           break;
12399         }
12400       dxf_free_pair (pair);
12401       pair = dxf_read_pair (dat);
12402       if (!pair)
12403         break;
12404     }
12405   dxf_free_pair (pair);
12406   return 0;
12407 }
12408 
12409 // read to AcDs, TODO
12410 // SECTION ACDSDATA: 0 ACDSSCHEMA, 0 ACDSRECORD
12411 static int
dxf_acds_read(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12412 dxf_acds_read (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12413 {
12414   // Dxf_Pair *pair = dxf_read_pair (dat);
12415   // unsigned written = 0;
12416   LOG_WARN ("SECTION %s ignored for now", "ACDSDATA");
12417   dxf_unknownsection_read (dat, dwg);
12418   return 0;
12419 }
12420 
12421 static void
resolve_postponed_header_refs(Dwg_Data * restrict dwg)12422 resolve_postponed_header_refs (Dwg_Data *restrict dwg)
12423 {
12424   Dwg_Header_Variables *vars = &dwg->header_vars;
12425   uint32_t i;
12426   LOG_TRACE ("resolve %d postponed header ref names:\n", header_hdls->nitems);
12427   for (i = 0; i < header_hdls->nitems; i++)
12428     {
12429       char *field = header_hdls->items[i].field;
12430       Dxf_Pair p = { 0, DWG_VT_STRING };
12431       BITCODE_H hdl = NULL;
12432       p.value.s = header_hdls->items[i].name;
12433       if (!p.value.s || !*p.value.s)
12434         {
12435           LOG_WARN ("HEADER.%s empty dxf:%d", field, (int)p.code);
12436           continue;
12437         }
12438       p.code = header_hdls->items[i].code;
12439       if (strEQc (field, "DIMSTYLE"))
12440         p.code = 3;
12441       else if (strstr (field, "UCS"))
12442         p.code = 345;
12443       hdl = find_tablehandle (dwg, &p);
12444       if (hdl)
12445         {
12446           if (hdl->handleref.code != 5)
12447             hdl = dwg_add_handleref (dwg, 5, hdl->absolute_ref, NULL);
12448           dwg_dynapi_header_set_value (dwg, field, &hdl, 1);
12449           LOG_TRACE ("HEADER.%s %s => " FORMAT_REF " [H %d]\n", field,
12450                      p.value.s, ARGS_REF (hdl), (int)p.code);
12451         }
12452       else if (strEQc (field, "CMLSTYLE"))
12453         {
12454           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "MLINESTYLE");
12455           if (hdl)
12456             {
12457               if (hdl->handleref.code != 5)
12458                 hdl = dwg_add_handleref (dwg, 5, hdl->absolute_ref, NULL);
12459               dwg_dynapi_header_set_value (dwg, field, &hdl, 1);
12460               LOG_TRACE ("HEADER.%s %s => " FORMAT_REF " [H %d]\n", field,
12461                          p.value.s, ARGS_REF (hdl), (int)p.code)
12462             }
12463           else
12464             LOG_WARN ("Unknown HEADER.%s %s dxf:%d", field, p.value.s,
12465                       (int)p.code)
12466         }
12467       else
12468         LOG_WARN ("Unknown HEADER.%s %s dxf:%d", field, p.value.s, (int)p.code)
12469     }
12470 }
12471 
12472 // i.e. layer or block name
12473 static void
resolve_postponed_object_refs(Dwg_Data * restrict dwg)12474 resolve_postponed_object_refs (Dwg_Data *restrict dwg)
12475 {
12476   uint32_t i;
12477   LOG_TRACE ("resolve %d postponed object ref names:\n", obj_hdls->nitems);
12478   for (i = 0; i < obj_hdls->nitems; i++)
12479     {
12480       char *field = obj_hdls->items[i].field;
12481       Dxf_Pair p = { 0, DWG_VT_STRING };
12482       BITCODE_H hdl = NULL;
12483       int objid = obj_hdls->items[i].code;
12484       Dwg_Object *obj = &dwg->object[objid];
12485       int is_entity = obj->supertype == DWG_SUPERTYPE_ENTITY;
12486 
12487       p.value.s = obj_hdls->items[i].name;
12488       if (!p.value.s || !*p.value.s)
12489         {
12490           LOG_WARN ("%s.%s empty", obj->name, field);
12491           continue;
12492         }
12493       // TODO find field type => dxf code
12494       if (strEQc (field, "block_header"))
12495         hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "BLOCK");
12496       else if (strEQc (field, "style"))
12497         {
12498           if (is_entity)
12499             p.code = 7;
12500           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "STYLE");
12501         }
12502       else if (strEQc (field, "dimstyle"))
12503         {
12504           if (is_entity)
12505             p.code = 3;
12506           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "DIMSTYLE");
12507         }
12508       else if (strEQc (field, "layer"))
12509         {
12510           if (is_entity)
12511             p.code = 8;
12512           hdl = find_tablehandle (dwg, &p);
12513         }
12514       else if (strEQc (field, "ltype"))
12515         {
12516           if (is_entity)
12517             p.code = 6;
12518           hdl = find_tablehandle (dwg, &p);
12519         }
12520       else if (strEQc (field, "material")
12521                && (is_entity || obj->fixedtype == DWG_TYPE_LAYER))
12522         {
12523           if (is_entity)
12524             p.code = 347;
12525           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "MATERIAL");
12526         }
12527       else if (is_entity && strEQc (field, "shadow"))
12528         {
12529           p.code = 361;
12530           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "SHADOW");
12531         }
12532       else if (strEQc (field, "plotstyle")
12533                && (is_entity || obj->fixedtype == DWG_TYPE_LAYER))
12534         {
12535           if (is_entity)
12536             p.code = 390;
12537           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "PLOTSTYLENAME");
12538         }
12539       else if (is_entity && strEQc (field, "full_visualstyle"))
12540         {
12541           p.code = 348;
12542           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "VISUALSTYLE");
12543         }
12544       else if (is_entity && strEQc (field, "face_visualstyle"))
12545         {
12546           p.code = 348;
12547           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "VISUALSTYLE");
12548         }
12549       else if (is_entity && strEQc (field, "edge_visualstyle"))
12550         {
12551           p.code = 348;
12552           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "VISUALSTYLE");
12553         }
12554       else if (obj->fixedtype == DWG_TYPE_LAYER
12555                && strEQc (field, "visualstyle"))
12556         {
12557           hdl = dwg_find_tablehandle_silent (dwg, p.value.s, "VISUALSTYLE");
12558         }
12559       // TODO: check if DXF by name:
12560       // background, named_ucs, base_ucs, shadeplot, sun, livesection (VIEW,
12561       // VIEWPORT)
12562       else
12563         LOG_WARN ("missing code for %s", field)
12564       if (hdl)
12565         {
12566           Dwg_Object_APPID *_obj = obj->tio.object->tio.APPID;
12567           if (hdl->handleref.code != 5)
12568             hdl = dwg_add_handleref (dwg, 5, hdl->absolute_ref, NULL);
12569           if (p.code > 0)
12570             dwg_dynapi_common_set_value (_obj, field, &hdl, 0);
12571           else
12572             dwg_dynapi_entity_set_value (_obj, obj->name, field, &hdl, 0);
12573           LOG_TRACE ("%s.%s %s => " FORMAT_REF " [H %d]\n", obj->name, field,
12574                      p.value.s, ARGS_REF (hdl), (int)p.code);
12575         }
12576       else
12577         LOG_WARN ("Unknown %s.%s %s", obj->name, field, p.value.s)
12578     }
12579 }
12580 
12581 #define CHECK_DICTIONARY_HDR(name)                                            \
12582   if (!vars->DICTIONARY_##name)                                               \
12583     {                                                                         \
12584       vars->DICTIONARY_##name = dwg_find_dictionary (dwg, #name);             \
12585       if (vars->DICTIONARY_##name)                                            \
12586         LOG_TRACE ("HEADER.DICTIONARY_" #name " = " FORMAT_REF "\n",          \
12587                    ARGS_REF (vars->DICTIONARY_##name))                        \
12588       else if ((vars->DICTIONARY_##name                                       \
12589                 = dwg_find_dictionary (dwg, "ACAD_" #name)))                  \
12590         LOG_TRACE ("HEADER.DICTIONARY_" #name " = " FORMAT_REF "\n",          \
12591                    ARGS_REF (vars->DICTIONARY_##name))                        \
12592     }
12593 
12594 static void
resolve_header_dicts(Dwg_Data * restrict dwg)12595 resolve_header_dicts (Dwg_Data *restrict dwg)
12596 {
12597   Dwg_Header_Variables *vars = &dwg->header_vars;
12598 
12599   if (!vars->DICTIONARY_NAMED_OBJECT)
12600     vars->DICTIONARY_NAMED_OBJECT = dwg_add_handleref (dwg, 3, 0xC, NULL);
12601   // only possible after OBJECTS
12602   CHECK_DICTIONARY_HDR (ACAD_GROUP)
12603   CHECK_DICTIONARY_HDR (ACAD_MLINESTYLE)
12604   if (dwg->header.version >= R_2000)
12605     {
12606       CHECK_DICTIONARY_HDR (LAYOUT)
12607       CHECK_DICTIONARY_HDR (PLOTSETTINGS)
12608       CHECK_DICTIONARY_HDR (PLOTSTYLENAME)
12609     }
12610   if (dwg->header.version >= R_2004)
12611     {
12612       CHECK_DICTIONARY_HDR (MATERIAL)
12613       CHECK_DICTIONARY_HDR (COLOR)
12614     }
12615   if (dwg->header.version >= R_2007)
12616     {
12617       CHECK_DICTIONARY_HDR (VISUALSTYLE)
12618     }
12619 }
12620 #undef CHECK_DICTIONARY_HDR
12621 
12622 static void
resolve_postponed_eed_refs(Dwg_Data * restrict dwg)12623 resolve_postponed_eed_refs (Dwg_Data *restrict dwg)
12624 {
12625   LOG_TRACE ("resolve %d postponed eed APPID refs\n", eed_hdls->nitems);
12626   for (uint32_t i = 0; i < eed_hdls->nitems; i++)
12627     {
12628       char *name = eed_hdls->items[i].name;
12629       BITCODE_H ref
12630           = dwg_find_tablehandle (dwg, eed_hdls->items[i].name, "APPID");
12631       if (ref)
12632         {
12633           // copy to eed[i].handle. need: objid + eed[i]
12634           BITCODE_RL objid;
12635           Dwg_Eed *eed;
12636           int j = (int)eed_hdls->items[i].code;
12637           sscanf (eed_hdls->items[i].field, "%d", &objid);
12638           if (objid <= 0 || objid >= dwg->num_objects)
12639             {
12640               LOG_ERROR ("Skip invalid postponed eed APPID %s",
12641                          eed_hdls->items[i].field);
12642               continue;
12643             }
12644           eed = dwg->object[objid].tio.object->eed;
12645           if (!eed || j >= (int)dwg->object[objid].tio.object->num_eed)
12646             {
12647               LOG_ERROR ("Skip invalid postponed APPID eed[%d]", j);
12648               continue;
12649             }
12650           memcpy (&eed[j].handle, &ref->handleref, sizeof (Dwg_Handle));
12651           eed[j].handle.code = 5;
12652           LOG_TRACE (
12653               "postponed %s[%d]->eed[%d].handle for APPID.%s => " FORMAT_H
12654               " [H]\n",
12655               dwg->object[objid].name, objid, j, name, ARGS_H (eed[j].handle));
12656         }
12657       else
12658         LOG_WARN ("Unknown eed[].handle for APPID.%s", name)
12659     }
12660 }
12661 
12662 EXPORT int
dwg_read_dxf(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12663 dwg_read_dxf (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12664 {
12665   // const int minimal = dwg->opts & DWG_OPTS_MINIMAL;
12666   Dxf_Pair *pair = NULL;
12667   int error = 0;
12668 
12669   loglevel = dwg->opts & DWG_OPTS_LOGLEVEL;
12670   if (!dat->chain && dat->fh)
12671     {
12672       error = dat_read_stream (dat, dat->fh);
12673       if (error >= DWG_ERR_CRITICAL)
12674         return error;
12675       if (dat->size >= 22 &&
12676           !memcmp (dat->chain, "AutoCAD Binary DXF",
12677                    sizeof ("AutoCAD Binary DXF") - 1))
12678         {
12679           dat->opts |= DWG_OPTS_DXFB;
12680           dat->byte = 22;
12681         }
12682     }
12683   if (dat->size < 256)
12684     {
12685       LOG_ERROR ("DXF input too small, %lu byte.\n", dat->size);
12686       return DWG_ERR_IOERROR;
12687     }
12688   /* Fail early on DWG */
12689   if (!memcmp (dat->chain, "AC10", 4) ||
12690       !memcmp (dat->chain, "AC1.", 4) ||
12691       !memcmp (dat->chain, "AC2.10", 4) ||
12692       !memcmp (dat->chain, "MC0.0", 4))
12693     {
12694       LOG_ERROR ("This is a DWG, not a DXF\n");
12695       return DWG_ERR_INVALIDDWG;
12696     }
12697   dat->opts |= DWG_OPTS_INDXF;
12698   dwg->opts |= DWG_OPTS_INDXF;
12699   //num_dxf_objs = 0;
12700   //size_dxf_objs = 1000;
12701   //dxf_objs = (Dxf_Objs *)malloc (1000 * sizeof (Dxf_Objs));
12702   if (!dwg->object_map)
12703     dwg->object_map = hash_new (dat->size / 1000);
12704   // cannot rely on ref->obj during realloc's
12705   dwg->dirty_refs = 1;
12706 
12707   header_hdls = new_array_hdls (16);
12708   eed_hdls = new_array_hdls (16);
12709   obj_hdls = new_array_hdls (16);
12710 
12711   // start with the BLOCK_HEADER at objid 0
12712   if (!dwg->num_objects)
12713     {
12714       Dwg_Object *obj;
12715       Dwg_Object_BLOCK_HEADER *_obj;
12716       char *dxfname = strdup ((char *)"BLOCK_HEADER");
12717       NEW_OBJECT (dwg, obj);
12718       ADD_OBJECT (BLOCK_HEADER);
12719       // dwg->header.version probably here still unknown. <r2000: 0x17
12720       // later fixed up when reading $ACADVER and the BLOCK_HEADER.name
12721       _obj->name = dwg_add_u8_input (dwg, "*Model_Space");
12722       _obj->is_xref_ref = 1;
12723       obj->tio.object->is_xdic_missing = 1;
12724       dwg_add_handle (&obj->handle, 0, 0x1F, obj);
12725       obj->tio.object->ownerhandle = dwg_add_handleref (dwg, 4, 1, NULL);
12726     }
12727 
12728   while (dat->byte < dat->size)
12729     {
12730       pair = dxf_read_pair (dat);
12731       DXF_BREAK_EOF;
12732       pair = dxf_expect_code (dat, pair, 0);
12733       DXF_BREAK_EOF;
12734       if (pair->type == DWG_VT_STRING && strEQc (pair->value.s, "SECTION"))
12735         {
12736           dxf_free_pair (pair);
12737           pair = dxf_read_pair (dat);
12738           DXF_BREAK_EOF;
12739           pair = dxf_expect_code (dat, pair, 2);
12740           DXF_BREAK_EOF;
12741           if (!pair->value.s)
12742             {
12743               LOG_ERROR ("Expected SECTION string code 2, got code %d",
12744                          pair->code);
12745               dxf_free_pair (pair);
12746               pair = NULL;
12747               break;
12748             }
12749           else if (strEQc (pair->value.s, "HEADER"))
12750             {
12751               dxf_free_pair (pair);
12752               pair = NULL;
12753               error = dxf_header_read (dat, dwg);
12754               if (error > DWG_ERR_CRITICAL)
12755                 goto error;
12756               dxf_fixup_header (dwg);
12757               // skip minimal DXF
12758               /*
12759               if (!dwg->header_vars.DIMPOST) // T in all versions
12760                 {
12761                   LOG_ERROR ("Unsupported minimal DXF");
12762                   return DWG_ERR_INVALIDDWG;
12763                 }
12764               */
12765             }
12766           else if (strEQc (pair->value.s, "CLASSES"))
12767             {
12768               dxf_free_pair (pair);
12769               pair = NULL;
12770               error = dxf_classes_read (dat, dwg);
12771               if (error > DWG_ERR_CRITICAL)
12772                 return error;
12773             }
12774           else if (strEQc (pair->value.s, "TABLES"))
12775             {
12776               BITCODE_H hdl;
12777               dxf_free_pair (pair);
12778               pair = NULL;
12779               error = dxf_tables_read (dat, dwg);
12780               if (error > DWG_ERR_CRITICAL)
12781                 goto error;
12782 
12783               resolve_postponed_header_refs (dwg);
12784               resolve_postponed_eed_refs (dwg);
12785 
12786               // should not happen
12787               if (!dwg->header_vars.LTYPE_BYLAYER
12788                   && (hdl = dwg_find_tablehandle_silent (
12789                           dwg, (char *)"ByLayer", "LTYPE")))
12790                 dwg->header_vars.LTYPE_BYLAYER
12791                     = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12792               // should not happen
12793               if (!dwg->header_vars.LTYPE_BYBLOCK
12794                   && (hdl = dwg_find_tablehandle_silent (
12795                           dwg, (char *)"ByBlock", "LTYPE")))
12796                 dwg->header_vars.LTYPE_BYBLOCK
12797                     = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12798               // but this is needed
12799               if (!dwg->header_vars.LTYPE_CONTINUOUS
12800                   && (hdl = dwg_find_tablehandle_silent (
12801                           dwg, (char *)"Continuous", "LTYPE")))
12802                 dwg->header_vars.LTYPE_CONTINUOUS
12803                     = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12804             }
12805           else if (strEQc (pair->value.s, "BLOCKS"))
12806             {
12807               BITCODE_H hdl;
12808               dxf_free_pair (pair);
12809               pair = NULL;
12810               error = dxf_blocks_read (dat, dwg);
12811               if (error > DWG_ERR_CRITICAL)
12812                 goto error;
12813 
12814               // resolve_postponed_header_refs (dwg);
12815               if (!dwg->header_vars.BLOCK_RECORD_PSPACE
12816                   && (hdl = dwg_find_tablehandle_silent (
12817                           dwg, (char *)"*Paper_Space", "BLOCK")))
12818                 dwg->header_vars.BLOCK_RECORD_PSPACE
12819                     = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12820               if (!dwg->header_vars.BLOCK_RECORD_MSPACE
12821                   && (hdl = dwg_find_tablehandle_silent (
12822                           dwg, (char *)"*Model_Space", "BLOCK")))
12823                 dwg->header_vars.BLOCK_RECORD_MSPACE
12824                     = dwg_add_handleref (dwg, 5, hdl->handleref.value, NULL);
12825             }
12826           else if (strEQc (pair->value.s, "ENTITIES"))
12827             {
12828               dxf_free_pair (pair);
12829               pair = NULL;
12830               error = dxf_entities_read (dat, dwg);
12831               if (error > DWG_ERR_CRITICAL)
12832                 goto error;
12833             }
12834           else if (strEQc (pair->value.s, "OBJECTS"))
12835             {
12836               dxf_free_pair (pair);
12837               pair = NULL;
12838               error = dxf_objects_read (dat, dwg);
12839               if (error > DWG_ERR_CRITICAL)
12840                 goto error;
12841               resolve_header_dicts (dwg);
12842             }
12843           else if (strEQc (pair->value.s, "THUMBNAILIMAGE"))
12844             {
12845               dxf_free_pair (pair);
12846               pair = NULL;
12847               error = dxf_thumbnail_read (dat, dwg);
12848             }
12849           else if (strEQc (pair->value.s, "ACDSDATA"))
12850             {
12851               dxf_free_pair (pair);
12852               pair = NULL;
12853               error = dxf_acds_read (dat, dwg);
12854             }
12855           else // if (strEQc (pair->value.s, ""))
12856             {
12857               LOG_WARN ("SECTION %s ignored for now", pair->value.s);
12858               dxf_free_pair (pair);
12859               pair = NULL;
12860               error = dxf_unknownsection_read (dat, dwg);
12861             }
12862         }
12863       else
12864         {
12865           LOG_ERROR ("Expected string SECTION");
12866           dxf_free_pair (pair);
12867         }
12868     }
12869   if (pair != NULL && pair->code == 0 &&
12870       pair->value.s != NULL && strEQc (pair->value.s, "EOF"))
12871     ;
12872   else if (dat->byte >= dat->size || (pair == NULL))
12873     error |= DWG_ERR_IOERROR;
12874   resolve_postponed_header_refs (dwg);
12875   resolve_postponed_object_refs (dwg);
12876   LOG_HANDLE ("Resolving pointers from ObjectRef vector:\n");
12877   dwg_resolve_objectrefs_silent (dwg);
12878   free_array_hdls (header_hdls);
12879   free_array_hdls (eed_hdls);
12880   free_array_hdls (obj_hdls);
12881   if (dwg->header.version <= R_2000 && dwg->header.from_version > R_2000)
12882     dwg_fixup_BLOCKS_entities (dwg);
12883   LOG_TRACE ("import from DXF\n");
12884   if (error > DWG_ERR_CRITICAL)
12885     return error;
12886   else
12887     return dwg->num_objects ? 1 : 0;
12888 
12889 error:
12890   dwg->dirty_refs = 0;
12891   free_array_hdls (header_hdls);
12892   free_array_hdls (eed_hdls);
12893   free_array_hdls (obj_hdls);
12894   return error;
12895 }
12896 
12897 EXPORT int
dwg_read_dxfb(Bit_Chain * restrict dat,Dwg_Data * restrict dwg)12898 dwg_read_dxfb (Bit_Chain *restrict dat, Dwg_Data *restrict dwg)
12899 {
12900   dwg->opts |= DWG_OPTS_DXFB; // binary
12901   dat->opts |= DWG_OPTS_DXFB;
12902   if (dat->size >= 22 && dat->byte < 22 &&
12903       !memcmp (dat->chain, "AutoCAD Binary DXF",
12904                sizeof ("AutoCAD Binary DXF") - 1))
12905     {
12906       dat->byte = 22;
12907     }
12908   return dwg_read_dxf (dat, dwg);
12909 }
12910 
12911 #undef IS_INDXF
12912