You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/filters/kword/msword/conversion.cpp

459 lines
14 KiB

/* 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 "conversion.h"
#include <wv2/word97_generated.h>
#include <wv2/functordata.h>
#include <wv2/fields.h>
#include <kdebug.h>
#include <tqregexp.h>
#include <tqdom.h>
#include <tdelocale.h>
TQColor Conversion::color(int number, int defaultcolor, bool defaultWhite)
{
switch(number)
{
case 0:
if(defaultWhite)
return TQt::white;
case 1:
return TQt::black;
case 2:
return TQt::blue;
case 3:
return TQt::cyan;
case 4:
return TQt::green;
case 5:
return TQt::magenta;
case 6:
return TQt::red;
case 7:
return TQt::yellow;
case 8:
return TQt::white;
case 9:
return TQt::darkBlue;
case 10:
return TQt::darkCyan;
case 11:
return TQt::darkGreen;
case 12:
return TQt::darkMagenta;
case 13:
return TQt::darkRed;
case 14:
return TQt::darkYellow;
case 15:
return TQt::darkGray;
case 16:
return TQt::lightGray;
default:
kdDebug(30513) << "Conversion::color: unknown color: " << number << endl;
if(defaultcolor == -1)
return TQColor("black");
else
return color(defaultcolor, -1);
}
}
int Conversion::fillPatternStyle( int ipat )
{
// See $TQTDIR/doc/html/qbrush.html#setStyle
switch( ipat ) {
case 0: // Automatic (Apparently it means Solid from background color instead of foreground)
case 1: // Solid
return TQt::SolidPattern;
case 2: // 5%
case 35: // 2.5 Percent
case 36: // 7.5 Percent
return TQt::Dense7Pattern;
case 3: // 10%
case 37: // 12.5 Percent
case 38: // 15 Percent
case 39: // 17.5 Percent
case 4: // 20%
return TQt::Dense6Pattern;
case 40: // 22.5 Percent
case 5: // 25%
case 41: // 27.5 Percent
case 6: // 30%
case 42: // 32.5 Percent
case 43: // 35 Percent
case 44: // 37.5 Percent
case 7: // 40%
return TQt::Dense5Pattern;
case 45: // 42.5 Percent
case 46: // 45 Percent
case 47: // 47.5 Percent
case 8: // 50%
case 48: // 52.5 Percent
case 49: // 55 Percent
return TQt::Dense4Pattern;
case 50: // 57.5 Percent
case 9: // 60%
case 51: // 62.5 Percent
case 52: // 65 Percent
case 53: // 67.5 Percent
case 10: // 70%
case 54: // 72.5 Percent
return TQt::Dense3Pattern;
case 11: // 75%
case 55: // 77.5 Percent
case 12: // 80%
case 56: // 82.5 Percent
case 57: // 85 Percent
case 58: // 87.5 Percent
case 13: // 90%
return TQt::Dense2Pattern;
case 59: // 92.5 Percent
case 60: // 95 Percent
case 61: // 97.5 Percent
case 62: // 97 Percent
return TQt::Dense1Pattern;
case 14: // DarkQt::Horizontal
case 20: //Qt::Horizontal
return TQt::HorPattern;
case 15: // DarkQt::Vertical
case 21: //Qt::Vertical
return TQt::VerPattern;
case 16: // Dark Forward Diagonal
case 22: // Forward Diagonal
return TQt::FDiagPattern;
case 17: // Dark Backward Diagonal
case 23: // Backward Diagonal
return TQt::BDiagPattern;
case 18: // Dark Cross
case 24: // Cross
return TQt::CrossPattern;
case 19: // Dark Diagonal Cross
case 25: // Diagonal Cross
return TQt::DiagCrossPattern;
default:
kdWarning(30513) << "Unhandled undocumented SHD ipat value: " << ipat << endl;
return TQt::NoBrush;
}
}
int Conversion::ditheringToGray( int ipat, bool* ok )
{
*ok = true; // optimistic ;)
switch( ipat ) {
case 2: // 5%
return 255 - tqRound(0.05 * 255);
case 35: // 2.5 Percent
return 255 - tqRound(0.025 * 255);
case 36: // 7.5 Percent
return 255 - tqRound(0.075 * 255);
case 3: // 10%
return 255 - tqRound(0.1 * 255);
case 37: // 12.5 Percent
return 255 - tqRound(0.125 * 255);
case 38: // 15 Percent
return 255 - tqRound(0.15 * 255);
case 39: // 17.5 Percent
return 255 - tqRound(0.175 * 255);
case 4: // 20%
return 255 - tqRound(0.2 * 255);
case 40: // 22.5 Percent
return 255 - tqRound(0.225 * 255);
case 5: // 25%
return 255 - tqRound(0.25 * 255);
case 41: // 27.5 Percent
return 255 - tqRound(0.275 * 255);
case 6: // 30%
return 255 - tqRound(0.3 * 255);
case 42: // 32.5 Percent
return 255 - tqRound(0.325 * 255);
case 43: // 35 Percent
return 255 - tqRound(0.35 * 255);
case 44: // 37.5 Percent
return 255 - tqRound(0.375 * 255);
case 7: // 40%
return 255 - tqRound(0.4 * 255);
case 45: // 42.5 Percent
return 255 - tqRound(0.425 * 255);
case 46: // 45 Percent
return 255 - tqRound(0.45 * 255);
case 47: // 47.5 Percent
return 255 - tqRound(0.475 * 255);
case 8: // 50%
return 255 - tqRound(0.5 * 255);
case 48: // 52.5 Percent
return 255 - tqRound(0.525 * 255);
case 49: // 55 Percent
return 255 - tqRound(0.55 * 255);
case 50: // 57.5 Percent
return 255 - tqRound(0.575 * 255);
case 9: // 60%
return 255 - tqRound(0.6 * 255);
case 51: // 62.5 Percent
return 255 - tqRound(0.625 * 255);
case 52: // 65 Percent
return 255 - tqRound(0.65 * 255);
case 53: // 67.5 Percent
return 255 - tqRound(0.675 * 255);
case 10: // 70%
return 255 - tqRound(0.7 * 255);
case 54: // 72.5 Percent
return 255 - tqRound(0.725 * 255);
case 11: // 75%
return 255 - tqRound(0.75 * 255);
case 55: // 77.5 Percent
return 255 - tqRound(0.775 * 255);
case 12: // 80%
return 255 - tqRound(0.8 * 255);
case 56: // 82.5 Percent
return 255 - tqRound(0.825 * 255);
case 57: // 85 Percent
return 255 - tqRound(0.85 * 255);
case 58: // 87.5 Percent
return 255 - tqRound(0.875 * 255);
case 13: // 90%
return 255 - tqRound(0.9 * 255);
case 59: // 92.5 Percent
return 255 - tqRound(0.925 * 255);
case 60: // 95 Percent
return 255 - tqRound(0.95 * 255);
case 61: // 97.5 Percent
return 255 - tqRound(0.975 * 255);
case 62: // 97 Percent
return 255 - tqRound(0.97 * 255);
default:
*ok = false;
return 0;
}
}
TQString Conversion::alignment( int jc ) {
TQString value( "left" );
if ( jc == 1 )
value = "center";
else if ( jc == 2 )
value = "right";
else if ( jc == 3 )
value = "justify";
return value;
}
TQString Conversion::lineSpacing( const wvWare::Word97::LSPD& lspd )
{
TQString value( "0" );
if ( lspd.fMultLinespace == 1 )
{
// This will be e.g. 1.5 for a 1.5 linespacing.
float proportionalLineSpacing = (float)lspd.dyaLine / 240.0;
if ( TQABS(proportionalLineSpacing - 1.5) <= 0.25 ) // close to 1.5?
value = "oneandhalf";
else if ( proportionalLineSpacing > 1.75) // close to 2.0, or more?
value = "double";
}
else if ( lspd.fMultLinespace == 0 )
{
// see sprmPDyaLine in generator_wword8.htm
//float value = TQABS((float)lspd.dyaLine / 20.0); // twip -> pt
// lspd.dyaLine > 0 means "at least", < 0 means "exactly"
// "at least" is now possible in kword, but here it's the size of the whole
// line, not the spacing between the line (!)
// To convert between the two, we'd need to find out the height of the
// highest character in the line, and substract it from the value..... Ouch.
// Better implement line-height-at-least like OOo has.
}
else
kdWarning(30513) << "Unhandled LSPD::fMultLinespace value: " << lspd.fMultLinespace << endl;
return value;
}
void Conversion::setColorAttributes( TQDomElement& element, int ico, const TQString& prefix, bool defaultWhite )
{
TQColor color = Conversion::color( ico, -1, defaultWhite );
element.setAttribute( prefix.isNull() ? "red" : prefix+"Red", color.red() );
element.setAttribute( prefix.isNull() ? "blue" : prefix+"Blue", color.blue() );
element.setAttribute( prefix.isNull() ? "green" : prefix+"Green", color.green() );
}
void Conversion::setBorderAttributes( TQDomElement& borderElement, const wvWare::Word97::BRC& brc, const TQString& prefix )
{
setColorAttributes( borderElement, brc.cv, prefix, false );
borderElement.setAttribute( prefix.isNull() ? "width" : prefix+"Width",
(double)brc.dptLineWidth / 8.0 );
TQString style = "0"; // KWord: solid
switch ( brc.brcType ) {
case 0: // none
Q_ASSERT( brc.dptLineWidth == 0 ); // otherwise kword will show a border!
break;
case 7: // dash large gap
case 22: // dash small gap
style = "1"; // KWord: dashes
break;
case 6: // dot
style = "2";
break;
case 8: // dot dash
style = "3";
break;
case 9: // dot dot dash
style = "4";
break;
case 3: // double
style = "5";
break;
case 1: // single
default:
// if a fancy unsupported border is specified -> better a normal border than none
// (so we keep the default value, "0", for "solid single line".
break;
}
borderElement.setAttribute( prefix.isNull() ? "style" : prefix+"Style", style );
// We ignore brc.dptSpace (spacing), brc.fShadow (shadow), and brc.fFrame (?)
}
int Conversion::numberFormatCode( int nfc )
{
switch ( nfc )
{
case 1: // upper case roman
return 5;
case 2: // lower case roman
return 4;
case 3: // upper case letter
return 3;
case 4: // lower case letter
return 2;
case 5: // arabic with a trailing dot (added by writeCounter)
case 6: // numbered (one, two, three) - not supported by KWord
case 7: // ordinal (first, second, third) - not supported by KWord
case 22: // leading zero (01-09, 10-99, 100-...) - not supported by KWord
case 0: // arabic
return 1;
}
kdWarning(30513) << k_funcinfo << "Unknown NFC: " << nfc << endl;
return 1;
}
int Conversion::headerTypeToFrameInfo( unsigned char type )
{
switch (type) {
case wvWare::HeaderData::HeaderEven:
return 2;
case wvWare::HeaderData::HeaderOdd:
return 3;
case wvWare::HeaderData::FooterEven:
return 5;
case wvWare::HeaderData::FooterOdd:
return 6;
case wvWare::HeaderData::HeaderFirst:
return 1;
case wvWare::HeaderData::FooterFirst:
return 4;
}
return 0;
}
TQString Conversion::headerTypeToFramesetName( unsigned char type )
{
switch (type) {
case wvWare::HeaderData::HeaderEven:
return i18n("Even Pages Header");
case wvWare::HeaderData::HeaderOdd:
return i18n("Odd Pages Header");
case wvWare::HeaderData::FooterEven:
return i18n("Even Pages Footer");
case wvWare::HeaderData::FooterOdd:
return i18n("Odd Pages Footer");
case wvWare::HeaderData::HeaderFirst:
return i18n("First Page Header");
case wvWare::HeaderData::FooterFirst:
return i18n("First Page Footer");
}
return TQString();
}
bool Conversion::isHeader( unsigned char type )
{
switch (type) {
case wvWare::HeaderData::HeaderEven:
case wvWare::HeaderData::HeaderOdd:
case wvWare::HeaderData::HeaderFirst:
return true;
}
return false;
}
int Conversion::headerMaskToHType( unsigned char mask )
{
bool hasFirst = ( mask & wvWare::HeaderData::HeaderFirst );
// Odd is always there. We have even!=odd only if Even is there too.
bool hasEvenOdd = ( mask & wvWare::HeaderData::HeaderEven );
//kdDebug(30513) << k_funcinfo << " hasEvenOdd=" << hasEvenOdd << endl;
if ( hasFirst )
return hasEvenOdd ? 1 : 2;
return hasEvenOdd ? 3 : 0;
}
int Conversion::headerMaskToFType( unsigned char mask )
{
bool hasFirst = ( mask & wvWare::HeaderData::FooterFirst );
bool hasEvenOdd = ( mask & wvWare::HeaderData::FooterEven );
// Odd is always there. We have even!=odd only if Even is there too.
kdDebug(30513) << k_funcinfo << " hasEvenOdd=" << hasEvenOdd << endl;
if ( hasFirst )
return hasEvenOdd ? 1 : 2;
return hasEvenOdd ? 3 : 0;
}
int Conversion::fldToFieldType( const wvWare::FLD* fld )
{
// assume unhandled
int m_fieldType = -1;
// sanity check
if( !fld ) return -1;
switch( fld->flt )
{
case 15: m_fieldType = 10; break; // title
case 17: m_fieldType = 2; break; // author
case 18: m_fieldType = -1; break; // keywords (unhandled)
case 19: m_fieldType = 11; break; // comments (unhandled)
case 21: m_fieldType = -1; break; // createdate (unhandled)
case 22: m_fieldType = -1; break; // savedate (unhandled)
case 23: m_fieldType = -1; break; // printdate (unhandled)
case 25: m_fieldType = -1; break; // edittime (unhandled)
case 29: m_fieldType = 0; break; // filename (unhandled)
case 32: m_fieldType = -1; break; // time (unhandled)
case 60: m_fieldType = 2; break; // username <-> KWord's author name
case 61: m_fieldType = 16; break; // userinitials <-> KWord's author initial)
case 62: m_fieldType = -1; break; // useraddress (unhandled)
default: m_fieldType = -1; break;
}
if( m_fieldType < 0 )
kdDebug(30513) << "unhandled field: fld.ftl: " << (int)fld->flt << endl;
return m_fieldType;
}