Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <algorithm>
21 :
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>
39 :
40 : #include <statstr.hrc>
41 : #include <swerror.h>
42 :
43 : /**
44 : * Calculate hash code (is not guaranteed to be unique)
45 : */
46 198 : sal_uInt16 SwImpBlocks::Hash( const OUString& r )
47 : {
48 198 : sal_uInt16 n = 0;
49 : // std::min requires an explicit cast to sal_Int32 on 32bit platforms
50 198 : const sal_Int32 nLen = std::min(r.getLength(), static_cast<sal_Int32>(8));
51 1692 : for (sal_Int32 i=0; i<nLen; ++i)
52 : {
53 1494 : n = ( n << 1 ) + r[i];
54 : }
55 198 : return n;
56 : }
57 :
58 0 : SwBlockName::SwBlockName( const OUString& rShort, const OUString& rLong )
59 : : aShort( rShort ), aLong( rLong ), aPackageName (rShort),
60 0 : bIsOnlyTextFlagInit( false ), bIsOnlyText( false ), bInPutMuchBlocks(false)
61 : {
62 0 : nHashS = SwImpBlocks::Hash( rShort );
63 0 : nHashL = SwImpBlocks::Hash( rLong );
64 0 : }
65 :
66 47 : SwBlockName::SwBlockName( const OUString& rShort, const OUString& rLong, const OUString& rPackageName)
67 : : aShort( rShort ), aLong( rLong ), aPackageName (rPackageName),
68 47 : bIsOnlyTextFlagInit( false ), bIsOnlyText( false ), bInPutMuchBlocks(false)
69 : {
70 47 : nHashS = SwImpBlocks::Hash( rShort );
71 47 : nHashL = SwImpBlocks::Hash( rLong );
72 47 : }
73 :
74 : /**
75 : * Is the provided file a storage or doesn't it exist?
76 : */
77 61 : short SwImpBlocks::GetFileType( const OUString& rFile )
78 : {
79 61 : if( !FStatHelper::IsDocument( rFile ) )
80 2 : return SWBLK_NO_FILE;
81 59 : if( SwXMLTextBlocks::IsFileUCBStorage( rFile ) )
82 59 : return SWBLK_XML;
83 0 : if( SotStorage::IsStorageFile( rFile ) )
84 0 : return SWBLK_SW3;
85 : //otherwise return NONE
86 0 : return SWBLK_NONE;
87 : }
88 :
89 63 : SwImpBlocks::SwImpBlocks( const OUString& rFile, bool )
90 : : aFile( rFile ),
91 : aDateModified( Date::EMPTY ),
92 : aTimeModified( tools::Time::EMPTY ),
93 : pDoc( 0 ), nCur( USHRT_MAX ),
94 : bReadOnly( true ), bInPutMuchBlocks( false ),
95 63 : bInfoChanged(false)
96 : {
97 : FStatHelper::GetModifiedDateTimeOfFile( rFile,
98 63 : &aDateModified, &aTimeModified );
99 63 : INetURLObject aObj(rFile);
100 63 : aObj.setExtension( OUString() );
101 63 : aName = aObj.GetBase();
102 63 : }
103 :
104 126 : SwImpBlocks::~SwImpBlocks()
105 : {
106 63 : aNames.DeleteAndDestroyAll();
107 63 : }
108 :
109 : /**
110 : * Delete the document's content
111 : */
112 0 : void SwImpBlocks::ClearDoc()
113 : {
114 0 : pDoc->ClearDoc();
115 0 : }
116 :
117 : /**
118 : * Creating a PaM, that spans the whole document
119 : */
120 1 : SwPaM* SwImpBlocks::MakePaM()
121 : {
122 1 : SwPaM* pPam = new SwPaM( pDoc->GetNodes().GetEndOfContent() );
123 1 : pPam->Move( fnMoveBackward, fnGoDoc );
124 1 : pPam->SetMark();
125 1 : pPam->Move( fnMoveForward, fnGoDoc );
126 1 : pPam->Exchange();
127 1 : return pPam;
128 : }
129 :
130 44 : sal_uInt16 SwImpBlocks::GetCount() const
131 : {
132 44 : return aNames.size();
133 : }
134 :
135 : /**
136 : * Case Insensitive
137 : */
138 103 : sal_uInt16 SwImpBlocks::GetIndex( const OUString& rShort ) const
139 : {
140 103 : const OUString s( GetAppCharClass().uppercase( rShort ) );
141 103 : const sal_uInt16 nHash = Hash( s );
142 120 : for( size_t i = 0; i < aNames.size(); i++ )
143 : {
144 48 : const SwBlockName* pName = aNames[ i ];
145 96 : if( pName->nHashS == nHash
146 48 : && pName->aShort == s )
147 31 : return i;
148 : }
149 72 : return USHRT_MAX;
150 : }
151 :
152 1 : sal_uInt16 SwImpBlocks::GetLongIndex( const OUString& rLong ) const
153 : {
154 1 : sal_uInt16 nHash = Hash( rLong );
155 2 : for( size_t i = 0; i < aNames.size(); i++ )
156 : {
157 1 : const SwBlockName* pName = aNames[ i ];
158 2 : if( pName->nHashL == nHash
159 1 : && pName->aLong == rLong )
160 0 : return i;
161 : }
162 1 : return USHRT_MAX;
163 : }
164 :
165 19 : OUString SwImpBlocks::GetShortName( sal_uInt16 n ) const
166 : {
167 19 : if( n < aNames.size() )
168 19 : return aNames[n]->aShort;
169 0 : return OUString();
170 : }
171 :
172 15 : OUString SwImpBlocks::GetLongName( sal_uInt16 n ) const
173 : {
174 15 : if( n < aNames.size() )
175 15 : return aNames[n]->aLong;
176 0 : return OUString();
177 : }
178 :
179 16 : OUString SwImpBlocks::GetPackageName( sal_uInt16 n ) const
180 : {
181 16 : if( n < aNames.size() )
182 16 : return aNames[n]->aPackageName;
183 0 : return OUString();
184 : }
185 :
186 0 : void SwImpBlocks::AddName( const OUString& rShort, const OUString& rLong,
187 : bool bOnlyText )
188 : {
189 0 : sal_uInt16 nIdx = GetIndex( rShort );
190 0 : if( nIdx != USHRT_MAX )
191 : {
192 0 : delete aNames[nIdx];
193 0 : aNames.erase( aNames.begin() + nIdx );
194 : }
195 0 : SwBlockName* pNew = new SwBlockName( rShort, rLong );
196 0 : pNew->bIsOnlyTextFlagInit = true;
197 0 : pNew->bIsOnlyText = bOnlyText;
198 0 : aNames.insert( pNew );
199 0 : }
200 :
201 19 : bool SwImpBlocks::IsFileChanged() const
202 : {
203 19 : Date aTempDateModified( aDateModified );
204 19 : tools::Time aTempTimeModified( aTimeModified );
205 38 : return FStatHelper::GetModifiedDateTimeOfFile( aFile, &aTempDateModified, &aTempTimeModified ) &&
206 38 : ( aDateModified != aTempDateModified ||
207 38 : aTimeModified != aTempTimeModified );
208 : }
209 :
210 15 : void SwImpBlocks::Touch()
211 : {
212 15 : FStatHelper::GetModifiedDateTimeOfFile( aFile, &aDateModified, &aTimeModified );
213 15 : }
214 :
215 0 : bool SwImpBlocks::IsOnlyTextBlock( const OUString& ) const
216 : {
217 0 : return false;
218 : }
219 :
220 0 : sal_uLong SwImpBlocks::GetMacroTable( sal_uInt16, SvxMacroTableDtor&, bool )
221 : {
222 0 : return 0;
223 : }
224 :
225 0 : sal_uLong SwImpBlocks::SetMacroTable( sal_uInt16 , const SvxMacroTableDtor& , bool )
226 : {
227 0 : return 0;
228 : }
229 :
230 0 : bool SwImpBlocks::PutMuchEntries( bool )
231 : {
232 0 : return false;
233 : }
234 :
235 61 : SwTextBlocks::SwTextBlocks( const OUString& rFile )
236 61 : : pImp( 0 ), nErr( 0 )
237 : {
238 61 : INetURLObject aObj(rFile);
239 122 : const OUString sFileName = aObj.GetMainURL( INetURLObject::NO_DECODE );
240 61 : switch( SwImpBlocks::GetFileType( rFile ) )
241 : {
242 59 : case SWBLK_XML: pImp = new SwXMLTextBlocks( sFileName ); break;
243 2 : case SWBLK_NO_FILE: pImp = new SwXMLTextBlocks( sFileName ); break;
244 : }
245 61 : if( !pImp )
246 61 : nErr = ERR_SWG_FILE_FORMAT_ERROR;
247 61 : }
248 :
249 61 : SwTextBlocks::~SwTextBlocks()
250 : {
251 61 : delete pImp;
252 61 : }
253 :
254 59 : OUString SwTextBlocks::GetName()
255 : {
256 59 : return pImp ? pImp->aName : OUString();
257 : }
258 :
259 4 : void SwTextBlocks::SetName( const OUString& r )
260 : {
261 4 : if( pImp )
262 4 : pImp->SetName( r );
263 4 : }
264 :
265 0 : bool SwTextBlocks::IsOld() const
266 : {
267 0 : if (pImp)
268 : {
269 0 : short nType = pImp->GetFileType();
270 0 : if (SWBLK_SW3 == nType || SWBLK_SW2 == nType )
271 0 : return true;
272 : }
273 0 : return false;
274 : }
275 :
276 27 : sal_uInt16 SwTextBlocks::GetCount() const
277 : {
278 27 : return pImp ? pImp->GetCount() : 0;
279 : }
280 :
281 33 : sal_uInt16 SwTextBlocks::GetIndex( const OUString& r ) const
282 : {
283 33 : return pImp ? pImp->GetIndex( r ) : USHRT_MAX;
284 : }
285 :
286 1 : sal_uInt16 SwTextBlocks::GetLongIndex( const OUString& r ) const
287 : {
288 1 : return pImp ? pImp->GetLongIndex( r ) : USHRT_MAX;
289 : }
290 :
291 9 : OUString SwTextBlocks::GetShortName( sal_uInt16 n ) const
292 : {
293 9 : if( pImp )
294 9 : return pImp->GetShortName( n );
295 0 : return OUString();
296 : }
297 :
298 5 : OUString SwTextBlocks::GetLongName( sal_uInt16 n ) const
299 : {
300 5 : if( pImp )
301 5 : return pImp->GetLongName( n );
302 0 : return OUString();
303 : }
304 :
305 5 : bool SwTextBlocks::Delete( sal_uInt16 n )
306 : {
307 5 : if( pImp && !pImp->bInPutMuchBlocks )
308 : {
309 5 : if( pImp->IsFileChanged() )
310 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
311 5 : else if( 0 == (nErr = pImp->OpenFile( false ) ))
312 : {
313 5 : nErr = pImp->Delete( n );
314 5 : if( !nErr )
315 : {
316 5 : delete pImp->aNames[n];
317 5 : pImp->aNames.erase( pImp->aNames.begin() + n );
318 : }
319 5 : if( n == pImp->nCur )
320 0 : pImp->nCur = USHRT_MAX;
321 5 : if( !nErr )
322 5 : nErr = pImp->MakeBlockList();
323 : }
324 5 : pImp->CloseFile();
325 5 : pImp->Touch();
326 :
327 5 : return ( nErr == 0 );
328 : }
329 0 : return false;
330 : }
331 :
332 1 : sal_uInt16 SwTextBlocks::Rename( sal_uInt16 n, const OUString* s, const OUString* l )
333 : {
334 1 : sal_uInt16 nIdx = USHRT_MAX;
335 1 : if( pImp && !pImp->bInPutMuchBlocks )
336 : {
337 1 : pImp->nCur = nIdx;
338 1 : OUString aNew;
339 2 : OUString aLong;
340 1 : if( s )
341 1 : aNew = aLong = *s;
342 1 : if( l )
343 1 : aLong = *l;
344 1 : if( aNew.isEmpty() )
345 : {
346 : OSL_ENSURE( false, "No short name provided in the rename" );
347 0 : nErr = ERR_SWG_INTERNAL_ERROR;
348 0 : return USHRT_MAX;
349 : }
350 :
351 1 : if( pImp->IsFileChanged() )
352 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
353 1 : else if( 0 == ( nErr = pImp->OpenFile( false )))
354 : {
355 : // Set the new entry in the list before we do that!
356 1 : aNew = GetAppCharClass().uppercase( aNew );
357 1 : nErr = pImp->Rename( n, aNew, aLong );
358 1 : if( !nErr )
359 : {
360 1 : bool bOnlyText = pImp->aNames[ n ]->bIsOnlyText;
361 1 : delete pImp->aNames[n];
362 1 : pImp->aNames.erase( pImp->aNames.begin() + n );
363 1 : pImp->AddName( aNew, aLong, bOnlyText );
364 1 : nErr = pImp->MakeBlockList();
365 : }
366 : }
367 1 : pImp->CloseFile();
368 1 : pImp->Touch();
369 1 : if( !nErr )
370 2 : nIdx = pImp->GetIndex( aNew );
371 : }
372 1 : return nIdx;
373 : }
374 :
375 0 : sal_uLong SwTextBlocks::CopyBlock( SwTextBlocks& rSource, OUString& rSrcShort,
376 : const OUString& rLong )
377 : {
378 0 : bool bIsOld = false;
379 0 : if (rSource.pImp)
380 : {
381 0 : short nType = rSource.pImp->GetFileType();
382 0 : if (SWBLK_SW2 == nType || SWBLK_SW3 == nType )
383 0 : bIsOld = true;
384 : }
385 0 : if( bIsOld ) //rSource.IsOld() )
386 0 : nErr = ERR_SWG_OLD_GLOSSARY;
387 0 : else if( pImp->bInPutMuchBlocks )
388 0 : nErr = ERR_SWG_INTERNAL_ERROR;
389 : else
390 0 : nErr = pImp->CopyBlock(*rSource.pImp, rSrcShort, rLong);
391 0 : return nErr;
392 : }
393 :
394 6 : bool SwTextBlocks::BeginGetDoc( sal_uInt16 n )
395 : {
396 6 : if( pImp && !pImp->bInPutMuchBlocks )
397 : {
398 6 : if( pImp->IsFileChanged() )
399 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
400 6 : else if( 0 == ( nErr = pImp->OpenFile( true )))
401 : {
402 6 : pImp->ClearDoc();
403 6 : nErr = pImp->GetDoc( n );
404 6 : if( nErr )
405 0 : pImp->nCur = USHRT_MAX;
406 : else
407 6 : pImp->nCur = n;
408 : }
409 6 : return ( nErr == 0 );
410 : }
411 0 : return false;
412 : }
413 :
414 6 : void SwTextBlocks::EndGetDoc()
415 : {
416 6 : if( pImp && !pImp->bInPutMuchBlocks )
417 6 : pImp->CloseFile();
418 6 : }
419 :
420 1 : bool SwTextBlocks::BeginPutDoc( const OUString& s, const OUString& l )
421 : {
422 1 : if( pImp )
423 : {
424 1 : bool bOk = pImp->bInPutMuchBlocks;
425 1 : if( !bOk )
426 : {
427 1 : if( pImp->IsFileChanged() )
428 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
429 : else
430 1 : nErr = pImp->OpenFile( false );
431 1 : bOk = 0 == nErr;
432 : }
433 1 : if( bOk )
434 : {
435 1 : const OUString aNew = GetAppCharClass().uppercase(s);
436 1 : nErr = pImp->BeginPutDoc( aNew, l );
437 : }
438 1 : if( nErr )
439 0 : pImp->CloseFile();
440 : }
441 1 : return 0 == nErr;
442 : }
443 :
444 1 : sal_uInt16 SwTextBlocks::PutDoc()
445 : {
446 1 : sal_uInt16 nIdx = USHRT_MAX;
447 1 : if( pImp )
448 : {
449 1 : nErr = pImp->PutDoc();
450 1 : if( !nErr )
451 : {
452 1 : pImp->nCur = GetIndex( pImp->aShort );
453 1 : if( pImp->nCur != USHRT_MAX )
454 0 : pImp->aNames[ pImp->nCur ]->aLong = pImp->aLong;
455 : else
456 : {
457 1 : pImp->AddName( pImp->aShort, pImp->aLong );
458 1 : pImp->nCur = pImp->GetIndex( pImp->aShort );
459 : }
460 1 : if( !pImp->bInPutMuchBlocks )
461 1 : nErr = pImp->MakeBlockList();
462 : }
463 1 : if( !pImp->bInPutMuchBlocks )
464 : {
465 1 : pImp->CloseFile();
466 1 : pImp->Touch();
467 : }
468 1 : nIdx = pImp->nCur;
469 : }
470 1 : return nIdx;
471 : }
472 :
473 6 : sal_uInt16 SwTextBlocks::PutText( const OUString& rShort, const OUString& rName,
474 : const OUString& rText )
475 : {
476 6 : sal_uInt16 nIdx = USHRT_MAX;
477 6 : if( pImp )
478 : {
479 6 : bool bOk = pImp->bInPutMuchBlocks;
480 6 : if( !bOk )
481 : {
482 6 : if( pImp->IsFileChanged() )
483 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
484 : else
485 6 : nErr = pImp->OpenFile( false );
486 6 : bOk = 0 == nErr;
487 : }
488 6 : if( bOk )
489 : {
490 6 : OUString aNew = GetAppCharClass().uppercase( rShort );
491 6 : nErr = pImp->PutText( aNew, rName, rText );
492 6 : pImp->nCur = USHRT_MAX;
493 6 : if( !nErr )
494 : {
495 6 : nIdx = GetIndex( pImp->aShort );
496 6 : if( nIdx != USHRT_MAX )
497 1 : pImp->aNames[ nIdx ]->aLong = rName;
498 : else
499 : {
500 5 : pImp->AddName( pImp->aShort, rName, true );
501 5 : nIdx = pImp->GetIndex( pImp->aShort );
502 : }
503 6 : if( !pImp->bInPutMuchBlocks )
504 6 : nErr = pImp->MakeBlockList();
505 6 : }
506 : }
507 6 : if( !pImp->bInPutMuchBlocks )
508 : {
509 6 : pImp->CloseFile();
510 6 : pImp->Touch();
511 : }
512 : }
513 6 : return nIdx;
514 : }
515 :
516 13 : SwDoc* SwTextBlocks::GetDoc()
517 : {
518 13 : if( pImp )
519 13 : return pImp->pDoc;
520 0 : return 0;
521 : }
522 :
523 1 : void SwTextBlocks::ClearDoc()
524 : {
525 1 : if( pImp )
526 : {
527 1 : pImp->ClearDoc();
528 1 : pImp->nCur = USHRT_MAX;
529 : }
530 1 : }
531 :
532 0 : OUString SwTextBlocks::GetFileName() const
533 : {
534 0 : return pImp->GetFileName();
535 : }
536 :
537 0 : bool SwTextBlocks::IsReadOnly() const
538 : {
539 0 : return pImp->bReadOnly;
540 : }
541 :
542 4 : bool SwTextBlocks::IsOnlyTextBlock( sal_uInt16 nIdx ) const
543 : {
544 4 : bool bRet = false;
545 4 : if( pImp && !pImp->bInPutMuchBlocks )
546 : {
547 4 : SwBlockName* pBlkNm = pImp->aNames[ nIdx ];
548 8 : if( !pBlkNm->bIsOnlyTextFlagInit &&
549 4 : !pImp->IsFileChanged() && !pImp->OpenFile( true ) )
550 : {
551 0 : pBlkNm->bIsOnlyText = pImp->IsOnlyTextBlock( pBlkNm->aShort );
552 0 : pBlkNm->bIsOnlyTextFlagInit = true;
553 0 : pImp->CloseFile();
554 : }
555 4 : bRet = pBlkNm->bIsOnlyText;
556 : }
557 4 : return bRet;
558 : }
559 :
560 2 : bool SwTextBlocks::IsOnlyTextBlock( const OUString& rShort ) const
561 : {
562 2 : sal_uInt16 nIdx = pImp->GetIndex( rShort );
563 2 : if( USHRT_MAX != nIdx )
564 : {
565 1 : if( pImp->aNames[ nIdx ]->bIsOnlyTextFlagInit )
566 1 : return pImp->aNames[ nIdx ]->bIsOnlyText;
567 0 : return IsOnlyTextBlock( nIdx );
568 : }
569 :
570 : OSL_ENSURE( false, "Invalid name" );
571 1 : return false;
572 : }
573 :
574 1 : bool SwTextBlocks::GetMacroTable( sal_uInt16 nIdx, SvxMacroTableDtor& rMacroTable )
575 : {
576 1 : bool bRet = true;
577 1 : if ( pImp && !pImp->bInPutMuchBlocks )
578 1 : bRet = ( 0 == pImp->GetMacroTable( nIdx, rMacroTable ) );
579 1 : return bRet;
580 : }
581 :
582 0 : bool SwTextBlocks::SetMacroTable( sal_uInt16 nIdx, const SvxMacroTableDtor& rMacroTable )
583 : {
584 0 : bool bRet = true;
585 0 : if ( pImp && !pImp->bInPutMuchBlocks )
586 0 : bRet = ( 0 == pImp->SetMacroTable( nIdx, rMacroTable ) );
587 0 : return bRet;
588 : }
589 :
590 0 : bool SwTextBlocks::StartPutMuchBlockEntries()
591 : {
592 0 : bool bRet = false;
593 0 : if( !IsOld() && pImp )
594 0 : bRet = pImp->PutMuchEntries( true );
595 0 : return bRet;
596 : }
597 :
598 0 : void SwTextBlocks::EndPutMuchBlockEntries()
599 : {
600 0 : if( pImp )
601 0 : pImp->PutMuchEntries( false );
602 0 : }
603 :
604 0 : OUString SwTextBlocks::GetBaseURL() const
605 : {
606 0 : if(pImp)
607 0 : return pImp->GetBaseURL();
608 0 : return OUString();
609 : }
610 :
611 7 : void SwTextBlocks::SetBaseURL( const OUString& rURL )
612 : {
613 7 : if(pImp)
614 7 : pImp->SetBaseURL(rURL);
615 184 : }
616 :
617 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|