2151 lines
79 KiB
C
2151 lines
79 KiB
C
/*****************************************************************************/
|
|
/* LibreDWG - free implementation of the DWG file format */
|
|
/* */
|
|
/* Copyright (C) 2020-2023 Free Software Foundation, Inc. */
|
|
/* */
|
|
/* This library is free software, licensed under the terms of the GNU */
|
|
/* General Public License as published by the Free Software Foundation, */
|
|
/* either version 3 of the License, or (at your option) any later version. */
|
|
/* You should have received a copy of the GNU General Public License */
|
|
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
/*****************************************************************************/
|
|
|
|
/*
|
|
* dwgadd.c: Interpret a small language to add entities to a DWG or DXF.
|
|
* written by Reini Urban
|
|
*/
|
|
|
|
#include "../src/config.h"
|
|
#ifdef HAVE_SSCANF_S
|
|
# define __STDC_WANT_LIB_EXT1__ 1
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <getopt.h>
|
|
|
|
#include <dwg.h>
|
|
#define DWG_LOGLEVEL loglevel
|
|
#include "logging.h"
|
|
#include <dwg_api.h>
|
|
|
|
#include "common.h"
|
|
#include "decode.h"
|
|
#include "encode.h"
|
|
#include "bits.h"
|
|
#include "classes.h"
|
|
#include "dynapi.h"
|
|
#ifndef DISABLE_JSON
|
|
# include "in_json.h"
|
|
# include "out_json.h"
|
|
#endif
|
|
#ifndef DISABLE_DXF
|
|
# include "out_dxf.h"
|
|
# include "in_dxf.h"
|
|
#endif
|
|
|
|
static int dwg_add_dat (Dwg_Data **dwgp, Bit_Chain *dat);
|
|
static unsigned int loglevel;
|
|
|
|
// accepts only ASCII strings, for fuzzing only
|
|
#ifdef HAVE_SSCANF_S
|
|
# define SSCANF_S sscanf_s
|
|
// clang-format off
|
|
# define SZ ,119
|
|
// clang-format on
|
|
# define FMT_NAME "%[a-zA-Z0-9_]"
|
|
# define FMT_TAG "%[^ !]"
|
|
# define FMT_TBL "\"%[a-zA-Z0-9._ -]\""
|
|
# define FMT_PATH "\"%[a-zA-Z0-9_. \\-]\""
|
|
# define FMT_ANY "\"%[^\"]"
|
|
#else
|
|
# define SSCANF_S sscanf
|
|
# define SZ
|
|
# define FMT_NAME "%119[a-zA-Z0-9_]"
|
|
# define FMT_TAG "%119[^ !]"
|
|
# define FMT_TBL "\"%119[a-zA-Z0-9._ -]\""
|
|
# define FMT_PATH "\"%119[a-zA-Z0-9_. \\-]\""
|
|
# define FMT_ANY "\"%119[^\"]\""
|
|
#endif
|
|
|
|
static int
|
|
usage (void)
|
|
{
|
|
printf ("\nUsage: dwgadd [-v[0-9]] [--as rNNNN] [--dxf|--binary|--json] -o "
|
|
"OUTFILE "
|
|
"ADDFILE\n");
|
|
return 1;
|
|
}
|
|
static int
|
|
fn_version (void)
|
|
{
|
|
printf ("dwgadd %s\n", PACKAGE_VERSION);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
log_p (unsigned level, char *p)
|
|
{
|
|
char *n = strchr (p, '\n');
|
|
int size = n ? n - p : (int)strlen (p);
|
|
if (DWG_LOGLEVEL >= level)
|
|
{
|
|
HANDLER (OUTPUT, "%.*s\n", size, p);
|
|
}
|
|
}
|
|
|
|
static int
|
|
help (void)
|
|
{
|
|
printf ("\nUsage: dwgadd [OPTIONS] -o outfile addfile\n");
|
|
printf ("Create a DWG (or DXF, JSON) by adding entities with instructions "
|
|
"from a special dwgadd file.\n"
|
|
"See `man 5 dwgadd`\n");
|
|
#ifndef DISABLE_DXF
|
|
printf (" --dxf: write DXF, not DWG\n");
|
|
printf (" --binary: write binary DXF, not DWG\n");
|
|
#endif
|
|
#ifndef DISABLE_JSON
|
|
printf (" --json: write JSON, not DWG\n");
|
|
#endif
|
|
#ifdef HAVE_GETOPT_LONG
|
|
printf (" -v[0-9], --verbose [0-9] verbosity\n");
|
|
printf (" --as rNNNN save as version\n");
|
|
printf (" Valid versions:\n");
|
|
printf (" r1.1, r1.2, r1.4, r2.6, r2.10, r9, r10, r11, r12, "
|
|
"r14, r2000 (default)\n");
|
|
printf (" Planned versions:\n");
|
|
printf (" r2004, r2007, r2010, r2013, r2018\n");
|
|
printf (" -o outfile, --file outfile (default: stdout)\n");
|
|
#else
|
|
printf (" -v[0-9] verbosity\n");
|
|
printf (" -a rNNNN save as version\n");
|
|
printf (" Valid versions:\n");
|
|
printf (" r1.1, r1.2, r1.4, r2.6, r2.10, r9, r10, r11, r12, "
|
|
"r14, r2000 (default)\n");
|
|
printf (" Planned versions:\n");
|
|
printf (" r2004, r2007, r2010, r2013, r2018\n");
|
|
printf (" -o outfile (default: stdout)\n");
|
|
#endif
|
|
printf ("\n"
|
|
" --version display the version and exit\n");
|
|
printf (" --help display this help and exit\n");
|
|
return 0;
|
|
}
|
|
|
|
static int opts = 1;
|
|
|
|
int
|
|
main (int argc, char *argv[])
|
|
{
|
|
int i = 0;
|
|
Dwg_Data dwg;
|
|
Dwg_Data *dwgp;
|
|
Bit_Chain dat = { 0 };
|
|
Bit_Chain out_dat = { 0 };
|
|
const char *outfile = NULL;
|
|
Dwg_Version_Type dwg_version = R_2000;
|
|
// boolean options
|
|
struct opt_s
|
|
{
|
|
unsigned dwg : 1;
|
|
unsigned dxf : 1;
|
|
unsigned binary : 1;
|
|
unsigned json : 1;
|
|
unsigned geojson : 1;
|
|
unsigned verify : 1;
|
|
unsigned force_free : 1;
|
|
} opt;
|
|
int retval = 0;
|
|
int c;
|
|
FILE *fp;
|
|
struct stat attrib;
|
|
#ifdef HAVE_GETOPT_LONG
|
|
int option_index = 0;
|
|
static struct option long_options[]
|
|
= { { "verbose", 1, &opts, 1 }, // optional
|
|
{ "file", 1, 0, 'o' }, { "as", 1, 0, 'a' },
|
|
# ifndef DISABLE_JSON
|
|
{ "dxf", 0, 0, 0 }, { "binary", 0, 0, 0 },
|
|
# endif
|
|
# ifndef DISABLE_JSON
|
|
{ "json", 0, 0, 0 }, { "geojson", 0, 0, 0 },
|
|
# endif
|
|
{ "verify", 0, 0, 0 }, { "help", 0, 0, 0 },
|
|
{ "version", 0, 0, 0 }, { "force-free", 0, 0, 0 },
|
|
{ NULL, 0, NULL, 0 } };
|
|
#endif
|
|
|
|
if (argc <= 1 || !*argv[1])
|
|
return usage ();
|
|
memset (&opt, 0, sizeof (struct opt_s));
|
|
|
|
while
|
|
#ifdef HAVE_GETOPT_LONG
|
|
((c = getopt_long (argc, argv, "a:v::o:h", long_options, &option_index))
|
|
!= -1)
|
|
#else
|
|
((c = getopt (argc, argv, "a:v::o:hi")) != -1)
|
|
#endif
|
|
{
|
|
if (c == -1)
|
|
break;
|
|
switch (c)
|
|
{
|
|
case ':': // missing arg
|
|
if (optarg && !strcmp (optarg, "v"))
|
|
{
|
|
opts = 1;
|
|
break;
|
|
}
|
|
fprintf (stderr, "%s: option '-%c' requires an argument\n", argv[0],
|
|
optopt);
|
|
break;
|
|
#ifdef HAVE_GETOPT_LONG
|
|
case 0:
|
|
/* This option sets a flag */
|
|
if (!strcmp (long_options[option_index].name, "verbose"))
|
|
{
|
|
if (opts < 0 || opts > 9)
|
|
return usage ();
|
|
# if defined(USE_TRACING) && defined(HAVE_SETENV)
|
|
{
|
|
char v[2];
|
|
*v = opts + '0';
|
|
*(v + 1) = 0;
|
|
setenv ("LIBREDWG_TRACE", v, 1);
|
|
}
|
|
# endif
|
|
break;
|
|
}
|
|
if (strEQc (long_options[option_index].name, "version"))
|
|
return fn_version ();
|
|
else if (strEQc (long_options[option_index].name, "help"))
|
|
return help ();
|
|
else if (strEQc (long_options[option_index].name, "force-free"))
|
|
opt.force_free = 1;
|
|
# ifndef DISABLE_DXF
|
|
else if (strEQc (long_options[option_index].name, "dxf"))
|
|
opt.dxf = 1;
|
|
else if (strEQc (long_options[option_index].name, "binary"))
|
|
opt.binary = 1;
|
|
# endif
|
|
# ifndef DISABLE_JSON
|
|
else if (strEQc (long_options[option_index].name, "json"))
|
|
opt.json = 1;
|
|
# endif
|
|
else if (!strcmp (long_options[option_index].name, "verify"))
|
|
opt.verify = 1;
|
|
break;
|
|
#else
|
|
case 'i':
|
|
return opt_version ();
|
|
#endif
|
|
case 'o':
|
|
outfile = optarg;
|
|
break;
|
|
case 'a':
|
|
dwg_version = dwg_version_as (optarg);
|
|
if (dwg_version == R_INVALID)
|
|
{
|
|
fprintf (stderr, "Invalid version '%s'\n", argv[i]);
|
|
return usage ();
|
|
}
|
|
break;
|
|
case 'v': // support -v3 and -v
|
|
i = (optind > 0 && optind < argc) ? optind - 1 : 1;
|
|
if (!memcmp (argv[i], "-v", 2))
|
|
{
|
|
opts = argv[i][2] ? argv[i][2] - '0' : 3;
|
|
}
|
|
if (opts < 0 || opts > 9)
|
|
return usage ();
|
|
#if defined(USE_TRACING) && defined(HAVE_SETENV)
|
|
{
|
|
char v[2];
|
|
*v = opts + '0';
|
|
*(v + 1) = 0;
|
|
setenv ("LIBREDWG_TRACE", v, 1);
|
|
}
|
|
#endif
|
|
break;
|
|
case 'h':
|
|
return help ();
|
|
case '?':
|
|
fprintf (stderr, "%s: invalid option '-%c' ignored\n", argv[0],
|
|
optopt);
|
|
break;
|
|
default:
|
|
return usage ();
|
|
}
|
|
}
|
|
i = optind;
|
|
|
|
memset (&dwg, 0, sizeof (dwg));
|
|
loglevel = opts & DWG_OPTS_LOGLEVEL;
|
|
dwg.header.version = dwg_version;
|
|
dwg.header.from_version = dwg_version;
|
|
dwg.opts = opts;
|
|
dat.chain = NULL;
|
|
dat.size = 0;
|
|
dat.opts = opts;
|
|
fp = fopen (argv[i], "rb");
|
|
if (!fp)
|
|
{
|
|
LOG_ERROR ("Could not read %s", argv[i])
|
|
exit (1);
|
|
}
|
|
LOG_INFO ("dwgadd read %s\n", argv[i])
|
|
dat_read_file (&dat, fp, argv[i]);
|
|
if (dat.size == 0)
|
|
{
|
|
LOG_ERROR ("empty %s", argv[i])
|
|
free (dat.chain);
|
|
exit (1);
|
|
}
|
|
|
|
dwgp = &dwg;
|
|
LOG_INFO ("dwgadd process %s\n", argv[i])
|
|
if ((retval = dwg_add_dat (&dwgp, &dat)) == 0)
|
|
{
|
|
int error;
|
|
fclose (fp);
|
|
dwg = *dwgp;
|
|
out_dat.byte = 0;
|
|
out_dat.bit = 0;
|
|
if (!outfile)
|
|
{
|
|
#ifdef _WIN32
|
|
outfile = "CON";
|
|
#else
|
|
outfile = "/dev/stdout";
|
|
#endif
|
|
if (opt.verify)
|
|
LOG_ERROR ("Cannot --verify with %s\n", outfile)
|
|
opt.verify = false;
|
|
}
|
|
LOG_INFO ("\ndwgadd write %s\n", outfile)
|
|
out_dat.fh = fopen (outfile, "wb");
|
|
if (!out_dat.fh)
|
|
{
|
|
LOG_ERROR ("Could not write %s", outfile)
|
|
exit (1);
|
|
}
|
|
out_dat.from_version = dwg.header.from_version;
|
|
out_dat.version = dwg.header.version;
|
|
out_dat.opts = dwg.opts;
|
|
|
|
#ifndef DISABLE_DXF
|
|
if (opt.dxf && opt.binary)
|
|
error = dwg_write_dxfb (&out_dat, &dwg);
|
|
else if (opt.dxf)
|
|
error = dwg_write_dxf (&out_dat, &dwg);
|
|
else
|
|
#endif
|
|
#ifndef DISABLE_JSON
|
|
if (opt.json)
|
|
error = dwg_write_json (&out_dat, &dwg);
|
|
else if (opt.geojson)
|
|
error = dwg_write_geojson (&out_dat, &dwg);
|
|
else
|
|
#endif
|
|
{
|
|
if (out_dat.fh)
|
|
fclose (out_dat.fh);
|
|
opt.dwg = 1;
|
|
unlink (outfile);
|
|
error = dwg_write_file (outfile, &dwg);
|
|
}
|
|
if (error >= DWG_ERR_CRITICAL)
|
|
{
|
|
LOG_ERROR ("dwgadd -o %s failed with error 0x%x", outfile, error)
|
|
retval = error;
|
|
}
|
|
if (!opt.dwg)
|
|
fclose (out_dat.fh);
|
|
free (out_dat.chain);
|
|
free (dat.chain);
|
|
dwg_free (&dwg);
|
|
|
|
if (opt.verify)
|
|
{
|
|
dat.byte = 0;
|
|
dat.bit = 0;
|
|
dat.size = 0;
|
|
dat.opts = opts;
|
|
dat.fh = fopen (outfile, "rb");
|
|
memset (&dwg, 0, sizeof (Dwg_Data));
|
|
dwg.opts = opts;
|
|
LOG_INFO ("\ndwgadd verify %s\n", outfile)
|
|
dat_read_file (&dat, dat.fh, outfile);
|
|
|
|
#ifndef DISABLE_DXF
|
|
if (opt.dxf && opt.binary)
|
|
error = dwg_read_dxfb (&dat, &dwg);
|
|
else if (opt.dxf)
|
|
error = dwg_read_dxf (&dat, &dwg);
|
|
else
|
|
#endif
|
|
#ifndef DISABLE_JSON
|
|
if (opt.json)
|
|
error = dwg_read_json (&dat, &dwg);
|
|
else if (opt.geojson)
|
|
LOG_ERROR ("--verify skipped with --geojson")
|
|
else
|
|
#endif
|
|
error = dwg_decode (&dat, &dwg); // dat -> dwg
|
|
if (error >= DWG_ERR_CRITICAL)
|
|
{
|
|
LOG_ERROR ("--verify failed with error 0x%x", error)
|
|
retval = error;
|
|
}
|
|
fclose (dat.fh);
|
|
dwg_free (&dwg);
|
|
free (dat.chain);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fclose (fp);
|
|
dwg_free (&dwg);
|
|
free (dat.chain);
|
|
LOG_ERROR ("dwgadd failed to add objects")
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
static dwg_point_2d *
|
|
scan_pts2d (unsigned num_pts, char **pp)
|
|
{
|
|
char *p = *pp;
|
|
dwg_point_2d *pts;
|
|
|
|
p = strchr (p, '(');
|
|
if (!p)
|
|
return NULL;
|
|
p++;
|
|
while (isspace (*p))
|
|
p++;
|
|
if (num_pts > 5000)
|
|
exit (0);
|
|
pts = (dwg_point_2d *)calloc (num_pts, 16);
|
|
if (!pts)
|
|
exit (0);
|
|
for (unsigned i = 0; i < num_pts; i++)
|
|
{
|
|
while (isspace (*p))
|
|
p++;
|
|
if (2 == SSCANF_S (p, "(%lf %lf)", &pts[i].x, &pts[i].y))
|
|
{
|
|
p = strchr (p, ')');
|
|
if (!p)
|
|
break;
|
|
p++;
|
|
}
|
|
else
|
|
{
|
|
*pp = p;
|
|
p = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (p)
|
|
{
|
|
if (*p == ')')
|
|
p++;
|
|
while (isspace (*p) && *p != '\n')
|
|
p++;
|
|
*pp = p;
|
|
return pts;
|
|
}
|
|
else
|
|
{
|
|
free (pts);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static dwg_point_3d *
|
|
scan_pts3d (unsigned num_pts, char **pp)
|
|
{
|
|
char *p = *pp;
|
|
dwg_point_3d *pts;
|
|
|
|
p = strchr (p, '(');
|
|
if (!p)
|
|
return NULL;
|
|
p++;
|
|
while (isspace (*p))
|
|
p++;
|
|
if (num_pts > 5000)
|
|
exit (0);
|
|
pts = (dwg_point_3d *)calloc (num_pts, 24);
|
|
if (!pts)
|
|
exit (0);
|
|
for (unsigned i = 0; i < num_pts; i++)
|
|
{
|
|
while (isspace (*p))
|
|
p++;
|
|
if (3 == SSCANF_S (p, "(%lf %lf %lf)", &pts[i].x, &pts[i].y, &pts[i].z))
|
|
{
|
|
p = strchr (p, ')');
|
|
if (!p)
|
|
break;
|
|
p++;
|
|
}
|
|
else
|
|
{
|
|
*pp = p;
|
|
p = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (p && num_pts)
|
|
{
|
|
if (*p == ')')
|
|
p++;
|
|
while (isspace (*p) && *p != '\n')
|
|
p++;
|
|
*pp = p;
|
|
return pts;
|
|
}
|
|
else
|
|
{
|
|
free (pts);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static dwg_face *
|
|
scan_faces (unsigned num, char **pp)
|
|
{
|
|
char *p = *pp;
|
|
dwg_face *faces;
|
|
|
|
p = strchr (p, '(');
|
|
if (!p)
|
|
return NULL;
|
|
p++;
|
|
while (isspace (*p))
|
|
p++;
|
|
if (num > 5000)
|
|
exit (0);
|
|
faces = (dwg_face *)calloc (num, 4 * sizeof (int));
|
|
if (!faces)
|
|
exit (0);
|
|
for (unsigned i = 0; i < num; i++)
|
|
{
|
|
while (isspace (*p))
|
|
p++;
|
|
if (4
|
|
== SSCANF_S (p, "(%hd %hd %hd %hd)", &faces[i][0], &faces[i][1],
|
|
&faces[i][2], &faces[i][3]))
|
|
{
|
|
p = strchr (p, ')');
|
|
if (!p)
|
|
break;
|
|
p++;
|
|
}
|
|
else if (3
|
|
== SSCANF_S (p, "(%hd %hd %hd)", &faces[i][0], &faces[i][1],
|
|
&faces[i][2]))
|
|
{
|
|
p = strchr (p, ')');
|
|
if (!p)
|
|
break;
|
|
faces[i][3] = 0;
|
|
p++;
|
|
}
|
|
else
|
|
{
|
|
*pp = p;
|
|
p = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (p && num)
|
|
{
|
|
if (*p == ')')
|
|
p++;
|
|
while (isspace (*p) && *p != '\n')
|
|
p++;
|
|
*pp = p;
|
|
return faces;
|
|
}
|
|
else
|
|
{
|
|
free (faces);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
static char *
|
|
next_line (char *restrict p, const char *restrict end)
|
|
{
|
|
while (p < end && *p != '\n')
|
|
p++;
|
|
if (p < end)
|
|
p++;
|
|
return p;
|
|
}
|
|
|
|
static ATTRIBUTE_NORETURN void
|
|
fn_error (const char *msg)
|
|
{
|
|
fprintf (stderr, "%s", msg);
|
|
exit (1);
|
|
}
|
|
|
|
#define CHK_MISSING_BLOCK_HEADER \
|
|
if (!hdr) \
|
|
fn_error ("Missing block header\n");
|
|
|
|
static int
|
|
dwg_add_dat (Dwg_Data **dwgp, Bit_Chain *dat)
|
|
{
|
|
Dwg_Data *dwg = NULL;
|
|
Dwg_Object *mspace = NULL;
|
|
Dwg_Object_BLOCK_HEADER *hdr = NULL;
|
|
const char *end;
|
|
char *p;
|
|
Dwg_Version_Type version;
|
|
int error;
|
|
int i = 0;
|
|
int initial = 1;
|
|
int imperial = 0;
|
|
BITCODE_BL orig_num = 0;
|
|
typedef struct
|
|
{
|
|
int type;
|
|
union
|
|
{
|
|
Dwg_Entity_ATTDEF *attdef;
|
|
Dwg_Entity_ATTRIB *attrib;
|
|
Dwg_Entity_LINE *line;
|
|
Dwg_Entity_RAY *ray;
|
|
Dwg_Entity_XLINE *xline;
|
|
Dwg_Entity_CIRCLE *circle;
|
|
Dwg_Entity_ARC *arc;
|
|
Dwg_Entity_POINT *point;
|
|
Dwg_Entity_VIEWPORT *viewport;
|
|
Dwg_Entity_TEXT *text;
|
|
Dwg_Entity_MTEXT *mtext;
|
|
Dwg_Entity_INSERT *insert;
|
|
Dwg_Entity_MINSERT *minsert;
|
|
Dwg_Entity_DIMENSION_LINEAR *dimlin;
|
|
Dwg_Entity_DIMENSION_ALIGNED *dimali;
|
|
Dwg_Entity_DIMENSION_DIAMETER *dimdia;
|
|
Dwg_Entity_DIMENSION_RADIUS *dimrad;
|
|
Dwg_Entity_DIMENSION_ORDINATE *dimord;
|
|
Dwg_Entity_DIMENSION_ANG2LN *dimang2ln;
|
|
Dwg_Entity_DIMENSION_ANG3PT *dimang3pt;
|
|
Dwg_Entity_BLOCK *block;
|
|
Dwg_Entity_ENDBLK *endblk;
|
|
Dwg_Entity__3DFACE *_3dface;
|
|
Dwg_Entity__3DSOLID *_3dsolid;
|
|
Dwg_Entity_SOLID *solid;
|
|
Dwg_Entity_TRACE *trace;
|
|
Dwg_Entity_SHAPE *shape;
|
|
Dwg_Entity_ELLIPSE *ellipse;
|
|
Dwg_Entity_SPLINE *spline;
|
|
Dwg_Entity_LEADER *leader;
|
|
Dwg_Entity_MULTILEADER *mleader;
|
|
Dwg_Entity_TOLERANCE *tolerance;
|
|
Dwg_Entity_POLYLINE_2D *polyline_2d;
|
|
Dwg_Entity_POLYLINE_3D *polyline_3d;
|
|
Dwg_Entity_POLYLINE_MESH *polyline_mesh;
|
|
Dwg_Entity_POLYLINE_PFACE *polyline_pface;
|
|
Dwg_Entity_LWPOLYLINE *lwpolyline;
|
|
Dwg_Entity_MLINE *mline;
|
|
Dwg_Object_DICTIONARY *dictionary;
|
|
Dwg_Object_XRECORD *xrecord;
|
|
Dwg_Object_MLINESTYLE *mlinestyle;
|
|
Dwg_Object_DIMSTYLE *dimstyle;
|
|
Dwg_Object_UCS *ucs;
|
|
Dwg_Object_LAYER *layer;
|
|
Dwg_Object_STYLE *style;
|
|
Dwg_Object_LTYPE *ltype;
|
|
Dwg_Object_VPORT *vport;
|
|
Dwg_Object_VIEW *view;
|
|
Dwg_Object_LAYOUT *layout;
|
|
Dwg_Object_GROUP *group;
|
|
} u;
|
|
} lastent_t;
|
|
lastent_t ent, insert, dict, mtext;
|
|
char text[120];
|
|
char prompt[120];
|
|
char tag[120];
|
|
char default_text[120];
|
|
const char *hdr_s = "mspace";
|
|
|
|
LOG_TRACE ("==========================================\n");
|
|
if (!dat->chain)
|
|
abort ();
|
|
dwg = *dwgp;
|
|
ent = (lastent_t){ .type = DWG_TYPE_UNUSED, .u.insert = NULL };
|
|
insert = (lastent_t){ .type = DWG_TYPE_UNUSED, .u.insert = NULL };
|
|
dict = (lastent_t){ .type = DWG_TYPE_UNUSED, .u.dictionary = NULL };
|
|
mtext = (lastent_t){ .type = DWG_TYPE_UNUSED, .u.mtext = NULL };
|
|
if (!dwg->header.version)
|
|
version = R_2000;
|
|
else
|
|
version = dwg->header.version;
|
|
memset (&ent, 0, sizeof (lastent_t));
|
|
p = (char *)dat->chain;
|
|
end = (char *)&dat->chain[dat->size - 1];
|
|
|
|
// read dat line by line and call the matching add API
|
|
while (p && p < end)
|
|
{
|
|
char s1[120];
|
|
dwg_point_2d p2 = { 0.0, 0.0 };
|
|
dwg_point_2d p3 = { 0.0, 0.0 };
|
|
dwg_point_2d p4 = { 0.0, 0.0 };
|
|
dwg_point_3d pt1 = { 0.0, 0.0, 0.0 };
|
|
dwg_point_3d pt2 = { 0.0, 0.0, 0.0 };
|
|
dwg_point_3d pt3 = { 0.0, 0.0, 0.0 };
|
|
dwg_point_3d pt4 = { 0.0, 0.0, 0.0 };
|
|
dwg_point_3d scale = { 0.0, 0.0, 0.0 };
|
|
double height = 0.0, rot = 0.0, len = 0.0, f1 = 0.0, f2 = 0.0;
|
|
int i1 = 0, i2 = 0, flags = 0;
|
|
unsigned u = 0U;
|
|
|
|
while (p < end && (*p == ' ' || *p == '\t'))
|
|
p++; // skip spaces
|
|
if (p == end)
|
|
break;
|
|
if (*p == '\n' || *p == '#')
|
|
{ // skip empty lines and comments
|
|
p = next_line (p, end);
|
|
continue;
|
|
}
|
|
|
|
if (memBEGINc (p, "readdwg"))
|
|
{
|
|
if (dwg)
|
|
{
|
|
LOG_ERROR ("readdwg seen, but DWG already exists");
|
|
exit (1);
|
|
}
|
|
if (1 == SSCANF_S (p, "readdwg " FMT_PATH, text SZ))
|
|
{
|
|
LOG_INFO ("readdwg %s\n", text)
|
|
if ((error = dwg_read_file (text, *dwgp)) > DWG_ERR_CRITICAL)
|
|
{
|
|
LOG_ERROR ("Invalid readdwg \"%s\" => error 0x%x", text,
|
|
error);
|
|
exit (1);
|
|
}
|
|
dwg = *dwgp;
|
|
p = next_line (p, end);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
LOG_ERROR ("readdwg syntax error");
|
|
exit (1);
|
|
}
|
|
}
|
|
else if (memBEGINc (p, "readdxf"))
|
|
{
|
|
if (dwg)
|
|
{
|
|
LOG_ERROR ("readdxf seen, but DWG already exists");
|
|
exit (1);
|
|
}
|
|
if (1 == SSCANF_S (p, "readdxf " FMT_PATH, text SZ))
|
|
{
|
|
LOG_INFO ("readdxf %s\n", text)
|
|
if ((error = dxf_read_file (text, *dwgp)) > DWG_ERR_CRITICAL)
|
|
{
|
|
LOG_ERROR ("Invalid readdxf \"%s\" => error 0x%x", text,
|
|
error);
|
|
exit (1);
|
|
}
|
|
dwg = *dwgp;
|
|
p = next_line (p, end);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
LOG_ERROR ("readdxf syntax error");
|
|
exit (1);
|
|
}
|
|
}
|
|
else if (memBEGINc (p, "readjson"))
|
|
{
|
|
if (dwg)
|
|
{
|
|
LOG_ERROR ("readjson seen, but DWG already exists");
|
|
exit (1);
|
|
}
|
|
if (1 == SSCANF_S (p, "readjson " FMT_PATH, text SZ))
|
|
{
|
|
Bit_Chain in_dat = EMPTY_CHAIN (0);
|
|
LOG_INFO ("readjson %s\n", text)
|
|
in_dat.fh = fopen (text, "rb");
|
|
if (in_dat.fh)
|
|
dat_read_file (&in_dat, in_dat.fh, text);
|
|
if (!in_dat.fh
|
|
|| (error = dwg_read_json (&in_dat, *dwgp))
|
|
> DWG_ERR_CRITICAL)
|
|
{
|
|
LOG_ERROR ("Invalid readjson \"%s\" => error 0x%x", text,
|
|
error);
|
|
exit (1);
|
|
}
|
|
fclose (in_dat.fh);
|
|
dwg = *dwgp;
|
|
p = next_line (p, end);
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
LOG_ERROR ("readjson syntax error");
|
|
exit (1);
|
|
}
|
|
}
|
|
else if (memBEGINc (p, "imperial"))
|
|
{
|
|
if (!initial)
|
|
{
|
|
LOG_ERROR ("`imperial' directive out of header section");
|
|
exit (1);
|
|
}
|
|
imperial = 1;
|
|
p = next_line (p, end);
|
|
continue;
|
|
}
|
|
else if (memBEGINc (p, "version"))
|
|
{
|
|
int i_ver;
|
|
double f_ver;
|
|
char s_ver[16];
|
|
|
|
if (!initial)
|
|
{
|
|
LOG_ERROR ("`version' directive out of header section");
|
|
exit (1);
|
|
}
|
|
|
|
i = SSCANF_S (p, "version %d", &i_ver);
|
|
if (i)
|
|
{
|
|
snprintf (s_ver, 16, "r%d", i_ver);
|
|
s_ver[15] = '\0';
|
|
version = dwg_version_as (s_ver);
|
|
p += strlen ("version ");
|
|
}
|
|
else if ((i = SSCANF_S (p, "version %lf", &f_ver)))
|
|
{
|
|
snprintf (s_ver, 16, "r%f", f_ver);
|
|
s_ver[15] = '\0';
|
|
version = dwg_version_as (s_ver);
|
|
}
|
|
if (!i || version >= R_AFTER)
|
|
{
|
|
fprintf (stderr, "Invalid version %.*s", 40, p);
|
|
exit (1);
|
|
}
|
|
p = next_line (p, end);
|
|
continue;
|
|
}
|
|
|
|
if (initial)
|
|
{
|
|
if (!dwg)
|
|
dwg = dwg_new_Document (version, imperial, 0);
|
|
else
|
|
dwg_add_Document (dwg, imperial);
|
|
*dwgp = dwg;
|
|
|
|
mspace = dwg_model_space_object (dwg);
|
|
hdr = mspace ? mspace->tio.object->tio.BLOCK_HEADER : NULL;
|
|
orig_num = dwg->num_objects;
|
|
initial = 0;
|
|
LOG_TRACE ("==========================================\n");
|
|
}
|
|
|
|
// set entity/object field values.
|
|
#define SET_ENT(var, name) \
|
|
if (4 \
|
|
== SSCANF_S (p, #var "." FMT_NAME " = %d.%d.%X\n", s1 SZ, &i1, &i2, \
|
|
&u)) \
|
|
{ \
|
|
BITCODE_H hdl; \
|
|
if (!ent.u.var || ent.type != DWG_TYPE_##name) \
|
|
{ \
|
|
log_p (DWG_LOGLEVEL_ERROR, p); \
|
|
LOG_ERROR ("wrong last entity type 0x%x, needing " #var "\n", \
|
|
ent.type); \
|
|
exit (1); \
|
|
} \
|
|
hdl = dwg_add_handleref (dwg, i1, u, NULL); \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, hdl, 0); \
|
|
LOG_TRACE (#var ".%s = %d.%d.%X\n", s1, i1, i2, u); \
|
|
} \
|
|
else if (2 == SSCANF_S (p, #var "." FMT_NAME " = %lf\n", s1 SZ, &f1)) \
|
|
{ \
|
|
if (!ent.u.var || ent.type != DWG_TYPE_##name) \
|
|
{ \
|
|
log_p (DWG_LOGLEVEL_ERROR, p); \
|
|
LOG_ERROR ("wrong last entity type 0x%x, needing " #var, ent.type); \
|
|
exit (1); \
|
|
} \
|
|
if (2 == SSCANF_S (p, #var "." FMT_NAME " = %d\n", s1 SZ, &i1) \
|
|
&& i1 == f1) \
|
|
{ \
|
|
const Dwg_DYNAPI_field *f = dwg_dynapi_entity_field (#name, s1); \
|
|
if (!f || f->is_string) \
|
|
{ \
|
|
log_p (DWG_LOGLEVEL_ERROR, p); \
|
|
LOG_ERROR ("Invalid entity field %s.%s", #name, s1); \
|
|
exit (1); \
|
|
} \
|
|
else if (dwg_dynapi_is_float (f)) \
|
|
{ \
|
|
if (f->dxf >= 50 && f->dxf < 60) /* is_angle */ \
|
|
f1 = deg2rad (i1); \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &f1, 0); \
|
|
LOG_TRACE (#var ".%s = %f\n", s1, f1); \
|
|
} \
|
|
else if (sizeof (i1) == f->size) \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &i1, 0); \
|
|
else \
|
|
{ \
|
|
switch (sizeof (i1)) \
|
|
{ \
|
|
case 1: \
|
|
{ \
|
|
BITCODE_RC b = (unsigned)i1 & 0xFF; \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &b, \
|
|
0); \
|
|
break; \
|
|
} \
|
|
case 2: \
|
|
{ \
|
|
BITCODE_RS s = (unsigned)i1 & 0xFFFF; \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &s, \
|
|
0); \
|
|
break; \
|
|
} \
|
|
case 4: \
|
|
{ \
|
|
BITCODE_RL l = (BITCODE_RL)i1 & 0xFFFFFFFF; \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &l, \
|
|
0); \
|
|
break; \
|
|
} \
|
|
case 8: \
|
|
{ \
|
|
BITCODE_RLL rll = (BITCODE_RLL)i1; \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &rll, \
|
|
0); \
|
|
break; \
|
|
} \
|
|
default: \
|
|
{ \
|
|
LOG_ERROR ("Invalid entity field %s.%s size %u", #name, \
|
|
s1, f->size); \
|
|
exit (1); \
|
|
} \
|
|
} \
|
|
} \
|
|
LOG_TRACE (#var ".%s = %d\n", s1, i1); \
|
|
} \
|
|
else \
|
|
{ \
|
|
if (dwg_dynapi_is_angle (#name, s1)) \
|
|
f1 = deg2rad (f1); \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &f1, 0); \
|
|
LOG_TRACE (#var ".%s = %f\n", s1, f1); \
|
|
} \
|
|
} \
|
|
else if (2 == SSCANF_S (p, #var "." FMT_NAME " = %d\n", s1 SZ, &i1)) \
|
|
{ \
|
|
if (!ent.u.var || ent.type != DWG_TYPE_##name) \
|
|
{ \
|
|
log_p (DWG_LOGLEVEL_ERROR, p); \
|
|
LOG_ERROR ("wrong last entity type 0x%x, needing " #var "\n", \
|
|
ent.type); \
|
|
exit (1); \
|
|
} \
|
|
if (dwg_dynapi_is_angle (#name, s1)) \
|
|
i1 = deg2rad (i1); \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &i1, 0); \
|
|
LOG_TRACE (#var ".%s = %d\n", s1, i1); \
|
|
} \
|
|
else if (2 \
|
|
== SSCANF_S (p, #var "." FMT_NAME " = " FMT_ANY "\n", s1 SZ, \
|
|
text SZ)) \
|
|
{ \
|
|
char *str; \
|
|
if (strlen (text) && text[strlen (text) - 1] == '"') \
|
|
text[strlen (text) - 1] = '\0'; \
|
|
if (!ent.u.var || ent.type != DWG_TYPE_##name) \
|
|
{ \
|
|
log_p (DWG_LOGLEVEL_ERROR, p); \
|
|
LOG_ERROR ("wrong last entity type 0x%x, needing " #var "\n", \
|
|
ent.type); \
|
|
exit (1); \
|
|
} \
|
|
str = strdup (text); \
|
|
dwg_dynapi_entity_set_value (ent.u.var, #name, s1, &str, 1); \
|
|
free (str); \
|
|
LOG_TRACE (#var ".%s = \"%s\"\n", s1, text); \
|
|
}
|
|
|
|
if (memBEGINc (p, "pspace\n"))
|
|
{
|
|
Dwg_Object *pspace = dwg_paper_space_object (dwg);
|
|
if (pspace)
|
|
{
|
|
hdr = pspace->tio.object->tio.BLOCK_HEADER;
|
|
hdr_s = "pspace";
|
|
LOG_TRACE ("pspace\n");
|
|
}
|
|
else
|
|
fn_error ("Empty pspace object\n");
|
|
}
|
|
else if (memBEGINc (p, "mspace\n"))
|
|
{
|
|
if (mspace)
|
|
{
|
|
// gcc -O2 ubsan bug
|
|
GCC80_DIAG_IGNORE (-Wmaybe-uninitialized)
|
|
hdr = mspace->tio.object->tio.BLOCK_HEADER;
|
|
GCC80_DIAG_RESTORE
|
|
hdr_s = "mspace";
|
|
LOG_TRACE ("mspace\n");
|
|
}
|
|
else
|
|
fn_error ("Empty mspace object\n");
|
|
}
|
|
else if (8
|
|
== SSCANF_S (p,
|
|
"attdef %lf %d " FMT_ANY " (%lf %lf %lf) " FMT_TAG
|
|
" " FMT_ANY,
|
|
&height, &flags, prompt SZ, &pt1.x, &pt1.y, &pt1.z,
|
|
tag SZ, default_text SZ))
|
|
{
|
|
if (version < R_2_0b)
|
|
fn_error ("Invalid entity ATTDEF <r2.0b\n");
|
|
LOG_TRACE ("add_ATTDEF %s %f %d \"%s\" (%f %f %f) %s \"%s\"\n",
|
|
hdr_s, height, flags, prompt, pt1.x, pt1.y, pt1.z, tag,
|
|
default_text);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
GCC80_DIAG_IGNORE (-Wmaybe-uninitialized)
|
|
ent = (lastent_t){ .u.attdef
|
|
= dwg_add_ATTDEF (hdr, height, flags, prompt,
|
|
&pt1, tag, default_text),
|
|
.type = DWG_TYPE_ATTDEF };
|
|
GCC80_DIAG_RESTORE
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (attdef, ATTDEF)
|
|
// clang-format on
|
|
else if (7
|
|
== SSCANF_S (
|
|
p, "attrib %lf %d (%lf %lf %lf) " FMT_TAG " " FMT_ANY,
|
|
&height, &flags, &pt1.x, &pt1.y, &pt1.z, tag SZ, text SZ))
|
|
{
|
|
if (version < R_2_0b)
|
|
fn_error ("Invalid entity ATTRIB <r2.0b\n");
|
|
if (insert.type == DWG_TYPE_UNUSED)
|
|
{
|
|
log_p (DWG_LOGLEVEL_ERROR, p);
|
|
fn_error ("Missing INSERT for ATTRIB\n");
|
|
}
|
|
LOG_TRACE ("add_ATTRIB insert %f %d (%f %f %f) %s \"%s\"\n", height,
|
|
flags, pt1.x, pt1.y, pt1.z, tag, text);
|
|
ent = (lastent_t){ .u.attrib = dwg_add_ATTRIB (insert.u.insert, height,
|
|
flags, &pt1, tag, text),
|
|
.type = DWG_TYPE_ATTRIB };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (attrib, ATTRIB)
|
|
// clang-format on
|
|
else if (6
|
|
== SSCANF_S (p, "line (%lf %lf %lf) (%lf %lf %lf)", &pt1.x,
|
|
&pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z))
|
|
{
|
|
LOG_TRACE ("add_LINE %s (%f %f %f) (%f %f %f)\n", hdr_s, pt1.x, pt1.y,
|
|
pt1.z, pt2.x, pt2.y, pt2.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.line = dwg_add_LINE (hdr, &pt1, &pt2),
|
|
.type = DWG_TYPE_LINE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (line, LINE)
|
|
// clang-format on
|
|
else if (6
|
|
== SSCANF_S (p, "ray (%lf %lf %lf) (%lf %lf %lf)", &pt1.x,
|
|
&pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity RAY <r13\n");
|
|
LOG_TRACE ("add_RAY %s (%f %f %f) (%f %f %f)\n", hdr_s, pt1.x, pt1.y,
|
|
pt1.z, pt2.x, pt2.y, pt2.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.ray = dwg_add_RAY (hdr, &pt1, &pt2),
|
|
.type = DWG_TYPE_RAY };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (ray, RAY)
|
|
// clang-format on
|
|
else if (6
|
|
== SSCANF_S (p, "xline (%lf %lf %lf) (%lf %lf %lf)", &pt1.x,
|
|
&pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity XLINE\n");
|
|
LOG_TRACE ("add_XLINE %s (%f %f %f) (%f %f %f)\n", hdr_s, pt1.x, pt1.y,
|
|
pt1.z, pt2.x, pt2.y, pt2.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.xline = dwg_add_XLINE (hdr, &pt1, &pt2),
|
|
.type = DWG_TYPE_XLINE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (xline, XLINE)
|
|
// clang-format on
|
|
else if ((i = SSCANF_S (p, "text " FMT_ANY " (%lf %lf %lf) %lf\n", text,
|
|
&pt1.x, &pt1.y, &pt1.z, &height))
|
|
>= 5)
|
|
{
|
|
if (strlen (text) && text[strlen (text) - 1] == '"')
|
|
text[strlen (text) - 1] = '\0'; // strip the \"
|
|
LOG_TRACE ("add_TEXT %s %s (%f %f %f) %f\n", hdr_s, text, pt1.x, pt1.y,
|
|
pt1.z, height);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
GCC80_DIAG_IGNORE (-Wmaybe-uninitialized)
|
|
ent = (lastent_t){ .u.text = dwg_add_TEXT (hdr, text, &pt1, height),
|
|
.type = DWG_TYPE_TEXT };
|
|
GCC80_DIAG_RESTORE
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (text, TEXT)
|
|
// clang-format on
|
|
else if (5
|
|
== SSCANF_S (p, "mtext (%lf %lf %lf) %lf " FMT_ANY, &pt1.x,
|
|
&pt1.y, &pt1.z, &height, text SZ))
|
|
{
|
|
if (strlen (text) && text[strlen (text) - 1] == '"')
|
|
text[strlen (text) - 1] = '\0'; // strip the \"
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity MTEXT\n");
|
|
LOG_TRACE ("add_MTEXT %s (%f %f %f) %f \"%s\"\n", hdr_s, pt1.x, pt1.y,
|
|
pt1.z, height, text);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
mtext = ent
|
|
= (lastent_t){ .u.mtext = dwg_add_MTEXT (hdr, &pt1, height, text),
|
|
.type = DWG_TYPE_MTEXT };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (mtext, MTEXT)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "block " FMT_TBL, text SZ))
|
|
{
|
|
if (strlen (text) && text[strlen (text) - 1] == '"')
|
|
text[strlen (text) - 1] = '\0'; // strip the \"
|
|
CHK_MISSING_BLOCK_HEADER
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid BLOCK name\n");
|
|
else
|
|
{
|
|
dwg_add_BLOCK_HEADER (dwg, text);
|
|
ent = (lastent_t){ .u.block = dwg_add_BLOCK (hdr, text),
|
|
.type = DWG_TYPE_BLOCK };
|
|
}
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (block, BLOCK)
|
|
// clang-format on
|
|
else if (memBEGINc (p, "endblk\n"))
|
|
{
|
|
LOG_TRACE ("add_ENDBLK\n");
|
|
dwg_add_ENDBLK (hdr);
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (endblk, ENDBLK)
|
|
// clang-format on
|
|
else if (8
|
|
== SSCANF_S (p,
|
|
"insert (%lf %lf %lf) " FMT_TBL " %lf %lf %lf %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, text SZ, &scale.x,
|
|
&scale.y, &scale.z, &rot))
|
|
{
|
|
LOG_TRACE ("add_INSERT %s (%f %f %f) \"%s\" %f %f %f %f\n", hdr_s,
|
|
pt1.x, pt1.y, pt1.z, text, scale.x, scale.y, scale.z,
|
|
deg2rad (rot));
|
|
CHK_MISSING_BLOCK_HEADER
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid BLOCK name\n");
|
|
else
|
|
insert = ent = (lastent_t){ .u.insert = dwg_add_INSERT (
|
|
hdr, &pt1, text, scale.x, scale.y,
|
|
scale.z, deg2rad (rot)),
|
|
.type = DWG_TYPE_INSERT };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (insert, INSERT)
|
|
// clang-format on
|
|
else if (12
|
|
== SSCANF_S (p,
|
|
"minsert (%lf %lf %lf) " FMT_TBL
|
|
" %lf %lf %lf %lf %d %d "
|
|
"%lf %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, text SZ, &scale.x,
|
|
&scale.y, &scale.z, &rot, &i1, &i2, &f1, &f2))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity MINSERT\n");
|
|
LOG_TRACE (
|
|
"add_MINSERT %s (%f %f %f) \"%s\" %f %f %f %f %d %d %f %f\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, text, scale.x, scale.y, scale.z,
|
|
deg2rad (rot), i1, i2, f1, f2);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid block name\n");
|
|
insert = ent
|
|
= (lastent_t){ .u.minsert = dwg_add_MINSERT (
|
|
hdr, &pt1, text, scale.x, scale.y, scale.z,
|
|
deg2rad (rot), i1, i2, f1, f2),
|
|
.type = DWG_TYPE_MINSERT };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (minsert, MINSERT)
|
|
// clang-format on
|
|
else if (3
|
|
== SSCANF_S (p, "point (%lf %lf %lf)", &pt1.x, &pt1.y, &pt1.z))
|
|
{
|
|
LOG_TRACE ("add_POINT %s (%f %f %f)\n", hdr_s, pt1.x, pt1.y, pt1.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.point = dwg_add_POINT (hdr, &pt1),
|
|
.type = DWG_TYPE_POINT };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (point, POINT)
|
|
// clang-format on
|
|
else if (4
|
|
== SSCANF_S (p, "circle (%lf %lf %lf) %lf", &pt1.x, &pt1.y,
|
|
&pt1.z, &f1))
|
|
{
|
|
LOG_TRACE ("add_CIRCLE %s (%f %f %f) %f\n", hdr_s, pt1.x, pt1.y, pt1.z,
|
|
f1);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.circle = dwg_add_CIRCLE (hdr, &pt1, f1),
|
|
.type = DWG_TYPE_CIRCLE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (circle, CIRCLE)
|
|
// clang-format on
|
|
else if (6
|
|
== SSCANF_S (p, "arc (%lf %lf %lf) %lf %lf %lf", &pt1.x, &pt1.y,
|
|
&pt1.z, &len, &f1, &f2))
|
|
{
|
|
LOG_TRACE ("add_ARC %s (%f %f %f) %f %f %f\n", hdr_s, pt1.x, pt1.y,
|
|
pt1.z, len, deg2rad (f1), deg2rad (f2));
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.arc = dwg_add_ARC (hdr, &pt1, len, deg2rad (f1),
|
|
deg2rad (f2)),
|
|
.type = DWG_TYPE_ARC };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (arc, ARC)
|
|
// clang-format on
|
|
else if (9
|
|
== SSCANF_S (
|
|
p,
|
|
"dimension_aligned (%lf %lf %lf) (%lf %lf %lf) (%lf "
|
|
"%lf %lf)",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
|
|
&pt3.y, &pt3.z))
|
|
{
|
|
LOG_TRACE (
|
|
"add_DIMENSION_ALIGNED %s (%f %f %f) (%f %f %f) (%f %f %f)\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x, pt3.y,
|
|
pt3.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.dimali
|
|
= dwg_add_DIMENSION_ALIGNED (hdr, &pt1, &pt2, &pt3),
|
|
.type = DWG_TYPE_DIMENSION_ALIGNED };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dimali, DIMENSION_ALIGNED)
|
|
// clang-format on
|
|
else if (10
|
|
== SSCANF_S (
|
|
p,
|
|
"dimension_linear (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
|
|
"%lf) %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
|
|
&pt3.y, &pt3.z, &rot))
|
|
{
|
|
LOG_TRACE (
|
|
"add_DIMENSION_LINEAR %s (%f %f %f) (%f %f %f) (%f %f %f) %f\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x, pt3.y,
|
|
pt3.z, deg2rad (rot));
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.dimlin = dwg_add_DIMENSION_LINEAR (
|
|
hdr, &pt1, &pt2, &pt3, deg2rad (rot)),
|
|
.type = DWG_TYPE_DIMENSION_LINEAR };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dimlin, DIMENSION_LINEAR)
|
|
// clang-format on
|
|
else if (12
|
|
== SSCANF_S (
|
|
p,
|
|
"dimension_ang2ln (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
|
|
"%lf) (%lf %lf %lf)",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
|
|
&pt3.y, &pt3.z, &pt4.x, &pt4.y, &pt4.z))
|
|
{
|
|
LOG_TRACE ("add_DIMENSION_ANG2LN %s (%f %f %f) (%f %f %f) (%f %f %f) "
|
|
"(%f %f %f)\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x,
|
|
pt3.y, pt3.z, pt4.x, pt4.y, pt4.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.dimang2ln = dwg_add_DIMENSION_ANG2LN (
|
|
hdr, &pt1, &pt2, &pt3, &pt4),
|
|
.type = DWG_TYPE_DIMENSION_ANG2LN };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dimang2ln, DIMENSION_ANG2LN)
|
|
// clang-format on
|
|
else if (12
|
|
== SSCANF_S (
|
|
p,
|
|
"dimension_ang3pt (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
|
|
"%lf) (%lf %lf %lf)",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
|
|
&pt3.y, &pt3.z, &pt4.x, &pt4.y, &pt4.z))
|
|
{
|
|
LOG_TRACE ("add_DIMENSION_ANG3PT %s (%f %f %f) (%f %f %f) (%f %f %f) "
|
|
"(%f %f %f)\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x,
|
|
pt3.y, pt3.z, pt4.x, pt4.y, pt4.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.dimang3pt = dwg_add_DIMENSION_ANG3PT (
|
|
hdr, &pt1, &pt2, &pt3, &pt4),
|
|
.type = DWG_TYPE_DIMENSION_ANG3PT };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dimang3pt, DIMENSION_ANG3PT)
|
|
// clang-format on
|
|
else if (7
|
|
== SSCANF_S (
|
|
p, "dimension_diameter (%lf %lf %lf) (%lf %lf %lf) %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &len))
|
|
{
|
|
LOG_TRACE ("add_DIMENSION_DIAMETER %s (%f %f %f) (%f %f %f) %f\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, len);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.dimdia
|
|
= dwg_add_DIMENSION_DIAMETER (hdr, &pt1, &pt2, len),
|
|
.type = DWG_TYPE_DIMENSION_DIAMETER };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dimdia, DIMENSION_DIAMETER)
|
|
// clang-format on
|
|
else if (7
|
|
== SSCANF_S (
|
|
p, "dimension_ordinate (%lf %lf %lf) (%lf %lf %lf) %d",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &i1))
|
|
{
|
|
LOG_TRACE ("add_DIMENSION_ORDINATE %s (%f %f %f) (%f %f %f) %s\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z,
|
|
i1 ? "true" : "false");
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.dimord = dwg_add_DIMENSION_ORDINATE (
|
|
hdr, &pt1, &pt2, i1 ? true : false),
|
|
.type = DWG_TYPE_DIMENSION_ORDINATE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dimord, DIMENSION_ORDINATE)
|
|
// clang-format on
|
|
else if (7
|
|
== SSCANF_S (
|
|
p, "dimension_radius (%lf %lf %lf) (%lf %lf %lf) %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &len))
|
|
{
|
|
LOG_TRACE ("add_DIMENSION_RADIUS %s (%f %f %f) (%f %f %f) %f\n", hdr_s,
|
|
pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, len);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.dimrad
|
|
= dwg_add_DIMENSION_RADIUS (hdr, &pt1, &pt2, len),
|
|
.type = DWG_TYPE_DIMENSION_RADIUS };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dimrad, DIMENSION_RADIUS)
|
|
// clang-format on
|
|
else if (12
|
|
== SSCANF_S (p,
|
|
"3dface (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
|
|
"%lf) (%lf %lf %lf)",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
|
|
&pt3.x, &pt3.y, &pt3.z, &pt4.x, &pt4.y, &pt4.z))
|
|
{
|
|
LOG_TRACE (
|
|
"add_3DFACE %s (%f %f %f) (%f %f %f) (%f %f %f) (%f %f %f)\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x, pt3.y,
|
|
pt3.z, pt4.x, pt4.y, pt4.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dface
|
|
= dwg_add_3DFACE (hdr, &pt1, &pt2, &pt3, &pt4),
|
|
.type = DWG_TYPE__3DFACE };
|
|
}
|
|
else if (9
|
|
== SSCANF_S (p,
|
|
"3dface (%lf %lf %lf) (%lf %lf %lf) (%lf %lf "
|
|
"%lf)",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
|
|
&pt3.x, &pt3.y, &pt3.z))
|
|
{
|
|
LOG_TRACE ("add_3DFACE %s (%f %f %f) (%f %f %f) (%f %f %f) NULL\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x,
|
|
pt3.y, pt3.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dface
|
|
= dwg_add_3DFACE (hdr, &pt1, &pt2, &pt3, NULL),
|
|
.type = DWG_TYPE__3DFACE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (_3dface, _3DFACE)
|
|
// clang-format on
|
|
else if (9
|
|
== SSCANF_S (
|
|
p, "solid (%lf %lf %lf) (%lf %lf) (%lf %lf) (%lf %lf)",
|
|
&pt1.x, &pt1.y, &pt1.z, &p2.x, &p2.y, &p3.x, &p3.y, &p4.x,
|
|
&p4.y))
|
|
{
|
|
LOG_TRACE (
|
|
"add_SOLID %s (%f %f %f) (%f %f %f) (%f %f %f) (%f %f %f)\n",
|
|
hdr_s, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x, pt3.y,
|
|
pt3.z, pt4.x, pt4.y, pt4.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.solid = dwg_add_SOLID (hdr, &pt1, &p2, &p3, &p4),
|
|
.type = DWG_TYPE_SOLID };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (solid, SOLID)
|
|
// clang-format on
|
|
else if (9
|
|
== SSCANF_S (
|
|
p, "trace (%lf %lf %lf) (%lf %lf) (%lf %lf) (%lf %lf)",
|
|
&pt1.x, &pt1.y, &pt1.z, &p2.x, &p2.y, &p3.x, &p3.y, &p4.x,
|
|
&p4.y))
|
|
{
|
|
LOG_TRACE ("add_TRACE %s (%f %f %f) (%f %f) (%f %f) (%f %f)\n", hdr_s,
|
|
pt1.x, pt1.y, pt1.z, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.trace = dwg_add_TRACE (hdr, &pt1, &p2, &p3, &p4),
|
|
.type = DWG_TYPE_TRACE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (trace, TRACE)
|
|
// clang-format on
|
|
else if (3
|
|
== SSCANF_S (p, "polyline_2d %d ((%lf %lf)", &i1, &pt1.x,
|
|
&pt1.y))
|
|
{
|
|
dwg_point_2d *pts = scan_pts2d (i1, &p);
|
|
if (i1 && pts)
|
|
{
|
|
LOG_TRACE ("add_POLYLINE_2D %s %d ((%f %f)", hdr_s, i1, pt1.x,
|
|
pt1.y);
|
|
for (i = 1; i < i1; i++)
|
|
{
|
|
LOG_TRACE (" (%f %f)", pts[i].x, pts[i].y);
|
|
}
|
|
LOG_TRACE (")\n");
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.polyline_2d
|
|
= dwg_add_POLYLINE_2D (hdr, i1, pts),
|
|
.type = DWG_TYPE_POLYLINE_2D };
|
|
free (pts);
|
|
}
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (polyline_2d, POLYLINE_2D)
|
|
// clang-format on
|
|
else if (4
|
|
== SSCANF_S (p, "polyline_3d %d ((%lf %lf %lf)", &i1, &pt1.x,
|
|
&pt1.y, &pt1.z))
|
|
{
|
|
dwg_point_3d *pts = scan_pts3d (i1, &p);
|
|
if (i1 && pts)
|
|
{
|
|
LOG_TRACE ("add_POLYLINE_3D %s %d ((%f %f %f)", hdr_s, i1, pt1.x,
|
|
pt1.y, pt1.z);
|
|
for (i = 1; i < i1; i++)
|
|
{
|
|
LOG_TRACE (" (%f %f %f)", pts[i].x, pts[i].y, pts[i].z);
|
|
}
|
|
LOG_TRACE (")\n");
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.polyline_3d
|
|
= dwg_add_POLYLINE_3D (hdr, i1, pts),
|
|
.type = DWG_TYPE_POLYLINE_3D };
|
|
free (pts);
|
|
}
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (polyline_3d, POLYLINE_3D)
|
|
// clang-format on
|
|
else if (5
|
|
== SSCANF_S (p, "polyline_mesh %d %d ((%lf %lf %lf)", &i1, &i2,
|
|
&pt1.x, &pt1.y, &pt1.z))
|
|
{
|
|
dwg_point_3d *pts = scan_pts3d (i1 * i2, &p);
|
|
if (i1 && i2 && pts)
|
|
{
|
|
LOG_TRACE ("add_POLYLINE_MESH %s %d %d ((%f %f %f)", hdr_s, i1, i2,
|
|
pt1.x, pt1.y, pt1.z);
|
|
for (i = 1; i < i1; i++)
|
|
{
|
|
LOG_TRACE (" (%f %f %f)", pts[i].x, pts[i].y, pts[i].z);
|
|
}
|
|
LOG_TRACE (")\n");
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.polyline_mesh
|
|
= dwg_add_POLYLINE_MESH (hdr, i1, i2, pts),
|
|
.type = DWG_TYPE_POLYLINE_MESH };
|
|
free (pts);
|
|
}
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (polyline_mesh, POLYLINE_MESH)
|
|
// clang-format on
|
|
else if (5
|
|
== SSCANF_S (p, "polyline_pface %d %d ((%lf %lf %lf)", &i1, &i2,
|
|
&pt1.x, &pt1.y, &pt1.z))
|
|
{
|
|
int face[4];
|
|
dwg_face *faces = NULL;
|
|
dwg_point_3d *verts = scan_pts3d (i1, &p);
|
|
if (4
|
|
== SSCANF_S (p, "((%d %d %d %d)", &face[0], &face[1], &face[2],
|
|
&face[3]))
|
|
faces = scan_faces (i2, &p);
|
|
else if (3
|
|
== SSCANF_S (p, "((%d %d %d)", &face[0], &face[1], &face[2]))
|
|
faces = scan_faces (i2, &p);
|
|
else if (i2) // else no faces
|
|
{
|
|
log_p (DWG_LOGLEVEL_ERROR, p);
|
|
LOG_ERROR ("reading faces");
|
|
}
|
|
if (i1 && i2 && verts && faces)
|
|
{
|
|
LOG_TRACE ("add_POLYLINE_PFACE %s %d %d ((%f %f %f)", hdr_s, i1,
|
|
i2, pt1.x, pt1.y, pt1.z);
|
|
for (i = 1; i < i1; i++)
|
|
{
|
|
LOG_TRACE (" (%f %f %f)", verts[i].x, verts[i].y, verts[i].z);
|
|
}
|
|
LOG_TRACE (") (");
|
|
for (i = 0; i < i2; i++)
|
|
{
|
|
if (faces[i][3])
|
|
{
|
|
LOG_TRACE (" (%d %d %d %d)", faces[i][0], faces[i][1],
|
|
faces[i][2], faces[i][3]);
|
|
}
|
|
else
|
|
{
|
|
LOG_TRACE (" (%d %d %d)", faces[i][0], faces[i][1],
|
|
faces[i][2]);
|
|
}
|
|
}
|
|
LOG_TRACE (")\n");
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.polyline_pface = dwg_add_POLYLINE_PFACE (
|
|
hdr, i1, i2, verts, faces),
|
|
.type = DWG_TYPE_POLYLINE_PFACE };
|
|
free (verts);
|
|
free (faces);
|
|
}
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (polyline_pface, POLYLINE_PFACE)
|
|
// clang-format on
|
|
else if (3
|
|
== SSCANF_S (p, "lwpolyline %d ((%lf %lf)", &i1, &pt1.x,
|
|
&pt1.y))
|
|
{
|
|
dwg_point_2d *pts = scan_pts2d (i1, &p);
|
|
if (i1 && pts)
|
|
{
|
|
LOG_TRACE ("add_LWPOLYLINE %s %d ((%f %f)", hdr_s, i1, pt1.x,
|
|
pt1.y);
|
|
for (i = 1; i < i1; i++)
|
|
{
|
|
LOG_TRACE (" (%f %f)", pts[i].x, pts[i].y);
|
|
}
|
|
LOG_TRACE (")\n");
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.lwpolyline
|
|
= dwg_add_LWPOLYLINE (hdr, i1, pts),
|
|
.type = DWG_TYPE_LWPOLYLINE };
|
|
free (pts);
|
|
}
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (lwpolyline, LWPOLYLINE)
|
|
// clang-format on
|
|
else if (4
|
|
== SSCANF_S (p, "mline %d ((%lf %lf %lf)", &i1, &pt1.x, &pt1.y,
|
|
&pt1.z))
|
|
{
|
|
dwg_point_3d *pts = scan_pts3d (i1, &p);
|
|
if (i1 && pts)
|
|
{
|
|
LOG_TRACE ("add_MLINE %s %d ((%f %f %f)", hdr_s, i1, pt1.x, pt1.y,
|
|
pt1.z);
|
|
for (i = 1; i < i1; i++)
|
|
{
|
|
LOG_TRACE (" (%f %f %f)", pts[i].x, pts[i].y, pts[i].z);
|
|
}
|
|
LOG_TRACE (")\n");
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.mline = dwg_add_MLINE (hdr, i1, pts),
|
|
.type = DWG_TYPE_MLINE };
|
|
free (pts);
|
|
}
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (mline, MLINE)
|
|
// clang-format on
|
|
else if (3
|
|
== SSCANF_S (p, "dictionary " FMT_TBL " " FMT_TBL " %u",
|
|
text SZ, s1 SZ, &u))
|
|
{
|
|
LOG_TRACE ("add_DICTIONARY \"%s\" \"%s\" %u\n", text, s1, u);
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid dictionary name\n");
|
|
dict = ent = (lastent_t){ .u.dictionary = dwg_add_DICTIONARY (
|
|
dwg, text, s1, (unsigned long)u),
|
|
.type = DWG_TYPE_DICTIONARY };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dictionary, DICTIONARY)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "xrecord dictionary " FMT_TBL, text SZ))
|
|
{
|
|
if (dict.type != DWG_TYPE_DICTIONARY)
|
|
fn_error ("xrecord: missing dictionary\n");
|
|
LOG_TRACE ("add_XRECORD dictionary \"%s\"\n", text);
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid dictionary name\n");
|
|
ent = (lastent_t){ .u.xrecord
|
|
= dwg_add_XRECORD (dict.u.dictionary, text),
|
|
.type = DWG_TYPE_XRECORD };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (xrecord, XRECORD)
|
|
// clang-format on
|
|
else if (6
|
|
== SSCANF_S (p, "shape " FMT_PATH " (%lf %lf %lf) %lf %lf",
|
|
text SZ, &pt1.x, &pt1.y, &pt1.z, &scale.x, &rot))
|
|
{
|
|
LOG_TRACE ("add_SHAPE %s \"%s\" (%f %f %f) %f %f\n", hdr_s, text,
|
|
pt1.x, pt1.y, pt1.z, scale.x, deg2rad (rot));
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.shape = dwg_add_SHAPE (hdr, text, &pt1, scale.x,
|
|
deg2rad (rot)),
|
|
.type = DWG_TYPE_SHAPE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (shape, SHAPE)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "viewport " FMT_TBL, text SZ))
|
|
{
|
|
LOG_TRACE ("add_VIEWPORT %s \"%s\"\n", hdr_s, text);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid table record name\n");
|
|
ent = (lastent_t){ .u.viewport = dwg_add_VIEWPORT (hdr, text),
|
|
.type = DWG_TYPE_VIEWPORT };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (viewport, VIEWPORT)
|
|
// clang-format on
|
|
else if (5
|
|
== SSCANF_S (p, "ellipse (%lf %lf %lf) %lf %lf", &pt1.x, &pt1.y,
|
|
&pt1.z, &f1, &f2))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity ELLIPSE <r13\n");
|
|
LOG_TRACE ("add_ELLIPSE %s (%f %f %f) %f %f\n", hdr_s, pt1.x, pt1.y,
|
|
pt1.z, f1, f2);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.ellipse = dwg_add_ELLIPSE (hdr, &pt1, f1, f2),
|
|
.type = DWG_TYPE_ELLIPSE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (ellipse, ELLIPSE)
|
|
// clang-format on
|
|
else if (4
|
|
== SSCANF_S (p, "spline %d ((%lf %lf %lf)", &i1, &pt1.x, &pt1.y,
|
|
&pt1.z))
|
|
{
|
|
dwg_point_3d *fitpts;
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity SPLINE <r13\n");
|
|
fitpts = scan_pts3d (i1, &p);
|
|
if (i1 && fitpts
|
|
&& SSCANF_S (p, ") (%lf %lf %lf) (%lf %lf %lf)", &pt2.x, &pt2.y,
|
|
&pt2.z, &pt3.x, &pt3.y, &pt3.z))
|
|
{
|
|
LOG_TRACE ("add_SPLINE %s %d ((%f %f %f)", hdr_s, i1, pt1.x, pt1.y,
|
|
pt1.z);
|
|
for (i = 1; i < i1; i++)
|
|
{
|
|
LOG_TRACE (" (%f %f %f)", fitpts[i].x, fitpts[i].y,
|
|
fitpts[i].z);
|
|
}
|
|
LOG_TRACE (" (%f %f %f) (%f %f %f)\n", pt2.x, pt2.y, pt2.z, pt3.x,
|
|
pt3.y, pt3.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.spline
|
|
= dwg_add_SPLINE (hdr, i1, fitpts, &pt2, &pt3),
|
|
.type = DWG_TYPE_SPLINE };
|
|
}
|
|
free (fitpts);
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (spline, SPLINE)
|
|
// clang-format on
|
|
else if (ent.type == DWG_TYPE_MTEXT
|
|
&& SSCANF_S (p, "leader %d ((%lf %lf %lf)", &i1, &pt1.x, &pt1.y,
|
|
&pt1.z))
|
|
{
|
|
dwg_point_3d *pts;
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity LEADER <r13\n");
|
|
if (mtext.type != DWG_TYPE_MTEXT)
|
|
fn_error ("LEADER: Missing mtext\n");
|
|
pts = scan_pts3d (i1, &p);
|
|
if (i1 && pts && SSCANF_S (p, ") mtext %d", &i2))
|
|
{
|
|
LOG_TRACE ("add_LEADER %s %d ((%f %f %f)", hdr_s, i1, pt1.x, pt1.y,
|
|
pt1.z);
|
|
for (i = 1; i < i1; i++)
|
|
{
|
|
LOG_TRACE (" (%f %f %f)", pts[i].x, pts[i].y, pts[i].z);
|
|
}
|
|
LOG_TRACE (" mtext %d\n", i2);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.leader = dwg_add_LEADER (hdr, i1, pts,
|
|
mtext.u.mtext, i2),
|
|
.type = DWG_TYPE_LEADER };
|
|
}
|
|
free (pts);
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (leader, LEADER)
|
|
// clang-format on
|
|
else if (7
|
|
== SSCANF_S (
|
|
p, "tolerance " FMT_TBL " (%lf %lf %lf) (%lf %lf %lf)",
|
|
text SZ, &pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity TOLERANCE <r13\n");
|
|
LOG_TRACE ("add_TOLERANCE %s \"%s\" (%f %f %f) (%f %f %f)\n", hdr_s,
|
|
text, pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u.tolerance
|
|
= dwg_add_TOLERANCE (hdr, text, &pt1, &pt2),
|
|
.type = DWG_TYPE_TOLERANCE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (tolerance, TOLERANCE)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "mlinestyle " FMT_TBL, text SZ))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity MLINESTYLE <r13\n");
|
|
LOG_TRACE ("add_MLINESTYLE \"%s\"\n", text);
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid style name\n");
|
|
ent = (lastent_t){ .u.mlinestyle = dwg_add_MLINESTYLE (dwg, text),
|
|
.type = DWG_TYPE_MLINESTYLE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (mlinestyle, MLINESTYLE)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "layer " FMT_TBL, text SZ))
|
|
{
|
|
LOG_TRACE ("add_LAYER \"%s\"\n", text);
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid table record name\n");
|
|
ent = (lastent_t){ .u.layer = dwg_add_LAYER (dwg, text),
|
|
.type = DWG_TYPE_LAYER };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (layer, LAYER)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "style " FMT_TBL, text SZ))
|
|
{
|
|
LOG_TRACE ("add_STYLE \"%s\"\n", text);
|
|
ent = (lastent_t){ .u.style = dwg_add_STYLE (dwg, text),
|
|
.type = DWG_TYPE_STYLE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (style, STYLE)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "ltype " FMT_TBL, text SZ))
|
|
{
|
|
LOG_TRACE ("add_LTYPE \"%s\"\n", text);
|
|
ent = (lastent_t){ .u.ltype = dwg_add_LTYPE (dwg, text),
|
|
.type = DWG_TYPE_LTYPE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (ltype, LTYPE)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "view " FMT_TBL, text SZ))
|
|
{
|
|
LOG_TRACE ("add_VIEW \"%s\"\n", text);
|
|
ent = (lastent_t){ .u.view = dwg_add_VIEW (dwg, text),
|
|
.type = DWG_TYPE_VIEW };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (view, VIEW)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "vport " FMT_TBL, text SZ))
|
|
{
|
|
LOG_TRACE ("add_VPORT \"%s\"\n", text);
|
|
ent = (lastent_t){ .u.vport = dwg_add_VPORT (dwg, text),
|
|
.type = DWG_TYPE_VPORT };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (vport, VPORT)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "dimstyle " FMT_TBL, text SZ))
|
|
{
|
|
if (version < R_11)
|
|
fn_error ("Invalid table DIMSTYLE <r11\n");
|
|
LOG_TRACE ("add_DIMSTYLE \"%s\"\n", text);
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid table record name\n");
|
|
ent = (lastent_t){ .u.dimstyle = dwg_add_DIMSTYLE (dwg, text),
|
|
.type = DWG_TYPE_DIMSTYLE };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (dimstyle, DIMSTYLE)
|
|
// clang-format on
|
|
else if (1 == SSCANF_S (p, "group " FMT_TBL, text SZ))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid object GROUP < r13\n");
|
|
LOG_TRACE ("add_GROUP \"%s\"\n", text);
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid group name\n");
|
|
ent = (lastent_t){ .u.group = dwg_add_GROUP (dwg, text),
|
|
.type = DWG_TYPE_GROUP };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (group, GROUP)
|
|
// clang-format on
|
|
else if (10
|
|
== SSCANF_S (
|
|
p, "ucs (%lf %lf %lf) (%lf %lf %lf) (%lf %lf %lf) " FMT_TBL,
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &pt3.x,
|
|
&pt3.y, &pt3.z, text SZ))
|
|
{
|
|
if (version < R_10)
|
|
fn_error ("Invalid table UCS <r10\n");
|
|
LOG_TRACE ("add_UCS (%f %f %f) (%f %f %f) (%f %f %f) \"%s\"\n", pt1.x,
|
|
pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, pt3.x, pt3.y, pt3.z,
|
|
text);
|
|
ent = (lastent_t){ .u.ucs = dwg_add_UCS (dwg, &pt1, &pt2, &pt3, text),
|
|
.type = DWG_TYPE_UCS };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (ucs, UCS)
|
|
// clang-format on
|
|
else if (2
|
|
== SSCANF_S (p, "layout viewport " FMT_TBL " " FMT_ANY, text SZ,
|
|
s1 SZ))
|
|
{
|
|
Dwg_Object *obj = dwg_ent_generic_to_object (ent.u.viewport, &error);
|
|
if (version <= R_11)
|
|
fn_error ("Invalid object LAYOUT <r13\n");
|
|
if (ent.type != DWG_TYPE_VIEWPORT)
|
|
fn_error ("layout viewport: last entity is not a viewport\n");
|
|
if (strlen (s1) && text[strlen (s1) - 1] == '"')
|
|
text[strlen (s1) - 1] = '\0'; // strip the \"
|
|
if (!dwg_is_valid_name (dwg, text))
|
|
fn_error ("Invalid table record name\n");
|
|
if (!error)
|
|
ent = (lastent_t){ .u.layout = dwg_add_LAYOUT (obj, text, s1),
|
|
.type = DWG_TYPE_LAYOUT };
|
|
}
|
|
else if (8
|
|
== SSCANF_S (p, "torus (%lf %lf %lf) (%lf %lf %lf) %lf %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
|
|
&f1, &f2))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity TORUS <r13\n");
|
|
LOG_TRACE ("add_TORUS %s (%f %f %f) (%f %f %f) %f %f\n", hdr_s, pt1.x,
|
|
pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, f1, f2);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dsolid
|
|
= dwg_add_TORUS (hdr, &pt1, &pt2, f1, f2),
|
|
.type = DWG_TYPE__3DSOLID };
|
|
}
|
|
else if (7
|
|
== SSCANF_S (p, "sphere (%lf %lf %lf) (%lf %lf %lf) %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
|
|
&f1))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity SPHERE <r13\n");
|
|
LOG_TRACE ("add_SPHERE %s (%f %f %f) (%f %f %f) %f\n", hdr_s, pt1.x,
|
|
pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, f1);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dsolid = dwg_add_SPHERE (hdr, &pt1, &pt2, f1),
|
|
.type = DWG_TYPE__3DSOLID };
|
|
}
|
|
else if (10
|
|
== SSCANF_S (
|
|
p, "cylinder (%lf %lf %lf) (%lf %lf %lf) %lf %lf %lf %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &height,
|
|
&f1, &f2, &len))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity CYLINDER <r13\n");
|
|
LOG_TRACE ("add_CYLINDER %s (%f %f %f) (%f %f %f) %f %f %f %f", hdr_s,
|
|
pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, height, f1, f2,
|
|
len);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dsolid = dwg_add_CYLINDER (
|
|
hdr, &pt1, &pt2, height, f1, f2, len),
|
|
.type = DWG_TYPE__3DSOLID };
|
|
}
|
|
else if (10
|
|
== SSCANF_S (p,
|
|
"cone (%lf %lf %lf) (%lf %lf %lf) %lf %lf %lf %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
|
|
&height, &f1, &f2, &len))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity CONE <r13\n");
|
|
LOG_TRACE ("add_CONE %s (%f %f %f) (%f %f %f) %f %f %f %f", hdr_s,
|
|
pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, height, f1, f2,
|
|
len);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dsolid = dwg_add_CONE (hdr, &pt1, &pt2, height,
|
|
f1, f2, len),
|
|
.type = DWG_TYPE__3DSOLID };
|
|
}
|
|
else if (9
|
|
== SSCANF_S (p, "wedge (%lf %lf %lf) (%lf %lf %lf) %lf %lf %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
|
|
&len, &f1, &height))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity WEDGE <r13\n");
|
|
LOG_TRACE ("add_WEDGE %s (%f %f %f) (%f %f %f) %f %f %f", hdr_s, pt1.x,
|
|
pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, len, f1, height);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dsolid
|
|
= dwg_add_WEDGE (hdr, &pt1, &pt2, len, f1, height),
|
|
.type = DWG_TYPE__3DSOLID };
|
|
}
|
|
else if (9
|
|
== SSCANF_S (p, "box (%lf %lf %lf) (%lf %lf %lf) %lf %lf %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z,
|
|
&len, &f1, &height))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity BOX <r13\n");
|
|
LOG_TRACE ("add_BOX %s (%f %f %f) (%f %f %f) %f %f %f", hdr_s, pt1.x,
|
|
pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, len, f1, height);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dsolid
|
|
= dwg_add_BOX (hdr, &pt1, &pt2, len, f1, height),
|
|
.type = DWG_TYPE__3DSOLID };
|
|
}
|
|
else if (10
|
|
== SSCANF_S (
|
|
p, "pyramid (%lf %lf %lf) (%lf %lf %lf) %lf %d %lf %lf",
|
|
&pt1.x, &pt1.y, &pt1.z, &pt2.x, &pt2.y, &pt2.z, &height,
|
|
&i1, &f1, &f2))
|
|
{
|
|
if (version <= R_11)
|
|
fn_error ("Invalid entity PYRAMID <r13\n");
|
|
LOG_TRACE ("add_PYRAMID %s (%f %f %f) (%f %f %f) %f %d %f %f", hdr_s,
|
|
pt1.x, pt1.y, pt1.z, pt2.x, pt2.y, pt2.z, height, i1, f1,
|
|
f2);
|
|
CHK_MISSING_BLOCK_HEADER
|
|
ent = (lastent_t){ .u._3dsolid = dwg_add_PYRAMID (hdr, &pt1, &pt2,
|
|
height, i1, f1, f2),
|
|
.type = DWG_TYPE__3DSOLID };
|
|
}
|
|
else
|
|
// clang-format off
|
|
SET_ENT (_3dsolid, _3DSOLID)
|
|
// clang-format on
|
|
else if (2 == SSCANF_S (p, "HEADER." FMT_NAME " = %lf\n", s1 SZ, &f1))
|
|
{
|
|
if (2 == SSCANF_S (p, "HEADER." FMT_NAME " = %d\n", s1 SZ, &i1)
|
|
&& i1 == f1)
|
|
{
|
|
const Dwg_DYNAPI_field *f = dwg_dynapi_header_field (s1);
|
|
if (!f || f->is_string)
|
|
{
|
|
log_p (DWG_LOGLEVEL_ERROR, p);
|
|
LOG_ERROR ("Invalid HEADER.%s", s1);
|
|
exit (1);
|
|
}
|
|
else if (dwg_dynapi_is_float (f))
|
|
{
|
|
if (f->dxf >= 50 && f->dxf < 60) /* is_angle */
|
|
f1 = deg2rad (i1);
|
|
dwg_dynapi_header_set_value (dwg, s1, &f1, 0);
|
|
LOG_TRACE ("HEADER.%s = %lf\n", s1, f1);
|
|
}
|
|
// is integer
|
|
else if (sizeof (i1) == f->size)
|
|
dwg_dynapi_header_set_value (dwg, s1, &i1, 0);
|
|
else
|
|
{
|
|
switch (sizeof (i1))
|
|
{
|
|
case 1:
|
|
{
|
|
BITCODE_RC rc = (unsigned)i1 & 0xFF;
|
|
dwg_dynapi_header_set_value (dwg, s1, &rc, 0);
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
BITCODE_RS rs = (unsigned)i1 & 0xFFFF;
|
|
dwg_dynapi_header_set_value (dwg, s1, &rs, 0);
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
BITCODE_RL rl = (BITCODE_RL)i1 & 0xFFFFFFFF;
|
|
dwg_dynapi_header_set_value (dwg, s1, &rl, 0);
|
|
break;
|
|
}
|
|
case 8:
|
|
{
|
|
BITCODE_RLL rll = (BITCODE_RLL)i1;
|
|
dwg_dynapi_header_set_value (dwg, s1, &rll, 0);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
LOG_ERROR ("Invalid header.%s size %u", s1, f->size);
|
|
exit (1);
|
|
}
|
|
}
|
|
LOG_TRACE ("HEADER.%s = %d\n", s1, i1);
|
|
}
|
|
}
|
|
else // float
|
|
{
|
|
dwg_dynapi_header_set_value (dwg, s1, &f1, 0);
|
|
LOG_TRACE ("HEADER.%s = %lf\n", s1, f1);
|
|
}
|
|
}
|
|
else if (2
|
|
== SSCANF_S (p, "HEADER." FMT_NAME " = " FMT_ANY "\n", s1 SZ,
|
|
text SZ))
|
|
{
|
|
char *str;
|
|
if (strlen (text) && text[strlen (text) - 1] == '"')
|
|
text[strlen (text) - 1] = '\0'; // strip the \"
|
|
str = strdup (text);
|
|
dwg_dynapi_header_set_value (dwg, s1, &str, 1);
|
|
free (str);
|
|
LOG_TRACE ("HEADER.%s = \"%s\"\n", s1, text);
|
|
}
|
|
else if (4
|
|
== SSCANF_S (p, "HEADER." FMT_NAME " = (%lf %lf %lf)", s1 SZ,
|
|
&pt1.x, &pt1.y, &pt1.z))
|
|
{
|
|
LOG_TRACE ("HEADER.%s = (%f %f %f)\n", s1, pt1.x, pt1.y, pt1.z);
|
|
dwg_dynapi_header_set_value (dwg, s1, &pt1, 0);
|
|
}
|
|
else if (3
|
|
== SSCANF_S (p, "HEADER." FMT_NAME " = (%lf %lf)", s1 SZ,
|
|
&pt1.x, &pt1.y))
|
|
{
|
|
pt1.z = 0.0;
|
|
LOG_TRACE ("HEADER.%s = (%f %f)\n", s1, pt1.x, pt1.y);
|
|
dwg_dynapi_header_set_value (dwg, s1, &pt1, 0);
|
|
}
|
|
else
|
|
{
|
|
char *n = strchr (p, '\n');
|
|
int size = n ? n - p : (int)strlen (p);
|
|
LOG_WARN ("Ignored %.*s", size, p)
|
|
}
|
|
|
|
p = next_line (p, end);
|
|
}
|
|
// if we added at least one object
|
|
return (dwg->num_objects - orig_num > 0 ? 0 : 1);
|
|
}
|