1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: swblocks.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <sfx2/docfilt.hxx>
36 #include <sot/storage.hxx>
37 #include <tools/urlobj.hxx>
38 #ifndef SVTOOLS_FSTATHELPER_HXX
39 #include <svtools/fstathelper.hxx>
41 #include <svtools/macitem.hxx>
42 #include <unotools/charclass.hxx>
47 #include <shellio.hxx>
48 #include <swblocks.hxx>
50 #include <mdiexp.hxx> // Progress
51 #include <SwXMLTextBlocks.hxx>
55 #include <swunohelper.hxx>
58 #include <statstr.hrc>
62 SV_IMPL_OP_PTRARR_SORT( SwBlockNames
, SwBlockName
* );
64 //////////////////////////////////////////////////////////////////////////
66 // Hash-Code errechnen (muss nicht eindeutig sein)
69 USHORT
SwImpBlocks::Hash( const String
& r
)
72 xub_StrLen nLen
= r
.Len();
75 const sal_Unicode
* p
= r
.GetBuffer();
77 n
= ( n
<< 1 ) + *p
++;
82 SwBlockName::SwBlockName( const String
& rShort
, const String
& rLong
, long n
)
83 : nPos( n
), aShort( rShort
), aLong( rLong
), aPackageName (rShort
),
84 bIsOnlyTxtFlagInit( FALSE
), bIsOnlyTxt( FALSE
)
86 nHashS
= SwImpBlocks::Hash( rShort
);
87 nHashL
= SwImpBlocks::Hash( rLong
);
89 SwBlockName::SwBlockName( const String
& rShort
, const String
& rLong
, const String
& rPackageName
)
90 : nPos( 0 ), aShort( rShort
), aLong( rLong
), aPackageName (rPackageName
),
91 bIsOnlyTxtFlagInit( FALSE
), bIsOnlyTxt( FALSE
)
93 nHashS
= SwImpBlocks::Hash( rShort
);
94 nHashL
= SwImpBlocks::Hash( rLong
);
98 // Ist die angegebene Datei ein Storage oder gibt es sie nicht?
100 short SwImpBlocks::GetFileType( const String
& rFile
)
102 if( !FStatHelper::IsDocument( rFile
) )
103 return SWBLK_NO_FILE
;
104 if( SwXMLTextBlocks::IsFileUCBStorage( rFile
) )
106 if( SvStorage::IsStorageFile( rFile
) )
108 //otherwise return NONE
113 SwImpBlocks::SwImpBlocks( const String
& rFile
, BOOL
)
114 : aFile( rFile
), pDoc( 0 ), nCur( (USHORT
)-1 ),
115 bReadOnly( TRUE
), bInPutMuchBlocks( FALSE
)
117 FStatHelper::GetModifiedDateTimeOfFile( rFile
,
118 &aDateModified
, &aTimeModified
);
119 INetURLObject
aObj(rFile
);
120 aObj
.setExtension( aEmptyStr
);
121 aName
= aObj
.GetBase();
125 SwImpBlocks::~SwImpBlocks()
127 aNames
.DeleteAndDestroy( 0, aNames
.Count() );
130 // Loeschen des Inhaltes des Dokuments
131 void SwImpBlocks::ClearDoc()
136 ULONG
SwImpBlocks::GetDocForConversion( USHORT n
)
141 // Erzeugen eines PaMs, der das ganze Dokument umfasst
142 SwPaM
* SwImpBlocks::MakePaM()
144 SwPaM
* pPam
= new SwPaM( pDoc
->GetNodes().GetEndOfContent() );
145 pPam
->Move( fnMoveBackward
, fnGoDoc
);
147 pPam
->Move( fnMoveForward
, fnGoDoc
);
153 USHORT
SwImpBlocks::GetCount() const
155 return aNames
.Count();
159 USHORT
SwImpBlocks::GetIndex( const String
& rShort
) const
161 String
s( GetAppCharClass().upper( rShort
) );
162 USHORT nHash
= Hash( s
);
163 for( USHORT i
= 0; i
< aNames
.Count(); i
++ )
165 SwBlockName
* pName
= aNames
[ i
];
166 if( pName
->nHashS
== nHash
167 && pName
->aShort
== s
)
174 USHORT
SwImpBlocks::GetLongIndex( const String
& rLong
) const
176 USHORT nHash
= Hash( rLong
);
177 for( USHORT i
= 0; i
< aNames
.Count(); i
++ )
179 SwBlockName
* pName
= aNames
[ i
];
180 if( pName
->nHashL
== nHash
181 && pName
->aLong
== rLong
)
188 const String
& SwImpBlocks::GetShortName( USHORT n
) const
190 if( n
< aNames
.Count() )
191 return aNames
[ n
]->aShort
;
196 const String
& SwImpBlocks::GetLongName( USHORT n
) const
198 if( n
< aNames
.Count() )
199 return aNames
[ n
]->aLong
;
203 const String
& SwImpBlocks::GetPackageName( USHORT n
) const
205 if( n
< aNames
.Count() )
206 return aNames
[ n
]->aPackageName
;
210 void SwImpBlocks::AddName( const String
& rShort
, const String
& rLong
,
213 USHORT nIdx
= GetIndex( rShort
);
214 if( nIdx
!= (USHORT
) -1 )
215 aNames
.DeleteAndDestroy( nIdx
);
216 SwBlockName
* pNew
= new SwBlockName( rShort
, rLong
, 0L );
217 pNew
->bIsOnlyTxtFlagInit
= TRUE
;
218 pNew
->bIsOnlyTxt
= bOnlyTxt
;
219 aNames
.C40_PTR_INSERT( SwBlockName
, pNew
);
224 BOOL
SwImpBlocks::IsFileChanged() const
226 Date
aTempDateModified( aDateModified
);
227 Time
aTempTimeModified( aTimeModified
);
228 return FStatHelper::GetModifiedDateTimeOfFile( aFile
,
229 &aTempDateModified
, &aTempTimeModified
) &&
230 ( aDateModified
!= aTempDateModified
||
231 aTimeModified
!= aTempTimeModified
);
235 void SwImpBlocks::Touch()
237 FStatHelper::GetModifiedDateTimeOfFile( aFile
,
238 &aDateModified
, &aTimeModified
);
241 BOOL
SwImpBlocks::IsOnlyTextBlock( const String
& ) const
246 ULONG
SwImpBlocks::GetMacroTable( USHORT
, SvxMacroTableDtor
&, sal_Bool
)
251 ULONG
SwImpBlocks::SetMacroTable( USHORT
,
252 const SvxMacroTableDtor
& , sal_Bool
)
257 BOOL
SwImpBlocks::PutMuchEntries( BOOL
)
262 ////////////////////////////////////////////////////////////////////////////
265 SwTextBlocks::SwTextBlocks( const String
& rFile
)
266 : pImp( 0 ), nErr( 0 )
268 INetURLObject
aObj(rFile
);
269 String sFileName
= aObj
.GetMainURL( INetURLObject::NO_DECODE
);
270 switch( SwImpBlocks::GetFileType( rFile
) )
272 //case SWBLK_SW2: pImp = new Sw2TextBlocks( sFileName ); break;
273 //case SWBLK_SW3: pImp = new Sw3TextBlocks( sFileName ); break;
274 case SWBLK_XML
: pImp
= new SwXMLTextBlocks( sFileName
); break;
275 case SWBLK_NO_FILE
: pImp
= new SwXMLTextBlocks( sFileName
); break;
278 nErr
= ERR_SWG_FILE_FORMAT_ERROR
;
281 SwTextBlocks::~SwTextBlocks()
286 const String
& SwTextBlocks::GetName()
288 return pImp
? pImp
->aName
: aEmptyStr
;
292 void SwTextBlocks::SetName( const String
& r
)
299 BOOL
SwTextBlocks::IsOld() const
303 short nType
= pImp
->GetFileType();
304 if (SWBLK_SW3
== nType
|| SWBLK_SW2
== nType
)
312 ULONG SwTextBlocks::ConvertToNew()
314 // Wir nehmen die aktuelle Datei, benennen diese in .BAK um
315 // und kreieren den neuen Storage
318 // Erst mal muessen wir die Datei freigeben
319 short nType = pImp->GetFileType();
320 Sw2TextBlocks *pTwo = NULL;
321 Sw3TextBlocks *pThree = NULL;
322 SwImpBlocks *pOld = NULL;
324 pImp->nCur = (USHORT) -1;
325 String aName( pImp->aFile );
326 delete pImp; pImp = NULL;
327 // Jetzt wird umbenannt
328 INetURLObject aOldFull( aName );
329 INetURLObject aNewFull( aName );
331 aOldFull.SetExtension( String::CreateFromAscii("bak") );
332 String aOld( aOldFull.GetMainURL( INetURLObject::NO_DECODE ) );
333 String aNew( aNewFull.GetMainURL( INetURLObject::NO_DECODE ) );
335 BOOL bError = !SWUnoHelper::UCB_CopyFile( aNew, aOld, TRUE );
338 if (nType == SWBLK_SW2)
339 pImp = new Sw2TextBlocks( aOld );
341 pImp = new Sw3TextBlocks( aOld );
342 return nErr = ERR_SWG_CANNOT_WRITE;
345 // Die Datei ist erfolgreich umbenannt. Jetzt wird der Storage
347 if (nType == SWBLK_SW2)
348 pOld = pTwo = new Sw2TextBlocks( aOld );
350 pOld = pThree = new Sw3TextBlocks( aOld );
351 SwXMLTextBlocks* pNew = new SwXMLTextBlocks( aName );
352 pNew->SetName ( pOld->GetName());
353 // Wir kopieren den Doc-Ptr in das alte System
354 // den alten SvPersist heben wir uns aber auf,
355 // da dieser die ganze Zeit leben bleibt
356 // und lesen die Dateivorlagen erneut ein
357 SvPersist* pPersist2 = pOld->pDoc->GetPersist();
358 if (SWBLK_SW2 == nType )
361 pOld->pDoc = pNew->pDoc;nLinkCt
362 nErr = pTwo->LoadDoc();
366 nErr = pThree->OpenFile ( TRUE );
367 // Within this call, Sw3IoImp::SetDoc calls RemoveLink
368 // on the old document, and deletes it if the
369 // ref count is now zero
370 pThree->SetDoc ( pNew->pDoc );
371 pOld->pDoc->AddLink();
373 if( !nErr && 0 == ( nErr = pNew->OpenFile( FALSE )) )
375 nErr = pNew->SetConvertMode( TRUE );
376 // jetzt werden die Bausteine einfach umkopiert!
379 if (SWBLK_SW2 == nType)
380 pTwo->StatLineStartPercent();
381 USHORT nCount = pOld->GetCount();
382 for( USHORT i = 0; i < nCount; i++ )
385 String aShort( pOld->GetShortName( i ) );
386 String aLong( pOld->GetLongName( i ) );
387 pNew->AddName( aShort, aLong );
388 if ( SWBLK_SW3 == nType && pThree->IsOnlyTextBlock(aShort) )
391 pThree->GetText( aShort, sText );
392 pNew->PutText( aShort, aLong, sText );
396 if (SWBLK_SW2 == nType )
398 // I think this is how it should work (!!!!!!) mtg
399 pNew->pDoc->SetPersist( pPersist2 );
401 nErr = pOld->GetDocForConversion( i );
404 nErr = pNew->BeginPutDoc( aShort, aLong );
407 nErr = pNew->PutDoc();
412 // convert macros, too
413 SvxMacroTableDtor aMacroTable;
414 pOld->GetMacroTable( i, aMacroTable, sal_True );
415 pNew->SetMacroTable( i, aMacroTable, sal_True );
417 if (SWBLK_SW2 == nType )
418 pNew->pDoc->SetPersist( 0 );
420 if (SWBLK_SW2 == nType )
421 ::EndProgress( pOld->pDoc->GetDocShell() );
424 nErr = pNew->SetConvertMode( FALSE );
426 if ( SWBLK_SW3 == nType )
432 // Haben wir es geschafft?
440 SWUnoHelper::UCB_DeleteFile( aOld );
441 pNew->MakeBlockList();
445 delete pOld; delete pNew;
446 SWUnoHelper::UCB_DeleteFile( aNew );
447 SWUnoHelper::UCB_CopyFile( aOld, aNew, TRUE );
448 if ( SWBLK_SW2 == nType )
449 pImp = new Sw2TextBlocks( aOld );
451 pImp = new Sw3TextBlocks( aOld );
454 FStatHelper::GetModifiedDateTimeOfFile( aNew,
455 &pImp->aDateModified, &pImp->aTimeModified );
461 USHORT
SwTextBlocks::GetCount() const
463 return pImp
? pImp
->GetCount() : 0;
467 USHORT
SwTextBlocks::GetIndex( const String
& r
) const
469 return pImp
? pImp
->GetIndex( r
) : (USHORT
) -1;
473 USHORT
SwTextBlocks::GetLongIndex( const String
& r
) const
475 return pImp
? (USHORT
)(pImp
->GetLongIndex( r
)) : (USHORT
) -1;
479 const String
& SwTextBlocks::GetShortName( USHORT n
) const
482 return pImp
->GetShortName( n
);
487 const String
& SwTextBlocks::GetLongName( USHORT n
) const
490 return pImp
->GetLongName( n
);
495 BOOL
SwTextBlocks::Delete( USHORT n
)
497 if( pImp
&& !pImp
->bInPutMuchBlocks
)
499 if( pImp
->IsFileChanged() )
500 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
501 else if( 0 == (nErr
= pImp
->OpenFile( FALSE
) ))
503 nErr
= pImp
->Delete( n
);
505 pImp
->aNames
.DeleteAndDestroy( n
);
506 if( n
== pImp
->nCur
)
507 pImp
->nCur
= (USHORT
) -1;
509 nErr
= pImp
->MakeBlockList();
514 return BOOL( nErr
== 0 );
520 USHORT
SwTextBlocks::Rename( USHORT n
, const String
* s
, const String
* l
)
522 USHORT nIdx
= (USHORT
)-1;
523 if( pImp
&& !pImp
->bInPutMuchBlocks
)
533 ASSERT( !this, "Kein Kurzname in Rename angegeben" );
534 nErr
= ERR_SWG_INTERNAL_ERROR
; return (USHORT
) -1;
537 if( pImp
->IsFileChanged() )
538 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
539 else if( 0 == ( nErr
= pImp
->OpenFile( FALSE
)))
541 // Vorher den neuen Eintrag in die Liste setzen!
542 GetAppCharClass().toUpper( aNew
);
543 nErr
= pImp
->Rename( n
, aNew
, aLong
);
546 BOOL bOnlyTxt
= pImp
->aNames
[ n
]->bIsOnlyTxt
;
547 pImp
->aNames
.DeleteAndDestroy( n
);
548 pImp
->AddName( aNew
, aLong
, bOnlyTxt
);
549 nErr
= pImp
->MakeBlockList();
555 nIdx
= pImp
->GetIndex( aNew
);
560 ULONG
SwTextBlocks::CopyBlock( SwTextBlocks
& rSource
, String
& rSrcShort
,
561 const String
& rLong
)
566 short nType
= rSource
.pImp
->GetFileType();
567 if (SWBLK_SW2
== nType
|| SWBLK_SW3
== nType
)
570 if( bIsOld
) //rSource.IsOld() )
571 nErr
= ERR_SWG_OLD_GLOSSARY
;
572 else if( pImp
->bInPutMuchBlocks
)
573 nErr
= ERR_SWG_INTERNAL_ERROR
;
575 nErr
= pImp
->CopyBlock(*rSource
.pImp
, rSrcShort
, rLong
);
579 BOOL
SwTextBlocks::BeginGetDoc( USHORT n
)
581 if( pImp
&& !pImp
->bInPutMuchBlocks
)
583 // diese Optimierierung darf es nicht mehr geben. OLE-Objecte muessen auf
584 // ihre SubStorages zugreifem koennen!
585 // if( n == pImp->nCur )
588 if( pImp
->IsFileChanged() )
589 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
590 else if( 0 == ( nErr
= pImp
->OpenFile( TRUE
)))
593 nErr
= pImp
->GetDoc( n
);
595 pImp
->nCur
= (USHORT
)-1;
599 return BOOL( nErr
== 0 );
605 void SwTextBlocks::EndGetDoc()
607 if( pImp
&& !pImp
->bInPutMuchBlocks
)
612 BOOL
SwTextBlocks::BeginPutDoc( const String
& s
, const String
& l
)
616 BOOL bOk
= pImp
->bInPutMuchBlocks
;
619 if( pImp
->IsFileChanged() )
620 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
622 nErr
= pImp
->OpenFile( FALSE
);
628 GetAppCharClass().toUpper( aNew
);
629 nErr
= pImp
->BeginPutDoc( aNew
, l
);
638 USHORT
SwTextBlocks::PutDoc()
640 USHORT nIdx
= (USHORT
)-1;
643 nErr
= pImp
->PutDoc();
646 pImp
->nCur
= GetIndex( pImp
->aShort
);
647 if( pImp
->nCur
!= (USHORT
) -1 )
648 pImp
->aNames
[ pImp
->nCur
]->aLong
= pImp
->aLong
;
651 pImp
->AddName( pImp
->aShort
, pImp
->aLong
);
652 pImp
->nCur
= pImp
->GetIndex( pImp
->aShort
);
654 if( !pImp
->bInPutMuchBlocks
)
655 nErr
= pImp
->MakeBlockList();
657 if( !pImp
->bInPutMuchBlocks
)
667 USHORT
SwTextBlocks::PutText( const String
& rShort
, const String
& rName
,
670 USHORT nIdx
= (USHORT
) -1;
673 BOOL bOk
= pImp
->bInPutMuchBlocks
;
676 if( pImp
->IsFileChanged() )
677 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
679 nErr
= pImp
->OpenFile( FALSE
);
684 String
aNew( rShort
);
685 GetAppCharClass().toUpper( aNew
);
686 nErr
= pImp
->PutText( aNew
, rName
, rTxt
);
687 pImp
->nCur
= (USHORT
) -1;
690 nIdx
= GetIndex( pImp
->aShort
);
691 if( nIdx
!= (USHORT
) -1 )
692 pImp
->aNames
[ nIdx
]->aLong
= rName
;
695 pImp
->AddName( pImp
->aShort
, rName
, TRUE
);
696 nIdx
= pImp
->GetIndex( pImp
->aShort
);
698 if( !pImp
->bInPutMuchBlocks
)
699 nErr
= pImp
->MakeBlockList();
702 if( !pImp
->bInPutMuchBlocks
)
712 SwDoc
* SwTextBlocks::GetDoc()
720 void SwTextBlocks::ClearDoc()
724 pImp
->nCur
= (USHORT
) -1;
728 const String
& SwTextBlocks::GetFileName() const
730 return pImp
->GetFileName();
734 BOOL
SwTextBlocks::IsReadOnly() const
736 return pImp
->bReadOnly
;
739 BOOL
SwTextBlocks::IsOnlyTextBlock( USHORT nIdx
) const
742 if( pImp
&& !pImp
->bInPutMuchBlocks
)
744 SwBlockName
* pBlkNm
= pImp
->aNames
[ nIdx
];
745 if( !pBlkNm
->bIsOnlyTxtFlagInit
&&
746 !pImp
->IsFileChanged() && !pImp
->OpenFile( TRUE
) )
748 pBlkNm
->bIsOnlyTxt
= pImp
->IsOnlyTextBlock( pBlkNm
->aShort
);
749 pBlkNm
->bIsOnlyTxtFlagInit
= TRUE
;
752 bRet
= pBlkNm
->bIsOnlyTxt
;
757 BOOL
SwTextBlocks::IsOnlyTextBlock( const String
& rShort
) const
759 USHORT nIdx
= pImp
->GetIndex( rShort
);
760 if( USHRT_MAX
!= nIdx
)
762 if( pImp
->aNames
[ nIdx
]->bIsOnlyTxtFlagInit
)
763 return pImp
->aNames
[ nIdx
]->bIsOnlyTxt
;
764 return IsOnlyTextBlock( nIdx
);
767 ASSERT( !this, "ungueltiger Name" );
771 BOOL
SwTextBlocks::GetMacroTable( USHORT nIdx
, SvxMacroTableDtor
& rMacroTbl
)
774 if ( pImp
&& !pImp
->bInPutMuchBlocks
)
775 bRet
= ( 0 == pImp
->GetMacroTable( nIdx
, rMacroTbl
) );
779 BOOL
SwTextBlocks::SetMacroTable( USHORT nIdx
,
780 const SvxMacroTableDtor
& rMacroTbl
)
783 if ( pImp
&& !pImp
->bInPutMuchBlocks
)
784 bRet
= ( 0 == pImp
->SetMacroTable( nIdx
, rMacroTbl
) );
788 BOOL
SwTextBlocks::StartPutMuchBlockEntries()
791 if( !IsOld() && pImp
)
792 bRet
= pImp
->PutMuchEntries( TRUE
);
796 void SwTextBlocks::EndPutMuchBlockEntries()
799 pImp
->PutMuchEntries( FALSE
);
802 /*-- 20.09.2004 10:25:33---------------------------------------------------
804 -----------------------------------------------------------------------*/
805 String
SwTextBlocks::GetBaseURL() const
809 sRet
= pImp
->GetBaseURL();
812 /*-- 20.09.2004 10:25:33---------------------------------------------------
814 -----------------------------------------------------------------------*/
815 void SwTextBlocks::SetBaseURL( const String
& rURL
)
818 pImp
->SetBaseURL(rURL
);