1 /*****************************************************************************/
2 /* LibreDWG - free implementation of the DWG file format */
3 /* */
4 /* Copyright (C) 2009-2023 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 * common.c: common data arrays
15 * written by Felipe Castro
16 * modified by Felipe CorrĂȘa da Silva Sances
17 * modified by Rodrigo Rodrigues da Silva
18 * modified by Reini Urban
19 */
20
21 #include "config.h"
22 #define COMMON_C
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <time.h>
28 #include <math.h>
29 #include <ctype.h>
30 #include "common.h"
31 #include "logging.h"
32
33 // See also
34 // http://devel.gvsig.org/sites/org.gvsig.dwg/2.0-SNAPSHOT/gvsig-base-library-pom/org.gvsig.dwg/xref/org/gvsig/dwg/lib/DwgFile.html
35 const struct dwg_versions dwg_versions[] = {
36 /* r, type, hdr, desc, dwg_version */
37 { R_INVALID, "invalid", "INVALI", "No DWG", 0 },
38 { R_1_1, "r1.1", "MC0.0", "MicroCAD Release 1.1", 0 },
39 { R_1_2, "r1.2", "AC1.2", "AutoCAD Release 1.2", 0 },
40 { R_1_3, "r1.3", "AC1.3", "AutoCAD Release 1.3", 1 },
41 { R_1_4, "r1.4", "AC1.40", "AutoCAD Release 1.4", 2 },
42 { R_2_0b, "r2.0b", "AC1.50", "AutoCAD 2.0 beta", 3 }, // not seen
43 { R_2_0, "r2.0", "AC1.50", "AutoCAD Release 2.0", 4 },
44 { R_2_10, "r2.10", "AC2.10", "AutoCAD Release 2.10", 5 },
45 { R_2_21, "r2.21", "AC2.21", "AutoCAD Release 2.21", 6 },
46 { R_2_22, "r2.22", "AC2.22", "AutoCAD Release 2.22", 7 },
47 { R_2_4, "r2.4", "AC1001", "AutoCAD Release 2.4", 8 },
48 { R_2_5, "r2.5", "AC1002", "AutoCAD Release 2.5", 9 },
49 { R_2_6, "r2.6", "AC1003", "AutoCAD Release 2.6", 10 },
50 { R_9, "r9", "AC1004", "AutoCAD Release 9", 0xb },
51 { R_9c1, "r9c1", "AC1005", "AutoCAD Release 9c1", 0xc },
52 { R_10, "r10", "AC1006", "AutoCAD Release 10", 0xd },
53 { R_11b1, "r11b1", "AC1007", "AutoCAD 11 beta 1", 0xe },
54 { R_11b2, "r11b2", "AC1008", "AutoCAD 11 beta 2", 0xf },
55 { R_11, "r11", "AC1009", "AutoCAD Release 11/12 (LT R1/R2)", 0x10 },
56 { R_13b1, "r13b1", "AC1010", "AutoCAD pre-R13 a", 0x11 },
57 { R_13b2, "r13b2", "AC1011", "AutoCAD pre-R13 b", 0x12 },
58 { R_13, "r13", "AC1012", "AutoCAD Release 13", 0x13 },
59 { R_13c3, "r13c3", "AC1013", "AutoCAD Release 13c3", 0x14 },
60 { R_14, "r14", "AC1014", "AutoCAD Release 14", 0x15 },
61 { R_2000b, "r2000b", "AC1500", "AutoCAD 2000 beta", 0x16 },
62 { R_2000, "r2000", "AC1015", "AutoCAD Release 2000", 0x17 },
63 { R_2000i, "r2000i", "AC1016", "AutoCAD Release 2000i", 0x17 },
64 { R_2002, "r2002", "AC1017", "AutoCAD Release 2002", 0x17 },
65 { R_2004a, "r2004a", "AC402a", "AutoCAD 2004 alpha a", 0x18 },
66 { R_2004b, "r2004b", "AC402b", "AutoCAD 2004 alpha b", 0x18 },
67 { R_2004c, "r2004c", "AC1018", "AutoCAD 2004 beta", 0x18 },
68 // (includes versions AC1019/0x19 and AC1020/0x1a)
69 { R_2004, "r2004", "AC1018", "AutoCAD Release 2004", 0x19 },
70 //{ R_2005, "r2005", "AC1019", "AutoCAD 2005", 0x19 }, // not seen
71 //{ R_2006, "r2006", "AC1020", "AutoCAD 2006", 0x19 }, // not seen
72 { R_2007a, "r2007a", "AC701a", "AutoCAD 2007 alpha", 0x1a },
73 { R_2007b, "r2007b", "AC1021", "AutoCAD 2007 beta", 0x1a },
74 { R_2007, "r2007", "AC1021", "AutoCAD Release 2007", 0x1b },
75 //{ R_2008, "r2008", "AC1022", "AutoCAD 2008", 0x1b }, // not seen
76 //{ R_2009, "r2009", "AC1023", "AutoCAD 2009", 0x1b }, // not seen
77 { R_2010b, "r2010b", "AC1024", "AutoCAD 2010 beta", 0x1c },
78 { R_2010, "r2010", "AC1024", "AutoCAD Release 2010", 0x1d },
79 //{ R_2011, "r2011", "AC1025", "AutoCAD 2011", 0x1d }, // not seen
80 //{ R_2012, "r2012", "AC1026", "AutoCAD 2012", 0x1e }, // not seen
81 { R_2013b, "r2013b", "AC1027", "AutoCAD 2013 beta", 0x1e },
82 { R_2013, "r2013", "AC1027", "AutoCAD Release 2013", 0x1f },
83 //{ R_2014, "r2014", "AC1028", "AutoCAD 2014", 0x1f }, // not seen
84 //{ R_2015, "r2015", "AC1029", "AutoCAD 2015", 0x1f }, // not seen
85 //{ R_2016, "r2016", "AC1030", "AutoCAD 2016", 0x1f }, // not seen
86 //{ R_2017, "r2017", "AC1031", "AutoCAD 2017", 0x20 }, // not seen
87 { R_2018b, "r2018b", "AC1032", "AutoCAD 2018 beta", 0x20 },
88 { R_2018, "r2018", "AC1032", "AutoCAD Release 2018", 0x21 },
89 //{ R_2019, "r2019", "AC1033", "AutoCAD Release 2019", 0x22 }, // not seen
90 //{ R_2020, "r2020", "AC1034", "AutoCAD Release 2020", 0x23 }, // not seen
91 //{ R_2021, "r2021", "AC1035", "AutoCAD Release 2021", 0x23 }, // not seen
92 { R_2022b, "r2022b", "AC103-4", "AutoCAD 2022 beta", 0x24 },
93 { R_AFTER, "r>2022", NULL, "AutoCAD Release >2022", 0 },
94 };
95
96 const unsigned char *
97 dwg_sentinel (const Dwg_Sentinel sentinel_id)
98 {
99 static const unsigned char sentinels[DWG_SENTINEL_R11_AUXHEADER_END + 2][16]
100 = { // DWG_SENTINEL_HEADER_END
101 { 0x95, 0xA0, 0x4E, 0x28, 0x99, 0x82, 0x1A, 0xE5, 0x5E, 0x41, 0xE0,
102 0x5F, 0x9D, 0x3A, 0x4D, 0x00 },
103 // DWG_SENTINEL_THUMBNAIL_BEGIN
104 { 0x1F, 0x25, 0x6D, 0x07, 0xD4, 0x36, 0x28, 0x28, 0x9D, 0x57, 0xCA,
105 0x3F, 0x9D, 0x44, 0x10, 0x2B },
106 // DWG_SENTINEL_THUMBNAIL_END
107 { 0xE0, 0xDA, 0x92, 0xF8, 0x2B, 0xc9, 0xD7, 0xD7, 0x62, 0xA8, 0x35,
108 0xC0, 0x62, 0xBB, 0xEF, 0xD4 },
109 // DWG_SENTINEL_VARIABLE_BEGIN
110 { 0xCF, 0x7B, 0x1F, 0x23, 0xFD, 0xDE, 0x38, 0xA9, 0x5F, 0x7C, 0x68,
111 0xB8, 0x4E, 0x6D, 0x33, 0x5F },
112 // DWG_SENTINEL_VARIABLE_END
113 { 0x30, 0x84, 0xE0, 0xDC, 0x02, 0x21, 0xC7, 0x56, 0xA0, 0x83, 0x97,
114 0x47, 0xB1, 0x92, 0xCC, 0xA0 },
115 // DWG_SENTINEL_CLASS_BEGIN
116 { 0x8D, 0xA1, 0xC4, 0xB8, 0xC4, 0xA9, 0xF8, 0xC5, 0xC0, 0xDC, 0xF4,
117 0x5F, 0xE7, 0xCF, 0xB6, 0x8A },
118 // DWG_SENTINEL_CLASS_END
119 { 0x72, 0x5E, 0x3B, 0x47, 0x3B, 0x56, 0x07, 0x3A, 0x3F, 0x23, 0x0B,
120 0xA0, 0x18, 0x30, 0x49, 0x75 },
121 // DWG_SENTINEL_2NDHEADER_BEGIN
122 { 0xD4, 0x7B, 0x21, 0xCE, 0x28, 0x93, 0x9F, 0xBF, 0x53, 0x24, 0x40,
123 0x09, 0x12, 0x3C, 0xAA, 0x01 },
124 // DWG_SENTINEL_2NDHEADER_END
125 { 0x2B, 0x84, 0xDE, 0x31, 0xD7, 0x6C, 0x60, 0x40, 0xAC, 0xDB, 0xBF,
126 0xF6, 0xED, 0xC3, 0x55, 0xFE },
127 // DWG_SENTINEL_R11_ENTITIES_BEGIN C46E6854F86E3330633EC1852ADC9401
128 { 0xC4, 0x6E, 0x68, 0x54, 0xF8, 0x6E, 0x33, 0x30, 0x63, 0x3E, 0xC1,
129 0x85, 0x2A, 0xDC, 0x94, 0x01 },
130 // DWG_SENTINEL_R11_ENTITIES_END 3B9197AB0791CCCF9CC13E7AD5236BFE
131 { 0x3B, 0x91, 0x97, 0xAB, 0x07, 0x91, 0xCC, 0xCF, 0x9C, 0xC1, 0x3E,
132 0x7A, 0xD5, 0x23, 0x6B, 0xFE },
133 // DWG_SENTINEL_R11_BLOCK_BEGIN DBEFB3F0C73E6DA6C9B6245C4C6F32CB
134 { 0xDB, 0xEF, 0xB3, 0xF0, 0xC7, 0x3E, 0x6D, 0xA6, 0xC9, 0xB6, 0x24,
135 0x5C, 0x4C, 0x6F, 0x32, 0xCB },
136 // DWG_SENTINEL_R11_BLOCK_END 24104C0F38C192593649DBA3B390CD34
137 { 0x24, 0x10, 0x4C, 0x0F, 0x38, 0xC1, 0x92, 0x59, 0x36, 0x49, 0xDB,
138 0xA3, 0xB3, 0x90, 0xCD, 0x34 },
139 // DWG_SENTINEL_R11_LAYER_BEGIN 0EC4646FBB1DD38B0049C2EF18EA6FFB
140 { 0x0E, 0xC4, 0x64, 0x6F, 0xBB, 0x1D, 0xD3, 0x8B, 0x00, 0x49, 0xC2,
141 0xEF, 0x18, 0xEA, 0x6F, 0xFB },
142 // DWG_SENTINEL_R11_LAYER_END F13B9B9044E22C74FFB63D10E7159004
143 { 0xF1, 0x3B, 0x9B, 0x90, 0x44, 0xE2, 0x2C, 0x74, 0xFF, 0xB6, 0x3D,
144 0x10, 0xE7, 0x15, 0x90, 0x04 },
145 // DWG_SENTINEL_R11_STYLE_BEGIN E23EC182439F617750ABC76696000618
146 { 0xE2, 0x3E, 0xC1, 0x82, 0x43, 0x9F, 0x61, 0x77, 0x50, 0xAB, 0xC7,
147 0x66, 0x96, 0x00, 0x06, 0x18 },
148 // DWG_SENTINEL_R11_STYLE_END 1DC13E7DBC609E88AF54389969FFF9E7
149 { 0x1D, 0xC1, 0x3E, 0x7D, 0xBC, 0x60, 0x9E, 0x88, 0xAF, 0x54, 0x38,
150 0x99, 0x69, 0xFF, 0xF9, 0xE7 },
151 // DWG_SENTINEL_R11_LTYPE_BEGIN AC901ACA1CBD951516164C14CE1888AF
152 { 0xAC, 0x90, 0x1A, 0xCA, 0x1C, 0xBD, 0x95, 0x15, 0x16, 0x16, 0x4C,
153 0x14, 0xCE, 0x18, 0x88, 0xAF },
154 // DWG_SENTINEL_R11_LTYPE_END 536FE535E3426AEAE9E9B3EB31E77750
155 { 0x53, 0x6F, 0xE5, 0x35, 0xE3, 0x42, 0x6A, 0xEA, 0xE9, 0xE9, 0xB3,
156 0xEB, 0x31, 0xE7, 0x77, 0x50 },
157 // DWG_SENTINEL_R11_VIEW_BEGIN C13CAA5668F4B41E4B74F408424DBFA5
158 { 0xC1, 0x3C, 0xAA, 0x56, 0x68, 0xF4, 0xB4, 0x1E, 0x4B, 0x74, 0xF4,
159 0x08, 0x42, 0x4D, 0xBF, 0xA5 },
160 // DWG_SENTINEL_R11_VIEW_END 3EC355A9970B4BE1B48B0BF7BDB2405A
161 { 0x3E, 0xC3, 0x55, 0xA9, 0x97, 0x0B, 0x4B, 0xE1, 0xB4, 0x8B, 0x0B,
162 0xF7, 0xBD, 0xB2, 0x40, 0x5A },
163 // DWG_SENTINEL_R11_UCS_BEGIN 604AFA3D8490CC5BEFE7D6A57F1E61CD
164 { 0x60, 0x4A, 0xFA, 0x3D, 0x84, 0x90, 0xCC, 0x5B, 0xEF, 0xE7, 0xD6,
165 0xA5, 0x7F, 0x1E, 0x61, 0xCD },
166 // DWG_SENTINEL_R11_UCS_END 9FB505C27B6F33A41018295A80E19E32
167 { 0x9F, 0xB5, 0x05, 0xC2, 0x7B, 0x6F, 0x33, 0xA4, 0x10, 0x18, 0x29,
168 0x5A, 0x80, 0xE1, 0x9E, 0x32 },
169 // DWG_SENTINEL_R11_VPORT_BEGIN F6ED44612ADCE47B4EB92BBB6660638D
170 { 0xF6, 0xED, 0x44, 0x61, 0x2A, 0xDC, 0xE4, 0x7B, 0x4E, 0xB9, 0x2B,
171 0xBB, 0x66, 0x60, 0x63, 0x8D },
172 // DWG_SENTINEL_R11_VPORT_END 0912BB9ED5231B84B146D444999F9C72
173 { 0x09, 0x12, 0xBB, 0x9E, 0xD5, 0x23, 0x1B, 0x84, 0xB1, 0x46, 0xD4,
174 0x44, 0x99, 0x9F, 0x9C, 0x72 },
175 // DWG_SENTINEL_R11_APPID_BEGIN E125C25036686C0C3BD35D56C1791C3A
176 { 0xE1, 0x25, 0xC2, 0x50, 0x36, 0x68, 0x6C, 0x0C, 0x3B, 0xD3, 0x5D,
177 0x56, 0xC1, 0x79, 0x1C, 0x3A },
178 // DWG_SENTINEL_R11_APPID_END 1EDA3DAFC99793F3C42CA2A93E86E3C5
179 { 0x1E, 0xDA, 0x3D, 0xAF, 0xC9, 0x97, 0x93, 0xF3, 0xC4, 0x2C, 0xA2,
180 0xA9, 0x3E, 0x86, 0xE3, 0xC5 },
181 // DWG_SENTINEL_R11_DIMSTYLE_BEGIN B4183E42C99FFFE5B6E2CBB375C3C3B0
182 { 0xB4, 0x18, 0x3E, 0x42, 0xC9, 0x9F, 0xFF, 0xE5, 0xB6, 0xE2, 0xCB,
183 0xB3, 0x75, 0xC3, 0xC3, 0xB0 },
184 // DWG_SENTINEL_R11_DIMSTYLE_END 4BE7C1BD3660001A491D344C8A3C3C4F
185 { 0x4B, 0xE7, 0xC1, 0xBD, 0x36, 0x60, 0x00, 0x1A, 0x49, 0x1D, 0x34,
186 0x4C, 0x8A, 0x3C, 0x3C, 0x4F },
187 // DWG_SENTINEL_R11_VX_BEGIN E0CA367CCEE7586F2B7D745505F1447F
188 { 0xE0, 0xCA, 0x36, 0x7C, 0xCE, 0xE7, 0x58, 0x6F, 0x2B, 0x7D, 0x74,
189 0x55, 0x05, 0xF1, 0x44, 0x7F },
190 // DWG_SENTINEL_R11_VX_END 1F35C9833118A790D4828BAAFA0EBB80
191 { 0x1F, 0x35, 0xC9, 0x83, 0x31, 0x18, 0xA7, 0x90, 0xD4, 0x82, 0x8B,
192 0xAA, 0xFA, 0x0E, 0xBB, 0x80 },
193 // DWG_SENTINEL_R11_BLOCK_ENTITIES_BEGIN
194 // 722B7DEC3E8C886C7A720AFDC86C8426
195 { 0x72, 0x2B, 0x7D, 0xEC, 0x3E, 0x8C, 0x88, 0x6C, 0x7A, 0x72, 0x0A,
196 0xFD, 0xC8, 0x6C, 0x84, 0x26 },
197 // DWG_SENTINEL_R11_BLOCK_ENTITIES_END
198 // 8DD48213C1737793858DF50237937BD9
199 { 0x8D, 0xD4, 0x82, 0x13, 0xC1, 0x73, 0x77, 0x93, 0x85, 0x8D, 0xF5,
200 0x02, 0x37, 0x93, 0x7B, 0xD9 },
201 // DWG_SENTINEL_R11_EXTRA_ENTITIES_BEGIN
202 // D5F9D3BB0AA969A6CD1C87C7EE804B17
203 { 0xD5, 0xF9, 0xD3, 0xBB, 0x0A, 0xA9, 0x69, 0xA6, 0xCD, 0x1C, 0x87,
204 0xC7, 0xEE, 0x80, 0x4B, 0x17 },
205 // DWG_SENTINEL_R11_EXTRA_ENTITIES_END
206 // 2A062C44F556965932E37838117FB4E8
207 { 0x2A, 0x06, 0x2C, 0x44, 0xF5, 0x56, 0x96, 0x59, 0x32, 0xE3, 0x78,
208 0x38, 0x11, 0x7F, 0xB4, 0xE8 },
209 // DWG_SENTINEL_R11_AUXHEADER_BEGIN 298DD149A9731FEA99DE32F94D0AE019
210 { 0x29, 0x8D, 0xD1, 0x49, 0xA9, 0x73, 0x1F, 0xEA, 0x99, 0xDE, 0x32,
211 0xF9, 0x4D, 0x0A, 0xE0, 0x19 },
212 // DWG_SENTINEL_R11_AUXHEADER_END D6722EB6568CE0156621CD06B2F51FE6
213 { 0xD6, 0x72, 0x2E, 0xB6, 0x56, 0x8C, 0xE0, 0x15, 0x66, 0x21, 0xCD,
214 0x06, 0xB2, 0xF5, 0x1F, 0xE6 },
215 // DWG_SENTINEL_ILLEGAL (used for memcmp)
216 { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
217 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }
218 };
219 if ((unsigned)sentinel_id > DWG_SENTINEL_R11_AUXHEADER_END)
220 {
221 fprintf (stderr, "ERROR: Illegal sentinel_id %u\n",
222 (unsigned)sentinel_id);
223 return sentinels[DWG_SENTINEL_R11_AUXHEADER_END + 1];
224 }
225 return (const unsigned char *)sentinels[sentinel_id];
226 }
227
228 const struct dwg_versions *
229 dwg_version_struct (const Dwg_Version_Type version)
230 {
231 if (version < R_AFTER)
232 return &dwg_versions[version];
233 else
234 return NULL;
235 }
236
237 /* Returns the AC header magic string [6] */
238 const char *
239 dwg_version_codes (const Dwg_Version_Type version)
240 {
241 if (version < R_AFTER)
242 return dwg_versions[version].hdr;
243 else
244 return "------";
245 }
246
247 // map [rVER] to our enum number, not the dwg->header.dwgversion
248 // Acad 2018 offers SaveAs DWG: 2018,2013,2010,2007,2004,2000,r14
249 // DXF: 2018,2013,2010,2007,2004,2000,r12
250 // libdxfrw dwg2dxf offers R12, v2000, v2004, v2007, v2010
251 EXPORT Dwg_Version_Type
252 dwg_version_as (const char *version)
253 {
254 for (int i = R_AFTER - 1; i > 0; i--)
255 {
256 if (strEQ (dwg_versions[i].type, version))
257 return dwg_versions[i].r;
258 }
259 return R_INVALID;
260 }
261
262 /** The reverse of dwg_version_as (char*) */
263 EXPORT const char *
264 dwg_version_type (const Dwg_Version_Type version)
265 {
266 if (version < R_AFTER)
267 return dwg_versions[version].type;
268 else
269 return "invalid after";
270 }
271
272 /** The version from the magic char[6] header.
273 The proper release must then be set when we read the dwg_version also. */
274 EXPORT Dwg_Version_Type
275 dwg_version_hdr_type (const char *hdr)
276 {
277 for (int i = R_AFTER - 1; i > 0; i--)
278 {
279 if (strEQ (dwg_versions[i].hdr, hdr))
280 return dwg_versions[i].r;
281 }
282 return R_INVALID;
283 }
284
285 /** The version from the magic char[6] header and the matching dwg_version
286 * number. */
287 Dwg_Version_Type
288 dwg_version_hdr_type2 (const char *hdr, unsigned dwg_version)
289 {
290 for (int i = R_AFTER - 1; i > 0; i--)
291 {
292 if (strEQ (dwg_versions[i].hdr, hdr))
293 if (!dwg_version || dwg_versions[i].dwg_version == dwg_version)
294 return dwg_versions[i].r;
295 }
296 return R_INVALID;
297 }
298
299 // keep in sync with common.h DWG_BITS
300 const char *dwg_bits_name[]
301 = { "UNKNOWN", "RC", "RS", "RL", "B", "BB", "3B", "4BITS",
302 "BS", "BL", "BLd", "RLL", "RD", "BD", "MC", "UMC",
303 "MS", "TV", "TU", "T", "TF", "T32", "HANDLE", "BE",
304 "DD", "BT", "BOT", "BLL", "TIMEBLL", "CMC", "ENC", "2RD",
305 "3RD", "2BD", "3BD", "2DD", "3DD", "CRC", "CRC64", "RLLd" };
306
307 // minimal size of type in bits
308 // keep in sync with above
309 // used by unit-tests
310 const unsigned char dwg_bits_size[] = {
311 0, //"UNKNOWN",
312 8, //"RC",
313 16, //"RS",
314 32, //"RL",
315 1, //"B",
316 2, //"BB",
317 3, //"3B",
318 4, //"4BITS",
319 2, //"BS", 10,18
320 2, //"BL", 10,34
321 2, //"BLd", 10,34
322 64, //"RLL",
323 64, //"RD",
324 2, //"BD", 66
325 1, //"MC", 1-4
326 1, //"UMC", 1-4
327 16, //"MS", 32
328 2, //"TV",
329 18, //"TU",
330 2, //"T",
331 1, //"TF",
332 2, //"T32",
333 4, //"TU32",
334 8, //"HANDLE",
335 1, //"BE", or 3BD
336 2, //"DD",
337 1, //"BT",
338 10, //"BOT",
339 3, //"BLL",
340 4, //"TIMEBLL", 2xBL
341 2, //"CMC", r2004+: +2
342 4, //"ENC", r2004+
343 128, //"2RD",
344 196, //"3RD",
345 4, //"2BD",
346 6, //"3BD",
347 4, //"2DD",
348 6, //"3DD",
349 8, //"CRC",
350 64, //"CRC64",
351 64, //"RLLd",
352 };
353
354 /* replace from ("[rcount1]") with to ("[%d]") in s (e.g.
355 "ref[rcount1].classname"). s is a global constant (#nam), so we cannot
356 change it in-place.
357 */
358 EXPORT char *
359 strrplc (const char *s, const char *from, const char *to)
360 {
361 const char *p = strstr (s, from);
362 if (p)
363 {
364 const size_t l1 = strlen (from);
365 const size_t l2 = strlen (to);
366 char *dest = (char *)calloc (1, 80);
367 long i = p - s;
368 assert (strlen (s) - ((long)l1 - l2) < 80);
369 memcpy (dest, s, i);
370 strncat (dest, to, 79 - l2);
371 strncat (dest, s + i + l1, 79 - l1);
372 return dest;
373 }
374 else
375 return NULL;
376 }
377
378 #if !defined(HAVE_MEMMEM) || defined(COMMON_TEST_C)
379 // naive from scratch implementation, not from glibc.
380 // see also examples/unknown.c:membits
381 void *__nonnull ((1, 3))
382 my_memmem (const void *h0, size_t k, const void *n0, size_t l)
383 {
384 const unsigned char *h = h0, *n = n0;
385 unsigned char *plast;
386
387 if (!l)
388 return (void *)h; // empty needle
389 if (k < l)
390 return NULL; // needle longer than haystack
391 h = memchr (h0, *n, k);
392 if (!h || l == 1)
393 return (void *)h; // first needle char not found
394 k -= h - (const unsigned char *)h0;
395 if (k < l)
396 return NULL; // no room for needle
397
398 plast = (unsigned char *)h + (k - l);
399 do // naive 2 loops: O(n^2)
400 {
401 size_t i = 0;
402 while (h[i] == n[i])
403 {
404 if (++i == l)
405 return (void *)h;
406 }
407 }
408 while (++h <= plast);
409 return NULL;
410 }
411 #endif
412
413 /*
414 32 types, with 3 categories: Face, Edge, Display, plus 58 props r2013+
415 */
416 const char *const _dwg_VISUALSTYLE_types[32] = { "Flat",
417 "FlatWithEdges",
418 "Gouraud",
419 "GouraudWithEdges",
420 "2DWireframe",
421 "3DWireFrame",
422 "Hidden",
423 "Basic",
424 "Realistic",
425 "Conceptual",
426 "Dim",
427 "Brighten",
428 "Thicken",
429 "LinePattern",
430 "Facepattern",
431 "ColorChange",
432 "FaceOnly",
433 "EdgeOnly",
434 "DisplayOnly",
435 "JitterOff",
436 "OverhangOff",
437 "EdgeColorOff",
438 "Shades of Gray",
439 "Sketchy",
440 "X-Ray",
441 "Shaded with edges",
442 "Shaded",
443 "ByViewport",
444 "ByLayer",
445 "ByBlock",
446 "ForEmptyStyle" };
447
448 /* types of the 58 rest r2013+ properties.
449 * 1:
450 * 2:
451 * 3:
452 * 4:
453 * 5:
454 */
455 const unsigned char _dwg_VISUALSTYLE_proptypes[58] = {
456 /* [0] */ 2, 2, 2, 2,
457 /* [4] */ 3, 3, 4, 2,
458 /* [8] */ 2, 4, 4, 2,
459 /* [12] */ 2, 3, 2, 4,
460 /* [16] */ 3, 2, 2, 2,
461 /* [20] */ 4, 2, 2, 2,
462 /* [24] */ 1, 2, 3, 2,
463 /* [28] */ 1, 1, 1, 1,
464 /* [32] */ 1, 1, 1, 1,
465 /* [36] */ 1, 2, 3, 3,
466 /* [40] */ 2, 4, 2, 2,
467 /* [44] */ 4, 1, 2, 2,
468 /* [48] */ 2, 1, 2, 4,
469 /* [52] */ 3, 2, 5, 1,
470 /* [56] */ 3, 3
471 };
472
473 // returns the first ref from the handle vector.
474 BITCODE_H
475 shift_hv (BITCODE_H *hv, BITCODE_BL *num_p)
476 {
477 BITCODE_H ref = hv[0];
478 *num_p = *num_p - 1;
479 memmove (&hv[0], &hv[1], *num_p * sizeof (BITCODE_H));
480 return ref;
481 }
482
483 // delete an entry from an HV ("handle vector") at index i
484 void
485 delete_hv (BITCODE_H *entries, BITCODE_BS *num_p, BITCODE_BS i)
486 {
487 BITCODE_H ref;
488 BITCODE_BS nume = *num_p;
489 assert (i < nume);
490 ref = entries[i];
491 *num_p = *num_p - 1;
492 nume--;
493 if (!ref->handleref.is_global)
494 free (ref);
495 if (!nume || i != nume) // not the last?
496 {
497 memmove (&entries[i], &entries[i + 1], (nume - i) * sizeof (BITCODE_H));
498 }
499 }
500
501 /* from my dwg11.c, 1995 - rurban */
502 struct tm *
503 cvt_TIMEBLL (struct tm *tm, BITCODE_TIMEBLL date)
504 {
505 double t, ss;
506 long ja, jalpha, jb, jc, jd, je;
507
508 #define TRUNC(n) (long)floor (n)
509
510 t = 0.864 * date.ms / 1000.0; /*t=1000000 = 1 day, means 86400 in seconds */
511 if (date.days > 2299161)
512 {
513 jalpha = TRUNC (((date.days - 1867216) - 0.25) / 36524.25);
514 ja = (long)(date.days + 1 + jalpha - TRUNC (0.25 * jalpha));
515 }
516 else
517 ja = (long)date.days;
518 if (ja < 1000)
519 {
520 // TDINDWG: relative minutes
521 memset (tm, 0, sizeof (struct tm));
522 }
523 else
524 {
525 jb = ja + 1524;
526 jc = TRUNC (6680.0 + ((jb - 2439870) - 122.1) / 365.25);
527 jd = 365 * jc + TRUNC (0.25 * jc);
528 je = TRUNC ((jb - jd) / 30.6001);
529
530 tm->tm_mday = (int)(jb - jd - TRUNC (30.6001 * je));
531 if (tm->tm_mday < 1)
532 tm->tm_mday = 1;
533 else if (tm->tm_mday > 31)
534 tm->tm_mday %= 31;
535 tm->tm_mon = (int)(je - 1);
536 if (tm->tm_mon > 12)
537 tm->tm_mon -= 12;
538 tm->tm_year = (int)(jc - 4715);
539 if (tm->tm_mon > 2)
540 tm->tm_year--;
541 if (tm->tm_year <= 0)
542 tm->tm_year--;
543 tm->tm_year -= 1900; // epoch start
544 tm->tm_mon--; // zero-based
545 }
546 tm->tm_hour = (int)floor (t / 3600.0);
547 t -= tm->tm_hour * 3600.0;
548 if (ja >= 1000)
549 tm->tm_hour = tm->tm_hour % 24;
550 tm->tm_min = (int)floor (t / 60.0);
551 ss = t - (tm->tm_min * 60.0);
552 tm->tm_sec = (int)ss;
553 // sprintf (s, "%02d.%02d.%4d %02d:%02d:%05.2f", d, m, y, hh, mm, ss);
554 return tm;
555 }
556
557 /* in seconds */
558 long
559 tm_offset (void)
560 {
561 time_t gmt, rawtime = time (NULL);
562 struct tm *tm;
563
564 #ifdef HAVE_GMTIME_R
565 struct tm gbuf;
566 tm = gmtime_r (&rawtime, &gbuf);
567 #else
568 tm = gmtime (&rawtime);
569 #endif
570 // Force mktime() lookup dst in timezone database
571 tm->tm_isdst = -1;
572 gmt = mktime (tm);
573 return (long)difftime (rawtime, gmt);
574 }
575
576 // portability compat funcs
577
578 #ifndef HAVE_STRCASECMP
579 EXPORT int
580 strcasecmp (const char *a, const char *b)
581 {
582 size_t l2;
583 int r1 = strcmp (a, b);
584 if (!r1)
585 return 0;
586 l2 = strlen (b);
587 for (size_t i = 0; i < strlen (a); i++)
588 {
589 if (i > l2)
590 return 1;
591 if (toupper (a[i]) != toupper (b[i]))
592 return toupper (a[i]) < toupper (b[i]);
593 }
594 return 0;
595 }
596 #endif
597
598 #ifdef _MSC_VER
599 EXPORT char *
600 basename (char *path)
601 {
602 // I've looked at the winsdk basename implementation. It's a clusterfuck,
603 // because they have 2-byte widechars. We only accept utf-8 paths
604 char *p = strrchr (path, '/');
605 if (!p)
606 p = strrchr (path, '\\');
607 return p;
608 }
609 #endif