/*****************************************************************************/ /* LibreDWG - free implementation of the DWG file format */ /* */ /* Copyright (C) 2009-2025 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 . */ /*****************************************************************************/ /* * common.c: common data arrays * written by Felipe Castro * modified by Felipe CorrĂȘa da Silva Sances * modified by Rodrigo Rodrigues da Silva * modified by Reini Urban */ #include "config.h" #define COMMON_C #include #include #include #include #include #include #include #include "common.h" #include "logging.h" // See also // 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 const struct dwg_versions dwg_versions[DWG_VERSIONS] = { /* r, type, hdr, desc, dwg_version, maint_rel_version */ { R_INVALID, "invalid", "INVALI", "No DWG", 0, 0 }, { R_1_1, "r1.1", "MC0.0", "MicroCAD Release 1.1", 0, 0 }, { R_1_2, "r1.2", "AC1.2", "AutoCAD Release 1.2", 0, 0 }, { R_1_3, "r1.3", "AC1.3", "AutoCAD Release 1.3", 1, 0 }, { R_1_4, "r1.4", "AC1.40", "AutoCAD Release 1.4", 2, 0 }, { R_2_0b, "r2.0b", "AC1.50", "AutoCAD 2.0 beta", 3, 0 }, // not seen { R_2_0, "r2.0", "AC1.50", "AutoCAD Release 2.0", 4, 0 }, { R_2_10, "r2.10", "AC2.10", "AutoCAD Release 2.10", 5, 0 }, { R_2_21, "r2.21", "AC2.21", "AutoCAD Release 2.21", 6, 0 }, { R_2_22, "r2.22", "AC2.22", "AutoCAD Release 2.22", 7, 0 }, { R_2_4, "r2.4", "AC1001", "AutoCAD Release 2.4", 8, 0 }, { R_2_5, "r2.5", "AC1002", "AutoCAD Release 2.5", 9, 0 }, { R_2_6, "r2.6", "AC1003", "AutoCAD Release 2.6", 10, 0 }, { R_9, "r9", "AC1004", "AutoCAD Release 9", 0xb, 0 }, { R_9c1, "r9c1", "AC1005", "AutoCAD Release 9c1", 0xc, 0 }, { R_10, "r10", "AC1006", "AutoCAD Release 10", 0xd, 0 }, { R_11b1, "r11b1", "AC1007", "AutoCAD 11 beta 1", 0xe, 0 }, { R_11b2, "r11b2", "AC1008", "AutoCAD 11 beta 2", 0xf, 0 }, { R_11, "r11", "AC1009", "AutoCAD Release 11/12 (LT R1/R2)", 0x10, 0 }, { R_13b1, "r13b1", "AC1010", "AutoCAD pre-R13 a", 0x11, 0 }, { R_13b2, "r13b2", "AC1011", "AutoCAD pre-R13 b", 0x12, 0 }, { R_13, "r13", "AC1012", "AutoCAD Release 13", 0x13, 0 }, { R_13c3, "r13c3", "AC1013", "AutoCAD Release 13c3", 0x14, 0x5 }, { R_14, "r14", "AC1014", "AutoCAD Release 14", 0x15, 0 }, { R_2000b, "r2000b", "AC1500", "AutoCAD 2000 beta", 0x16, 0 }, { R_2000, "r2000", "AC1015", "AutoCAD Release 2000", 0x17, 0xf }, { R_2000i, "r2000i", "AC1016", "AutoCAD Release 2000i", 0x17, 0xf }, { R_2002, "r2002", "AC1017", "AutoCAD Release 2002", 0x17, 0xf }, { R_2004a, "r2004a", "AC402a", "AutoCAD 2004 alpha a", 0x18, 0x68 }, { R_2004b, "r2004b", "AC402b", "AutoCAD 2004 alpha b", 0x18, 0x68 }, { R_2004c, "r2004c", "AC1018", "AutoCAD 2004 beta", 0x18, 0x68 }, // (includes versions AC1019/0x19 and AC1020/0x1a) { R_2004, "r2004", "AC1018", "AutoCAD Release 2004", 0x19, 0x68 }, //{ R_2005, "r2005", "AC1019", "AutoCAD 2005", 0x19, 0 }, // not seen //{ R_2006, "r2006", "AC1020", "AutoCAD 2006", 0x19, 0 }, // not seen { R_2007a, "r2007a", "AC701a", "AutoCAD 2007 alpha", 0x1a, 0x32 }, { R_2007b, "r2007b", "AC1021", "AutoCAD 2007 beta", 0x1a, 0x32 }, { R_2007, "r2007", "AC1021", "AutoCAD Release 2007", 0x1b, 0x32 }, //{ R_2008, "r2008", "AC1022", "AutoCAD 2008", 0x1b, 0 }, // not seen //{ R_2009, "r2009", "AC1023", "AutoCAD 2009", 0x1b, 0 }, // not seen { R_2010b, "r2010b", "AC1024", "AutoCAD 2010 beta", 0x1c, 0x6d }, { R_2010, "r2010", "AC1024", "AutoCAD Release 2010", 0x1d, 0x6d }, //{ R_2011, "r2011", "AC1025", "AutoCAD 2011", 0x1d, 0 }, // not seen //{ R_2012, "r2012", "AC1026", "AutoCAD 2012", 0x1e, 0 }, // not seen { R_2013b, "r2013b", "AC1027", "AutoCAD 2013 beta", 0x1e, 0x7d }, { R_2013, "r2013", "AC1027", "AutoCAD Release 2013", 0x1f, 0x7d }, //{ R_2014, "r2014", "AC1028", "AutoCAD 2014", 0x1f, 0 }, // not seen //{ R_2015, "r2015", "AC1029", "AutoCAD 2015", 0x1f, 0 }, // not seen //{ R_2016, "r2016", "AC1030", "AutoCAD 2016", 0x1f, 0 }, // not seen //{ R_2017, "r2017", "AC1031", "AutoCAD 2017", 0x20, 0 }, // not seen { R_2018b, "r2018b", "AC1032", "AutoCAD 2018 beta", 0x20, 0x1d }, { R_2018, "r2018", "AC1032", "AutoCAD Release 2018", 0x21, 0x1d }, //{ R_2019, "r2019", "AC1033", "AutoCAD Release 2019", 0x22, 0 }, // not seen //{ R_2020, "r2020", "AC1034", "AutoCAD Release 2020", 0x23, 0 }, // not seen //{ R_2021, "r2021", "AC1035", "AutoCAD Release 2021", 0x23, 0 }, // not seen { R_2022b, "r2022b", "AC103-4", "AutoCAD 2022 beta", 0x24, 0x1d }, { R_AFTER, "r>2022", NULL, "AutoCAD Release >2022", 0, 0 }, }; const unsigned char * dwg_sentinel (const Dwg_Sentinel sentinel_id) { static const unsigned char sentinels[DWG_SENTINEL_R11_AUXHEADER_END + 2][16] = { // DWG_SENTINEL_HEADER_END { 0x95, 0xA0, 0x4E, 0x28, 0x99, 0x82, 0x1A, 0xE5, 0x5E, 0x41, 0xE0, 0x5F, 0x9D, 0x3A, 0x4D, 0x00 }, // DWG_SENTINEL_THUMBNAIL_BEGIN { 0x1F, 0x25, 0x6D, 0x07, 0xD4, 0x36, 0x28, 0x28, 0x9D, 0x57, 0xCA, 0x3F, 0x9D, 0x44, 0x10, 0x2B }, // DWG_SENTINEL_THUMBNAIL_END { 0xE0, 0xDA, 0x92, 0xF8, 0x2B, 0xc9, 0xD7, 0xD7, 0x62, 0xA8, 0x35, 0xC0, 0x62, 0xBB, 0xEF, 0xD4 }, // DWG_SENTINEL_VARIABLE_BEGIN { 0xCF, 0x7B, 0x1F, 0x23, 0xFD, 0xDE, 0x38, 0xA9, 0x5F, 0x7C, 0x68, 0xB8, 0x4E, 0x6D, 0x33, 0x5F }, // DWG_SENTINEL_VARIABLE_END { 0x30, 0x84, 0xE0, 0xDC, 0x02, 0x21, 0xC7, 0x56, 0xA0, 0x83, 0x97, 0x47, 0xB1, 0x92, 0xCC, 0xA0 }, // DWG_SENTINEL_CLASS_BEGIN { 0x8D, 0xA1, 0xC4, 0xB8, 0xC4, 0xA9, 0xF8, 0xC5, 0xC0, 0xDC, 0xF4, 0x5F, 0xE7, 0xCF, 0xB6, 0x8A }, // DWG_SENTINEL_CLASS_END { 0x72, 0x5E, 0x3B, 0x47, 0x3B, 0x56, 0x07, 0x3A, 0x3F, 0x23, 0x0B, 0xA0, 0x18, 0x30, 0x49, 0x75 }, // DWG_SENTINEL_2NDHEADER_BEGIN { 0xD4, 0x7B, 0x21, 0xCE, 0x28, 0x93, 0x9F, 0xBF, 0x53, 0x24, 0x40, 0x09, 0x12, 0x3C, 0xAA, 0x01 }, // DWG_SENTINEL_2NDHEADER_END { 0x2B, 0x84, 0xDE, 0x31, 0xD7, 0x6C, 0x60, 0x40, 0xAC, 0xDB, 0xBF, 0xF6, 0xED, 0xC3, 0x55, 0xFE }, // DWG_SENTINEL_R11_ENTITIES_BEGIN C46E6854F86E3330633EC1852ADC9401 { 0xC4, 0x6E, 0x68, 0x54, 0xF8, 0x6E, 0x33, 0x30, 0x63, 0x3E, 0xC1, 0x85, 0x2A, 0xDC, 0x94, 0x01 }, // DWG_SENTINEL_R11_ENTITIES_END 3B9197AB0791CCCF9CC13E7AD5236BFE { 0x3B, 0x91, 0x97, 0xAB, 0x07, 0x91, 0xCC, 0xCF, 0x9C, 0xC1, 0x3E, 0x7A, 0xD5, 0x23, 0x6B, 0xFE }, // DWG_SENTINEL_R11_BLOCK_BEGIN DBEFB3F0C73E6DA6C9B6245C4C6F32CB { 0xDB, 0xEF, 0xB3, 0xF0, 0xC7, 0x3E, 0x6D, 0xA6, 0xC9, 0xB6, 0x24, 0x5C, 0x4C, 0x6F, 0x32, 0xCB }, // DWG_SENTINEL_R11_BLOCK_END 24104C0F38C192593649DBA3B390CD34 { 0x24, 0x10, 0x4C, 0x0F, 0x38, 0xC1, 0x92, 0x59, 0x36, 0x49, 0xDB, 0xA3, 0xB3, 0x90, 0xCD, 0x34 }, // DWG_SENTINEL_R11_LAYER_BEGIN 0EC4646FBB1DD38B0049C2EF18EA6FFB { 0x0E, 0xC4, 0x64, 0x6F, 0xBB, 0x1D, 0xD3, 0x8B, 0x00, 0x49, 0xC2, 0xEF, 0x18, 0xEA, 0x6F, 0xFB }, // DWG_SENTINEL_R11_LAYER_END F13B9B9044E22C74FFB63D10E7159004 { 0xF1, 0x3B, 0x9B, 0x90, 0x44, 0xE2, 0x2C, 0x74, 0xFF, 0xB6, 0x3D, 0x10, 0xE7, 0x15, 0x90, 0x04 }, // DWG_SENTINEL_R11_STYLE_BEGIN E23EC182439F617750ABC76696000618 { 0xE2, 0x3E, 0xC1, 0x82, 0x43, 0x9F, 0x61, 0x77, 0x50, 0xAB, 0xC7, 0x66, 0x96, 0x00, 0x06, 0x18 }, // DWG_SENTINEL_R11_STYLE_END 1DC13E7DBC609E88AF54389969FFF9E7 { 0x1D, 0xC1, 0x3E, 0x7D, 0xBC, 0x60, 0x9E, 0x88, 0xAF, 0x54, 0x38, 0x99, 0x69, 0xFF, 0xF9, 0xE7 }, // DWG_SENTINEL_R11_LTYPE_BEGIN AC901ACA1CBD951516164C14CE1888AF { 0xAC, 0x90, 0x1A, 0xCA, 0x1C, 0xBD, 0x95, 0x15, 0x16, 0x16, 0x4C, 0x14, 0xCE, 0x18, 0x88, 0xAF }, // DWG_SENTINEL_R11_LTYPE_END 536FE535E3426AEAE9E9B3EB31E77750 { 0x53, 0x6F, 0xE5, 0x35, 0xE3, 0x42, 0x6A, 0xEA, 0xE9, 0xE9, 0xB3, 0xEB, 0x31, 0xE7, 0x77, 0x50 }, // DWG_SENTINEL_R11_VIEW_BEGIN C13CAA5668F4B41E4B74F408424DBFA5 { 0xC1, 0x3C, 0xAA, 0x56, 0x68, 0xF4, 0xB4, 0x1E, 0x4B, 0x74, 0xF4, 0x08, 0x42, 0x4D, 0xBF, 0xA5 }, // DWG_SENTINEL_R11_VIEW_END 3EC355A9970B4BE1B48B0BF7BDB2405A { 0x3E, 0xC3, 0x55, 0xA9, 0x97, 0x0B, 0x4B, 0xE1, 0xB4, 0x8B, 0x0B, 0xF7, 0xBD, 0xB2, 0x40, 0x5A }, // DWG_SENTINEL_R11_UCS_BEGIN 604AFA3D8490CC5BEFE7D6A57F1E61CD { 0x60, 0x4A, 0xFA, 0x3D, 0x84, 0x90, 0xCC, 0x5B, 0xEF, 0xE7, 0xD6, 0xA5, 0x7F, 0x1E, 0x61, 0xCD }, // DWG_SENTINEL_R11_UCS_END 9FB505C27B6F33A41018295A80E19E32 { 0x9F, 0xB5, 0x05, 0xC2, 0x7B, 0x6F, 0x33, 0xA4, 0x10, 0x18, 0x29, 0x5A, 0x80, 0xE1, 0x9E, 0x32 }, // DWG_SENTINEL_R11_VPORT_BEGIN F6ED44612ADCE47B4EB92BBB6660638D { 0xF6, 0xED, 0x44, 0x61, 0x2A, 0xDC, 0xE4, 0x7B, 0x4E, 0xB9, 0x2B, 0xBB, 0x66, 0x60, 0x63, 0x8D }, // DWG_SENTINEL_R11_VPORT_END 0912BB9ED5231B84B146D444999F9C72 { 0x09, 0x12, 0xBB, 0x9E, 0xD5, 0x23, 0x1B, 0x84, 0xB1, 0x46, 0xD4, 0x44, 0x99, 0x9F, 0x9C, 0x72 }, // DWG_SENTINEL_R11_APPID_BEGIN E125C25036686C0C3BD35D56C1791C3A { 0xE1, 0x25, 0xC2, 0x50, 0x36, 0x68, 0x6C, 0x0C, 0x3B, 0xD3, 0x5D, 0x56, 0xC1, 0x79, 0x1C, 0x3A }, // DWG_SENTINEL_R11_APPID_END 1EDA3DAFC99793F3C42CA2A93E86E3C5 { 0x1E, 0xDA, 0x3D, 0xAF, 0xC9, 0x97, 0x93, 0xF3, 0xC4, 0x2C, 0xA2, 0xA9, 0x3E, 0x86, 0xE3, 0xC5 }, // DWG_SENTINEL_R11_DIMSTYLE_BEGIN B4183E42C99FFFE5B6E2CBB375C3C3B0 { 0xB4, 0x18, 0x3E, 0x42, 0xC9, 0x9F, 0xFF, 0xE5, 0xB6, 0xE2, 0xCB, 0xB3, 0x75, 0xC3, 0xC3, 0xB0 }, // DWG_SENTINEL_R11_DIMSTYLE_END 4BE7C1BD3660001A491D344C8A3C3C4F { 0x4B, 0xE7, 0xC1, 0xBD, 0x36, 0x60, 0x00, 0x1A, 0x49, 0x1D, 0x34, 0x4C, 0x8A, 0x3C, 0x3C, 0x4F }, // DWG_SENTINEL_R11_VX_BEGIN E0CA367CCEE7586F2B7D745505F1447F { 0xE0, 0xCA, 0x36, 0x7C, 0xCE, 0xE7, 0x58, 0x6F, 0x2B, 0x7D, 0x74, 0x55, 0x05, 0xF1, 0x44, 0x7F }, // DWG_SENTINEL_R11_VX_END 1F35C9833118A790D4828BAAFA0EBB80 { 0x1F, 0x35, 0xC9, 0x83, 0x31, 0x18, 0xA7, 0x90, 0xD4, 0x82, 0x8B, 0xAA, 0xFA, 0x0E, 0xBB, 0x80 }, // DWG_SENTINEL_R11_BLOCK_ENTITIES_BEGIN // 722B7DEC3E8C886C7A720AFDC86C8426 { 0x72, 0x2B, 0x7D, 0xEC, 0x3E, 0x8C, 0x88, 0x6C, 0x7A, 0x72, 0x0A, 0xFD, 0xC8, 0x6C, 0x84, 0x26 }, // DWG_SENTINEL_R11_BLOCK_ENTITIES_END // 8DD48213C1737793858DF50237937BD9 { 0x8D, 0xD4, 0x82, 0x13, 0xC1, 0x73, 0x77, 0x93, 0x85, 0x8D, 0xF5, 0x02, 0x37, 0x93, 0x7B, 0xD9 }, // DWG_SENTINEL_R11_EXTRA_ENTITIES_BEGIN // D5F9D3BB0AA969A6CD1C87C7EE804B17 { 0xD5, 0xF9, 0xD3, 0xBB, 0x0A, 0xA9, 0x69, 0xA6, 0xCD, 0x1C, 0x87, 0xC7, 0xEE, 0x80, 0x4B, 0x17 }, // DWG_SENTINEL_R11_EXTRA_ENTITIES_END // 2A062C44F556965932E37838117FB4E8 { 0x2A, 0x06, 0x2C, 0x44, 0xF5, 0x56, 0x96, 0x59, 0x32, 0xE3, 0x78, 0x38, 0x11, 0x7F, 0xB4, 0xE8 }, // DWG_SENTINEL_R11_AUXHEADER_BEGIN 298DD149A9731FEA99DE32F94D0AE019 { 0x29, 0x8D, 0xD1, 0x49, 0xA9, 0x73, 0x1F, 0xEA, 0x99, 0xDE, 0x32, 0xF9, 0x4D, 0x0A, 0xE0, 0x19 }, // DWG_SENTINEL_R11_AUXHEADER_END D6722EB6568CE0156621CD06B2F51FE6 { 0xD6, 0x72, 0x2E, 0xB6, 0x56, 0x8C, 0xE0, 0x15, 0x66, 0x21, 0xCD, 0x06, 0xB2, 0xF5, 0x1F, 0xE6 }, // DWG_SENTINEL_ILLEGAL (used for memcmp) { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE } }; if ((unsigned)sentinel_id > DWG_SENTINEL_R11_AUXHEADER_END) { fprintf (stderr, "ERROR: Illegal sentinel_id %u\n", (unsigned)sentinel_id); return sentinels[DWG_SENTINEL_R11_AUXHEADER_END + 1]; } return (const unsigned char *)sentinels[sentinel_id]; } const struct dwg_versions * dwg_version_struct (const Dwg_Version_Type version) { if (version < R_AFTER) return &dwg_versions[version]; else return NULL; } /* Returns the AC header magic string [6] */ const char * dwg_version_codes (const Dwg_Version_Type version) { if (version < R_AFTER) return dwg_versions[version].hdr; else return "------"; } // map [rVER] to our enum number, not the dwg->header.dwgversion // Acad 2018 offers SaveAs DWG: 2018,2013,2010,2007,2004,2000,r14 // DXF: 2018,2013,2010,2007,2004,2000,r12 // libdxfrw dwg2dxf offers R12, v2000, v2004, v2007, v2010 EXPORT Dwg_Version_Type dwg_version_as (const char *version) { // "r12" is the common name of the AC1009 format (R_12 == R_11 in the // enum); the tools' usage lists it as valid, but the table (indexed by // enum, so it cannot carry an alias row) only has "r11". if (strEQ (version, "r12")) return R_11; for (int i = R_AFTER - 1; i > 0; i--) { if (strEQ (dwg_versions[i].type, version)) return dwg_versions[i].r; } return R_INVALID; } /** The reverse of dwg_version_as (char*) */ EXPORT const char * dwg_version_type (const Dwg_Version_Type version) { if (version < R_AFTER) return dwg_versions[version].type; else return "invalid after"; } /** The version from the magic char[6] header. The proper release must then be set when we read the dwg_version also. */ EXPORT Dwg_Version_Type dwg_version_hdr_type (const char *hdr) { #ifndef HAVE_NONNULL if (!hdr) return R_INVALID; #endif for (int i = R_AFTER - 1; i > 0; i--) { if (strEQ (dwg_versions[i].hdr, hdr)) return dwg_versions[i].r; } return R_INVALID; } /** The version from the magic char[6] header and the matching dwg_version * number. */ Dwg_Version_Type dwg_version_hdr_type2 (const char *hdr, unsigned dwg_version) { #ifndef HAVE_NONNULL if (!hdr) return R_INVALID; #endif for (int i = R_AFTER - 1; i > 0; i--) { if (strEQ (dwg_versions[i].hdr, hdr)) if (!dwg_version || dwg_versions[i].dwg_version == dwg_version) return dwg_versions[i].r; } return R_INVALID; } // keep in sync with common.h DWG_BITS const char *dwg_bits_name[] = { "UNKNOWN", "RC", "RS", "RL", "B", "BB", "3B", "4BITS", "BS", "BL", "BLd", "RLL", "RD", "BD", "MC", "UMC", "MS", "TV", "TU", "T", "TF", "T32", "HANDLE", "BE", "DD", "BT", "BOT", "BLL", "TIMEBLL", "CMC", "ENC", "2RD", "3RD", "2BD", "3BD", "2DD", "3DD", "CRC", "CRC64", "RLLd" }; // minimal size of type in bits // keep in sync with above // used by unit-tests const unsigned char dwg_bits_size[] = { 0, //"UNKNOWN", 8, //"RC", 16, //"RS", 32, //"RL", 1, //"B", 2, //"BB", 3, //"3B", 4, //"4BITS", 2, //"BS", 10,18 2, //"BL", 10,34 2, //"BLd", 10,34 64, //"RLL", 64, //"RD", 2, //"BD", 66 1, //"MC", 1-4 1, //"UMC", 1-4 16, //"MS", 32 2, //"TV", 18, //"TU", 2, //"T", 1, //"TF", 2, //"T32", 4, //"TU32", 8, //"HANDLE", 1, //"BE", or 3BD 2, //"DD", 1, //"BT", 10, //"BOT", 3, //"BLL", 4, //"TIMEBLL", 2xBL 2, //"CMC", r2004+: +2 4, //"ENC", r2004+ 128, //"2RD", 196, //"3RD", 4, //"2BD", 6, //"3BD", 4, //"2DD", 6, //"3DD", 8, //"CRC", 64, //"CRC64", 64, //"RLLd", }; /* replace from ("[rcount1]") with to ("[%d]") in s (e.g. "ref[rcount1].classname"). s is a global constant (#nam), so we cannot change it in-place. */ EXPORT char * strrplc (const char *s, const char *from, const char *to) { const char *p = strstr (s, from); if (p) { const size_t l1 = strlen (from); const size_t l2 = strlen (to); const size_t len = strlen (s); char *dest = (char *)calloc (1, len - l1 + l2 + 1); long i = p - s; memcpy (dest, s, i); memcpy (dest + i, to, l2); memcpy (dest + i + l2, s + i + l1, len - i - l1); return dest; } else return NULL; } /* replace [rcount1], [rcount2] and [vcount] with concrete indexes. */ EXPORT char * format_field_name (const char *s, long row_count1, long row_count2, long value_count) { char *dest = (char *)calloc (1, 128); size_t j = 0; bool changed = false; if (!dest) return NULL; for (size_t i = 0; s[i] && j < 127;) { if (!strncmp (&s[i], "[rcount1]", 9)) { j += (size_t)snprintf (&dest[j], 128 - j, "[%ld]", row_count1); i += 9; changed = true; } else if (!strncmp (&s[i], "[rcount2]", 9)) { j += (size_t)snprintf (&dest[j], 128 - j, "[%ld]", row_count2); i += 9; changed = true; } else if (!strncmp (&s[i], "[vcount]", 8)) { j += (size_t)snprintf (&dest[j], 128 - j, "[%ld]", value_count); i += 8; changed = true; } else dest[j++] = s[i++]; } assert (j < 128); if (!changed) { free (dest); return NULL; } return dest; } // naive from scratch implementation, not from glibc. // see also examples/unknown.c:membits void *__nonnull ((1, 3)) my_memmem (const void *h0, size_t k, const void *n0, size_t l) { const unsigned char *h = h0, *n = n0; unsigned char *plast; if (!l) return (void *)h; // empty needle if (k < l) return NULL; // needle longer than haystack h = memchr (h0, *n, k); if (!h || l == 1) return (void *)h; // first needle char not found k -= h - (const unsigned char *)h0; if (k < l) return NULL; // no room for needle plast = (unsigned char *)h + (k - l); do // naive 2 loops: O(n^2) { size_t i = 0; while (h[i] == n[i]) { if (++i == l) return (void *)h; } } while (++h <= plast); return NULL; } /* 32 types, with 3 categories: Face, Edge, Display, plus 58 props r2013+ */ const char *const _dwg_VISUALSTYLE_types[32] = { "Flat", "FlatWithEdges", "Gouraud", "GouraudWithEdges", "2DWireframe", "3DWireFrame", "Hidden", "Basic", "Realistic", "Conceptual", "Dim", "Brighten", "Thicken", "LinePattern", "Facepattern", "ColorChange", "FaceOnly", "EdgeOnly", "DisplayOnly", "JitterOff", "OverhangOff", "EdgeColorOff", "Shades of Gray", "Sketchy", "X-Ray", "Shaded with edges", "Shaded", "ByViewport", "ByLayer", "ByBlock", "ForEmptyStyle" }; /* types of the 58 rest r2013+ properties. * 1: * 2: * 3: * 4: * 5: */ const unsigned char _dwg_VISUALSTYLE_proptypes[58] = { /* [0] */ 2, 2, 2, 2, /* [4] */ 3, 3, 4, 2, /* [8] */ 2, 4, 4, 2, /* [12] */ 2, 3, 2, 4, /* [16] */ 3, 2, 2, 2, /* [20] */ 4, 2, 2, 2, /* [24] */ 1, 2, 3, 2, /* [28] */ 1, 1, 1, 1, /* [32] */ 1, 1, 1, 1, /* [36] */ 1, 2, 3, 3, /* [40] */ 2, 4, 2, 2, /* [44] */ 4, 1, 2, 2, /* [48] */ 2, 1, 2, 4, /* [52] */ 3, 2, 5, 1, /* [56] */ 3, 3 }; // returns the first ref from the handle vector. BITCODE_H shift_hv (BITCODE_H *hv, BITCODE_BL *num_p) { BITCODE_H ref = hv[0]; *num_p = *num_p - 1; memmove (&hv[0], &hv[1], *num_p * sizeof (BITCODE_H)); return ref; } // delete an entry from an HV ("handle vector") at index i void delete_hv (BITCODE_H *entries, BITCODE_BS *num_p, BITCODE_BS i) { BITCODE_H ref; BITCODE_BS nume = *num_p; assert (i < nume); ref = entries[i]; *num_p = *num_p - 1; nume--; if (!ref->handleref.is_global) free (ref); if (!nume || i != nume) // not the last? { memmove (&entries[i], &entries[i + 1], (nume - i) * sizeof (BITCODE_H)); } } // find if handle already exists, returns index or -1 BITCODE_BSd find_hv (BITCODE_H *entries, BITCODE_BS num_entries, BITCODE_RLL handle_value) { BITCODE_BS i; #ifndef HAVE_NONNULL if (!entries || !num_entries) return -1; // empty handle vector #else if (!num_entries) return -1; // empty handle vector #endif for (i = 0; i < num_entries; i++) { if (entries[i] && (entries[i]->handleref.value == handle_value)) return i; } return -1; // not found } /* from my dwg11.c, 1995 - rurban */ struct tm * cvt_TIMEBLL (struct tm *tm, BITCODE_TIMEBLL date) { double t, ss; long ja, jalpha, jb, jc, jd, je; #define TRUNC(n) (long)floor (n) t = date.ms / 1000.0; // ms within the day, in seconds if (date.days > 2299161) { jalpha = TRUNC (((date.days - 1867216) - 0.25) / 36524.25); ja = (long)(date.days + 1 + jalpha - TRUNC (0.25 * jalpha)); } else ja = (long)date.days; if (ja < 1000) { // TDINDWG: relative minutes memset (tm, 0, sizeof (struct tm)); } else { jb = ja + 1524; jc = TRUNC (6680.0 + ((jb - 2439870) - 122.1) / 365.25); jd = 365 * jc + TRUNC (0.25 * jc); je = TRUNC ((jb - jd) / 30.6001); tm->tm_mday = (int)(jb - jd - TRUNC (30.6001 * je)); if (tm->tm_mday < 1) tm->tm_mday = 1; else if (tm->tm_mday > 31) tm->tm_mday %= 31; tm->tm_mon = (int)(je - 1); if (tm->tm_mon > 12) tm->tm_mon -= 12; tm->tm_year = (int)(jc - 4715); if (tm->tm_mon > 2) tm->tm_year--; if (tm->tm_year <= 0) tm->tm_year--; tm->tm_year -= 1900; // epoch start tm->tm_mon--; // zero-based } tm->tm_hour = (int)floor (t / 3600.0); t -= tm->tm_hour * 3600.0; if (ja >= 1000) tm->tm_hour = tm->tm_hour % 24; tm->tm_min = (int)floor (t / 60.0); ss = t - (tm->tm_min * 60.0); tm->tm_sec = (int)ss; // sprintf (s, "%02d.%02d.%4d %02d:%02d:%05.2f", d, m, y, hh, mm, ss); return tm; } /* in seconds */ long tm_offset (void) { time_t gmt, rawtime = time (NULL); struct tm *tm; #ifdef HAVE_GMTIME_R struct tm gbuf; tm = gmtime_r (&rawtime, &gbuf); #else tm = gmtime (&rawtime); #endif // Force mktime() lookup dst in timezone database tm->tm_isdst = -1; gmt = mktime (tm); return (long)difftime (rawtime, gmt); } // portability compat funcs EXPORT int my_strcasecmp (const char *a, const char *b) { while (*a && *b) { int diff = toupper ((unsigned char)*a) - toupper ((unsigned char)*b); if (diff) return diff; a++; b++; } return toupper ((unsigned char)*a) - toupper ((unsigned char)*b); } #ifdef _MSC_VER EXPORT char * basename (char *path) { // I've looked at the winsdk basename implementation. It's a clusterfuck, // because they have 2-byte widechars. We only accept utf-8 paths char *p = strrchr (path, '/'); if (!p) p = strrchr (path, '\\'); return p; } #endif