summaryrefslogtreecommitdiffstats
path: root/hwpfilter/source/hwpread.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'hwpfilter/source/hwpread.cxx')
-rw-r--r--hwpfilter/source/hwpread.cxx930
1 files changed, 930 insertions, 0 deletions
diff --git a/hwpfilter/source/hwpread.cxx b/hwpfilter/source/hwpread.cxx
new file mode 100644
index 000000000..a77f380b5
--- /dev/null
+++ b/hwpfilter/source/hwpread.cxx
@@ -0,0 +1,930 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "precompile.h"
+
+#include <comphelper/newarray.hxx>
+#include <unotools/configmgr.hxx>
+#include <tools/long.hxx>
+
+#include <assert.h>
+
+#include "hwpfile.h"
+#include "hbox.h"
+#include "hpara.h"
+#include "drawing.h"
+#include "htags.h"
+#include "hcode.h"
+
+static short fboxnum = 1;
+static int zindex = 1;
+static int lnnumber = 0;
+
+bool HBox::Read(HWPFile & )
+{
+ // already read
+ return true;
+}
+
+// skip block
+bool SkipData::Read(HWPFile & hwpf)
+{
+ uint data_block_len;
+ hwpf.Read4b(data_block_len);
+
+ hchar dummy;
+ if (!hwpf.Read2b(dummy))
+ return hwpf.SetState(HWP_InvalidFileFormat);
+
+ if (!(IS_SP_SKIP_BLOCK(hh) && (hh == dummy))){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ return hwpf.SkipBlock(data_block_len);
+}
+
+// Field code(5)
+bool FieldCode::Read(HWPFile & hwpf)
+{
+ uint size;
+ hchar dummy;
+ uint len1; /* Length of hchar type string DATA #1 */
+ uint len2; /* Length of hchar type string DATA #2 */
+ uint len3; /* Length of hchar type string DATA #3 */
+ uint binlen; /* Length of any binary data format */
+
+ hwpf.Read4b(size);
+ if (!hwpf.Read2b(dummy))
+ return false;
+ hwpf.ReadBlock(&type, 2);
+ hwpf.ReadBlock(reserved1.data(), 4);
+ if (!hwpf.Read2b(location_info))
+ return false;
+ hwpf.ReadBlock(reserved2.data(), 22);
+ hwpf.Read4b(len1);
+ hwpf.Read4b(len2);
+ hwpf.Read4b(len3);
+ if (!hwpf.Read4b(binlen))
+ return false;
+
+ uint const len1_ = std::min<uint>(len1, 1024) / sizeof(hchar);
+ uint const len2_ = std::min<uint>(len2, 1024) / sizeof(hchar);
+ uint const len3_ = std::min<uint>(len3, 1024) / sizeof(hchar);
+
+ str1.reset( new hchar[len1_ ? len1_ : 1] );
+ str2.reset( new hchar[len2_ ? len2_ : 1] );
+ str3.reset( new hchar[len3_ ? len3_ : 1] );
+
+ if (hwpf.Read2b(str1.get(), len1_) != len1_)
+ return false;
+ hwpf.SkipBlock(len1 - (len1_ * sizeof(hchar)));
+ str1[len1_ ? (len1_ - 1) : 0] = 0;
+ if (hwpf.Read2b(str2.get(), len2_) != len2_)
+ return false;
+ hwpf.SkipBlock(len2 - (len2_ * sizeof(hchar)));
+ str2[len2_ ? (len2_ - 1) : 0] = 0;
+ if (hwpf.Read2b(str3.get(), len3_) != len3_)
+ return false;
+ hwpf.SkipBlock(len3 - (len3_ * sizeof(hchar)));
+ str3[len3_ ? (len3_ - 1) : 0] = 0;
+
+ hwpf.SkipBlock(binlen);
+
+ if( type[0] == 3 && type[1] == 2 ){ /* It must create a format as created date. */
+ DateCode *pDate = new DateCode;
+ for (uint i = 0 ; i < len3_; i++) {
+ if(str3[i] == 0 ) break;
+ if( i >= DATE_SIZE ) break;
+ pDate->format[i] = str3[i];
+ }
+ hwpf.AddDateFormat(pDate);
+ m_pDate.reset( pDate );
+ }
+
+ return true;
+}
+
+// book mark(6)
+bool Bookmark::Read(HWPFile & hwpf)
+{
+ uint len;
+
+ hwpf.Read4b(len);
+ if (!hwpf.Read2b(dummy))
+ return false;
+
+ if (len != 34)// 2 * (BMK_COMMENT_LEN + 1) + 2
+ {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ if (hh != dummy || dummy != CH_BOOKMARK) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ hwpf.Read2b(id, BMK_COMMENT_LEN + 1);
+ hwpf.Read2b(&type, 1);
+ return true;
+}
+
+// date format(7)
+bool DateFormat::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(format, DATE_SIZE);
+ if (!hwpf.Read2b(dummy))
+ return false;
+ if (hh != dummy || CH_DATE_FORM != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return true;
+}
+
+// date code(8)
+bool DateCode::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(format, DATE_SIZE);
+ hwpf.Read2b(date, 6);
+ if (!hwpf.Read2b(dummy))
+ return false;
+ if (hh != dummy || CH_DATE_CODE != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ hwpf.AddDateFormat(this);
+ return true;
+}
+
+// tab(9)
+bool Tab::Read(HWPFile & hwpf)
+{
+ unsigned short tmp16;
+ if (!hwpf.Read2b(tmp16))
+ return false;
+ width = tmp16;
+ if (!hwpf.Read2b(leader))
+ return false;
+ if (!hwpf.Read2b(dummy))
+ return false;
+ if (hh != dummy || CH_TAB != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return true;
+}
+
+// tbox(10) TABLE BOX MATH BUTTON HYPERTEXT
+static void UpdateBBox(FBox * fbox)
+{
+ fbox->boundsy = fbox->pgy;
+ fbox->boundey = fbox->pgy + fbox->ys - 1;
+}
+
+bool Cell::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&p, 1);
+ hwpf.Read2b(&color, 1);
+ hwpf.Read2b(&x, 1);
+ hwpf.Read2b(&y, 1);
+ hwpf.Read2b(&w, 1);
+ hwpf.Read2b(&h, 1);
+ hwpf.Read2b(&txthigh, 1);
+ hwpf.Read2b(&cellhigh, 1);
+
+ hwpf.Read1b(flag);
+ hwpf.Read1b(changed);
+ hwpf.Read1b(used);
+ hwpf.Read1b(ver_align);
+ hwpf.ReadBlock(linetype, 4);
+ hwpf.Read1b(shade);
+ hwpf.Read1b(diagonal);
+ return hwpf.Read1b(protect);
+}
+
+bool TxtBox::Read(HWPFile & hwpf)
+{
+ int ii, ncell;
+
+ hwpf.Read2b(reserved, 2);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy || CH_TEXT_BOX != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ hwpf.Read2b(&style.cap_len, 1);
+ hwpf.Read2b(&dummy1, 1);
+ unsigned short next;
+ hwpf.Read2b(&next, 1);
+ hwpf.Read2b(&dummy2, 1);
+
+ style.boxnum = fboxnum++;
+ zorder = zindex++;
+ hwpf.Read1b(style.anchor_type);
+ hwpf.Read1b(style.txtflow);
+ hwpf.Read2b(&style.xpos, 1);
+ hwpf.Read2b(&style.ypos, 1);
+ hwpf.Read2b(&option, 1);
+ hwpf.Read2b(&ctrl_ch, 1);
+ hwpf.Read2b(style.margin, 12);
+ hwpf.Read2b(&box_xs, 1);
+ hwpf.Read2b(&box_ys, 1);
+ hwpf.Read2b(&cap_xs, 1);
+ hwpf.Read2b(&cap_ys, 1);
+ hwpf.Read2b(&style.cap_len, 1);
+ hwpf.Read2b(&xs, 1);
+ hwpf.Read2b(&ys, 1);
+ hwpf.Read2b(&cap_margin, 1);
+ hwpf.Read1b(xpos_type);
+ hwpf.Read1b(ypos_type);
+ hwpf.Read1b(smart_linesp);
+ hwpf.Read1b(reserved1);
+ hwpf.Read2b(&pgx, 1);
+ hwpf.Read2b(&pgy, 1);
+ hwpf.Read2b(&pgno, 1);
+ if( ( pgno +1 ) != hwpf.getCurrentPage() )
+ pgno = sal::static_int_cast<short>(hwpf.getCurrentPage() -1) ;
+
+ hwpf.Read2b(&showpg, 1);
+ hwpf.Read2b(&cap_pos, 1);
+ hwpf.Read2b(&num, 1);
+ hwpf.Read2b(&dummy3, 1);
+ hwpf.Read2b(&baseline, 1);
+ hwpf.Read2b(&type, 1);
+ hwpf.Read2b(&nCell, 1);
+ hwpf.Read2b(&protect, 1);
+ switch (type)
+ {
+ case 0: //table
+ style.boxtype = 'T';
+ break;
+ case 1: // text-box
+ style.boxtype = 'X';
+ break;
+ case 2: // equation
+ style.boxtype = 'E';
+ break;
+ case 3: // button
+ style.boxtype = 'B';
+ break;
+ default: // other
+ style.boxtype = 'O';
+ break;
+ }
+
+ UpdateBBox(this);
+
+ ncell = nCell;
+ if (ncell <= 0) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ if (ncell > 4096 && utl::ConfigManager::IsFuzzing()) {
+ // cut off at an arbitrary size to speed up fuzzing
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ cell.reset( ::comphelper::newArray_null<Cell>(ncell) );
+ if (!cell) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ bool bSuccess = true;
+ for (ii = 0; ii < ncell && bSuccess; ii++)
+ {
+ bSuccess = cell[ii].Read(hwpf);
+ cell[ii].key = sal::static_int_cast<unsigned char>(ii);
+ }
+ if (!bSuccess)
+ return false;
+ if (ncell == 1)
+ style.cell = &cell[0];
+ plists.resize(ncell);
+ for (ii = 0; ii < ncell; ii++)
+ hwpf.ReadParaList(plists[ii]);
+ // caption
+ hwpf.ReadParaList(caption);
+
+ if( type == 0 ){ // if table?
+ std::unique_ptr<TCell*[]> pArr(new TCell*[ncell]);
+ std::fill(pArr.get(), pArr.get() + ncell, nullptr);
+ if (!pArr) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ std::unique_ptr<Table> tbl(new Table);
+ for( ii = 0 ; ii < ncell; ii++)
+ {
+ tbl->columns.insert(cell[ii].x);
+ tbl->columns.insert(cell[ii].x + cell[ii].w);
+ tbl->rows.insert(cell[ii].y);
+ tbl->rows.insert(cell[ii].y + cell[ii].h);
+ }
+ for( ii = 0 ; ii < ncell; ii++)
+ {
+ TCell *tcell = new TCell;
+ tcell->nColumnIndex = tbl->columns.getIndex(cell[ii].x);
+ tcell->nColumnSpan = tbl->columns.getIndex(cell[ii].x + cell[ii].w) -
+ tcell->nColumnIndex;
+ tcell->nRowIndex = tbl->rows.getIndex(cell[ii].y);
+ tcell->nRowSpan = tbl->rows.getIndex(cell[ii].y + cell[ii].h) -
+ tcell->nRowIndex;
+ tcell->pCell = &cell[ii];
+ pArr[ii] = tcell;
+ }
+
+ // Sort by row and column
+ for( ii = 0 ; ii < ncell - 1; ii++ ){
+ for( int jj = ii ; jj < ncell ; jj++){
+ if( pArr[ii]->nRowIndex > pArr[jj]->nRowIndex ){
+ std::swap(pArr[ii], pArr[jj]);
+ }
+ }
+ for( int kk = ii ; kk > 0 ; kk--){
+ if( ( pArr[kk]->nRowIndex == pArr[kk-1]->nRowIndex ) &&
+ (pArr[kk]->nColumnIndex < pArr[kk-1]->nColumnIndex )){
+ std::swap(pArr[kk], pArr[kk-1]);
+ }
+ }
+ }
+ for( ii = 0 ; ii < ncell ; ii++ ){
+ tbl->cells.emplace_back(pArr[ii]);
+ }
+ tbl->box = this;
+ m_pTable = tbl.get();
+ hwpf.AddTable(std::move(tbl));
+ }
+ else
+ m_pTable = nullptr;
+
+ bSuccess = !hwpf.State();
+ if (bSuccess)
+ hwpf.AddFBoxStyle(&style);
+ return bSuccess;
+}
+
+namespace
+{
+ class ChangeMemGuard
+ {
+ private:
+ HIODev* m_pOldMem;
+ std::unique_ptr<HMemIODev> m_xNewMem;
+ public:
+ ChangeMemGuard(unsigned char* data, size_t nLen)
+ : m_pOldMem(hmem)
+ , m_xNewMem(std::make_unique<HMemIODev>(reinterpret_cast<char*>(data), nLen))
+ {
+ hmem = m_xNewMem.get();
+ }
+ ~ChangeMemGuard()
+ {
+ assert(hmem == m_xNewMem.get());
+ hmem = m_pOldMem;
+ }
+ };
+}
+
+// picture(11)
+bool Picture::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(reserved, 2);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy || CH_PICTURE != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ hwpf.Read4b(follow_block_size);
+
+ //when fuzzing with a max len set, max decompress to 10 times that limit
+ static size_t nMaxAllowedDecompression = [](const char* pEnv) { size_t nRet = pEnv ? std::atoi(pEnv) : 0; return nRet * 10; }(std::getenv("FUZZ_MAX_INPUT_LEN"));
+
+ hwpf.Read2b(&dummy1, 1); /* Reserved 4 bytes */
+ hwpf.Read2b(&dummy2, 1);
+
+ style.boxnum = fboxnum++;
+ zorder = zindex++;
+ hwpf.Read1b(style.anchor_type); /* Reference position */
+ hwpf.Read1b(style.txtflow); /* Avoid painting. 0-2 (seat occupied, transparency, harmony) */
+ hwpf.Read2b(&style.xpos, 1); /* Horizontal position: 1=left, 2=right, 3=center, and others=any */
+ hwpf.Read2b(&style.ypos, 1); /* Vertical position: 1=top, 2=down, 3=middle, and others=any */
+ hwpf.Read2b(&option, 1); /* Other options: Borders, reverse picture, and so on. Save as bit. */
+ hwpf.Read2b(&ctrl_ch, 1); /* Always 11 */
+ hwpf.Read2b(style.margin, 12); /* Margin: [0-2] [] out / in / cell, [], [0-3] left / right / top / bottom margins */
+ hwpf.Read2b(&box_xs, 1); /* Box Size Width */
+ hwpf.Read2b(&box_ys, 1); /* Vertical */
+ hwpf.Read2b(&cap_xs, 1); /* Caption Size Width */
+ hwpf.Read2b(&cap_ys, 1); /* Vertical */
+ hwpf.Read2b(&style.cap_len, 1); /* Length */
+ hwpf.Read2b(&xs, 1); /* The total size (box size + caption + margin) Horizontal */
+ hwpf.Read2b(&ys, 1); /* Vertical */
+ hwpf.Read2b(&cap_margin, 1); /* Caption margins */
+ hwpf.Read1b(xpos_type);
+ hwpf.Read1b(ypos_type);
+ hwpf.Read1b(smart_linesp); /* Line Spacing protection: 0 unprotected 1 protected */
+ hwpf.Read1b(reserved1);
+ hwpf.Read2b(&pgx, 1); /* Real Calculated box width */
+ hwpf.Read2b(&pgy, 1); /* Height */
+ hwpf.Read2b(&pgno, 1); /* Page number: starts from 0 */
+ hwpf.Read2b(&showpg, 1); /* Show the Box */
+ hwpf.Read2b(&cap_pos, 1); /* Caption positions 0-7 Menu Order. */
+ hwpf.Read2b(&num, 1); /* Box number, serial number which starts from 0 */
+
+ hwpf.Read1b(pictype); /* Picture type */
+
+ unsigned short tmp16;
+ if (!hwpf.Read2b(tmp16)) /* the real horizontal starting point where shows the picture */
+ return false;
+ skip[0] = tmp16;
+ if (!hwpf.Read2b(tmp16)) /* Vertical */
+ return false;
+ skip[1] = tmp16;
+ if (!hwpf.Read2b(tmp16)) /* Zoom Ratio: 0:fixed, others are percentage for horizontal */
+ return false;
+ scale[0] = tmp16;
+ if (!hwpf.Read2b(tmp16)) /* Vertical */
+ return false;
+ scale[1] = tmp16;
+
+ hwpf.ReadBlock(picinfo.picun.path, 256); /* Picture File Name: when type is not a Drawing. */
+ picinfo.picun.path[255] = 0; // ensure null terminated
+ hwpf.ReadBlock(reserved3, 9); /* Brightness / Contrast / Picture Effect, etc. */
+
+ UpdateBBox(this);
+ if( pictype != PICTYPE_DRAW )
+ style.cell = reserved3;
+ else
+ {
+ //picinfo.picun read above is unioned with
+ //picinfo.picdraw and so wrote to the hdo pointer
+ //value, which is definitely not useful to us
+ picinfo.picdraw.hdo = nullptr;
+ }
+
+ if (follow_block_size != 0)
+ {
+ follow.clear();
+
+ //read potentially compressed data in blocks as it's more
+ //likely large values are simply broken and we'll run out
+ //of data before we need to realloc
+ for (size_t i = 0; i < follow_block_size; i+= SAL_N_ELEMENTS(hwpf.scratch))
+ {
+ size_t nOldSize = follow.size();
+ size_t nBlock = std::min(SAL_N_ELEMENTS(hwpf.scratch), follow_block_size - nOldSize);
+ size_t nReadBlock = hwpf.ReadBlock(hwpf.scratch, nBlock);
+ if (nReadBlock)
+ {
+ follow.insert(follow.end(), hwpf.scratch, hwpf.scratch + nReadBlock);
+ }
+ if (nBlock != nReadBlock)
+ break;
+ if (nMaxAllowedDecompression && follow.size() > nMaxAllowedDecompression)
+ break;
+ }
+ follow_block_size = follow.size();
+
+ if (pictype == PICTYPE_DRAW)
+ {
+ auto xGuard(std::make_unique<ChangeMemGuard>(follow.data(), follow_block_size));
+ LoadDrawingObjectBlock(this, hwpf);
+ style.cell = picinfo.picdraw.hdo;
+ xGuard.reset();
+ }
+ else if (follow_block_size >= 4)
+ {
+ if ((follow[3] << 24 | follow[2] << 16 | follow[1] << 8 | follow[0]) == 0x269)
+ {
+ ishyper = true;
+ }
+ }
+ }
+
+ if( pictype != 3 )
+ style.boxtype = 'G';
+ else
+ style.boxtype = 'D';
+
+// caption
+ hwpf.ReadParaList(caption);
+
+ bool bSuccess = !hwpf.State();
+ if (bSuccess)
+ hwpf.AddFBoxStyle(&style);
+ return bSuccess;
+}
+
+// line(15)
+Line::Line()
+ : FBox(CH_LINE)
+ , dummy(0)
+ , sx(0)
+ , sy(0)
+ , ex(0)
+ , ey(0)
+ , width(0)
+ , shade(0)
+ , color(0)
+{
+}
+
+bool Line::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(reserved, 2);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy || CH_LINE != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ style.boxnum = fboxnum++;
+ zorder = zindex++;
+ style.boxtype = 'L';
+ hwpf.ReadBlock(&reserved2, 8);
+ hwpf.Read1b(style.anchor_type);
+ hwpf.Read1b(style.txtflow);
+ hwpf.Read2b(&style.xpos, 1);
+ hwpf.Read2b(&style.ypos, 1);
+ hwpf.Read2b(&option, 1);
+ hwpf.Read2b(&ctrl_ch, 1);
+ hwpf.Read2b(style.margin, 12);
+ hwpf.Read2b(&box_xs, 1);
+ hwpf.Read2b(&box_ys, 1);
+ hwpf.Read2b(&cap_xs, 1);
+ hwpf.Read2b(&cap_ys, 1);
+ hwpf.Read2b(&style.cap_len, 1);
+ hwpf.Read2b(&xs, 1);
+ hwpf.Read2b(&ys, 1);
+ lnnumber = style.boxnum;
+ hwpf.linenumber = 1;
+ hwpf.Read2b(&boundsy, 1);
+ hwpf.Read2b(&boundey, 1);
+ hwpf.Read1b(boundx);
+ hwpf.Read1b(draw);
+
+ hwpf.Read2b(&pgx, 1);
+ hwpf.Read2b(&pgy, 1);
+ hwpf.Read2b(&pgno, 1);
+ hwpf.Read2b(&showpg, 1);
+
+ hwpf.Read2b(&sx, 1);
+ hwpf.Read2b(&sy, 1);
+ hwpf.Read2b(&ex, 1);
+ hwpf.Read2b(&sy, 1);
+ hwpf.Read2b(&width, 1);
+ hwpf.Read2b(&shade, 1);
+ hwpf.Read2b(&color, 1);
+ style.xpos = width;
+
+ bool bSuccess = !hwpf.State();
+ if (bSuccess)
+ hwpf.AddFBoxStyle(&style);
+ return bSuccess;
+}
+
+// hidden(15)
+Hidden::Hidden()
+ : HBox(CH_HIDDEN)
+ , dummy(0)
+{
+}
+
+bool Hidden::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(reserved, 2);
+ hwpf.Read2b(&dummy, 1);
+ if (hh != dummy || CH_HIDDEN != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ hwpf.ReadBlock(info, 8);
+ hwpf.ReadParaList(plist);
+
+ return !hwpf.State();
+}
+
+// header/footer(16)
+HeaderFooter::HeaderFooter()
+ : HBox(CH_HEADER_FOOTER)
+ , dummy(0)
+ , type(0)
+ , where(0)
+ , linenumber(0)
+ , m_nPageNumber(0)
+{
+}
+
+bool HeaderFooter::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(reserved, 2);
+ hwpf.Read2b(&dummy, 1);
+ if (hh != dummy || CH_HEADER_FOOTER != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ hwpf.ReadBlock(info, 8);
+ hwpf.Read1b(type);
+ hwpf.Read1b(where);
+ lnnumber = 0;
+ hwpf.ReadParaList(plist, CH_HEADER_FOOTER);
+ linenumber = sal::static_int_cast<unsigned char>(lnnumber);
+ m_nPageNumber = hwpf.getCurrentPage();
+ hwpf.setMaxSettedPage();
+ hwpf.AddHeaderFooter(this);
+
+ return !hwpf.State();
+}
+
+
+// footnote(17)
+Footnote::Footnote()
+ : HBox(CH_FOOTNOTE)
+ , dummy(0)
+ , number(0)
+ , type(0)
+ , width(0)
+{
+}
+
+bool Footnote::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(reserved, 2);
+ hwpf.Read2b(&dummy, 1);
+ if (hh != dummy || CH_FOOTNOTE != dummy) {
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+
+ hwpf.ReadBlock(info, 8);
+ hwpf.Read2b(&number, 1);
+ hwpf.Read2b(&type, 1);
+ unsigned short tmp16;
+ if (!hwpf.Read2b(tmp16))
+ return false;
+ width = tmp16;
+ hwpf.ReadParaList(plist, CH_FOOTNOTE);
+
+ return !hwpf.State();
+}
+
+// auto number(18)
+AutoNum::AutoNum()
+ : HBox(CH_AUTO_NUM)
+ , type(0)
+ , number(0)
+ , dummy(0)
+{
+}
+
+bool AutoNum::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&type, 1);
+ hwpf.Read2b(&number, 1);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+
+// new number(19)
+NewNum::NewNum()
+ : HBox(CH_NEW_NUM)
+ , type(0)
+ , number(0)
+ , dummy(0)
+{
+}
+
+
+bool NewNum::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&type, 1);
+ hwpf.Read2b(&number, 1);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+// show page number (20)
+ShowPageNum::ShowPageNum()
+ : HBox(CH_SHOW_PAGE_NUM)
+ , where(0)
+ , m_nPageNumber(0)
+ , shape(0)
+ , dummy(0)
+{
+}
+
+bool ShowPageNum::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&where, 1);
+ hwpf.Read2b(&shape, 1);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ m_nPageNumber = hwpf.getCurrentPage();
+ hwpf.setMaxSettedPage();
+ hwpf.AddPageNumber(this);
+ return !hwpf.State();
+}
+
+/* 홀수쪽시작/감추기 (21) */
+PageNumCtrl::PageNumCtrl()
+ : HBox(CH_PAGE_NUM_CTRL)
+ , kind(0)
+ , what(0)
+ , dummy(0)
+{
+}
+
+bool PageNumCtrl::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&kind, 1);
+ hwpf.Read2b(&what, 1);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+// mail merge(22)
+MailMerge::MailMerge()
+ : HBox(CH_MAIL_MERGE)
+ , dummy(0)
+{
+}
+
+bool MailMerge::Read(HWPFile & hwpf)
+{
+ hwpf.ReadBlock(field_name, 20);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+// char composition(23)
+Compose::Compose()
+ : HBox(CH_COMPOSE)
+ , dummy(0)
+{
+}
+
+bool Compose::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(compose, 3);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+// hyphen(24)
+Hyphen::Hyphen()
+ : HBox(CH_HYPHEN)
+ , width(0)
+ , dummy(0)
+{
+}
+
+bool Hyphen::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&width, 1);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+
+// toc mark(25)
+TocMark::TocMark()
+ : HBox(CH_TOC_MARK)
+ , kind(0)
+ , dummy(0)
+{
+}
+
+
+bool TocMark::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&kind, 1);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+// index mark(26)
+IndexMark::IndexMark()
+ : HBox(CH_INDEX_MARK)
+ , pgno(0)
+ , dummy(0)
+{
+}
+
+bool IndexMark::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&keyword1, 60);
+ hwpf.Read2b(&keyword2, 60);
+ hwpf.Read2b(&pgno, 1);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+// outline(28)
+Outline::Outline()
+ : HBox(CH_OUTLINE)
+ , kind(0)
+ , shape(0)
+ , level(0)
+ , dummy(0)
+{
+}
+
+bool Outline::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&kind, 1);
+ hwpf.Read1b(shape);
+ hwpf.Read1b(level);
+ hwpf.Read2b(number, 7);
+ hwpf.Read2b(user_shape, 7);
+ hwpf.Read2b(deco, 14);
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+
+/* Bundle of spaces (30)*/
+KeepSpace::KeepSpace()
+ : HBox(CH_KEEP_SPACE)
+ , dummy(0)
+{
+}
+
+
+bool KeepSpace::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+
+/* Fixed-width spaces (31) */
+FixedSpace::FixedSpace()
+ : HBox(CH_FIXED_SPACE)
+ , dummy(0)
+{
+}
+
+
+bool FixedSpace::Read(HWPFile & hwpf)
+{
+ hwpf.Read2b(&dummy, 1);
+
+ if (hh != dummy){
+ return hwpf.SetState(HWP_InvalidFileFormat);
+ }
+ return !hwpf.State();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */