|
|
|
/* This file is part of the KOffice project
|
|
|
|
Copyright (C) 2002 Werner Trobin <trobin@kde.org>
|
|
|
|
Copyright (C) 2002 David Faure <faure@kde.org>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU General Public
|
|
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; see the file COPYING. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "document.h"
|
|
|
|
#include "conversion.h"
|
|
|
|
#include "texthandler.h"
|
|
|
|
#include "graphicshandler.h"
|
|
|
|
#include "versionmagic.h"
|
|
|
|
|
|
|
|
#include <KoRect.h>
|
|
|
|
#include <KoUnit.h>
|
|
|
|
#include <KoPageLayout.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include <wv2/styles.h>
|
|
|
|
#include <wv2/ustring.h>
|
|
|
|
#include <wv2/word97_generated.h>
|
|
|
|
#include <wv2/parser.h>
|
|
|
|
#include <wv2/parserfactory.h>
|
|
|
|
#include <wv2/paragraphproperties.h>
|
|
|
|
#include <wv2/associatedstrings.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <KoStore.h>
|
|
|
|
#include <KoFilterChain.h>
|
|
|
|
|
|
|
|
|
|
|
|
Document::Document( const std::string& fileName, TQDomDocument& mainDocument, TQDomDocument& documentInfo, TQDomElement& framesetsElement, KoFilterChain* chain )
|
|
|
|
: m_mainDocument( mainDocument ), m_documentInfo ( documentInfo ),
|
|
|
|
m_framesetsElement( framesetsElement ),
|
|
|
|
m_replacementHandler( new KWordReplacementHandler ), m_tableHandler( new KWordTableHandler ),
|
|
|
|
m_pictureHandler( new KWordPictureHandler( this ) ), m_textHandler( 0 ),
|
|
|
|
m_chain( chain ),
|
|
|
|
m_parser( wvWare::ParserFactory::createParser( fileName ) ), m_headerFooters( 0 ), m_bodyFound( false ),
|
|
|
|
m_footNoteNumber( 0 ), m_endNoteNumber( 0 )
|
|
|
|
{
|
|
|
|
if ( m_parser ) // 0 in case of major error (e.g. unsupported format)
|
|
|
|
{
|
|
|
|
m_textHandler = new KWordTextHandler( m_parser );
|
|
|
|
connect( m_textHandler, TQT_SIGNAL( subDocFound( const wvWare::FunctorBase*, int ) ),
|
|
|
|
this, TQT_SLOT( slotSubDocFound( const wvWare::FunctorBase*, int ) ) );
|
|
|
|
connect( m_textHandler, TQT_SIGNAL( tableFound( const KWord::Table& ) ),
|
|
|
|
this, TQT_SLOT( slotTableFound( const KWord::Table& ) ) );
|
|
|
|
connect( m_textHandler, TQT_SIGNAL( pictureFound( const TQString&, const TQString&, const wvWare::FunctorBase* ) ),
|
|
|
|
this, TQT_SLOT( slotPictureFound( const TQString&, const TQString&, const wvWare::FunctorBase* ) ) );
|
|
|
|
m_parser->setSubDocumentHandler( this );
|
|
|
|
m_parser->setTextHandler( m_textHandler );
|
|
|
|
m_parser->setTableHandler( m_tableHandler );
|
|
|
|
#ifdef IMAGE_IMPORT
|
|
|
|
m_parser->setPictureHandler( m_pictureHandler );
|
|
|
|
#endif
|
|
|
|
m_parser->setInlineReplacementHandler( m_replacementHandler );
|
|
|
|
processStyles();
|
|
|
|
processAssociatedStrings();
|
|
|
|
connect( m_tableHandler, TQT_SIGNAL( sigTableCellStart( int, int, int, int, const KoRect&, const TQString&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::SHD& ) ),
|
|
|
|
this, TQT_SLOT( slotTableCellStart( int, int, int, int, const KoRect&, const TQString&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::BRC&, const wvWare::Word97::SHD& ) ) );
|
|
|
|
connect( m_tableHandler, TQT_SIGNAL( sigTableCellEnd() ),
|
|
|
|
this, TQT_SLOT( slotTableCellEnd() ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Document::~Document()
|
|
|
|
{
|
|
|
|
delete m_textHandler;
|
|
|
|
delete m_pictureHandler;
|
|
|
|
delete m_tableHandler;
|
|
|
|
delete m_replacementHandler;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::finishDocument()
|
|
|
|
{
|
|
|
|
const wvWare::Word97::DOP& dop = m_parser->dop();
|
|
|
|
|
|
|
|
TQDomElement elementDoc = m_mainDocument.documentElement();
|
|
|
|
|
|
|
|
TQDomElement element;
|
|
|
|
element = m_mainDocument.createElement("ATTRIBUTES");
|
|
|
|
element.setAttribute("processing",0); // WP
|
|
|
|
char allHeaders = ( wvWare::HeaderData::HeaderEven |
|
|
|
|
wvWare::HeaderData::HeaderOdd |
|
|
|
|
wvWare::HeaderData::HeaderFirst );
|
|
|
|
element.setAttribute("hasHeader", m_headerFooters & allHeaders ? 1 : 0 );
|
|
|
|
char allFooters = ( wvWare::HeaderData::FooterEven |
|
|
|
|
wvWare::HeaderData::FooterOdd |
|
|
|
|
wvWare::HeaderData::FooterFirst );
|
|
|
|
element.setAttribute("hasFooter", m_headerFooters & allFooters ? 1 : 0 );
|
|
|
|
//element.setAttribute("unit","mm"); // How to figure out the unit to use?
|
|
|
|
|
|
|
|
element.setAttribute("tabStopValue", (double)dop.dxaTab / 20.0 );
|
|
|
|
elementDoc.appendChild(element);
|
|
|
|
|
|
|
|
element = m_mainDocument.createElement("FOOTNOTESETTING");
|
|
|
|
elementDoc.appendChild(element);
|
|
|
|
element.setAttribute( "start", dop.nFtn ); // initial footnote number for document. Starts at 1.
|
|
|
|
element.setAttribute( "type", Conversion::numberFormatCode( dop.nfcFtnRef2 ) );
|
|
|
|
|
|
|
|
element = m_mainDocument.createElement("ENDNOTESETTING");
|
|
|
|
elementDoc.appendChild(element);
|
|
|
|
element.setAttribute( "start", dop.nEdn ); // initial endnote number for document. Starts at 1.
|
|
|
|
element.setAttribute( "type", Conversion::numberFormatCode( dop.nfcEdnRef2 ) );
|
|
|
|
|
|
|
|
// Done at the end: write the type of headers/footers,
|
|
|
|
// depending on which kind of headers and footers we received.
|
|
|
|
TQDomElement paperElement = elementDoc.namedItem("PAPER").toElement();
|
|
|
|
Q_ASSERT ( !paperElement.isNull() ); // slotFirstSectionFound should have been called!
|
|
|
|
if ( !paperElement.isNull() )
|
|
|
|
{
|
|
|
|
kdDebug(30513) << k_funcinfo << "m_headerFooters=" << m_headerFooters << endl;
|
|
|
|
paperElement.setAttribute("hType", Conversion::headerMaskToHType( m_headerFooters ) );
|
|
|
|
paperElement.setAttribute("fType", Conversion::headerMaskToFType( m_headerFooters ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Write out <PICTURES> tag
|
|
|
|
TQDomElement picturesElem = m_mainDocument.createElement("PICTURES");
|
|
|
|
elementDoc.appendChild( picturesElem );
|
|
|
|
for( TQStringList::Iterator it = m_pictureList.begin(); it != m_pictureList.end(); ++it ) {
|
|
|
|
TQDomElement keyElem = m_mainDocument.createElement("KEY");
|
|
|
|
picturesElem.appendChild( keyElem );
|
|
|
|
keyElem.setAttribute( "filename", *it );
|
|
|
|
keyElem.setAttribute( "name", *it );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::processAssociatedStrings() {
|
|
|
|
wvWare::AssociatedStrings strings( m_parser->associatedStrings() );
|
|
|
|
|
|
|
|
TQDomElement infodoc = m_documentInfo.createElement( "document-info" );
|
|
|
|
TQDomElement author = m_documentInfo.createElement( "author" );
|
|
|
|
TQDomElement fullname = m_documentInfo.createElement( "full-name" );
|
|
|
|
TQDomElement title = m_documentInfo.createElement( "title" );
|
|
|
|
TQDomElement about = m_documentInfo.createElement( "about" );
|
|
|
|
|
|
|
|
m_documentInfo.appendChild(infodoc);
|
|
|
|
|
|
|
|
if ( !strings.author().isNull()) {
|
|
|
|
fullname.appendChild(
|
|
|
|
m_documentInfo.createTextNode(
|
|
|
|
Conversion::string (
|
|
|
|
strings.author()
|
|
|
|
).string()));
|
|
|
|
author.appendChild(fullname);
|
|
|
|
infodoc.appendChild(author);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !strings.title().isNull()) {
|
|
|
|
title.appendChild(
|
|
|
|
m_documentInfo.createTextNode(
|
|
|
|
Conversion::string (
|
|
|
|
strings.title()
|
|
|
|
).string()));
|
|
|
|
about.appendChild(title);
|
|
|
|
infodoc.appendChild(about);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::processStyles()
|
|
|
|
{
|
|
|
|
TQDomElement stylesElem = m_mainDocument.createElement( "STYLES" );
|
|
|
|
m_mainDocument.documentElement().appendChild( stylesElem );
|
|
|
|
|
|
|
|
m_textHandler->setFrameSetElement( stylesElem ); /// ### naming!
|
|
|
|
const wvWare::StyleSheet& styles = m_parser->styleSheet();
|
|
|
|
unsigned int count = styles.size();
|
|
|
|
//kdDebug(30513) << k_funcinfo << "styles count=" << count << endl;
|
|
|
|
for ( unsigned int i = 0; i < count ; ++i )
|
|
|
|
{
|
|
|
|
const wvWare::Style* style = styles.styleByIndex( i );
|
|
|
|
Q_ASSERT( style );
|
|
|
|
//kdDebug(30513) << k_funcinfo << "style " << i << " " << style << endl;
|
|
|
|
if ( style && style->type() == wvWare::Style::sgcPara )
|
|
|
|
{
|
|
|
|
TQDomElement styleElem = m_mainDocument.createElement("STYLE");
|
|
|
|
stylesElem.appendChild( styleElem );
|
|
|
|
|
|
|
|
TQConstString name = Conversion::string( style->name() );
|
|
|
|
TQDomElement element = m_mainDocument.createElement("NAME");
|
|
|
|
element.setAttribute( "value", name.string() );
|
|
|
|
styleElem.appendChild( element );
|
|
|
|
|
|
|
|
kdDebug(30513) << k_funcinfo << "Style " << i << ": " << name.string() << endl;
|
|
|
|
|
|
|
|
const wvWare::Style* followingStyle = styles.styleByID( style->followingStyle() );
|
|
|
|
if ( followingStyle && followingStyle != style )
|
|
|
|
{
|
|
|
|
TQConstString followingName = Conversion::string( followingStyle->name() );
|
|
|
|
element = m_mainDocument.createElement("FOLLOWING");
|
|
|
|
element.setAttribute( "name", followingName.string() );
|
|
|
|
styleElem.appendChild( element );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_textHandler->paragLayoutBegin(); // new style, reset some vars
|
|
|
|
|
|
|
|
// It's important to do that one first, for m_shadowTextFound
|
|
|
|
m_textHandler->writeFormat( styleElem, &style->chp(), 0L /*all of it, no ref chp*/, 0, 0, 1, 0L );
|
|
|
|
|
|
|
|
m_textHandler->writeLayout( styleElem, style->paragraphProperties(), style );
|
|
|
|
}
|
|
|
|
// KWord doesn't support character styles yet
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Document::parse()
|
|
|
|
{
|
|
|
|
if ( m_parser )
|
|
|
|
return m_parser->parse();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::bodyStart()
|
|
|
|
{
|
|
|
|
kdDebug(30513) << k_funcinfo << endl;
|
|
|
|
|
|
|
|
TQDomElement mainFramesetElement = m_mainDocument.createElement("FRAMESET");
|
|
|
|
mainFramesetElement.setAttribute("frameType",1);
|
|
|
|
mainFramesetElement.setAttribute("frameInfo",0);
|
|
|
|
// TODO: "name" attribute (needs I18N)
|
|
|
|
m_framesetsElement.appendChild(mainFramesetElement);
|
|
|
|
|
|
|
|
// Those values are unused. The paper margins make recalcFrames() resize this frame.
|
|
|
|
createInitialFrame( mainFramesetElement, 29, 798, 42, 566, false, Reconnect );
|
|
|
|
|
|
|
|
m_textHandler->setFrameSetElement( mainFramesetElement );
|
|
|
|
connect( m_textHandler, TQT_SIGNAL( firstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> ) ),
|
|
|
|
this, TQT_SLOT( slotFirstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> ) ) );
|
|
|
|
m_bodyFound = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::bodyEnd()
|
|
|
|
{
|
|
|
|
kdDebug(30513) << k_funcinfo << endl;
|
|
|
|
disconnect( m_textHandler, TQT_SIGNAL( firstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> ) ),
|
|
|
|
this, TQT_SLOT( slotFirstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Document::slotFirstSectionFound( wvWare::SharedPtr<const wvWare::Word97::SEP> sep )
|
|
|
|
{
|
|
|
|
kdDebug(30513) << k_funcinfo << endl;
|
|
|
|
TQDomElement elementDoc = m_mainDocument.documentElement();
|
|
|
|
|
|
|
|
TQDomElement elementPaper = m_mainDocument.createElement("PAPER");
|
|
|
|
bool landscape = (sep->dmOrientPage == 2);
|
|
|
|
double width = (double)sep->xaPage / 20.0;
|
|
|
|
double height = (double)sep->yaPage / 20.0;
|
|
|
|
elementPaper.setAttribute("width", width);
|
|
|
|
elementPaper.setAttribute("height", height);
|
|
|
|
|
|
|
|
// guessFormat takes millimeters
|
|
|
|
width = POINT_TO_MM( width );
|
|
|
|
height = POINT_TO_MM( height );
|
|
|
|
KoFormat paperFormat = KoPageFormat::guessFormat( landscape ? height : width, landscape ? width : height );
|
|
|
|
elementPaper.setAttribute("format",paperFormat);
|
|
|
|
|
|
|
|
elementPaper.setAttribute("orientation", landscape ? PG_LANDSCAPE : PG_PORTRAIT );
|
|
|
|
elementPaper.setAttribute("columns", sep->ccolM1 + 1 );
|
|
|
|
elementPaper.setAttribute("columnspacing", (double)sep->dxaColumns / 20.0);
|
|
|
|
elementPaper.setAttribute("spHeadBody", (double)sep->dyaHdrTop / 20.0);
|
|
|
|
elementPaper.setAttribute("spFootBody", (double)sep->dyaHdrBottom / 20.0);
|
|
|
|
// elementPaper.setAttribute("zoom",100); // not a doc property in kword
|
|
|
|
elementDoc.appendChild(elementPaper);
|
|
|
|
|
|
|
|
TQDomElement element = m_mainDocument.createElement("PAPERBORDERS");
|
|
|
|
element.setAttribute("left", (double)sep->dxaLeft / 20.0);
|
|
|
|
element.setAttribute("top",(double)sep->dyaTop / 20.0);
|
|
|
|
element.setAttribute("right", (double)sep->dxaRight / 20.0);
|
|
|
|
element.setAttribute("bottom", (double)sep->dyaBottom / 20.0);
|
|
|
|
elementPaper.appendChild(element);
|
|
|
|
|
|
|
|
// TODO apply brcTop/brcLeft etc. to the main FRAME
|
|
|
|
// TODO use sep->fEndNote to set the 'use endnotes or footnotes' flag
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::headerStart( wvWare::HeaderData::Type type )
|
|
|
|
{
|
|
|
|
kdDebug(30513) << "startHeader type=" << type << " (" << Conversion::headerTypeToFramesetName( type ) << ")" << endl;
|
|
|
|
// Werner says the headers are always emitted in the order of the Type enum.
|
|
|
|
|
|
|
|
TQDomElement framesetElement = m_mainDocument.createElement("FRAMESET");
|
|
|
|
framesetElement.setAttribute( "frameType", 1 );
|
|
|
|
framesetElement.setAttribute( "frameInfo", Conversion::headerTypeToFrameInfo( type ) );
|
|
|
|
framesetElement.setAttribute( "name", Conversion::headerTypeToFramesetName( type ) );
|
|
|
|
m_framesetsElement.appendChild(framesetElement);
|
|
|
|
|
|
|
|
bool isHeader = Conversion::isHeader( type );
|
|
|
|
|
|
|
|
createInitialFrame( framesetElement, 29, 798, isHeader?0:567, isHeader?41:567+41, true, Copy );
|
|
|
|
|
|
|
|
m_textHandler->setFrameSetElement( framesetElement );
|
|
|
|
|
|
|
|
m_headerFooters |= type;
|
|
|
|
|
|
|
|
/*if ( Conversion::isHeader( type ) )
|
|
|
|
m_hasHeader = true;
|
|
|
|
else
|
|
|
|
m_hasFooter = true;*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::headerEnd()
|
|
|
|
{
|
|
|
|
m_textHandler->setFrameSetElement( TQDomElement() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::footnoteStart()
|
|
|
|
{
|
|
|
|
// Grab data that was stored with the functor, that triggered this parsing
|
|
|
|
SubDocument subdoc( m_subdocQueue.front() );
|
|
|
|
int type = subdoc.data;
|
|
|
|
|
|
|
|
// Create footnote/endnote frameset
|
|
|
|
TQDomElement framesetElement = m_mainDocument.createElement("FRAMESET");
|
|
|
|
framesetElement.setAttribute( "frameType", 1 /* text */ );
|
|
|
|
framesetElement.setAttribute( "frameInfo", 7 /* footnote/endnote */ );
|
|
|
|
if ( type == wvWare::FootnoteData::Endnote )
|
|
|
|
// Keep name in sync with KWordTextHandler::footnoteFound
|
|
|
|
framesetElement.setAttribute("name", i18n("Endnote %1").arg( ++m_endNoteNumber ) );
|
|
|
|
else
|
|
|
|
// Keep name in sync with KWordTextHandler::footnoteFound
|
|
|
|
framesetElement.setAttribute("name", i18n("Footnote %1").arg( ++m_footNoteNumber ) );
|
|
|
|
m_framesetsElement.appendChild(framesetElement);
|
|
|
|
|
|
|
|
createInitialFrame( framesetElement, 29, 798, 567, 567+41, true, NoFollowup );
|
|
|
|
|
|
|
|
m_textHandler->setFrameSetElement( framesetElement );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::footnoteEnd()
|
|
|
|
{
|
|
|
|
kdDebug(30513) << k_funcinfo << endl;
|
|
|
|
m_textHandler->setFrameSetElement( TQDomElement() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::slotTableCellStart( int row, int column, int rowSpan, int columnSpan, const KoRect& cellRect, const TQString& tableName, const wvWare::Word97::BRC& brcTop, const wvWare::Word97::BRC& brcBottom, const wvWare::Word97::BRC& brcLeft, const wvWare::Word97::BRC& brcRight, const wvWare::Word97::SHD& shd )
|
|
|
|
{
|
|
|
|
// Create footnote/endnote frameset
|
|
|
|
TQDomElement framesetElement = m_mainDocument.createElement("FRAMESET");
|
|
|
|
framesetElement.setAttribute( "frameType", 1 /* text */ );
|
|
|
|
framesetElement.setAttribute( "frameInfo", 0 /* normal text */ );
|
|
|
|
framesetElement.setAttribute( "grpMgr", tableName );
|
|
|
|
TQString name = i18n("Table_Name Cell row,column", "%1 Cell %2,%3").arg(tableName).arg(row).arg(column);
|
|
|
|
framesetElement.setAttribute( "name", name );
|
|
|
|
framesetElement.setAttribute( "row", row );
|
|
|
|
framesetElement.setAttribute( "col", column );
|
|
|
|
framesetElement.setAttribute( "rows", rowSpan );
|
|
|
|
framesetElement.setAttribute( "cols", columnSpan );
|
|
|
|
m_framesetsElement.appendChild(framesetElement);
|
|
|
|
|
|
|
|
TQDomElement frameElem = createInitialFrame( framesetElement, cellRect.left(), cellRect.right(), cellRect.top(), cellRect.bottom(), true, NoFollowup );
|
|
|
|
generateFrameBorder( frameElem, brcTop, brcBottom, brcLeft, brcRight, shd );
|
|
|
|
|
|
|
|
m_textHandler->setFrameSetElement( framesetElement );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::slotTableCellEnd()
|
|
|
|
{
|
|
|
|
m_textHandler->setFrameSetElement( TQDomElement() );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDomElement Document::createInitialFrame( TQDomElement& parentFramesetElem, double left, double right, double top, double bottom, bool autoExtend, NewFrameBehavior nfb )
|
|
|
|
{
|
|
|
|
TQDomElement frameElementOut = parentFramesetElem.ownerDocument().createElement("FRAME");
|
|
|
|
frameElementOut.setAttribute( "left", left );
|
|
|
|
frameElementOut.setAttribute( "right", right );
|
|
|
|
frameElementOut.setAttribute( "top", top );
|
|
|
|
frameElementOut.setAttribute( "bottom", bottom );
|
|
|
|
frameElementOut.setAttribute( "runaround", 1 );
|
|
|
|
// AutoExtendFrame for header/footer/footnote/endnote, AutoCreateNewFrame for body text
|
|
|
|
frameElementOut.setAttribute( "autoCreateNewFrame", autoExtend ? 0 : 1 );
|
|
|
|
frameElementOut.setAttribute( "newFrameBehavior", nfb );
|
|
|
|
parentFramesetElem.appendChild( frameElementOut );
|
|
|
|
return frameElementOut;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::generateFrameBorder( TQDomElement& frameElementOut, const wvWare::Word97::BRC& brcTop, const wvWare::Word97::BRC& brcBottom, const wvWare::Word97::BRC& brcLeft, const wvWare::Word97::BRC& brcRight, const wvWare::Word97::SHD& shd )
|
|
|
|
{
|
|
|
|
// Frame borders
|
|
|
|
|
|
|
|
if ( brcTop.cv != 255 && brcTop.dptLineWidth != 255 ) // see tablehandler.cpp
|
|
|
|
Conversion::setBorderAttributes( frameElementOut, brcTop, "t" );
|
|
|
|
if ( brcBottom.cv != 255 && brcBottom.dptLineWidth != 255 ) // see tablehandler.cpp
|
|
|
|
Conversion::setBorderAttributes( frameElementOut, brcBottom, "b" );
|
|
|
|
if ( brcLeft.cv != 255 && brcLeft.dptLineWidth != 255 ) // could still be 255, for first column
|
|
|
|
Conversion::setBorderAttributes( frameElementOut, brcLeft, "l" );
|
|
|
|
if ( brcRight.cv != 255 && brcRight.dptLineWidth != 255 ) // could still be 255, for last column
|
|
|
|
Conversion::setBorderAttributes( frameElementOut, brcRight, "r" );
|
|
|
|
|
|
|
|
// Frame background brush (color and fill style)
|
|
|
|
if ( shd.cvFore != 0 || shd.cvBack != 0 )
|
|
|
|
{
|
|
|
|
// If ipat = 0 (solid fill), icoBack is the background color.
|
|
|
|
// But otherwise, icoFore is the one we need to set as bkColor
|
|
|
|
// (and icoBack is usually white; it's the other colour of the pattern,
|
|
|
|
// something that we can't set in TQt apparently).
|
|
|
|
int bkColor = shd.ipat ? shd.cvFore : shd.cvBack;
|
|
|
|
kdDebug(30513) << "generateFrameBorder: " << " icoFore=" << shd.cvFore << " icoBack=" << shd.cvBack << " ipat=" << shd.ipat << " -> bkColor=" << bkColor << endl;
|
|
|
|
|
|
|
|
// Reverse-engineer MSWord's own hackery: it models various gray levels
|
|
|
|
// using dithering. But this looks crappy with TQt. So we go back to a TQColor.
|
|
|
|
bool grayHack = ( shd.ipat && shd.cvFore == 1 && shd.cvBack == 8 );
|
|
|
|
if ( grayHack )
|
|
|
|
{
|
|
|
|
bool ok;
|
|
|
|
int grayLevel = Conversion::ditheringToGray( shd.ipat, &ok );
|
|
|
|
if ( ok )
|
|
|
|
{
|
|
|
|
TQColor color( 0, 0, grayLevel, TQColor::Hsv );
|
|
|
|
TQString prefix = "bk";
|
|
|
|
frameElementOut.setAttribute( "bkRed", color.red() );
|
|
|
|
frameElementOut.setAttribute( "bkBlue", color.blue() );
|
|
|
|
frameElementOut.setAttribute( "bkGreen", color.green() );
|
|
|
|
}
|
|
|
|
else grayHack = false;
|
|
|
|
}
|
|
|
|
if ( !grayHack )
|
|
|
|
{
|
|
|
|
Conversion::setColorAttributes( frameElementOut, bkColor, "bk", true );
|
|
|
|
// Fill style
|
|
|
|
int brushStyle = Conversion::fillPatternStyle( shd.ipat );
|
|
|
|
frameElementOut.setAttribute( "bkStyle", brushStyle );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::slotSubDocFound( const wvWare::FunctorBase* functor, int data )
|
|
|
|
{
|
|
|
|
SubDocument subdoc( functor, data, TQString(), TQString() );
|
|
|
|
m_subdocQueue.push( subdoc );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::slotTableFound( const KWord::Table& table )
|
|
|
|
{
|
|
|
|
m_tableQueue.push( table );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::slotPictureFound( const TQString& frameName, const TQString& pictureName,
|
|
|
|
const wvWare::FunctorBase* pictureFunctor )
|
|
|
|
{
|
|
|
|
SubDocument subdoc( pictureFunctor, 0, frameName, pictureName );
|
|
|
|
m_subdocQueue.push( subdoc );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Document::processSubDocQueue()
|
|
|
|
{
|
|
|
|
// Table cells can contain footnotes, and footnotes can contain tables [without footnotes though]
|
|
|
|
// This is why we need to repeat until there's nothing more do to (#79024)
|
|
|
|
while ( !m_subdocQueue.empty() || !m_tableQueue.empty() )
|
|
|
|
{
|
|
|
|
while ( !m_subdocQueue.empty() )
|
|
|
|
{
|
|
|
|
SubDocument subdoc( m_subdocQueue.front() );
|
|
|
|
Q_ASSERT( subdoc.functorPtr );
|
|
|
|
(*subdoc.functorPtr)(); // call it
|
|
|
|
delete subdoc.functorPtr; // delete it
|
|
|
|
m_subdocQueue.pop();
|
|
|
|
}
|
|
|
|
while ( !m_tableQueue.empty() )
|
|
|
|
{
|
|
|
|
KWord::Table& table = m_tableQueue.front();
|
|
|
|
m_tableHandler->tableStart( &table );
|
|
|
|
TQValueList<KWord::Row> &rows = table.rows;
|
|
|
|
for( TQValueList<KWord::Row>::Iterator it = rows.begin(); it != rows.end(); ++it ) {
|
|
|
|
KWord::TableRowFunctorPtr f = (*it).functorPtr;
|
|
|
|
Q_ASSERT( f );
|
|
|
|
(*f)(); // call it
|
|
|
|
delete f; // delete it
|
|
|
|
}
|
|
|
|
m_tableHandler->tableEnd();
|
|
|
|
m_tableQueue.pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KoStoreDevice* Document::createPictureFrameSet( const KoSize& size )
|
|
|
|
{
|
|
|
|
// Grab data that was stored with the functor, that triggered this parsing
|
|
|
|
SubDocument subdoc( m_subdocQueue.front() );
|
|
|
|
|
|
|
|
TQDomElement framesetElement = m_mainDocument.createElement("FRAMESET");
|
|
|
|
framesetElement.setAttribute( "frameType", 2 /*picture*/ );
|
|
|
|
framesetElement.setAttribute( "frameInfo", 0 );
|
|
|
|
framesetElement.setAttribute( "name", subdoc.name );
|
|
|
|
m_framesetsElement.appendChild(framesetElement);
|
|
|
|
|
|
|
|
// The position doesn't matter as long as the picture is inline
|
|
|
|
// FIXME for non-inline pics ####
|
|
|
|
// To determine the size, look at OOo's filter (WW8PicDesc in ww8graf2.cxx, version 1.50, line 406)
|
|
|
|
// Hint: #i17200#, a bit of guesswork I'm afraid
|
|
|
|
// if (aPic.dxaGoal == 1000 && aPic.mx == 1) //100% hack ? (from ww8graf2.cxx)
|
|
|
|
createInitialFrame( framesetElement, 0, size.width(), 0, size.height(), false, NoFollowup );
|
|
|
|
|
|
|
|
TQDomElement pictureElem = m_mainDocument.createElement("PICTURE");
|
|
|
|
framesetElement.appendChild( pictureElem );
|
|
|
|
|
|
|
|
TQDomElement keyElem = m_mainDocument.createElement("KEY");
|
|
|
|
pictureElem.appendChild( keyElem );
|
|
|
|
keyElem.setAttribute( "filename", subdoc.extraName );
|
|
|
|
m_pictureList.append( subdoc.extraName );
|
|
|
|
|
|
|
|
kdDebug(30513) << "Preparing to write picture for '" << subdoc.name << "' into " << subdoc.extraName << endl;
|
|
|
|
return m_chain->storageFile( subdoc.extraName, KoStore::Write );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#include "document.moc"
|