xref: /aoo41x/main/sfx2/source/doc/doctempl.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 
31 #include <limits.h>
32 #include <com/sun/star/uno/Any.h>
33 #include <vos/mutex.hxx>
34 #include <vos/thread.hxx>
35 
36 #ifndef _SV_RESARY_HXX
37 #include <tools/resary.hxx>
38 #endif
39 #include <vcl/svapp.hxx>
40 #include <vcl/settings.hxx>
41 #include <unotools/localedatawrapper.hxx>
42 #include <unotools/pathoptions.hxx>
43 #include <tools/string.hxx>
44 #include <tools/urlobj.hxx>
45 #include <svtools/ehdl.hxx>
46 #include <svtools/sfxecode.hxx>
47 #include <comphelper/processfactory.hxx>
48 #include <ucbhelper/content.hxx>
49 #include <com/sun/star/beans/PropertyAttribute.hpp>
50 #include <com/sun/star/beans/PropertyValue.hpp>
51 #include <com/sun/star/beans/XPropertyContainer.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/beans/XPropertySetInfo.hpp>
54 #include <com/sun/star/document/XTypeDetection.hpp>
55 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
56 #include <com/sun/star/frame/XComponentLoader.hpp>
57 #include <com/sun/star/frame/XDocumentTemplates.hpp>
58 #include <com/sun/star/io/XInputStream.hpp>
59 #include <com/sun/star/io/XPersist.hpp>
60 #include <com/sun/star/lang/XLocalizable.hpp>
61 #include <com/sun/star/sdbc/XResultSet.hpp>
62 #include <com/sun/star/sdbc/XRow.hpp>
63 #include <com/sun/star/ucb/ContentInfo.hpp>
64 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
65 #include <com/sun/star/ucb/NameClash.hpp>
66 #include <com/sun/star/ucb/TransferInfo.hpp>
67 #include <com/sun/star/ucb/XCommandProcessor.hpp>
68 #include <com/sun/star/ucb/XContent.hpp>
69 #include <com/sun/star/ucb/XContentAccess.hpp>
70 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
71 #include <com/sun/star/ucb/XAnyCompare.hpp>
72 #include <com/sun/star/ucb/NumberedSortingInfo.hpp>
73 #include <com/sun/star/embed/ElementModes.hpp>
74 #include <com/sun/star/embed/XTransactedObject.hpp>
75 
76 #include "sfxurlrelocator.hxx"
77 
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::beans;
80 using namespace ::com::sun::star::frame;
81 using namespace ::com::sun::star::io;
82 using namespace ::com::sun::star::lang;
83 using namespace ::com::sun::star::sdbc;
84 using namespace ::com::sun::star::uno;
85 using namespace ::com::sun::star::ucb;
86 using namespace ::com::sun::star::document;
87 using namespace ::rtl;
88 using namespace ::ucbhelper;
89 
90 
91 #include <sfx2/doctempl.hxx>
92 #include <sfx2/docfac.hxx>
93 #include <sfx2/docfile.hxx>
94 #include <sfx2/objsh.hxx>
95 #include "sfxtypes.hxx"
96 #include <sfx2/app.hxx>
97 #include "sfx2/sfxresid.hxx"
98 #include "doc.hrc"
99 #include <sfx2/fcontnr.hxx>
100 #include <svtools/templatefoldercache.hxx>
101 
102 #include <comphelper/storagehelper.hxx>
103 #include <unotools/ucbhelper.hxx>
104 
105 //========================================================================
106 
107 // #define DONT_USE_HIERARCHY
108 
109 #define TITLE                   "Title"
110 #define IS_FOLDER               "IsFolder"
111 #define PROPERTY_TYPE           "TypeDescription"
112 #define TARGET_URL              "TargetURL"
113 #define TYPE_FOLDER             "application/vnd.sun.star.hier-folder"
114 #define TYPE_LINK               "application/vnd.sun.star.hier-link"
115 #define TYPE_FSYS_FOLDER        "application/vnd.sun.staroffice.fsys-folder"
116 
117 #define TARGET_DIR_URL          "TargetDirURL"
118 #define COMMAND_DELETE          "delete"
119 #define COMMAND_TRANSFER        "transfer"
120 
121 #define STANDARD_FOLDER         "standard"
122 
123 #define SERVICENAME_TYPEDETECTION       "com.sun.star.document.TypeDetection"
124 #define TYPEDETECTION_PARAMETER         "FileName"
125 //#define SERVICENAME_OLD_TYPEDETECTION   "com.sun.star.frame.FrameLoaderFactory"
126 //#define PARAMETER_OLD_TYPEDETECTION     "DeepDetection"
127 #define SERVICENAME_DOCINFO             "com.sun.star.document.DocumentProperties"
128 #define SERVICENAME_DOCTEMPLATES        "com.sun.star.frame.DocumentTemplates"
129 #define SERVICENAME_DESKTOP             "com.sun.star.frame.Desktop"
130 
131 //========================================================================
132 
133 class RegionData_Impl;
134 
135 namespace DocTempl {
136 
137 class DocTempl_EntryData_Impl
138 {
139     RegionData_Impl*    mpParent;
140 
141     // the following member must be SfxObjectShellLock since it controlls that SfxObjectShell lifetime by design
142     // and users of this class expect it to be so.
143     SfxObjectShellLock  mxObjShell;
144 
145     OUString            maTitle;
146     OUString            maOwnURL;
147     OUString            maTargetURL;
148     sal_Bool            mbIsOwner   : 1;
149     sal_Bool            mbDidConvert: 1;
150 
151 private:
152     RegionData_Impl*    GetParent() const { return mpParent; }
153 
154 public:
155                         DocTempl_EntryData_Impl( RegionData_Impl* pParent,
156                                         const OUString& rTitle );
157 
158     const OUString&     GetTitle() const { return maTitle; }
159     const OUString&     GetTargetURL();
160     const OUString&     GetHierarchyURL();
161 
162     void                SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
163     void                SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
164     void                SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
165 
166     int                 Compare( const OUString& rTitle ) const;
167 
168     SfxObjectShellRef   CreateObjectShell();
169     sal_Bool                DeleteObjectShell();
170 };
171 
172 }
173 
174 using namespace ::DocTempl;
175 
176 // ------------------------------------------------------------------------
177 
178 class RegionData_Impl
179 {
180     DECLARE_LIST( EntryList_Impl, DocTempl_EntryData_Impl* )
181     const SfxDocTemplate_Impl*  mpParent;
182     EntryList_Impl              maEntries;
183     OUString                    maTitle;
184     OUString                    maOwnURL;
185     OUString                    maTargetURL;
186 
187 private:
188     long                        GetEntryPos( const OUString& rTitle,
189                                              sal_Bool& rFound ) const;
190     const SfxDocTemplate_Impl*  GetParent() const { return mpParent; }
191 
192 public:
193                         RegionData_Impl( const SfxDocTemplate_Impl* pParent,
194                                          const OUString& rTitle );
195                         ~RegionData_Impl();
196 
197     void                SetTargetURL( const OUString& rURL ) { maTargetURL = rURL; }
198     void                SetHierarchyURL( const OUString& rURL) { maOwnURL = rURL; }
199 
200     DocTempl_EntryData_Impl*     GetEntry( sal_uIntPtr nIndex ) const;
201     DocTempl_EntryData_Impl*     GetEntry( const OUString& rName ) const;
202     DocTempl_EntryData_Impl*     GetByTargetURL( const OUString& rName ) const;
203 
204     const OUString&     GetTitle() const { return maTitle; }
205     const OUString&     GetTargetURL();
206     const OUString&     GetHierarchyURL();
207 
208     sal_uIntPtr               GetCount() const;
209 
210     void                SetTitle( const OUString& rTitle ) { maTitle = rTitle; }
211 
212     void                AddEntry( const OUString& rTitle,
213                                   const OUString& rTargetURL,
214                                   sal_uInt16 *pPos = NULL );
215     void                DeleteEntry( sal_uIntPtr nIndex );
216 
217     int                 Compare( const OUString& rTitle ) const
218                             { return maTitle.compareTo( rTitle ); }
219     int                 Compare( RegionData_Impl* pCompareWith ) const;
220 };
221 
222 DECLARE_LIST( RegionList_Impl, RegionData_Impl* )
223 
224 // ------------------------------------------------------------------------
225 
226 class SfxDocTemplate_Impl : public SvRefBase
227 {
228     uno::Reference< XPersist >               mxInfo;
229     uno::Reference< XDocumentTemplates >     mxTemplates;
230 
231     ::osl::Mutex        maMutex;
232     OUString            maRootURL;
233     OUString            maStandardGroup;
234     RegionList_Impl     maRegions;
235     sal_Bool            mbConstructed;
236 
237     uno::Reference< XAnyCompareFactory > m_rCompareFactory;
238 
239     // the following member is intended to prevent clearing of the global data when it is in use
240     // TODO/LATER: it still does not make the implementation complete thread-safe
241     sal_Int32           mnLockCounter;
242 
243 private:
244     void                Clear();
245 
246 public:
247                         SfxDocTemplate_Impl();
248                         ~SfxDocTemplate_Impl();
249 
250     void                IncrementLock();
251     void                DecrementLock();
252 
253     sal_Bool            Construct( );
254     void                CreateFromHierarchy( Content &rTemplRoot );
255     void                ReInitFromComponent();
256     void                AddRegion( const OUString& rTitle,
257                                    Content& rContent );
258 
259     void                Rescan();
260 
261     void                DeleteRegion( sal_uIntPtr nIndex );
262 
263     sal_uIntPtr               GetRegionCount() const
264                             { return maRegions.Count(); }
265     RegionData_Impl*    GetRegion( const OUString& rName ) const;
266     RegionData_Impl*    GetRegion( sal_uIntPtr nIndex ) const;
267     void                GetTemplates( Content& rTargetFolder,
268                                       Content& rParentFolder,
269                                       RegionData_Impl* pRegion );
270 
271     long                GetRegionPos( const OUString& rTitle,
272                                       sal_Bool& rFound ) const;
273 
274     sal_Bool            GetTitleFromURL( const OUString& rURL, OUString& aTitle );
275     sal_Bool            InsertRegion( RegionData_Impl *pData, sal_uIntPtr nPos = LIST_APPEND );
276     OUString            GetRootURL() const { return maRootURL; }
277 
278     uno::Reference< XDocumentTemplates >     getDocTemplates() { return mxTemplates; }
279 };
280 
281 // ------------------------------------------------------------------------
282 
283 class DocTemplLocker_Impl
284 {
285     SfxDocTemplate_Impl& m_aDocTempl;
286 public:
287     DocTemplLocker_Impl( SfxDocTemplate_Impl& aDocTempl )
288     : m_aDocTempl( aDocTempl )
289     {
290         m_aDocTempl.IncrementLock();
291     }
292 
293     ~DocTemplLocker_Impl()
294     {
295         m_aDocTempl.DecrementLock();
296     }
297 };
298 
299 // ------------------------------------------------------------------------
300 
301 #ifndef SFX_DECL_DOCTEMPLATES_DEFINED
302 #define SFX_DECL_DOCTEMPLATES_DEFINED
303 SV_DECL_REF(SfxDocTemplate_Impl)
304 #endif
305 
306 SV_IMPL_REF(SfxDocTemplate_Impl)
307 
308 // ------------------------------------------------------------------------
309 
310 SfxDocTemplate_Impl *gpTemplateData = 0;
311 
312 // -----------------------------------------------------------------------
313 
314 static sal_Bool getTextProperty_Impl( Content& rContent,
315                                       const OUString& rPropName,
316                                       OUString& rPropValue );
317 
318 //========================================================================
319 //========================================================================
320 //========================================================================
321 
322 String SfxDocumentTemplates::GetFullRegionName
323 (
324     sal_uInt16 nIdx                     // Index des Bereiches
325 )   const
326 
327 /*  [Beschreibung]
328 
329     Liefert den logischen Namen eines Bereiches Plus seinem  Pfad
330 
331 
332     [R"uckgabewert]                 Referenz auf diesen Namen
333 
334 */
335 
336 {
337     // First: find the RegionData for the index
338     String aName;
339 
340     DocTemplLocker_Impl aLocker( *pImp );
341 
342     if ( pImp->Construct() )
343     {
344         RegionData_Impl *pData1 = pImp->GetRegion( nIdx );
345 
346         if ( pData1 )
347             aName = pData1->GetTitle();
348 
349         // --**-- here was some code which appended the path to the
350         //      group if there was more than one with the same name.
351         //      this should not happen anymore
352     }
353 
354     return aName;
355 }
356 
357 //------------------------------------------------------------------------
358 
359 const String& SfxDocumentTemplates::GetRegionName
360 (
361     sal_uInt16 nIdx                 // Index des Bereiches
362 )   const
363 
364 /*  [Beschreibung]
365 
366     Liefert den logischen Namen eines Bereiches
367 
368 
369     [R"uckgabewert]
370 
371     const String&                   Referenz auf diesen Namen
372 
373 */
374 {
375     static String maTmpString;
376 
377     DocTemplLocker_Impl aLocker( *pImp );
378 
379     if ( pImp->Construct() )
380     {
381         RegionData_Impl *pData = pImp->GetRegion( nIdx );
382 
383         if ( pData )
384             maTmpString = pData->GetTitle();
385         else
386             maTmpString.Erase();
387     }
388     else
389         maTmpString.Erase();
390 
391     return maTmpString;
392 }
393 
394 
395 //------------------------------------------------------------------------
396 
397 sal_uInt16 SfxDocumentTemplates::GetRegionNo
398 (
399     const String &rRegion       // Name der Region
400 )   const
401 
402 /*  [Beschreibung]
403 
404     Liefert den Index f"ur einen logischen Namen eines Bereiches.
405 
406 
407     [R"uckgabewert]
408 
409     sal_uInt16          Index von 'rRegion' oder USHRT_MAX falls unbekannt
410 
411 */
412 {
413     DocTemplLocker_Impl aLocker( *pImp );
414 
415     if ( !pImp->Construct() )
416         return USHRT_MAX;
417 
418     sal_Bool    bFound;
419     sal_uIntPtr       nIndex = pImp->GetRegionPos( rRegion, bFound );
420 
421     if ( bFound )
422         return (sal_uInt16) nIndex;
423     else
424         return USHRT_MAX;
425 }
426 
427 
428 //------------------------------------------------------------------------
429 
430 sal_uInt16 SfxDocumentTemplates::GetRegionCount() const
431 
432 /*  [Beschreibung]
433 
434     Liefert die Anzahl der Bereiche
435 
436 
437     [R"uckgabewert]
438 
439     sal_uInt16                  Anzahl der Bereiche
440 
441 */
442 {
443     DocTemplLocker_Impl aLocker( *pImp );
444 
445     if ( !pImp->Construct() )
446         return 0;
447 
448     sal_uIntPtr nCount = pImp->GetRegionCount();
449 
450     return (sal_uInt16) nCount;
451 }
452 
453 //------------------------------------------------------------------------
454 
455 sal_Bool SfxDocumentTemplates::IsRegionLoaded( sal_uInt16 nIdx ) const
456 {
457     DocTemplLocker_Impl aLocker( *pImp );
458 
459     if ( !pImp->Construct() )
460         return sal_False;
461 
462     RegionData_Impl *pData = pImp->GetRegion( nIdx );
463 
464     if ( pData )
465         return sal_True;
466     else
467         return sal_False;
468 }
469 
470 //------------------------------------------------------------------------
471 
472 sal_uInt16 SfxDocumentTemplates::GetCount
473 (
474     const String&   rName   /*  Name des Bereiches, dessen Eintrags-
475                                 anzahl ermittelt werden soll */
476 
477 )   const
478 
479 /*  [Beschreibung]
480 
481     Liefert die Anzahl der Eintr"age eines Bereiches
482 
483 
484     [R"uckgabewert]
485 
486     USHORT                      Anzahl der Eintr"age
487 
488 */
489 
490 {
491     DocTemplLocker_Impl aLocker( *pImp );
492 
493     if ( !pImp->Construct() )
494         return 0;
495 
496     RegionData_Impl *pData = pImp->GetRegion( rName );
497     sal_uIntPtr            nCount = 0;
498 
499     if ( pData )
500         nCount = pData->GetCount();
501 
502     return (sal_uInt16) nCount;
503 }
504 
505 //------------------------------------------------------------------------
506 
507 sal_uInt16 SfxDocumentTemplates::GetCount
508 (
509     sal_uInt16 nRegion              /*  Index des Bereiches, dessen Eintrags-
510                                     anzahl ermittelt werden soll */
511 
512 )   const
513 
514 /*  [Beschreibung]
515 
516     Liefert die Anzahl der Eintr"age eines Bereiches
517 
518 
519     [R"uckgabewert]                 Anzahl der Eintr"age
520 
521 */
522 
523 {
524     DocTemplLocker_Impl aLocker( *pImp );
525 
526     if ( !pImp->Construct() )
527         return 0;
528 
529     RegionData_Impl *pData = pImp->GetRegion( nRegion );
530     sal_uIntPtr            nCount = 0;
531 
532     if ( pData )
533         nCount = pData->GetCount();
534 
535     return (sal_uInt16) nCount;
536 }
537 
538 //------------------------------------------------------------------------
539 
540 const String& SfxDocumentTemplates::GetName
541 (
542     sal_uInt16 nRegion,     //  Index des Bereiches, in dem der Eintrag liegt
543     sal_uInt16 nIdx         //  Index des Eintrags
544 )   const
545 
546 /*  [Beschreibung]
547 
548     Liefert den logischen Namen eines Eintrags eines Bereiches
549 
550 
551     [R"uckgabewert]
552 
553     const String&           Name des Eintrags
554 
555 */
556 
557 {
558     DocTemplLocker_Impl aLocker( *pImp );
559 
560     static String maTmpString;
561 
562     if ( pImp->Construct() )
563     {
564         DocTempl_EntryData_Impl  *pEntry = NULL;
565         RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
566 
567         if ( pRegion )
568             pEntry = pRegion->GetEntry( nIdx );
569 
570         if ( pEntry )
571             maTmpString = pEntry->GetTitle();
572         else
573             maTmpString.Erase();
574     }
575     else
576         maTmpString.Erase();
577 
578     return maTmpString;
579 }
580 
581 //------------------------------------------------------------------------
582 
583 String SfxDocumentTemplates::GetFileName
584 (
585     sal_uInt16 nRegion,     //  Index des Bereiches, in dem der Eintrag liegt
586     sal_uInt16 nIdx         //  Index des Eintrags
587 )   const
588 
589 /*  [Beschreibung]
590 
591     Liefert den Dateinamen eines Eintrags eines Bereiches
592 
593     [R"uckgabewert]                 Dateiname des Eintrags
594 
595 */
596 {
597     DocTemplLocker_Impl aLocker( *pImp );
598 
599     if ( !pImp->Construct() )
600         return String();
601 
602     DocTempl_EntryData_Impl  *pEntry = NULL;
603     RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
604 
605     if ( pRegion )
606         pEntry = pRegion->GetEntry( nIdx );
607 
608     if ( pEntry )
609     {
610         INetURLObject aURLObj( pEntry->GetTargetURL() );
611         return aURLObj.getName( INetURLObject::LAST_SEGMENT, true,
612                                 INetURLObject::DECODE_WITH_CHARSET );
613     }
614     else
615         return String();
616 }
617 
618 //------------------------------------------------------------------------
619 
620 String SfxDocumentTemplates::GetPath
621 (
622     sal_uInt16  nRegion,    //  Index des Bereiches, in dem der Eintrag liegt
623     sal_uInt16  nIdx        //  Index des Eintrags
624 )   const
625 
626 /*  [Beschreibung]
627 
628     Liefert den Dateinamen mit vollst"andigem Pfad zu der einem
629     Eintrag zugeordneten Datei
630 
631 
632     [R"uckgabewert]
633 
634     String                  Dateiname mit vollst"andigem Pfad
635 
636 */
637 {
638     DocTemplLocker_Impl aLocker( *pImp );
639 
640     if ( !pImp->Construct() )
641         return String();
642 
643     DocTempl_EntryData_Impl  *pEntry = NULL;
644     RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
645 
646     if ( pRegion )
647         pEntry = pRegion->GetEntry( nIdx );
648 
649     if ( pEntry )
650         return pEntry->GetTargetURL();
651     else
652         return String();
653 }
654 
655 //------------------------------------------------------------------------
656 
657 String SfxDocumentTemplates::GetTemplatePath
658 (
659     sal_uInt16          nRegion,    //  Index des Bereiches, in dem der Eintrag liegt
660     const String&   rLongName   //  logischer Name des Eintrags
661 )   const
662 
663 /*  [Beschreibung]
664 
665     Liefert den Dateinamen mit vollst"andigem Pfad zu der einem
666     Eintrag zugeordneten Datei
667 
668 
669     [R"uckgabewert]
670 
671     String                          Dateiname mit vollst"andigem Pfad
672 
673 */
674 {
675     DocTemplLocker_Impl aLocker( *pImp );
676 
677     if ( !pImp->Construct() )
678         return String();
679 
680     DocTempl_EntryData_Impl  *pEntry = NULL;
681     RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
682 
683     if ( pRegion )
684         pEntry = pRegion->GetEntry( rLongName );
685 
686     if ( pEntry )
687         return pEntry->GetTargetURL();
688     else if ( pRegion )
689     {
690         // a new template is going to be inserted, generate a new URL
691         // TODO/LATER: if the title is localized, use minimized URL in future
692 
693         // --**-- extension handling will become more complicated, because
694         //          every new document type will have it's own extension
695         //          e.g.: .stw or .stc instead of .vor
696         INetURLObject aURLObj( pRegion->GetTargetURL() );
697         aURLObj.insertName( rLongName, false,
698                      INetURLObject::LAST_SEGMENT, true,
699                      INetURLObject::ENCODE_ALL );
700 
701         OUString aExtension = aURLObj.getExtension();
702 
703         if ( ! aExtension.getLength() )
704             aURLObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM( "vor" ) ) );
705 
706         return aURLObj.GetMainURL( INetURLObject::NO_DECODE );
707     }
708     else
709         return String();
710 }
711 
712 //------------------------------------------------------------------------
713 
714 String SfxDocumentTemplates::GetDefaultTemplatePath
715 (
716     const String& rLongName
717 )
718 
719 /*  [Beschreibung]
720 
721     Liefert den Standardpfad zu Dokumentvorlagen
722 
723 
724     [R"uckgabewert]
725 
726     String                  Standardpfad zu Dokumentvorlagen
727 
728 */
729 {
730     DocTemplLocker_Impl aLocker( *pImp );
731 
732     if ( ! pImp->Construct() )
733         return String();
734 
735     // the first region in the list should always be the standard
736     // group
737     // --**-- perhaps we have to create it ???
738     RegionData_Impl *pRegion = pImp->GetRegion( 0L );
739     DocTempl_EntryData_Impl  *pEntry = NULL;
740 
741     if ( pRegion )
742         pEntry = pRegion->GetEntry( rLongName );
743 
744     if ( pEntry )
745         return pEntry->GetTargetURL();
746     else if ( pRegion )
747     {
748         // a new template is going to be inserted, generate a new URL
749         // TODO/LATER: if the title is localized, use minimized URL in future
750 
751         INetURLObject aURLObj( pRegion->GetTargetURL() );
752         aURLObj.insertName( rLongName, false,
753                      INetURLObject::LAST_SEGMENT, true,
754                      INetURLObject::ENCODE_ALL );
755 
756         OUString aExtension = aURLObj.getExtension();
757 
758         if ( ! aExtension.getLength() )
759             aURLObj.setExtension( OUString( RTL_CONSTASCII_USTRINGPARAM( "vor" ) ) );
760 
761         return aURLObj.GetMainURL( INetURLObject::NO_DECODE );
762     }
763     else
764         return String();
765 
766 /* dv! missing: create the directory, if it doesn't exists
767 
768 
769     DBG_ASSERT(aDirs.GetTokenCount(cDelim), "Keine Bereiche");
770     DirEntry aPath(aDirs.GetToken(0, cDelim));
771 
772     // Verzeichnis anlegen
773     if(!aPath.MakeDir())
774         return String();
775 
776     MakeFileName_Impl(aPath, rLongName, sal_True);
777     SfxTemplateDir  *pEntry = new SfxTemplateDir;
778     SfxTemplateDirEntryPtr pDirEntry =
779         new SfxTemplateDirEntry( String( '.' ), aPath.GetPath() );
780     pDirEntry->SetContent(new SfxTemplateDir(aPath.GetPath()));
781     pEntry->Insert(pDirEntry, pEntry->Count());
782     pDirs->Insert(pEntry, pDirs->Count());
783     return aPath.GetFull();
784 */
785 }
786 
787 //------------------------------------------------------------------------
788 
789 ::rtl::OUString SfxDocumentTemplates::GetTemplateTargetURLFromComponent( const ::rtl::OUString& aGroupName,
790                                                                          const ::rtl::OUString& aTitle )
791 {
792     DocTemplLocker_Impl aLocker( *pImp );
793 
794     INetURLObject aTemplateObj( pImp->GetRootURL() );
795 
796     aTemplateObj.insertName( aGroupName, false,
797                         INetURLObject::LAST_SEGMENT, true,
798                         INetURLObject::ENCODE_ALL );
799 
800     aTemplateObj.insertName( aTitle, false,
801                         INetURLObject::LAST_SEGMENT, true,
802                         INetURLObject::ENCODE_ALL );
803 
804 
805     ::rtl::OUString aResult;
806     Content aTemplate;
807     uno::Reference< XCommandEnvironment > aCmdEnv;
808     if ( Content::create( aTemplateObj.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv, aTemplate ) )
809     {
810         OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
811         getTextProperty_Impl( aTemplate, aPropName, aResult );
812         aResult = SvtPathOptions().SubstituteVariable( aResult );
813     }
814 
815     return aResult;
816 }
817 
818 //------------------------------------------------------------------------
819 
820 sal_Bool SfxDocumentTemplates::SaveDir
821 (
822 //  SfxTemplateDir& rDir        //  das zu speichernde Directory
823 )
824 
825 /*  [Beschreibung]
826 
827     Speichert das Directory rDir
828 
829 
830     [R"uckgabewert]
831 
832     sal_Bool                        sal_False,
833                                 Schreibfehler
834 
835                                 sal_True
836                                 gespeichert
837 
838 */
839 
840 {
841     return sal_True;
842 }
843 
844 //------------------------------------------------------------------------
845 
846 void SfxDocumentTemplates::NewTemplate
847 (
848     sal_uInt16          nRegion,    /*  Index des Bereiches, in dem die Vorlage
849                                     angelegt werden soll */
850 
851     const String&   rLongName,  //  logischer Name der neuen Vorlage
852     const String&   rFileName   //  Dateiname der neuen Vorlage
853 )
854 
855 /*  [Beschreibung]
856 
857     Eintragen einer neuen Dokumentvorlage in die Verwaltungsstrukturen
858     Das "Uberschreiben einer Vorlage gleichen Namens wird
859     verhindert (!! Fehlermeldung)
860 
861 */
862 
863 {
864     DocTemplLocker_Impl aLocker( *pImp );
865 
866     if ( ! pImp->Construct() )
867         return;
868 
869     DocTempl_EntryData_Impl  *pEntry;
870     RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
871 
872     // do nothing if there is no region with that index
873     if ( !pRegion )
874         return;
875 
876     pEntry = pRegion->GetEntry( rLongName );
877 
878     // do nothing if there is already an entry with that name
879     if ( pEntry )
880         return;
881 
882     uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
883 
884     if ( xTemplates->addTemplate( pRegion->GetTitle(), rLongName, rFileName ) )
885         pRegion->AddEntry( rLongName, rFileName );
886 }
887 
888 //------------------------------------------------------------------------
889 
890 sal_Bool SfxDocumentTemplates::CopyOrMove
891 (
892     sal_uInt16  nTargetRegion,      //  Index des Zielbereiches
893     sal_uInt16  nTargetIdx,         //  Index Zielposition
894     sal_uInt16  nSourceRegion,      //  Index des Quellbereiches
895     sal_uInt16  nSourceIdx,         /*  Index der zu kopierenden / zu verschiebenden
896                                     Dokumentvorlage */
897     sal_Bool    bMove               //  kopieren / verschieben
898 )
899 
900 /*  [Beschreibung]
901 
902     Kopieren oder Verschieben einer Dokumentvorlage
903 
904     [R"uckgabewert]
905 
906     sal_Bool                            sal_True
907                                     Aktion konnte ausgef"uhrt werden
908 
909                                     sal_False
910                                     Aktion konnte nicht ausgef2uhrt werden
911     [Querverweise]
912 
913     <SfxDocumentTemplates::Move(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
914     <SfxDocumentTemplates::Copy(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16)>
915 */
916 
917 {
918     /* to perform a copy or move, we need to send a transfer command to
919        the destination folder with the URL of the source as parameter.
920        ( If the destination content doesn't support the transfer command,
921        we could try a copy ( and delete ) instead. )
922        We need two transfers ( one for the real template and one for its
923        representation in the hierarchy )
924        ...
925     */
926 
927     DocTemplLocker_Impl aLocker( *pImp );
928 
929     if ( !pImp->Construct() )
930         return sal_False;
931 
932     // Don't copy or move any folders
933     if( nSourceIdx == USHRT_MAX )
934         return sal_False ;
935 
936     if ( nSourceRegion == nTargetRegion )
937     {
938         DBG_ERRORFILE( "Don't know, what to do!" );
939         return sal_False;
940 #if 0
941     // Verschieben einer Vorlage innerhalb eines Bereiches
942     // --> nur Verwaltungsdaten aktualisieren
943     if ( bMove && nTargetRegion == nSourceRegion )
944     {
945         if(nTargetIdx == USHRT_MAX)
946             nTargetIdx = 0;
947         const SfxTemplateDirEntryPtr pEntry = rTargetDir[nSourceIdx];
948         rTargetDir.Insert(pEntry, nTargetIdx);
949         if(nTargetIdx < nSourceIdx)
950             ++nSourceIdx;
951         rTargetDir.Remove(nSourceIdx);
952         return SaveDir(rTargetDir);
953     }
954 #endif
955     }
956 
957     RegionData_Impl *pSourceRgn = pImp->GetRegion( nSourceRegion );
958     if ( !pSourceRgn )
959         return sal_False;
960 
961     DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nSourceIdx );
962     if ( !pSource )
963         return sal_False;
964 
965     RegionData_Impl *pTargetRgn = pImp->GetRegion( nTargetRegion );
966     if ( !pTargetRgn )
967         return sal_False;
968 
969     OUString aTitle = pSource->GetTitle();
970 
971     uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
972 
973     if ( xTemplates->addTemplate( pTargetRgn->GetTitle(),
974                                   aTitle,
975                                   pSource->GetTargetURL() ) )
976     {
977 
978         INetURLObject aSourceObj( pSource->GetTargetURL() );
979 
980         ::rtl::OUString aNewTargetURL = GetTemplateTargetURLFromComponent( pTargetRgn->GetTitle(), aTitle );
981         if ( !aNewTargetURL.getLength() )
982             return sal_False;
983 
984         if ( bMove )
985         {
986             // --**-- delete the original file
987             sal_Bool bDeleted = xTemplates->removeTemplate( pSourceRgn->GetTitle(),
988                                                             pSource->GetTitle() );
989             if ( bDeleted )
990                 pSourceRgn->DeleteEntry( nSourceIdx );
991             else
992             {
993                 if ( xTemplates->removeTemplate( pTargetRgn->GetTitle(), aTitle ) )
994                     return sal_False; // will trigger tetry with copy instead of move
995 
996                 // if it is not possible to remove just created template ( must be possible! )
997                 // it is better to report success here, since at least the copy has succeeded
998                 // TODO/LATER: solve it more gracefully in future
999             }
1000         }
1001 
1002         pTargetRgn->AddEntry( aTitle, aNewTargetURL, &nTargetIdx );
1003 
1004         return sal_True;
1005     }
1006 
1007     // --**-- wenn aktuell das File geoeffnet ist,
1008     // muss es hinterher wieder geoeffnet werden
1009 
1010     return sal_False;
1011 }
1012 
1013 //------------------------------------------------------------------------
1014 
1015 sal_Bool SfxDocumentTemplates::Move
1016 (
1017     sal_uInt16 nTargetRegion,       //  Index des Zielbereiches
1018     sal_uInt16 nTargetIdx,          //  Index Zielposition
1019     sal_uInt16 nSourceRegion,       //  Index des Quellbereiches
1020     sal_uInt16 nSourceIdx           /*  Index der zu kopierenden / zu verschiebenden
1021                                     Dokumentvorlage */
1022 )
1023 
1024 /*  [Beschreibung]
1025 
1026     Verschieben einer Dokumentvorlage
1027 
1028 
1029     [R"uckgabewert]
1030 
1031     sal_Bool                            sal_True
1032                                     Aktion konnte ausgef"uhrt werden
1033 
1034                                     sal_False
1035                                     Aktion konnte nicht ausgef2uhrt werden
1036 
1037     [Querverweise]
1038 
1039     <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
1040 */
1041 {
1042     DocTemplLocker_Impl aLocker( *pImp );
1043 
1044     return CopyOrMove( nTargetRegion, nTargetIdx,
1045                        nSourceRegion, nSourceIdx, sal_True );
1046 }
1047 
1048 //------------------------------------------------------------------------
1049 
1050 sal_Bool SfxDocumentTemplates::Copy
1051 (
1052     sal_uInt16 nTargetRegion,       //  Index des Zielbereiches
1053     sal_uInt16 nTargetIdx,          //  Index Zielposition
1054     sal_uInt16 nSourceRegion,       //  Index des Quellbereiches
1055     sal_uInt16 nSourceIdx           /*  Index der zu kopierenden / zu verschiebenden
1056                                     Dokumentvorlage */
1057 )
1058 
1059 /*  [Beschreibung]
1060 
1061     Kopieren einer Dokumentvorlage
1062 
1063 
1064     [R"uckgabewert]
1065 
1066     sal_Bool                            sal_True
1067                                     Aktion konnte ausgef"uhrt werden
1068 
1069                                     sal_False
1070                                     Aktion konnte nicht ausgef"uhrt werden
1071 
1072     [Querverweise]
1073 
1074     <SfxDocumentTemplates::CopyOrMove(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16,sal_Bool)>
1075 */
1076 
1077 {
1078     DocTemplLocker_Impl aLocker( *pImp );
1079 
1080     return CopyOrMove( nTargetRegion, nTargetIdx,
1081                        nSourceRegion, nSourceIdx, sal_False );
1082 }
1083 
1084 //------------------------------------------------------------------------
1085 
1086 sal_Bool SfxDocumentTemplates::CopyTo
1087 (
1088     sal_uInt16          nRegion,    /*  Bereich der Vorlage, die exportiert werden
1089                                     soll  */
1090     sal_uInt16          nIdx,       /*  Index der Vorlage, die exportiert werden
1091                                     soll */
1092     const String&   rName       /*  Dateiname, unter dem die Vorlage angelegt
1093                                     werden soll */
1094 )   const
1095 
1096 /*  [Beschreibung]
1097 
1098     Exportieren einer Dokumentvorlage in das Dateisystem
1099 
1100 
1101     [R"uckgabewert]
1102 
1103     sal_Bool                            sal_True
1104                                     Aktion konnte ausgef"uhrt werden
1105 
1106                                     sal_False
1107                                     Aktion konnte nicht ausgef"uhrt werden
1108 
1109 
1110     [Querverweise]
1111 
1112     <SfxDocumentTemplates::CopyFrom(sal_uInt16,sal_uInt16,String&)>
1113 */
1114 
1115 {
1116     DocTemplLocker_Impl aLocker( *pImp );
1117 
1118     if ( ! pImp->Construct() )
1119         return sal_False;
1120 
1121     RegionData_Impl *pSourceRgn = pImp->GetRegion( nRegion );
1122     if ( !pSourceRgn )
1123         return sal_False;
1124 
1125     DocTempl_EntryData_Impl *pSource = pSourceRgn->GetEntry( nIdx );
1126     if ( !pSource )
1127         return sal_False;
1128 
1129     INetURLObject aTargetURL( rName );
1130 
1131     OUString aTitle( aTargetURL.getName( INetURLObject::LAST_SEGMENT, true,
1132                                          INetURLObject::DECODE_WITH_CHARSET ) );
1133     aTargetURL.removeSegment();
1134 
1135     OUString aParentURL = aTargetURL.GetMainURL( INetURLObject::NO_DECODE );
1136 
1137     uno::Reference< XCommandEnvironment > aCmdEnv;
1138     Content aTarget;
1139 
1140     try
1141     {
1142         aTarget = Content( aParentURL, aCmdEnv );
1143 
1144         TransferInfo aTransferInfo;
1145         aTransferInfo.MoveData = sal_False;
1146         aTransferInfo.SourceURL = pSource->GetTargetURL();
1147         aTransferInfo.NewTitle = aTitle;
1148         aTransferInfo.NameClash = NameClash::OVERWRITE;
1149 
1150         Any aArg = makeAny( aTransferInfo );
1151         OUString aCmd( RTL_CONSTASCII_USTRINGPARAM( COMMAND_TRANSFER ) );
1152 
1153         aTarget.executeCommand( aCmd, aArg );
1154     }
1155     catch ( ContentCreationException& )
1156     { return sal_False; }
1157     catch ( Exception& )
1158     { return sal_False; }
1159 
1160     return sal_True;
1161 }
1162 
1163 //------------------------------------------------------------------------
1164 
1165 sal_Bool SfxDocumentTemplates::CopyFrom
1166 (
1167     sal_uInt16      nRegion,        /*  Bereich, in den die Vorlage importiert
1168                                     werden soll */
1169     sal_uInt16      nIdx,           //  Index der neuen Vorlage in diesem Bereich
1170     String&     rName           /*  Dateiname der Vorlage, die importiert
1171                                     werden soll, als out-Parameter der (auto-
1172                                     matisch aus dem Dateinamen generierte)
1173                                     logische Name der Vorlage */
1174 )
1175 
1176 /*  [Beschreibung]
1177 
1178     Importieren einer Dokumentvorlage aus dem Dateisystem
1179 
1180 
1181     [R"uckgabewert]                 Erfolg (sal_True) oder Mi"serfpTargetDirectory->GetContent());
1182 
1183     sal_Bool                            sal_True
1184                                     Aktion konnte ausgef"uhrt werden
1185 
1186                                     sal_False
1187                                     Aktion konnte nicht ausgef"uhrt werden
1188 
1189     [Querverweise]
1190 
1191     <SfxDocumentTemplates::CopyTo(sal_uInt16,sal_uInt16,const String&)>
1192 */
1193 
1194 {
1195     DocTemplLocker_Impl aLocker( *pImp );
1196 
1197     if ( ! pImp->Construct() )
1198         return sal_False;
1199 
1200     RegionData_Impl *pTargetRgn = pImp->GetRegion( nRegion );
1201 
1202     if ( !pTargetRgn )
1203         return sal_False;
1204 
1205     uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1206     if ( !xTemplates.is() )
1207         return sal_False;
1208 
1209     OUString aTitle;
1210     sal_Bool bTemplateAdded = sal_False;
1211 
1212     if( pImp->GetTitleFromURL( rName, aTitle ) )
1213     {
1214         bTemplateAdded = xTemplates->addTemplate( pTargetRgn->GetTitle(), aTitle, rName );
1215     }
1216     else
1217     {
1218         OUString aService( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DESKTOP ) );
1219         uno::Reference< XComponentLoader > xDesktop( ::comphelper::getProcessServiceFactory()->createInstance( aService ),
1220                                                 UNO_QUERY );
1221 
1222         Sequence< PropertyValue > aArgs( 1 );
1223         aArgs[0].Name = ::rtl::OUString::createFromAscii("Hidden");
1224         aArgs[0].Value <<= sal_True;
1225 
1226         INetURLObject   aTemplURL( rName );
1227         uno::Reference< XDocumentPropertiesSupplier > xDocPropsSupplier;
1228         uno::Reference< XStorable > xStorable;
1229         try
1230         {
1231             xStorable = uno::Reference< XStorable >(
1232                 xDesktop->loadComponentFromURL( aTemplURL.GetMainURL(INetURLObject::NO_DECODE),
1233                                                 OUString::createFromAscii( "_blank" ),
1234                                                 0,
1235                                                 aArgs ),
1236                 UNO_QUERY );
1237 
1238             xDocPropsSupplier = uno::Reference< XDocumentPropertiesSupplier >(
1239                 xStorable, UNO_QUERY );
1240         }
1241         catch( Exception& )
1242         {
1243         }
1244 
1245         if( xStorable.is() )
1246         {
1247             // get Title from XDocumentPropertiesSupplier
1248             if( xDocPropsSupplier.is() )
1249             {
1250                 uno::Reference< XDocumentProperties > xDocProps
1251                     = xDocPropsSupplier->getDocumentProperties();
1252                 if (xDocProps.is() ) {
1253                     aTitle = xDocProps->getTitle();
1254                 }
1255             }
1256 
1257             if( ! aTitle.getLength() )
1258             {
1259                 INetURLObject aURL( aTemplURL );
1260                 aURL.CutExtension();
1261                 aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
1262                                         INetURLObject::DECODE_WITH_CHARSET );
1263             }
1264 
1265             // write a template using XStorable interface
1266             bTemplateAdded = xTemplates->storeTemplate( pTargetRgn->GetTitle(), aTitle, xStorable );
1267         }
1268     }
1269 
1270 
1271     if( bTemplateAdded )
1272     {
1273         INetURLObject aTemplObj( pTargetRgn->GetHierarchyURL() );
1274         aTemplObj.insertName( aTitle, false,
1275                               INetURLObject::LAST_SEGMENT, true,
1276                               INetURLObject::ENCODE_ALL );
1277         OUString aTemplURL = aTemplObj.GetMainURL( INetURLObject::NO_DECODE );
1278 
1279         uno::Reference< XCommandEnvironment > aCmdEnv;
1280         Content aTemplCont;
1281 
1282         if( Content::create( aTemplURL, aCmdEnv, aTemplCont ) )
1283         {
1284             OUString aTemplName;
1285             OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
1286 
1287             if( getTextProperty_Impl( aTemplCont, aPropName, aTemplName ) )
1288             {
1289                 if ( nIdx == USHRT_MAX )
1290                     nIdx = 0;
1291                 else
1292                     nIdx += 1;
1293 
1294                 pTargetRgn->AddEntry( aTitle, aTemplName, &nIdx );
1295                 rName = aTitle;
1296                 return sal_True;
1297             }
1298             else
1299             {
1300                 DBG_ASSERT( sal_False, "CopyFrom(): The content should contain target URL!" );
1301             }
1302         }
1303         else
1304         {
1305             DBG_ASSERT( sal_False, "CopyFrom(): The content just was created!" );
1306         }
1307     }
1308 
1309     return sal_False;
1310 }
1311 
1312 //------------------------------------------------------------------------
1313 
1314 sal_Bool SfxDocumentTemplates::Delete
1315 (
1316     sal_uInt16 nRegion,             //  Index des Bereiches
1317     sal_uInt16 nIdx                 /*  Index des Eintrags oder USHRT_MAX,
1318                                     wenn ein Verzeichnis gemeint ist. */
1319 )
1320 
1321 /*  [Beschreibung]
1322 
1323     "oschen eines Eintrags oder eines Verzeichnisses
1324 
1325 
1326     [R"uckgabewert]
1327 
1328     sal_Bool                            sal_True
1329                                     Aktion konnte ausgef"uhrt werden
1330 
1331                                     sal_False
1332                                     Aktion konnte nicht ausgef"uhrt werden
1333 
1334 
1335     [Querverweise]
1336 
1337     <SfxDocumentTemplates::InsertDir(const String&,sal_uInt16)>
1338     <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
1339     <SfxDocumentTemplates::SaveDir(SfxTemplateDir&)>
1340 */
1341 
1342 {
1343     DocTemplLocker_Impl aLocker( *pImp );
1344 
1345     /* delete the template or folder in the hierarchy and in the
1346        template folder by sending a delete command to the content.
1347        Then remove the data from the lists
1348     */
1349     if ( ! pImp->Construct() )
1350         return sal_False;
1351 
1352     RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1353 
1354     if ( !pRegion )
1355         return sal_False;
1356 
1357     sal_Bool bRet;
1358     uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1359 
1360     if ( nIdx == USHRT_MAX )
1361     {
1362         bRet = xTemplates->removeGroup( pRegion->GetTitle() );
1363         if ( bRet )
1364             pImp->DeleteRegion( nRegion );
1365     }
1366     else
1367     {
1368         DocTempl_EntryData_Impl *pEntry = pRegion->GetEntry( nIdx );
1369 
1370         if ( !pEntry )
1371             return sal_False;
1372 
1373         bRet = xTemplates->removeTemplate( pRegion->GetTitle(),
1374                                            pEntry->GetTitle() );
1375         if( bRet )
1376             pRegion->DeleteEntry( nIdx );
1377     }
1378 
1379     return bRet;
1380 }
1381 
1382 //------------------------------------------------------------------------
1383 
1384 sal_Bool SfxDocumentTemplates::InsertDir
1385 (
1386     const String&   rText,      //  der logische Name des neuen Bereiches
1387     sal_uInt16          nRegion     //  Index des Bereiches
1388 )
1389 
1390 /*  [Beschreibung]
1391 
1392     Einf"ugen eines Verzeichnisses
1393 
1394 
1395     [R"uckgabewert]
1396 
1397     sal_Bool                            sal_True
1398                                     Aktion konnte ausgef"uhrt werden
1399 
1400                                     sal_False
1401                                     Aktion konnte nicht ausgef"uhrt werden
1402 
1403     [Querverweise]
1404 
1405     <SfxDocumentTemplates::KillDir(SfxTemplateDir&)>
1406     <SfxDocumentTemplates::SaveDir(SfxTemplateDir&)>
1407 */
1408 {
1409     DocTemplLocker_Impl aLocker( *pImp );
1410 
1411     if ( ! pImp->Construct() )
1412         return sal_False;
1413 
1414     RegionData_Impl *pRegion = pImp->GetRegion( rText );
1415 
1416     if ( pRegion )
1417         return sal_False;
1418 
1419     uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1420 
1421     if ( xTemplates->addGroup( rText ) )
1422     {
1423         RegionData_Impl* pNewRegion = new RegionData_Impl( pImp, rText );
1424 
1425         if ( ! pImp->InsertRegion( pNewRegion, nRegion ) )
1426         {
1427             delete pNewRegion;
1428             return sal_False;
1429         }
1430         return sal_True;
1431     }
1432 
1433     return sal_False;
1434 }
1435 
1436 //------------------------------------------------------------------------
1437 
1438 sal_Bool SfxDocumentTemplates::SetName
1439 (
1440     const String&   rName,      //  Der zu setzende Name
1441     sal_uInt16          nRegion,    //  Index des Bereiches
1442     sal_uInt16          nIdx        /*  Index des Eintrags oder USHRT_MAX,
1443                                     wenn ein Verzeichnis gemeint ist. */
1444 )
1445 
1446 /*  [Beschreibung]
1447 
1448     "Andern des Namens eines Eintrags oder eines Verzeichnisses
1449 
1450 
1451     [R"uckgabewert]
1452 
1453     sal_Bool                            sal_True
1454                                     Aktion konnte ausgef"uhrt werden
1455 
1456                                     sal_False
1457                                     Aktion konnte nicht ausgef"uhrt werden
1458 
1459 */
1460 
1461 {
1462     DocTemplLocker_Impl aLocker( *pImp );
1463 
1464     if ( ! pImp->Construct() )
1465         return sal_False;
1466 
1467     RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1468     DocTempl_EntryData_Impl *pEntry = NULL;
1469 
1470     if ( !pRegion )
1471         return sal_False;
1472 
1473     uno::Reference< XDocumentTemplates > xTemplates = pImp->getDocTemplates();
1474     OUString aEmpty;
1475 
1476     if ( nIdx == USHRT_MAX )
1477     {
1478         if ( pRegion->GetTitle() == OUString( rName ) )
1479             return sal_True;
1480 
1481         // we have to rename a region
1482         if ( xTemplates->renameGroup( pRegion->GetTitle(), rName ) )
1483         {
1484             pRegion->SetTitle( rName );
1485             pRegion->SetTargetURL( aEmpty );
1486             pRegion->SetHierarchyURL( aEmpty );
1487             return sal_True;
1488         }
1489     }
1490     else
1491     {
1492         pEntry = pRegion->GetEntry( nIdx );
1493 
1494         if ( !pEntry )
1495             return sal_False;
1496 
1497         if ( pEntry->GetTitle() == OUString( rName ) )
1498             return sal_True;
1499 
1500         if ( xTemplates->renameTemplate( pRegion->GetTitle(),
1501                                          pEntry->GetTitle(),
1502                                          rName ) )
1503         {
1504             pEntry->SetTitle( rName );
1505             pEntry->SetTargetURL( aEmpty );
1506             pEntry->SetHierarchyURL( aEmpty );
1507             return sal_True;
1508         }
1509     }
1510 
1511     return sal_False;
1512 }
1513 
1514 //------------------------------------------------------------------------
1515 
1516 sal_Bool SfxDocumentTemplates::Rescan()
1517 
1518 /*  [Beschreibung]
1519 
1520     Abgleich des Verwaltungsdaten mit dem aktuellen Zustand auf der Platte.
1521     Die logischen Namen, zu denen keine Datei mit existiert, werden aus
1522     der Verwaltungsstruktur entfernt; Dateien, zu denen kein Eintrag
1523     existiert, werden aufgenommen.
1524 
1525 
1526     [R"uckgabewert]
1527 
1528     sal_Bool                            sal_True
1529                                     Aktion konnte ausgef"uhrt werden
1530 
1531                                     sal_False
1532                                     Aktion konnte nicht ausgef"uhrt werden
1533 
1534 
1535     [Querverweise]
1536 
1537     <SfxTemplateDir::Scan(sal_Bool bDirectory, sal_Bool bSave)>
1538     <SfxTemplateDir::Freshen(const SfxTemplateDir &rNew)>
1539 */
1540 {
1541     if ( !pImp->Construct() )
1542         return sal_False;
1543 
1544     pImp->Rescan();
1545 
1546     return sal_True;
1547 }
1548 
1549 //------------------------------------------------------------------------
1550 
1551 SfxObjectShellRef SfxDocumentTemplates::CreateObjectShell
1552 (
1553     sal_uInt16 nRegion,         //  Index des Bereiches
1554     sal_uInt16 nIdx             //  Index des Eintrags
1555 )
1556 
1557 /*  [Beschreibung]
1558 
1559     Zugriff auf die DokumentShell eines Eintrags
1560 
1561 
1562     [R"uckgabewert]
1563 
1564     SfxObjectShellRef         Referenz auf die ObjectShell
1565 
1566 
1567     [Querverweise]
1568 
1569     <SfxTemplateDirEntry::CreateObjectShell()>
1570     <SfxDocumentTemplates::DeleteObjectShell(sal_uInt16, sal_uInt16)>
1571 */
1572 
1573 {
1574     DocTemplLocker_Impl aLocker( *pImp );
1575 
1576     if ( !pImp->Construct() )
1577         return NULL;
1578 
1579     RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1580     DocTempl_EntryData_Impl *pEntry = NULL;
1581 
1582     if ( pRegion )
1583         pEntry = pRegion->GetEntry( nIdx );
1584 
1585     if ( pEntry )
1586         return pEntry->CreateObjectShell();
1587     else
1588         return NULL;
1589 }
1590 
1591 //------------------------------------------------------------------------
1592 
1593 sal_Bool SfxDocumentTemplates::DeleteObjectShell
1594 (
1595     sal_uInt16 nRegion,         //  Index des Bereiches
1596     sal_uInt16 nIdx             //  Index des Eintrags
1597 )
1598 
1599 /*  [Beschreibung]
1600 
1601     Freigeben der ObjectShell eines Eintrags
1602 
1603 
1604     [R"uckgabewert]
1605 
1606     sal_Bool                            sal_True
1607                                     Aktion konnte ausgef"uhrt werden
1608 
1609                                     sal_False
1610                                     Aktion konnte nicht ausgef"uhrt werden
1611 
1612     [Querverweise]
1613 
1614     <SfxTemplateDirEntry::DeleteObjectShell()>
1615     <SfxDocumentTemplates::CreateObjectShell(sal_uInt16, sal_uInt16)>
1616 */
1617 
1618 {
1619     DocTemplLocker_Impl aLocker( *pImp );
1620 
1621     if ( ! pImp->Construct() )
1622         return sal_True;
1623 
1624     RegionData_Impl *pRegion = pImp->GetRegion( nRegion );
1625     DocTempl_EntryData_Impl *pEntry = NULL;
1626 
1627     if ( pRegion )
1628         pEntry = pRegion->GetEntry( nIdx );
1629 
1630     if ( pEntry )
1631         return pEntry->DeleteObjectShell();
1632     else
1633         return sal_True;
1634 }
1635 
1636 //------------------------------------------------------------------------
1637 
1638 sal_Bool SfxDocumentTemplates::GetFull
1639 (
1640     const String &rRegion,      // Der Name des Bereiches
1641     const String &rName,        // Der Name der Vorlage
1642     String &rPath               // Out: Pfad + Dateiname
1643 )
1644 
1645 /*  [Beschreibung]
1646 
1647     Liefert Pfad + Dateiname zu der durch rRegion und rName bezeichneten
1648     Vorlage
1649 
1650 
1651     [R"uckgabewert]
1652 
1653     sal_Bool                            sal_True
1654                                     Aktion konnte ausgef"uhrt werden
1655 
1656                                     sal_False
1657                                     Aktion konnte nicht ausgef"uhrt werden
1658 
1659 
1660     [Querverweise]
1661 
1662     <SfxDocumentTemplates::GetLogicNames(const String&,String&,String&)>
1663 */
1664 
1665 {
1666     DocTemplLocker_Impl aLocker( *pImp );
1667 
1668     // We don't search for empty names!
1669     if ( ! rName.Len() )
1670         return sal_False;
1671 
1672     if ( ! pImp->Construct() )
1673         return sal_False;
1674 
1675     DocTempl_EntryData_Impl* pEntry = NULL;
1676     const sal_uInt16 nCount = GetRegionCount();
1677 
1678     for ( sal_uInt16 i = 0; i < nCount; ++i )
1679     {
1680         RegionData_Impl *pRegion = pImp->GetRegion( i );
1681 
1682         if( pRegion &&
1683             ( !rRegion.Len() || ( rRegion == String( pRegion->GetTitle() ) ) ) )
1684         {
1685             pEntry = pRegion->GetEntry( rName );
1686 
1687             if ( pEntry )
1688             {
1689                 rPath = pEntry->GetTargetURL();
1690                 break;
1691             }
1692         }
1693     }
1694 
1695     return ( pEntry != NULL );
1696 }
1697 
1698 //------------------------------------------------------------------------
1699 
1700 sal_Bool SfxDocumentTemplates::GetLogicNames
1701 (
1702     const String &rPath,            // vollst"andiger Pfad zu der Vorlage
1703     String &rRegion,                // Out: der Bereichsname
1704     String &rName                   // Out: der Vorlagenname
1705 ) const
1706 
1707 /*  [Beschreibung]
1708 
1709     Liefert Pfad und logischen Namen zu der durch rPath bezeichneten
1710     Vorlage
1711 
1712     [R"uckgabewert]
1713 
1714     sal_Bool                            sal_True
1715                                     Aktion konnte ausgef"uhrt werden
1716 
1717                                     sal_False
1718                                     Aktion konnte nicht ausgef"uhrt werden
1719 
1720 
1721     [Querverweise]
1722 
1723     <SfxDocumentTemplates::GetFull(const String&,const String&,DirEntry&)>
1724 */
1725 
1726 {
1727     DocTemplLocker_Impl aLocker( *pImp );
1728 
1729     if ( ! pImp->Construct() )
1730         return sal_False;
1731 
1732     INetURLObject aFullPath;
1733 
1734     aFullPath.SetSmartProtocol( INET_PROT_FILE );
1735     aFullPath.SetURL( rPath );
1736     OUString aPath( aFullPath.GetMainURL( INetURLObject::NO_DECODE ) );
1737 
1738     RegionData_Impl *pData = NULL;
1739     DocTempl_EntryData_Impl  *pEntry = NULL;
1740     sal_Bool         bFound = sal_False;
1741 
1742     sal_uIntPtr nCount = GetRegionCount();
1743 
1744     for ( sal_uIntPtr i=0; !bFound && (i<nCount); i++ )
1745     {
1746         pData = pImp->GetRegion( i );
1747         if ( pData )
1748         {
1749             sal_uIntPtr nChildCount = pData->GetCount();
1750 
1751             for ( sal_uIntPtr j=0; !bFound && (j<nChildCount); j++ )
1752             {
1753                 pEntry = pData->GetEntry( j );
1754                 if ( pEntry->GetTargetURL() == aPath )
1755                 {
1756                     bFound = sal_True;
1757                 }
1758             }
1759         }
1760     }
1761 
1762     if ( bFound )
1763     {
1764         rRegion = pData->GetTitle();
1765         rName = pEntry->GetTitle();
1766     }
1767 
1768     return bFound;
1769 }
1770 
1771 //------------------------------------------------------------------------
1772 
1773 SfxDocumentTemplates::SfxDocumentTemplates()
1774 
1775 /*  [Beschreibung]
1776 
1777     Konstruktor
1778 */
1779 {
1780     if ( !gpTemplateData )
1781         gpTemplateData = new SfxDocTemplate_Impl;
1782 
1783     pImp = gpTemplateData;
1784 }
1785 
1786 //-------------------------------------------------------------------------
1787 
1788 void SfxDocumentTemplates::Construct()
1789 
1790 //  verz"ogerter Aufbau der Verwaltungsdaten
1791 
1792 {
1793 //  pImp->Construct();
1794 }
1795 
1796 //------------------------------------------------------------------------
1797 
1798 SfxDocumentTemplates::~SfxDocumentTemplates()
1799 
1800 /*  [Beschreibung]
1801 
1802     Destruktor
1803     Freigeben der Verwaltungsdaten
1804 */
1805 
1806 {
1807     pImp = NULL;
1808 }
1809 
1810 void SfxDocumentTemplates::Update( sal_Bool _bSmart )
1811 {
1812     if  (   !_bSmart                                                // don't be smart
1813         ||  ::svt::TemplateFolderCache( sal_True ).needsUpdate()    // update is really necessary
1814         )
1815     {
1816         if ( pImp->Construct() )
1817             pImp->Rescan();
1818     }
1819 }
1820 
1821 void SfxDocumentTemplates::ReInitFromComponent()
1822 {
1823     pImp->ReInitFromComponent();
1824 }
1825 
1826 
1827 sal_Bool SfxDocumentTemplates::HasUserContents( sal_uInt16 nRegion, sal_uInt16 nIdx ) const
1828 {
1829     DocTemplLocker_Impl aLocker( *pImp );
1830 
1831     sal_Bool bResult = sal_False;
1832 
1833     RegionData_Impl* pRegion = pImp->GetRegion( nRegion );
1834 
1835     if ( pRegion )
1836     {
1837         ::rtl::OUString aRegionTargetURL = pRegion->GetTargetURL();
1838         if ( aRegionTargetURL.getLength() )
1839         {
1840             sal_uInt16 nLen = 0;
1841             sal_uInt16 nStartInd = 0;
1842 
1843             if( nIdx == USHRT_MAX )
1844             {
1845                 // this is a folder
1846                 // check whether there is at least one editable template
1847                 nLen = ( sal_uInt16 )pRegion->GetCount();
1848                 nStartInd = 0;
1849                 if ( nLen == 0 )
1850                     bResult = sal_True; // the writing part of empty folder with writing URL can be removed
1851             }
1852             else
1853             {
1854                 // this is a template
1855                 // check whether the template is inserted by user
1856                 nLen = 1;
1857                 nStartInd = nIdx;
1858             }
1859 
1860             for ( sal_uInt16 nInd = nStartInd; nInd < nStartInd + nLen; nInd++ )
1861             {
1862                 DocTempl_EntryData_Impl* pEntryData = pRegion->GetEntry( nInd );
1863                 if ( pEntryData )
1864                 {
1865                     ::rtl::OUString aEntryTargetURL = pEntryData->GetTargetURL();
1866                     if ( aEntryTargetURL.getLength()
1867                       && ::utl::UCBContentHelper::IsSubPath( aRegionTargetURL, aEntryTargetURL ) )
1868                     {
1869                         bResult = sal_True;
1870                         break;
1871                     }
1872                 }
1873             }
1874         }
1875     }
1876 
1877     return bResult;
1878 }
1879 
1880 // -----------------------------------------------------------------------
1881 // -----------------------------------------------------------------------
1882 // -----------------------------------------------------------------------
1883 DocTempl_EntryData_Impl::DocTempl_EntryData_Impl( RegionData_Impl* pParent,
1884                                 const OUString& rTitle )
1885 {
1886     mpParent    = pParent;
1887     maTitle     = rTitle;
1888     mbIsOwner   = sal_False;
1889     mbDidConvert= sal_False;
1890 }
1891 
1892 // -----------------------------------------------------------------------
1893 int DocTempl_EntryData_Impl::Compare( const OUString& rTitle ) const
1894 {
1895     return maTitle.compareTo( rTitle );
1896 }
1897 
1898 //------------------------------------------------------------------------
1899 SfxObjectShellRef DocTempl_EntryData_Impl::CreateObjectShell()
1900 {
1901     if( ! mxObjShell.Is() )
1902     {
1903         mbIsOwner = sal_False;
1904         sal_Bool bDum = sal_False;
1905         SfxApplication *pSfxApp = SFX_APP();
1906         String          aTargetURL = GetTargetURL();
1907 
1908         mxObjShell = pSfxApp->DocAlreadyLoaded( aTargetURL, sal_True, bDum );
1909 
1910         if( ! mxObjShell.Is() )
1911         {
1912             mbIsOwner = sal_True;
1913             SfxMedium *pMed=new SfxMedium(
1914                 aTargetURL,(STREAM_STD_READWRITE | STREAM_SHARE_DENYALL),  sal_False, 0 );
1915             const SfxFilter* pFilter = NULL;
1916             pMed->UseInteractionHandler(sal_True);
1917             if( pSfxApp->GetFilterMatcher().GuessFilter(
1918                 *pMed, &pFilter, SFX_FILTER_TEMPLATE, 0 ) ||
1919                 (pFilter && !pFilter->IsOwnFormat()) ||
1920                 (pFilter && !pFilter->UsesStorage()) )
1921             {
1922                 SfxErrorContext aEc( ERRCTX_SFX_LOADTEMPLATE,
1923                                      aTargetURL );
1924                 delete pMed;
1925                 mbDidConvert=sal_True;
1926                 sal_uIntPtr lErr;
1927                 if ( mxObjShell.Is() ) {
1928                     lErr = pSfxApp->LoadTemplate( mxObjShell,aTargetURL);
1929                     if( lErr != ERRCODE_NONE )
1930                         ErrorHandler::HandleError(lErr);
1931                 }
1932 
1933             }
1934             else if (pFilter)
1935             {
1936                 mbDidConvert=sal_False;
1937                 mxObjShell = SfxObjectShell::CreateObject( pFilter->GetServiceName(), SFX_CREATE_MODE_ORGANIZER );
1938                 if ( mxObjShell.Is() )
1939                 {
1940                     mxObjShell->DoInitNew(0);
1941                     // TODO/LATER: make sure that we don't use binary templates!
1942                     if( mxObjShell->LoadFrom( *pMed ) )
1943                     {
1944                         mxObjShell->DoSaveCompleted( pMed );
1945                     }
1946                     else
1947                         mxObjShell.Clear();
1948                 }
1949             }
1950         }
1951     }
1952 
1953     return (SfxObjectShellRef)(SfxObjectShell*) mxObjShell;
1954 }
1955 
1956 //------------------------------------------------------------------------
1957 sal_Bool DocTempl_EntryData_Impl::DeleteObjectShell()
1958 {
1959     sal_Bool bRet = sal_True;
1960 
1961     if ( mxObjShell.Is() )
1962     {
1963         if( mxObjShell->IsModified() )
1964         {
1965             //Hier speichern wir auch, falls die Vorlage in Bearbeitung ist...
1966             bRet = sal_False;
1967 
1968             if ( mbIsOwner )
1969             {
1970                 if( mbDidConvert )
1971                 {
1972                     bRet=mxObjShell->PreDoSaveAs_Impl(
1973                         GetTargetURL(),
1974                         mxObjShell->GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_EXPORT | SFX_FILTER_IMPORT, SFX_FILTER_INTERNAL )->GetFilterName(), 0 );
1975                 }
1976                 else
1977                 {
1978                     if( mxObjShell->Save() )
1979                     {
1980                         uno::Reference< embed::XTransactedObject > xTransacted( mxObjShell->GetStorage(), uno::UNO_QUERY );
1981                         DBG_ASSERT( xTransacted.is(), "Storage must implement XTransactedObject!\n" );
1982                         if ( xTransacted.is() )
1983                         {
1984                             try
1985                             {
1986                                 xTransacted->commit();
1987                                 bRet = sal_True;
1988                             }
1989                             catch( uno::Exception& )
1990                             {
1991                             }
1992                         }
1993                     }
1994                 }
1995             }
1996         }
1997 
1998         if( bRet )
1999         {
2000             mxObjShell.Clear();
2001         }
2002     }
2003     return bRet;
2004 }
2005 
2006 // -----------------------------------------------------------------------
2007 const OUString& DocTempl_EntryData_Impl::GetHierarchyURL()
2008 {
2009     if ( !maOwnURL.getLength() )
2010     {
2011         INetURLObject aTemplateObj( GetParent()->GetHierarchyURL() );
2012 
2013         aTemplateObj.insertName( GetTitle(), false,
2014                      INetURLObject::LAST_SEGMENT, true,
2015                      INetURLObject::ENCODE_ALL );
2016 
2017         maOwnURL = aTemplateObj.GetMainURL( INetURLObject::NO_DECODE );
2018         DBG_ASSERT( maOwnURL.getLength(), "GetHierarchyURL(): Could not create URL!" );
2019     }
2020 
2021     return maOwnURL;
2022 }
2023 
2024 // -----------------------------------------------------------------------
2025 const OUString& DocTempl_EntryData_Impl::GetTargetURL()
2026 {
2027     if ( !maTargetURL.getLength() )
2028     {
2029         uno::Reference< XCommandEnvironment > aCmdEnv;
2030         Content aRegion;
2031 
2032         if ( Content::create( GetHierarchyURL(), aCmdEnv, aRegion ) )
2033         {
2034             OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_URL ) );
2035 
2036             getTextProperty_Impl( aRegion, aPropName, maTargetURL );
2037         }
2038         else
2039         {
2040             DBG_ERRORFILE( "GetTargetURL(): Could not create hierarchy content!" );
2041         }
2042     }
2043 
2044     return maTargetURL;
2045 }
2046 
2047 // -----------------------------------------------------------------------
2048 // -----------------------------------------------------------------------
2049 // -----------------------------------------------------------------------
2050 // -----------------------------------------------------------------------
2051 RegionData_Impl::RegionData_Impl( const SfxDocTemplate_Impl* pParent,
2052                                   const OUString& rTitle )
2053 {
2054     maTitle     = rTitle;
2055     mpParent    = pParent;
2056 }
2057 
2058 // -----------------------------------------------------------------------
2059 RegionData_Impl::~RegionData_Impl()
2060 {
2061     DocTempl_EntryData_Impl *pData = maEntries.First();
2062 
2063     while ( pData )
2064     {
2065         delete pData;
2066         pData = maEntries.Next();
2067     }
2068 }
2069 
2070 // -----------------------------------------------------------------------
2071 long RegionData_Impl::GetEntryPos( const OUString& rTitle,
2072                                    sal_Bool& rFound ) const
2073 {
2074 #if 1   // Don't use binary search today
2075     sal_uIntPtr i;
2076     sal_uIntPtr nCount = maEntries.Count();
2077 
2078     for ( i=0; i<nCount; i++ )
2079     {
2080         DocTempl_EntryData_Impl *pData = maEntries.GetObject( i );
2081 
2082         if ( pData->Compare( rTitle ) == 0 )
2083         {
2084             rFound = sal_True;
2085             return i;
2086         }
2087     }
2088 
2089     rFound = sal_False;
2090     return i;
2091 
2092 #else
2093     // use binary search to find the correct position
2094     // in the maEntries list
2095 
2096     int     nCompVal = 1;
2097     long    nStart = 0;
2098     long    nEnd = maEntries.Count() - 1;
2099     long    nMid;
2100 
2101     DocTempl_EntryData_Impl* pMid;
2102 
2103     rFound = sal_False;
2104 
2105     while ( nCompVal && ( nStart <= nEnd ) )
2106     {
2107         nMid = ( nEnd - nStart ) / 2 + nStart;
2108         pMid = maEntries.GetObject( nMid );
2109 
2110         nCompVal = pMid->Compare( rTitle );
2111 
2112         if ( nCompVal < 0 )     // pMid < pData
2113             nStart = nMid + 1;
2114         else
2115             nEnd = nMid - 1;
2116     }
2117 
2118     if ( nCompVal == 0 )
2119     {
2120         rFound = sal_True;
2121     }
2122     else
2123     {
2124         if ( nCompVal < 0 )     // pMid < pData
2125             nMid++;
2126     }
2127 
2128     return nMid;
2129 #endif
2130 }
2131 
2132 // -----------------------------------------------------------------------
2133 void RegionData_Impl::AddEntry( const OUString& rTitle,
2134                                 const OUString& rTargetURL,
2135                                 sal_uInt16 *pPos )
2136 {
2137     INetURLObject aLinkObj( GetHierarchyURL() );
2138     aLinkObj.insertName( rTitle, false,
2139                       INetURLObject::LAST_SEGMENT, true,
2140                       INetURLObject::ENCODE_ALL );
2141     OUString aLinkURL = aLinkObj.GetMainURL( INetURLObject::NO_DECODE );
2142 
2143     DocTempl_EntryData_Impl *pEntry;
2144     sal_Bool        bFound = sal_False;
2145     long            nPos = GetEntryPos( rTitle, bFound );
2146 
2147     if ( bFound )
2148     {
2149         pEntry = maEntries.GetObject( nPos );
2150     }
2151     else
2152     {
2153         if ( pPos )
2154             nPos = *pPos;
2155 
2156         pEntry = new DocTempl_EntryData_Impl( this, rTitle );
2157         pEntry->SetTargetURL( rTargetURL );
2158         pEntry->SetHierarchyURL( aLinkURL );
2159         maEntries.Insert( pEntry, nPos );
2160     }
2161 }
2162 
2163 // -----------------------------------------------------------------------
2164 sal_uIntPtr RegionData_Impl::GetCount() const
2165 {
2166     return maEntries.Count();
2167 }
2168 
2169 // -----------------------------------------------------------------------
2170 const OUString& RegionData_Impl::GetHierarchyURL()
2171 {
2172     if ( !maOwnURL.getLength() )
2173     {
2174         INetURLObject aRegionObj( GetParent()->GetRootURL() );
2175 
2176         aRegionObj.insertName( GetTitle(), false,
2177                      INetURLObject::LAST_SEGMENT, true,
2178                      INetURLObject::ENCODE_ALL );
2179 
2180         maOwnURL = aRegionObj.GetMainURL( INetURLObject::NO_DECODE );
2181         DBG_ASSERT( maOwnURL.getLength(), "GetHierarchyURL(): Could not create URL!" );
2182     }
2183 
2184     return maOwnURL;
2185 }
2186 
2187 // -----------------------------------------------------------------------
2188 const OUString& RegionData_Impl::GetTargetURL()
2189 {
2190     if ( !maTargetURL.getLength() )
2191     {
2192         uno::Reference< XCommandEnvironment > aCmdEnv;
2193         Content aRegion;
2194 
2195         if ( Content::create( GetHierarchyURL(), aCmdEnv, aRegion ) )
2196         {
2197             OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TARGET_DIR_URL ) );
2198 
2199             getTextProperty_Impl( aRegion, aPropName, maTargetURL );
2200             // --> PB 2004-10-27 #i32656# - the targeturl must be substituted: $(baseinsturl)
2201             maTargetURL = SvtPathOptions().SubstituteVariable( maTargetURL );
2202             // <--
2203         }
2204         else
2205         {
2206             DBG_ERRORFILE( "GetTargetURL(): Could not create hierarchy content!" );
2207         }
2208     }
2209 
2210     return maTargetURL;
2211 }
2212 
2213 // -----------------------------------------------------------------------
2214 DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( const OUString& rName ) const
2215 {
2216     sal_Bool    bFound = sal_False;
2217     long        nPos = GetEntryPos( rName, bFound );
2218 
2219     if ( bFound )
2220         return maEntries.GetObject( nPos );
2221     else
2222         return NULL;
2223 }
2224 
2225 // -----------------------------------------------------------------------
2226 DocTempl_EntryData_Impl* RegionData_Impl::GetByTargetURL( const OUString& rName ) const
2227 {
2228     DocTempl_EntryData_Impl *pEntry;
2229 
2230     sal_uIntPtr nCount = maEntries.Count();
2231 
2232     for ( sal_uIntPtr i=0; i<nCount; i++ )
2233     {
2234         pEntry = maEntries.GetObject( i );
2235         if ( pEntry && ( pEntry->GetTargetURL() == rName ) )
2236             return pEntry;
2237     }
2238 
2239     return NULL;
2240 }
2241 
2242 // -----------------------------------------------------------------------
2243 DocTempl_EntryData_Impl* RegionData_Impl::GetEntry( sal_uIntPtr nIndex ) const
2244 {
2245     return maEntries.GetObject( nIndex );
2246 }
2247 
2248 // -----------------------------------------------------------------------
2249 void RegionData_Impl::DeleteEntry( sal_uIntPtr nIndex )
2250 {
2251     DocTempl_EntryData_Impl *pEntry = maEntries.GetObject( nIndex );
2252 
2253     if ( pEntry )
2254     {
2255         delete pEntry;
2256         maEntries.Remove( (sal_uIntPtr) nIndex );
2257     }
2258 }
2259 
2260 // -----------------------------------------------------------------------
2261 int RegionData_Impl::Compare( RegionData_Impl* pCompare ) const
2262 {
2263     int nCompare = maTitle.compareTo( pCompare->maTitle );
2264 
2265     return nCompare;
2266 }
2267 
2268 // -----------------------------------------------------------------------
2269 // -----------------------------------------------------------------------
2270 // -----------------------------------------------------------------------
2271 
2272 SfxDocTemplate_Impl::SfxDocTemplate_Impl()
2273 : mbConstructed( sal_False )
2274 , mnLockCounter( 0 )
2275 {
2276 }
2277 
2278 // -----------------------------------------------------------------------
2279 SfxDocTemplate_Impl::~SfxDocTemplate_Impl()
2280 {
2281     Clear();
2282 
2283     gpTemplateData = NULL;
2284 }
2285 
2286 // -----------------------------------------------------------------------
2287 void SfxDocTemplate_Impl::IncrementLock()
2288 {
2289     ::osl::MutexGuard aGuard( maMutex );
2290     mnLockCounter++;
2291 }
2292 
2293 // -----------------------------------------------------------------------
2294 void SfxDocTemplate_Impl::DecrementLock()
2295 {
2296     ::osl::MutexGuard aGuard( maMutex );
2297     if ( mnLockCounter )
2298         mnLockCounter--;
2299 }
2300 
2301 // -----------------------------------------------------------------------
2302 RegionData_Impl* SfxDocTemplate_Impl::GetRegion( sal_uIntPtr nIndex ) const
2303 {
2304     return maRegions.GetObject( nIndex );
2305 }
2306 
2307 // -----------------------------------------------------------------------
2308 RegionData_Impl* SfxDocTemplate_Impl::GetRegion( const OUString& rName )
2309     const
2310 {
2311     sal_uIntPtr nCount = maRegions.Count();
2312     RegionData_Impl *pData;
2313 
2314     for ( sal_uIntPtr i=0; i<nCount; i++ )
2315     {
2316         pData = maRegions.GetObject( i );
2317 
2318         if ( pData->GetTitle() == rName )
2319             return pData;
2320     }
2321 
2322     return NULL;
2323 }
2324 
2325 // -----------------------------------------------------------------------
2326 void SfxDocTemplate_Impl::DeleteRegion( sal_uIntPtr nIndex )
2327 {
2328     RegionData_Impl* pRegion = maRegions.GetObject( nIndex );
2329 
2330     if ( pRegion )
2331     {
2332         delete pRegion;
2333         maRegions.Remove( (sal_uIntPtr) nIndex );
2334     }
2335 }
2336 
2337 // -----------------------------------------------------------------------
2338 /*  AddRegion adds a Region to the RegionList
2339 */
2340 void SfxDocTemplate_Impl::AddRegion( const OUString& rTitle,
2341                                      Content& rContent )
2342 {
2343     RegionData_Impl* pRegion;
2344     pRegion = new RegionData_Impl( this, rTitle );
2345 
2346     if ( ! InsertRegion( pRegion ) )
2347     {
2348         delete pRegion;
2349         return;
2350     }
2351 
2352     // now get the content of the region
2353     uno::Reference< XResultSet > xResultSet;
2354     Sequence< OUString > aProps(2);
2355     aProps[0] = OUString::createFromAscii( TITLE );
2356     aProps[1] = OUString::createFromAscii( TARGET_URL );
2357 
2358     try
2359     {
2360         ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
2361         Sequence< NumberedSortingInfo >     aSortingInfo(1);
2362         aSortingInfo.getArray()->ColumnIndex = 1;
2363         aSortingInfo.getArray()->Ascending = sal_True;
2364         xResultSet = rContent.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
2365     }
2366     catch ( Exception& ) {}
2367 
2368     if ( xResultSet.is() )
2369     {
2370         uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2371         uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2372 
2373         try
2374         {
2375             while ( xResultSet->next() )
2376             {
2377                 OUString aTitle( xRow->getString( 1 ) );
2378                 OUString aTargetDir( xRow->getString( 2 ) );
2379 
2380                 pRegion->AddEntry( aTitle, aTargetDir );
2381             }
2382         }
2383         catch ( Exception& ) {}
2384     }
2385 }
2386 
2387 // -----------------------------------------------------------------------
2388 void SfxDocTemplate_Impl::CreateFromHierarchy( Content &rTemplRoot )
2389 {
2390     uno::Reference< XResultSet > xResultSet;
2391     Sequence< OUString > aProps(1);
2392     aProps[0] = OUString::createFromAscii( TITLE );
2393 
2394     try
2395     {
2396         ResultSetInclude eInclude = INCLUDE_FOLDERS_ONLY;
2397         Sequence< NumberedSortingInfo >     aSortingInfo(1);
2398         aSortingInfo.getArray()->ColumnIndex = 1;
2399         aSortingInfo.getArray()->Ascending = sal_True;
2400         xResultSet = rTemplRoot.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
2401     }
2402     catch ( Exception& ) {}
2403 
2404     if ( xResultSet.is() )
2405     {
2406         uno::Reference< XCommandEnvironment > aCmdEnv;
2407         uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2408         uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2409 
2410         try
2411         {
2412             while ( xResultSet->next() )
2413             {
2414                 OUString aTitle( xRow->getString( 1 ) );
2415 
2416                 OUString aId = xContentAccess->queryContentIdentifierString();
2417                 Content  aContent = Content( aId, aCmdEnv );
2418 
2419                 AddRegion( aTitle, aContent );
2420             }
2421         }
2422         catch ( Exception& ) {}
2423     }
2424 }
2425 
2426 // ------------------------------------------------------------------------
2427 sal_Bool SfxDocTemplate_Impl::Construct( )
2428 {
2429     ::osl::MutexGuard aGuard( maMutex );
2430 
2431     if ( mbConstructed )
2432         return sal_True;
2433 
2434     uno::Reference< XMultiServiceFactory >   xFactory;
2435     xFactory = ::comphelper::getProcessServiceFactory();
2436 
2437     OUString aService( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DOCINFO ) );
2438     uno::Reference< XPersist > xInfo( xFactory->createInstance( aService ), UNO_QUERY );
2439     mxInfo = xInfo;
2440 
2441     aService = OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICENAME_DOCTEMPLATES ) );
2442     uno::Reference< XDocumentTemplates > xTemplates( xFactory->createInstance( aService ), UNO_QUERY );
2443 
2444     if ( xTemplates.is() )
2445         mxTemplates = xTemplates;
2446     else
2447         return sal_False;
2448 
2449     uno::Reference< XLocalizable > xLocalizable( xTemplates, UNO_QUERY );
2450 
2451     Sequence< Any > aCompareArg(1);
2452     *(aCompareArg.getArray()) <<= xLocalizable->getLocale();;
2453     m_rCompareFactory = uno::Reference< XAnyCompareFactory >(
2454                     xFactory->createInstanceWithArguments( OUString::createFromAscii( "com.sun.star.ucb.AnyCompareFactory" ),
2455                                                            aCompareArg ),
2456                     UNO_QUERY );
2457 
2458     uno::Reference < XContent > aRootContent = xTemplates->getContent();
2459     uno::Reference < XCommandEnvironment > aCmdEnv;
2460 
2461     if ( ! aRootContent.is() )
2462         return sal_False;
2463 
2464     mbConstructed = sal_True;
2465     maRootURL = aRootContent->getIdentifier()->getContentIdentifier();
2466 
2467     ResStringArray  aLongNames( SfxResId( TEMPLATE_LONG_NAMES_ARY ) );
2468 
2469     if ( aLongNames.Count() )
2470         maStandardGroup = aLongNames.GetString( 0 );
2471 
2472     Content aTemplRoot( aRootContent, aCmdEnv );
2473     CreateFromHierarchy( aTemplRoot );
2474 
2475     return sal_True;
2476 }
2477 
2478 // -----------------------------------------------------------------------
2479 void SfxDocTemplate_Impl::ReInitFromComponent()
2480 {
2481     uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
2482     if ( xTemplates.is() )
2483     {
2484         uno::Reference < XContent > aRootContent = xTemplates->getContent();
2485         uno::Reference < XCommandEnvironment > aCmdEnv;
2486         Content aTemplRoot( aRootContent, aCmdEnv );
2487         Clear();
2488         CreateFromHierarchy( aTemplRoot );
2489     }
2490 }
2491 
2492 // -----------------------------------------------------------------------
2493 void SfxDocTemplate_Impl::GetTemplates( Content& rTargetFolder,
2494                                         Content& /*rParentFolder*/,
2495                                         RegionData_Impl* pRegion )
2496 {
2497     uno::Reference< XResultSet > xResultSet;
2498     Sequence< OUString >    aProps(1);
2499 
2500     aProps[0] = OUString::createFromAscii( TITLE );
2501 
2502     try
2503     {
2504         ResultSetInclude eInclude = INCLUDE_DOCUMENTS_ONLY;
2505         Sequence< NumberedSortingInfo >     aSortingInfo(1);
2506         aSortingInfo.getArray()->ColumnIndex = 1;
2507         aSortingInfo.getArray()->Ascending = sal_True;
2508         xResultSet = rTargetFolder.createSortedCursor( aProps, aSortingInfo, m_rCompareFactory, eInclude );
2509     }
2510     catch ( Exception& ) {}
2511 
2512     if ( xResultSet.is() )
2513     {
2514         uno::Reference< XContentAccess > xContentAccess( xResultSet, UNO_QUERY );
2515         uno::Reference< XRow > xRow( xResultSet, UNO_QUERY );
2516 
2517         try
2518         {
2519             while ( xResultSet->next() )
2520             {
2521                 OUString aTitle( xRow->getString(1) );
2522 
2523                 if ( aTitle.compareToAscii( "sfx.tlx" ) == 0 )
2524                     continue;
2525 
2526                 OUString aId = xContentAccess->queryContentIdentifierString();
2527 
2528                 DocTempl_EntryData_Impl* pEntry = pRegion->GetByTargetURL( aId );
2529 
2530                 if ( ! pEntry )
2531                 {
2532                     OUString aFullTitle;
2533                     if( !GetTitleFromURL( aId, aFullTitle ) )
2534                     {
2535                         DBG_ERRORFILE( "GetTemplates(): template of alien format" );
2536                         continue;
2537                     }
2538 
2539                     if ( aFullTitle.getLength() )
2540                         aTitle = aFullTitle;
2541 
2542                     pRegion->AddEntry( aTitle, aId );
2543                 }
2544             }
2545         }
2546         catch ( Exception& ) {}
2547     }
2548 }
2549 
2550 
2551 // -----------------------------------------------------------------------
2552 long SfxDocTemplate_Impl::GetRegionPos( const OUString& rTitle,
2553                                         sal_Bool& rFound ) const
2554 {
2555     int     nCompVal = 1;
2556     long    nStart = 0;
2557     long    nEnd = maRegions.Count() - 1;
2558     long    nMid = 0;
2559 
2560     RegionData_Impl* pMid;
2561 
2562     while ( nCompVal && ( nStart <= nEnd ) )
2563     {
2564         nMid = ( nEnd - nStart ) / 2 + nStart;
2565         pMid = maRegions.GetObject( nMid );
2566 
2567         nCompVal = pMid->Compare( rTitle );
2568 
2569         if ( nCompVal < 0 )     // pMid < pData
2570             nStart = nMid + 1;
2571         else
2572             nEnd = nMid - 1;
2573     }
2574 
2575     if ( nCompVal == 0 )
2576         rFound = sal_True;
2577     else
2578     {
2579         if ( nCompVal < 0 )     // pMid < pData
2580             nMid++;
2581 
2582         rFound = sal_False;
2583     }
2584 
2585     return nMid;
2586 }
2587 
2588 // -----------------------------------------------------------------------
2589 sal_Bool SfxDocTemplate_Impl::InsertRegion( RegionData_Impl *pNew,
2590                                             sal_uIntPtr nPos )
2591 {
2592     ::osl::MutexGuard   aGuard( maMutex );
2593     RegionData_Impl    *pData = maRegions.First();
2594 
2595     while ( pData && ( pData->Compare( pNew ) != 0 ) )
2596         pData = maRegions.Next();
2597 
2598     if ( ! pData )
2599     {
2600         // compare with the name of the standard group here to insert it
2601         // first
2602 
2603         if ( pNew->GetTitle() == maStandardGroup )
2604             maRegions.Insert( pNew, (sal_uIntPtr) 0 );
2605         else
2606             maRegions.Insert( pNew, nPos );
2607     }
2608 
2609     return ( pData == NULL );
2610 }
2611 
2612 // -----------------------------------------------------------------------
2613 void SfxDocTemplate_Impl::Rescan()
2614 {
2615     Clear();
2616 
2617     try
2618     {
2619         uno::Reference< XDocumentTemplates > xTemplates = getDocTemplates();
2620         DBG_ASSERT( xTemplates.is(), "SfxDocTemplate_Impl::Rescan:invalid template instance!" );
2621         if ( xTemplates.is() )
2622         {
2623             xTemplates->update();
2624 
2625             uno::Reference < XContent > aRootContent = xTemplates->getContent();
2626             uno::Reference < XCommandEnvironment > aCmdEnv;
2627 
2628             Content aTemplRoot( aRootContent, aCmdEnv );
2629             CreateFromHierarchy( aTemplRoot );
2630         }
2631     }
2632     catch( const Exception& )
2633     {
2634         DBG_ERRORFILE( "SfxDocTemplate_Impl::Rescan: caught an exception while doing the update!" );
2635     }
2636 }
2637 
2638 // -----------------------------------------------------------------------
2639 sal_Bool SfxDocTemplate_Impl::GetTitleFromURL( const OUString& rURL,
2640                                            OUString& aTitle )
2641 {
2642     if ( mxInfo.is() )
2643     {
2644         try
2645         {
2646             mxInfo->read( rURL );
2647         }
2648         catch ( Exception& )
2649         {
2650             // the document is not a StarOffice document
2651             return sal_False;
2652         }
2653 
2654 
2655         try
2656         {
2657             uno::Reference< XPropertySet > aPropSet( mxInfo, UNO_QUERY );
2658             if ( aPropSet.is() )
2659             {
2660                 OUString aPropName( RTL_CONSTASCII_USTRINGPARAM( TITLE ) );
2661                 Any aValue = aPropSet->getPropertyValue( aPropName );
2662                 aValue >>= aTitle;
2663             }
2664         }
2665         catch ( IOException& ) {}
2666         catch ( UnknownPropertyException& ) {}
2667         catch ( Exception& ) {}
2668     }
2669 
2670     if ( ! aTitle.getLength() )
2671     {
2672         INetURLObject aURL( rURL );
2673         aURL.CutExtension();
2674         aTitle = aURL.getName( INetURLObject::LAST_SEGMENT, true,
2675                                INetURLObject::DECODE_WITH_CHARSET );
2676     }
2677 
2678     return sal_True;
2679 }
2680 
2681 
2682 // -----------------------------------------------------------------------
2683 void SfxDocTemplate_Impl::Clear()
2684 {
2685     ::osl::MutexGuard   aGuard( maMutex );
2686     if ( mnLockCounter )
2687         return;
2688 
2689     RegionData_Impl *pRegData = maRegions.First();
2690 
2691     while ( pRegData )
2692     {
2693         delete pRegData;
2694         pRegData = maRegions.Next();
2695     }
2696 
2697     maRegions.Clear();
2698 }
2699 
2700 // -----------------------------------------------------------------------
2701 // -----------------------------------------------------------------------
2702 // -----------------------------------------------------------------------
2703 sal_Bool getTextProperty_Impl( Content& rContent,
2704                                const OUString& rPropName,
2705                                OUString& rPropValue )
2706 {
2707     sal_Bool bGotProperty = sal_False;
2708 
2709     // Get the property
2710     try
2711     {
2712         uno::Reference< XPropertySetInfo > aPropInfo = rContent.getProperties();
2713 
2714         // check, wether or not the property exists
2715         if ( !aPropInfo.is() || !aPropInfo->hasPropertyByName( rPropName ) )
2716         {
2717             return sal_False;
2718         }
2719 
2720         // now get the property
2721         Any aAnyValue;
2722 
2723         aAnyValue = rContent.getPropertyValue( rPropName );
2724         aAnyValue >>= rPropValue;
2725 
2726         if ( SfxURLRelocator_Impl::propertyCanContainOfficeDir( rPropName ) )
2727         {
2728             SfxURLRelocator_Impl aRelocImpl( ::comphelper::getProcessServiceFactory() );
2729             aRelocImpl.makeAbsoluteURL( rPropValue );
2730         }
2731 
2732         bGotProperty = sal_True;
2733     }
2734     catch ( RuntimeException& ) {}
2735     catch ( Exception& ) {}
2736 
2737     return bGotProperty;
2738 }
2739 
2740