1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2009, 2023 Free Software Foundation, Inc. */
5 /* Copyright (C) 2010 Thien-Thi Nguyen */
6 /* */
7 /* This library is free software, licensed under the terms of the GNU */
8 /* General Public License as published by the Free Software Foundation, */
9 /* either version 3 of the License, or (at your option) any later version. */
10 /* You should have received a copy of the GNU General Public License */
11 /* along with this program. If not, see <http://www.gnu.org/licenses/>. */
12 /*****************************************************************************/
13
14 /*
15 * load_dwg.c: load a DWG, get lines, text and circles
16 * written by Felipe Castro
17 * modified by Felipe CorrĂȘa da Silva Sances
18 * modified by Thien-Thi Nguyen
19 * modified by Reini Urban
20 */
21
22 #include "config.h"
23 #ifdef __STDC_ALLOC_LIB__ /* for strdup */
24 # define __STDC_WANT_LIB_EXT2__ 1 /* for strdup */
25 #else
26 # define _USE_BSD 1
27 #endif
28 #ifndef _XOPEN_SOURCE /* for strdup, snprintf */
29 # define _XOPEN_SOURCE 700
30 #endif
31
32 #include <stdio.h>
33 #include <time.h>
34 #ifndef DISABLE_WRITE
35 # include <sys/stat.h>
36 # include <unistd.h>
37 #endif
38 #include "dwg.h"
39 #include "dwg_api.h"
40 #include "../src/bits.h"
41
42 #include "../programs/suffix.inc"
43 static int help (void);
44 int verbosity (int argc, char **argv, int i, unsigned int *opts);
45 #include "../programs/common.inc"
46
47 static int
48 usage (void)
49 {
50 printf ("\nUsage: load_dwg [-v[0-9]] DWGFILE\n");
51 return 1;
52 }
53 static int
54 opt_version (void)
55 {
56 printf ("load_dwg %s\n", PACKAGE_VERSION);
57 return 0;
58 }
59 static int
60 help (void)
61 {
62 printf ("\nUsage: load_dwg [OPTION]... DWGFILE\n");
63 printf ("Example to add fingerprint elements to a DWG.\n"
64 "\n");
65 printf (" -v[0-9], --verbose [0-9] verbosity\n");
66 printf (" --help display this help and exit\n");
67 printf (" --version output version information and exit\n"
68 "\n");
69 printf ("GNU LibreDWG online manual: "
70 "<https://www.gnu.org/software/libredwg/>\n");
71 return 0;
72 }
73
74 static int
75 add_fingerprint (Dwg_Data *dwg, dwg_point_3d *pt)
76 {
77 int error = 0;
78 char text[128];
79 double height = dwg->header_vars.TEXTSIZE;
80 time_t t = time (NULL);
81 Dwg_Object_BLOCK_HEADER *hdr = dwg_get_block_header (dwg, &error);
82 Dwg_Entity_TEXT *ent;
83 if (error)
84 return 1;
85
86 #ifdef HAVE_WFORMAT_Y2K
87 GCC46_DIAG_IGNORE (-Wformat-y2k)
88 #endif
89 strftime (text, sizeof (text), "Last updated: %c", localtime (&t));
90 #ifdef HAVE_WFORMAT_Y2K
91 GCC46_DIAG_RESTORE
92 #endif
93
94 #ifdef USE_WRITE
95 if ((ent = dwg_add_TEXT (hdr, text, pt, height)))
96 {
97 ent->horiz_alignment = HORIZ_ALIGNMENT_RIGHT;
98 return 0;
99 }
100 else
101 #endif
102 return 1;
103 }
104
105 static int
106 change_fingerprint (Dwg_Data *dwg, Dwg_Entity_TEXT *_obj)
107 {
108 char text[128];
109 double height = dwg->header_vars.TEXTSIZE;
110 time_t t = time (NULL);
111
112 #ifdef HAVE_WFORMAT_Y2K
113 GCC46_DIAG_IGNORE (-Wformat-y2k)
114 #endif
115 strftime (text, sizeof (text), "Last updated: %c", localtime (&t));
116 #ifdef HAVE_WFORMAT_Y2K
117 GCC46_DIAG_RESTORE
118 #endif
119
120 if (dwg->header.version < R_2007)
121 {
122 if (strlen (text) < strlen (_obj->text_value))
123 strcpy (_obj->text_value, text);
124 else
125 {
126 free (_obj->text_value);
127 _obj->text_value = strdup (text);
128 }
129 }
130 else
131 {
132 free (_obj->text_value);
133 _obj->text_value = (BITCODE_TV)bit_utf8_to_TU (text, 0);
134 }
135 return 0;
136 }
137
138 static int
139 load_dwg (char *filename, unsigned int opts)
140 {
141 BITCODE_BL i;
142 int success, found = 0;
143 Dwg_Data dwg;
144 dwg_point_3d pt;
145
146 #ifdef USE_WRITE
147 char *new_filename = (char *)malloc (strlen (filename) + 4);
148 char *fn = strdup (filename);
149 char *base = basename (fn);
150 char *p;
151 struct stat st;
152
153 if ((p = strrchr (base, '.')))
154 *p = '\0';
155 sprintf (new_filename, "%s_new.dwg", base);
156 free (fn);
157 #endif
158
159 memset (&dwg, 0, sizeof (Dwg_Data));
160 dwg.opts = opts;
161 success = dwg_read_file (filename, &dwg);
162 // get the insertion point for our fingerprint
163 pt.x = dwg.header_vars.LIMMAX.x;
164 pt.y = dwg.header_vars.LIMMAX.y;
165 pt.z = 0.0;
166
167 // check if a fingerprint already exists there.
168 // if so update it. if not add it
169 for (i = 0; i < dwg.num_objects; i++)
170 {
171 if (dwg.object[i].fixedtype == DWG_TYPE_TEXT)
172 {
173 Dwg_Entity_TEXT *_obj = dwg.object[i].tio.entity->tio.TEXT;
174 if (pt.x == _obj->ins_pt.x && pt.y == _obj->ins_pt.y
175 && _obj->horiz_alignment == HORIZ_ALIGNMENT_RIGHT)
176 {
177 found++;
178 change_fingerprint (&dwg, _obj);
179 fprintf (stderr, "fingerprint updated at (%f, %f)\n", pt.x,
180 pt.y);
181 }
182 }
183 }
184
185 if (!found)
186 {
187 add_fingerprint (&dwg, &pt);
188 fprintf (stderr, "fingerprint added at (%f, %f)\n", pt.x, pt.y);
189 }
190
191 #ifdef USE_WRITE
192 if (0 == stat (new_filename, &st))
193 unlink (new_filename);
194 if (dwg.header.version > R_2000)
195 dwg.header.version = R_2000;
196 success = dwg_write_file (new_filename, &dwg);
197 free (new_filename);
198 #endif
199
200 dwg_free (&dwg);
201 return success;
202 }
203
204 int
205 main (int argc, char *argv[])
206 {
207 int i = 1;
208 unsigned int opts = 0;
209
210 if (argc < 2)
211 return usage ();
212 #if defined(USE_TRACING) && defined(HAVE_SETENV)
213 setenv ("LIBREDWG_TRACE", "1", 0);
214 #endif
215 if (argc > 2
216 && (!strcmp (argv[i], "--verbose") || !strncmp (argv[i], "-v", 2)))
217 {
218 int num_args = verbosity (argc, argv, i, &opts);
219 argc -= num_args;
220 i += num_args;
221 }
222 if (argc > 1 && !strcmp (argv[i], "--help"))
223 return help ();
224 if (argc > 1 && !strcmp (argv[i], "--version"))
225 return opt_version ();
226
227 REQUIRE_INPUT_FILE_ARG (argc);
228 load_dwg (argv[i], opts);
229 return 0;
230 }