/* -*- 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 #include #include #include #include #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(len1, 1024) / sizeof(hchar); uint const len2_ = std::min(len2, 1024) / sizeof(hchar); uint const len3_ = std::min(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(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(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(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 pArr(new TCell*[ncell]); std::fill(pArr.get(), pArr.get() + ncell, nullptr); if (!pArr) { return hwpf.SetState(HWP_InvalidFileFormat); } std::unique_ptr 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 m_xNewMem; public: ChangeMemGuard(unsigned char* data, size_t nLen) : m_pOldMem(hmem) , m_xNewMem(std::make_unique(reinterpret_cast(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) { SAL_WARN("filter.hwp", "too much decompression, abandoning"); follow.clear(); return false; } } follow_block_size = follow.size(); if (pictype == PICTYPE_DRAW) { auto xGuard(std::make_unique(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(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: */