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 356 : sal_uInt16 SwImpBlocks::Hash( const OUString& r )
47 : {
48 356 : sal_uInt16 n = 0;
49 : // std::min requires an explicit cast to sal_Int32 on 32bit platforms
50 356 : const sal_Int32 nLen = std::min(r.getLength(), static_cast<sal_Int32>(8));
51 3204 : for (sal_Int32 i=0; i<nLen; ++i)
52 : {
53 2848 : n = ( n << 1 ) + r[i];
54 : }
55 356 : return n;
56 : }
57 :
58 0 : SwBlockName::SwBlockName( const OUString& rShort, const OUString& rLong )
59 : : aShort( rShort ), aLong( rLong ), aPackageName (rShort),
60 0 : bIsOnlyTxtFlagInit( false ), bIsOnlyTxt( false ), bInPutMuchBlocks(false)
61 : {
62 0 : nHashS = SwImpBlocks::Hash( rShort );
63 0 : nHashL = SwImpBlocks::Hash( rLong );
64 0 : }
65 :
66 82 : SwBlockName::SwBlockName( const OUString& rShort, const OUString& rLong, const OUString& rPackageName)
67 : : aShort( rShort ), aLong( rLong ), aPackageName (rPackageName),
68 82 : bIsOnlyTxtFlagInit( false ), bIsOnlyTxt( false ), bInPutMuchBlocks(false)
69 : {
70 82 : nHashS = SwImpBlocks::Hash( rShort );
71 82 : nHashL = SwImpBlocks::Hash( rLong );
72 82 : }
73 :
74 : /**
75 : * Is the provided file a storage or doesn't it exist?
76 : */
77 118 : short SwImpBlocks::GetFileType( const OUString& rFile )
78 : {
79 118 : if( !FStatHelper::IsDocument( rFile ) )
80 4 : return SWBLK_NO_FILE;
81 114 : if( SwXMLTextBlocks::IsFileUCBStorage( rFile ) )
82 114 : return SWBLK_XML;
83 0 : if( SvStorage::IsStorageFile( rFile ) )
84 0 : return SWBLK_SW3;
85 : //otherwise return NONE
86 0 : return SWBLK_NONE;
87 : }
88 :
89 118 : 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 118 : bInfoChanged(false)
96 : {
97 : FStatHelper::GetModifiedDateTimeOfFile( rFile,
98 118 : &aDateModified, &aTimeModified );
99 118 : INetURLObject aObj(rFile);
100 118 : aObj.setExtension( OUString() );
101 118 : aName = aObj.GetBase();
102 118 : }
103 :
104 236 : SwImpBlocks::~SwImpBlocks()
105 : {
106 118 : aNames.DeleteAndDestroyAll();
107 118 : }
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 2 : SwPaM* SwImpBlocks::MakePaM()
121 : {
122 2 : SwPaM* pPam = new SwPaM( pDoc->GetNodes().GetEndOfContent() );
123 2 : pPam->Move( fnMoveBackward, fnGoDoc );
124 2 : pPam->SetMark();
125 2 : pPam->Move( fnMoveForward, fnGoDoc );
126 2 : pPam->Exchange();
127 2 : return pPam;
128 : }
129 :
130 88 : sal_uInt16 SwImpBlocks::GetCount() const
131 : {
132 88 : return aNames.size();
133 : }
134 :
135 : /**
136 : * Case Insensitive
137 : */
138 190 : sal_uInt16 SwImpBlocks::GetIndex( const OUString& rShort ) const
139 : {
140 190 : const OUString s( GetAppCharClass().uppercase( rShort ) );
141 190 : const sal_uInt16 nHash = Hash( s );
142 216 : for( sal_uInt16 i = 0; i < aNames.size(); i++ )
143 : {
144 84 : const SwBlockName* pName = aNames[ i ];
145 168 : if( pName->nHashS == nHash
146 84 : && pName->aShort == s )
147 58 : return i;
148 : }
149 132 : return USHRT_MAX;
150 : }
151 :
152 2 : sal_uInt16 SwImpBlocks::GetLongIndex( const OUString& rLong ) const
153 : {
154 2 : sal_uInt16 nHash = Hash( rLong );
155 4 : for( sal_uInt16 i = 0; i < aNames.size(); i++ )
156 : {
157 2 : const SwBlockName* pName = aNames[ i ];
158 4 : if( pName->nHashL == nHash
159 2 : && pName->aLong == rLong )
160 0 : return i;
161 : }
162 2 : return USHRT_MAX;
163 : }
164 :
165 38 : OUString SwImpBlocks::GetShortName( sal_uInt16 n ) const
166 : {
167 38 : if( n < aNames.size() )
168 38 : return aNames[n]->aShort;
169 0 : return OUString();
170 : }
171 :
172 30 : OUString SwImpBlocks::GetLongName( sal_uInt16 n ) const
173 : {
174 30 : if( n < aNames.size() )
175 30 : return aNames[n]->aLong;
176 0 : return OUString();
177 : }
178 :
179 28 : OUString SwImpBlocks::GetPackageName( sal_uInt16 n ) const
180 : {
181 28 : if( n < aNames.size() )
182 28 : return aNames[n]->aPackageName;
183 0 : return OUString();
184 : }
185 :
186 0 : void SwImpBlocks::AddName( const OUString& rShort, const OUString& rLong,
187 : bool bOnlyTxt )
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->bIsOnlyTxtFlagInit = true;
197 0 : pNew->bIsOnlyTxt = bOnlyTxt;
198 0 : aNames.insert( pNew );
199 0 : }
200 :
201 34 : bool SwImpBlocks::IsFileChanged() const
202 : {
203 34 : Date aTempDateModified( aDateModified );
204 34 : tools::Time aTempTimeModified( aTimeModified );
205 68 : return FStatHelper::GetModifiedDateTimeOfFile( aFile, &aTempDateModified, &aTempTimeModified ) &&
206 68 : ( aDateModified != aTempDateModified ||
207 68 : aTimeModified != aTempTimeModified );
208 : }
209 :
210 30 : void SwImpBlocks::Touch()
211 : {
212 30 : FStatHelper::GetModifiedDateTimeOfFile( aFile, &aDateModified, &aTimeModified );
213 30 : }
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 118 : SwTextBlocks::SwTextBlocks( const OUString& rFile )
236 118 : : pImp( 0 ), nErr( 0 )
237 : {
238 118 : INetURLObject aObj(rFile);
239 236 : const OUString sFileName = aObj.GetMainURL( INetURLObject::NO_DECODE );
240 118 : switch( SwImpBlocks::GetFileType( rFile ) )
241 : {
242 114 : case SWBLK_XML: pImp = new SwXMLTextBlocks( sFileName ); break;
243 4 : case SWBLK_NO_FILE: pImp = new SwXMLTextBlocks( sFileName ); break;
244 : }
245 118 : if( !pImp )
246 118 : nErr = ERR_SWG_FILE_FORMAT_ERROR;
247 118 : }
248 :
249 118 : SwTextBlocks::~SwTextBlocks()
250 : {
251 118 : delete pImp;
252 118 : }
253 :
254 118 : OUString SwTextBlocks::GetName()
255 : {
256 118 : return pImp ? pImp->aName : OUString();
257 : }
258 :
259 8 : void SwTextBlocks::SetName( const OUString& r )
260 : {
261 8 : if( pImp )
262 8 : pImp->SetName( r );
263 8 : }
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 54 : sal_uInt16 SwTextBlocks::GetCount() const
277 : {
278 54 : return pImp ? pImp->GetCount() : 0;
279 : }
280 :
281 62 : sal_uInt16 SwTextBlocks::GetIndex( const OUString& r ) const
282 : {
283 62 : return pImp ? pImp->GetIndex( r ) : USHRT_MAX;
284 : }
285 :
286 2 : sal_uInt16 SwTextBlocks::GetLongIndex( const OUString& r ) const
287 : {
288 2 : return pImp ? pImp->GetLongIndex( r ) : USHRT_MAX;
289 : }
290 :
291 18 : OUString SwTextBlocks::GetShortName( sal_uInt16 n ) const
292 : {
293 18 : if( pImp )
294 18 : return pImp->GetShortName( n );
295 0 : return OUString();
296 : }
297 :
298 10 : OUString SwTextBlocks::GetLongName( sal_uInt16 n ) const
299 : {
300 10 : if( pImp )
301 10 : return pImp->GetLongName( n );
302 0 : return OUString();
303 : }
304 :
305 10 : bool SwTextBlocks::Delete( sal_uInt16 n )
306 : {
307 10 : if( pImp && !pImp->bInPutMuchBlocks )
308 : {
309 10 : if( pImp->IsFileChanged() )
310 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
311 10 : else if( 0 == (nErr = pImp->OpenFile( false ) ))
312 : {
313 10 : nErr = pImp->Delete( n );
314 10 : if( !nErr )
315 : {
316 10 : delete pImp->aNames[n];
317 10 : pImp->aNames.erase( pImp->aNames.begin() + n );
318 : }
319 10 : if( n == pImp->nCur )
320 0 : pImp->nCur = USHRT_MAX;
321 10 : if( !nErr )
322 10 : nErr = pImp->MakeBlockList();
323 : }
324 10 : pImp->CloseFile();
325 10 : pImp->Touch();
326 :
327 10 : return ( nErr == 0 );
328 : }
329 0 : return false;
330 : }
331 :
332 2 : sal_uInt16 SwTextBlocks::Rename( sal_uInt16 n, const OUString* s, const OUString* l )
333 : {
334 2 : sal_uInt16 nIdx = USHRT_MAX;
335 2 : if( pImp && !pImp->bInPutMuchBlocks )
336 : {
337 2 : pImp->nCur = nIdx;
338 2 : OUString aNew;
339 4 : OUString aLong;
340 2 : if( s )
341 2 : aNew = aLong = *s;
342 2 : if( l )
343 2 : aLong = *l;
344 2 : 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 2 : if( pImp->IsFileChanged() )
352 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
353 2 : else if( 0 == ( nErr = pImp->OpenFile( false )))
354 : {
355 : // Set the new entry in the list before we do that!
356 2 : aNew = GetAppCharClass().uppercase( aNew );
357 2 : nErr = pImp->Rename( n, aNew, aLong );
358 2 : if( !nErr )
359 : {
360 2 : bool bOnlyTxt = pImp->aNames[ n ]->bIsOnlyTxt;
361 2 : delete pImp->aNames[n];
362 2 : pImp->aNames.erase( pImp->aNames.begin() + n );
363 2 : pImp->AddName( aNew, aLong, bOnlyTxt );
364 2 : nErr = pImp->MakeBlockList();
365 : }
366 : }
367 2 : pImp->CloseFile();
368 2 : pImp->Touch();
369 2 : if( !nErr )
370 4 : nIdx = pImp->GetIndex( aNew );
371 : }
372 2 : 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 8 : bool SwTextBlocks::BeginGetDoc( sal_uInt16 n )
395 : {
396 8 : if( pImp && !pImp->bInPutMuchBlocks )
397 : {
398 8 : if( pImp->IsFileChanged() )
399 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
400 8 : else if( 0 == ( nErr = pImp->OpenFile( true )))
401 : {
402 8 : pImp->ClearDoc();
403 8 : nErr = pImp->GetDoc( n );
404 8 : if( nErr )
405 0 : pImp->nCur = USHRT_MAX;
406 : else
407 8 : pImp->nCur = n;
408 : }
409 8 : return ( nErr == 0 );
410 : }
411 0 : return false;
412 : }
413 :
414 8 : void SwTextBlocks::EndGetDoc()
415 : {
416 8 : if( pImp && !pImp->bInPutMuchBlocks )
417 8 : pImp->CloseFile();
418 8 : }
419 :
420 2 : bool SwTextBlocks::BeginPutDoc( const OUString& s, const OUString& l )
421 : {
422 2 : if( pImp )
423 : {
424 2 : bool bOk = pImp->bInPutMuchBlocks;
425 2 : if( !bOk )
426 : {
427 2 : if( pImp->IsFileChanged() )
428 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
429 : else
430 2 : nErr = pImp->OpenFile( false );
431 2 : bOk = 0 == nErr;
432 : }
433 2 : if( bOk )
434 : {
435 2 : const OUString aNew = GetAppCharClass().uppercase(s);
436 2 : nErr = pImp->BeginPutDoc( aNew, l );
437 : }
438 2 : if( nErr )
439 0 : pImp->CloseFile();
440 : }
441 2 : return 0 == nErr;
442 : }
443 :
444 2 : sal_uInt16 SwTextBlocks::PutDoc()
445 : {
446 2 : sal_uInt16 nIdx = USHRT_MAX;
447 2 : if( pImp )
448 : {
449 2 : nErr = pImp->PutDoc();
450 2 : if( !nErr )
451 : {
452 2 : pImp->nCur = GetIndex( pImp->aShort );
453 2 : if( pImp->nCur != USHRT_MAX )
454 0 : pImp->aNames[ pImp->nCur ]->aLong = pImp->aLong;
455 : else
456 : {
457 2 : pImp->AddName( pImp->aShort, pImp->aLong );
458 2 : pImp->nCur = pImp->GetIndex( pImp->aShort );
459 : }
460 2 : if( !pImp->bInPutMuchBlocks )
461 2 : nErr = pImp->MakeBlockList();
462 : }
463 2 : if( !pImp->bInPutMuchBlocks )
464 : {
465 2 : pImp->CloseFile();
466 2 : pImp->Touch();
467 : }
468 2 : nIdx = pImp->nCur;
469 : }
470 2 : return nIdx;
471 : }
472 :
473 12 : sal_uInt16 SwTextBlocks::PutText( const OUString& rShort, const OUString& rName,
474 : const OUString& rTxt )
475 : {
476 12 : sal_uInt16 nIdx = USHRT_MAX;
477 12 : if( pImp )
478 : {
479 12 : bool bOk = pImp->bInPutMuchBlocks;
480 12 : if( !bOk )
481 : {
482 12 : if( pImp->IsFileChanged() )
483 0 : nErr = ERR_TXTBLOCK_NEWFILE_ERROR;
484 : else
485 12 : nErr = pImp->OpenFile( false );
486 12 : bOk = 0 == nErr;
487 : }
488 12 : if( bOk )
489 : {
490 12 : OUString aNew = GetAppCharClass().uppercase( rShort );
491 12 : nErr = pImp->PutText( aNew, rName, rTxt );
492 12 : pImp->nCur = USHRT_MAX;
493 12 : if( !nErr )
494 : {
495 12 : nIdx = GetIndex( pImp->aShort );
496 12 : if( nIdx != USHRT_MAX )
497 2 : pImp->aNames[ nIdx ]->aLong = rName;
498 : else
499 : {
500 10 : pImp->AddName( pImp->aShort, rName, true );
501 10 : nIdx = pImp->GetIndex( pImp->aShort );
502 : }
503 12 : if( !pImp->bInPutMuchBlocks )
504 12 : nErr = pImp->MakeBlockList();
505 12 : }
506 : }
507 12 : if( !pImp->bInPutMuchBlocks )
508 : {
509 12 : pImp->CloseFile();
510 12 : pImp->Touch();
511 : }
512 : }
513 12 : return nIdx;
514 : }
515 :
516 22 : SwDoc* SwTextBlocks::GetDoc()
517 : {
518 22 : if( pImp )
519 22 : return pImp->pDoc;
520 0 : return 0;
521 : }
522 :
523 2 : void SwTextBlocks::ClearDoc()
524 : {
525 2 : if( pImp )
526 : {
527 2 : pImp->ClearDoc();
528 2 : pImp->nCur = USHRT_MAX;
529 : }
530 2 : }
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 8 : bool SwTextBlocks::IsOnlyTextBlock( sal_uInt16 nIdx ) const
543 : {
544 8 : bool bRet = false;
545 8 : if( pImp && !pImp->bInPutMuchBlocks )
546 : {
547 8 : SwBlockName* pBlkNm = const_cast<SwBlockName*>( pImp->aNames[ nIdx ] );
548 16 : if( !pBlkNm->bIsOnlyTxtFlagInit &&
549 8 : !pImp->IsFileChanged() && !pImp->OpenFile( true ) )
550 : {
551 0 : pBlkNm->bIsOnlyTxt = pImp->IsOnlyTextBlock( pBlkNm->aShort );
552 0 : pBlkNm->bIsOnlyTxtFlagInit = true;
553 0 : pImp->CloseFile();
554 : }
555 8 : bRet = pBlkNm->bIsOnlyTxt;
556 : }
557 8 : return bRet;
558 : }
559 :
560 4 : bool SwTextBlocks::IsOnlyTextBlock( const OUString& rShort ) const
561 : {
562 4 : sal_uInt16 nIdx = pImp->GetIndex( rShort );
563 4 : if( USHRT_MAX != nIdx )
564 : {
565 2 : if( pImp->aNames[ nIdx ]->bIsOnlyTxtFlagInit )
566 2 : return pImp->aNames[ nIdx ]->bIsOnlyTxt;
567 0 : return IsOnlyTextBlock( nIdx );
568 : }
569 :
570 : OSL_ENSURE( false, "Invalid name" );
571 2 : return false;
572 : }
573 :
574 2 : bool SwTextBlocks::GetMacroTable( sal_uInt16 nIdx, SvxMacroTableDtor& rMacroTbl )
575 : {
576 2 : bool bRet = true;
577 2 : if ( pImp && !pImp->bInPutMuchBlocks )
578 2 : bRet = ( 0 == pImp->GetMacroTable( nIdx, rMacroTbl ) );
579 2 : return bRet;
580 : }
581 :
582 0 : bool SwTextBlocks::SetMacroTable( sal_uInt16 nIdx, const SvxMacroTableDtor& rMacroTbl )
583 : {
584 0 : bool bRet = true;
585 0 : if ( pImp && !pImp->bInPutMuchBlocks )
586 0 : bRet = ( 0 == pImp->SetMacroTable( nIdx, rMacroTbl ) );
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 14 : void SwTextBlocks::SetBaseURL( const OUString& rURL )
612 : {
613 14 : if(pImp)
614 14 : pImp->SetBaseURL(rURL);
615 284 : }
616 :
617 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|