|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2002 Ariya Hidayat <ariya@kde.org>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <tqtextcodec.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqvaluevector.h>
|
|
|
|
|
|
|
|
#include <KWEFBaseWorker.h>
|
|
|
|
#include <KWEFKWordLeader.h>
|
|
|
|
#include <KWEFUtil.h>
|
|
|
|
|
|
|
|
#include <wp6.h>
|
|
|
|
|
|
|
|
bool WPSixWorker::doOpenFile(const TQString& filenameOut, const TQString& /*to*/)
|
|
|
|
{
|
|
|
|
filename = filenameOut;
|
|
|
|
outfile.setName( filename );
|
|
|
|
if( !outfile.open( IO_WriteOnly ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
output.setDevice( &outfile );
|
|
|
|
output.setByteOrder (TQDataStream::LittleEndian);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WPSixWorker::doCloseFile(void)
|
|
|
|
{
|
|
|
|
// asssume we're at the end of the file
|
|
|
|
TQ_UINT32 total_filesize = outfile.at();
|
|
|
|
|
|
|
|
// close the file first
|
|
|
|
outfile.close();
|
|
|
|
|
|
|
|
// reopen for read and write
|
|
|
|
if( !outfile.open( IO_ReadWrite ) )
|
|
|
|
return false;
|
|
|
|
output.setDevice( &outfile );
|
|
|
|
|
|
|
|
// now it's time to fix-up some header fields
|
|
|
|
|
|
|
|
// fix for offset 12, int32, filesize
|
|
|
|
outfile.at( 20 );
|
|
|
|
output << total_filesize;
|
|
|
|
|
|
|
|
// offset 4, int32, pointer to document area
|
|
|
|
outfile.at( 4 );
|
|
|
|
output << document_area_ptr;
|
|
|
|
|
|
|
|
outfile.close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WPSixWorker::doOpenDocument(void)
|
|
|
|
{
|
|
|
|
// write WP document header
|
|
|
|
// note that some fields are still "dummy"
|
|
|
|
|
|
|
|
// magic id: -1, "WPC"
|
|
|
|
TQ_UINT8 magic[] = { 0xff, 0x57, 0x50, 0x43 };
|
|
|
|
for( int i=0; i<4; i++ ) output << magic[i];
|
|
|
|
|
|
|
|
// pointer to document area (dummy, will be fixed later)
|
|
|
|
TQ_UINT8 docptr[] = { 0x0E, 0x02, 0x00, 0x00 } ;
|
|
|
|
for( int i=0; i<4; i++ ) output << docptr[i];
|
|
|
|
|
|
|
|
// write product type ( 1 = WordPerfect )
|
|
|
|
TQ_UINT8 product_type = 1;
|
|
|
|
output << product_type;
|
|
|
|
|
|
|
|
// write file type ( 10 = WordPerfect document )
|
|
|
|
TQ_UINT8 file_type = 10;
|
|
|
|
output << file_type;
|
|
|
|
|
|
|
|
// write version (TODO explain)
|
|
|
|
TQ_UINT16 version = 0x0202;
|
|
|
|
output << version;
|
|
|
|
|
|
|
|
// write encryption flag ( 0 = not encrypted )
|
|
|
|
TQ_UINT16 encrypt = 0;
|
|
|
|
output << encrypt;
|
|
|
|
|
|
|
|
// offset to index header (always 0x200?)
|
|
|
|
TQ_UINT16 index_header_ptr = 0x200;
|
|
|
|
output << index_header_ptr;
|
|
|
|
|
|
|
|
// beginning of extended file header (always 5)
|
|
|
|
TQ_UINT32 extheader = 5;
|
|
|
|
output << extheader;
|
|
|
|
|
|
|
|
// filesize (dummy, will be fixed later)
|
|
|
|
TQ_UINT32 filesize = 0;
|
|
|
|
output << filesize;
|
|
|
|
|
|
|
|
// filler 488 bytes
|
|
|
|
TQ_UINT8 dummy = 0;
|
|
|
|
for( int i=0; i<488; i++ ) output << dummy;
|
|
|
|
|
|
|
|
// index header (specified 0 index!)
|
|
|
|
TQ_UINT8 index_header[] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
|
|
0, 0, 0, 0 };
|
|
|
|
for( int i=0; i<14; i++ ) output << index_header[i];
|
|
|
|
|
|
|
|
// document area starts, mark it for the header fields
|
|
|
|
document_area_ptr = output.device()->at();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WPSixWorker::doCloseDocument(void)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// this helper functions "escape" plain Unicode string to WP-compliance string
|
|
|
|
// what it does: converting spaces and tabs to hard-spaces and hard-tabs
|
|
|
|
// TODO handle Unicode characters using WP charsets
|
|
|
|
static TQCString WPSixEscape( const TQString& text )
|
|
|
|
{
|
|
|
|
TQCString result;
|
|
|
|
|
|
|
|
for( unsigned int i=0; i < text.length(); i++ )
|
|
|
|
{
|
|
|
|
int c = text[i].unicode();
|
|
|
|
if( c < 32 ) result += '.';
|
|
|
|
else if ( c == 32 ) result += 0x80 ; // hard space
|
|
|
|
else if ( c < 128 ) result += text[i].latin1();
|
|
|
|
else result += '.';
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool WPSixWorker::doFullParagraph(const TQString& paraText,
|
|
|
|
const LayoutData& layout, const ValueListFormatData& paraFormatDataList)
|
|
|
|
{
|
|
|
|
// handle paragraph alignment/justification (default to left)
|
|
|
|
unsigned char wp_align[] = { 0xd3, 5, 12, 0, 0, 1, 0, 0, 2, 12, 0, 0xd3 };
|
|
|
|
if( layout.alignment == "left" ) wp_align[7] = 0;
|
|
|
|
if( layout.alignment == "justify" ) wp_align[7] = 1;
|
|
|
|
if( layout.alignment == "center" ) wp_align[7] = 2;
|
|
|
|
if( layout.alignment == "right" ) wp_align[7] = 3;
|
|
|
|
output.writeRawBytes( (const char*)wp_align, 12 );
|
|
|
|
|
|
|
|
ValueListFormatData::ConstIterator it;
|
|
|
|
for( it = paraFormatDataList.begin(); it!=paraFormatDataList.end(); ++it )
|
|
|
|
{
|
|
|
|
const FormatData& formatData = *it;
|
|
|
|
|
|
|
|
// only if the format is for text (id==1)
|
|
|
|
if( formatData.id == 1 )
|
|
|
|
{
|
|
|
|
|
|
|
|
TQ_UINT8 attr = 0; //invalid
|
|
|
|
if( formatData.text.weight >= 75 ) attr = 12; // bold
|
|
|
|
if( formatData.text.italic ) attr = 8;
|
|
|
|
if( formatData.text.underline )
|
|
|
|
{
|
|
|
|
if( formatData.text.underlineValue == "double" )
|
|
|
|
attr = 11; // double underline
|
|
|
|
else
|
|
|
|
attr = 14; // single underline
|
|
|
|
}
|
|
|
|
if( formatData.text.verticalAlignment == 1 ) attr = 6; //subscript
|
|
|
|
if( formatData.text.verticalAlignment == 2 ) attr = 5; //superscript
|
|
|
|
if( formatData.text.strikeout ) attr = 13;
|
|
|
|
|
|
|
|
TQColor fgColor = formatData.text.fgColor;
|
|
|
|
TQColor bgColor = formatData.text.bgColor;
|
|
|
|
|
|
|
|
// due to the file format, before writing the text we must
|
|
|
|
// write some refix-code (such as Bold On) and possibly appropriate suffix-code (Bold Off)
|
|
|
|
|
|
|
|
// attribute on
|
|
|
|
if( attr > 0 ) output << (TQ_UINT8)0xf2 << attr << (TQ_UINT8)0xf2;
|
|
|
|
|
|
|
|
// set font color
|
|
|
|
if( fgColor.isValid() )
|
|
|
|
{
|
|
|
|
TQ_UINT8 wp_color[] = { 0xd4, 0x18, 16, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0xd4 };
|
|
|
|
wp_color[7] = (TQ_UINT8) fgColor.red();
|
|
|
|
wp_color[8] = (TQ_UINT8) fgColor.green();
|
|
|
|
wp_color[9] = (TQ_UINT8) fgColor.blue();
|
|
|
|
output.writeRawBytes( (const char*)wp_color, 16 );
|
|
|
|
}
|
|
|
|
|
|
|
|
// highlight on (background color)
|
|
|
|
if( bgColor.isValid() )
|
|
|
|
{
|
|
|
|
output << (TQ_UINT8) 0xfb;
|
|
|
|
output << (TQ_UINT8)bgColor.red() << (TQ_UINT8)bgColor.green() << (TQ_UINT8)bgColor.blue();
|
|
|
|
output << (TQ_UINT8) 100 << (TQ_UINT8) 0xfb;
|
|
|
|
}
|
|
|
|
|
|
|
|
// the text itself, "escape" it first
|
|
|
|
TQCString out = WPSixEscape( paraText.mid( formatData.pos, formatData.len ) );
|
|
|
|
output.writeRawBytes( (const char*)out, out.length() );
|
|
|
|
|
|
|
|
// attribute off
|
|
|
|
if( attr > 0 ) output << (TQ_UINT8)0xf3 << attr << (TQ_UINT8)0xf3;
|
|
|
|
|
|
|
|
// highlight off
|
|
|
|
if( bgColor.isValid() )
|
|
|
|
{
|
|
|
|
output << (TQ_UINT8) 0xfc;
|
|
|
|
output << (TQ_UINT8)bgColor.red() << (TQ_UINT8)bgColor.green() << (TQ_UINT8)bgColor.blue();
|
|
|
|
output << (TQ_UINT8) 100 << (TQ_UINT8) 0xfc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// write hard-return
|
|
|
|
output << (TQ_UINT8) 0xcc;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|