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