diff --git a/include/dwg.h b/include/dwg.h index 762f5244d4..722bee14a3 100644 --- a/include/dwg.h +++ b/include/dwg.h @@ -9037,10 +9037,11 @@ typedef enum DWG_SECTION_TYPE_R13 SECTION_HEADER_R13 = 0, SECTION_CLASSES_R13 = 1, SECTION_HANDLES_R13 = 2, - SECTION_OBJFREESPACE_R13 = 3, /* including the 2ndheader */ + SECTION_OBJFREESPACE_R13 = 3, SECTION_TEMPLATE_R13 = 4, SECTION_AUXHEADER_R2000 = 5, SECTION_THUMBNAIL_R13 = 6, + SECTION_SECOND_HEADER_R13 = 7, } Dwg_Section_Type_r13; typedef enum DWG_SECTION_TYPE_R11 /* tables */ @@ -9379,7 +9380,7 @@ typedef struct _dwg_header BITCODE_RL summaryinfo_address; /* R2004+ */ BITCODE_RL vbaproj_address; /* R2004+ */ BITCODE_RL r2004_header_address; /* R2004+ */ - BITCODE_RL sections; // as in the header, 5 or 6 usually + BITCODE_RL sections; // as in the header, 3 .. 6 usually BITCODE_RL num_sections; // as allocated, many more Dwg_Section *section; Dwg_Section_InfoHdr section_infohdr; /* R2004+ */ diff --git a/src/decode.c b/src/decode.c index a4d8e40b43..4f9f58253c 100644 --- a/src/decode.c +++ b/src/decode.c @@ -333,11 +333,10 @@ decode_R13_R2000 (Bit_Chain *restrict dat, Dwg_Data *restrict dwg) * 1: class section * 2: Handles (object map) * 3: optional: ObjFreeSpace - * -: 2ndHeader and its sentinels * 4: optional: Template (MEASUREMENT) * 5: optional: AuxHeader (no sentinels, since R13c3) */ - for (j = 0; j < dwg->header.num_sections; j++) + for (j = 0; j < dwg->header.sections; j++) { dwg->header.section[j].number = (BITCODE_RLd)bit_read_RC (dat); dwg->header.section[j].address = (BITCODE_RLL)bit_read_RL (dat); diff --git a/src/dwg.c b/src/dwg.c index 20a793c898..376b374e89 100644 --- a/src/dwg.c +++ b/src/dwg.c @@ -3378,7 +3378,8 @@ dwg_sections_init (Dwg_Data *dwg) /* section 0: header vars * 1: class section * 2: object map (i.e. handles) - * 3: optional ObjFreeSpace (r13+, no sentinels) + 2ndheader (r13+, sentinels) + * 3: optional ObjFreeSpace (r13c3+, no sentinels) + * 7: 2ndheader (not a section, r13+, sentinels) * 4: optional: Template (MEASUREMENT) * 5: optional: AuxHeader (no sentinels, since R_2000b) * 6: optional: THUMBNAIL (not a section, but treated as one) @@ -3386,22 +3387,27 @@ dwg_sections_init (Dwg_Data *dwg) if (!dwg->header.num_sections || (dwg->header.from_version > R_2000 && dwg->header.version <= R_2000)) { - dwg->header.num_sections = dwg->header.version < R_13c3 ? 3 - : dwg->header.version < R_2000b ? 5 - : 6; - if (dwg->header.num_sections == 3 && dwg->objfreespace.numnums) - dwg->header.num_sections = 5; + if (dwg->header.sections) + { + // Plus thumbnail and second header + dwg->header.num_sections = dwg->header.sections + 2; + } + else + { + dwg->header.num_sections = dwg->header.version < R_13c3 ? 5 + : dwg->header.version < R_2000b ? 7 + : 8; + if (dwg->header.num_sections == 5 && dwg->objfreespace.numnums) + dwg->header.num_sections = 6; + } } if (!dwg->header.sections || (dwg->header.from_version > R_2000 && dwg->header.version <= R_2000)) - // ODA writes zeros - dwg->header.sections = dwg->header.num_sections; - // newer DWG's have proper HEADER.sections - if (dwg->header.num_sections != dwg->header.sections) - dwg->header.num_sections = dwg->header.sections; + // ODA writes zeros + dwg->header.sections = dwg->header.num_sections - 2; } LOG_TRACE ("num_sections => " FORMAT_RL "\n", dwg->header.num_sections); - if (dwg->header.num_sections < 3) + if (dwg->header.num_sections < 5) { LOG_ERROR ("Not enough sections: " FORMAT_RL, dwg->header.num_sections); return DWG_ERR_INVALIDDWG; @@ -3413,13 +3419,13 @@ dwg_sections_init (Dwg_Data *dwg) } if (dwg->header.section) - // zero-based, including THUMBNAIL + // zero-based, including THUMBNAIL and Second Header dwg->header.section = (Dwg_Section *)realloc ( dwg->header.section, - sizeof (Dwg_Section) * (dwg->header.num_sections + 2)); + sizeof (Dwg_Section) * (dwg->header.num_sections)); else dwg->header.section = (Dwg_Section *)calloc (sizeof (Dwg_Section), - dwg->header.num_sections + 2); + dwg->header.num_sections); if (!dwg->header.section) { LOG_ERROR ("Out of memory"); diff --git a/src/encode.c b/src/encode.c index 9f7bf4a80c..ce87ecf794 100644 --- a/src/encode.c +++ b/src/encode.c @@ -85,7 +85,7 @@ static BITCODE_BL rcount1 = 0, rcount2 = 0; /* section_order: A static array of section types. SECTION_R13_SIZE is the size and the sentinel. */ -#define SECTION_R13_SIZE 7U +#define SECTION_R13_SIZE 8U static Dwg_Section_Type_r13 section_order[SECTION_R13_SIZE] = { 0 }; #ifdef USE_TRACING @@ -1996,7 +1996,7 @@ find_section_info_type (const Dwg_Data *restrict dwg, Dwg_Section_Type type) return NULL; } -/* Ordering of r13-r2000 sections 0-6 */ +/* Ordering of r13-r2000 sections 0-7 */ static void section_order_trace (const Dwg_Data *dwg, const BITCODE_BL numsections, @@ -3066,22 +3066,16 @@ encode_objects_handles (Dwg_Data *restrict dwg, Bit_Chain *restrict dat, } static int -encode_objfreespace_2ndheader (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) +encode_objfreespace (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) { int error = 0; - BITCODE_BL i; - size_t pvzadr; /*------------------------------------------------------------ - * ObjFreeSpace and Second header - r13-r2000 only. - * Note: partially also since r2004. + * ObjFreeSpace - r13c3-r2000 only. */ if (dwg->header.version >= R_13 && dwg->header.version < R_2004 && dwg->header.num_sections >= 3) { - struct _dwg_secondheader *_obj = &dwg->secondheader; - Dwg_Object *obj = NULL; - assert (dat->byte); dwg->header.section[SECTION_OBJFREESPACE_R13].number = 3; if (dwg->objfreespace.numnums) @@ -3094,6 +3088,26 @@ encode_objfreespace_2ndheader (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) LOG_INFO ("=======> ObjFreeSpace 3 (end): %4u\n", (unsigned)dat->byte); } + } + + return error; +} + +static int +encode_2ndheader (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) +{ + int error = 0; + BITCODE_BL i; + size_t pvzadr; + + /*------------------------------------------------------------ + * Second Header - r13-r2000 only. + */ + if (dwg->header.version >= R_13 && dwg->header.version < R_2004 + && dwg->header.num_sections >= 3) + { + struct _dwg_secondheader *_obj = &dwg->secondheader; + Dwg_Object *obj = NULL; LOG_INFO ("\n=======> Second Header: %4zu\n", dat->byte + 16); write_sentinel (dat, DWG_SENTINEL_2NDHEADER_BEGIN); @@ -3715,15 +3729,15 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) THUMBNAIL * 2: Handles * 3: ObjFreeSpace (r13c3+, optional) - + 2NDHEADER (r13-r2000) + * 7: 2NDHEADER (r13-r2000, not a section) * 4: Template (r14-r2000, optional) * 5: AuxHeader (r2000, no sentinels) * 6: THUMBNAIL (r13c3+, not a section) */ - /* Usually 3-5, max 6 */ + /* Usually 5-7, max 8 */ if (!dwg->header.num_sections - || (dat->from_version >= R_2004 && dwg->header.num_sections > 6)) + || (dat->from_version >= R_2004 && dwg->header.num_sections > 8)) { if (dwg->header.version <= R_2000) { @@ -3732,11 +3746,11 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) else dwg->header.num_sections = dwg->auxheader.dwg_version && dwg->header.version == R_2000 - ? 6 - : 5; + ? 7 + : 6; } else - dwg->header.num_sections = 6; + dwg->header.num_sections = 7; // minimal DXF: // if (dwg->opts & (DWG_OPTS_INDXF | DWG_OPTS_MINIMAL) // && (!dwg->header_vars.HANDSEED || @@ -3766,19 +3780,23 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) if (dwg->header.sections > 3) { section_order[3] = SECTION_OBJFREESPACE_R13; - section_order[4] = SECTION_TEMPLATE_R13; + section_order[4] = SECTION_SECOND_HEADER_R13; + section_order[5] = SECTION_TEMPLATE_R13; if (dwg->header.sections > 5) { - section_order[5] = SECTION_AUXHEADER_R2000; - section_order[6] = SECTION_THUMBNAIL_R13; + section_order[6] = SECTION_AUXHEADER_R2000; + section_order[7] = SECTION_THUMBNAIL_R13; } else { - section_order[5] = SECTION_THUMBNAIL_R13; + section_order[6] = SECTION_THUMBNAIL_R13; } } else - section_order[3] = SECTION_THUMBNAIL_R13; + { + section_order[3] = SECTION_THUMBNAIL_R13; + section_order[4] = SECTION_SECOND_HEADER_R13; + } if (DWG_LOGLEVEL >= DWG_LOGLEVEL_TRACE) section_order_trace (dwg, dwg->header.num_sections, @@ -3894,20 +3912,10 @@ dwg_encode (Dwg_Data *restrict dwg, Bit_Chain *restrict dat) error |= encode_objects_handles (dwg, dat, (Bit_Chain **)&sec_dat); break; case SECTION_OBJFREESPACE_R13: - { - int err1; - pvzadr = dat->byte; - err1 = encode_objfreespace_2ndheader (dwg, dat); - /* - if (err1 & 1) - { - LOG_TRACE ("2ndheader size changed, rewrite it\n") - dat->byte = pvzadr; - err1 = encode_objfreespace_2ndheader (dwg, dat); - } - */ - error |= err1; - } + error |= encode_objfreespace (dwg, dat); + break; + case SECTION_SECOND_HEADER_R13: + error |= encode_2ndheader (dwg, dat); break; case SECTION_TEMPLATE_R13: error |= encode_template (dwg, dat);