/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */ /* libmwaw * Version: MPL 2.0 / LGPLv2+ * * The contents of this file are subject to the Mozilla Public License Version * 2.0 (the "License"); you may not use this file except in compliance with * the License or as specified alternatively below. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * Major Contributor(s): * Copyright (C) 2002 William Lachance (wrlach@gmail.com) * Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net) * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch) * Copyright (C) 2006, 2007 Andrew Ziem * Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr) * * * All Rights Reserved. * * For minor contributions see the git repository. * * Alternatively, the contents of this file may be used under the terms of * the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"), * in which case the provisions of the LGPLv2+ are applicable * instead of those above. */ #include #include #include #include #include #include #include "MWAWTextListener.hxx" #include "MWAWFont.hxx" #include "MWAWFontConverter.hxx" #include "MWAWHeader.hxx" #include "MWAWParagraph.hxx" #include "MWAWPictMac.hxx" #include "MWAWPosition.hxx" #include "MWAWPrinter.hxx" #include "MWAWRSRCParser.hxx" #include "MWAWSubDocument.hxx" #include "MouseWrtParser.hxx" /** Internal: the structures of a MouseWrtParser */ namespace MouseWrtParserInternal { //////////////////////////////////////// //! Internal: class to store zone information of a MouseWrtParser struct Zone { //! constructor Zone() : m_font() , m_writingHebrew(false) , m_text() { } //! the font MWAWFont m_font; //! flag to know if the writing is reverted bool m_writingHebrew; //! the text entry MWAWEntry m_text; }; //////////////////////////////////////// //! Internal: class to store paragraph information of a MouseWrtParser struct Paragraph { //! constructor explicit Paragraph(int id=0) : m_id(id) , m_paragraph() , m_picture(false) { } //! the paragraph id int m_id; //! the paragraph MWAWParagraph m_paragraph; //! flag to know if this is a picture bool m_picture; }; //////////////////////////////////////// //! Internal: the state of a MouseWrtParser struct State { //! constructor State() : m_actPage(0) , m_numPages(0) , m_charPLCMap() , m_paraPLCMap() , m_text() { for (auto &size : m_blockSizes) size=0; } int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */; /** the first zone's size */ long m_blockSizes[5]; /** the map position to charPLC */ std::map m_charPLCMap; /** the map position to paraPLC */ std::map m_paraPLCMap; /** the main text entry */ MWAWEntry m_text; /** the header and the footer zone */ Zone m_zones[2]; }; //////////////////////////////////////// //! Internal: the subdocument of a MouseWrtParser class SubDocument final : public MWAWSubDocument { public: SubDocument(MouseWrtParser &pars, MWAWInputStreamPtr const &input, int zoneId) : MWAWSubDocument(&pars, input, MWAWEntry()) , m_id(zoneId) { } //! destructor ~SubDocument() final {} //! operator!= bool operator!=(MWAWSubDocument const &doc) const final; //! the parser function void parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType type) final; protected: //! the subdocument id int m_id; }; void SubDocument::parse(MWAWListenerPtr &listener, libmwaw::SubDocumentType /*type*/) { if (!listener.get()) { MWAW_DEBUG_MSG(("MouseWrtParserInternal::SubDocument::parse: no listener\n")); return; } auto *parser=dynamic_cast(m_parser); if (!parser) { MWAW_DEBUG_MSG(("MouseWrtParserInternal::SubDocument::parse: no parser\n")); return; } long pos = m_input->tell(); parser->sendZone(m_id); m_input->seek(pos, librevenge::RVNG_SEEK_SET); } bool SubDocument::operator!=(MWAWSubDocument const &doc) const { if (MWAWSubDocument::operator!=(doc)) return true; auto const *sDoc = dynamic_cast(&doc); if (!sDoc) return true; if (m_id != sDoc->m_id) return true; return false; } } //////////////////////////////////////////////////////////// // constructor/destructor, ... //////////////////////////////////////////////////////////// MouseWrtParser::MouseWrtParser(MWAWInputStreamPtr const &input, MWAWRSRCParserPtr const &rsrcParser, MWAWHeader *header) : MWAWTextParser(input, rsrcParser, header) , m_state(new MouseWrtParserInternal::State) { setAsciiName("main-1"); } MouseWrtParser::~MouseWrtParser() { } //////////////////////////////////////////////////////////// // new page //////////////////////////////////////////////////////////// void MouseWrtParser::newPage(int number) { if (number <= m_state->m_actPage || number > m_state->m_numPages) return; while (m_state->m_actPage < number) { m_state->m_actPage++; if (!getTextListener() || m_state->m_actPage == 1) continue; getTextListener()->insertBreak(MWAWTextListener::PageBreak); } } //////////////////////////////////////////////////////////// // the parser //////////////////////////////////////////////////////////// void MouseWrtParser::parse(librevenge::RVNGTextInterface *docInterface) { if (!getInput().get() || !checkHeader(nullptr)) throw(libmwaw::ParseException()); bool ok = true; try { // create the asciiFile ascii().setStream(getInput()); ascii().open(asciiName()); checkHeader(nullptr); ok=createZones(); if (ok) { createDocument(docInterface); sendMainZone(); } ascii().reset(); } catch (...) { MWAW_DEBUG_MSG(("MouseWrtParser::parse: exception catched when parsing\n")); ok = false; } resetTextListener(); if (!ok) throw(libmwaw::ParseException()); } //////////////////////////////////////////////////////////// // create the document //////////////////////////////////////////////////////////// void MouseWrtParser::createDocument(librevenge::RVNGTextInterface *documentInterface) { if (!documentInterface) return; if (getTextListener()) { MWAW_DEBUG_MSG(("MouseWrtParser::createDocument: listener already exist\n")); return; } // update the page m_state->m_actPage = 0; // create the page list MWAWPageSpan ps(getPageSpan()); m_state->m_numPages=computeNumPages(); ps.setPageSpan(m_state->m_numPages); for (int i=0; i<2; ++i) { if (!m_state->m_zones[i].m_text.valid()) continue; MWAWHeaderFooter hF(i==0 ? MWAWHeaderFooter::HEADER : MWAWHeaderFooter::FOOTER, MWAWHeaderFooter::ALL); hF.m_subDocument.reset(new MouseWrtParserInternal::SubDocument(*this, getInput(), i)); ps.setHeaderFooter(hF); } std::vector pageList; pageList.push_back(ps); // MWAWTextListenerPtr listen(new MWAWTextListener(*getParserState(), pageList, documentInterface)); setTextListener(listen); listen->startDocument(); } //////////////////////////////////////////////////////////// // // Intermediate level // //////////////////////////////////////////////////////////// bool MouseWrtParser::createZones() { MWAWInputStreamPtr input = getInput(); libmwaw::DebugStream f; for (int i=0; i<5; ++i) { if (!m_state->m_blockSizes[i]) continue; long pos = input->tell(); if (m_state->m_blockSizes[i]<0 || !input->checkPosition(pos+m_state->m_blockSizes[i])) { MWAW_DEBUG_MSG(("MouseWrtParser::createZones: the block sizes are wrong\n")); return false; } if (i==1) continue; bool done=false; switch (i) { case 0: done=readCharPLCs(m_state->m_blockSizes[i]); break; case 2: done=readParagraphPLCs(m_state->m_blockSizes[i]); break; case 3: done=m_state->m_blockSizes[i]>=120 && readPrintInfo(); break; case 4: done=readDocumentInfo(m_state->m_blockSizes[i]); break; default: break; } if (done) { if (input->tell()!=pos+m_state->m_blockSizes[i]) ascii().addDelimiter(input->tell(),'|'); } else { f.str(""); f << "Entries(Zone" << i << "):"; ascii().addPos(pos); ascii().addNote(f.str().c_str()); } input->seek(pos+m_state->m_blockSizes[i], librevenge::RVNG_SEEK_SET); } m_state->m_text.setBegin(input->tell()); m_state->m_text.setLength(m_state->m_blockSizes[1]); if (m_state->m_blockSizes[1]<0 || !input->checkPosition(m_state->m_text.end())) { MWAW_DEBUG_MSG(("MouseWrtParser::createZones: can not find the text zone\n")); return false; } if (!input->isEnd()) { ascii().addPos(input->tell()); ascii().addNote("Entries(Unknown):"); } return true; } //////////////////////////////////////////////////////////// // // Low level // //////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////// // read the header //////////////////////////////////////////////////////////// bool MouseWrtParser::checkHeader(MWAWHeader *header, bool strict) { *m_state = MouseWrtParserInternal::State(); MWAWInputStreamPtr input = getInput(); if (!input || !input->hasDataFork()) return false; libmwaw::DebugStream f; f << "FileHeader:"; int headerSize=30; if (!input->checkPosition(headerSize)) { MWAW_DEBUG_MSG(("MouseWrtParser::checkHeader: file is too short\n")); return false; } input->seek(0,librevenge::RVNG_SEEK_SET); if (input->readULong(4)!=0x4474d30 || input->readULong(2)!=0x3400) return false; long totalSize=m_state->m_blockSizes[0]; for (int i=0; i<5; ++i) { m_state->m_blockSizes[i]=long(input->readLong(4)); if (m_state->m_blockSizes[i]<0) return false; char const *wh[]= {"charPlc","text","paraPLC","printer","zone4"}; f << wh[i] << "[sz]=" << m_state->m_blockSizes[i] << ","; totalSize+=m_state->m_blockSizes[i]; } if (totalSize<0 || !input->checkPosition(30+totalSize)) return false; if (strict && ((m_state->m_blockSizes[0]%8)!=0 || (m_state->m_blockSizes[2]%38)!=0 || (m_state->m_blockSizes[3] && m_state->m_blockSizes[3]<120) || (m_state->m_blockSizes[4] && m_state->m_blockSizes[4]<76))) return false; // probably a size, maybe pict size auto dSz=long(input->readLong(4)); if (dSz) { MWAW_DEBUG_MSG(("MouseWrtParser::checkHeader: find some extra size?\n")); f << "##f0=" << dSz << ","; } // ok, we can finish initialization if (header) header->reset(MWAWDocument::MWAW_T_MOUSEWRITE, 1); input->seek(headerSize,librevenge::RVNG_SEEK_SET); ascii().addPos(0); ascii().addNote(f.str().c_str()); ascii().addPos(headerSize); return true; } //////////////////////////////////////////////////////////// // read the basic structure //////////////////////////////////////////////////////////// bool MouseWrtParser::readCharPLCs(long sz) { MWAWInputStreamPtr input = getInput(); long pos = input->tell(); if (sz<0 || (sz%8)!=0 || !input->checkPosition(pos+sz)) { MWAW_DEBUG_MSG(("MouseWrtParser::readCharPLCs: find unexpected size length\n")); return false; } long N=sz/8; libmwaw::DebugStream f; f << "Entries(CharPLC):"; ascii().addPos(pos); ascii().addNote(f.str().c_str()); for (long i=0; itell(); f.str(""); f << "CharPLC-C" << i << ":"; int cPos; MWAWFont font; if (i+1!=N && readFont(font, cPos)) { f << "cPos=" << cPos << "," << font.getDebugString(getParserState()->m_fontConverter); m_state->m_charPLCMap[cPos]=font; } input->seek(pos+8, librevenge::RVNG_SEEK_SET); ascii().addPos(pos); ascii().addNote(f.str().c_str()); } return true; } bool MouseWrtParser::readFont(MWAWFont &font, int &cPos) { MWAWInputStreamPtr input = getInput(); long pos = input->tell(); if (!input->checkPosition(pos+8)) return false; cPos=static_cast(input->readULong(2)); libmwaw::DebugStream f; font=MWAWFont(); auto val=int(input->readULong(1)); if (val) f << "f0=" << val << ","; font.setSize(float(input->readULong(1))); auto flag=static_cast(input->readULong(1)); uint32_t flags=0; if (flag&0x1) flags |= MWAWFont::boldBit; if (flag&0x2) flags |= MWAWFont::italicBit; if (flag&0x4) font.setUnderlineStyle(MWAWFont::Line::Simple); if (flag&0x8) flags |= MWAWFont::embossBit; if (flag&0x10) flags |= MWAWFont::shadowBit; if (flag&0x60) f << "#flag[hi]=" << std::hex << (flag&0x60) << std::dec << ","; font.setFlags(flags); val=static_cast(input->readULong(1)); // 0|7d if (val) f << "f1=" << val << ","; font.setId(static_cast(input->readULong(2))); font.m_extra=f.str().c_str(); return true; } bool MouseWrtParser::readParagraphPLCs(long sz) { MWAWInputStreamPtr input = getInput(); long pos = input->tell(); if (sz<0 || (sz%38)!=0 || !input->checkPosition(pos+sz)) { MWAW_DEBUG_MSG(("MouseWrtParser::readParagraphPLCs: find unexpected size length\n")); return false; } auto N=int(sz/38); libmwaw::DebugStream f; f << "Entries(ParaPLC):"; ascii().addPos(pos); ascii().addNote(f.str().c_str()); for (int i=0; itell(); f.str(""); f << "ParaPLC-P" << i << ":"; if (i+1==N) { // last is sometimes random input->seek(pos+36, librevenge::RVNG_SEEK_SET); auto cPos=static_cast(input->readULong(2)); f << "cPos=" << cPos << ","; input->seek(pos+38, librevenge::RVNG_SEEK_SET); ascii().addPos(pos); ascii().addNote(f.str().c_str()); break; } MouseWrtParserInternal::Paragraph para(i); para.m_paragraph.m_marginsUnit=librevenge::RVNG_POINT; // note: right margins is defined from left, so must be corrected when we know the page length para.m_paragraph.m_margins[1] = double(input->readLong(2)); para.m_paragraph.m_margins[2] = double(input->readLong(2)); auto val=static_cast(input->readULong(1)); switch (val) { case 0xf: // left break; case 0x10: para.m_paragraph.m_justify = MWAWParagraph::JustificationFull; break; case 0x11: para.m_paragraph.m_justify = MWAWParagraph::JustificationRight; break; case 0x12: para.m_paragraph.m_justify = MWAWParagraph::JustificationCenter; break; case 0x13: f << "justify=rowCol,"; break; case 0x14: f << "justify=col,"; break; default: if (!val) break; MWAW_DEBUG_MSG(("MouseWrtParser::readParagraphPLCs: unknown justify\n")); f << "#justify=" << std::hex << val << std::dec << ","; } for (int j=0; j<2; ++j) { // fl0=1|7, maybe related to tabs definition val=static_cast(input->readULong(1)); // 1|7 if (val) f << "fl" << j << "=" << std::hex << val << std::dec << ","; } val=static_cast(input->readULong(1)); switch (val) { case 0xb: break; case 0xc: para.m_paragraph.setInterline(1.1, librevenge::RVNG_PERCENT); break; case 0xd: para.m_paragraph.setInterline(1.5, librevenge::RVNG_PERCENT); break; case 0xe: para.m_paragraph.setInterline(2, librevenge::RVNG_PERCENT); break; default: MWAW_DEBUG_MSG(("MouseWrtParser::readParagraphPLCs: unknown interline\n")); f << "#interline=" << val << ","; break; } val=static_cast(input->readULong(1)); // always 0 if (val) f << "fl2=" << val << ","; val=static_cast(input->readULong(1)); switch (val) { case 0: break; case 1: para.m_picture=true; f << "picture,"; break; default: MWAW_DEBUG_MSG(("MouseWrtParser::readParagraphPLCs: unknown picture def\n")); f << "#picture=" << val << ","; break; } int lastTabPos=0; // check that the tabulation are in increasing order for (int j=0; j<10; ++j) { val=static_cast(input->readLong(2)); if (!val || val<=lastTabPos) break; MWAWTabStop tab; tab.m_alignment=MWAWTabStop::CENTER; tab.m_position=double(val)/72.; para.m_paragraph.m_tabs->push_back(tab); lastTabPos=val; } input->seek(pos+30, librevenge::RVNG_SEEK_SET); val=static_cast(input->readLong(2)); if (val) f << "act[tab]=" << val << ","; val=static_cast(input->readULong(1)); switch (val) { case 0: para.m_paragraph.m_writingMode=libmwaw::WritingRightTop; break; case 1: // normal writing break; default: MWAW_DEBUG_MSG(("MouseWrtParser::readParagraphPLCs: unknown writing mode\n")); f << "#writing[mode]=" << val << ","; break; } for (int j=0; j<3; ++j) { // always 0? val=static_cast(input->readULong(1)); if (val) f << "flA" << j << "=" << val << ","; } f << para.m_paragraph; auto cPos=static_cast(input->readULong(2)); f << "cPos=" << cPos << ","; m_state->m_paraPLCMap[cPos]=para; input->seek(pos+38, librevenge::RVNG_SEEK_SET); ascii().addPos(pos); ascii().addNote(f.str().c_str()); } return true; } bool MouseWrtParser::readDocumentInfo(long sz) { MWAWInputStreamPtr input = getInput(); long pos = input->tell(); if (sz<76 || !input->checkPosition(pos+sz)) { MWAW_DEBUG_MSG(("MouseWrtParser::readDocumentInfo: find unexpected size length\n")); return false; } libmwaw::DebugStream f; f << "Entries(DocumentInfo):"; int val; f << "unkns=["; for (int i=0; i<2; ++i) { // footer,header // find 0|18|25, does not seems related to heigth... val=static_cast(input->readULong(2)); if (val) f << val << ","; else f << "_,"; } f << "],"; for (auto &zone : m_state->m_zones) { // header,footer val=static_cast(input->readULong(1)); switch (val) { case 0: zone.m_writingHebrew=true; f << "writing[mode]=rt-lb,"; break; case 1: // normal writing break; default: MWAW_DEBUG_MSG(("MouseWrtParser::readDocumentInfo: unknown writing mode\n")); f << "#writing[mode]=" << val << ","; break; } } f << "ids=["; for (int i=0; i<2; ++i) { // header,footer val=static_cast(input->readULong(4)); if (val) f << std::hex << val << std::dec << ","; else f << "_,"; } f << "],"; long zoneSize[2]; for (int i=0; i<2; ++i) { // header,footer zoneSize[i]=long(input->readULong(4)); if (zoneSize[i]) f << "block" << i << "[sz]=" << zoneSize[i] << ","; } for (int i=0; i<2; ++i) { // header,footer, always 0|-1? val=static_cast(input->readLong(4)); if (val) f << "f" << i+2 << "=" << val << ","; } for (int i=0; i<2; ++i) { // header,footer long actPos=input->tell(); int cPos; if (zoneSize[i]==0 || !readFont(m_state->m_zones[i].m_font, cPos)) input->seek(actPos+8, librevenge::RVNG_SEEK_SET); else f << "font" << i << "=[" << m_state->m_zones[i].m_font.getDebugString(getParserState()->m_fontConverter) << "],"; } ascii().addDelimiter(input->tell(),'|'); if (sz > 76+zoneSize[0]+zoneSize[1] || zoneSize[0]<0 || zoneSize[1]<0) { MWAW_DEBUG_MSG(("MouseWrtParser::readDocumentInfo: problem with the zoneSize\n")); f << "##zoneSize,"; input->seek(pos+sz, librevenge::RVNG_SEEK_SET); } else { input->seek(pos+76, librevenge::RVNG_SEEK_SET); for (int i=0; i<2; ++i) { if (zoneSize[i]<=0) continue; m_state->m_zones[i].m_text.setBegin(input->tell()); m_state->m_zones[i].m_text.setLength(zoneSize[i]); input->seek(zoneSize[i], librevenge::RVNG_SEEK_CUR); } } ascii().addPos(pos); ascii().addNote(f.str().c_str()); return true; } int MouseWrtParser::computeNumPages() { if (!m_state->m_text.valid()) return 1; MWAWInputStreamPtr input = getInput(); int numPages=1; auto pIt=m_state->m_paraPLCMap.begin(); long const beginPos=m_state->m_text.begin(); while (pIt!=m_state->m_paraPLCMap.end()) { if (pIt->second.m_picture) { ++pIt; continue; } long actPos=beginPos+(pIt++)->first; long lastPos=(pIt!=m_state->m_paraPLCMap.end()) ? beginPos+pIt->first : m_state->m_text.end(); if (lastPos>m_state->m_text.end()) { MWAW_DEBUG_MSG(("MouseWrtParser::computeNumPages: oops, problem with some plc pos\n")); break; } input->seek(actPos, librevenge::RVNG_SEEK_SET); for (long cPos=actPos; cPosreadULong(1)==0xd7) ++numPages; } } return numPages; } //////////////////////////////////////////////////////////// // read the print info //////////////////////////////////////////////////////////// bool MouseWrtParser::readPrintInfo() { MWAWInputStreamPtr input = getInput(); long pos = input->tell(); libmwaw::DebugStream f; // print info libmwaw::PrinterInfo info; if (!info.read(input)) return false; f << "Entries(PrintInfo):"<< info; MWAWVec2i paperSize = info.paper().size(); MWAWVec2i pageSize = info.page().size(); if (pageSize.x() <= 0 || pageSize.y() <= 0 || paperSize.x() <= 0 || paperSize.y() <= 0) return false; // define margin from print info MWAWVec2i lTopMargin= -1 * info.paper().pos(0); MWAWVec2i rBotMargin=info.paper().pos(1) - info.page().pos(1); // move margin left | top int decalX = lTopMargin.x() > 14 ? lTopMargin.x()-14 : 0; int decalY = lTopMargin.y() > 14 ? lTopMargin.y()-14 : 0; lTopMargin -= MWAWVec2i(decalX, decalY); rBotMargin += MWAWVec2i(decalX, decalY); // decrease right | bottom int rightMarg = rBotMargin.x() -10; if (rightMarg < 0) rightMarg=0; int botMarg = rBotMargin.y() -50; if (botMarg < 0) botMarg=0; getPageSpan().setMarginTop(lTopMargin.y()/72.0); getPageSpan().setMarginBottom(botMarg/72.0); getPageSpan().setMarginLeft(lTopMargin.x()/72.0); getPageSpan().setMarginRight(rightMarg/72.0); getPageSpan().setFormLength(paperSize.y()/72.); getPageSpan().setFormWidth(paperSize.x()/72.); ascii().addPos(pos); ascii().addNote(f.str().c_str()); input->seek(pos+0x78, librevenge::RVNG_SEEK_SET); if (long(input->tell()) != pos+0x78) { MWAW_DEBUG_MSG(("MouseWrtParser::readPrintInfo: file is too short\n")); return false; } ascii().addPos(input->tell()); return true; } //////////////////////////////////////////////////////////// // send the data //////////////////////////////////////////////////////////// bool MouseWrtParser::sendMainZone() { MWAWListenerPtr listener=getMainListener(); if (!listener) { MWAW_DEBUG_MSG(("MouseWrtParser::sendMainZone: can not find the listener\n")); } MWAWInputStreamPtr input = getInput(); if (!m_state->m_text.valid() || !input->checkPosition(m_state->m_text.end())) { listener->insertChar(' '); return true; } long begPos = m_state->m_text.begin(), pos=begPos; input->seek(pos, librevenge::RVNG_SEEK_SET); auto N=static_cast(m_state->m_text.length()); libmwaw::DebugStream f; f << "Entries(Text):"; double const pageWidth=72. * getPageSpan().getPageWidth(); int actPage=1; newPage(actPage); for (int i=0; im_paraPLCMap.find(i); if (pIt!=m_state->m_paraPLCMap.end()) { if (i!=0) { ascii().addPos(pos); ascii().addNote(f.str().c_str()); pos=input->tell(); f.str(""); f << "Text:"; } auto const ¶=pIt->second; f << "[P" << para.m_id << "]"; // time to send the paragraph, so first update the right margins MWAWParagraph paragraph=para.m_paragraph; if (*(paragraph.m_margins[2])>pageWidth) { f << "#"; paragraph.m_margins[2]=0; } else paragraph.m_margins[2]=pageWidth-*paragraph.m_margins[2]; if (para.m_picture) paragraph.m_justify = MWAWParagraph::JustificationRight; listener->setParagraph(paragraph); if (para.m_picture) { f << "[picture],"; ++pIt; long endPos=pIt==m_state->m_paraPLCMap.end() ? m_state->m_text.end() : begPos+pIt->first; if (endPos<=input->tell()) { // check that we do not go backward f << "###"; MWAW_DEBUG_MSG(("MouseWrtParser::sendZone: can not compute the end of picture pos, stop!!!\n")); break; } long actPos=input->tell(); bool ok=endPos-actPos>9; if (ok) { // look for pict auto dSz=static_cast(input->readULong(2)); if (dSz+9>endPos-actPos || dSz+12seek(endPos-9, librevenge::RVNG_SEEK_SET); } else input->seek(actPos+dSz, librevenge::RVNG_SEEK_SET); long pictSz=input->tell()-actPos; int dim[4]; for (auto &d : dim) d=static_cast(input->readLong(2)); MWAWBox2i box(MWAWVec2i(dim[1],dim[0]),MWAWVec2i(dim[3],dim[2])); f << "box=" << box << ","; if (box.size()[0]<0 || box.size()[1]<0 || box.size()[0]>2000 || box.size()[1]>2000) { MWAW_DEBUG_MSG(("MouseWrtParser::sendZone: the bdbox is bad\n")); f << "###"; ok=false; } else { librevenge::RVNGBinaryData data; input->seek(actPos, librevenge::RVNG_SEEK_SET); input->readDataBlock(pictSz, data); MWAWEmbeddedObject object(data); MWAWPosition position(MWAWVec2f(0,0), MWAWVec2f(box.size()), librevenge::RVNG_POINT); position.m_anchorTo=MWAWPosition::Char; listener->insertPicture(position, object); #ifdef DEBUG_WITH_FILES static int volatile pictName = 0; libmwaw::DebugStream f2; f2 << "Pict-" << ++pictName << ".pct"; libmwaw::Debug::dumpFile(data, f2.str().c_str()); #endif ascii().skipZone(actPos, actPos+pictSz-1); } } if (ok || endPos-actPos>20) { listener->insertEOL(); ascii().addPos(pos); ascii().addNote(f.str().c_str()); pos=input->tell(); f.str(""); f << "Text:"; input->seek(endPos, librevenge::RVNG_SEEK_SET); i=int(endPos-begPos-1); // will be endPos-begPos after continue; } } } auto fIt=m_state->m_charPLCMap.find(i); if (fIt!=m_state->m_charPLCMap.end()) { listener->setFont(fIt->second); f << "[" << fIt->second.getDebugString(getParserState()->m_fontConverter) << "]"; } auto c=static_cast(input->readULong(1)); f << c; switch (c) { case 0x9: listener->insertTab(); break; case 0xd: listener->insertEOL(); ascii().addPos(pos); ascii().addNote(f.str().c_str()); pos=input->tell(); f.str(""); f << "Text:"; break; case 0xd7: { newPage(++actPage); long actPos=input->tell(); if (i+1!=N && input->readULong(1)==0xd) { ascii().addPos(pos); ascii().addNote(f.str().c_str()); pos=input->tell(); f.str(""); f << "Text:"; ++i; } else input->seek(actPos, librevenge::RVNG_SEEK_SET); break; } default: listener->insertCharacter(c); break; } } if (input->tell()!=pos) { ascii().addPos(pos); ascii().addNote(f.str().c_str()); } return true; } bool MouseWrtParser::sendZone(int zoneId) { if (zoneId < 0 || zoneId >= 2) { MWAW_DEBUG_MSG(("MouseWrtParser::sendZone: invalid zone %d\n", zoneId)); return false; } MWAWListenerPtr listener=getMainListener(); if (!listener) { MWAW_DEBUG_MSG(("MouseWrtParser::sendZone: can not find the listener\n")); return false; } auto const &zone=m_state->m_zones[zoneId]; if (!zone.m_text.valid()) return true; if (zone.m_writingHebrew) { MWAWParagraph para; para.m_writingMode=libmwaw::WritingRightTop; listener->setParagraph(para); } listener->setFont(zone.m_font); MWAWInputStreamPtr input = getInput(); libmwaw::DebugStream f; f << "Entries(Text):" << (zoneId==0 ? "header" : "footer") << ","; input->seek(zone.m_text.begin(), librevenge::RVNG_SEEK_SET); auto N=static_cast(zone.m_text.length()); for (long i=0; iisEnd()) { MWAW_DEBUG_MSG(("MouseWrtParser::sendZone: oops the text length seems too big\n")); f << "###"; break; } auto c=static_cast(input->readULong(1)); f << c; switch (c) { case 0x9: MWAW_DEBUG_MSG(("MouseWrtParser::sendZone: oops unexpected tab\n")); listener->insertChar(' '); break; case 0xd: if (i+1==N) break; listener->insertEOL(); break; default: listener->insertCharacter(c); break; } } ascii().addPos(zone.m_text.begin()); ascii().addNote(f.str().c_str()); return true; } // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: