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