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

« back to all changes in this revision

Viewing changes to kword/kwdoc.cc

  • Committer: Bazaar Package Importer
  • Author(s): Jonathan Riddell
  • Date: 2005-10-11 14:49:50 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051011144950-lwpngbifzp8nk0ds
Tags: 1:1.4.1-0ubuntu7
* SECURITY UPDATE: fix heap based buffer overflow in the RTF importer of KWord
* Opening specially crafted RTF files in KWord can cause
  execution of abitrary code.
* Add kubuntu_01_rtfimport_heap_overflow.diff
* References:
  CAN-2005-2971
  CESA-2005-005
  http://www.koffice.org/security/advisory-20051011-1.txt

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* This file is part of the KDE project
2
2
   Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
 
3
   Copyright (C) 2002-2005 David Faure <faure@kde.org>
3
4
 
4
5
   This library is free software; you can redistribute it and/or
5
6
   modify it under the terms of the GNU Library General Public
17
18
   Boston, MA 02111-1307, USA.
18
19
*/
19
20
 
20
 
#include <qfileinfo.h>
21
 
#include <qregexp.h>
22
 
#include <qtimer.h>
23
 
 
24
 
#include <kapplication.h> // for KDE_VERSION
25
 
#include <kdebug.h>
26
 
#if ! KDE_IS_VERSION(3,1,90)
27
 
#include <kdebugclasses.h>
28
 
#endif
29
 
#include <klibloader.h>
30
 
#include <klocale.h>
31
 
#include <kstandarddirs.h>
32
 
#include <kmessagebox.h>
33
 
#include <kspell.h>
34
 
#include <kcursor.h>
35
 
 
36
 
#include <koTemplateChooseDia.h>
37
 
#include <koMainWindow.h>
38
 
#include <koDocumentInfo.h>
39
 
#include <koGlobal.h>
40
 
#include <koparagcounter.h>
41
 
#include <kotextobject.h>
42
 
#include <koAutoFormat.h>
43
 
#include <kovariable.h>
44
 
#include <kformuladocument.h>
45
 
#include <unistd.h>
46
 
#include <math.h>
 
21
#include "kwdoc.h"
47
22
 
48
23
#include "KWordDocIface.h"
49
 
#include "defs.h"
50
24
#include "kwbgspellcheck.h"
 
25
#include "kwbookmark.h"
51
26
#include "kwcanvas.h"
52
27
#include "kwcommand.h"
53
 
#include "kwdoc.h"
54
28
#include "kwformulaframe.h"
55
29
#include "kwframelayout.h"
56
30
#include "kwpartframeset.h"
62
36
#include "kwview.h"
63
37
#include "kwviewmode.h"
64
38
#include "mailmerge.h"
65
 
 
66
 
#include <X11/Xlib.h>
 
39
#include "kwloadinginfo.h"
 
40
#include "paragvisitors.h"
 
41
#include "kwoasisloader.h"
 
42
#include "kwoasissaver.h"
 
43
 
 
44
#include <koPictureCollection.h>
 
45
#include <koTemplateChooseDia.h>
 
46
#include <koMainWindow.h>
 
47
#include <koDocumentInfo.h>
 
48
#include <koGlobal.h>
 
49
#include <koparagcounter.h>
 
50
#include <kotextobject.h>
 
51
#include <koAutoFormat.h>
 
52
#include <kovariable.h>
 
53
#include <kformuladocument.h>
 
54
#include <koApplication.h>
 
55
#include <kooasiscontext.h>
 
56
#include <kocommandhistory.h>
 
57
#include <koGenStyles.h>
 
58
#include <koStore.h>
 
59
#include <koStoreDrag.h>
 
60
#include <koStoreDevice.h>
 
61
#include <koxmlwriter.h>
 
62
#include <koOasisStore.h>
 
63
#include <koOasisStyles.h>
 
64
#include <koxmlns.h>
 
65
#include <kodom.h>
 
66
 
 
67
#include <kcursor.h>
 
68
#include <kdebug.h>
67
69
#include <kglobalsettings.h>
68
 
#include "kocommandhistory.h"
69
 
 
70
 
#include <koSconfig.h>
71
 
 
72
 
#include "koApplication.h"
 
70
#include <klibloader.h>
 
71
#include <kmultipledrag.h>
 
72
#include <klocale.h>
 
73
#include <kmessagebox.h>
 
74
#include <kspell.h>
 
75
#include <kstandarddirs.h>
 
76
 
 
77
#ifdef HAVE_LIBKSPELL2
 
78
#include <kspell2/settings.h>
 
79
#endif
 
80
 
 
81
#include <qfileinfo.h>
 
82
#include <qregexp.h>
 
83
#include <qtimer.h>
 
84
#include <qbuffer.h>
 
85
 
 
86
#include <unistd.h>
 
87
#include <math.h>
73
88
 
74
89
//#define DEBUG_PAGES
75
90
//#define DEBUG_SPEED
78
93
static const char * CURRENT_DTD_VERSION = "1.2";
79
94
 
80
95
/******************************************************************/
81
 
/* Class: KWChild                                              */
82
 
/******************************************************************/
83
 
 
84
 
KWChild::KWChild( KWDocument *_wdoc, const QRect& _rect, KoDocument *_doc )
85
 
    : KoDocumentChild( _wdoc, _doc, _rect ), m_partFrameSet( 0L )
86
 
{
87
 
}
88
 
 
89
 
KWChild::KWChild( KWDocument *_wdoc )
90
 
    : KoDocumentChild( _wdoc ), m_partFrameSet( 0L )
91
 
{
92
 
}
93
 
 
94
 
KWChild::~KWChild()
95
 
{
96
 
}
97
 
 
98
 
KoDocument* KWChild::hitTest( const QPoint& p, const QWMatrix& _matrix )
99
 
{
100
 
    Q_ASSERT( m_partFrameSet );
101
 
    if ( isDeleted() ) {
102
 
        //kdDebug() << k_funcinfo << "is deleted!" << endl;
103
 
        return 0L;
104
 
    }
105
 
    // Only activate when it's already selected.
106
 
    if ( !m_partFrameSet->frame(0)->isSelected() ) {
107
 
        //kdDebug() << k_funcinfo << " is not selected" << endl;
108
 
        return 0L;
109
 
    }
110
 
    // And only if CTRL isn't pressed.
111
 
 
112
 
    Window root;
113
 
    Window child;
114
 
    int root_x, root_y, win_x, win_y;
115
 
    uint keybstate;
116
 
    XQueryPointer( qt_xdisplay(), qt_xrootwin(), &root, &child,
117
 
                   &root_x, &root_y, &win_x, &win_y, &keybstate );
118
 
    if ( keybstate & ControlMask )
119
 
        return 0L;
120
 
 
121
 
    return KoDocumentChild::hitTest( p, _matrix );
122
 
}
123
 
 
124
 
 
125
 
/******************************************************************/
126
96
/* Class: KWCommandHistory                                        */
127
97
/******************************************************************/
128
98
class KWCommandHistory : public KoCommandHistory
161
131
 
162
132
/**
163
133
 * Temporary storage for the initial edition info
164
 
 * (activeFrameset, cursorParagraph and cursorIndex attributes of the XML
 
134
 * (activeFrameset, cursorParagraph and cursorIndex attributes of the XML)
165
135
 */
166
136
class KWDocument::InitialEditing {
167
137
public:
170
140
    int m_initialCursorIndex;
171
141
};
172
142
 
173
 
KWBookMark::KWBookMark(const QString &_name)
174
 
    : m_name(_name),
175
 
      m_startParag(0L),
176
 
      m_endParag(0L),
177
 
      m_frameSet(0L),
178
 
      m_startIndex( 0 ),
179
 
      m_endIndex( 0)
180
 
{
181
 
}
182
 
 
183
 
KWBookMark::KWBookMark(const QString &_name, KoTextParag *_startParag, KoTextParag *_endParag,KWFrameSet *_frameSet, int _pos, int _end)
184
 
    : m_name(_name),
185
 
      m_startParag(_startParag),
186
 
      m_endParag(_endParag),
187
 
      m_frameSet(_frameSet),
188
 
      m_startIndex( _pos ),
189
 
      m_endIndex( _end )
190
 
{
191
 
}
192
 
 
193
 
KWBookMark::~KWBookMark()
194
 
{
195
 
    m_startParag=0L;
196
 
    m_endParag=0L;
197
 
    m_frameSet=0L;
198
 
}
199
 
 
200
143
/******************************************************************/
201
144
/* Class: KWDocument                                              */
202
145
/******************************************************************/
204
147
 
205
148
KWDocument::KWDocument(QWidget *parentWidget, const char *widgetName, QObject* parent, const char* name, bool singleViewMode )
206
149
    : KoDocument( parentWidget, widgetName, parent, name, singleViewMode ),
207
 
      m_unit( KoUnit::U_MM ),
208
150
      m_urlIntern()
209
151
{
 
152
    KWStatisticVariable::setExtendedType(  true );
210
153
    dcop = 0;
 
154
    if (KGlobal::locale()->measureSystem() == KLocale::Imperial) {
 
155
        m_unit = KoUnit::U_INCH;
 
156
    } else {
 
157
        m_unit = KoUnit::U_CM;
 
158
    }
211
159
    m_pages = 1;
 
160
    m_loadingInfo = 0L;
212
161
    m_tabStop = MM_TO_POINT( 15.0 );
213
 
    bgFrameSpellChecked = 0L;
214
162
    m_processingType = WP;
215
163
 
216
 
    m_lstViews.setAutoDelete( false );
217
 
    m_lstChildren.setAutoDelete( true );
218
164
//    varFormats.setAutoDelete(true);
219
165
    m_lstFrameSet.setAutoDelete( true );
220
166
    // m_textImageRequests does not create or delete the KWTextImage classes
225
171
    m_frameStyleColl = new KWFrameStyleCollection();
226
172
    m_tableStyleColl = new KWTableStyleCollection();
227
173
    m_tableTemplateColl = new KWTableTemplateCollection();
 
174
    m_pictureCollection = new KoPictureCollection();
228
175
 
229
176
    m_personalExpressionPath = KWFactory::global()->dirs()->resourceDirs("expression");
230
177
    m_picturePath= KGlobalSettings::documentPath();
245
192
 
246
193
    m_footNoteSeparatorLinePos=SLP_LEFT;
247
194
 
248
 
    //by default it's 1/5
249
 
    m_iFootNoteSeparatorLineLength = 20;
 
195
    m_iFootNoteSeparatorLineLength = 20; // 20%, i.e. 1/5th
250
196
    m_footNoteSeparatorLineWidth = 2.0;
251
197
    m_footNoteSeparatorLineType = SLT_SOLID;
252
198
 
264
210
    m_bShowRuler = true;
265
211
    m_bShowStatusBar = true;
266
212
    m_bAllowAutoFormat = true;
267
 
    m_pgUpDownMovesCaret = false;
 
213
    m_pgUpDownMovesCaret = true;
268
214
    m_bShowScrollBar = true;
269
215
    m_cursorInProtectectedArea = true;
270
216
    m_bHasEndNotes = false;
272
218
    m_bInsertDirectCursor=false;
273
219
    m_globalLanguage = KGlobal::locale()->language();
274
220
    m_bGlobalHyphenation = false;
 
221
    m_bGeneratingPreview = false;
275
222
    m_lastViewMode="ModeNormal";
276
223
    m_viewMode = 0;
277
224
 
291
238
    m_varColl = new KWVariableCollection( new KWVariableSettings(), m_varFormatCollection );
292
239
 
293
240
    m_autoFormat = new KoAutoFormat(this,m_varColl,m_varFormatCollection );
294
 
 
 
241
#ifdef HAVE_LIBKSPELL2
295
242
    m_bgSpellCheck = new KWBgSpellCheck(this);
296
 
 
 
243
#endif
297
244
    m_slDataBase = new KWMailMergeDataBase( this );
298
245
    slRecordNum = -1;
299
246
 
300
247
    m_syntaxVersion = CURRENT_SYNTAX_VERSION;
301
248
 
302
 
    m_pKOSpellConfig = 0;
303
 
 
304
249
    m_hasTOC=false;
305
250
 
306
251
    // It's important to call this to have the kformula actions
333
278
    //kdDebug() << "Default font: requested family: " << m_defaultFont.family() << endl;
334
279
    //kdDebug() << "Default font: real family: " << QFontInfo(m_defaultFont).family() << endl;
335
280
 
336
 
    // Some simple import filters don't define any style,
337
 
    // so let's have a Standard style at least
338
 
    KWStyle * standardStyle = new KWStyle( "Standard" ); // This gets translated later on
339
 
    //kdDebug() << "KWDocument::KWDocument creating standardStyle " << standardStyle << endl;
340
 
    standardStyle->format().setFont( m_defaultFont );
341
 
    m_styleColl->addStyleTemplate( standardStyle );
342
 
 
343
 
    // And let's do the same for framestyles
344
 
    KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
345
 
    standardFrameStyle->setBackgroundColor(QColor("white"));
346
 
    standardFrameStyle->setTopBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
347
 
    standardFrameStyle->setRightBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
348
 
    standardFrameStyle->setLeftBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
349
 
    standardFrameStyle->setBottomBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
350
 
    m_frameStyleColl->addFrameStyleTemplate( standardFrameStyle );
351
 
 
352
 
    // And let's do the same for tablestyles
353
 
    KWTableStyle *standardTableStyle = new KWTableStyle( "Plain", standardStyle, standardFrameStyle );
354
 
    m_tableStyleColl->addTableStyleTemplate( standardTableStyle );
355
 
 
356
281
    if ( name )
357
282
        dcopObject();
358
283
    connect(m_varColl,SIGNAL(repaintVariable()),this,SLOT(slotRepaintVariable()));
376
301
    // formula frames have to be deleted before m_formulaDocumentWrapper
377
302
    m_lstFrameSet.clear();
378
303
    m_bookmarkList.clear();
379
 
    m_tmpBookMarkList.clear();
 
304
    delete m_loadingInfo;
380
305
    delete m_autoFormat;
381
306
    delete m_formulaDocumentWrapper;
382
307
    delete m_commandHistory;
384
309
    delete m_varFormatCollection;
385
310
    delete m_slDataBase;
386
311
    delete dcop;
 
312
#ifdef HAVE_LIBKSPELL2
387
313
    delete m_bgSpellCheck;
 
314
#endif
388
315
    delete m_styleColl;
389
316
    delete m_frameStyleColl;
390
317
    delete m_tableStyleColl;
391
318
    delete m_tableTemplateColl;
392
 
    delete m_pKOSpellConfig;
393
319
    delete m_viewMode;
394
320
    delete m_bufPixmap;
 
321
    delete m_pictureCollection;
395
322
}
396
323
 
397
324
void KWDocument::initConfig()
398
325
{
399
326
  KConfig *config = KWFactory::global()->config();
400
 
  KOSpellConfig kosconfig;
401
327
  if( config->hasGroup("KSpell kword" ) )
402
328
  {
403
329
      config->setGroup( "KSpell kword" );
404
 
      kosconfig.setNoRootAffix(config->readNumEntry ("KSpell_NoRootAffix", 0));
405
 
      kosconfig.setRunTogether(config->readNumEntry ("KSpell_RunTogether", 0));
406
 
      kosconfig.setDictionary(config->readEntry ("KSpell_Dictionary", ""));
407
 
      kosconfig.setDictFromList(config->readNumEntry ("KSpell_DictFromList", FALSE));
408
 
      kosconfig.setEncoding(config->readNumEntry ("KSpell_Encoding", KOS_E_ASCII));
409
 
      kosconfig.setClient(config->readNumEntry ("KSpell_Client", KOS_CLIENT_ISPELL));
410
 
 
411
 
      kosconfig.setIgnoreCase( config->readNumEntry( "KSpell_IgnoreCase", 0));
412
 
      kosconfig.setIgnoreAccent( config->readNumEntry( "KSpell_IgnoreAccent", 0));
413
 
      kosconfig.setDontCheckUpperWord(config->readBoolEntry("KSpell_dont_check_upper_word",false));
414
 
      kosconfig.setDontCheckTitleCase(config->readBoolEntry("KSpell_dont_check_title_case",false));
415
 
      kosconfig.setSpellWordWithNumber( config->readNumEntry("KSpell_SpellWordWithNumber", false));
416
 
 
417
 
      setKOSpellConfig( kosconfig );
418
330
 
419
331
      // Default is false for spellcheck, but the spell-check config dialog
420
332
      // should write out "true" when the user configures spell checking.
 
333
#ifdef HAVE_LIBKSPELL2
421
334
      if ( isReadWrite() )
422
 
          m_bgSpellCheck->enableBackgroundSpellCheck(config->readBoolEntry( "SpellCheck", false ));
 
335
          m_bgSpellCheck->setEnabled(config->readBoolEntry( "SpellCheck", false ));
423
336
      else
424
 
          m_bgSpellCheck->enableBackgroundSpellCheck( false );
425
 
 
 
337
          m_bgSpellCheck->setEnabled( false );
 
338
#endif
426
339
  }
427
340
 
428
341
  if(config->hasGroup("Interface" ) )
437
350
      setShowRuler(config->readBoolEntry("Rulers",true));
438
351
      int defaultAutoSave = KoDocument::defaultAutoSave()/60; // in minutes
439
352
      setAutoSave(config->readNumEntry("AutoSave",defaultAutoSave)*60); // read key in minutes, call setAutoSave(seconds)
440
 
      setBackupFile( config->readNumEntry("BackupFile", true));
 
353
      setBackupFile( config->readBoolEntry("BackupFile", true) );
441
354
 
442
355
      setNbPagePerRow(config->readNumEntry("nbPagePerRow",4));
443
356
      m_maxRecentFiles = config->readNumEntry( "NbRecentFile", 10 );
458
371
      setShowScrollBar( config->readBoolEntry( "ShowScrollBar", true ) );
459
372
      if ( isEmbedded() )
460
373
          m_bShowDocStruct = false; // off by default for embedded docs, but still toggleable
461
 
      m_pgUpDownMovesCaret = config->readBoolEntry( "PgUpDownMovesCaret", false );
 
374
      m_pgUpDownMovesCaret = config->readBoolEntry( "PgUpDownMovesCaret", true );
462
375
      m_bInsertDirectCursor= config->readBoolEntry( "InsertDirectCursor", false );
463
376
      m_globalLanguage=config->readEntry("language", KGlobal::locale()->language());
464
377
      m_bGlobalHyphenation=config->readBoolEntry("hyphenation", false);
474
387
  if(undo!=-1)
475
388
      setUndoRedoLimit(undo);
476
389
 
477
 
  setZoomAndResolution( m_zoom, QPaintDevice::x11AppDpiX(), QPaintDevice::x11AppDpiY() );
 
390
  setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() );
478
391
 
479
392
  //text mode view is not a good default for a readonly document...
480
393
  if ( !isReadWrite() && m_lastViewMode =="ModeText" )
486
399
  {
487
400
      config->setGroup( "Kword Path" );
488
401
      if ( config->hasKey( "expression path" ) )
489
 
          m_personalExpressionPath = config->readListEntry( "expression path" );
 
402
          m_personalExpressionPath = config->readPathListEntry( "expression path" );
490
403
#if 0 // KWORD_HORIZONTAL_LINE
491
404
      if ( config->hasKey( "horizontal line path" ) )
492
 
          m_horizontalLinePath = config->readListEntry( "horizontal line path" );
 
405
          m_horizontalLinePath = config->readPathListEntry( "horizontal line path" );
493
406
#endif
494
407
      if ( config->hasKey( "picture path" ) )
495
408
          m_picturePath = config->readPathEntry( "picture path" );
496
409
      setBackupPath(config->readPathEntry( "backup path" ));
497
410
  }
 
411
 
 
412
  // Load personal dict
 
413
  KConfigGroup group( KoGlobal::kofficeConfig(), "Spelling" );
 
414
  m_spellCheckPersonalDict = group.readListEntry( "PersonalDict" );
498
415
}
499
416
 
500
417
void KWDocument::saveConfig()
501
418
{
502
 
    if ( isEmbedded() || !isReadWrite() )
 
419
    if ( !isReadWrite() )
503
420
        return;
504
 
    // Only save the config that is manipulated by the UI directly.
505
 
    // The config from the config dialog is saved by the dialog itself.
506
 
    KConfig *config = KWFactory::global()->config();
507
 
    config->setGroup( "Interface" );
508
 
    config->writeEntry( "ViewFormattingChars", m_viewFormattingChars );
509
 
    config->writeEntry( "ViewFormattingBreaks", m_viewFormattingBreak );
510
 
    config->writeEntry( "ViewFormattingEndParag", m_viewFormattingEndParag );
511
 
    config->writeEntry( "ViewFormattingTabs", m_viewFormattingTabs );
512
 
    config->writeEntry( "ViewFormattingSpace", m_viewFormattingSpace );
513
 
    config->writeEntry( "ViewFrameBorders", m_viewFrameBorders );
514
 
    config->writeEntry( "Zoom", m_zoom );
515
 
    config->writeEntry( "showDocStruct", m_bShowDocStruct);
516
 
    config->writeEntry( "Rulers", m_bShowRuler);
517
 
    config->writeEntry( "viewmode", m_lastViewMode);
518
 
    config->writeEntry( "AllowAutoFormat", m_bAllowAutoFormat );
 
421
    KConfigGroup group( KoGlobal::kofficeConfig(), "Spelling" );
 
422
    group.writeEntry( "PersonalDict", m_spellCheckPersonalDict );
 
423
 
 
424
    if ( !isEmbedded() )
 
425
    {
 
426
        // Only save the config that is manipulated by the UI directly.
 
427
        // The config from the config dialog is saved by the dialog itself.
 
428
        KConfig *config = KWFactory::global()->config();
 
429
        config->setGroup( "Interface" );
 
430
        config->writeEntry( "ViewFormattingChars", m_viewFormattingChars );
 
431
        config->writeEntry( "ViewFormattingBreaks", m_viewFormattingBreak );
 
432
        config->writeEntry( "ViewFormattingEndParag", m_viewFormattingEndParag );
 
433
        config->writeEntry( "ViewFormattingTabs", m_viewFormattingTabs );
 
434
        config->writeEntry( "ViewFormattingSpace", m_viewFormattingSpace );
 
435
        config->writeEntry( "ViewFrameBorders", m_viewFrameBorders );
 
436
        config->writeEntry( "Zoom", m_zoom );
 
437
        config->writeEntry( "showDocStruct", m_bShowDocStruct);
 
438
        config->writeEntry( "Rulers", m_bShowRuler);
 
439
        config->writeEntry( "viewmode", m_lastViewMode);
 
440
        config->writeEntry( "AllowAutoFormat", m_bAllowAutoFormat );
 
441
    }
519
442
}
520
443
 
521
444
void KWDocument::setZoomAndResolution( int zoom, int dpiX, int dpiY )
552
475
        fit.current()->zoom( forPrint );
553
476
#endif
554
477
 
 
478
    // First recalc all frames (including the kotextdocument width)
 
479
    updateAllFrames();
 
480
    // Then relayout the text inside the frames
555
481
    layout();
556
 
    updateAllFrames();
557
482
    if ( updateViews )
558
483
    {
559
484
        emit newContentsSize();
561
486
    }
562
487
}
563
488
 
564
 
bool KWDocument::initDoc()
 
489
bool KWDocument::initDoc(InitDocFlags flags, QWidget* parentWidget)
565
490
{
566
491
    m_pages = 1;
567
492
 
574
499
    m_pageHeaderFooter.ptFooterBodySpacing = 10;
575
500
    m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
576
501
 
577
 
    QString _template;
578
 
 
579
502
    bool ok = FALSE;
580
503
 
 
504
    if (flags==KoDocument::InitDocEmpty)
 
505
    {
 
506
        QString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::global() ) );
 
507
        resetURL();
 
508
        initUnit();
 
509
        ok = loadNativeFormat( fileName );
 
510
        if ( !ok )
 
511
            showLoadingErrorDialog();
 
512
        setEmpty();
 
513
        setModified( FALSE );
 
514
        return ok;
 
515
    }
 
516
 
581
517
    KoTemplateChooseDia::DialogType dlgtype;
582
 
    if (initDocFlags() != KoDocument::InitDocFileNew)
 
518
 
 
519
    if (flags != KoDocument::InitDocFileNew)
583
520
            dlgtype = KoTemplateChooseDia::Everything;
584
521
    else
585
522
            dlgtype = KoTemplateChooseDia::OnlyTemplates;
586
523
 
587
524
 
 
525
    QString file;
588
526
    KoTemplateChooseDia::ReturnType ret = KoTemplateChooseDia::choose(
589
 
        KWFactory::global(), _template, "application/x-kword", "*.kwd", i18n("KWord"),
590
 
        dlgtype, "kword_template");
 
527
        KWFactory::global(), file,
 
528
        dlgtype, "kword_template", parentWidget );
591
529
    if ( ret == KoTemplateChooseDia::Template ) {
592
 
        QFileInfo fileInfo( _template );
593
 
        QString fileName( fileInfo.dirPath( TRUE ) + "/" + fileInfo.baseName() + ".kwt" );
594
530
        resetURL();
595
 
        ok = loadNativeFormat( fileName );
 
531
        ok = loadNativeFormat( file );
 
532
        if ( !ok )
 
533
            showLoadingErrorDialog();
596
534
        initUnit();
597
535
        setEmpty();
598
536
    } else if ( ret == KoTemplateChooseDia::File ) {
599
 
        KURL url( _template);
 
537
        KURL url( file );
600
538
        //kdDebug() << "KWDocument::initDoc opening URL " << url.prettyURL() << endl;
601
539
        ok = openURL( url );
602
540
    } else if ( ret == KoTemplateChooseDia::Empty ) {
603
541
        QString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::global() ) );
604
542
        resetURL();
 
543
        initUnit();
605
544
        ok = loadNativeFormat( fileName );
606
 
        initUnit();
 
545
        if ( !ok )
 
546
            showLoadingErrorDialog();
607
547
        setEmpty();
608
548
    }
609
549
    setModified( FALSE );
612
552
 
613
553
void KWDocument::initUnit()
614
554
{
615
 
    //load unit config after we load file.
616
 
    //load it for new file or empty file
 
555
    //load default unit setting - this is only used for new files (from templates) or empty files
617
556
    KConfig *config = KWFactory::global()->config();
 
557
 
 
558
    if (KGlobal::locale()->measureSystem() == KLocale::Imperial) {
 
559
        m_unit = KoUnit::U_INCH;
 
560
    } else {
 
561
        m_unit = KoUnit::U_CM;
 
562
    }
 
563
 
618
564
    if(config->hasGroup("Misc") )
619
565
    {
620
566
        config->setGroup( "Misc" );
621
 
        setUnit(KoUnit::unit( config->readEntry("Units",KoUnit::unitName(KoUnit::U_MM  ))));
 
567
        if ( config->hasKey( "Units" ) )
 
568
            setUnit( KoUnit::unit( config->readEntry("Units") ) );
622
569
        setDefaultColumnSpacing( config->readDoubleNumEntry("ColumnSpacing", 3.0) );
623
570
    }
624
571
    m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
638
585
    m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
639
586
 
640
587
    QString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::global() ) );
641
 
    /*bool ok = */loadNativeFormat( fileName );
 
588
    bool ok = loadNativeFormat( fileName );
 
589
    if ( !ok )
 
590
        showLoadingErrorDialog();
642
591
    resetURL();
643
592
    setModified( FALSE );
644
593
    setEmpty();
681
630
        m_pageHeaderFooter = _hf;
682
631
    }
683
632
 
 
633
    // pages have a different size -> update framesInPage
 
634
    // TODO: it would be better to move stuff so that text boxes remain in the same page...
 
635
    // (page-number preservation instead of Y preservation)
 
636
    updateAllFrames( KWFrameSet::UpdateFramesInPage );
 
637
 
684
638
    recalcFrames();
685
639
 
686
640
    updateAllFrames();
812
766
            Q_ASSERT( firstHeader );
813
767
            Q_ASSERT( oddHeader );
814
768
            Q_ASSERT( evenHeader );
815
 
            switch ( getHeaderType() ) {
 
769
            switch ( headerType() ) {
816
770
            case HF_SAME:
817
771
                oddHeader->setVisible( true );
818
772
                evenHeader->setVisible( false );
867
821
            Q_ASSERT( firstFooter );
868
822
            Q_ASSERT( oddFooter );
869
823
            Q_ASSERT( evenFooter );
870
 
            switch ( getFooterType() ) {
 
824
            switch ( footerType() ) {
871
825
            case HF_SAME:
872
826
                oddFooter->setVisible( true );
873
827
                evenFooter->setVisible( false );
985
939
 
986
940
        // Then from the other frames ( framesetNum > 0 )
987
941
        double maxBottom = 0;
988
 
        for (int m = getNumFrameSets() - 1; m > 0; m-- )
 
942
        for (int m = numFrameSets() - 1; m > 0; m-- )
989
943
        {
990
944
            KWFrameSet *fs=frameSet(m);
991
945
            if ( fs->isVisible() && !fs->isAHeader() && !fs->isAFooter() && !fs->isFloating() && !fs->isFootEndNote() )
1018
972
 
1019
973
        // If the number of pages changed, update views and variables etc.
1020
974
        // (now that the frame layout has been done)
1021
 
        if ( m_pages != oldPages )
 
975
        if ( m_pages != oldPages && !m_bGeneratingPreview )
1022
976
        {
1023
977
            // Very much like the end of appendPage, but we don't want to call recalcFrames ;)
1024
978
            emit newContentsSize();
1046
1000
        kdDebug(32002) << "DTP mode: pages = maxBottom("<<maxBottom<<") / ptPaperHeight=" << ptPaperHeight() << " = " << m_pages << endl;
1047
1001
#endif
1048
1002
        if(m_pages < 1) m_pages=1;
 
1003
 
 
1004
        if ( toPage == -1 )
 
1005
            toPage = m_pages - 1;
 
1006
        // #106187, make text flow around frames upon loading
 
1007
        for ( int pg = fromPage ; pg <= toPage ; ++pg )
 
1008
            updateFramesOnTopOrBelow( pg );
1049
1009
    }
1050
1010
}
1051
1011
 
1069
1029
    QDomElement picturesElem = domElement.namedItem( "PICTURES" ).toElement();
1070
1030
    if ( !picturesElem.isNull() )
1071
1031
    {
1072
 
       m_pictureCollection.readXML( picturesElem, m_pictureMap );
 
1032
       m_pictureCollection->readXML( picturesElem, m_pictureMap );
1073
1033
    }
1074
1034
 
1075
1035
    // <PIXMAPS>
1076
1036
    QDomElement pixmapsElem = domElement.namedItem( "PIXMAPS" ).toElement();
1077
1037
    if ( !pixmapsElem.isNull() )
1078
1038
    {
1079
 
       m_pictureCollection.readXML( pixmapsElem, m_pictureMap );
 
1039
       m_pictureCollection->readXML( pixmapsElem, m_pictureMap );
1080
1040
    }
1081
1041
 
1082
1042
    // <CLIPARTS>
1083
1043
    QDomElement clipartsElem = domElement.namedItem( "CLIPARTS" ).toElement();
1084
1044
    if ( !clipartsElem.isNull() )
1085
1045
    {
1086
 
       m_pictureCollection.readXML( pixmapsElem, m_pictureMap );
1087
 
    }
1088
 
}
1089
 
 
 
1046
       m_pictureCollection->readXML( pixmapsElem, m_pictureMap );
 
1047
    }
 
1048
}
 
1049
 
 
1050
 
 
1051
bool KWDocument::loadOasis( const QDomDocument& doc, KoOasisStyles& oasisStyles, const QDomDocument& settings, KoStore* store )
 
1052
{
 
1053
    QTime dt;
 
1054
    dt.start();
 
1055
    emit sigProgress( 0 );
 
1056
    clear();
 
1057
    kdDebug(32001) << "KWDocument::loadOasis" << endl;
 
1058
 
 
1059
    KoColumns __columns;
 
1060
    __columns.columns = 1;
 
1061
    __columns.ptColumnSpacing = m_defaultColumnSpacing;
 
1062
    KoKWHeaderFooter __hf;
 
1063
    __hf.header = HF_SAME;
 
1064
    __hf.footer = HF_SAME;
 
1065
    __hf.ptHeaderBodySpacing = 10.0;
 
1066
    __hf.ptFooterBodySpacing = 10.0;
 
1067
    __hf.ptFootNoteBodySpacing = 10.0;
 
1068
 
 
1069
    QDomElement content = doc.documentElement();
 
1070
    QDomElement body ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) );
 
1071
    if ( body.isNull() )
 
1072
    {
 
1073
        kdError(32001) << "No office:body found!" << endl;
 
1074
        setErrorMessage( i18n( "Invalid OASIS document. No office:body tag found." ) );
 
1075
        return false;
 
1076
    }
 
1077
    body = KoDom::namedItemNS( body, KoXmlNS::office, "text" );
 
1078
    if ( body.isNull() )
 
1079
    {
 
1080
        kdError(32001) << "No office:text found!" << endl;
 
1081
        // ## TODO: print the actual tag that was found, it might help finding the right app to use :)
 
1082
        setErrorMessage( i18n( "Invalid OASIS document. No office:text tag found." ) );
 
1083
        return false;
 
1084
    }
 
1085
 
 
1086
    // TODO check versions and mimetypes etc.
 
1087
 
 
1088
    QString masterPageName = "Standard"; // use default layout as fallback
 
1089
    // In theory the page format is the style:master-page-name of the first paragraph...
 
1090
    // But, hmm, in a doc with only a table there was no reference to the master page at all...
 
1091
    QDomElement* masterPage = oasisStyles.masterPages()[ masterPageName ];
 
1092
    Q_ASSERT( masterPage );
 
1093
    QDomElement *masterPageStyle = masterPage ? oasisStyles.styles()[masterPage->attributeNS( KoXmlNS::style, "page-layout-name", QString::null )] : 0;
 
1094
    Q_ASSERT( masterPageStyle );
 
1095
    if ( masterPageStyle )
 
1096
    {
 
1097
        m_pageLayout.loadOasis( *masterPageStyle );
 
1098
        if ( m_pageLayout.ptWidth <= 1e-13 || m_pageLayout.ptHeight <= 1e-13 )
 
1099
        {
 
1100
            // Loading page layout failed, try to see why.
 
1101
            QDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) );
 
1102
            //if ( properties.isNull() )
 
1103
            //    setErrorMessage( i18n( "Invalid document. No page layout properties were found. The application which produced this document isn't OASIS-compliant." ) );
 
1104
            //else if ( properties.hasAttributeNS( KoXmlNS::fo, "page-width" ) )
 
1105
            //    setErrorMessage( i18n( "Invalid document. Page layout has no page width. The application which produced this document isn't OASIS-compliant." ) );
 
1106
            //else
 
1107
            if ( properties.hasAttributeNS( "http://www.w3.org/1999/XSL/Format", "page-width" ) )
 
1108
                setErrorMessage( i18n( "Invalid document. 'fo' has the wrong namespace. The application which produced this document is not OASIS-compliant." ) );
 
1109
            else
 
1110
                setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" ).arg( m_pageLayout.ptWidth ).arg( m_pageLayout.ptHeight ) );
 
1111
            return false;
 
1112
        }
 
1113
 
 
1114
        //__hf.ptHeaderBodySpacing = getAttribute( paper, "spHeadBody", 0.0 );
 
1115
        //__hf.ptFooterBodySpacing  = getAttribute( paper, "spFootBody", 0.0 );
 
1116
        //__hf.ptFootNoteBodySpacing  = getAttribute( paper, "spFootNoteBody", 10.0 );
 
1117
 
 
1118
        const QDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) );
 
1119
        const QDomElement footnoteSep = KoDom::namedItemNS( properties, KoXmlNS::style, "footnote-sep" );
 
1120
        if ( !footnoteSep.isNull() ) {
 
1121
            // style:width="0.018cm" style:distance-before-sep="0.101cm"
 
1122
            // style:distance-after-sep="0.101cm" style:adjustment="left"
 
1123
            // style:rel-width="25%" style:color="#000000"
 
1124
            const QString width = footnoteSep.attributeNS( KoXmlNS::style, "width", QString::null );
 
1125
            if ( !width.isEmpty() ) {
 
1126
                m_footNoteSeparatorLineWidth = KoUnit::parseValue( width );
 
1127
            }
 
1128
 
 
1129
            QString pageWidth = footnoteSep.attributeNS( KoXmlNS::style, "rel-width", QString::null );
 
1130
            if ( pageWidth.endsWith( "%" ) ) {
 
1131
                pageWidth.truncate( pageWidth.length() - 1 ); // remove '%'
 
1132
                m_iFootNoteSeparatorLineLength = qRound( pageWidth.toDouble() );
 
1133
            }
 
1134
            // Not in KWord: color, distance before and after separator
 
1135
 
 
1136
            const QString style = footnoteSep.attributeNS( KoXmlNS::style, "line-style", QString::null );
 
1137
            if ( style == "solid" || style.isEmpty() )
 
1138
                m_footNoteSeparatorLineType = SLT_SOLID;
 
1139
            else if ( style == "dash" )
 
1140
                m_footNoteSeparatorLineType = SLT_DASH;
 
1141
            else if ( style == "dotted" )
 
1142
                m_footNoteSeparatorLineType = SLT_DOT;
 
1143
            else if ( style == "dot-dash" )
 
1144
                m_footNoteSeparatorLineType = SLT_DASH_DOT;
 
1145
            else if ( style == "dot-dot-dash" )
 
1146
                m_footNoteSeparatorLineType = SLT_DASH_DOT_DOT;
 
1147
            else
 
1148
                kdDebug() << "Unknown value for m_footNoteSeparatorLineType: " << style << endl;
 
1149
 
 
1150
            const QString pos = footnoteSep.attributeNS( KoXmlNS::style, "adjustment", QString::null );
 
1151
            if ( pos == "centered" )
 
1152
                m_footNoteSeparatorLinePos = SLP_CENTERED;
 
1153
            else if ( pos == "right")
 
1154
                m_footNoteSeparatorLinePos = SLP_RIGHT;
 
1155
            else // if ( pos == "left" )
 
1156
                m_footNoteSeparatorLinePos = SLP_LEFT;
 
1157
        }
 
1158
 
 
1159
        __columns.columns = 1;
 
1160
        __columns.ptColumnSpacing = m_defaultColumnSpacing;
 
1161
 
 
1162
        const QDomElement columnsElem = KoDom::namedItemNS( properties, KoXmlNS::style, "columns" );
 
1163
        if ( !columnsElem.isNull() )
 
1164
        {
 
1165
            __columns.columns = columnsElem.attributeNS( KoXmlNS::fo, "column-count", QString::null ).toInt();
 
1166
            if ( __columns.columns == 0 )
 
1167
                __columns.columns = 1;
 
1168
            // TODO OASIS OpenDocument supports columns of different sizes, using <style:column style:rel-width="...">
 
1169
            // (with fo:start-indent/fo:end-indent for per-column spacing)
 
1170
            // But well, it also allows us to specify a single gap.
 
1171
            if ( columnsElem.hasAttributeNS( KoXmlNS::fo, "column-gap" ) )
 
1172
                __columns.ptColumnSpacing = KoUnit::parseValue( columnsElem.attributeNS( KoXmlNS::fo, "column-gap", QString::null ) );
 
1173
            // It also supports drawing a vertical line as a separator...
 
1174
        }
 
1175
 
 
1176
        m_headerVisible = false;
 
1177
        m_footerVisible = false;
 
1178
 
 
1179
        // TODO spHeadBody (where is this in OOo?)
 
1180
        // TODO spFootBody (where is this in OOo?)
 
1181
        // Answer: margins of the <style:header-footer> element
 
1182
    }
 
1183
    else // this doesn't happen with normal documents, but it can happen if copying something,
 
1184
         // pasting into konq as foo.odt, then opening that...
 
1185
    {
 
1186
        __columns.columns = 1;
 
1187
        __columns.ptColumnSpacing = 2;
 
1188
        m_headerVisible = false;
 
1189
        m_footerVisible = false;
 
1190
        m_pageLayout = KoPageLayout::standardLayout();
 
1191
    }
 
1192
 
 
1193
    createLoadingInfo();
 
1194
    KWOasisLoader oasisLoader( this );
 
1195
 
 
1196
    // <text:page-sequence> oasis extension for DTP (2003-10-27 post by Daniel)
 
1197
    m_processingType = ( !KoDom::namedItemNS( body, KoXmlNS::text, "page-sequence" ).isNull() )
 
1198
                       ? DTP : WP;
 
1199
 
 
1200
    // TODO settings (m_unit, spellcheck settings)
 
1201
 
 
1202
    m_hasTOC = false;
 
1203
    m_tabStop = MM_TO_POINT(15);
 
1204
    QDomElement* defaultParagStyle = oasisStyles.defaultStyle( "paragraph" );
 
1205
    if ( defaultParagStyle ) {
 
1206
        KoStyleStack stack;
 
1207
        stack.push( *defaultParagStyle );
 
1208
        stack.setTypeProperties( "paragraph" );
 
1209
        QString tabStopVal = stack.attributeNS( KoXmlNS::style, "tab-stop-distance" );
 
1210
        if ( !tabStopVal.isEmpty() )
 
1211
            m_tabStop = KoUnit::parseValue( tabStopVal );
 
1212
    }
 
1213
    m_initialEditing = 0;
 
1214
 
 
1215
    // TODO variable settings
 
1216
    // By default display real variable value
 
1217
    if ( !isReadWrite())
 
1218
        m_varColl->variableSetting()->setDisplayFieldCode(false);
 
1219
 
 
1220
    // TODO MAILMERGE
 
1221
 
 
1222
    KoOasisContext context( this, *m_varColl, oasisStyles, store );
 
1223
    Q_ASSERT( !oasisStyles.officeStyle().isNull() );
 
1224
 
 
1225
    // Load all styles before the corresponding paragraphs try to use them!
 
1226
    m_styleColl->loadOasisStyleTemplates( context );
 
1227
    static_cast<KWVariableSettings *>( m_varColl->variableSetting() )
 
1228
        ->loadNoteConfiguration( oasisStyles.officeStyle() );
 
1229
 
 
1230
    // TODO framestyles and tablestyles
 
1231
 
 
1232
    loadDefaultTableTemplates();
 
1233
 
 
1234
    if ( m_processingType == WP ) {
 
1235
        // Create main frameset
 
1236
        KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Main Text Frameset" ) );
 
1237
        m_lstFrameSet.append( fs ); // don't use addFrameSet here. We'll call finalize() once and for all in completeLoading
 
1238
        fs->loadOasisContent( body, context );
 
1239
        KWFrame* frame = new KWFrame( fs, 29, 42, 798-29, 566-42 );
 
1240
        frame->setFrameBehavior( KWFrame::AutoCreateNewFrame );
 
1241
        frame->setNewFrameBehavior( KWFrame::Reconnect );
 
1242
        fs->addFrame( frame );
 
1243
 
 
1244
        fs->renumberFootNotes( false /*no repaint*/ );
 
1245
 
 
1246
    } else {
 
1247
        // DTP mode: the items in the body are page-sequence and then frames
 
1248
        QDomElement tag;
 
1249
        forEachElement( tag, body )
 
1250
        {
 
1251
            context.styleStack().save();
 
1252
            const QString localName = tag.localName();
 
1253
            if ( localName == "page-sequence" && tag.namespaceURI() == KoXmlNS::text )
 
1254
            {
 
1255
                // We don't have support for changing the page layout yet, so just take the
 
1256
                // number of pages
 
1257
                m_pages = 1;
 
1258
                QDomElement page;
 
1259
                forEachElement( page, tag )
 
1260
                    ++m_pages;
 
1261
                kdDebug() << "DTP mode: found " << m_pages << "pages" << endl;
 
1262
            }
 
1263
            else if ( localName == "frame" && tag.namespaceURI() == KoXmlNS::draw )
 
1264
                oasisLoader.loadFrame( tag, context );
 
1265
            else
 
1266
                kdWarning(32001) << "Unsupported tag in DTP loading:" << tag.tagName() << endl;
 
1267
        }
 
1268
    }
 
1269
 
 
1270
    // Header/Footer
 
1271
    // TODO support for first-page
 
1272
    bool hasEvenOddHeader = false;
 
1273
    bool hasEvenOddFooter = false;
 
1274
    if ( masterPageStyle )
 
1275
    {
 
1276
        QDomElement headerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "header-style" );
 
1277
        QDomElement footerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "footer-style" );
 
1278
        QDomElement headerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header-left" );
 
1279
        if ( !headerLeftElem.isNull() ) {
 
1280
            kdDebug() << "Found header-left" << endl;
 
1281
            hasEvenOddHeader = true;
 
1282
            __hf.header = HF_EO_DIFF; // ###
 
1283
            oasisLoader.loadOasisHeaderFooter( headerLeftElem, hasEvenOddHeader, headerStyle, context );
 
1284
        }
 
1285
        QDomElement headerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header" );
 
1286
        if ( !headerElem.isNull() ) {
 
1287
            kdDebug() << "Found header" << endl;
 
1288
            oasisLoader.loadOasisHeaderFooter( headerElem, hasEvenOddHeader, headerStyle, context );
 
1289
        }
 
1290
        QDomElement footerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer-left" );
 
1291
        if ( !footerLeftElem.isNull() ) {
 
1292
            kdDebug() << "Found footer-left" << endl;
 
1293
            hasEvenOddFooter = true;
 
1294
            __hf.footer = HF_EO_DIFF; // ###
 
1295
            oasisLoader.loadOasisHeaderFooter( footerLeftElem, hasEvenOddFooter, footerStyle, context );
 
1296
        }
 
1297
        QDomElement footerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer" );
 
1298
        if ( !footerElem.isNull() ) {
 
1299
            kdDebug() << "Found footer" << endl;
 
1300
            oasisLoader.loadOasisHeaderFooter( footerElem, hasEvenOddFooter, footerStyle, context );
 
1301
        }
 
1302
    }
 
1303
 
 
1304
    // TODO embedded objects
 
1305
 
 
1306
    if ( context.cursorTextParagraph() ) {
 
1307
        // Maybe, once 1.3-support is dropped, we can get rid of InitialEditing and fetch the
 
1308
        // values from KoOasisContext? But well, it lives a bit longer.
 
1309
        // At least we could store a KWFrameSet* and a KoTextParag* instead of a name and an id.
 
1310
        m_initialEditing = new InitialEditing();
 
1311
        KWTextFrameSet* fs = static_cast<KWTextDocument *>( context.cursorTextParagraph()->textDocument() )->textFrameSet();
 
1312
        m_initialEditing->m_initialFrameSet = fs->name();
 
1313
        m_initialEditing->m_initialCursorParag = context.cursorTextParagraph()->paragId();
 
1314
        m_initialEditing->m_initialCursorIndex = context.cursorTextIndex();
 
1315
    }
 
1316
 
 
1317
    kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
 
1318
    endOfLoading();
 
1319
 
 
1320
    // This sets the columns and header/footer flags, and calls recalcFrames,
 
1321
    // so it must be done last.
 
1322
    setPageLayout( m_pageLayout, __columns, __hf, false );
 
1323
 
 
1324
    if ( !settings.isNull() )
 
1325
    {
 
1326
        oasisLoader.loadOasisSettings( settings );
 
1327
    }
 
1328
    //printDebug();
 
1329
 
 
1330
    return true;
 
1331
}
 
1332
 
 
1333
// called before loading
 
1334
void KWDocument::clear()
 
1335
{
 
1336
    m_pictureMap.clear();
 
1337
    m_textImageRequests.clear();
 
1338
    m_pictureRequests.clear();
 
1339
    m_anchorRequests.clear();
 
1340
    m_footnoteVarRequests.clear();
 
1341
    m_spellCheckIgnoreList.clear();
 
1342
    m_pageColumns.columns = 1;
 
1343
    m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
 
1344
 
 
1345
    m_pageHeaderFooter.header = HF_SAME;
 
1346
    m_pageHeaderFooter.footer = HF_SAME;
 
1347
    m_pageHeaderFooter.ptHeaderBodySpacing = 10;
 
1348
    m_pageHeaderFooter.ptFooterBodySpacing = 10;
 
1349
    m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
 
1350
    m_pageColumns.columns = 1;
 
1351
    m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
 
1352
    m_pages = 1;
 
1353
    m_bHasEndNotes = false;
 
1354
 
 
1355
    m_varColl->clear();
 
1356
    m_pictureCollection->clear();
 
1357
    m_varFormatCollection->clear();
 
1358
 
 
1359
    m_styleColl->clear();
 
1360
    m_frameStyleColl->clear();
 
1361
    m_tableStyleColl->clear();
 
1362
    m_tableTemplateColl->clear();
 
1363
 
 
1364
    // Some simple import filters don't define any style,
 
1365
    // so let's have a Standard style at least
 
1366
    KoParagStyle * standardStyle = new KoParagStyle( "Standard" ); // This gets translated later on
 
1367
    //kdDebug() << "KWDocument::KWDocument creating standardStyle " << standardStyle << endl;
 
1368
    standardStyle->format().setFont( m_defaultFont );
 
1369
    m_styleColl->addStyleTemplate( standardStyle );
 
1370
 
 
1371
    // And let's do the same for framestyles
 
1372
    KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
 
1373
    standardFrameStyle->setBackgroundColor(Qt::white);
 
1374
    standardFrameStyle->setTopBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
 
1375
    standardFrameStyle->setRightBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
 
1376
    standardFrameStyle->setLeftBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
 
1377
    standardFrameStyle->setBottomBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
 
1378
    m_frameStyleColl->addFrameStyleTemplate( standardFrameStyle );
 
1379
 
 
1380
    // And let's do the same for tablestyles
 
1381
    KWTableStyle *standardTableStyle = new KWTableStyle( "Plain", standardStyle, standardFrameStyle );
 
1382
    m_tableStyleColl->addTableStyleTemplate( standardTableStyle );
 
1383
}
1090
1384
 
1091
1385
bool KWDocument::loadXML( QIODevice *, const QDomDocument & doc )
1092
1386
{
1093
1387
    QTime dt;
1094
1388
    dt.start();
1095
1389
    emit sigProgress( 0 );
1096
 
    //kdDebug(32001) << "KWDocument::loadXML" << endl;
1097
 
    m_pictureMap.clear();
1098
 
    m_textImageRequests.clear();
1099
 
    m_pictureRequests.clear();
1100
 
    m_anchorRequests.clear();
1101
 
    m_footnoteVarRequests.clear();
1102
 
    m_spellListIgnoreAll.clear();
1103
 
 
1104
 
    m_pageColumns.columns = 1;
1105
 
    m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
1106
 
 
1107
 
    m_pageHeaderFooter.header = HF_SAME;
1108
 
    m_pageHeaderFooter.footer = HF_SAME;
1109
 
    m_pageHeaderFooter.ptHeaderBodySpacing = 10;
1110
 
    m_pageHeaderFooter.ptFooterBodySpacing = 10;
1111
 
    m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
1112
 
    m_varFormatCollection->clear();
1113
 
 
1114
 
    m_pages = 1;
1115
 
    m_bHasEndNotes = false;
 
1390
    kdDebug(32001) << "KWDocument::loadXML" << endl;
 
1391
    clear();
1116
1392
 
1117
1393
    KoPageLayout __pgLayout;
1118
1394
    KoColumns __columns;
1155
1431
        }
1156
1432
    }
1157
1433
 
 
1434
    createLoadingInfo();
 
1435
 
1158
1436
    // Looks like support for the old way of naming images internally,
1159
1437
    // see completeLoading.
1160
1438
    value = KWDocument::getAttribute( word, "url", QString::null );
1161
 
    if ( value != QString::null )
 
1439
    if ( !value.isNull() )
1162
1440
    {
1163
1441
        m_urlIntern = KURL( value ).path();
1164
1442
    }
1173
1451
        __pgLayout.orientation = static_cast<KoOrientation>( KWDocument::getAttribute( paper, "orientation", 0 ) );
1174
1452
        __pgLayout.ptWidth = getAttribute( paper, "width", 0.0 );
1175
1453
        __pgLayout.ptHeight = getAttribute( paper, "height", 0.0 );
 
1454
        kdDebug() << " ptWidth=" << __pgLayout.ptWidth << endl;
 
1455
        kdDebug() << " ptHeight=" << __pgLayout.ptHeight << endl;
 
1456
        if ( __pgLayout.ptWidth <= 0 || __pgLayout.ptHeight <= 0 )
 
1457
        {
 
1458
            // Old document?
 
1459
            __pgLayout.ptWidth = getAttribute( paper, "ptWidth", 0.0 );
 
1460
            __pgLayout.ptHeight = getAttribute( paper, "ptHeight", 0.0 );
 
1461
                kdDebug() << " ptWidth=" << __pgLayout.ptWidth << endl;
 
1462
                kdDebug() << " ptHeight=" << __pgLayout.ptHeight << endl;
 
1463
 
 
1464
            // Still wrong?
 
1465
            if ( __pgLayout.ptWidth <= 0 || __pgLayout.ptHeight <= 0 )
 
1466
            {
 
1467
                setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" )
 
1468
                    .arg( __pgLayout.ptWidth ).arg( __pgLayout.ptHeight ) );
 
1469
                return false;
 
1470
            }
 
1471
        }
 
1472
 
1176
1473
        __hf.header = static_cast<KoHFType>( KWDocument::getAttribute( paper, "hType", 0 ) );
1177
1474
        __hf.footer = static_cast<KoHFType>( KWDocument::getAttribute( paper, "fType", 0 ) );
1178
1475
        __hf.ptHeaderBodySpacing = getAttribute( paper, "spHeadBody", 0.0 );
1197
1494
        // Now part of the app config
1198
1495
        //m_zoom = KWDocument::getAttribute( paper, "zoom", 100 );
1199
1496
        //if(m_zoom!=100)
1200
 
        //    setZoomAndResolution( m_zoom, QPaintDevice::x11AppDpiX(), QPaintDevice::x11AppDpiY(), false, false );
 
1497
        //    setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY(), false, false );
1201
1498
 
1202
1499
 
1203
1500
        // Support the undocumented syntax actually used by KDE 2.0 for some of the above (:-().
1239
1536
        kdWarning() << "No <PAPER> tag! This is a mandatory tag! Expect weird page sizes..." << endl;
1240
1537
 
1241
1538
    // <ATTRIBUTES>
 
1539
    m_unit = KoUnit::U_CM;
1242
1540
    QDomElement attributes = word.namedItem( "ATTRIBUTES" ).toElement();
1243
 
    QString unitName;
1244
1541
    if ( !attributes.isNull() )
1245
1542
    {
1246
1543
        m_processingType = static_cast<ProcessingType>( KWDocument::getAttribute( attributes, "processing", 0 ) );
1247
1544
        //KWDocument::getAttribute( attributes, "standardpage", QString::null );
1248
1545
        m_headerVisible = static_cast<bool>( KWDocument::getAttribute( attributes, "hasHeader", 0 ) );
1249
1546
        m_footerVisible = static_cast<bool>( KWDocument::getAttribute( attributes, "hasFooter", 0 ) );
1250
 
        unitName = KWDocument::getAttribute( attributes, "unit", "mm" );
 
1547
        if ( attributes.hasAttribute( "unit" ) )
 
1548
            m_unit = KoUnit::unit( attributes.attribute( "unit" ) );
1251
1549
        m_hasTOC =  static_cast<bool>(KWDocument::getAttribute( attributes,"hasTOC", 0 ) );
1252
1550
        m_tabStop = KWDocument::getAttribute( attributes, "tabStopValue", MM_TO_POINT(15) );
1253
1551
        m_initialEditing = new InitialEditing();
1258
1556
        m_processingType = WP;
1259
1557
        m_headerVisible = false;
1260
1558
        m_footerVisible = false;
1261
 
        unitName = "mm";
1262
1559
        m_hasTOC = false;
1263
1560
        m_tabStop = MM_TO_POINT(15);
1264
1561
        delete m_initialEditing;
1265
1562
        m_initialEditing = 0L;
1266
1563
    }
1267
 
    m_unit = KoUnit::unit( unitName );
1268
1564
 
1269
1565
    setPageLayout( __pgLayout, __columns, __hf, false );
1270
1566
 
1271
 
    getVariableCollection()->variableSetting()->load(word );
 
1567
    variableCollection()->variableSetting()->load(word );
1272
1568
    //by default display real variable value
1273
1569
    if ( !isReadWrite())
1274
 
        getVariableCollection()->variableSetting()->setDisplayFieldCode(false);
 
1570
        variableCollection()->variableSetting()->setDisplayFieldCode(false);
1275
1571
 
1276
1572
    emit sigProgress(10);
1277
1573
 
1313
1609
    QDomElement bookmark = word.namedItem( "BOOKMARKS" ).toElement();
1314
1610
    if( !bookmark.isNull() )
1315
1611
    {
1316
 
        QDomElement bookmarkitem=word.namedItem("BOOKMARKS").toElement();
1317
 
        bookmarkitem=bookmarkitem.firstChild().toElement();
 
1612
        QDomElement bookmarkitem = word.namedItem("BOOKMARKS").toElement();
 
1613
        bookmarkitem = bookmarkitem.firstChild().toElement();
1318
1614
 
1319
1615
        while ( !bookmarkitem.isNull() )
1320
1616
        {
1321
 
            if ( bookmarkitem.tagName()=="BOOKMARKITEM" )
 
1617
            if ( bookmarkitem.tagName() == "BOOKMARKITEM" )
1322
1618
            {
1323
 
                bookMark *tmp=new bookMark;
1324
 
                tmp->bookname=bookmarkitem.attribute("name");
1325
 
                tmp->cursorStartIndex=bookmarkitem.attribute("cursorIndexStart").toInt();
1326
 
                tmp->frameSetName=bookmarkitem.attribute("frameset");
1327
 
                tmp->paragStartIndex = bookmarkitem.attribute("startparag").toInt();
1328
 
                tmp->paragEndIndex = bookmarkitem.attribute("endparag").toInt();
1329
 
                tmp->cursorEndIndex = bookmarkitem.attribute("cursorIndexEnd").toInt();
1330
 
                m_tmpBookMarkList.append(tmp);
 
1619
                KWLoadingInfo::BookMark bk;
 
1620
                bk.bookname=bookmarkitem.attribute("name");
 
1621
                bk.cursorStartIndex=bookmarkitem.attribute("cursorIndexStart").toInt();
 
1622
                bk.frameSetName=bookmarkitem.attribute("frameset");
 
1623
                bk.paragStartIndex = bookmarkitem.attribute("startparag").toInt();
 
1624
                bk.paragEndIndex = bookmarkitem.attribute("endparag").toInt();
 
1625
                bk.cursorEndIndex = bookmarkitem.attribute("cursorIndexEnd").toInt();
 
1626
                Q_ASSERT( m_loadingInfo );
 
1627
                m_loadingInfo->bookMarkList.append( bk );
1331
1628
            }
1332
 
            bookmarkitem=bookmarkitem.nextSibling().toElement();
 
1629
            bookmarkitem = bookmarkitem.nextSibling().toElement();
1333
1630
        }
1334
1631
    }
1335
1632
 
 
1633
    QStringList lst;
1336
1634
    QDomElement spellCheckIgnore = word.namedItem( "SPELLCHECKIGNORELIST" ).toElement();
1337
1635
    if( !spellCheckIgnore.isNull() )
1338
1636
    {
1341
1639
        while ( !spellWord.isNull() )
1342
1640
        {
1343
1641
            if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" )
1344
 
                m_spellListIgnoreAll.append(spellWord.attribute("word"));
 
1642
                lst.append(spellWord.attribute("word"));
1345
1643
            spellWord=spellWord.nextSibling().toElement();
1346
1644
        }
1347
1645
    }
1348
 
    m_bgSpellCheck->addIgnoreWordAllList( m_spellListIgnoreAll );
 
1646
    setSpellCheckIgnoreList( lst );
1349
1647
 
1350
1648
    emit sigProgress(25);
1351
1649
 
1365
1663
 
1366
1664
    emit sigProgress(100); // the rest is only processing, not loading
1367
1665
 
1368
 
    bool _first_footer = FALSE, _even_footer = FALSE, _odd_footer = FALSE;
1369
 
    bool _first_header = FALSE, _even_header = FALSE, _odd_header = FALSE;
 
1666
    kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
 
1667
 
 
1668
    endOfLoading();
 
1669
    return true;
 
1670
}
 
1671
 
 
1672
void KWDocument::endOfLoading()
 
1673
{
 
1674
    bool _first_footer = false, _even_footer = false, _odd_footer = false;
 
1675
    bool _first_header = false, _even_header = false, _odd_header = false;
1370
1676
 
1371
1677
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
1372
1678
    for ( ; fit.current() ; ++fit )
1373
1679
    {
1374
1680
        switch( fit.current()->frameSetInfo() ) {
1375
 
        case KWFrameSet::FI_FIRST_HEADER: _first_header = TRUE; break;
1376
 
        case KWFrameSet::FI_ODD_HEADER: _odd_header = TRUE; break;
1377
 
        case KWFrameSet::FI_EVEN_HEADER: _even_header = TRUE; break;
1378
 
        case KWFrameSet::FI_FIRST_FOOTER: _first_footer = TRUE; break;
1379
 
        case KWFrameSet::FI_ODD_FOOTER: _odd_footer = TRUE; break;
1380
 
        case KWFrameSet::FI_EVEN_FOOTER: _even_footer = TRUE; break;
 
1681
        case KWFrameSet::FI_FIRST_HEADER: _first_header = true; break;
 
1682
        case KWFrameSet::FI_ODD_HEADER: _odd_header = true; break;
 
1683
        case KWFrameSet::FI_EVEN_HEADER: _even_header = true; break;
 
1684
        case KWFrameSet::FI_FIRST_FOOTER: _first_footer = true; break;
 
1685
        case KWFrameSet::FI_ODD_FOOTER: _odd_footer = true; break;
 
1686
        case KWFrameSet::FI_EVEN_FOOTER: _even_footer = true; break;
1381
1687
        case KWFrameSet::FI_FOOTNOTE: break;
1382
1688
        default: break;
1383
1689
        }
1384
1690
    }
1385
1691
 
1386
 
    // create defaults if they were not in the input file.
 
1692
    // Create defaults if they were not in the input file.
 
1693
 
 
1694
    // Where to insert the new frames: not at the end, since that breaks oasis-kword.sh
 
1695
    uint newFramesetsIndex = m_lstFrameSet.isEmpty() ? 0 : 1;
1387
1696
 
1388
1697
    if ( !_first_header ) {
1389
1698
        KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "First Page Header" ) );
1395
1704
        frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1396
1705
        frame->setNewFrameBehavior( KWFrame::Copy );
1397
1706
        fs->addFrame( frame );
1398
 
        m_lstFrameSet.append( fs );
 
1707
        m_lstFrameSet.insert( newFramesetsIndex++, fs );
1399
1708
    }
1400
1709
 
1401
1710
    if ( !_odd_header ) {
1406
1715
        frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1407
1716
        frame->setNewFrameBehavior( KWFrame::Copy );
1408
1717
        fs->addFrame( frame );
1409
 
        m_lstFrameSet.append( fs );
 
1718
        m_lstFrameSet.insert( newFramesetsIndex++, fs );
1410
1719
    }
1411
1720
 
1412
1721
    if ( !_even_header ) {
1417
1726
        frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1418
1727
        frame->setNewFrameBehavior( KWFrame::Copy );
1419
1728
        fs->addFrame( frame );
1420
 
        m_lstFrameSet.append( fs );
 
1729
        m_lstFrameSet.insert( newFramesetsIndex++, fs );
1421
1730
    }
1422
1731
 
1423
1732
    if ( !_first_footer ) {
1429
1738
        frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1430
1739
        frame->setNewFrameBehavior( KWFrame::Copy );
1431
1740
        fs->addFrame( frame );
1432
 
        m_lstFrameSet.append( fs );
 
1741
        m_lstFrameSet.insert( newFramesetsIndex++, fs );
1433
1742
    }
1434
1743
 
1435
1744
    if ( !_odd_footer ) {
1441
1750
        frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1442
1751
        frame->setNewFrameBehavior( KWFrame::Copy );
1443
1752
        fs->addFrame( frame );
1444
 
        m_lstFrameSet.append( fs );
 
1753
        m_lstFrameSet.insert( newFramesetsIndex++, fs );
1445
1754
    }
1446
1755
 
1447
1756
    if ( !_even_footer ) {
1453
1762
        frame->setFrameBehavior( KWFrame::AutoExtendFrame );
1454
1763
        frame->setNewFrameBehavior( KWFrame::Copy );
1455
1764
        fs->addFrame( frame );
1456
 
        m_lstFrameSet.append( fs );
 
1765
        m_lstFrameSet.insert( newFramesetsIndex++, fs );
1457
1766
    }
1458
1767
 
1459
1768
    // do some sanity checking on document.
1460
 
    for (int i = getNumFrameSets()-1; i>-1; i--) {
 
1769
    for (int i = numFrameSets()-1; i>-1; i--) {
1461
1770
        KWFrameSet *fs = frameSet(i);
1462
1771
        if(!fs) {
1463
1772
            kdWarning() << "frameset " << i << " is NULL!!" << endl;
1486
1795
            }
1487
1796
        }
1488
1797
    }
 
1798
 
 
1799
    // Renumber footnotes
 
1800
    KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
 
1801
    if ( frameset  )
 
1802
        frameset->renumberFootNotes( false /*no repaint*/ );
 
1803
 
1489
1804
    emit sigProgress(-1);
1490
1805
 
1491
1806
    //kdDebug(32001) << "KWDocument::loadXML done" << endl;
1492
1807
 
1493
 
    setModified( false );
1494
 
 
1495
1808
    // Connect to notifications from main text-frameset
1496
 
    KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
1497
1809
    if ( frameset ) {
1498
1810
        connect( frameset->textObject(), SIGNAL( chapterParagraphFormatted( KoTextParag * ) ),
1499
1811
                 SLOT( slotChapterParagraphFormatted( KoTextParag * ) ) );
1501
1813
                 SIGNAL( mainTextHeightChanged() ) );
1502
1814
    }
1503
1815
 
1504
 
    kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
1505
 
 
1506
 
    return true;
 
1816
    // Note that more stuff will happen in completeLoading
1507
1817
}
1508
1818
 
1509
1819
void KWDocument::startBackgroundSpellCheck()
1510
1820
{
1511
 
    //don't start bg spell checking if
1512
 
    if(backgroundSpellCheckEnabled() && isReadWrite())
 
1821
    if ( backgroundSpellCheckEnabled() && isReadWrite() )
1513
1822
    {
1514
 
        m_bgSpellCheck->objectForSpell(textFrameSet(0));
1515
 
        m_bgSpellCheck->startBackgroundSpellCheck();
 
1823
#ifdef HAVE_LIBKSPELL2
 
1824
        m_bgSpellCheck->start();
 
1825
#endif
1516
1826
    }
1517
 
 
1518
1827
}
1519
1828
 
1520
1829
void KWDocument::loadEmbeddedObjects( QDomElement& word )
1553
1862
        kdError(32001) << "No <OBJECT> tag in EMBEDDED" << endl;
1554
1863
}
1555
1864
 
 
1865
 
1556
1866
void KWDocument::loadStyleTemplates( const QDomElement &stylesElem )
1557
1867
{
1558
1868
    QValueList<QString> followingStyles;
1559
1869
    QDomNodeList listStyles = stylesElem.elementsByTagName( "STYLE" );
1560
1870
    if( listStyles.count() > 0) { // we are going to import at least one style.
1561
 
        KWStyle *s = m_styleColl->findStyle("Standard");
 
1871
        KoParagStyle *s = m_styleColl->findStyle("Standard");
1562
1872
        //kdDebug(32001) << "KWDocument::loadStyleTemplates looking for Standard, to delete it. Found " << s << endl;
1563
1873
        if(s) // delete the standard style.
1564
1874
            m_styleColl->removeStyleTemplate(s);
1566
1876
    for (unsigned int item = 0; item < listStyles.count(); item++) {
1567
1877
        QDomElement styleElem = listStyles.item( item ).toElement();
1568
1878
 
1569
 
        KWStyle *sty = new KWStyle( QString::null );
 
1879
        KoParagStyle *sty = new KoParagStyle( QString::null );
1570
1880
        // Load the style from the <STYLE> element
1571
1881
        sty->loadStyle( styleElem, m_syntaxVersion );
1572
1882
 
1573
 
        //kdDebug(32001) << "KoStyle created name=" << sty->name() << endl;
 
1883
        //kdDebug(32001) << "KoParagStyle created name=" << sty->name() << endl;
1574
1884
 
1575
1885
        if ( m_syntaxVersion < 3 )
1576
1886
        {
1605
1915
 
1606
1916
    unsigned int i=0;
1607
1917
    for( QValueList<QString>::Iterator it = followingStyles.begin(); it != followingStyles.end(); ++it ) {
1608
 
        KWStyle * style = m_styleColl->findStyle(*it);
 
1918
        KoParagStyle * style = m_styleColl->findStyle(*it);
1609
1919
        m_styleColl->styleAt(i++)->setFollowingStyle( style );
1610
1920
    }
1611
1921
 
1629
1939
 
1630
1940
void KWDocument::loadDefaultFrameStyleTemplates()
1631
1941
{
1632
 
    KURL fsfile;
1633
 
 
1634
 
    if ( ! QFile::exists(locate("appdata", "framestyles.xml")) )
 
1942
    // ### FIXME: why is this not working for $KDE_LANG != "en_US" (#61007)
 
1943
    const QString fsfileName( locate("appdata", "framestyles.xml") );
 
1944
 
 
1945
    kdDebug(30003) << "Data directory: " << KGlobal::dirs()->resourceDirs( "data" ) << endl;
 
1946
    kdDebug(30003) << "Directory searched: " << KGlobal::dirs()->resourceDirs( "appdata" ) << endl;
 
1947
    kdDebug(30003) << "File framestyles.xml searched at: " << fsfileName << endl;
 
1948
 
 
1949
    if ( ! QFile::exists( fsfileName ) )
1635
1950
    {
 
1951
        kdWarning(30003) << "Cannot find any framestyles.xml" << endl;
1636
1952
        if (!m_frameStyleColl->findFrameStyle("Plain")) {
1637
1953
            KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
1638
1954
            standardFrameStyle->setBackgroundColor(QColor("white"));
1645
1961
        return;
1646
1962
    }
1647
1963
 
1648
 
    fsfile.setPath( locate("appdata", "framestyles.xml") );
 
1964
    kdDebug(30003) << "File framestyles.xml found!" << endl;
1649
1965
 
1650
1966
    // Open file and parse it
1651
 
    QFile in( fsfile.path() );
 
1967
    QFile in( fsfileName );
1652
1968
    if ( !in.open( IO_ReadOnly ) )
1653
1969
    {
1654
1970
        //i18n( "Couldn't open the file for reading (check read permissions)" );
 
1971
        kdWarning(30003) << "Couldn't open the file for reading (check read permissions)" << endl;
1655
1972
        return;
1656
1973
    }
1657
 
    in.at(0);
1658
1974
    QString errorMsg;
1659
1975
    int errorLine;
1660
1976
    int errorColumn;
1661
1977
    QDomDocument doc;
1662
 
    if ( doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) ) {
1663
 
    }
1664
 
    else
 
1978
    if ( ! doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) )
1665
1979
    {
1666
1980
        kdError (30003) << "Parsing Error! Aborting! (in KWDocument::loadDefaultFrameStyleTemplates())" << endl
1667
1981
                        << "  Line: " << errorLine << " Column: " << errorColumn << endl
1963
2277
 
1964
2278
void KWDocument::loadImagesFromStore( KoStore *_store )
1965
2279
{
1966
 
    if ( _store ) {
1967
 
        m_pictureCollection.readFromStore( _store, m_pictureMap );
 
2280
    if ( _store && !m_pictureMap.isEmpty() ) {
 
2281
        m_pictureCollection->readFromStore( _store, m_pictureMap );
1968
2282
        m_pictureMap.clear(); // Release memory
1969
2283
    }
1970
2284
}
1971
2285
 
1972
2286
bool KWDocument::completeLoading( KoStore *_store )
1973
2287
{
 
2288
    kdDebug() << k_funcinfo << endl;
 
2289
    // Old-XML stuff. No-op when loading OASIS.
1974
2290
    loadImagesFromStore( _store );
1975
 
 
1976
2291
    processPictureRequests();
1977
2292
    processAnchorRequests();
1978
2293
    processFootNoteRequests();
1983
2298
    // The fields from documentinfo.xml just got loaded -> update vars
1984
2299
    recalcVariables( VT_FIELD );
1985
2300
 
1986
 
    // Finalize all the existing framesets
 
2301
    // Finalize all the existing [non-inline] framesets
1987
2302
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
1988
2303
    for ( ; fit.current() ; ++fit )
1989
2304
        fit.current()->finalize();
2004
2319
    //attributes isReadWrite is not placed at the beginning !
2005
2320
    if ( !isReadWrite())
2006
2321
        enableBackgroundSpellCheck( false );
2007
 
    return TRUE;
 
2322
 
 
2323
    // Load bookmarks
 
2324
    initBookmarkList();
 
2325
 
 
2326
    deleteLoadingInfo();
 
2327
 
 
2328
    setModified( false );
 
2329
 
 
2330
    return true;
 
2331
}
 
2332
 
 
2333
KWLoadingInfo* KWDocument::createLoadingInfo()
 
2334
{
 
2335
    Q_ASSERT( !m_loadingInfo );
 
2336
    m_loadingInfo = new KWLoadingInfo();
 
2337
    return m_loadingInfo;
 
2338
}
 
2339
 
 
2340
void KWDocument::deleteLoadingInfo()
 
2341
{
 
2342
    Q_ASSERT( m_loadingInfo );
 
2343
    delete m_loadingInfo;
 
2344
    m_loadingInfo = 0;
2008
2345
}
2009
2346
 
2010
2347
void KWDocument::processPictureRequests()
2012
2349
    QPtrListIterator<KWTextImage> it2 ( m_textImageRequests );
2013
2350
    for ( ; it2.current() ; ++it2 )
2014
2351
    {
2015
 
        it2.current()->setImage( m_pictureCollection );
 
2352
        it2.current()->setImage( *m_pictureCollection );
2016
2353
    }
2017
2354
    m_textImageRequests.clear();
2018
2355
 
2019
 
    kdDebug() << k_funcinfo << m_pictureRequests.count() << " picture requests." << endl;
 
2356
    //kdDebug(32001) << m_pictureRequests.count() << " picture requests." << endl;
2020
2357
    QPtrListIterator<KWPictureFrameSet> it3( m_pictureRequests );
2021
2358
    for ( ; it3.current() ; ++it3 )
2022
 
        it3.current()->setPicture( m_pictureCollection.findPicture( it3.current()->key() ) );
 
2359
        it3.current()->setPicture( m_pictureCollection->findPicture( it3.current()->key() ) );
2023
2360
    m_pictureRequests.clear();
2024
2361
}
2025
2362
 
2052
2389
        //kdDebug(32001) << "KWDocument::processFootNoteRequests binding footnote var " << itvar.data() << " and frameset " << fsname << endl;
2053
2390
        KWFrameSet * fs = frameSetByName( fsname );
2054
2391
        Q_ASSERT( fs );
 
2392
        if ( !fs ) // #104431
 
2393
            continue;
2055
2394
        Q_ASSERT( fs->type() == FT_TEXT );
2056
2395
        Q_ASSERT( fs->frameSetInfo() == KWFrameSet::FI_FOOTNOTE );
2057
2396
        KWFootNoteFrameSet* fnfs = dynamic_cast<KWFootNoteFrameSet *>(fs);
2074
2413
 
2075
2414
QString KWDocument::uniqueFramesetName( const QString& oldName )
2076
2415
{
2077
 
    // make up a new name for the frameset, use Copy[digits]-[oldname] as template.
2078
 
    // Fully translatable naturally :)
2079
 
    int count=0;
2080
 
    QString searchString ("^("+ i18n("Copy%1-%2").arg("\\d*").arg("){0,1}"));
2081
 
    searchString=searchString.replace(QRegExp("\\-"), "\\-"); // escape the '-'
2082
 
    QString newName=oldName;
 
2416
    QString newName = oldName;
2083
2417
    if (frameSetByName( oldName ))//rename it if name frameset exists
2084
2418
    {
 
2419
        // make up a new name for the frameset, use Copy[digits]-[oldname] as template.
 
2420
        // Fully translatable naturally :)
 
2421
        QString searchString( "^(" + i18n("Copy%1-%2").arg("\\d*").arg("){0,1}") );
 
2422
        searchString = searchString.replace(QRegExp("\\-"), "\\-"); // escape the '-'
2085
2423
        QRegExp searcher(searchString);
 
2424
        int count=0;
2086
2425
        do {
2087
2426
            newName=oldName;
2088
2427
            newName.replace(searcher,i18n("Copy%1-%2").arg(count > 0? QString("%1").arg(count):"").arg(""));
2248
2587
    m_pasteFramesetsMap = 0L;
2249
2588
}
2250
2589
 
 
2590
void KWDocument::completeOasisPasting()
 
2591
{
 
2592
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
 
2593
    for ( ; fit.current() ; ++fit )
 
2594
        fit.current()->finalize();
 
2595
    repaintAllViews();
 
2596
}
 
2597
 
2251
2598
void KWDocument::insertEmbedded( KoStore *store, QDomElement topElem, KMacroCommand * macroCmd, double offset )
2252
2599
{
2253
2600
    if ( !m_pasteFramesetsMap ) // may have been created by pasteFrames
2301
2648
    refreshDocStructure( (int)Embedded );
2302
2649
}
2303
2650
 
 
2651
bool KWDocument::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
 
2652
{
 
2653
    return saveOasis( store, manifestWriter, SaveAll );
 
2654
}
 
2655
 
 
2656
// can't be const due to recalcVariables()
 
2657
// TODO: rename to saveOasisHelper
 
2658
bool KWDocument::saveOasis( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag,
 
2659
                            QString* plainText, KoPicture* picture, KWTextFrameSet* fs )
 
2660
{
 
2661
    m_pictureCollection->assignUniqueIds();
 
2662
 
 
2663
    manifestWriter->addManifestEntry( "content.xml", "text/xml" );
 
2664
    KoOasisStore oasisStore( store );
 
2665
 
 
2666
    KoXmlWriter* contentWriter = oasisStore.contentWriter();
 
2667
    if ( !contentWriter )
 
2668
        return false;
 
2669
 
 
2670
    QValueList<KoPictureKey> pictureList;
 
2671
    if ( saveFlag == SaveAll )
 
2672
        pictureList = savePictureList();
 
2673
 
 
2674
    m_varColl->variableSetting()->setModificationDate(QDateTime::currentDateTime());
 
2675
    recalcVariables( VT_DATE );
 
2676
    recalcVariables( VT_TIME ); // for "current time"
 
2677
    m_syntaxVersion = CURRENT_SYNTAX_VERSION; // ### clean this up once we remove the old format
 
2678
 
 
2679
    KoGenStyles mainStyles;
 
2680
    KoSavingContext savingContext( mainStyles, m_varColl->variableSetting(), m_pageColumns.columns > 1, KoSavingContext::Store );
 
2681
 
 
2682
    // Save user styles as KoGenStyle objects
 
2683
    KoSavingContext::StyleNameMap map = m_styleColl->saveOasis( mainStyles, KoGenStyle::STYLE_USER, savingContext );
 
2684
    savingContext.setStyleNameMap( map );
 
2685
 
 
2686
    if ( saveFlag == SaveAll )
 
2687
    {
 
2688
        // Save visual info for the first view, such as the active frameset and cursor position
 
2689
        // It looks like a hack, but reopening a document creates only one view anyway (David)
 
2690
        KWView * view = static_cast<KWView*>(views().getFirst());
 
2691
        if ( view ) // no view if embedded document
 
2692
        {
 
2693
            KWFrameSetEdit* edit = view->getGUI()->canvasWidget()->currentFrameSetEdit();
 
2694
            if ( edit )
 
2695
            {
 
2696
                KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(edit);
 
2697
                if ( textedit && textedit->cursor() ) {
 
2698
                    KoTextCursor* cursor = textedit->cursor();
 
2699
                    savingContext.setCursorPosition( cursor->parag(),
 
2700
                                                     cursor->index() );
 
2701
                }
 
2702
            }
 
2703
        }
 
2704
    }
 
2705
 
 
2706
    KoXmlWriter* bodyWriter = oasisStore.bodyWriter();
 
2707
    bodyWriter->startElement( "office:body" );
 
2708
    bodyWriter->startElement( "office:text" );
 
2709
 
 
2710
    if ( saveFlag == SaveAll )
 
2711
    {
 
2712
        // save the body into bodyWriter
 
2713
        saveOasisBody( *bodyWriter, savingContext );
 
2714
    }
 
2715
    else // SaveSelected
 
2716
    {
 
2717
        // In theory we should pass a view to this method, in order to
 
2718
        // copy what is currently selected in that view only. But selection
 
2719
        // is currently part of the KoTextParag data, so it's shared between views.
 
2720
        if ( fs ) {
 
2721
            *plainText = fs->textDocument()->copySelection( *bodyWriter, savingContext, KoTextDocument::Standard );
 
2722
            // Collect inline framesets for e.g. pictures
 
2723
            KWCollectFramesetsVisitor visitor;
 
2724
            fs->textDocument()->visitSelection( KoTextDocument::Standard, &visitor );
 
2725
            const QValueList<KWFrameSet *>& frameset = visitor.frameSets();
 
2726
            kdDebug(32001) << frameset.count() << " inline framesets" << endl;
 
2727
            for ( QValueList<KWFrameSet *>::ConstIterator it = frameset.begin(); it != frameset.end(); ++it )
 
2728
            {
 
2729
                switch ( (*it)->type() ) {
 
2730
                case FT_PICTURE:
 
2731
                {
 
2732
                    const KoPictureKey key = static_cast<KWPictureFrameSet *>( *it )->key();
 
2733
                    if ( !pictureList.contains( key ) )
 
2734
                        pictureList.append( key );
 
2735
                }
 
2736
                break;
 
2737
                case FT_PART:
 
2738
                    // TODO
 
2739
                default:
 
2740
                    break;
 
2741
                }
 
2742
            }
 
2743
        }
 
2744
 
 
2745
        // write selected (non-inline) frames
 
2746
        QString newText;
 
2747
        saveSelectedFrames( *bodyWriter, store, manifestWriter, savingContext, pictureList,
 
2748
                            &newText ); // output vars
 
2749
        *plainText += newText;
 
2750
        // Single image -> return it
 
2751
        if ( picture && pictureList.count() == 1 )
 
2752
        {
 
2753
            *picture = m_pictureCollection->findPicture( pictureList.first() );
 
2754
        }
 
2755
    }
 
2756
 
 
2757
    bodyWriter->endElement(); // office:text
 
2758
    bodyWriter->endElement(); // office:body
 
2759
 
 
2760
    KWOasisSaver::writeAutomaticStyles( *contentWriter, mainStyles, savingContext );
 
2761
 
 
2762
    oasisStore.closeContentWriter();
 
2763
 
 
2764
    // Done with content.xml
 
2765
 
 
2766
    if ( !store->open( "styles.xml" ) )
 
2767
        return false;
 
2768
    manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
 
2769
    saveOasisDocumentStyles( store, mainStyles, savingContext, saveFlag );
 
2770
    if ( !store->close() ) // done with styles.xml
 
2771
        return false;
 
2772
 
 
2773
    //kdDebug(32001) << "saveOasis: " << pictureList.count() << " pictures" << endl;
 
2774
    m_pictureCollection->saveOasisToStore( store, pictureList, manifestWriter );
 
2775
 
 
2776
    if ( saveFlag == SaveAll )
 
2777
    {
 
2778
 
 
2779
        if(!store->open("settings.xml"))
 
2780
            return false;
 
2781
 
 
2782
        KoStoreDevice contentDev( store );
 
2783
        KoXmlWriter& settingsWriter = *createOasisXmlWriter(&contentDev, "office:document-settings");
 
2784
 
 
2785
        saveOasisSettings( settingsWriter );
 
2786
 
 
2787
        delete &settingsWriter;
 
2788
 
 
2789
        if(!store->close())
 
2790
            return false;
 
2791
 
 
2792
        manifestWriter->addManifestEntry("settings.xml", "text/xml");
 
2793
    }
 
2794
    return true;
 
2795
}
 
2796
 
 
2797
// can't be const due to recalcVariables()
 
2798
QDragObject* KWDocument::dragSelected( QWidget* parent, KWTextFrameSet* fs )
 
2799
{
 
2800
    // We'll create a store (ZIP format) in memory
 
2801
    QBuffer buffer;
 
2802
    QCString mimeType = KWOasisSaver::selectionMimeType();
 
2803
    KoStore* store = KoStore::createStore( &buffer, KoStore::Write, mimeType );
 
2804
    Q_ASSERT( store );
 
2805
    Q_ASSERT( !store->bad() );
 
2806
    KoOasisStore oasisStore( store );
 
2807
 
 
2808
    KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
 
2809
 
 
2810
    QString plainText;
 
2811
    KoPicture picture;
 
2812
    if ( !saveOasis( store, manifestWriter, KWDocument::SaveSelected, &plainText, &picture, fs )
 
2813
         || !oasisStore.closeManifestWriter() )
 
2814
    {
 
2815
        delete store;
 
2816
        return 0;
 
2817
    }
 
2818
 
 
2819
    delete store;
 
2820
 
 
2821
    KMultipleDrag* multiDrag = new KMultipleDrag( parent );
 
2822
    if ( !plainText.isEmpty() )
 
2823
        multiDrag->addDragObject( new QTextDrag( plainText, 0 ) );
 
2824
    if ( !picture.isNull() )
 
2825
        multiDrag->addDragObject( picture.dragObject( 0 ) );
 
2826
    KoStoreDrag* storeDrag = new KoStoreDrag( KWOasisSaver::selectionMimeType(), 0 );
 
2827
    kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl;
 
2828
    storeDrag->setEncodedData( buffer.buffer() );
 
2829
    multiDrag->addDragObject( storeDrag );
 
2830
    return multiDrag;
 
2831
}
 
2832
 
 
2833
void KWDocument::saveSelectedFrames( KoXmlWriter& bodyWriter, KoStore* store, KoXmlWriter* manifestWriter,
 
2834
                                     KoSavingContext& savingContext, QValueList<KoPictureKey>& pictureList,
 
2835
                                     QString* plainText ) const
 
2836
{
 
2837
    QPtrList<KoDocumentChild> embeddedObjects;
 
2838
 
 
2839
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
 
2840
    for ( ; fit.current() ; ++fit ) {
 
2841
        KWFrameSet * fs = fit.current();
 
2842
        if ( fs->isVisible() && fs->type() == FT_PART
 
2843
             && fs->frameIterator().getFirst()->isSelected() ) {
 
2844
            embeddedObjects.append( static_cast<KWPartFrameSet *>(fs)->getChild() );
 
2845
        }
 
2846
    }
 
2847
 
 
2848
    fit = framesetsIterator();
 
2849
    for ( ; fit.current() ; ++fit )
 
2850
    {
 
2851
        KWFrameSet * fs = fit.current();
 
2852
        if ( fs->isVisible() )
 
2853
        {
 
2854
            bool isTable = ( fs->type() == FT_TABLE );
 
2855
            if ( fs->type() == FT_PART )
 
2856
                continue;
 
2857
            QPtrListIterator<KWFrame> frameIt = fs->frameIterator();
 
2858
            KWFrame * firstFrame = frameIt.current();
 
2859
            for ( ; frameIt.current(); ++frameIt )
 
2860
            {
 
2861
                KWFrame * frame = frameIt.current();
 
2862
                if ( frame->isSelected() )
 
2863
                {
 
2864
                    kdDebug(32001) << "Selected frame " << frame << " from " << fs->getName() << endl;
 
2865
                    // Two cases to be distinguished here
 
2866
                    // If it's the first frame of a frameset, then copy the frameset contents and the frame itself
 
2867
                    // Otherwise copy only the frame information
 
2868
                    if ( frame == firstFrame || isTable )
 
2869
                    {
 
2870
                        fs->saveOasis( bodyWriter, savingContext, /*TODO: check this: isTable ? true :*/ false );
 
2871
                        if ( plainText )
 
2872
                            *plainText += fs->toPlainText();
 
2873
                    }
 
2874
                    else if ( !isTable )
 
2875
                    {
 
2876
#if 0
 
2877
                        // Save the frame information
 
2878
                        QDomElement frameElem = parentElem.ownerDocument().createElement( "FRAME" );
 
2879
                        parentElem.appendChild( frameElem );
 
2880
                        frame->save( frameElem );
 
2881
                        if ( frame != firstFrame )
 
2882
                        {
 
2883
                            // Frame saved alone -> remember which frameset it's part of
 
2884
                            frameElem.setAttribute( "parentFrameset", fs->getName() );
 
2885
                        }
 
2886
#endif
 
2887
                    }
 
2888
                    if ( fs->type() == FT_PICTURE ) {
 
2889
                        kdDebug(32001) << "found non-inline picture framesets" << endl;
 
2890
 
 
2891
                        const KoPictureKey key = static_cast<KWPictureFrameSet *>( fs )->key();
 
2892
                        if ( !pictureList.contains( key ) )
 
2893
                            pictureList.append( key );
 
2894
                    }
 
2895
                    if ( isTable ) // Copy tables only once, even if they have many cells selected
 
2896
                        break;
 
2897
                }
 
2898
            } // for each frame
 
2899
        }
 
2900
    }
 
2901
 
 
2902
    // Save embedded objects - code inspired from KoDocument::saveChildrenOasis
 
2903
    QPtrListIterator<KoDocumentChild> chl( embeddedObjects );
 
2904
    for( ; chl.current(); ++chl ) {
 
2905
        KoDocument* childDoc = chl.current()->document();
 
2906
        QString path;
 
2907
        if ( childDoc ) {
 
2908
            if ( !childDoc->isStoredExtern() ) {
 
2909
                if ( !chl.current()->saveOasisToStore( store, manifestWriter ) )
 
2910
                    return;
 
2911
 
 
2912
                //assert( childDoc->url().protocol() == INTERNAL_PROTOCOL );
 
2913
                path = store->currentDirectory();
 
2914
                if ( !path.isEmpty() )
 
2915
                    path += '/';
 
2916
                path += childDoc->url().path();
 
2917
            } else {
 
2918
                path = childDoc->url().url();
 
2919
            }
 
2920
            manifestWriter->addManifestEntry( path, childDoc->nativeOasisMimeType() );
 
2921
        }
 
2922
    }
 
2923
}
 
2924
 
 
2925
void KWDocument::saveOasisSettings( KoXmlWriter& settingsWriter ) const
 
2926
{
 
2927
    settingsWriter.startElement("office:settings");
 
2928
    settingsWriter.startElement("config:config-item-set");
 
2929
 
 
2930
    settingsWriter.addAttribute("config:name", "view-settings");
 
2931
 
 
2932
    KoUnit::saveOasis(&settingsWriter, m_unit);
 
2933
 
 
2934
    settingsWriter.endElement(); // config:config-item-set
 
2935
 
 
2936
    settingsWriter.startElement("config:config-item-set");
 
2937
    settingsWriter.addAttribute("config:name", "configuration-settings");
 
2938
    settingsWriter.addConfigItem("SpellCheckerIgnoreList", m_spellCheckIgnoreList.join( "," ) );
 
2939
    settingsWriter.endElement(); // config:config-item-set
 
2940
 
 
2941
    m_varColl->variableSetting()->saveOasis( settingsWriter );
 
2942
 
 
2943
    settingsWriter.endElement(); // office:settings
 
2944
    settingsWriter.endElement(); // Root element
 
2945
    settingsWriter.endDocument();
 
2946
}
 
2947
 
 
2948
void KWDocument::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles, KoSavingContext& savingContext, SaveFlag saveFlag ) const
 
2949
{
 
2950
    KoStoreDevice stylesDev( store );
 
2951
    KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" );
 
2952
 
 
2953
    stylesWriter->startElement( "office:styles" );
 
2954
 
 
2955
    if ( saveFlag == SaveAll )
 
2956
    {
 
2957
        stylesWriter->startElement( "style:default-style" );
 
2958
        stylesWriter->addAttribute( "style:family", "paragraph" );
 
2959
        stylesWriter->startElement( "style:paragraph-properties" );
 
2960
        stylesWriter->addAttributePt( "style:tab-stop-distance", m_tabStop );
 
2961
        stylesWriter->endElement(); // paragraph-properties
 
2962
        stylesWriter->endElement(); // default-style
 
2963
    }
 
2964
 
 
2965
    QValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_USER );
 
2966
    QValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
 
2967
    for ( ; it != styles.end() ; ++it ) {
 
2968
        (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
 
2969
    }
 
2970
    styles = mainStyles.styles( KoGenStyle::STYLE_LIST );
 
2971
    it = styles.begin();
 
2972
    for ( ; it != styles.end() ; ++it ) {
 
2973
        (*it).style->writeStyle( stylesWriter, mainStyles, "text:list-style", (*it).name, 0 );
 
2974
    }
 
2975
    m_styleColl->saveOasisOutlineStyles( *stylesWriter );
 
2976
    if ( saveFlag == SaveAll )
 
2977
        static_cast<KWVariableSettings *>( m_varColl->variableSetting() )->saveNoteConfiguration( *stylesWriter );
 
2978
    stylesWriter->endElement(); // office:styles
 
2979
 
 
2980
    QString pageLayoutName;
 
2981
    QByteArray headerFooters;
 
2982
    if ( saveFlag == SaveAll )
 
2983
    {
 
2984
        stylesWriter->startElement( "office:automatic-styles" );
 
2985
 
 
2986
        KoGenStyle pageLayout = m_pageLayout.saveOasis();
 
2987
        pageLayout.addAttribute( "style:page-usage", "all" ); // needed?
 
2988
        // This is for e.g. spreadsheets, not for word-processors.
 
2989
        //pageLayout.addProperty( "style:first-page-number", m_varColl->variableSetting()->startingPage() );
 
2990
 
 
2991
        QBuffer buffer;
 
2992
        buffer.open( IO_WriteOnly );
 
2993
        KoXmlWriter footnoteSepTmpWriter( &buffer );  // TODO pass indentation level
 
2994
        footnoteSepTmpWriter.startElement( "style:footnote-sep" );
 
2995
        QString tmp;
 
2996
        switch( m_footNoteSeparatorLinePos )
 
2997
        {
 
2998
        case SLP_CENTERED:
 
2999
            tmp = "centered";
 
3000
            break;
 
3001
        case SLP_RIGHT:
 
3002
            tmp = "right";
 
3003
            break;
 
3004
        case SLP_LEFT:
 
3005
            tmp = "left";
 
3006
            break;
 
3007
        }
 
3008
 
 
3009
        footnoteSepTmpWriter.addAttribute( "style:adjustment", tmp );
 
3010
        footnoteSepTmpWriter.addAttributePt( "style:width", m_footNoteSeparatorLineWidth );
 
3011
        footnoteSepTmpWriter.addAttribute( "style:rel-width", QString::number( footNoteSeparatorLineLength() ) + "%" );
 
3012
        switch( m_footNoteSeparatorLineType )
 
3013
        {
 
3014
        case SLT_SOLID:
 
3015
            tmp = "solid";
 
3016
            break;
 
3017
        case SLT_DASH:
 
3018
            tmp = "dash";
 
3019
            break;
 
3020
        case SLT_DOT:
 
3021
            tmp = "dotted";
 
3022
            break;
 
3023
        case SLT_DASH_DOT:
 
3024
            tmp = "dot-dash";
 
3025
            break;
 
3026
        case SLT_DASH_DOT_DOT:
 
3027
            tmp = "dot-dot-dash";
 
3028
            break;
 
3029
        }
 
3030
 
 
3031
        footnoteSepTmpWriter.addAttribute( "style:line-style", tmp );
 
3032
 
 
3033
        footnoteSepTmpWriter.endElement();
 
3034
        const QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
 
3035
        pageLayout.addChildElement( "separator", elementContents );
 
3036
        buffer.close();
 
3037
 
 
3038
        if ( m_pageColumns.columns > 1 ) {
 
3039
            buffer.setBuffer( QByteArray() ); // clear data
 
3040
            buffer.open( IO_WriteOnly );
 
3041
            KoXmlWriter columnsTmpWriter( &buffer );  // TODO pass indentation level
 
3042
            columnsTmpWriter.startElement( "style:columns" );
 
3043
            columnsTmpWriter.addAttribute( "fo:column-count", m_pageColumns.columns );
 
3044
            columnsTmpWriter.addAttributePt( "fo:column-gap", m_pageColumns.ptColumnSpacing );
 
3045
            columnsTmpWriter.endElement(); // style:columns
 
3046
            buffer.close();
 
3047
            const QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
 
3048
            pageLayout.addChildElement( "columns", elementContents );
 
3049
        }
 
3050
 
 
3051
        // This is a bit of a hack, which only works as long as we have only one page master
 
3052
        // if there's more than one pagemaster we need to rethink all this
 
3053
 
 
3054
        pageLayoutName = mainStyles.lookup( pageLayout, "pm" );
 
3055
        pageLayout.writeStyle( stylesWriter, mainStyles, "style:page-layout", pageLayoutName,
 
3056
                               "style:page-layout-properties", false /*don't close*/ );
 
3057
 
 
3058
        // Header and footers save their content into master-styles/master-page, but their
 
3059
        // styles into the page-layout automatic-style. To avoid splitting that code
 
3060
        // in two places (and inconsistent iteration), we save both here, the content
 
3061
        // going into
 
3062
        buffer.setBuffer( headerFooters );
 
3063
        buffer.open( IO_WriteOnly );
 
3064
        // Ouch another problem: there is only one header style in oasis
 
3065
        // ##### can't have different borders for even/odd headers...
 
3066
        bool headerStyleSaved = false;
 
3067
        bool footerStyleSaved = false;
 
3068
        KoXmlWriter headerFooterTmpWriter( &buffer );  // TODO pass indentation level
 
3069
        QPtrListIterator<KWFrameSet> fit = framesetsIterator();
 
3070
        for ( ; fit.current() ; ++fit ) {
 
3071
            const KWFrameSet* fs = fit.current();
 
3072
            if ( fs->isVisible() && // HACK to avoid saving [hidden] headers/footers framesets for now
 
3073
                 !fs->isFloating() &&
 
3074
                 !fs->isDeleted() &&
 
3075
                 fs->type() == FT_TEXT &&
 
3076
                 fs->isHeaderOrFooter() )
 
3077
            {
 
3078
                // Save content
 
3079
                headerFooterTmpWriter.startElement( fs->headerFooterTag() ); // e.g. style:header
 
3080
                static_cast<const KWTextFrameSet *>(fs)->saveOasisContent( headerFooterTmpWriter, savingContext );
 
3081
                headerFooterTmpWriter.endElement();
 
3082
                // Save style
 
3083
                KWFrame* frame = fs->frame(0);
 
3084
                if ( fs->isAHeader() ) {
 
3085
                    if ( headerStyleSaved )
 
3086
                        continue;
 
3087
                    stylesWriter->startElement( "style:header-style" );
 
3088
                } else {
 
3089
                    if ( footerStyleSaved )
 
3090
                        continue;
 
3091
                    stylesWriter->startElement( "style:footer-style" );
 
3092
                }
 
3093
#if 0 // more code reuse, but harder to integrate
 
3094
                KoGenStyle hfStyle;
 
3095
                hfStyle.addPropertyPt( "fo:min-height", frame->minFrameHeight() );
 
3096
                frame->saveBorderProperties( hfStyle );
 
3097
                frame->saveMarginProperties( hfStyle );
 
3098
                ...
 
3099
#endif
 
3100
                stylesWriter->startElement( "style:header-footer-properties" );
 
3101
                stylesWriter->addAttributePt( "fo:min-height", frame->minFrameHeight() );
 
3102
                // TODO frame->saveBorderAttributes( *stylesWriter );
 
3103
                frame->saveMarginAttributes( *stylesWriter );
 
3104
                stylesWriter->endElement(); // header-footer-properties
 
3105
                stylesWriter->endElement(); // header-style
 
3106
            }
 
3107
        }
 
3108
        stylesWriter->endElement(); // style:page-layout
 
3109
        stylesWriter->endElement(); // office:automatic-styles
 
3110
    }
 
3111
 
 
3112
 
 
3113
    stylesWriter->startElement( "office:master-styles" );
 
3114
    stylesWriter->startElement( "style:master-page" );
 
3115
    stylesWriter->addAttribute( "style:name", "Standard" );
 
3116
    stylesWriter->addAttribute( "style:page-layout-name", pageLayoutName );
 
3117
 
 
3118
    if ( isHeaderVisible() || isFooterVisible() ) { // ### TODO save them even when hidden (and not empty)?
 
3119
        headerFooters.resize( headerFooters.size() + 1 );
 
3120
        headerFooters[headerFooters.size()-1] = '\0';
 
3121
        stylesWriter->addCompleteElement( headerFooters.data() );
 
3122
    }
 
3123
 
 
3124
    stylesWriter->endElement();
 
3125
    stylesWriter->endElement(); // office:master-styles
 
3126
 
 
3127
    stylesWriter->endElement(); // root element (office:document-styles)
 
3128
    stylesWriter->endDocument();
 
3129
    delete stylesWriter;
 
3130
}
 
3131
 
 
3132
void KWDocument::saveOasisCustomFied( KoXmlWriter &writer )const
 
3133
{
 
3134
    bool customVariableFound = false;
 
3135
    QPtrListIterator<KoVariable> it( m_varColl->getVariables() );
 
3136
    for ( ; it.current() ; ++it )
 
3137
    {
 
3138
        if ( it.current()->type() == VT_CUSTOM )
 
3139
        {
 
3140
            if ( !customVariableFound )
 
3141
            {
 
3142
                writer.startElement( "text:user-field-decls" );
 
3143
                customVariableFound = true;
 
3144
            }
 
3145
            //<text:user-field-decl office:value-type="string" office:string-value="dfddd" text:name="cvbcbcbx"/>
 
3146
            writer.startElement( "text:user-field-decl" );
 
3147
            writer.addAttribute( "office:value-type", "string" );
 
3148
            writer.addAttribute( "office:string-value", static_cast<KoCustomVariable *>( it.current() )->value() );
 
3149
            writer.addAttribute( "text:name", static_cast<KoCustomVariable*>( it.current() )->name() );
 
3150
            writer.endElement();
 
3151
        }
 
3152
    }
 
3153
    if ( customVariableFound )
 
3154
        writer.endElement();
 
3155
}
 
3156
 
 
3157
void KWDocument::saveOasisBody( KoXmlWriter& writer, KoSavingContext& context ) const
 
3158
{
 
3159
    saveOasisCustomFied( writer );
 
3160
    if ( m_processingType == WP ) {
 
3161
        // Write out the main text frameset's contents
 
3162
        KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
 
3163
        if ( frameset ) {
 
3164
            frameset->saveOasisContent( writer, context );
 
3165
        }
 
3166
        // Write out the other (non-inline) framesets
 
3167
        QPtrListIterator<KWFrameSet> fit = framesetsIterator();
 
3168
        ++fit; // skip main text frameset
 
3169
        for ( ; fit.current() ; ++fit ) {
 
3170
            KWFrameSet* fs = fit.current();
 
3171
            if ( !fs->isFloating() &&
 
3172
                 !fs->isDeleted() &&
 
3173
                // footnotes already saved inline, header/footers elsewhere
 
3174
                 fs->frameSetInfo() == KWFrameSet::FI_BODY )
 
3175
            {
 
3176
                fs->saveOasis( writer, context, true );
 
3177
            }
 
3178
        }
 
3179
 
 
3180
    } else { // DTP mode: all framesets are equal
 
3181
        // write text:page-sequence, one item per page.
 
3182
        writer.startElement( "text:page-sequence" );
 
3183
        for ( int page = 0; page < m_pages; ++page )
 
3184
        {
 
3185
            writer.startElement( "text:page" );
 
3186
            // "pm" is a hack, see mainStyles.lookup( pageLayout, "pm" ) in saveOasis
 
3187
            // [which currently happens afterwards...]
 
3188
            writer.addAttribute( "text:master-page-name", "pm" );
 
3189
            writer.endElement(); // text:page
 
3190
        }
 
3191
        writer.endElement() ; // "text:page-sequence";
 
3192
        // Now write the framesets
 
3193
        QPtrListIterator<KWFrameSet> fit = framesetsIterator();
 
3194
        for ( ; fit.current() ; ++fit ) {
 
3195
            KWFrameSet* fs = fit.current();
 
3196
            if ( !fs->isFloating() &&
 
3197
                 !fs->isDeleted() &&
 
3198
                 fs->frameSetInfo() == KWFrameSet::FI_BODY )
 
3199
            {
 
3200
                fs->saveOasis( writer, context, true );
 
3201
            }
 
3202
        }
 
3203
     }
 
3204
}
 
3205
 
2304
3206
QDomDocument KWDocument::saveXML()
2305
3207
{
2306
3208
    m_varColl->variableSetting()->setModificationDate(QDateTime::currentDateTime());
2359
3261
    docattrs.setAttribute( "standardpage", 1 );
2360
3262
    docattrs.setAttribute( "hasHeader", static_cast<int>(isHeaderVisible()) );
2361
3263
    docattrs.setAttribute( "hasFooter", static_cast<int>(isFooterVisible()) );
2362
 
    docattrs.setAttribute( "unit", KoUnit::unitName(getUnit()) );
 
3264
    docattrs.setAttribute( "unit", KoUnit::unitName(unit()) );
2363
3265
    docattrs.setAttribute( "hasTOC", static_cast<int>(m_hasTOC));
2364
3266
    docattrs.setAttribute( "tabStopValue", m_tabStop );
2365
3267
 
2366
 
    // Save visual info for the first view, such as active table and active cell
 
3268
    // Save visual info for the first view, such as the active frameset and cursor position
2367
3269
    // It looks like a hack, but reopening a document creates only one view anyway (David)
2368
3270
    KWView * view = static_cast<KWView*>(views().getFirst());
2369
3271
    if ( view ) // no view if embedded document
2406
3308
            }
2407
3309
        }
2408
3310
    }
2409
 
    getVariableCollection()->variableSetting()->save(kwdoc );
 
3311
    variableCollection()->variableSetting()->save(kwdoc );
2410
3312
 
2411
3313
    QDomElement framesets = doc.createElement( "FRAMESETS" );
2412
3314
    kwdoc.appendChild( framesets );
2425
3327
        {
2426
3328
            // Set the child geometry from the frame geometry, with no viewmode applied
2427
3329
            // to prepare saving below with the correct geometry
2428
 
            static_cast<KWPartFrameSet *>(frameSet)->updateChildGeometry( 0L );
 
3330
            KWPartFrameSet *fs = static_cast<KWPartFrameSet *>(frameSet);
 
3331
            fs->getChild()->blockSignals( true ); // we don't want slotChildChanged to be called as it makes KWord call setModified(true) when the user leave the part.
 
3332
            fs->updateChildGeometry( 0L );
 
3333
            fs->getChild()->blockSignals( false );
2429
3334
        }
2430
3335
 
2431
3336
        // If picture frameset, make a note of the image it needs.
2449
3354
 
2450
3355
    QDomElement styles = doc.createElement( "STYLES" );
2451
3356
    kwdoc.appendChild( styles );
2452
 
    QPtrList<KWStyle> m_styleList(m_styleColl->styleList());
2453
 
    for ( KWStyle * p = m_styleList.first(); p != 0L; p = m_styleList.next() )
 
3357
    QPtrList<KoParagStyle> styleList(m_styleColl->styleList());
 
3358
    for ( KoParagStyle * p = styleList.first(); p != 0L; p = styleList.next() )
2454
3359
        saveStyle( p, styles );
2455
3360
 
2456
3361
    QDomElement frameStyles = doc.createElement( "FRAMESTYLES" );
2467
3372
 
2468
3373
    if (specialOutputFlag()==SaveAsKOffice1dot1)
2469
3374
    {
2470
 
        m_pictureCollection.saveXMLAsKOffice1Dot1( doc, kwdoc, savePictures );
 
3375
        m_pictureCollection->saveXMLAsKOffice1Dot1( doc, kwdoc, savePictures );
2471
3376
    }
2472
3377
    else
2473
3378
    {
2474
 
        QDomElement pictures = m_pictureCollection.saveXML( KoPictureCollection::CollectionPicture, doc, savePictures );
 
3379
        QDomElement pictures = m_pictureCollection->saveXML( KoPictureCollection::CollectionPicture, doc, savePictures );
2475
3380
        kwdoc.appendChild( pictures );
2476
3381
    }
2477
3382
    // Not needed anymore
2493
3398
    QDomElement mailMerge=m_slDataBase->save(doc);
2494
3399
    kwdoc.appendChild(mailMerge);
2495
3400
 
2496
 
    if( !m_spellListIgnoreAll.isEmpty() )
 
3401
    if( !m_spellCheckIgnoreList.isEmpty() )
2497
3402
    {
2498
3403
        QDomElement spellCheckIgnore = doc.createElement( "SPELLCHECKIGNORELIST" );
2499
3404
        kwdoc.appendChild( spellCheckIgnore );
2500
 
        for ( QStringList::Iterator it = m_spellListIgnoreAll.begin(); it != m_spellListIgnoreAll.end(); ++it )
 
3405
        for ( QStringList::ConstIterator it = m_spellCheckIgnoreList.begin(); it != m_spellCheckIgnoreList.end(); ++it )
2501
3406
        {
2502
3407
            QDomElement spellElem = doc.createElement( "SPELLCHECKIGNOREWORD" );
2503
3408
            spellCheckIgnore.appendChild( spellElem );
2510
3415
    return doc;
2511
3416
}
2512
3417
 
 
3418
// KWord-1.3 format
2513
3419
void KWDocument::saveEmbeddedObjects( QDomElement& parentElem, const QPtrList<KoDocumentChild>& childList )
2514
3420
{
2515
3421
    // Write "OBJECT" tag for every child, appending "EMBEDDING" tags to the main XML
2533
3439
    }
2534
3440
}
2535
3441
 
2536
 
void KWDocument::saveStyle( KWStyle *sty, QDomElement parentElem )
 
3442
// KWord-1.3 format
 
3443
void KWDocument::saveStyle( KoParagStyle *sty, QDomElement parentElem )
2537
3444
{
2538
3445
    QDomDocument doc = parentElem.ownerDocument();
2539
3446
    QDomElement styleElem = doc.createElement( "STYLE" );
2545
3452
    styleElem.appendChild( formatElem );
2546
3453
}
2547
3454
 
 
3455
// KWord-1.3 format
2548
3456
void KWDocument::saveFrameStyle( KWFrameStyle *sty, QDomElement parentElem )
2549
3457
{
2550
3458
    QDomDocument doc = parentElem.ownerDocument();
2554
3462
    sty->saveFrameStyle( frameStyleElem );
2555
3463
}
2556
3464
 
 
3465
// KWord-1.3 format
2557
3466
void KWDocument::saveTableStyle( KWTableStyle *sty, QDomElement parentElem )
2558
3467
{
2559
3468
    QDomDocument doc = parentElem.ownerDocument();
2563
3472
    sty->saveTableStyle( tableStyleElem );
2564
3473
}
2565
3474
 
 
3475
 
 
3476
QValueList<KoPictureKey> KWDocument::savePictureList()
 
3477
{
 
3478
    QValueList<KoPictureKey> savePictures;
 
3479
 
 
3480
    // At first, we must process the data of the KWTextImage classes.
 
3481
    // Process the data of the KWTextImage classes.
 
3482
    QPtrListIterator<KWTextImage> textIt ( m_textImageRequests );
 
3483
    for ( ; textIt.current() ; ++textIt )
 
3484
    {
 
3485
        KoPictureKey key = textIt.current()->getKey();
 
3486
        kdDebug(32001) << "KWDocument::saveXML registering text image " << key.toString() << endl;
 
3487
        if ( !savePictures.contains( key ) )
 
3488
            savePictures.append( key );
 
3489
    }
 
3490
    m_textImageRequests.clear(); // Save some memory!
 
3491
 
 
3492
    // Now do the images/cliparts in frames.
 
3493
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
 
3494
    for ( ; fit.current() ; ++fit )
 
3495
    {
 
3496
        KWFrameSet *frameSet = fit.current();
 
3497
        // If picture frameset, make a note of the image it needs.
 
3498
        if ( !frameSet->isDeleted() && ( frameSet->type() == FT_PICTURE ) )
 
3499
        {
 
3500
            KoPictureKey key = static_cast<KWPictureFrameSet *>( frameSet )->key();
 
3501
            if ( !savePictures.contains( key ) )
 
3502
                savePictures.append( key );
 
3503
        }
 
3504
    }
 
3505
    return savePictures;
 
3506
}
 
3507
 
 
3508
// KWord-1.3 format
2566
3509
bool KWDocument::completeSaving( KoStore *_store )
2567
3510
{
2568
3511
    if ( !_store )
2570
3513
 
2571
3514
    QString u = KURL( url() ).path();
2572
3515
 
2573
 
    QValueList<KoPictureKey> savePictures;
2574
 
 
2575
 
    // At first, we must process the data of the KWTextImage classes.
2576
 
    // Process the data of the KWTextImage classes.
2577
 
    QPtrListIterator<KWTextImage> textIt ( m_textImageRequests );
2578
 
    for ( ; textIt.current() ; ++textIt )
2579
 
    {
2580
 
        KoPictureKey key = textIt.current()->getKey();
2581
 
        kdDebug(32001) << "KWDocument::saveXML registering text image " << key.toString() << endl;
2582
 
        if ( !savePictures.contains( key ) )
2583
 
            savePictures.append( key );
2584
 
    }
2585
 
    m_textImageRequests.clear(); // Save some memory!
2586
 
 
2587
 
    // Now do the images/cliparts in frames.
2588
 
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
2589
 
    for ( ; fit.current() ; ++fit )
2590
 
    {
2591
 
        KWFrameSet *frameSet = fit.current();
2592
 
        // If picture frameset, make a note of the image it needs.
2593
 
        if ( !frameSet->isDeleted() && ( frameSet->type() == FT_PICTURE ) )
2594
 
        {
2595
 
            KoPictureKey key = static_cast<KWPictureFrameSet *>( frameSet )->key();
2596
 
            if ( !savePictures.contains( key ) )
2597
 
                savePictures.append( key );
2598
 
        }
2599
 
    }
 
3516
    QValueList<KoPictureKey> savePictures( savePictureList() );
 
3517
 
2600
3518
    if (specialOutputFlag()==SaveAsKOffice1dot1)
2601
3519
    {
2602
 
        return m_pictureCollection.saveToStoreAsKOffice1Dot1( KoPictureCollection::CollectionImage, _store, savePictures );
 
3520
        return m_pictureCollection->saveToStoreAsKOffice1Dot1( KoPictureCollection::CollectionImage, _store, savePictures );
2603
3521
    }
2604
3522
    else
2605
3523
    {
2606
 
        return m_pictureCollection.saveToStore( KoPictureCollection::CollectionPicture, _store, savePictures );
 
3524
        return m_pictureCollection->saveToStore( KoPictureCollection::CollectionPicture, _store, savePictures );
2607
3525
    }
2608
3526
}
2609
3527
 
 
3528
int KWDocument::supportedSpecialFormats() const
 
3529
{
 
3530
    return SaveAsKOffice1dot1 | KoDocument::supportedSpecialFormats();
 
3531
}
 
3532
 
2610
3533
void KWDocument::addView( KoView *_view )
2611
3534
{
2612
3535
    m_lstViews.append( (KWView*)_view );
2613
3536
    KoDocument::addView( _view );
2614
 
    QPtrListIterator<KWView> it( m_lstViews );
2615
 
    for ( ; it.current() ; ++it )
2616
 
        it.current()->deselectAllFrames();
 
3537
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
 
3538
        (*it)->deselectAllFrames();
 
3539
    }
2617
3540
}
2618
3541
 
2619
3542
void KWDocument::removeView( KoView *_view )
2620
3543
{
2621
 
    m_lstViews.setAutoDelete( FALSE );
2622
 
    m_lstViews.removeRef( static_cast<KWView*>(_view) );
2623
 
    m_lstViews.setAutoDelete( TRUE );
 
3544
    m_lstViews.remove( static_cast<KWView*>(_view) );
2624
3545
    KoDocument::removeView( _view );
2625
3546
}
2626
3547
 
2627
3548
void KWDocument::addShell( KoMainWindow *shell )
2628
3549
{
2629
3550
    connect( shell, SIGNAL( documentSaved() ), m_commandHistory, SLOT( documentSaved() ) );
 
3551
    connect( shell, SIGNAL( saveDialogShown() ), this, SLOT( saveDialogShown() ) );
2630
3552
    KoDocument::addShell( shell );
2631
3553
}
2632
3554
 
2635
3557
    return new KWView( m_viewMode, parent, name, this );
2636
3558
}
2637
3559
 
 
3560
// Paint this document when it's embedded
 
3561
// This is also used to paint the preview.png that goes into the ZIP file
2638
3562
void KWDocument::paintContent( QPainter& painter, const QRect& _rect, bool transparent, double zoomX, double zoomY )
2639
3563
{
2640
3564
    //kdDebug(32001) << "KWDocument::paintContent m_zoom=" << m_zoom << " zoomX=" << zoomX << " zoomY=" << zoomY << " transparent=" << transparent << endl;
2641
 
    m_zoom = 100;
 
3565
 
 
3566
    setZoom( 100 );
2642
3567
    if ( m_zoomedResolutionX != zoomX || m_zoomedResolutionY != zoomY )
2643
3568
    {
2644
3569
        setResolution( zoomX, zoomY );
2678
3603
QPixmap KWDocument::generatePreview( const QSize& size )
2679
3604
{
2680
3605
    int oldZoom = m_zoom;
2681
 
    double oldZoomX = m_zoomedResolutionX;
2682
 
    double oldZoomY = m_zoomedResolutionY;
 
3606
    double oldResolutionX = resolutionX();
 
3607
    double oldResolutionY = resolutionY();
 
3608
    double oldZoomX = zoomedResolutionX();
 
3609
    double oldZoomY = zoomedResolutionY();
2683
3610
 
 
3611
    // Sometimes (due to the different resolution?) the layout creates a new page
 
3612
    // while saving the preview. If this happens, we don't want to repaint the real views
 
3613
    // (due to KWCanvas::slotNewContentsSize)
 
3614
    // ##### One day when we have real doc/view separation in kotextparag, we shouldn't mess with
 
3615
    // the real view's resolution, we should instead create a fake view for the preview itself.
 
3616
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
 
3617
        (*it)->getGUI()->canvasWidget()->setUpdatesEnabled( false );
 
3618
    }
 
3619
    Q_ASSERT( !m_bGeneratingPreview );
 
3620
    m_bGeneratingPreview = true;
2684
3621
    QPixmap pix = KoDocument::generatePreview(size);
2685
3622
 
2686
 
    m_zoom = oldZoom;
2687
 
    setResolution( oldZoomX, oldZoomY );
2688
 
    newZoomAndResolution( false, false );
 
3623
    // Restore everything as it was before
 
3624
    setResolution( oldResolutionX, oldResolutionY );
 
3625
    setZoom( oldZoom );
2689
3626
 
 
3627
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
 
3628
        (*it)->getGUI()->canvasWidget()->setUpdatesEnabled( true );
 
3629
    }
 
3630
    newZoomAndResolution( true /*set contents size again*/, false );
 
3631
    m_bGeneratingPreview = false;
2690
3632
    if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() ) {
2691
3633
        formulaDocument->setZoomAndResolution( oldZoom, oldZoomX, oldZoomY );
2692
3634
    }
2716
3658
    painter->restore();
2717
3659
}
2718
3660
 
 
3661
KWChild* KWDocument::createChildDoc( const KoRect& rect, KoDocument* childDoc )
 
3662
{
 
3663
    KWChild* ch = new KWChild( this, rect.toQRect(), childDoc );
 
3664
    insertChild( ch );
 
3665
    return ch;
 
3666
}
 
3667
 
2719
3668
void KWDocument::insertObject( const KoRect& rect, KoDocumentEntry& _e )
2720
3669
{
2721
3670
    KoDocument* doc = _e.createDoc( this );
2722
3671
    if ( !doc )
2723
3672
        return;
2724
 
    doc->setInitDocFlags( KoDocument::InitDocEmbedded );
2725
 
    if ( !doc->initDoc() )
 
3673
    if ( !doc->initDoc(KoDocument::InitDocEmbedded) )
2726
3674
        return;
2727
3675
 
2728
 
    KWChild* ch = new KWChild( this, rect.toQRect(), doc );
2729
 
 
2730
 
    insertChild( ch );
 
3676
    KWChild* ch = createChildDoc( rect, doc );
2731
3677
    setModified( TRUE );
2732
3678
 
2733
3679
    KWPartFrameSet *frameset = new KWPartFrameSet( this, ch, QString::null );
2778
3724
void KWDocument::repaintAllViewsExcept( KWView *_view, bool erase )
2779
3725
{
2780
3726
    //kdDebug(32001) << "KWDocument::repaintAllViewsExcept" << endl;
2781
 
    for ( KWView * viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() ) {
 
3727
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
 
3728
        KWView* viewPtr = *it;
2782
3729
        if ( viewPtr != _view /*&& viewPtr->getGUI() && viewPtr->getGUI()->canvasWidget()*/ ) {
2783
3730
            viewPtr->getGUI()->canvasWidget()->repaintAll( erase );
2784
3731
        }
2788
3735
void KWDocument::setUnit( KoUnit::Unit _unit )
2789
3736
{
2790
3737
    m_unit = _unit;
2791
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() ) {
 
3738
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
 
3739
        KWView* viewPtr = *it;
2792
3740
        if ( viewPtr->getGUI() ) {
2793
 
            viewPtr->getGUI()->getHorzRuler()->setUnit( KoUnit::unitName( m_unit ) );
2794
 
            viewPtr->getGUI()->getVertRuler()->setUnit( KoUnit::unitName( m_unit ) );
 
3741
            viewPtr->getGUI()->getHorzRuler()->setUnit( m_unit );
 
3742
            viewPtr->getGUI()->getVertRuler()->setUnit( m_unit );
2795
3743
        }
2796
3744
    }
2797
3745
}
2798
3746
 
2799
3747
void KWDocument::updateAllStyleLists()
2800
3748
{
2801
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
2802
 
        viewPtr->updateStyleList();
 
3749
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
3750
        (*it)->updateStyleList();
2803
3751
}
2804
3752
 
2805
3753
void KWDocument::updateStyleListOrder( const QStringList &list )
2807
3755
    styleCollection()->updateStyleListOrder( list );
2808
3756
}
2809
3757
 
2810
 
void KWDocument::applyStyleChange( StyleChangeDefMap changed )
 
3758
void KWDocument::applyStyleChange( KoStyleChangeDefMap changed )
2811
3759
{
2812
3760
    QPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
2813
3761
 
2819
3767
 
2820
3768
void KWDocument::updateAllFrameStyleLists()
2821
3769
{
2822
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
2823
 
        viewPtr->updateFrameStyleList();
 
3770
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
3771
        (*it)->updateFrameStyleList();
2824
3772
}
2825
3773
 
2826
3774
void KWDocument::updateAllTableStyleLists()
2827
3775
{
2828
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
2829
 
        viewPtr->updateTableStyleList();
 
3776
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
3777
        (*it)->updateTableStyleList();
2830
3778
}
2831
3779
 
2832
3780
void KWDocument::repaintAllViews( bool erase )
2833
3781
{
2834
3782
    //kdDebug(32001) << "KWDocument::repaintAllViews" << endl;
2835
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
2836
 
        viewPtr->getGUI()->canvasWidget()->repaintAll( erase );
 
3783
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
3784
        (*it)->getGUI()->canvasWidget()->repaintAll( erase );
2837
3785
}
2838
3786
 
2839
3787
QPtrList<KWFrame> KWDocument::framesToCopyOnNewPage( int afterPageNum ) const // can be -1 for 'before page 0'
2944
3892
#ifdef DEBUG_PAGES
2945
3893
    kdDebug(32002) << "KWDocument::afterAppendPage " << pageNum << endl;
2946
3894
#endif
2947
 
    emit newContentsSize();
 
3895
    if ( !m_bGeneratingPreview )
 
3896
        emit newContentsSize();
2948
3897
 
2949
3898
    if ( isHeaderVisible() || isFooterVisible() || m_bHasEndNotes )
2950
3899
    {
3041
3990
        fit.current()->updateFrames();
3042
3991
 
3043
3992
    recalcVariables( VT_PGNUM );
3044
 
    emit newContentsSize();
 
3993
    if ( !m_bGeneratingPreview )
 
3994
        emit newContentsSize();
3045
3995
}
3046
3996
 
3047
 
void KWDocument::tryRemovingPages()
 
3997
bool KWDocument::tryRemovingPages()
3048
3998
{
3049
3999
    int lastPage = numPages() - 1;
3050
4000
    bool removed = false;
3060
4010
        removed = true;
3061
4011
        lastPage = m_pages - 1;
3062
4012
    }
3063
 
    // Do all the recalc in one go. Speeds up deleting many pages.
3064
 
    if ( removed )
3065
 
        afterRemovePages();
 
4013
    // Don't call afterRemovePages or recalcFrames from here, since this method is
 
4014
    // itself called from KWFrameLayout (#95047)
 
4015
    return removed;
3066
4016
}
3067
4017
 
3068
4018
 
3157
4107
    int page = QMIN(m_pages-1, static_cast<int>(docPoint.y() / ptPaperHeight()));
3158
4108
    QPtrList<KWFrame> frames = framesInPage(page);
3159
4109
 
 
4110
#ifdef DEBUG_FRAMESELECT
 
4111
    for (KWFrame *f = frames.last();f;f=frames.prev()) { // z-order
 
4112
        kdDebug(32001) << "KWDocument::topFrameUnderMouse frame " << f << " (from " << f->frameSet()->getName() << ") zOrder=" << f->zOrder() << endl;
 
4113
    }
 
4114
#endif
3160
4115
 
3161
4116
    for (KWFrame *f = frames.last();f;f=frames.prev()) { // z-order
3162
4117
        // only consider non-inline frames.
3234
4189
        else // text view mode
3235
4190
            return MEANING_MOUSE_INSIDE_TEXT;
3236
4191
    }
 
4192
    // Allow to select paragraphs by clicking on the left
 
4193
    // TODO - introduce real mouse-meaning value, to change the cursor.
 
4194
    // TODO: test if other word-processors allow doing it with text-boxes
 
4195
    // when clicking on the left of the text box means clicking inside another frame.
 
4196
    // Also note that one can currently select text in the very first parag by clicking
 
4197
    // above the frame; this would need a normal "inside text" cursor, not a left one.
 
4198
    if ( m_viewMode->hasFrames() )
 
4199
    {
 
4200
        return MEANING_MOUSE_INSIDE_TEXT;
 
4201
    }
3237
4202
    return MEANING_NONE;
3238
4203
}
3239
4204
 
3249
4214
        return QCursor(); // default cursor !?!?
3250
4215
    case MEANING_MOUSE_INSIDE_TEXT:
3251
4216
        return Qt::ibeamCursor;
 
4217
    case MEANING_MOUSE_OVER_LINK:
 
4218
        return Qt::PointingHandCursor;
 
4219
    case MEANING_MOUSE_OVER_FOOTNOTE:
 
4220
        return Qt::PointingHandCursor;
3252
4221
    case MEANING_MOUSE_MOVE:
3253
4222
        return Qt::sizeAllCursor;
3254
4223
    case MEANING_MOUSE_SELECT:
3308
4277
/** if we are close on the left or the top of a table,
3309
4278
 * the user can select rows/cols */
3310
4279
KWDocument::TableToSelectPosition KWDocument::positionToSelectRowcolTable(const QPoint& nPoint, KWTableFrameSet **ppTable /*=0L*/) {
 
4280
 
 
4281
    static const int DISTANCE_TABLE_SELECT_ROWCOL = 5;
 
4282
 
3311
4283
    KWFrame *frameundermouse, *frameclosetomouseright, *frameclosetomouseunder;
3312
4284
 
3313
4285
    TableToSelectPosition result = TABLE_POSITION_NONE;
3319
4291
    // now get a frame close to the mouse pointer
3320
4292
    // slightly on the right (could it be that it is a table?)
3321
4293
    QPoint pointTestTableSelect = nPoint;
3322
 
    pointTestTableSelect.rx() += KWDocument::DISTANCE_TABLE_SELECT_ROWCOL;
 
4294
    pointTestTableSelect.rx() += DISTANCE_TABLE_SELECT_ROWCOL;
3323
4295
    frameclosetomouseright = frameUnderMouse(pointTestTableSelect, &border);
3324
4296
 
3325
4297
    pointTestTableSelect = nPoint;
3326
 
    pointTestTableSelect.ry() += KWDocument::DISTANCE_TABLE_SELECT_ROWCOL;
 
4298
    pointTestTableSelect.ry() += DISTANCE_TABLE_SELECT_ROWCOL;
3327
4299
    frameclosetomouseunder = frameUnderMouse(pointTestTableSelect, &border);
3328
4300
 
3329
4301
    KWFrame *frameclosetomouse; // the frame that we are going to test to know whether it is a table
3354
4326
 
3355
4327
 
3356
4328
// TODO pass viewmode for isVisible
 
4329
// TODO use QValueList
3357
4330
QPtrList<KWFrame> KWDocument::getSelectedFrames() const {
3358
4331
    QPtrList<KWFrame> frames;
3359
4332
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
3375
4348
void KWDocument::fixZOrders() {
3376
4349
    bool fixed_something = false;
3377
4350
    for (int pgnum = 0 ; pgnum < m_pages ; pgnum++) {
3378
 
        QPtrList<KWFrame> frames= framesInPage(pgnum,false);
3379
 
        // scan this page to see if we need to fixup.
3380
 
        bool need_fixup=true;
3381
 
        for (KWFrame *f = frames.last();f;f=frames.prev()) {
3382
 
            if (f->zOrder() != 0) { // assumption: old documents come with no zorder=>initialised to 0
3383
 
                need_fixup=false;
 
4351
        QPtrList<KWFrame> frames = framesInPage(pgnum,true /*sorted by zorder*/);
 
4352
        // scan this page to see if we need to fixup:
 
4353
        // fix up if two frames have the same zOrder.
 
4354
        bool need_fixup = false;
 
4355
        KWFrame *f = frames.last();
 
4356
        if ( !f )
 
4357
            continue;
 
4358
        int lastZOrder = f->zOrder();
 
4359
        f = frames.prev();
 
4360
        for ( ; f ; f=frames.prev() ) {
 
4361
            if ( !f->frameSet()->isFloating() &&
 
4362
                 f->zOrder() == lastZOrder ) {
 
4363
                need_fixup = true;
3384
4364
                break;
3385
4365
            }
 
4366
            lastZOrder = f->zOrder();
3386
4367
        }
3387
 
        if (need_fixup) {
 
4368
        if ( need_fixup ) {
3388
4369
            int current_zorder=0;
3389
4370
            kdDebug() << "fixing page " << pgnum << " z-orders " << endl;
3390
4371
            for (KWFrame *fr = frames.first();fr;fr=frames.next()) {
3467
4448
    return 0L;
3468
4449
}
3469
4450
 
3470
 
void KWDocument::updateAllFrames()
 
4451
void KWDocument::updateAllFrames( int flags )
3471
4452
{
3472
4453
#ifdef DEBUG_SPEED
3473
4454
    QTime dt;
3475
4456
#endif
3476
4457
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
3477
4458
    for ( ; fit.current() ; ++fit )
3478
 
        fit.current()->updateFrames();
 
4459
        fit.current()->updateFrames( flags );
3479
4460
 
3480
4461
#ifdef DEBUG_SPEED
3481
 
    kdDebug(32001) << "updateAllFrames took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
 
4462
    kdDebug(32001) << "updateAllFrames(" << flags << ") took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
3482
4463
#endif
3483
4464
 
3484
4465
    // TODO: check all calls to updateAllFrames, and fix them.
3706
4687
 
3707
4688
void KWDocument::updateHeaderButton()
3708
4689
{
3709
 
    QPtrListIterator<KWView> it( m_lstViews );
3710
 
    for ( ; it.current() ; ++it )
 
4690
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
3711
4691
    {
3712
 
        it.current()->updateHeaderFooterButton();
3713
 
        it.current()->updateHeader();
 
4692
        (*it)->updateHeaderFooterButton();
 
4693
        (*it)->updateHeader();
3714
4694
    }
3715
4695
}
3716
4696
 
3717
4697
void KWDocument::updateFooterButton()
3718
4698
{
3719
 
    QPtrListIterator<KWView> it( m_lstViews );
3720
 
    for ( ; it.current() ; ++it )
 
4699
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
3721
4700
    {
3722
 
        it.current()->updateHeaderFooterButton();
3723
 
        it.current()->updateFooter();
 
4701
        (*it)->updateHeaderFooterButton();
 
4702
        (*it)->updateFooter();
3724
4703
    }
3725
4704
}
3726
4705
 
3727
4706
 
3728
 
bool KWDocument::isOnlyOneFrameSelected() {
3729
 
    return getSelectedFrames().count()==1;
 
4707
bool KWDocument::isOnlyOneFrameSelected() const {
 
4708
    return getSelectedFrames().count() == 1;
3730
4709
}
3731
4710
 
3732
 
void KWDocument::setFrameMargins( double l, double r, double t, double b )
 
4711
void KWDocument::setFramePadding( double l, double r, double t, double b )
3733
4712
{
3734
4713
    // todo, make this more OO, and update the tableheaders as well..
3735
 
    for ( unsigned int i = 0; i < getNumFrameSets(); i++ ) {
 
4714
    for ( unsigned int i = 0; i < numFrameSets(); i++ ) {
3736
4715
        if ( frameSet( i )->hasSelectedFrame() ) {
3737
4716
            KWFrameSet *frameset = frameSet( i );
3738
4717
            for ( unsigned int j = 0; j < frameset->getNumFrames(); j++ ) {
3739
4718
                if ( frameset->frame( j )->isSelected() ) {
3740
 
                    frameset->frame( j )->setBLeft( l );
3741
 
                    frameset->frame( j )->setBRight( r );
3742
 
                    frameset->frame( j )->setBTop( t );
3743
 
                    frameset->frame( j )->setBBottom( b );
 
4719
                    frameset->frame( j )->setPaddingLeft( l );
 
4720
                    frameset->frame( j )->setPaddingRight( r );
 
4721
                    frameset->frame( j )->setPaddingTop( t );
 
4722
                    frameset->frame( j )->setPaddingBottom( b );
3744
4723
                }
3745
4724
            }
3746
4725
        }
3781
4760
void KWDocument::recalcVariables( int type )
3782
4761
{
3783
4762
    m_varColl->recalcVariables(type);
3784
 
    slotRepaintVariable();
 
4763
    if ( !m_bGeneratingPreview )
 
4764
        slotRepaintVariable();
 
4765
 
3785
4766
#if 0
3786
4767
    bool update = false;
3787
4768
    QPtrListIterator<KWVariable> it( variables );
3814
4795
{
3815
4796
    QPtrListIterator<KWFrameSet> it = framesetsIterator();
3816
4797
    for (; it.current(); ++it )
3817
 
        if( it.current()->type()==FT_TEXT)
 
4798
        if( it.current()->type()==FT_TEXT && it.current()->isVisible() )
3818
4799
            slotRepaintChanged( (*it) );
3819
4800
#if 0
3820
4801
    KWTextFrameSet * textfs = static_cast<KWTextDocument *>(it.current()->textDocument())->textFrameSet();
3828
4809
#endif
3829
4810
}
3830
4811
 
3831
 
int KWDocument::getMailMergeRecord() const
 
4812
int KWDocument::mailMergeRecord() const
3832
4813
{
3833
4814
    return slRecordNum;
3834
4815
}
3861
4842
{
3862
4843
    emit sig_terminateEditing( f );
3863
4844
    m_lstFrameSet.take( m_lstFrameSet.find(f) );
3864
 
    if ( m_bgSpellCheck->currentCheckSpellingFrame() == f )
3865
 
        // TODO nextTextFrameSet instead of:
3866
 
        m_bgSpellCheck->objectForSpell( 0L);
3867
4845
    setModified( true );
3868
4846
}
3869
4847
 
3900
4878
    setModified( true );
3901
4879
}
3902
4880
 
3903
 
 
3904
 
void KWDocument::setKOSpellConfig(const KOSpellConfig& _kspell)
3905
 
{
3906
 
  if(m_pKOSpellConfig==0)
3907
 
    m_pKOSpellConfig=new KOSpellConfig();
3908
 
 
3909
 
  m_pKOSpellConfig->setNoRootAffix(_kspell.noRootAffix ());
3910
 
  m_pKOSpellConfig->setRunTogether(_kspell.runTogether ());
3911
 
  m_pKOSpellConfig->setDictionary(_kspell.dictionary ());
3912
 
  m_pKOSpellConfig->setDictFromList(_kspell.dictFromList());
3913
 
  m_pKOSpellConfig->setEncoding(_kspell.encoding());
3914
 
  m_pKOSpellConfig->setEncoding(_kspell.encoding());
3915
 
  m_pKOSpellConfig->setIgnoreCase ( _kspell.ignoreCase ());
3916
 
  m_pKOSpellConfig->setIgnoreAccent( _kspell.ignoreAccent());
3917
 
  m_pKOSpellConfig->setDontCheckTitleCase( _kspell.dontCheckTitleCase());
3918
 
  m_pKOSpellConfig->setDontCheckUpperWord( _kspell.dontCheckUpperWord() );
3919
 
  m_pKOSpellConfig->setSpellWordWithNumber( _kspell.spellWordWithNumber());
3920
 
  m_pKOSpellConfig->setClient (_kspell.client());
3921
 
  m_bgSpellCheck->setKSpellConfig(_kspell);
3922
 
}
3923
 
 
3924
4881
#ifndef NDEBUG
3925
4882
void KWDocument::printStyleDebug()
3926
4883
{
3927
4884
    kdDebug() << "----------------------------------------"<<endl;
3928
 
    QPtrList<KWStyle> m_styleList(m_styleColl->styleList());
3929
 
    for ( KWStyle * p = m_styleList.first(); p != 0L; p = m_styleList.next() )
 
4885
    QPtrList<KoParagStyle> styleList(m_styleColl->styleList());
 
4886
    for ( KoParagStyle * p = styleList.first(); p != 0L; p = styleList.next() )
3930
4887
    {
3931
4888
        kdDebug() << "Style " << p << "  " << p->name() <<endl;
3932
4889
        kdDebug() << "   format: " << p->format().key() <<endl;
3933
4890
        static const char * const s_align[] = { "Auto", "Left", "Right", "ERROR", "HCenter", "ERR", "ERR", "ERR", "Justify", };
3934
 
        kdDebug() << "  align: " << s_align[p->paragLayout().alignment] << endl;
 
4891
        kdDebug() << "  align: " << s_align[(Qt::AlignmentFlags)p->paragLayout().alignment] << endl;
3935
4892
 
3936
4893
        kdDebug() << "   following style: " << p->followingStyle() << " "
3937
4894
                  << ( p->followingStyle() ? p->followingStyle()->name() : QString::null ) << endl;
3947
4904
    kdDebug() << "size: x:" << ptLeftBorder()<< ", y:"<<ptTopBorder() << ", w:"<< ptPaperWidth() << ", h:"<<ptPaperHeight()<<endl;
3948
4905
    kdDebug() << "Header visible: " << isHeaderVisible() << endl;
3949
4906
    kdDebug() << "Footer visible: " << isFooterVisible() << endl;
3950
 
    kdDebug() << "Units: " << getUnit() <<endl;
3951
 
    kdDebug() << "# Framesets: " << getNumFrameSets() <<endl;
 
4907
    kdDebug() << "Units: " << unit() <<endl;
 
4908
    kdDebug() << "# Framesets: " << numFrameSets() <<endl;
3952
4909
    QPtrListIterator<KWFrameSet> fit = framesetsIterator();
3953
4910
    for ( unsigned int iFrameset = 0; fit.current() ; ++fit, iFrameset++ )
3954
4911
    {
3988
4945
            it.current()->invalidate();
3989
4946
}
3990
4947
 
3991
 
KFormula::Document* KWDocument::getFormulaDocument()
 
4948
KFormula::Document* KWDocument::formulaDocument()
3992
4949
{
3993
4950
    KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document();
3994
4951
    if (!formulaDocument) {
4011
4968
{
4012
4969
    // This has to be a loop instead of a signal, so that we can
4013
4970
    // send "true" for the last view (see KWFrameSet::drawContents)
4014
 
    QPtrListIterator<KWView> it( m_lstViews );
4015
 
    for ( ; it.current() ; ++it )
4016
 
        it.current()->getGUI()->canvasWidget()->repaintChanged( frameset, it.atLast() );
 
4971
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
 
4972
        (*it)->getGUI()->canvasWidget()->repaintChanged( frameset, it == m_lstViews.fromLast() );
 
4973
    }
4017
4974
}
4018
4975
 
4019
4976
void KWDocument::refreshFrameBorderButton()
4022
4979
    KWFrame *frame= getFirstSelectedFrame();
4023
4980
    if (frame)
4024
4981
    {
4025
 
        QPtrListIterator<KWView> it( m_lstViews );
4026
4982
        frame = KWFrameSet::settingsFrame(frame);
4027
 
        for ( ; it.current() ; ++it )
4028
 
        {
4029
 
            it.current()->showFrameBorders( frame->leftBorder(), frame->rightBorder(), frame->topBorder(), frame->bottomBorder() );
 
4983
        for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
 
4984
            (*it)->showFrameBorders( frame->leftBorder(), frame->rightBorder(), frame->topBorder(), frame->bottomBorder() );
4030
4985
        }
4031
4986
    }
4032
4987
}
4212
5167
 
4213
5168
void KWDocument::reorganizeGUI()
4214
5169
{
4215
 
   QPtrListIterator<KWView> it( m_lstViews );
4216
 
   for ( ; it.current() ; ++it )
4217
 
       it.current()->getGUI()->reorganize();
 
5170
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5171
        (*it)->getGUI()->reorganize();
4218
5172
}
4219
5173
 
4220
5174
void KWDocument::slotDocumentInfoModifed()
4221
5175
{
4222
 
    if (!getVariableCollection()->variableSetting()->displayFieldCode())
 
5176
    if (!variableCollection()->variableSetting()->displayFieldCode())
4223
5177
        recalcVariables( VT_FIELD );
4224
5178
}
4225
5179
 
4259
5213
    emit docStructureChanged(typeItemDocStructure(_type));
4260
5214
}
4261
5215
 
 
5216
QBrush KWDocument::resolveBgBrush( const QBrush & brush, QPainter * painter )
 
5217
{
 
5218
    if ( brush.color().isValid() )
 
5219
        return brush;
 
5220
    QBrush ret( brush );
 
5221
    ret.setColor( defaultBgColor( painter ) );
 
5222
    return ret;
 
5223
}
 
5224
 
4262
5225
QColor KWDocument::resolveBgColor( const QColor & col, QPainter * painter )
4263
5226
{
4264
5227
    if (col.isValid())
4269
5232
 
4270
5233
QColor KWDocument::defaultBgColor( QPainter * painter )
4271
5234
{
4272
 
    if ( painter->device()->devType() == QInternal::Printer )
 
5235
    if ( painter && painter->device()->devType() == QInternal::Printer )
4273
5236
        return Qt::white;
4274
5237
    return QApplication::palette().color( QPalette::Active, QColorGroup::Base );
4275
5238
}
4278
5241
void KWDocument::renameButtonTOC(bool b)
4279
5242
{
4280
5243
    m_hasTOC=b;
4281
 
    QPtrListIterator<KWView> it( m_lstViews );
4282
 
    for ( ; it.current() ; ++it )
4283
 
    {
4284
 
        it.current()->renameButtonTOC(b);
4285
 
    }
 
5244
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5245
        (*it)->renameButtonTOC(b);
4286
5246
}
4287
5247
 
4288
5248
void KWDocument::refreshMenuExpression()
4289
5249
{
4290
 
    QPtrListIterator<KWView> it( m_lstViews );
4291
 
    for ( ; it.current() ; ++it )
4292
 
        it.current()->refreshMenuExpression();
 
5250
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5251
        (*it)->refreshMenuExpression();
4293
5252
}
4294
5253
 
4295
5254
void KWDocument::frameSelectedChanged()
4299
5258
 
4300
5259
void KWDocument::updateZoomRuler()
4301
5260
{
4302
 
    QPtrListIterator<KWView> it( m_lstViews );
4303
 
    for ( ; it.current() ; ++it )
4304
 
    {
4305
 
        it.current()->getGUI()->getHorzRuler()->setZoom( zoomedResolutionX() );
4306
 
        it.current()->getGUI()->getVertRuler()->setZoom( zoomedResolutionY() );
4307
 
        it.current()->slotUpdateRuler();
 
5261
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
 
5262
        (*it)->getGUI()->getHorzRuler()->setZoom( zoomedResolutionX() );
 
5263
        (*it)->getGUI()->getVertRuler()->setZoom( zoomedResolutionY() );
 
5264
        (*it)->slotUpdateRuler();
4308
5265
    }
4309
5266
}
4310
5267
 
4311
5268
void KWDocument::updateRulerFrameStartEnd()
4312
5269
{
4313
 
    QPtrListIterator<KWView> it( m_lstViews );
4314
 
    for ( ; it.current() ; ++it )
4315
 
        it.current()->slotUpdateRuler();
 
5270
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5271
        (*it)->slotUpdateRuler();
4316
5272
}
4317
5273
 
4318
5274
void KWDocument::updateFrameStatusBarItem()
4319
5275
{
4320
 
    QPtrListIterator<KWView> it( m_lstViews );
4321
 
    for ( ; it.current() ; ++it )
4322
 
        it.current()->updateFrameStatusBarItem();
 
5276
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5277
        (*it)->updateFrameStatusBarItem();
4323
5278
}
4324
5279
 
4325
5280
int KWDocument::undoRedoLimit() const
4335
5290
 
4336
5291
void KWDocument::setGridX(double _gridx) {
4337
5292
    m_gridX = _gridx;
4338
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4339
 
        viewPtr->getGUI()->getHorzRuler()->setGridSize(_gridx);
 
5293
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5294
        (*it)->getGUI()->getHorzRuler()->setGridSize(_gridx);
4340
5295
}
4341
5296
 
4342
5297
QValueList<KoTextObject *> KWDocument::visibleTextObjects(KWViewMode *viewmode) const
4357
5312
 
4358
5313
void KWDocument::refreshGUIButton()
4359
5314
{
4360
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4361
 
        viewPtr->initGUIButton();
 
5315
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5316
        (*it)->initGUIButton();
4362
5317
}
4363
5318
 
4364
5319
void KWDocument::enableBackgroundSpellCheck( bool b )
4365
5320
{
4366
 
    m_bgSpellCheck->enableBackgroundSpellCheck(b);
4367
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4368
 
        viewPtr->updateBgSpellCheckingState();
 
5321
#ifdef HAVE_LIBKSPELL2
 
5322
    m_bgSpellCheck->setEnabled(b);
 
5323
#endif
 
5324
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5325
        (*it)->updateBgSpellCheckingState();
4369
5326
}
4370
5327
 
4371
5328
bool KWDocument::backgroundSpellCheckEnabled() const
4372
5329
{
4373
 
    return m_bgSpellCheck->backgroundSpellCheckEnabled();
 
5330
#ifdef HAVE_LIBKSPELL2
 
5331
    return m_bgSpellCheck->enabled();
 
5332
#else
 
5333
    return false;
 
5334
#endif
4374
5335
}
4375
5336
 
4376
5337
void KWDocument::reactivateBgSpellChecking()
4385
5346
    startBackgroundSpellCheck();
4386
5347
}
4387
5348
 
4388
 
// to be removed
4389
 
KWTextFrameSet* KWDocument::nextTextFrameSet(KWTextFrameSet *obj)
4390
 
{
4391
 
    int pos = -1;
4392
 
    if ( bgFrameSpellChecked )
4393
 
        pos=m_lstFrameSet.findNextRef(bgFrameSpellChecked);
4394
 
    if(pos !=-1)
4395
 
    {
4396
 
        KWFrameSet *frm=0L;
4397
 
        for ( frm=m_lstFrameSet.at(pos); frm != 0; frm=m_lstFrameSet.next() ){
4398
 
            KWTextFrameSet *newFrm = frm->nextTextObject( obj );
4399
 
            if(newFrm && !newFrm->isDeleted()  && newFrm->textObject()->needSpellCheck())
4400
 
            {
4401
 
                //kdDebug() << "KWDocument::nextTextFrameSet checking " << bgFrameSpellChecked << endl;
4402
 
                bgFrameSpellChecked = frm;
4403
 
                return newFrm;
4404
 
            }
4405
 
        }
4406
 
    }
4407
 
    else
4408
 
    {
4409
 
        KWFrameSet *frm=0L;
4410
 
        for ( frm=m_lstFrameSet.first(); frm != 0; frm=m_lstFrameSet.next() ){
4411
 
            KWTextFrameSet *newFrm = frm->nextTextObject( obj );
4412
 
            if(newFrm && !newFrm->isDeleted() && newFrm->textObject()->needSpellCheck())
4413
 
            {
4414
 
                //kdDebug() << "KWDocument::nextTextFrameSet checking " << bgFrameSpellChecked << endl;
4415
 
                bgFrameSpellChecked = frm;
4416
 
                return newFrm;
4417
 
            }
4418
 
        }
4419
 
    }
4420
 
    //kdDebug() << "KWDocument::nextTextFrameSet returning 0L" << endl;
4421
 
    bgFrameSpellChecked = 0L;
4422
 
    return 0L;
4423
 
}
4424
 
 
4425
5349
void KWDocument::slotChapterParagraphFormatted( KoTextParag* /*parag*/ )
4426
5350
{
4427
5351
    // Attempt at invalidating from the parag's page only
4537
5461
    return QString::null;
4538
5462
}
4539
5463
 
4540
 
void KWDocument::addIgnoreWordAll( const QString & word)
 
5464
 
 
5465
void KWDocument::setSpellCheckIgnoreList( const QStringList& lst )
4541
5466
{
4542
 
    if( m_spellListIgnoreAll.findIndex( word )==-1)
4543
 
        m_spellListIgnoreAll.append( word );
4544
 
    m_bgSpellCheck->addIgnoreWordAll( word );
4545
 
 
 
5467
    m_spellCheckIgnoreList = lst;
 
5468
#ifdef HAVE_LIBKSPELL2
 
5469
    m_bgSpellCheck->settings()->setCurrentIgnoreList( m_spellCheckIgnoreList + m_spellCheckPersonalDict );
 
5470
#endif
 
5471
    setModified( true );
4546
5472
}
4547
5473
 
4548
 
void KWDocument::clearIgnoreWordAll( )
 
5474
void KWDocument::addSpellCheckIgnoreWord( const QString & word )
4549
5475
{
4550
 
    m_spellListIgnoreAll.clear();
4551
 
    m_bgSpellCheck->clearIgnoreWordAll();
4552
 
 
 
5476
    // ### missing: undo/redo support
 
5477
    if( m_spellCheckIgnoreList.findIndex( word ) == -1 )
 
5478
        m_spellCheckIgnoreList.append( word );
 
5479
    setSpellCheckIgnoreList( m_spellCheckIgnoreList );
 
5480
    if ( backgroundSpellCheckEnabled() )
 
5481
        // Re-check everything to make this word normal again
 
5482
        reactivateBgSpellChecking();
4553
5483
}
4554
5484
 
4555
5485
int KWDocument::maxZOrder( int pageNum) const
4591
5521
 
4592
5522
void KWDocument::updateTextFrameSetEdit()
4593
5523
{
4594
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4595
 
        viewPtr->slotFrameSetEditChanged();
 
5524
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5525
        (*it)->slotFrameSetEditChanged();
4596
5526
 
4597
5527
}
4598
5528
 
4652
5582
    repaintAllViews();
4653
5583
}
4654
5584
 
 
5585
void KWDocument::setGlobalHyphenation( bool _hyphen )
 
5586
{
 
5587
    m_bGlobalHyphenation = _hyphen;
 
5588
    // This is only used as a default setting for the default format in new documents;
 
5589
    // In existing documents the hyphenation comes from the existing formats.
 
5590
}
 
5591
 
4655
5592
void KWDocument::switchViewMode( KWViewMode * newViewMode )
4656
5593
{
4657
5594
    // Don't compare m_viewMode and newViewMode here, it would break
4663
5600
    //necessary to switchmode view in all canvas in first.
4664
5601
    //otherwise in multiview kword crash !
4665
5602
    //perhaps it's not a good idea to store m_modeView into kwcanvas.
4666
 
    //but it's necessary for the futur when kword will support
 
5603
    //but it's necessary for the future when kword will support
4667
5604
    //different view mode in different view.
4668
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4669
 
        viewPtr->getGUI()->canvasWidget()->switchViewMode( m_viewMode );
 
5605
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5606
        (*it)->getGUI()->canvasWidget()->switchViewMode( m_viewMode );
4670
5607
 
4671
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4672
 
        viewPtr->switchModeView();
 
5608
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5609
        (*it)->switchModeView();
4673
5610
    emit newContentsSize();
4674
5611
    updateResizeHandles();
4675
5612
 
4680
5617
    layout();
4681
5618
 
4682
5619
    repaintAllViews( true );
4683
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4684
 
        viewPtr->getGUI()->canvasWidget()->ensureCursorVisible();
 
5620
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5621
        (*it)->getGUI()->canvasWidget()->ensureCursorVisible();
4685
5622
}
4686
5623
 
4687
5624
void KWDocument::changeBgSpellCheckingState( bool b )
4730
5667
{
4731
5668
    if ( !m_cursorInProtectectedArea )
4732
5669
    {
4733
 
        for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4734
 
            viewPtr->testAndCloseAllFrameSetProtectedContent();
 
5670
        for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5671
            (*it)->testAndCloseAllFrameSetProtectedContent();
4735
5672
    }
4736
5673
}
4737
5674
 
4738
5675
void KWDocument::updateRulerInProtectContentMode()
4739
5676
{
4740
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4741
 
        viewPtr->updateRulerInProtectContentMode();
 
5677
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5678
        (*it)->updateRulerInProtectContentMode();
4742
5679
}
4743
5680
 
4744
5681
 
4819
5756
}
4820
5757
 
4821
5758
 
4822
 
void KWDocument::spellCheckParagraphDeleted( KoTextParag *_parag,  KWTextFrameSet *frm)
4823
 
{
4824
 
    m_bgSpellCheck->spellCheckParagraphDeleted( _parag, frm->textObject());
4825
 
}
4826
 
 
4827
5759
void KWDocument::paragraphDeleted( KoTextParag *_parag, KWFrameSet *frm )
4828
5760
{
4829
5761
    if ( m_bookmarkList.isEmpty() )
4844
5776
 
4845
5777
void KWDocument::initBookmarkList()
4846
5778
{
4847
 
    QPtrListIterator<bookMark> book(m_tmpBookMarkList);
4848
 
    for ( ; book.current() ; ++book )
 
5779
    Q_ASSERT( m_loadingInfo );
 
5780
    if ( !m_loadingInfo )
 
5781
        return;
 
5782
    KWLoadingInfo::BookMarkList bookmarks();
 
5783
    KWLoadingInfo::BookMarkList::Iterator it = m_loadingInfo->bookMarkList.begin();
 
5784
    KWLoadingInfo::BookMarkList::Iterator end = m_loadingInfo->bookMarkList.end();
 
5785
    for( ; it != end; ++it )
4849
5786
    {
4850
5787
        KWFrameSet * fs = 0L;
4851
 
        QString fsName = book.current()->frameSetName;
 
5788
        QString fsName = (*it).frameSetName;
4852
5789
        if ( !fsName.isEmpty() )
4853
5790
            fs = frameSetByName( fsName );
4854
5791
        if ( fs )
4855
5792
        {
4856
5793
            KWTextFrameSet *frm = dynamic_cast<KWTextFrameSet *>(fs);
4857
 
            if ( frm)
 
5794
            if ( frm )
4858
5795
            {
4859
 
                KWBookMark *tmp =new KWBookMark( book.current()->bookname);
4860
 
                tmp->setFrameSet(frm);
4861
 
                KWTextParag* startparag = dynamic_cast<KWTextParag*>(frm->textDocument()->paragAt( book.current()->paragStartIndex ));
4862
 
                KWTextParag* endparag = dynamic_cast<KWTextParag*>(frm->textDocument()->paragAt( book.current()->paragEndIndex ));
4863
 
 
4864
 
                if ( !startparag || !endparag)
4865
 
                {
4866
 
                    delete tmp;
4867
 
                }
4868
 
                else
4869
 
                {
4870
 
                    tmp->setStartParag( startparag );
4871
 
                    tmp->setEndParag( endparag );
4872
 
                    tmp->setBookmarkStartIndex( book.current()->cursorStartIndex);
4873
 
                    tmp->setBookmarkEndIndex( book.current()->cursorEndIndex);
4874
 
                    m_bookmarkList.append( tmp );
 
5796
                KoTextParag* startparag = frm->textDocument()->paragAt( (*it).paragStartIndex );
 
5797
                KoTextParag* endparag = frm->textDocument()->paragAt( (*it).paragEndIndex );
 
5798
                if ( startparag && endparag )
 
5799
                {
 
5800
                    KWBookMark *bk = new KWBookMark( (*it).bookname );
 
5801
                    bk->setFrameSet( frm );
 
5802
                    bk->setStartParag( startparag );
 
5803
                    bk->setEndParag( endparag );
 
5804
                    bk->setBookmarkStartIndex( (*it).cursorStartIndex );
 
5805
                    bk->setBookmarkEndIndex( (*it).cursorEndIndex );
 
5806
                    m_bookmarkList.append( bk );
4875
5807
                }
4876
5808
            }
4877
5809
        }
4878
5810
    }
4879
 
    m_tmpBookMarkList.setAutoDelete( true );
4880
 
    m_tmpBookMarkList.clear();
4881
5811
}
4882
5812
 
4883
5813
QPixmap* KWDocument::doubleBufferPixmap( const QSize& s )
4906
5836
    }
4907
5837
}
4908
5838
 
4909
 
void KWDocument::configureSpellChecker()
4910
 
{
4911
 
    KWView * view = static_cast<KWView*>(views().getFirst());
4912
 
    if ( view ) // no view if embedded document
4913
 
    {
4914
 
        view->configureSpellChecker();
4915
 
    }
4916
 
}
4917
 
 
4918
5839
void KWDocument::setPersonalExpressionPath( const QStringList & lst)
4919
5840
{
4920
5841
    m_personalExpressionPath = lst;
4923
5844
 
4924
5845
void KWDocument::updateDirectCursorButton()
4925
5846
{
4926
 
    for ( KWView *viewPtr = m_lstViews.first(); viewPtr != 0; viewPtr = m_lstViews.next() )
4927
 
        viewPtr->updateDirectCursorButton();
 
5847
    for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
 
5848
        (*it)->updateDirectCursorButton();
4928
5849
}
4929
5850
 
4930
5851
void KWDocument::setInsertDirectCursor(bool _b)
4936
5857
    updateDirectCursorButton();
4937
5858
}
4938
5859
 
 
5860
void KWDocument::saveDialogShown()
 
5861
{
 
5862
    if ( !textFrameSet(0) )
 
5863
        return;
 
5864
    // Grab first 50 chars from the main frameset's document
 
5865
    // ### This is a somewhat slow method, if the document is huge - better iterate
 
5866
    // over the first few parags until 50 chars have been collected.
 
5867
    QString first_row = textFrameSet(0)->textDocument()->plainText().left(50);
 
5868
    bool truncate = false;
 
5869
    QChar ch;
 
5870
    for (int i=0; i < (int)first_row.length(); i++)
 
5871
    {
 
5872
        ch = first_row.at(i);
 
5873
        if (!truncate)
 
5874
            if (ch.isPunct() || ch.isSpace() || ch == '.' )
 
5875
            {
 
5876
                first_row.remove(i,1);
 
5877
                --i;
 
5878
            }
 
5879
            else
 
5880
                truncate = true;
 
5881
        else if ( truncate && (ch.isPunct() || ch == '.' || ch == '\n' ) )
 
5882
        {
 
5883
            first_row.truncate(i);
 
5884
            break;
 
5885
        }
 
5886
    }
 
5887
    first_row = first_row.stripWhiteSpace();
 
5888
    kdDebug() << "Suggested filename:" << first_row << endl;
 
5889
    setURL(first_row);
 
5890
}
 
5891
 
4939
5892
#if 0 // KWORD_HORIZONTAL_LINE
4940
5893
void KWDocument::setHorizontalLinePath( const QStringList & lst)
4941
5894
{
4943
5896
}
4944
5897
#endif
4945
5898
 
4946
 
void KWDocument::addWordToDictionary( const QString & word)
 
5899
void KWDocument::addWordToDictionary( const QString& word )
4947
5900
{
 
5901
#ifdef HAVE_LIBKSPELL2
4948
5902
    if ( m_bgSpellCheck )
4949
5903
    {
4950
 
        m_bgSpellCheck->addPersonalDictonary( word );
 
5904
        if( m_spellCheckPersonalDict.findIndex( word ) == -1 )
 
5905
            m_spellCheckPersonalDict.append( word );
 
5906
        m_bgSpellCheck->settings()->setCurrentIgnoreList( m_spellCheckIgnoreList + m_spellCheckPersonalDict );
 
5907
        if ( backgroundSpellCheckEnabled() )
 
5908
            // Re-check everything to make this word normal again
 
5909
            reactivateBgSpellChecking();
4951
5910
    }
 
5911
#endif
4952
5912
}
4953
5913
 
4954
5914
void KWDocument::setEmpty()