Version 6.1.0.2, tag libreoffice-6.1.0.2
[LibreOffice.git] / sw / source / core / swg / swblocks.cxx
blob70d8c037c4fcc6c02bb96de3120c3df6d4d2f090
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <algorithm>
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>
28 #include <frmfmt.hxx>
29 #include <doc.hxx>
30 #include <docary.hxx>
31 #include <pam.hxx>
32 #include <shellio.hxx>
33 #include <swblocks.hxx>
34 #include <ndtxt.hxx>
35 #include <mdiexp.hxx>
36 #include <SwXMLTextBlocks.hxx>
37 #include <docsh.hxx>
38 #include <swunohelper.hxx>
40 #include <swerror.h>
42 /**
43 * Calculate hash code (is not guaranteed to be unique)
45 sal_uInt16 SwImpBlocks::Hash( const OUString& r )
47 sal_uInt16 n = 0;
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];
54 return n;
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 );
73 /**
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 ) )
81 return FileType::XML;
82 if( SotStorage::IsStorageFile( rFile ) )
83 return FileType::SW3;
84 //otherwise return NONE
85 return FileType::None;
88 SwImpBlocks::SwImpBlocks( const OUString& rFile )
89 : m_aFile( rFile ),
90 m_aDateModified( Date::EMPTY ),
91 m_aTimeModified( tools::Time::EMPTY ),
92 m_nCurrentIndex( USHRT_MAX ),
93 m_bReadOnly( true ), m_bInPutMuchBlocks( false ),
94 m_bInfoChanged(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()
113 m_xDoc->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 );
123 pPam->SetMark();
124 pPam->Move( fnMoveForward, GoInDoc );
125 pPam->Exchange();
126 return pPam;
129 sal_uInt16 SwImpBlocks::GetCount() const
131 return m_aNames.size();
135 * Case Insensitive
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 )
146 return i;
148 return USHRT_MAX;
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 )
159 return i;
161 return USHRT_MAX;
164 OUString SwImpBlocks::GetShortName( sal_uInt16 n ) const
166 if( n < m_aNames.size() )
167 return m_aNames[n]->aShort;
168 return OUString();
171 OUString SwImpBlocks::GetLongName( sal_uInt16 n ) const
173 if( n < m_aNames.size() )
174 return m_aNames[n]->aLong;
175 return OUString();
178 OUString SwImpBlocks::GetPackageName( sal_uInt16 n ) const
180 if( n < m_aNames.size() )
181 return m_aNames[n]->aPackageName;
182 return OUString();
185 void SwImpBlocks::AddName( const OUString& rShort, const OUString& rLong,
186 bool bOnlyText )
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
216 return false;
219 ErrCode SwImpBlocks::GetMacroTable( sal_uInt16, SvxMacroTableDtor& )
221 return ERRCODE_NONE;
224 ErrCode SwImpBlocks::SetMacroTable( sal_uInt16 , const SvxMacroTableDtor& )
226 return ERRCODE_NONE;
229 bool SwImpBlocks::PutMuchEntries( bool )
231 return false;
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;
243 default: break;
245 if( !pImp )
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 )
260 if( pImp )
261 pImp->SetName( r );
264 bool SwTextBlocks::IsOld() const
266 if (pImp)
268 SwImpBlocks::FileType nType = pImp->GetFileType();
269 if (SwImpBlocks::FileType::SW3 == nType)
270 return true;
272 return false;
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
292 if( pImp )
293 return pImp->GetShortName( n );
294 return OUString();
297 OUString SwTextBlocks::GetLongName( sal_uInt16 n ) const
299 if( pImp )
300 return pImp->GetLongName( n );
301 return OUString();
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 );
313 if( !nErr )
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;
320 if( !nErr )
321 nErr = pImp->MakeBlockList();
323 pImp->CloseFile();
324 pImp->Touch();
326 return ( nErr == ERRCODE_NONE );
328 return false;
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;
336 OUString aNew;
337 OUString aLong;
338 if( s )
339 aNew = aLong = *s;
340 if( l )
341 aLong = *l;
342 if( aNew.isEmpty() )
344 OSL_ENSURE( false, "No short name provided in the rename" );
345 nErr = ERR_SWG_INTERNAL_ERROR;
346 return;
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 );
356 if( !nErr )
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();
365 pImp->CloseFile();
366 pImp->Touch();
370 ErrCode const & SwTextBlocks::CopyBlock( SwTextBlocks const & rSource, OUString& rSrcShort,
371 const OUString& rLong )
373 bool bIsOld = false;
374 if (rSource.pImp)
376 SwImpBlocks::FileType nType = rSource.pImp->GetFileType();
377 if (SwImpBlocks::FileType::SW3 == nType)
378 bIsOld = true;
380 if( bIsOld ) //rSource.IsOld() )
381 nErr = ERR_SWG_OLD_GLOSSARY;
382 else if( pImp->m_bInPutMuchBlocks )
383 nErr = ERR_SWG_INTERNAL_ERROR;
384 else
385 nErr = pImp->CopyBlock(*rSource.pImp, rSrcShort, rLong);
386 return nErr;
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()))
397 pImp->ClearDoc();
398 nErr = pImp->GetDoc( n );
399 if( nErr )
400 pImp->m_nCurrentIndex = USHRT_MAX;
401 else
402 pImp->m_nCurrentIndex = n;
404 return ( nErr == ERRCODE_NONE );
406 return false;
409 void SwTextBlocks::EndGetDoc()
411 if( pImp && !pImp->m_bInPutMuchBlocks )
412 pImp->CloseFile();
415 bool SwTextBlocks::BeginPutDoc( const OUString& s, const OUString& l )
417 if( pImp )
419 bool bOk = pImp->m_bInPutMuchBlocks;
420 if( !bOk )
422 if( pImp->IsFileChanged() )
423 nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
424 else
425 nErr = pImp->OpenFile( false );
426 bOk = ERRCODE_NONE == nErr;
428 if( bOk )
430 const OUString aNew = GetAppCharClass().uppercase(s);
431 nErr = pImp->BeginPutDoc( aNew, l );
433 if( nErr )
434 pImp->CloseFile();
436 return ERRCODE_NONE == nErr;
439 sal_uInt16 SwTextBlocks::PutDoc()
441 sal_uInt16 nIdx = USHRT_MAX;
442 if( pImp )
444 nErr = pImp->PutDoc();
445 if( !nErr )
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;
450 else
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 )
460 pImp->CloseFile();
461 pImp->Touch();
463 nIdx = pImp->m_nCurrentIndex;
465 return nIdx;
468 sal_uInt16 SwTextBlocks::PutText( const OUString& rShort, const OUString& rName,
469 const OUString& rText )
471 sal_uInt16 nIdx = USHRT_MAX;
472 if( pImp )
474 bool bOk = pImp->m_bInPutMuchBlocks;
475 if( !bOk )
477 if( pImp->IsFileChanged() )
478 nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
479 else
480 nErr = pImp->OpenFile( false );
481 bOk = ERRCODE_NONE == nErr;
483 if( bOk )
485 OUString aNew = GetAppCharClass().uppercase( rShort );
486 nErr = pImp->PutText( aNew, rName, rText );
487 pImp->m_nCurrentIndex = USHRT_MAX;
488 if( !nErr )
490 nIdx = GetIndex( pImp->m_aShort );
491 if( nIdx != USHRT_MAX )
492 pImp->m_aNames[ nIdx ]->aLong = rName;
493 else
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 )
504 pImp->CloseFile();
505 pImp->Touch();
508 return nIdx;
511 SwDoc* SwTextBlocks::GetDoc()
513 if( pImp )
514 return pImp->m_xDoc.get();
515 return nullptr;
518 void SwTextBlocks::ClearDoc()
520 if( pImp )
522 pImp->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
539 bool bRet = false;
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;
548 pImp->CloseFile();
550 bRet = pBlkNm->bIsOnlyText;
552 return bRet;
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" );
566 return false;
569 bool SwTextBlocks::GetMacroTable( sal_uInt16 nIdx, SvxMacroTableDtor& rMacroTable )
571 bool bRet = true;
572 if ( pImp && !pImp->m_bInPutMuchBlocks )
573 bRet = ( ERRCODE_NONE == pImp->GetMacroTable( nIdx, rMacroTable ) );
574 return bRet;
577 bool SwTextBlocks::SetMacroTable( sal_uInt16 nIdx, const SvxMacroTableDtor& rMacroTable )
579 bool bRet = true;
580 if ( pImp && !pImp->m_bInPutMuchBlocks )
581 bRet = ( ERRCODE_NONE == pImp->SetMacroTable( nIdx, rMacroTable ) );
582 return bRet;
585 bool SwTextBlocks::StartPutMuchBlockEntries()
587 bool bRet = false;
588 if( !IsOld() && pImp )
589 bRet = pImp->PutMuchEntries( true );
590 return bRet;
593 void SwTextBlocks::EndPutMuchBlockEntries()
595 if( pImp )
596 pImp->PutMuchEntries( false );
599 OUString SwTextBlocks::GetBaseURL() const
601 if(pImp)
602 return pImp->GetBaseURL();
603 return OUString();
606 void SwTextBlocks::SetBaseURL( const OUString& rURL )
608 if(pImp)
609 pImp->SetBaseURL(rURL);
612 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */