1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <sfx2/docfilt.hxx>
23 #include <sot/storage.hxx>
24 #include <tools/urlobj.hxx>
25 #include <svl/fstathelper.hxx>
26 #include <svl/macitem.hxx>
27 #include <unotools/charclass.hxx>
32 #include <shellio.hxx>
33 #include <swblocks.hxx>
36 #include <SwXMLTextBlocks.hxx>
38 #include <swunohelper.hxx>
43 * Calculate hash code (is not guaranteed to be unique)
45 sal_uInt16
SwImpBlocks::Hash( const OUString
& r
)
48 // std::min requires an explicit cast to sal_Int32 on 32bit platforms
49 const sal_Int32 nLen
= std::min(r
.getLength(), static_cast<sal_Int32
>(8));
50 for (sal_Int32 i
=0; i
<nLen
; ++i
)
52 n
= ( n
<< 1 ) + r
[i
];
57 SwBlockName::SwBlockName( const OUString
& rShort
, const OUString
& rLong
)
58 : aShort( rShort
), aLong( rLong
), aPackageName (rShort
),
59 bIsOnlyTextFlagInit( false ), bIsOnlyText( false )
61 nHashS
= SwImpBlocks::Hash( rShort
);
62 nHashL
= SwImpBlocks::Hash( rLong
);
65 SwBlockName::SwBlockName( const OUString
& rShort
, const OUString
& rLong
, const OUString
& rPackageName
)
66 : aShort( rShort
), aLong( rLong
), aPackageName (rPackageName
),
67 bIsOnlyTextFlagInit( false ), bIsOnlyText( false )
69 nHashS
= SwImpBlocks::Hash( rShort
);
70 nHashL
= SwImpBlocks::Hash( rLong
);
74 * Is the provided file a storage or doesn't it exist?
76 SwImpBlocks::FileType
SwImpBlocks::GetFileType( const OUString
& rFile
)
78 if( !FStatHelper::IsDocument( rFile
) )
79 return FileType::NoFile
;
80 if( SwXMLTextBlocks::IsFileUCBStorage( rFile
) )
82 if( SotStorage::IsStorageFile( rFile
) )
84 //otherwise return NONE
85 return FileType::None
;
88 SwImpBlocks::SwImpBlocks( const OUString
& rFile
)
90 m_aDateModified( Date::EMPTY
),
91 m_aTimeModified( tools::Time::EMPTY
),
92 m_nCurrentIndex( USHRT_MAX
),
93 m_bReadOnly( true ), m_bInPutMuchBlocks( false ),
96 FStatHelper::GetModifiedDateTimeOfFile( rFile
,
97 &m_aDateModified
, &m_aTimeModified
);
98 INetURLObject
aObj(rFile
);
99 aObj
.setExtension( OUString() );
100 m_aName
= aObj
.GetBase();
103 SwImpBlocks::~SwImpBlocks()
105 m_aNames
.DeleteAndDestroyAll();
109 * Delete the document's content
111 void SwImpBlocks::ClearDoc()
117 * Creating a PaM, that spans the whole document
119 SwPaM
* SwImpBlocks::MakePaM()
121 SwPaM
* pPam
= new SwPaM( m_xDoc
->GetNodes().GetEndOfContent() );
122 pPam
->Move( fnMoveBackward
, GoInDoc
);
124 pPam
->Move( fnMoveForward
, GoInDoc
);
129 sal_uInt16
SwImpBlocks::GetCount() const
131 return m_aNames
.size();
137 sal_uInt16
SwImpBlocks::GetIndex( const OUString
& rShort
) const
139 const OUString
s( GetAppCharClass().uppercase( rShort
) );
140 const sal_uInt16 nHash
= Hash( s
);
141 for( size_t i
= 0; i
< m_aNames
.size(); i
++ )
143 const SwBlockName
* pName
= m_aNames
[ i
];
144 if( pName
->nHashS
== nHash
145 && pName
->aShort
== s
)
151 sal_uInt16
SwImpBlocks::GetLongIndex( const OUString
& rLong
) const
153 sal_uInt16 nHash
= Hash( rLong
);
154 for( size_t i
= 0; i
< m_aNames
.size(); i
++ )
156 const SwBlockName
* pName
= m_aNames
[ i
];
157 if( pName
->nHashL
== nHash
158 && pName
->aLong
== rLong
)
164 OUString
SwImpBlocks::GetShortName( sal_uInt16 n
) const
166 if( n
< m_aNames
.size() )
167 return m_aNames
[n
]->aShort
;
171 OUString
SwImpBlocks::GetLongName( sal_uInt16 n
) const
173 if( n
< m_aNames
.size() )
174 return m_aNames
[n
]->aLong
;
178 OUString
SwImpBlocks::GetPackageName( sal_uInt16 n
) const
180 if( n
< m_aNames
.size() )
181 return m_aNames
[n
]->aPackageName
;
185 void SwImpBlocks::AddName( const OUString
& rShort
, const OUString
& rLong
,
188 sal_uInt16 nIdx
= GetIndex( rShort
);
189 if( nIdx
!= USHRT_MAX
)
191 delete m_aNames
[nIdx
];
192 m_aNames
.erase( m_aNames
.begin() + nIdx
);
194 SwBlockName
* pNew
= new SwBlockName( rShort
, rLong
);
195 pNew
->bIsOnlyTextFlagInit
= true;
196 pNew
->bIsOnlyText
= bOnlyText
;
197 m_aNames
.insert( pNew
);
200 bool SwImpBlocks::IsFileChanged() const
202 Date
aTempDateModified( m_aDateModified
);
203 tools::Time
aTempTimeModified( m_aTimeModified
);
204 return FStatHelper::GetModifiedDateTimeOfFile( m_aFile
, &aTempDateModified
, &aTempTimeModified
) &&
205 ( m_aDateModified
!= aTempDateModified
||
206 m_aTimeModified
!= aTempTimeModified
);
209 void SwImpBlocks::Touch()
211 FStatHelper::GetModifiedDateTimeOfFile( m_aFile
, &m_aDateModified
, &m_aTimeModified
);
214 bool SwImpBlocks::IsOnlyTextBlock( const OUString
& ) const
219 ErrCode
SwImpBlocks::GetMacroTable( sal_uInt16
, SvxMacroTableDtor
& )
224 ErrCode
SwImpBlocks::SetMacroTable( sal_uInt16
, const SvxMacroTableDtor
& )
229 bool SwImpBlocks::PutMuchEntries( bool )
234 SwTextBlocks::SwTextBlocks( const OUString
& rFile
)
235 : pImp( nullptr ), nErr( 0 )
237 INetURLObject
aObj(rFile
);
238 const OUString sFileName
= aObj
.GetMainURL( INetURLObject::DecodeMechanism::NONE
);
239 switch( SwImpBlocks::GetFileType( rFile
) )
241 case SwImpBlocks::FileType::XML
: pImp
.reset( new SwXMLTextBlocks( sFileName
) ); break;
242 case SwImpBlocks::FileType::NoFile
: pImp
.reset( new SwXMLTextBlocks( sFileName
) ); break;
246 nErr
= ERR_SWG_FILE_FORMAT_ERROR
;
249 SwTextBlocks::~SwTextBlocks()
253 OUString
SwTextBlocks::GetName()
255 return pImp
? pImp
->m_aName
: OUString();
258 void SwTextBlocks::SetName( const OUString
& r
)
264 bool SwTextBlocks::IsOld() const
268 SwImpBlocks::FileType nType
= pImp
->GetFileType();
269 if (SwImpBlocks::FileType::SW3
== nType
)
275 sal_uInt16
SwTextBlocks::GetCount() const
277 return pImp
? pImp
->GetCount() : 0;
280 sal_uInt16
SwTextBlocks::GetIndex( const OUString
& r
) const
282 return pImp
? pImp
->GetIndex( r
) : USHRT_MAX
;
285 sal_uInt16
SwTextBlocks::GetLongIndex( const OUString
& r
) const
287 return pImp
? pImp
->GetLongIndex( r
) : USHRT_MAX
;
290 OUString
SwTextBlocks::GetShortName( sal_uInt16 n
) const
293 return pImp
->GetShortName( n
);
297 OUString
SwTextBlocks::GetLongName( sal_uInt16 n
) const
300 return pImp
->GetLongName( n
);
304 bool SwTextBlocks::Delete( sal_uInt16 n
)
306 if( pImp
&& !pImp
->m_bInPutMuchBlocks
)
308 if( pImp
->IsFileChanged() )
309 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
310 else if( ERRCODE_NONE
== (nErr
= pImp
->OpenFile( false ) ))
312 nErr
= pImp
->Delete( n
);
315 delete pImp
->m_aNames
[n
];
316 pImp
->m_aNames
.erase( pImp
->m_aNames
.begin() + n
);
318 if( n
== pImp
->m_nCurrentIndex
)
319 pImp
->m_nCurrentIndex
= USHRT_MAX
;
321 nErr
= pImp
->MakeBlockList();
326 return ( nErr
== ERRCODE_NONE
);
331 void SwTextBlocks::Rename( sal_uInt16 n
, const OUString
* s
, const OUString
* l
)
333 if( pImp
&& !pImp
->m_bInPutMuchBlocks
)
335 pImp
->m_nCurrentIndex
= USHRT_MAX
;
344 OSL_ENSURE( false, "No short name provided in the rename" );
345 nErr
= ERR_SWG_INTERNAL_ERROR
;
349 if( pImp
->IsFileChanged() )
350 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
351 else if( ERRCODE_NONE
== ( nErr
= pImp
->OpenFile( false )))
353 // Set the new entry in the list before we do that!
354 aNew
= GetAppCharClass().uppercase( aNew
);
355 nErr
= pImp
->Rename( n
, aNew
, aLong
);
358 bool bOnlyText
= pImp
->m_aNames
[ n
]->bIsOnlyText
;
359 delete pImp
->m_aNames
[n
];
360 pImp
->m_aNames
.erase( pImp
->m_aNames
.begin() + n
);
361 pImp
->AddName( aNew
, aLong
, bOnlyText
);
362 nErr
= pImp
->MakeBlockList();
370 ErrCode
const & SwTextBlocks::CopyBlock( SwTextBlocks
const & rSource
, OUString
& rSrcShort
,
371 const OUString
& rLong
)
376 SwImpBlocks::FileType nType
= rSource
.pImp
->GetFileType();
377 if (SwImpBlocks::FileType::SW3
== nType
)
380 if( bIsOld
) //rSource.IsOld() )
381 nErr
= ERR_SWG_OLD_GLOSSARY
;
382 else if( pImp
->m_bInPutMuchBlocks
)
383 nErr
= ERR_SWG_INTERNAL_ERROR
;
385 nErr
= pImp
->CopyBlock(*rSource
.pImp
, rSrcShort
, rLong
);
389 bool SwTextBlocks::BeginGetDoc( sal_uInt16 n
)
391 if( pImp
&& !pImp
->m_bInPutMuchBlocks
)
393 if( pImp
->IsFileChanged() )
394 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
395 else if( ERRCODE_NONE
== ( nErr
= pImp
->OpenFile()))
398 nErr
= pImp
->GetDoc( n
);
400 pImp
->m_nCurrentIndex
= USHRT_MAX
;
402 pImp
->m_nCurrentIndex
= n
;
404 return ( nErr
== ERRCODE_NONE
);
409 void SwTextBlocks::EndGetDoc()
411 if( pImp
&& !pImp
->m_bInPutMuchBlocks
)
415 bool SwTextBlocks::BeginPutDoc( const OUString
& s
, const OUString
& l
)
419 bool bOk
= pImp
->m_bInPutMuchBlocks
;
422 if( pImp
->IsFileChanged() )
423 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
425 nErr
= pImp
->OpenFile( false );
426 bOk
= ERRCODE_NONE
== nErr
;
430 const OUString aNew
= GetAppCharClass().uppercase(s
);
431 nErr
= pImp
->BeginPutDoc( aNew
, l
);
436 return ERRCODE_NONE
== nErr
;
439 sal_uInt16
SwTextBlocks::PutDoc()
441 sal_uInt16 nIdx
= USHRT_MAX
;
444 nErr
= pImp
->PutDoc();
447 pImp
->m_nCurrentIndex
= GetIndex( pImp
->m_aShort
);
448 if( pImp
->m_nCurrentIndex
!= USHRT_MAX
)
449 pImp
->m_aNames
[ pImp
->m_nCurrentIndex
]->aLong
= pImp
->m_aLong
;
452 pImp
->AddName( pImp
->m_aShort
, pImp
->m_aLong
);
453 pImp
->m_nCurrentIndex
= pImp
->GetIndex( pImp
->m_aShort
);
455 if( !pImp
->m_bInPutMuchBlocks
)
456 nErr
= pImp
->MakeBlockList();
458 if( !pImp
->m_bInPutMuchBlocks
)
463 nIdx
= pImp
->m_nCurrentIndex
;
468 sal_uInt16
SwTextBlocks::PutText( const OUString
& rShort
, const OUString
& rName
,
469 const OUString
& rText
)
471 sal_uInt16 nIdx
= USHRT_MAX
;
474 bool bOk
= pImp
->m_bInPutMuchBlocks
;
477 if( pImp
->IsFileChanged() )
478 nErr
= ERR_TXTBLOCK_NEWFILE_ERROR
;
480 nErr
= pImp
->OpenFile( false );
481 bOk
= ERRCODE_NONE
== nErr
;
485 OUString aNew
= GetAppCharClass().uppercase( rShort
);
486 nErr
= pImp
->PutText( aNew
, rName
, rText
);
487 pImp
->m_nCurrentIndex
= USHRT_MAX
;
490 nIdx
= GetIndex( pImp
->m_aShort
);
491 if( nIdx
!= USHRT_MAX
)
492 pImp
->m_aNames
[ nIdx
]->aLong
= rName
;
495 pImp
->AddName( pImp
->m_aShort
, rName
, true );
496 nIdx
= pImp
->GetIndex( pImp
->m_aShort
);
498 if( !pImp
->m_bInPutMuchBlocks
)
499 nErr
= pImp
->MakeBlockList();
502 if( !pImp
->m_bInPutMuchBlocks
)
511 SwDoc
* SwTextBlocks::GetDoc()
514 return pImp
->m_xDoc
.get();
518 void SwTextBlocks::ClearDoc()
523 pImp
->m_nCurrentIndex
= USHRT_MAX
;
527 OUString
const & SwTextBlocks::GetFileName() const
529 return pImp
->GetFileName();
532 bool SwTextBlocks::IsReadOnly() const
534 return pImp
->m_bReadOnly
;
537 bool SwTextBlocks::IsOnlyTextBlock( sal_uInt16 nIdx
) const
540 if( pImp
&& !pImp
->m_bInPutMuchBlocks
)
542 SwBlockName
* pBlkNm
= pImp
->m_aNames
[ nIdx
];
543 if( !pBlkNm
->bIsOnlyTextFlagInit
&&
544 !pImp
->IsFileChanged() && !pImp
->OpenFile() )
546 pBlkNm
->bIsOnlyText
= pImp
->IsOnlyTextBlock( pBlkNm
->aShort
);
547 pBlkNm
->bIsOnlyTextFlagInit
= true;
550 bRet
= pBlkNm
->bIsOnlyText
;
555 bool SwTextBlocks::IsOnlyTextBlock( const OUString
& rShort
) const
557 sal_uInt16 nIdx
= pImp
->GetIndex( rShort
);
558 if( USHRT_MAX
!= nIdx
)
560 if( pImp
->m_aNames
[ nIdx
]->bIsOnlyTextFlagInit
)
561 return pImp
->m_aNames
[ nIdx
]->bIsOnlyText
;
562 return IsOnlyTextBlock( nIdx
);
565 OSL_ENSURE( false, "Invalid name" );
569 bool SwTextBlocks::GetMacroTable( sal_uInt16 nIdx
, SvxMacroTableDtor
& rMacroTable
)
572 if ( pImp
&& !pImp
->m_bInPutMuchBlocks
)
573 bRet
= ( ERRCODE_NONE
== pImp
->GetMacroTable( nIdx
, rMacroTable
) );
577 bool SwTextBlocks::SetMacroTable( sal_uInt16 nIdx
, const SvxMacroTableDtor
& rMacroTable
)
580 if ( pImp
&& !pImp
->m_bInPutMuchBlocks
)
581 bRet
= ( ERRCODE_NONE
== pImp
->SetMacroTable( nIdx
, rMacroTable
) );
585 bool SwTextBlocks::StartPutMuchBlockEntries()
588 if( !IsOld() && pImp
)
589 bRet
= pImp
->PutMuchEntries( true );
593 void SwTextBlocks::EndPutMuchBlockEntries()
596 pImp
->PutMuchEntries( false );
599 OUString
SwTextBlocks::GetBaseURL() const
602 return pImp
->GetBaseURL();
606 void SwTextBlocks::SetBaseURL( const OUString
& rURL
)
609 pImp
->SetBaseURL(rURL
);
612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */