/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; namespace { class GalApp : public Application { bool mbInBuildTree; bool mbRelativeURLs; public: GalApp() : mbInBuildTree( false ), mbRelativeURLs( false ) { } virtual int Main() override; protected: uno::Reference xMSF; void Init() override; void DeInit() override; }; } static void createTheme( const OUString& aThemeName, const OUString& aGalleryURL, const OUString& aDestDir, std::vector &rFiles, bool bRelativeURLs ) { std::unique_ptr pGallery(new Gallery( aGalleryURL )); fprintf( stderr, "Work on gallery '%s'\n", OUStringToOString( aGalleryURL, RTL_TEXTENCODING_UTF8 ).getStr() ); fprintf( stderr, "Existing themes: %" SAL_PRI_SIZET "u\n", pGallery->GetThemeCount() ); GalleryTheme *pGalTheme; if( !pGallery->HasTheme( aThemeName) ) { if( !pGallery->CreateTheme( aThemeName ) ) { fprintf( stderr, "Failed to create theme\n" ); exit( 1 ); } } fprintf( stderr, "Existing themes: %" SAL_PRI_SIZET "u\n", pGallery->GetThemeCount() ); SfxListener aListener; pGalTheme = pGallery->AcquireTheme( aThemeName, aListener ); if ( !pGalTheme ) { fprintf( stderr, "Failed to acquire theme\n" ); exit( 1 ); } fprintf( stderr, "Using DestDir: %s\n", OUStringToOString( aDestDir, RTL_TEXTENCODING_UTF8 ).getStr() ); pGalTheme->SetDestDir( aDestDir, bRelativeURLs ); for( const auto& rFile : rFiles ) { // Should/could use: // if ( ! pGalTheme->InsertFileOrDirURL( aURL ) ) { // Requires a load more components ... if ( ! pGalTheme->InsertURL( rFile ) ) fprintf( stderr, "Failed to import '%s'\n", OUStringToOString( rFile.GetMainURL(INetURLObject::DecodeMechanism::NONE), RTL_TEXTENCODING_UTF8 ).getStr() ); else fprintf( stderr, "Imported file '%s' (%" SAL_PRIuUINT32 ")\n", OUStringToOString( rFile.GetMainURL(INetURLObject::DecodeMechanism::NONE), RTL_TEXTENCODING_UTF8 ).getStr(), pGalTheme->GetObjectCount() ); } pGallery->ReleaseTheme( pGalTheme, aListener ); } static int PrintHelp() { fprintf( stdout, "Utility to generate LibreOffice gallery files\n\n" ); fprintf( stdout, "using: gengal --name --path [ --destdir ]\n"); fprintf( stdout, " [ files ... ]\n\n" ); fprintf( stdout, "options:\n"); fprintf( stdout, " --name \t\tdefines the user visible name of the created or updated theme.\n"); fprintf( stdout, " --path \t\tdefines directory where the gallery files are created\n"); fprintf( stdout, "\t\t\tor updated.\n"); fprintf( stdout, " --destdir \tdefines a path prefix to be removed from the paths\n"); fprintf( stdout, "\t\t\tstored in the gallery files. It is useful to create\n"); fprintf( stdout, "\t\t\tRPM packages using the BuildRoot feature.\n"); fprintf( stdout, " --relative-urls\t\tflags that after removing the destdir, the URL should be a path relative to the gallery folder in the install\n"); fprintf( stdout, "\t\t\tprimarily used for internal gallery generation at compile time.\n"); fprintf( stdout, "\t\t\ttheme files.\n"); fprintf( stdout, " files\t\t\tlists files to be added to the gallery. Absolute paths\n"); fprintf( stdout, "\t\t\tare required.\n"); // --build-tree not documented - only useful during the build ... return EXIT_SUCCESS; } static INetURLObject Smartify( const OUString &rPath ) { INetURLObject aURL; aURL.SetSmartURL( rPath ); return aURL; } void GalApp::Init() { try { if( !mbInBuildTree && getenv( "OOO_INSTALL_PREFIX" ) == nullptr ) { OUString fileName = GetAppFileName(); int lastSlash = fileName.lastIndexOf( '/' ); #ifdef _WIN32 // Don't know which directory separators GetAppFileName() returns on Windows. // Be safe and take into consideration they might be backslashes. if( fileName.lastIndexOf( '\\' ) > lastSlash ) lastSlash = fileName.lastIndexOf( '\\' ); #endif OUString baseBinDir = fileName.copy( 0, lastSlash ); OUString installPrefix = baseBinDir + "/../.."; OUString envVar( "OOO_INSTALL_PREFIX"); osl_setEnvironment(envVar.pData, installPrefix.pData); } SAL_INFO("svx", "OOO_INSTALL_PREFIX=" << getenv( "OOO_INSTALL_PREFIX" ) ); uno::Reference xComponentContext = ::cppu::defaultBootstrap_InitialComponentContext(); xMSF.set( xComponentContext->getServiceManager(), uno::UNO_QUERY ); if( !xMSF.is() ) { fprintf( stderr, "Failed to bootstrap\n" ); exit( 1 ); } ::comphelper::setProcessServiceFactory( xMSF ); // For backwards compatibility, in case some code still uses plain // createInstance w/o args directly to obtain an instance: css::ucb::UniversalContentBroker::create(xComponentContext); } catch (const uno::Exception &e) { fprintf( stderr, "Bootstrap exception '%s'\n", OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() ); exit( 1 ); } } static std::vector ReadResponseFile_Impl(OUString const& rInput) { osl::File file(rInput); osl::FileBase::RC rc = file.open(osl_File_OpenFlag_Read); OString const uInput(OUStringToOString(rInput, RTL_TEXTENCODING_UTF8)); if (osl::FileBase::E_None != rc) { fprintf(stderr, "error while opening response file: %s (%d)\n", uInput.getStr(), rc); exit(1); } std::vector ret; OUStringBuffer b(256); char buf[1<<16]; while (true) { sal_uInt64 size(0); rc = file.read(buf, sizeof(buf), size); if (osl::FileBase::E_None != rc) { fprintf(stderr, "error while reading response file: %s (%d)\n", uInput.getStr(), rc); exit(1); } if (!size) break; for (sal_uInt64 i = 0; i < size; ++i) { if (static_cast(buf[i]) >= 128) { fprintf(stderr, "non-ASCII character in response file: %s\n", uInput.getStr()); exit(1); } switch (buf[i]) { case ' ' : case '\t': case '\r': case '\n': if (!b.isEmpty()) ret.push_back(b.makeStringAndClear()); break; default: b.append(buf[i]); break; } } } if (!b.isEmpty()) ret.push_back(b.makeStringAndClear()); return ret; } static void ReadResponseFile(std::vector & rFiles, OUString const& rInput) { std::vector files(ReadResponseFile_Impl(rInput)); for (size_t i = 0; i < files.size(); ++i) { rFiles.push_back(Smartify(files[i])); } } int GalApp::Main() { try { SfxApplication::GetOrCreate(); OUString aPath, aDestDir; OUString aName( "Default name" ); std::vector aFiles; for( sal_uInt16 i = 0; i < GetCommandLineParamCount(); ++i ) { OUString aParam = GetCommandLineParam( i ); if ( aParam.startsWith( "-env:" ) ) continue; else if ( aParam == "--help" || aParam == "-h" ) return PrintHelp(); else if ( aParam == "--build-tree" ) { mbRelativeURLs = true; mbInBuildTree = true; } else if ( aParam == "--name" ) aName = GetCommandLineParam( ++i ); else if ( aParam == "--path" ) aPath = Smartify( GetCommandLineParam( ++i ) ). GetMainURL(INetURLObject::DecodeMechanism::NONE); else if ( aParam == "--destdir" ) aDestDir = GetCommandLineParam( ++i ); else if ( aParam == "--relative-urls" ) mbRelativeURLs = true; else if ( aParam == "--number-from" ) fprintf ( stderr, "--number-from is deprecated, themes now " "have filenames based on their names\n" ); else if ( aParam == "--filenames" ) ReadResponseFile(aFiles, GetCommandLineParam(++i)); else aFiles.push_back( Smartify( aParam ) ); } if( aFiles.empty() ) return PrintHelp(); createTheme( aName, aPath, aDestDir, aFiles, mbRelativeURLs ); } catch (const uno::Exception&) { TOOLS_WARN_EXCEPTION("svx", "Fatal"); return EXIT_FAILURE; } catch (const std::exception &e) { SAL_WARN("svx", "Fatal: " << e.what()); return 1; } return EXIT_SUCCESS; } void GalApp::DeInit() { uno::Reference< lang::XComponent >( comphelper::getProcessComponentContext(), uno::UNO_QUERY_THROW )-> dispose(); ::comphelper::setProcessServiceFactory( nullptr ); } void vclmain::createApplication() { Application::EnableConsoleOnly(); static GalApp aGalApp; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */