filter/CppunitTest_filter_textfilterdetect.mk   |    1 
 filter/qa/unit/data/calc.ots                    |binary
 filter/qa/unit/data/impress.otp                 |binary
 filter/qa/unit/data/writer.ott                  |binary
 filter/qa/unit/textfilterdetect.cxx             |  159 +++++++++++++++---------
 filter/source/textfilterdetect/filterdetect.cxx |   53 --------
 sfx2/source/doc/objstor.cxx                     |   12 -
 sfx2/source/view/frmload.cxx                    |   60 +++++++++
 8 files changed, 170 insertions(+), 115 deletions(-)

New commits:
commit 064f4fe82c30118a34c4aeb47bf8604f0b8356a1
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Wed Apr 13 08:40:23 2022 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Wed Apr 13 15:46:59 2022 +0200

    tdf#139991: move 0-byte file handling to SfxFrameLoader_Impl::load
    
    This centralizes the code that handles templates, and allows the empty
    files to use default templates.
    
    This partially reverts commits:
    
    ada07f303e7cd1e39c73abe0741aefe7d9d73a57
      Author Miklos Vajna <vmik...@collabora.com>
      Date   Wed Oct 28 14:54:52 2020 +0100
        tdf#123476 filter: try to detect 0-byte files based on extension
    
    2854362f429e476d4a1ab4759c6a1f1c04150280
      Author Mike Kaganski <mike.kagan...@collabora.com>
      Date   Wed Jan 27 16:05:54 2021 +0100
       tdf#123476 filter: Also handle empty ODF
    
    dff586735b6618d9b011823594a33287d8f7f223
      Author Mike Kaganski <mike.kagan...@collabora.com>
      Date   Mon May 03 17:04:04 2021 +0200
        tdf#123476: also use filter by extension when its service is the same
    
    The unit tests from these commits are retained and extended for templates.
    
    Change-Id: I755738d2d5a6d6955d84d6e12f3accc017e0391f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132938
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/filter/CppunitTest_filter_textfilterdetect.mk 
b/filter/CppunitTest_filter_textfilterdetect.mk
index 4066c26591a3..6fb22f8b074e 100644
--- a/filter/CppunitTest_filter_textfilterdetect.mk
+++ b/filter/CppunitTest_filter_textfilterdetect.mk
@@ -21,6 +21,7 @@ $(eval $(call 
gb_CppunitTest_use_libraries,filter_textfilterdetect, \
        cppu \
        cppuhelper \
        sal \
+       sfx \
        test \
        textfd \
        tl \
diff --git a/filter/qa/unit/data/calc.ots b/filter/qa/unit/data/calc.ots
new file mode 100644
index 000000000000..d16d2307fee9
Binary files /dev/null and b/filter/qa/unit/data/calc.ots differ
diff --git a/filter/qa/unit/data/impress.otp b/filter/qa/unit/data/impress.otp
new file mode 100644
index 000000000000..199a5f9d470f
Binary files /dev/null and b/filter/qa/unit/data/impress.otp differ
diff --git a/filter/qa/unit/data/writer.ott b/filter/qa/unit/data/writer.ott
new file mode 100644
index 000000000000..1ded03150e01
Binary files /dev/null and b/filter/qa/unit/data/writer.ott differ
diff --git a/filter/qa/unit/textfilterdetect.cxx 
b/filter/qa/unit/textfilterdetect.cxx
index bbb9b91b527f..3c8daf2f2ef9 100644
--- a/filter/qa/unit/textfilterdetect.cxx
+++ b/filter/qa/unit/textfilterdetect.cxx
@@ -13,8 +13,13 @@
 #include <com/sun/star/document/XExtendedFilterDetection.hpp>
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/sheet/XCellRangesAccess.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
 
 #include <comphelper/propertyvalue.hxx>
+#include <sfx2/docfac.hxx>
 #include <unotools/mediadescriptor.hxx>
 #include <unotools/streamwrap.hxx>
 #include <tools/stream.hxx>
@@ -31,12 +36,8 @@ namespace
 /// Test class for PlainTextFilterDetect.
 class TextFilterDetectTest : public test::BootstrapFixture, public 
unotest::MacrosTest
 {
-    uno::Reference<lang::XComponent> mxComponent;
-
 public:
     void setUp() override;
-    void tearDown() override;
-    uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
 };
 
 void TextFilterDetectTest::setUp()
@@ -46,14 +47,6 @@ void TextFilterDetectTest::setUp()
     mxDesktop.set(frame::Desktop::create(mxComponentContext));
 }
 
-void TextFilterDetectTest::tearDown()
-{
-    if (mxComponent.is())
-        mxComponent->dispose();
-
-    test::BootstrapFixture::tearDown();
-}
-
 constexpr OUStringLiteral DATA_DIRECTORY = u"/filter/qa/unit/data/";
 
 CPPUNIT_TEST_FIXTURE(TextFilterDetectTest, testTdf114428)
@@ -78,68 +71,126 @@ CPPUNIT_TEST_FIXTURE(TextFilterDetectTest, testTdf114428)
 
 CPPUNIT_TEST_FIXTURE(TextFilterDetectTest, testEmptyFile)
 {
-    // Given an empty file, with a pptx extension
-    OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "empty.pptx";
+    const OUString sDataDirectory = 
m_directories.getURLFromSrc(DATA_DIRECTORY);
+    auto supportsService = [](const uno::Reference<lang::XComponent>& x, const 
OUString& s) {
+        return uno::Reference<lang::XServiceInfo>(x, 
uno::UNO_QUERY_THROW)->supportsService(s);
+    };
 
+    // Given an empty file, with a pptx extension
     // When loading the file
-    getComponent() = loadFromDesktop(aURL);
+    auto xComponent = loadFromDesktop(sDataDirectory + "empty.pptx");
 
     // Then make sure it is opened in Impress.
-    uno::Reference<lang::XServiceInfo> xServiceInfo(getComponent(), 
uno::UNO_QUERY);
-    CPPUNIT_ASSERT(xServiceInfo.is());
-
     // Without the accompanying fix in place, this test would have failed, as 
it was opened in
     // Writer instead.
-    
CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.presentation.PresentationDocument"));
-
-    getComponent()->dispose();
+    CPPUNIT_ASSERT(supportsService(xComponent, 
"com.sun.star.presentation.PresentationDocument"));
+    xComponent->dispose();
 
     // Now also test ODT
-    aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "empty.odt";
-    getComponent() = loadFromDesktop(aURL);
-    xServiceInfo.set(getComponent(), uno::UNO_QUERY);
-    CPPUNIT_ASSERT(xServiceInfo.is());
+    xComponent = loadFromDesktop(sDataDirectory + "empty.odt");
     // Make sure it opens in Writer.
-    
CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextDocument"));
-    getComponent()->dispose();
+    CPPUNIT_ASSERT(supportsService(xComponent, 
"com.sun.star.text.TextDocument"));
+    xComponent->dispose();
 
     // ... and ODS
-    aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "empty.ods";
-    getComponent() = loadFromDesktop(aURL);
-    xServiceInfo.set(getComponent(), uno::UNO_QUERY);
-    CPPUNIT_ASSERT(xServiceInfo.is());
+    xComponent = loadFromDesktop(sDataDirectory + "empty.ods");
     // Make sure it opens in Calc.
-    
CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument"));
-    getComponent()->dispose();
+    CPPUNIT_ASSERT(supportsService(xComponent, 
"com.sun.star.sheet.SpreadsheetDocument"));
+    xComponent->dispose();
 
     // ... and ODP
-    aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "empty.odp";
-    getComponent() = loadFromDesktop(aURL);
-    xServiceInfo.set(getComponent(), uno::UNO_QUERY);
-    CPPUNIT_ASSERT(xServiceInfo.is());
+    xComponent = loadFromDesktop(sDataDirectory + "empty.odp");
     // Without the accompanying fix in place, this test would have failed, as 
it was opened in
     // Writer instead.
-    
CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.presentation.PresentationDocument"));
-    getComponent()->dispose();
+    CPPUNIT_ASSERT(supportsService(xComponent, 
"com.sun.star.presentation.PresentationDocument"));
+    xComponent->dispose();
 
     // ... and DOC
-    aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "empty.doc";
     // Without the accompanying fix in place, this test would have failed, the 
import filter aborted
     // loading.
-    getComponent() = loadFromDesktop(aURL);
-    xServiceInfo.set(getComponent(), uno::UNO_QUERY);
-    CPPUNIT_ASSERT(xServiceInfo.is());
-    
CPPUNIT_ASSERT(xServiceInfo->supportsService("com.sun.star.text.TextDocument"));
-    uno::Reference<frame::XModel> xModel(getComponent(), uno::UNO_QUERY);
-    uno::Sequence<beans::PropertyValue> aArgs = xModel->getArgs();
-    comphelper::SequenceAsHashMap aMap(aArgs);
-    OUString aFilterName;
-    aMap["FilterName"] >>= aFilterName;
-    // Without the accompanying fix in place, this test would have failed with:
-    // - Expected: MS Word 97
-    // - Actual  : MS WinWord 6.0
-    // i.e. opening worked, but saving back failed instead of producing a WW8 
binary file.
-    CPPUNIT_ASSERT_EQUAL(OUString("MS Word 97"), aFilterName);
+    xComponent = loadFromDesktop(sDataDirectory + "empty.doc");
+    CPPUNIT_ASSERT(supportsService(xComponent, 
"com.sun.star.text.TextDocument"));
+    {
+        uno::Reference<frame::XModel> xModel(xComponent, uno::UNO_QUERY);
+        uno::Sequence<beans::PropertyValue> aArgs = xModel->getArgs();
+        comphelper::SequenceAsHashMap aMap(aArgs);
+        OUString aFilterName;
+        aMap["FilterName"] >>= aFilterName;
+        // Without the accompanying fix in place, this test would have failed 
with:
+        // - Expected: MS Word 97
+        // - Actual  : MS WinWord 6.0
+        // i.e. opening worked, but saving back failed instead of producing a 
WW8 binary file.
+        CPPUNIT_ASSERT_EQUAL(OUString("MS Word 97"), aFilterName);
+    }
+    xComponent->dispose();
+
+    // Now test with default templates set
+
+    
SfxObjectFactory::SetStandardTemplate("com.sun.star.presentation.PresentationDocument",
+                                          sDataDirectory + "impress.otp");
+    SfxObjectFactory::SetStandardTemplate("com.sun.star.text.TextDocument",
+                                          sDataDirectory + "writer.ott");
+    
SfxObjectFactory::SetStandardTemplate("com.sun.star.sheet.SpreadsheetDocument",
+                                          sDataDirectory + "calc.ots");
+
+    xComponent = loadFromDesktop(sDataDirectory + "empty.pptx");
+    {
+        uno::Reference<drawing::XDrawPagesSupplier> xDoc(xComponent, 
uno::UNO_QUERY_THROW);
+        uno::Reference<drawing::XDrawPages> xPages(xDoc->getDrawPages(), 
uno::UNO_SET_THROW);
+        uno::Reference<drawing::XDrawPage> xPage(xPages->getByIndex(0), 
uno::UNO_QUERY_THROW);
+        uno::Reference<text::XTextRange> xBox(xPage->getByIndex(0), 
uno::UNO_QUERY_THROW);
+
+        // Make sure the template's text was loaded
+        CPPUNIT_ASSERT_EQUAL(OUString("Title of Impress template"), 
xBox->getString());
+    }
+    xComponent->dispose();
+
+    xComponent = loadFromDesktop(sDataDirectory + "empty.odt");
+    {
+        uno::Reference<text::XTextDocument> xDoc(xComponent, 
uno::UNO_QUERY_THROW);
+        uno::Reference<container::XEnumerationAccess> xEA(xDoc->getText(), 
uno::UNO_QUERY_THROW);
+        uno::Reference<container::XEnumeration> 
xEnum(xEA->createEnumeration(), uno::UNO_SET_THROW);
+        uno::Reference<text::XTextRange> xParagraph(xEnum->nextElement(), 
uno::UNO_QUERY_THROW);
+
+        // Make sure the template's text was loaded
+        CPPUNIT_ASSERT_EQUAL(OUString(u"Writer template’s first line"), 
xParagraph->getString());
+    }
+    xComponent->dispose();
+
+    xComponent = loadFromDesktop(sDataDirectory + "empty.ods");
+    {
+        uno::Reference<sheet::XSpreadsheetDocument> xDoc(xComponent, 
uno::UNO_QUERY_THROW);
+        uno::Reference<sheet::XCellRangesAccess> xRA(xDoc->getSheets(), 
uno::UNO_QUERY_THROW);
+        uno::Reference<text::XTextRange> xC(xRA->getCellByPosition(0, 0, 0), 
uno::UNO_QUERY_THROW);
+
+        // Make sure the template's text was loaded
+        CPPUNIT_ASSERT_EQUAL(OUString(u"Calc template’s first cell"), 
xC->getString());
+    }
+    xComponent->dispose();
+
+    xComponent = loadFromDesktop(sDataDirectory + "empty.odp");
+    {
+        uno::Reference<drawing::XDrawPagesSupplier> xDoc(xComponent, 
uno::UNO_QUERY_THROW);
+        uno::Reference<drawing::XDrawPages> xPages(xDoc->getDrawPages(), 
uno::UNO_SET_THROW);
+        uno::Reference<drawing::XDrawPage> xPage(xPages->getByIndex(0), 
uno::UNO_QUERY_THROW);
+        uno::Reference<text::XTextRange> xBox(xPage->getByIndex(0), 
uno::UNO_QUERY_THROW);
+
+        // Make sure the template's text was loaded
+        CPPUNIT_ASSERT_EQUAL(OUString("Title of Impress template"), 
xBox->getString());
+    }
+    xComponent->dispose();
+
+    xComponent = loadFromDesktop(sDataDirectory + "empty.doc");
+    {
+        uno::Reference<text::XTextDocument> xDoc(xComponent, 
uno::UNO_QUERY_THROW);
+        uno::Reference<container::XEnumerationAccess> xEA(xDoc->getText(), 
uno::UNO_QUERY_THROW);
+        uno::Reference<container::XEnumeration> 
xEnum(xEA->createEnumeration(), uno::UNO_SET_THROW);
+        uno::Reference<text::XTextRange> xParagraph(xEnum->nextElement(), 
uno::UNO_QUERY_THROW);
+
+        // Make sure the template's text was loaded
+        CPPUNIT_ASSERT_EQUAL(OUString(u"Writer template’s first line"), 
xParagraph->getString());
+    }
+    xComponent->dispose();
 }
 }
 
diff --git a/filter/source/textfilterdetect/filterdetect.cxx 
b/filter/source/textfilterdetect/filterdetect.cxx
index 0edbb1f4cc47..9d25e289ec89 100644
--- a/filter/source/textfilterdetect/filterdetect.cxx
+++ b/filter/source/textfilterdetect/filterdetect.cxx
@@ -20,8 +20,6 @@
 #include <com/sun/star/io/XInputStream.hpp>
 #include <cppuhelper/supportsservice.hxx>
 #include <memory>
-#include <sfx2/fcontnr.hxx>
-#include <sfx2/docfilt.hxx>
 
 constexpr OUStringLiteral WRITER_TEXT_FILTER = u"Text";
 constexpr OUStringLiteral CALC_TEXT_FILTER = u"Text - txt - csv (StarCalc)";
@@ -129,45 +127,6 @@ bool IsHTMLStream( const uno::Reference<io::XInputStream>& 
xInStream )
     OString aToken = sHeader.copy( nStartOfTagIndex, i - nStartOfTagIndex );
     return GetHTMLToken( OStringToOUString( aToken.toAsciiLowerCase(), 
RTL_TEXTENCODING_ASCII_US ) ) != HtmlTokenId::NONE;
 }
-
-/**
- * Given an (empty) file URL in rMediaDesc and rExt, looks up the best filter 
type for it and
- * writes the type name to rType, the filter name to rMediaDesc.
- */
-bool HandleEmptyFileUrlByExtension(MediaDescriptor& rMediaDesc, const 
OUString& rExt,
-                                   OUString& rType, OUString& rService)
-{
-    OUString aURL = 
rMediaDesc.getUnpackedValueOrDefault(MediaDescriptor::PROP_URL, OUString());
-    if (!tools::isEmptyFileUrl(aURL))
-    {
-        return false;
-    }
-
-    if (rExt.isEmpty())
-    {
-        return false;
-    }
-
-    // Requiring the export+preferred flags helps to find the relevant filter, 
e.g. .doc -> WW8 (and
-    // not WW6 or Mac_Word).
-    SfxFilterFlags nMust
-        = SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT | 
SfxFilterFlags::PREFERED;
-    std::shared_ptr<const SfxFilter> 
pFilter(SfxFilterMatcher().GetFilter4Extension(rExt, nMust));
-    if (!pFilter)
-    {
-        // retry without PREFERRED so we can find at least something for 
0-byte *.ods
-        nMust = SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT;
-        pFilter = SfxFilterMatcher().GetFilter4Extension(rExt, nMust);
-
-        if (!pFilter)
-            return false;
-    }
-
-    rMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= pFilter->GetFilterName();
-    rType = pFilter->GetTypeName();
-    rService = pFilter->GetServiceName();
-    return true;
-}
 }
 
 PlainTextFilterDetect::PlainTextFilterDetect() {}
@@ -226,15 +185,7 @@ OUString SAL_CALL 
PlainTextFilterDetect::detect(uno::Sequence<beans::PropertyVal
         OUString aName = aParser.getName().toAsciiLowerCase();
 
         // Decide which filter to use based on the document service first,
-        // then on extension if that's not available. Make exception for 
0-byte files
-        // whose extensions are handled by the same service as passed document 
service.
-        OUString aEmptyType, aEmptyService;
-        bool bEmpty = HandleEmptyFileUrlByExtension(aMediaDesc, aExt, 
aEmptyType, aEmptyService);
-        if (bEmpty && aDocService == aEmptyService)
-        {
-            aDocService.clear(); // don't fallback to text filter, use 
extension-based match
-            // TODO: maybe reset aExt when it's "xls"
-        }
+        // then on extension if that's not available.
 
         if (aDocService == CALC_DOCSERVICE)
             aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= 
OUString(CALC_TEXT_FILTER);
@@ -242,8 +193,6 @@ OUString SAL_CALL 
PlainTextFilterDetect::detect(uno::Sequence<beans::PropertyVal
             aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= 
OUString(WRITER_TEXT_FILTER);
         else if (aExt == "csv" || aExt == "tsv" || aExt == "tab" || aExt == 
"xls" || aName.endsWith(".csv.gz"))
             aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= 
OUString(CALC_TEXT_FILTER);
-        else if (bEmpty)
-            aType = aEmptyType; // aMediaDesc is already updated in 
HandleEmptyFileUrlByExtension
         else
             aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= 
OUString(WRITER_TEXT_FILTER);
     }
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 0000a9b4f6df..0dc8cb2d1d5b 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -429,7 +429,7 @@ bool SfxObjectShell::InitNew( const uno::Reference< 
embed::XStorage >& xStorage
 
 bool SfxObjectShell::Load( SfxMedium& rMedium )
 {
-    return GeneralInit_Impl(rMedium.GetStorage(), 
!tools::isEmptyFileUrl(rMedium.GetName()));
+    return GeneralInit_Impl(rMedium.GetStorage(), true);
 }
 
 void SfxObjectShell::DoInitUnitTest()
@@ -662,9 +662,7 @@ bool SfxObjectShell::DoLoad( SfxMedium *pMed )
                     bWarnMediaTypeFallback = false;
                 }
 
-                if (bWarnMediaTypeFallback
-                    || (!tools::isEmptyFileUrl(pMedium->GetName())
-                        && !xStorage->getElementNames().hasElements()))
+                if (bWarnMediaTypeFallback || 
!xStorage->getElementNames().hasElements())
                     SetError(ERRCODE_IO_BROKENPACKAGE);
             }
             catch( uno::Exception& )
@@ -2260,11 +2258,7 @@ bool SfxObjectShell::ImportFrom(SfxMedium& rMedium,
 
             // #i119492# During loading, some OLE objects like chart will be 
set
             // modified flag, so needs to reset the flag to false after loading
-            bool bRtn = true;
-            if (!tools::isEmptyFileUrl(rMedium.GetName()))
-            {
-                bRtn = xLoader->filter(aArgs);
-            }
+            bool bRtn = xLoader->filter(aArgs);
             const uno::Sequence < OUString > aNames = 
GetEmbeddedObjectContainer().GetObjectNames();
             for ( const auto& rName : aNames )
             {
diff --git a/sfx2/source/view/frmload.cxx b/sfx2/source/view/frmload.cxx
index 91b045b2f1a3..bd0329fb2ac3 100644
--- a/sfx2/source/view/frmload.cxx
+++ b/sfx2/source/view/frmload.cxx
@@ -21,6 +21,7 @@
 #include <sfx2/app.hxx>
 #include <sfx2/bindings.hxx>
 #include <sfx2/docfac.hxx>
+#include <sfx2/docfile.hxx>
 #include <sfx2/docfilt.hxx>
 #include <sfx2/doctempl.hxx>
 #include <sfx2/fcontnr.hxx>
@@ -55,8 +56,11 @@
 #include <rtl/ref.hxx>
 #include <sal/log.hxx>
 #include <svl/eitem.hxx>
+#include <svl/stritem.hxx>
 #include <unotools/moduleoptions.hxx>
 #include <tools/diagnose_ex.h>
+#include <tools/stream.hxx>
+#include <tools/urlobj.hxx>
 #include <vcl/svapp.hxx>
 
 using namespace com::sun::star;
@@ -585,6 +589,25 @@ Reference< XController2 > 
SfxFrameLoader_Impl::impl_createDocumentView( const Re
     return xController;
 }
 
+std::shared_ptr<const SfxFilter> getEmptyURLFilter(const OUString& sURL)
+{
+    INetURLObject aParser(sURL);
+    const OUString aExt = aParser.getExtension(INetURLObject::LAST_SEGMENT, 
true,
+                                               
INetURLObject::DecodeMechanism::WithCharset);
+    const SfxFilterMatcher& rMatcher = SfxGetpApp()->GetFilterMatcher();
+
+    // Requiring the export+preferred flags helps to find the relevant filter, 
e.g. .doc -> WW8 (and
+    // not WW6 or Mac_Word).
+    std::shared_ptr<const SfxFilter> pFilter = rMatcher.GetFilter4Extension(
+        aExt, SfxFilterFlags::IMPORT | SfxFilterFlags::EXPORT | 
SfxFilterFlags::PREFERED);
+    if (!pFilter)
+    {
+        // retry without PREFERED so we can find at least something for 0-byte 
*.ods
+        pFilter
+            = rMatcher.GetFilter4Extension(aExt, SfxFilterFlags::IMPORT | 
SfxFilterFlags::EXPORT);
+    }
+    return pFilter;
+}
 
 sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const Sequence< PropertyValue >& 
rArgs,
                                              const Reference< XFrame >& 
_rTargetFrame )
@@ -608,6 +631,7 @@ sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const 
Sequence< PropertyValue >& rA
     // check for factory URLs to create a new doc, instead of loading one
     const OUString sURL = aDescriptor.getOrDefault( "URL", OUString() );
     const bool bIsFactoryURL = sURL.startsWith( "private:factory/" );
+    std::shared_ptr<const SfxFilter> pEmptyURLFilter;
     bool bInitNewModel = bIsFactoryURL;
     const bool bIsDefault = bIsFactoryURL && !bExternalModel;
     if (!aDescriptor.has("Replaceable"))
@@ -640,6 +664,28 @@ sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const 
Sequence< PropertyValue >& rA
     {
         // compatibility
         aDescriptor.put( "FileName", aDescriptor.get( "URL" ) );
+
+        if (!bIsFactoryURL && !bExternalModel && tools::isEmptyFileUrl(sURL))
+        {
+            pEmptyURLFilter = getEmptyURLFilter(sURL);
+            if (pEmptyURLFilter)
+            {
+                aDescriptor.put("DocumentService", 
pEmptyURLFilter->GetServiceName());
+                if (impl_determineTemplateDocument(aDescriptor))
+                {
+                    // if the media descriptor allowed us to determine a 
template document
+                    // to create the new document from, then do not init a new 
document model
+                    // from scratch (below), but instead load the template 
document
+                    bInitNewModel = false;
+                    // Do not try to load from empty UCB content
+                    aDescriptor.remove("UCBContent");
+                }
+                else
+                {
+                    bInitNewModel = true;
+                }
+            }
+        }
     }
 
     bool bLoadSuccess = false;
@@ -692,6 +738,20 @@ sal_Bool SAL_CALL SfxFrameLoader_Impl::load( const 
Sequence< PropertyValue >& rA
         const SfxObjectShellRef xDoc = impl_findObjectShell( xModel );
         ENSURE_OR_THROW( xDoc.is(), "no SfxObjectShell for the given model" );
 
+        if (pEmptyURLFilter)
+        {
+            // Detach the medium from the template, and set proper document 
name and filter
+            auto pMedium = xDoc->GetMedium();
+            auto pItemSet = pMedium->GetItemSet();
+            pItemSet->ClearItem(SID_TEMPLATE);
+            pItemSet->Put(SfxStringItem(SID_FILTER_NAME, 
pEmptyURLFilter->GetFilterName()));
+            pMedium->SetName(sURL, true);
+            pMedium->SetFilter(pEmptyURLFilter);
+            pMedium->GetInitFileDate(true);
+            xDoc->SetLoading(SfxLoadedFlags::NONE);
+            xDoc->FinishedLoading();
+        }
+
         // ensure the ID of the to-be-created view is in the descriptor, if 
possible
         const SfxInterfaceId nViewId = impl_determineEffectiveViewId_nothrow( 
*xDoc, aDescriptor );
         const sal_Int16 nViewNo = xDoc->GetFactory().GetViewNo_Impl( nViewId, 
0 );

Reply via email to