~ubuntu-branches/ubuntu/breezy/koffice/breezy

« back to all changes in this revision

Viewing changes to filters/kword/msword/conversion.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Ben Burton
  • Date: 2004-05-09 11:33:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040509113300-vfrdadqsvjfuhn3b
Tags: 1:1.3.1-1
* New upstream bugfix release.
* Built against newer imagemagick (closes: #246623).
* Made koffice-libs/kformula recommend/depend on latex-xft-fonts, which
  provides mathematical fonts that the formula editor can use.  Also
  patched the kformula part to make these fonts the default.
* Changed kword menu hint from "WordProcessors" to "Word processors"
  (closes: #246209).
* Spellchecker configuration is now fixed (closes: #221256, #227568).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of the KOffice project
 
2
   Copyright (C) 2002 Werner Trobin <trobin@kde.org>
 
3
   Copyright (C) 2002 David Faure <faure@kde.org>
 
4
 
 
5
   This program is free software; you can redistribute it and/or
 
6
   modify it under the terms of the GNU General Public
 
7
   License version 2 as published by the Free Software Foundation.
 
8
 
 
9
   This program is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
    General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License
 
15
   along with this program; see the file COPYING.  If not, write to
 
16
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
   Boston, MA 02111-1307, USA.
 
18
*/
 
19
 
 
20
#include "conversion.h"
 
21
 
 
22
#include <wv2/word97_generated.h>
 
23
#include <wv2/functordata.h>
 
24
#include <wv2/fields.h>
 
25
 
 
26
#include <kdebug.h>
 
27
#include <qregexp.h>
 
28
#include <qdom.h>
 
29
#include <klocale.h>
 
30
 
 
31
QColor Conversion::color(int number, int defaultcolor, bool defaultWhite)
 
32
{
 
33
    switch(number)
 
34
    {
 
35
        case 0:
 
36
            if(defaultWhite)
 
37
                return Qt::white;
 
38
        case 1:
 
39
            return Qt::black;
 
40
        case 2:
 
41
            return Qt::blue;
 
42
        case 3:
 
43
            return Qt::cyan;
 
44
        case 4:
 
45
            return Qt::green;
 
46
        case 5:
 
47
            return Qt::magenta;
 
48
        case 6:
 
49
            return Qt::red;
 
50
        case 7:
 
51
            return Qt::yellow;
 
52
        case 8:
 
53
            return Qt::white;
 
54
        case 9:
 
55
            return Qt::darkBlue;
 
56
        case 10:
 
57
            return Qt::darkCyan;
 
58
        case 11:
 
59
            return Qt::darkGreen;
 
60
        case 12:
 
61
            return Qt::darkMagenta;
 
62
        case 13:
 
63
            return Qt::darkRed;
 
64
        case 14:
 
65
            return Qt::darkYellow;
 
66
        case 15:
 
67
            return Qt::darkGray;
 
68
        case 16:
 
69
            return Qt::lightGray;
 
70
 
 
71
        default:
 
72
            kdDebug() << "Conversion::color: unknown color: " << number << endl;
 
73
            if(defaultcolor == -1)
 
74
                return QColor("black");
 
75
            else
 
76
                return color(defaultcolor, -1);
 
77
    }
 
78
}
 
79
 
 
80
int Conversion::fillPatternStyle( int ipat )
 
81
{
 
82
    // See $QTDIR/doc/html/qbrush.html#setStyle
 
83
    switch( ipat )  {
 
84
    case 0: // Automatic (Apparently it means Solid from background color instead of foreground)
 
85
    case 1: // Solid
 
86
        return Qt::SolidPattern;
 
87
    case 2: // 5%
 
88
    case 35: // 2.5 Percent
 
89
    case 36: // 7.5 Percent
 
90
        return Qt::Dense7Pattern;
 
91
    case 3: // 10%
 
92
    case 37: // 12.5 Percent
 
93
    case 38: // 15 Percent
 
94
    case 39: // 17.5 Percent
 
95
    case 4: // 20%
 
96
        return Qt::Dense6Pattern;
 
97
    case 40: // 22.5 Percent
 
98
    case 5: // 25%
 
99
    case 41: // 27.5 Percent
 
100
    case 6: // 30%
 
101
    case 42: // 32.5 Percent
 
102
    case 43: // 35 Percent
 
103
    case 44: // 37.5 Percent
 
104
    case 7: // 40%
 
105
        return Qt::Dense5Pattern;
 
106
    case 45: // 42.5 Percent
 
107
    case 46: // 45 Percent
 
108
    case 47: // 47.5 Percent
 
109
    case 8: // 50%
 
110
    case 48: // 52.5 Percent
 
111
    case 49: // 55 Percent
 
112
        return Qt::Dense4Pattern;
 
113
    case 50: // 57.5 Percent
 
114
    case 9: // 60%
 
115
    case 51: // 62.5 Percent
 
116
    case 52: // 65 Percent
 
117
    case 53: // 67.5 Percent
 
118
    case 10: // 70%
 
119
    case 54: // 72.5 Percent
 
120
        return Qt::Dense3Pattern;
 
121
    case 11: // 75%
 
122
    case 55: // 77.5 Percent
 
123
    case 12: // 80%
 
124
    case 56: // 82.5 Percent
 
125
    case 57: // 85 Percent
 
126
    case 58: // 87.5 Percent
 
127
    case 13: // 90%
 
128
        return Qt::Dense2Pattern;
 
129
    case 59: // 92.5 Percent
 
130
    case 60: // 95 Percent
 
131
    case 61: // 97.5 Percent
 
132
    case 62: // 97 Percent
 
133
        return Qt::Dense1Pattern;
 
134
    case 14: // Dark Horizontal
 
135
    case 20: // Horizontal
 
136
        return Qt::HorPattern;
 
137
    case 15: // Dark Vertical
 
138
    case 21: // Vertical
 
139
        return Qt::VerPattern;
 
140
    case 16: // Dark Forward Diagonal
 
141
    case 22: // Forward Diagonal
 
142
        return Qt::FDiagPattern;
 
143
    case 17: // Dark Backward Diagonal
 
144
    case 23: // Backward Diagonal
 
145
        return Qt::BDiagPattern;
 
146
    case 18: // Dark Cross
 
147
    case 24: // Cross
 
148
        return Qt::CrossPattern;
 
149
    case 19: // Dark Diagonal Cross
 
150
    case 25: // Diagonal Cross
 
151
        return Qt::DiagCrossPattern;
 
152
    default:
 
153
        kdWarning() << "Unhandled undocumented SHD ipat value: " << ipat << endl;
 
154
        return Qt::NoBrush;
 
155
    }
 
156
}
 
157
 
 
158
 
 
159
int Conversion::ditheringToGray( int ipat, bool* ok )
 
160
{
 
161
    *ok = true; // optimistic ;)
 
162
    switch( ipat )  {
 
163
    case 2: // 5%
 
164
        return 255 - qRound(0.05 * 255);
 
165
    case 35: // 2.5 Percent
 
166
        return 255 - qRound(0.025 * 255);
 
167
    case 36: // 7.5 Percent
 
168
        return 255 - qRound(0.075 * 255);
 
169
    case 3: // 10%
 
170
        return 255 - qRound(0.1 * 255);
 
171
    case 37: // 12.5 Percent
 
172
        return 255 - qRound(0.125 * 255);
 
173
    case 38: // 15 Percent
 
174
        return 255 - qRound(0.15 * 255);
 
175
    case 39: // 17.5 Percent
 
176
        return 255 - qRound(0.175 * 255);
 
177
    case 4: // 20%
 
178
        return 255 - qRound(0.2 * 255);
 
179
    case 40: // 22.5 Percent
 
180
        return 255 - qRound(0.225 * 255);
 
181
    case 5: // 25%
 
182
        return 255 - qRound(0.25 * 255);
 
183
    case 41: // 27.5 Percent
 
184
        return 255 - qRound(0.275 * 255);
 
185
    case 6: // 30%
 
186
        return 255 - qRound(0.3 * 255);
 
187
    case 42: // 32.5 Percent
 
188
        return 255 - qRound(0.325 * 255);
 
189
    case 43: // 35 Percent
 
190
        return 255 - qRound(0.35 * 255);
 
191
    case 44: // 37.5 Percent
 
192
        return 255 - qRound(0.375 * 255);
 
193
    case 7: // 40%
 
194
        return 255 - qRound(0.4 * 255);
 
195
    case 45: // 42.5 Percent
 
196
        return 255 - qRound(0.425 * 255);
 
197
    case 46: // 45 Percent
 
198
        return 255 - qRound(0.45 * 255);
 
199
    case 47: // 47.5 Percent
 
200
        return 255 - qRound(0.475 * 255);
 
201
    case 8: // 50%
 
202
        return 255 - qRound(0.5 * 255);
 
203
    case 48: // 52.5 Percent
 
204
        return 255 - qRound(0.525 * 255);
 
205
    case 49: // 55 Percent
 
206
        return 255 - qRound(0.55 * 255);
 
207
    case 50: // 57.5 Percent
 
208
        return 255 - qRound(0.575 * 255);
 
209
    case 9: // 60%
 
210
        return 255 - qRound(0.6 * 255);
 
211
    case 51: // 62.5 Percent
 
212
        return 255 - qRound(0.625 * 255);
 
213
    case 52: // 65 Percent
 
214
        return 255 - qRound(0.65 * 255);
 
215
    case 53: // 67.5 Percent
 
216
        return 255 - qRound(0.675 * 255);
 
217
    case 10: // 70%
 
218
        return 255 - qRound(0.7 * 255);
 
219
    case 54: // 72.5 Percent
 
220
        return 255 - qRound(0.725 * 255);
 
221
    case 11: // 75%
 
222
        return 255 - qRound(0.75 * 255);
 
223
    case 55: // 77.5 Percent
 
224
        return 255 - qRound(0.775 * 255);
 
225
    case 12: // 80%
 
226
        return 255 - qRound(0.8 * 255);
 
227
    case 56: // 82.5 Percent
 
228
        return 255 - qRound(0.825 * 255);
 
229
    case 57: // 85 Percent
 
230
        return 255 - qRound(0.85 * 255);
 
231
    case 58: // 87.5 Percent
 
232
        return 255 - qRound(0.875 * 255);
 
233
    case 13: // 90%
 
234
        return 255 - qRound(0.9 * 255);
 
235
    case 59: // 92.5 Percent
 
236
        return 255 - qRound(0.925 * 255);
 
237
    case 60: // 95 Percent
 
238
        return 255 - qRound(0.95 * 255);
 
239
    case 61: // 97.5 Percent
 
240
        return 255 - qRound(0.975 * 255);
 
241
    case 62: // 97 Percent
 
242
        return 255 - qRound(0.97 * 255);
 
243
    default:
 
244
        *ok = false;
 
245
        return 0;
 
246
    }
 
247
}
 
248
 
 
249
QString Conversion::alignment( int jc ) {
 
250
    QString value( "left" );
 
251
    if ( jc == 1 )
 
252
        value = "center";
 
253
    else if ( jc == 2 )
 
254
        value = "right";
 
255
    else if ( jc == 3 )
 
256
        value = "justify";
 
257
    return value;
 
258
}
 
259
 
 
260
QString Conversion::lineSpacing( const wvWare::Word97::LSPD& lspd )
 
261
{
 
262
    QString value( "0" );
 
263
    if ( lspd.fMultLinespace == 1 )
 
264
    {
 
265
        // This will be e.g. 1.5 for a 1.5 linespacing.
 
266
        float proportionalLineSpacing = (float)lspd.dyaLine / 240.0;
 
267
        if ( QABS(proportionalLineSpacing - 1.5) <= 0.25 ) // close to 1.5?
 
268
            value = "oneandhalf";
 
269
        else if ( proportionalLineSpacing > 1.75) // close to 2.0, or more?
 
270
            value = "double";
 
271
    }
 
272
    else if ( lspd.fMultLinespace == 0 )
 
273
    {
 
274
        // see sprmPDyaLine in generator_wword8.htm
 
275
        //float value = QABS((float)lspd.dyaLine / 20.0); // twip -> pt
 
276
        // lspd.dyaLine > 0 means "at least", < 0 means "exactly"
 
277
        // "at least" is now possible in kword, but here it's the size of the whole
 
278
        // line, not the spacing between the line (!)
 
279
        // To convert between the two, we'd need to find out the height of the
 
280
        // highest character in the line, and substract it from the value..... Ouch.
 
281
        // Better implement line-height-at-least like OOo has.
 
282
    }
 
283
    else
 
284
        kdWarning() << "Unhandled LSPD::fMultLinespace value: " << lspd.fMultLinespace << endl;
 
285
    return value;
 
286
}
 
287
 
 
288
void Conversion::setColorAttributes( QDomElement& element, int ico, const QString& prefix, bool defaultWhite )
 
289
{
 
290
    QColor color = Conversion::color( ico, -1, defaultWhite );
 
291
    element.setAttribute( prefix.isNull() ? "red" : prefix+"Red", color.red() );
 
292
    element.setAttribute( prefix.isNull() ? "blue" : prefix+"Blue", color.blue() );
 
293
    element.setAttribute( prefix.isNull() ? "green" : prefix+"Green", color.green() );
 
294
}
 
295
 
 
296
void Conversion::setBorderAttributes( QDomElement& borderElement, const wvWare::Word97::BRC& brc, const QString& prefix )
 
297
{
 
298
    setColorAttributes( borderElement, brc.ico, prefix, false );
 
299
 
 
300
    borderElement.setAttribute( prefix.isNull() ? "width" : prefix+"Width",
 
301
                                (double)brc.dptLineWidth / 8.0 );
 
302
 
 
303
    QString style = "0"; // KWord: solid
 
304
    switch ( brc.brcType ) {
 
305
    case 0: // none
 
306
        Q_ASSERT( brc.dptLineWidth == 0 ); // otherwise kword will show a border!
 
307
        break;
 
308
    case 7: // dash large gap
 
309
    case 22: // dash small gap
 
310
        style = "1"; // KWord: dashes
 
311
        break;
 
312
    case 6: // dot
 
313
        style = "2";
 
314
        break;
 
315
    case 8: // dot dash
 
316
        style = "3";
 
317
        break;
 
318
    case 9: // dot dot dash
 
319
        style = "4";
 
320
        break;
 
321
    case 3: // double
 
322
        style = "5";
 
323
        break;
 
324
    case 1: // single
 
325
    default:
 
326
        // if a fancy unsupported border is specified -> better a normal border than none
 
327
        // (so we keep the default value, "0", for "solid single line".
 
328
        break;
 
329
    }
 
330
    borderElement.setAttribute( prefix.isNull() ? "style" : prefix+"Style", style );
 
331
    // We ignore brc.dptSpace (spacing), brc.fShadow (shadow), and brc.fFrame (?)
 
332
}
 
333
 
 
334
int Conversion::numberFormatCode( int nfc )
 
335
{
 
336
    switch ( nfc )
 
337
    {
 
338
    case 1: // upper case roman
 
339
        return 5;
 
340
    case 2: // lower case roman
 
341
        return 4;
 
342
    case 3: // upper case letter
 
343
        return 3;
 
344
    case 4: // lower case letter
 
345
        return 2;
 
346
    case 5: // arabic with a trailing dot (added by writeCounter)
 
347
    case 6: // numbered (one, two, three) - not supported by KWord
 
348
    case 7: // ordinal (first, second, third) - not supported by KWord
 
349
    case 22: // leading zero (01-09, 10-99, 100-...) - not supported by KWord
 
350
    case 0: // arabic
 
351
        return 1;
 
352
    }
 
353
    kdWarning() << k_funcinfo << "Unknown NFC: " << nfc << endl;
 
354
    return 1;
 
355
}
 
356
 
 
357
int Conversion::headerTypeToFrameInfo( unsigned char type )
 
358
{
 
359
    switch (type) {
 
360
    case wvWare::HeaderData::HeaderEven:
 
361
        return 2;
 
362
    case wvWare::HeaderData::HeaderOdd:
 
363
        return 3;
 
364
    case wvWare::HeaderData::FooterEven:
 
365
        return 5;
 
366
    case wvWare::HeaderData::FooterOdd:
 
367
        return 6;
 
368
    case wvWare::HeaderData::HeaderFirst:
 
369
        return 1;
 
370
    case wvWare::HeaderData::FooterFirst:
 
371
        return 4;
 
372
    }
 
373
    return 0;
 
374
}
 
375
 
 
376
QString Conversion::headerTypeToFramesetName( unsigned char type )
 
377
{
 
378
    switch (type) {
 
379
    case wvWare::HeaderData::HeaderEven:
 
380
        return i18n("Even Pages Header");
 
381
    case wvWare::HeaderData::HeaderOdd:
 
382
        return i18n("Odd Pages Header");
 
383
    case wvWare::HeaderData::FooterEven:
 
384
        return i18n("Even Pages Footer");
 
385
    case wvWare::HeaderData::FooterOdd:
 
386
        return i18n("Odd Pages Footer");
 
387
    case wvWare::HeaderData::HeaderFirst:
 
388
        return i18n("First Page Header");
 
389
    case wvWare::HeaderData::FooterFirst:
 
390
        return i18n("First Page Footer");
 
391
    }
 
392
    return QString::null;
 
393
}
 
394
 
 
395
bool Conversion::isHeader( unsigned char type )
 
396
{
 
397
    switch (type) {
 
398
    case wvWare::HeaderData::HeaderEven:
 
399
    case wvWare::HeaderData::HeaderOdd:
 
400
    case wvWare::HeaderData::HeaderFirst:
 
401
        return true;
 
402
    }
 
403
    return false;
 
404
}
 
405
 
 
406
int Conversion::headerMaskToHType( unsigned char mask )
 
407
{
 
408
    bool hasFirst = ( mask & wvWare::HeaderData::HeaderFirst );
 
409
    // Odd is always there. We have even!=odd only if Even is there too.
 
410
    bool hasEvenOdd = ( mask & wvWare::HeaderData::HeaderEven );
 
411
    //kdDebug() << k_funcinfo << " hasEvenOdd=" << hasEvenOdd << endl;
 
412
    if ( hasFirst )
 
413
        return hasEvenOdd ? 1 : 2;
 
414
    return hasEvenOdd ? 3 : 0;
 
415
}
 
416
 
 
417
int Conversion::headerMaskToFType( unsigned char mask )
 
418
{
 
419
    bool hasFirst = ( mask & wvWare::HeaderData::FooterFirst );
 
420
    bool hasEvenOdd = ( mask & wvWare::HeaderData::FooterEven );
 
421
    // Odd is always there. We have even!=odd only if Even is there too.
 
422
    kdDebug() << k_funcinfo << " hasEvenOdd=" << hasEvenOdd << endl;
 
423
    if ( hasFirst )
 
424
        return hasEvenOdd ? 1 : 2;
 
425
    return hasEvenOdd ? 3 : 0;
 
426
}
 
427
 
 
428
int Conversion::fldToFieldType( const wvWare::FLD* fld )
 
429
{
 
430
    // assume unhandled
 
431
    int m_fieldType = -1;
 
432
 
 
433
    // sanity check
 
434
    if( !fld ) return -1;
 
435
 
 
436
    switch( fld->flt )
 
437
    {
 
438
    case 15:    m_fieldType = 10; break;  // title
 
439
    case 17:    m_fieldType =  2; break;  // author
 
440
    case 18:    m_fieldType = -1; break;  // keywords (unhandled)
 
441
    case 19:    m_fieldType = 11; break;  // comments (unhandled)
 
442
    case 21:    m_fieldType = -1; break;  // createdate (unhandled)
 
443
    case 22:    m_fieldType = -1; break;  // savedate (unhandled)
 
444
    case 23:    m_fieldType = -1; break;  // printdate (unhandled)
 
445
    case 25:    m_fieldType = -1; break;  // edittime (unhandled)
 
446
    case 29:    m_fieldType =  0; break;  // filename (unhandled)
 
447
    case 32:    m_fieldType = -1; break;  // time (unhandled)
 
448
    case 60:    m_fieldType =  2; break;  // username <-> KWord's author name
 
449
    case 61:    m_fieldType = 16; break;  // userinitials <-> KWord's author initial)
 
450
    case 62:    m_fieldType = -1; break;  // useraddress (unhandled)
 
451
    default:    m_fieldType = -1; break;
 
452
    }
 
453
 
 
454
    if( m_fieldType < 0 )
 
455
        kdDebug() << "unhandled field: fld.ftl: " << (int)fld->flt << endl;
 
456
 
 
457
    return m_fieldType;
 
458
}