Files
libreoffice/xmlhelp/source/treeview/tvread.cxx

1238 lines
37 KiB
C++
Raw Normal View History

/* -*- 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/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
2001-07-11 14:35:25 +00:00
#include <string.h>
#include <rtl/ustrbuf.hxx>
2010-10-10 19:46:48 -05:00
#include <osl/diagnose.h>
#include "tvread.hxx"
#include <expat.h>
2001-07-11 14:35:25 +00:00
#include <osl/file.hxx>
#include <unotools/configmgr.hxx>
#include <com/sun/star/configuration/theDefaultProvider.hpp>
#include <com/sun/star/ucb/SimpleFileAccess.hpp>
2001-07-12 12:32:24 +00:00
#include <com/sun/star/frame/XConfigManager.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <comphelper/processfactory.hxx>
#include "com/sun/star/deployment/thePackageManagerFactory.hpp"
#include <com/sun/star/util/theMacroExpander.hpp>
#include <com/sun/star/uri/UriReferenceFactory.hpp>
#include <com/sun/star/uri/XVndSunStarExpandUrl.hpp>
#include <i18nlangtag/languagetag.hxx>
2011-08-29 00:59:53 +01:00
#include <comphelper/string.hxx>
#include <unotools/pathoptions.hxx>
2001-07-12 12:32:24 +00:00
namespace treeview {
class TVDom
{
friend class TVChildTarget;
friend class TVRead;
public:
TVDom( TVDom* arent = 0 )
: kind( other ),
parent( arent ),
2011-12-07 02:33:51 -08:00
children( 0 )
2001-07-12 12:32:24 +00:00
{
}
~TVDom()
{
2011-12-07 02:33:51 -08:00
for( unsigned i = 0; i < children.size(); ++i )
delete children[i];
2001-07-12 12:32:24 +00:00
}
TVDom* newChild()
{
2011-12-07 02:33:51 -08:00
children.push_back( new TVDom( this ) );
return children.back();
2001-07-12 12:32:24 +00:00
}
TVDom* newChild(TVDom* p)
{
children.push_back( p );
p->parent = this;
return children.back();
}
2001-07-12 12:32:24 +00:00
TVDom* getParent() const
{
if( parent )
return parent;
else
return const_cast<TVDom*>(this); // I am my own parent, if I am the root
2001-07-12 12:32:24 +00:00
}
enum Kind {
tree_view,
tree_node,
tree_leaf,
other
};
bool isLeaf() const { return kind == TVDom::tree_leaf; }
void setKind( Kind ind ) { kind = ind; }
Kind getKind( ) const { return kind; }
void setApplication( const char* appl )
{
application = OUString( (sal_Char*)(appl),
2001-07-12 12:32:24 +00:00
strlen( appl ),
RTL_TEXTENCODING_UTF8 );
}
void setTitle( const char* itle )
{
title += OUString( (sal_Char*)(itle),
strlen( itle ),
RTL_TEXTENCODING_UTF8 );
2001-07-12 12:32:24 +00:00
}
void setTitle( const XML_Char* itle,int len )
{
title += OUString( (sal_Char*)(itle),
len,
RTL_TEXTENCODING_UTF8 );
2001-07-12 12:32:24 +00:00
}
void setId( const char* d )
{
id = OUString( (sal_Char*)(d),
2001-07-12 12:32:24 +00:00
strlen( d ),
RTL_TEXTENCODING_UTF8 );
}
void setAnchor( const char* nchor )
{
anchor = OUString( (sal_Char*)(nchor),
2001-07-12 12:32:24 +00:00
strlen( nchor ),
RTL_TEXTENCODING_UTF8 );
}
OUString getTargetURL()
2001-07-12 12:32:24 +00:00
{
if( targetURL.isEmpty() )
2001-07-12 12:32:24 +00:00
{
sal_Int32 len;
for ( const TVDom* p = this;; p = p->parent )
{
len = p->application.getLength();
if ( len != 0 )
break;
}
2001-07-12 12:32:24 +00:00
OUStringBuffer strBuff( 22 + len + id.getLength() );
strBuff.appendAscii(
"vnd.sun.star.help://"
).append(id);
targetURL = strBuff.makeStringAndClear();
2001-07-12 12:32:24 +00:00
}
return targetURL;
}
private:
Kind kind;
OUString application;
OUString title;
OUString id;
OUString anchor;
OUString targetURL;
2001-07-12 12:32:24 +00:00
TVDom *parent;
2011-12-07 02:33:51 -08:00
std::vector< TVDom* > children;
2001-07-12 12:32:24 +00:00
};
}
using namespace treeview;
using namespace com::sun::star;
using namespace com::sun::star::uno;
2001-07-12 12:32:24 +00:00
using namespace com::sun::star::beans;
using namespace com::sun::star::configuration;
using namespace com::sun::star::lang;
using namespace com::sun::star::util;
2001-07-12 12:32:24 +00:00
using namespace com::sun::star::frame;
using namespace com::sun::star::container;
using namespace com::sun::star::deployment;
2001-10-31 12:53:36 +00:00
ConfigData::ConfigData()
: prodName("%PRODUCTNAME"),
prodVersion("%PRODUCTVERSION"),
vendName("%VENDORNAME"),
vendVersion("%VENDORVERSION"),
vendShort("%VENDORSHORT")
2001-10-31 12:53:36 +00:00
{
memset(m_vAdd, 0, sizeof(m_vAdd));
2001-10-31 12:53:36 +00:00
}
void SAL_CALL ConfigData::replaceName( OUString& oustring ) const
{
2001-10-31 12:53:36 +00:00
sal_Int32 idx = -1,k = 0,off;
bool cap = false;
OUStringBuffer aStrBuf( 0 );
while( ( idx = oustring.indexOf( sal_Unicode('%'),++idx ) ) != -1 )
{
2001-10-31 12:53:36 +00:00
if( oustring.indexOf( prodName,idx ) == idx )
off = PRODUCTNAME;
2001-10-31 12:53:36 +00:00
else if( oustring.indexOf( prodVersion,idx ) == idx )
off = PRODUCTVERSION;
2001-10-31 12:53:36 +00:00
else if( oustring.indexOf( vendName,idx ) == idx )
off = VENDORNAME;
2001-10-31 12:53:36 +00:00
else if( oustring.indexOf( vendVersion,idx ) == idx )
off = VENDORVERSION;
2001-10-31 12:53:36 +00:00
else if( oustring.indexOf( vendShort,idx ) == idx )
off = VENDORSHORT;
else
2001-10-31 12:53:36 +00:00
off = -1;
2001-10-31 12:53:36 +00:00
if( off != -1 )
{
if( ! cap )
{
cap = true;
aStrBuf.ensureCapacity( 256 );
}
aStrBuf.append( &oustring.getStr()[k],idx - k );
aStrBuf.append( m_vReplacement[off] );
2001-10-31 12:53:36 +00:00
k = idx + m_vAdd[off];
}
}
if( cap )
{
if( k < oustring.getLength() )
aStrBuf.append( &oustring.getStr()[k],oustring.getLength()-k );
oustring = aStrBuf.makeStringAndClear();
}
}
// XInterface
void SAL_CALL
2001-07-12 14:48:32 +00:00
TVBase::acquire(
void )
2001-10-26 10:42:02 +00:00
throw()
{
OWeakObject::acquire();
}
void SAL_CALL
2001-07-12 14:48:32 +00:00
TVBase::release(
void )
2001-10-26 10:42:02 +00:00
throw()
{
OWeakObject::release();
}
Any SAL_CALL
2001-07-12 14:48:32 +00:00
TVBase::queryInterface(
const Type& rType )
throw( RuntimeException )
{
Any aRet = cppu::queryInterface( rType,
(static_cast< XTypeProvider* >(this)),
(static_cast< XNameAccess* >(this)),
(static_cast< XHierarchicalNameAccess* >(this)),
(static_cast< XChangesNotifier* >(this)),
(static_cast< XComponent* >(this)) );
return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
}
// XTypeProvider methods.
2001-07-12 14:48:32 +00:00
XTYPEPROVIDER_IMPL_5( TVBase,
XTypeProvider,
XNameAccess,
XHierarchicalNameAccess,
XChangesNotifier,
XComponent );
2001-07-12 14:48:32 +00:00
// TVRead
TVRead::TVRead( const ConfigData& configData,TVDom* tvDom )
{
if( ! tvDom )
return;
Title = tvDom->title;
configData.replaceName( Title );
2001-07-12 14:48:32 +00:00
if( tvDom->isLeaf() )
{
TargetURL = ( tvDom->getTargetURL() + configData.appendix );
if( !tvDom->anchor.isEmpty() )
TargetURL += ( OUString( "#" ) +
2001-07-12 14:48:32 +00:00
tvDom->anchor );
}
else
Children = new TVChildTarget( configData,tvDom );
}
TVRead::~TVRead()
{
}
// XNameAccess
Any SAL_CALL
TVRead::getByName( const OUString& aName )
throw( NoSuchElementException,
WrappedTargetException,
2001-07-11 14:35:25 +00:00
RuntimeException )
{
2001-07-11 14:35:25 +00:00
bool found( true );
Any aAny;
if( aName.compareToAscii( "Title" ) == 0 )
aAny <<= Title;
else if( aName.compareToAscii( "TargetURL" ) == 0 )
aAny <<= TargetURL;
2001-07-11 14:35:25 +00:00
else if( aName.compareToAscii( "Children" ) == 0 )
{
2001-07-11 14:35:25 +00:00
cppu::OWeakObject* p = Children.get();
aAny <<= Reference< XInterface >( p );
}
2001-07-11 14:35:25 +00:00
else
found = false;
2001-07-11 14:35:25 +00:00
if( found )
return aAny;
throw NoSuchElementException();
}
Sequence< OUString > SAL_CALL
TVRead::getElementNames( )
throw( RuntimeException )
{
Sequence< OUString > seq( 3 );
2001-07-11 14:35:25 +00:00
seq[0] = "Title";
seq[1] = "TargetURL";
seq[2] = "Children";
return seq;
}
sal_Bool SAL_CALL
TVRead::hasByName( const OUString& aName )
throw( RuntimeException )
{
if( aName.compareToAscii( "Title" ) == 0 ||
2001-07-11 14:35:25 +00:00
aName.compareToAscii( "TargetURL" ) == 0 ||
aName.compareToAscii( "Children" ) == 0 )
return true;
return false;
}
// XHierarchicalNameAccess
Any SAL_CALL
TVRead::getByHierarchicalName( const OUString& aName )
throw( NoSuchElementException,
RuntimeException )
{
sal_Int32 idx;
OUString name( aName );
2001-07-11 14:35:25 +00:00
if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 &&
name.copy( 0,idx ).compareToAscii( "Children" ) == 0 )
return Children->getByHierarchicalName( name.copy( 1 + idx ) );
return getByName( name );
}
sal_Bool SAL_CALL
TVRead::hasByHierarchicalName( const OUString& aName )
2001-07-11 14:35:25 +00:00
throw( RuntimeException )
{
sal_Int32 idx;
OUString name( aName );
2001-07-11 14:35:25 +00:00
if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 &&
name.copy( 0,idx ).compareToAscii( "Children" ) == 0 )
return Children->hasByHierarchicalName( name.copy( 1 + idx ) );
return hasByName( name );
}
/**************************************************************************/
/* */
/* TVChildTarget */
/* */
/**************************************************************************/
extern "C" void start_handler(void *userData,
2001-07-11 14:35:25 +00:00
const XML_Char *name,
const XML_Char **atts)
{
2001-07-12 12:32:24 +00:00
TVDom::Kind kind;
2001-07-11 14:35:25 +00:00
2001-07-12 12:32:24 +00:00
if( strcmp( name,"help_section" ) == 0 ||
strcmp( name,"node" ) == 0 )
kind = TVDom::tree_node;
else if( strcmp( name,"topic" ) == 0 )
kind = TVDom::tree_leaf;
else
return;
2001-07-11 14:35:25 +00:00
2001-07-12 12:32:24 +00:00
TVDom **tvDom = static_cast< TVDom** >( userData );
TVDom *p;
p = *tvDom;
2001-07-11 14:35:25 +00:00
2001-07-12 13:35:29 +00:00
*tvDom = p->newChild();
p = *tvDom;
2001-07-11 14:35:25 +00:00
2001-07-12 12:32:24 +00:00
p->setKind( kind );
while( *atts )
{
if( strcmp( *atts,"application" ) == 0 )
p->setApplication( *(atts+1) );
else if( strcmp( *atts,"title" ) == 0 )
p->setTitle( *(atts+1) );
else if( strcmp( *atts,"id" ) == 0 )
p->setId( *(atts+1) );
else if( strcmp( *atts,"anchor" ) == 0 )
p->setAnchor( *(atts+1) );
atts+=2;
2001-07-11 14:35:25 +00:00
}
}
extern "C" void end_handler(void *userData,
2001-07-11 14:35:25 +00:00
const XML_Char *name )
{
(void)name;
2001-07-12 12:32:24 +00:00
TVDom **tvDom = static_cast< TVDom** >( userData );
2001-07-12 13:35:29 +00:00
*tvDom = (*tvDom)->getParent();
2001-07-11 14:35:25 +00:00
}
extern "C" void data_handler( void *userData,
2001-07-11 14:35:25 +00:00
const XML_Char *s,
int len)
{
2001-07-12 12:32:24 +00:00
TVDom **tvDom = static_cast< TVDom** >( userData );
if( (*tvDom)->isLeaf() )
(*tvDom)->setTitle( s,len );
2001-07-11 14:35:25 +00:00
}
2001-07-12 12:32:24 +00:00
TVChildTarget::TVChildTarget( const ConfigData& configData,TVDom* tvDom )
2001-07-11 14:35:25 +00:00
{
2011-12-07 02:33:51 -08:00
Elements.resize( tvDom->children.size() );
2001-07-12 12:32:24 +00:00
for( unsigned i = 0; i < Elements.size(); ++i )
2011-12-07 02:33:51 -08:00
Elements[i] = new TVRead( configData,tvDom->children[i] );
2001-07-11 14:35:25 +00:00
}
TVChildTarget::TVChildTarget( const Reference< XComponentContext >& xContext )
2001-07-11 14:35:25 +00:00
{
ConfigData configData = init( xContext );
2001-07-11 14:35:25 +00:00
if( configData.locale.isEmpty() || configData.system.isEmpty() )
2001-07-12 12:32:24 +00:00
return;
2001-07-11 14:35:25 +00:00
sal_uInt64 ret,len = 0;
int j = configData.vFileURL.size();
2001-07-11 14:35:25 +00:00
2001-07-12 12:32:24 +00:00
TVDom tvDom;
TVDom* pTVDom = &tvDom;
2001-07-11 14:35:25 +00:00
while( j )
{
len = configData.vFileLen[--j];
char* s = new char[ int(len) ]; // the buffer to hold the installed files
osl::File aFile( configData.vFileURL[j] );
2010-12-11 18:02:43 +00:00
aFile.open( osl_File_OpenFlag_Read );
aFile.read( s,len,ret );
aFile.close();
XML_Parser parser = XML_ParserCreate( 0 );
XML_SetElementHandler( parser,
start_handler,
end_handler );
XML_SetCharacterDataHandler( parser,
data_handler);
XML_SetUserData( parser,&pTVDom ); // does not return this
XML_Status const parsed = XML_Parse(parser, s, int(len), j==0);
SAL_WARN_IF(XML_STATUS_ERROR == parsed, "xmlhelp",
"TVChildTarget::TVChildTarget(): Tree file parsing failed");
XML_ParserFree( parser );
delete[] s;
2001-07-12 12:32:24 +00:00
Check(pTVDom);
}
2001-07-12 12:32:24 +00:00
// now TVDom holds the relevant information
2011-12-07 02:33:51 -08:00
Elements.resize( tvDom.children.size() );
2001-07-12 12:32:24 +00:00
for( unsigned i = 0; i < Elements.size(); ++i )
2011-12-07 02:33:51 -08:00
Elements[i] = new TVRead( configData,tvDom.children[i] );
2001-07-11 14:35:25 +00:00
}
TVChildTarget::~TVChildTarget()
{
}
void TVChildTarget::Check(TVDom* tvDom)
{
if (tvDom->children.empty())
{
return;
}
unsigned i = 0;
bool h = false;
while((i<tvDom->children.size()-1) && (!h))
{
if (((tvDom->children[i])->application == (tvDom->children[tvDom->children.size()-1])->application) &&
((tvDom->children[i])->id == (tvDom->children[tvDom->children.size()-1])->id))
{
TVDom* p = tvDom->children[tvDom->children.size()-1];
for(unsigned k=0; k<p->children.size(); ++k)
if (!SearchAndInsert(p->children[k], tvDom->children[i])) tvDom->children[i]->newChild(p->children[k]);
2001-07-11 14:35:25 +00:00
tvDom->children.pop_back();
h = true;
}
++i;
}
}
bool TVChildTarget::SearchAndInsert(TVDom* p, TVDom* tvDom)
{
if (p->isLeaf()) return false;
bool h = false;
sal_Int32 max = 0;
std::vector< TVDom* >::iterator max_It, i;
max_It = tvDom->children.begin();
sal_Int32 c_int;
sal_Int32 p_int = p->id.toInt32();
for(i = tvDom->children.begin(); i!=tvDom->children.end(); ++i)
if (!((*i)->isLeaf()) &&
((*i)->id.getLength() == p->id.getLength()) &&
(p->id.replaceAt((*i)->parent->id.getLength(), p->id.getLength()-(*i)->parent->id.getLength(), OUString("")) == (*i)->parent->id)) //prefix check
{
h = true;
c_int = (*i)->id.toInt32();
if (p_int==c_int)
{
(*(tvDom->children.insert(i+1, p)))->parent = tvDom;
return true;
}
else if(c_int>max && c_int < p_int)
{
max = c_int;
max_It = i+1;
}
}
if (h) (*(tvDom->children.insert(max_It, p)))->parent = tvDom;
else
{
i = tvDom->children.begin();
while ((i!=tvDom->children.end()) && (!h))
{
h = SearchAndInsert(p, *i);
++i;
}
}
return h;
}
2001-07-11 14:35:25 +00:00
Any SAL_CALL
TVChildTarget::getByName( const OUString& aName )
2001-07-11 14:35:25 +00:00
throw( NoSuchElementException,
WrappedTargetException,
RuntimeException )
{
OUString num( aName.getStr()+2,aName.getLength()-4 );
2001-07-12 14:33:36 +00:00
sal_Int32 idx = num.toInt32() - 1;
2001-07-11 14:35:25 +00:00
if( idx < 0 || Elements.size() <= sal_uInt32( idx ) )
throw NoSuchElementException();
Any aAny;
cppu::OWeakObject* p = Elements[idx].get();
aAny <<= Reference< XInterface >( p );
return aAny;
}
Sequence< OUString > SAL_CALL
2001-07-11 14:35:25 +00:00
TVChildTarget::getElementNames( )
throw( RuntimeException )
{
Sequence< OUString > seq( Elements.size() );
2001-07-11 14:35:25 +00:00
for( unsigned i = 0; i < Elements.size(); ++i )
seq[i] = OUString::number( 1+i );
2001-07-11 14:35:25 +00:00
return seq;
}
sal_Bool SAL_CALL
TVChildTarget::hasByName( const OUString& aName )
2001-07-11 14:35:25 +00:00
throw( RuntimeException )
{
OUString num( aName.getStr()+2,aName.getLength()-4 );
2001-07-12 14:33:36 +00:00
sal_Int32 idx = num.toInt32() - 1;
2001-07-11 14:35:25 +00:00
if( idx < 0 || Elements.size() <= sal_uInt32( idx ) )
return false;
return true;
}
// XHierarchicalNameAccess
Any SAL_CALL
TVChildTarget::getByHierarchicalName( const OUString& aName )
2001-07-11 14:35:25 +00:00
throw( NoSuchElementException,
RuntimeException )
{
sal_Int32 idx;
OUString name( aName );
2001-07-11 14:35:25 +00:00
if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 )
{
OUString num( name.getStr()+2,idx-4 );
2001-07-12 14:33:36 +00:00
sal_Int32 pref = num.toInt32() - 1;
2001-07-11 14:35:25 +00:00
if( pref < 0 || Elements.size() <= sal_uInt32( pref ) )
throw NoSuchElementException();
2001-07-11 14:35:25 +00:00
return Elements[pref]->getByHierarchicalName( name.copy( 1 + idx ) );
}
else
return getByName( name );
}
sal_Bool SAL_CALL
TVChildTarget::hasByHierarchicalName( const OUString& aName )
throw( RuntimeException )
{
sal_Int32 idx;
OUString name( aName );
2001-07-11 14:35:25 +00:00
if( ( idx = name.indexOf( sal_Unicode( '/' ) ) ) != -1 )
{
OUString num( name.getStr()+2,idx-4 );
2001-07-12 14:33:36 +00:00
sal_Int32 pref = num.toInt32() - 1;
2001-07-11 14:35:25 +00:00
if( pref < 0 || Elements.size() <= sal_uInt32( pref ) )
return false;
2001-07-11 14:35:25 +00:00
return Elements[pref]->hasByHierarchicalName( name.copy( 1 + idx ) );
}
else
return hasByName( name );
}
2001-07-12 12:32:24 +00:00
ConfigData TVChildTarget::init( const Reference< XComponentContext >& xContext )
2001-07-12 12:32:24 +00:00
{
ConfigData configData;
Reference< XMultiServiceFactory > sProvider( getConfiguration(xContext) );
/**********************************************************************/
/* reading Office.Common */
/**********************************************************************/
Reference< XHierarchicalNameAccess > xHierAccess( getHierAccess( sProvider,
"org.openoffice.Office.Common" ) );
OUString system( getKey( xHierAccess,"Help/System" ) );
sal_Bool showBasic( getBooleanKey(xHierAccess,"Help/ShowBasic") );
OUString instPath( getKey( xHierAccess,"Path/Current/Help" ) );
if( instPath.isEmpty() )
// try to determine path from default
instPath = "$(instpath)/help";
// replace anything like $(instpath);
subst( instPath );
/**********************************************************************/
/* reading setup */
/**********************************************************************/
xHierAccess = getHierAccess( sProvider,
"org.openoffice.Setup" );
OUString setupversion( getKey( xHierAccess,"Product/ooSetupVersion" ) );
OUString setupextension;
try
{
Reference< lang::XMultiServiceFactory > xConfigProvider = theDefaultProvider::get( xContext );
uno::Sequence < uno::Any > lParams(1);
beans::PropertyValue aParam ;
aParam.Name = "nodepath";
aParam.Value <<= OUString("/org.openoffice.Setup/Product");
lParams[0] = uno::makeAny(aParam);
// open it
uno::Reference< uno::XInterface > xCFG( xConfigProvider->createInstanceWithArguments(
OUString("com.sun.star.configuration.ConfigurationAccess"),
lParams) );
uno::Reference< container::XNameAccess > xDirectAccess(xCFG, uno::UNO_QUERY);
uno::Any aRet = xDirectAccess->getByName("ooSetupExtension");
aRet >>= setupextension;
}
catch ( uno::Exception& )
{
}
OUString productVersion( setupversion +
OUString( " " ) +
setupextension );
OUString locale( getKey( xHierAccess,"L10N/ooLocale" ) );
2001-07-12 12:32:24 +00:00
// Determine fileurl from url and locale
OUString url;
2001-07-12 12:32:24 +00:00
osl::FileBase::RC errFile = osl::FileBase::getFileURLFromSystemPath( instPath,url );
if( errFile != osl::FileBase::E_None ) return configData;
2001-07-12 12:32:24 +00:00
if( url.lastIndexOf( sal_Unicode( '/' ) ) != url.getLength() - 1 )
url += "/";
OUString ret;
2001-07-12 12:32:24 +00:00
sal_Int32 idx;
osl::DirectoryItem aDirItem;
if( osl::FileBase::E_None == osl::DirectoryItem::get( url + locale,aDirItem ) )
ret = locale;
else if( ( ( idx = locale.indexOf( '-' ) ) != -1 ||
( idx = locale.indexOf( '_' ) ) != -1 ) &&
osl::FileBase::E_None == osl::DirectoryItem::get( url + locale.copy( 0,idx ),
aDirItem ) )
ret = locale.copy( 0,idx );
else
{
locale = "en-US";
ret = "en";
}
url = url + ret;
2001-07-12 12:32:24 +00:00
// first of all, try do determine whether there are any *.tree files present
2001-07-12 12:32:24 +00:00
// Start with extensions to set them at the end of the list
TreeFileIterator aTreeIt( locale );
OUString aTreeFile;
sal_Int32 nFileSize;
while( !(aTreeFile = aTreeIt.nextTreeFile( nFileSize ) ).isEmpty() )
{
configData.vFileLen.push_back( nFileSize );
configData.vFileURL.push_back( aTreeFile );
}
osl::Directory aDirectory( url );
osl::FileStatus aFileStatus(
osl_FileStatus_Mask_FileName | osl_FileStatus_Mask_FileURL );
if( osl::Directory::E_None == aDirectory.open() )
{
int idx_ = 0;
OUString aFileUrl, aFileName;
while( aDirectory.getNextItem( aDirItem ) == osl::FileBase::E_None &&
aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None &&
aFileStatus.isValid( osl_FileStatus_Mask_FileURL ) &&
aFileStatus.isValid( osl_FileStatus_Mask_FileName ) )
{
aFileUrl = aFileStatus.getFileURL();
aFileName = aFileStatus.getFileName();
idx_ = aFileName.lastIndexOf( sal_Unicode( '.' ) );
if( idx_ == -1 )
continue;
const sal_Unicode* str = aFileName.getStr();
if( aFileName.getLength() == idx_ + 5 &&
( str[idx_ + 1] == 't' || str[idx_ + 1] == 'T' ) &&
( str[idx_ + 2] == 'r' || str[idx_ + 2] == 'R' ) &&
( str[idx_ + 3] == 'e' || str[idx_ + 3] == 'E' ) &&
( str[idx_ + 4] == 'e' || str[idx_ + 4] == 'E' ) )
{
OUString baseName = aFileName.copy(0,idx_).toAsciiLowerCase();
if(! showBasic && baseName.compareToAscii("sbasic") == 0 )
continue;
osl::File aFile( aFileUrl );
2010-12-11 18:02:43 +00:00
if( osl::FileBase::E_None == aFile.open( osl_File_OpenFlag_Read ) )
{
// use the file size, not aFileStatus size, in case the
// tree file is a symlink
sal_uInt64 nSize;
aFile.getSize( nSize );
configData.vFileLen.push_back( nSize );
configData.vFileURL.push_back( aFileUrl );
aFile.close();
}
}
}
aDirectory.close();
}
2001-10-31 12:53:36 +00:00
configData.m_vAdd[0] = 12;
configData.m_vAdd[1] = 15;
configData.m_vAdd[2] = 11;
configData.m_vAdd[3] = 14;
configData.m_vAdd[4] = 12;
2011-11-11 22:48:37 +01:00
configData.m_vReplacement[0] = utl::ConfigManager::getProductName();
configData.m_vReplacement[1] = productVersion;
// m_vReplacement[2...4] (vendorName/-Version/-Short) are empty strings
2001-07-12 12:32:24 +00:00
configData.system = system;
2001-07-12 12:32:24 +00:00
configData.locale = locale;
configData.appendix =
OUString( "?Language=" ) +
configData.locale +
OUString( "&System=" ) +
configData.system +
OUString( "&UseDB=no" ) ;
2001-07-12 12:32:24 +00:00
return configData;
}
Reference< XMultiServiceFactory >
TVChildTarget::getConfiguration(const Reference< XComponentContext >& rxContext) const
{
Reference< XMultiServiceFactory > xProvider;
if( rxContext.is() )
{
try
{
xProvider = theDefaultProvider::get( rxContext );
}
catch( const com::sun::star::uno::Exception& )
{
OSL_ENSURE( xProvider.is(),"cant instantiate configuration" );
}
}
return xProvider;
}
Reference< XHierarchicalNameAccess >
TVChildTarget::getHierAccess( const Reference< XMultiServiceFactory >& sProvider,
const char* file ) const
{
Reference< XHierarchicalNameAccess > xHierAccess;
if( sProvider.is() )
{
Sequence< Any > seq(1);
OUString sReaderService =
OUString( "com.sun.star.configuration.ConfigurationAccess" );
seq[0] <<= OUString::createFromAscii( file );
try
{
xHierAccess =
Reference< XHierarchicalNameAccess >
( sProvider->createInstanceWithArguments( sReaderService,seq ),
UNO_QUERY );
}
catch( const com::sun::star::uno::Exception& )
{
}
}
return xHierAccess;
}
OUString
TVChildTarget::getKey( const Reference< XHierarchicalNameAccess >& xHierAccess,
const char* key ) const
{
OUString instPath;
if( xHierAccess.is() )
{
Any aAny;
try
{
aAny =
xHierAccess->getByHierarchicalName( OUString::createFromAscii( key ) );
}
catch( const com::sun::star::container::NoSuchElementException& )
{
}
aAny >>= instPath;
}
return instPath;
}
sal_Bool
TVChildTarget::getBooleanKey(const Reference<
XHierarchicalNameAccess >& xHierAccess,
const char* key) const
{
sal_Bool ret = sal_False;
if( xHierAccess.is() )
{
Any aAny;
try
{
aAny =
xHierAccess->getByHierarchicalName(
OUString::createFromAscii(key));
}
catch( const com::sun::star::container::NoSuchElementException& )
{
}
aAny >>= ret;
}
return ret;
}
void TVChildTarget::subst( OUString& instpath ) const
{
SvtPathOptions aOptions;
instpath = aOptions.SubstituteVariable( instpath );
}
// class ExtensionIteratorBase
static OUString aHelpMediaType("application/vnd.sun.star.help");
ExtensionIteratorBase::ExtensionIteratorBase( const OUString& aLanguage )
: m_eState( USER_EXTENSIONS )
, m_aLanguage( aLanguage )
{
init();
}
void ExtensionIteratorBase::init()
{
m_xContext = ::comphelper::getProcessComponentContext();
if( !m_xContext.is() )
{
throw RuntimeException(
OUString( "ExtensionIteratorBase::init(), no XComponentContext" ),
Reference< XInterface >() );
}
m_xSFA = ucb::SimpleFileAccess::create(m_xContext);
m_bUserPackagesLoaded = false;
m_bSharedPackagesLoaded = false;
m_bBundledPackagesLoaded = false;
m_iUserPackage = 0;
m_iSharedPackage = 0;
m_iBundledPackage = 0;
}
Reference< deployment::XPackage > ExtensionIteratorBase::implGetHelpPackageFromPackage
( Reference< deployment::XPackage > xPackage, Reference< deployment::XPackage >& o_xParentPackageBundle )
{
o_xParentPackageBundle.clear();
Reference< deployment::XPackage > xHelpPackage;
if( !xPackage.is() )
return xHelpPackage;
// Check if parent package is registered
beans::Optional< beans::Ambiguous<sal_Bool> > option( xPackage->isRegistered
( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() ) );
bool bRegistered = false;
if( option.IsPresent )
{
beans::Ambiguous<sal_Bool> const & reg = option.Value;
if( !reg.IsAmbiguous && reg.Value )
bRegistered = true;
}
if( !bRegistered )
return xHelpPackage;
if( xPackage->isBundle() )
{
Sequence< Reference< deployment::XPackage > > aPkgSeq = xPackage->getBundle
( Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>() );
sal_Int32 nPkgCount = aPkgSeq.getLength();
const Reference< deployment::XPackage >* pSeq = aPkgSeq.getConstArray();
for( sal_Int32 iPkg = 0 ; iPkg < nPkgCount ; ++iPkg )
{
const Reference< deployment::XPackage > xSubPkg = pSeq[ iPkg ];
const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xSubPkg->getPackageType();
OUString aMediaType = xPackageTypeInfo->getMediaType();
if( aMediaType.equals( aHelpMediaType ) )
{
xHelpPackage = xSubPkg;
o_xParentPackageBundle = xPackage;
break;
}
}
}
else
{
const Reference< deployment::XPackageTypeInfo > xPackageTypeInfo = xPackage->getPackageType();
OUString aMediaType = xPackageTypeInfo->getMediaType();
if( aMediaType.equals( aHelpMediaType ) )
xHelpPackage = xPackage;
}
return xHelpPackage;
}
Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextUserHelpPackage
( Reference< deployment::XPackage >& o_xParentPackageBundle )
{
Reference< deployment::XPackage > xHelpPackage;
if( !m_bUserPackagesLoaded )
{
Reference< XPackageManager > xUserManager =
thePackageManagerFactory::get( m_xContext )->getPackageManager("user");
m_aUserPackagesSeq = xUserManager->getDeployedPackages
( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
m_bUserPackagesLoaded = true;
}
if( m_iUserPackage == m_aUserPackagesSeq.getLength() )
{
m_eState = SHARED_EXTENSIONS; // Later: SHARED_MODULE
}
else
{
const Reference< deployment::XPackage >* pUserPackages = m_aUserPackagesSeq.getConstArray();
Reference< deployment::XPackage > xPackage = pUserPackages[ m_iUserPackage++ ];
2010-10-10 19:46:48 -05:00
OSL_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextUserHelpPackage(): Invalid package" );
xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
}
return xHelpPackage;
}
Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextSharedHelpPackage
( Reference< deployment::XPackage >& o_xParentPackageBundle )
{
Reference< deployment::XPackage > xHelpPackage;
if( !m_bSharedPackagesLoaded )
{
Reference< XPackageManager > xSharedManager =
thePackageManagerFactory::get( m_xContext )->getPackageManager("shared");
m_aSharedPackagesSeq = xSharedManager->getDeployedPackages
( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
m_bSharedPackagesLoaded = true;
}
if( m_iSharedPackage == m_aSharedPackagesSeq.getLength() )
{
m_eState = BUNDLED_EXTENSIONS;
}
else
{
const Reference< deployment::XPackage >* pSharedPackages = m_aSharedPackagesSeq.getConstArray();
Reference< deployment::XPackage > xPackage = pSharedPackages[ m_iSharedPackage++ ];
2010-10-10 19:46:48 -05:00
OSL_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextSharedHelpPackage(): Invalid package" );
xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
}
return xHelpPackage;
}
Reference< deployment::XPackage > ExtensionIteratorBase::implGetNextBundledHelpPackage
( Reference< deployment::XPackage >& o_xParentPackageBundle )
{
Reference< deployment::XPackage > xHelpPackage;
if( !m_bBundledPackagesLoaded )
{
Reference< XPackageManager > xBundledManager =
thePackageManagerFactory::get( m_xContext )->getPackageManager("bundled");
m_aBundledPackagesSeq = xBundledManager->getDeployedPackages
( Reference< task::XAbortChannel >(), Reference< ucb::XCommandEnvironment >() );
m_bBundledPackagesLoaded = true;
}
if( m_iBundledPackage == m_aBundledPackagesSeq.getLength() )
{
m_eState = END_REACHED;
}
else
{
const Reference< deployment::XPackage >* pBundledPackages = m_aBundledPackagesSeq.getConstArray();
Reference< deployment::XPackage > xPackage = pBundledPackages[ m_iBundledPackage++ ];
2010-10-10 19:46:48 -05:00
OSL_ENSURE( xPackage.is(), "ExtensionIteratorBase::implGetNextBundledHelpPackage(): Invalid package" );
xHelpPackage = implGetHelpPackageFromPackage( xPackage, o_xParentPackageBundle );
}
return xHelpPackage;
}
inline bool isLetter( sal_Unicode c )
{
return comphelper::string::isalphaAscii(c);
}
void ExtensionIteratorBase::implGetLanguageVectorFromPackage( ::std::vector< OUString > &rv,
com::sun::star::uno::Reference< com::sun::star::deployment::XPackage > xPackage )
{
rv.clear();
OUString aExtensionPath = xPackage->getURL();
Sequence< OUString > aEntrySeq = m_xSFA->getFolderContents( aExtensionPath, true );
const OUString* pSeq = aEntrySeq.getConstArray();
sal_Int32 nCount = aEntrySeq.getLength();
for( sal_Int32 i = 0 ; i < nCount ; ++i )
{
OUString aEntry = pSeq[i];
if( m_xSFA->isFolder( aEntry ) )
{
sal_Int32 nLastSlash = aEntry.lastIndexOf( '/' );
if( nLastSlash != -1 )
{
OUString aPureEntry = aEntry.copy( nLastSlash + 1 );
// Check language sceme
int nLen = aPureEntry.getLength();
const sal_Unicode* pc = aPureEntry.getStr();
bool bStartCanBeLanguage = ( nLen >= 2 && isLetter( pc[0] ) && isLetter( pc[1] ) );
bool bIsLanguage = bStartCanBeLanguage &&
( nLen == 2 || (nLen == 5 && pc[2] == '-' && isLetter( pc[3] ) && isLetter( pc[4] )) );
if( bIsLanguage )
rv.push_back( aPureEntry );
}
}
}
}
// class TreeFileIterator
OUString TreeFileIterator::nextTreeFile( sal_Int32& rnFileSize )
{
OUString aRetFile;
while( aRetFile.isEmpty() && m_eState != END_REACHED )
{
switch( m_eState )
{
case USER_EXTENSIONS:
{
Reference< deployment::XPackage > xParentPackageBundle;
Reference< deployment::XPackage > xHelpPackage = implGetNextUserHelpPackage( xParentPackageBundle );
if( !xHelpPackage.is() )
break;
aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
break;
}
case SHARED_EXTENSIONS:
{
Reference< deployment::XPackage > xParentPackageBundle;
Reference< deployment::XPackage > xHelpPackage = implGetNextSharedHelpPackage( xParentPackageBundle );
if( !xHelpPackage.is() )
break;
aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
break;
}
case BUNDLED_EXTENSIONS:
{
Reference< deployment::XPackage > xParentPackageBundle;
Reference< deployment::XPackage > xHelpPackage = implGetNextBundledHelpPackage( xParentPackageBundle );
if( !xHelpPackage.is() )
break;
aRetFile = implGetTreeFileFromPackage( rnFileSize, xHelpPackage );
break;
}
case END_REACHED:
OSL_FAIL( "DataBaseIterator::nextTreeFile(): Invalid case END_REACHED" );
break;
}
}
return aRetFile;
}
OUString TreeFileIterator::expandURL( const OUString& aURL )
{
static Reference< util::XMacroExpander > xMacroExpander;
static Reference< uri::XUriReferenceFactory > xFac;
osl::MutexGuard aGuard( m_aMutex );
if( !xMacroExpander.is() || !xFac.is() )
{
xFac = uri::UriReferenceFactory::create( m_xContext );
xMacroExpander = util::theMacroExpander::get(m_xContext);
}
OUString aRetURL = aURL;
Reference< uri::XUriReference > uriRef;
for (;;)
{
uriRef = Reference< uri::XUriReference >( xFac->parse( aRetURL ), UNO_QUERY );
if ( uriRef.is() )
{
Reference < uri::XVndSunStarExpandUrl > sxUri( uriRef, UNO_QUERY );
if( !sxUri.is() )
break;
aRetURL = sxUri->expand( xMacroExpander );
}
}
return aRetURL;
}
OUString TreeFileIterator::implGetTreeFileFromPackage
( sal_Int32& rnFileSize, Reference< deployment::XPackage > xPackage )
{
OUString aRetFile;
OUString aLanguage = m_aLanguage;
for( sal_Int32 iPass = 0 ; iPass < 2 ; ++iPass )
{
aRetFile = expandURL( xPackage->getURL() + "/" + aLanguage + "/help.tree" );
if( iPass == 0 )
{
if( m_xSFA->exists( aRetFile ) )
break;
::std::vector< OUString > av;
implGetLanguageVectorFromPackage( av, xPackage );
::std::vector< OUString >::const_iterator pFound = LanguageTag::getFallback( av, m_aLanguage );
if( pFound != av.end() )
aLanguage = *pFound;
}
}
rnFileSize = 0;
if( m_xSFA->exists( aRetFile ) )
rnFileSize = m_xSFA->getSize( aRetFile );
else
aRetFile = "";
return aRetFile;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */