2010-10-12 15:53:47 +02:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2012-11-12 17:21:24 +00:00
|
|
|
/*
|
|
|
|
* 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 .
|
|
|
|
*/
|
2008-06-13 08:21:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
#include <txtlists.hxx>
|
2014-10-03 17:12:23 +01:00
|
|
|
#include <comphelper/random.hxx>
|
2016-09-09 14:13:49 +02:00
|
|
|
|
|
|
|
#include <o3tl/make_unique.hxx>
|
|
|
|
|
2008-06-13 08:21:15 +00:00
|
|
|
#include <tools/date.hxx>
|
|
|
|
#include <tools/time.hxx>
|
|
|
|
|
2008-10-01 06:34:11 +00:00
|
|
|
#include <xmloff/txtimp.hxx>
|
|
|
|
#include <xmloff/xmlimp.hxx>
|
|
|
|
#include <xmloff/xmlnumi.hxx>
|
|
|
|
|
|
|
|
#include <com/sun/star/style/XStyle.hpp>
|
|
|
|
#include <com/sun/star/beans/XPropertySet.hpp>
|
|
|
|
#include "XMLTextListItemContext.hxx"
|
2008-08-27 07:57:34 +00:00
|
|
|
#include "XMLTextListBlockContext.hxx"
|
2008-10-01 06:34:11 +00:00
|
|
|
#include "txtparai.hxx"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
|
2008-08-27 07:57:34 +00:00
|
|
|
|
2008-06-13 08:21:15 +00:00
|
|
|
XMLTextListsHelper::XMLTextListsHelper()
|
2016-09-09 14:13:49 +02:00
|
|
|
: msLastProcessedListId(),
|
|
|
|
msListStyleOfLastProcessedList()
|
2010-11-09 01:42:14 +05:00
|
|
|
// Inconsistent behavior regarding lists (#i92811#)
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2008-10-01 06:34:11 +00:00
|
|
|
void XMLTextListsHelper::PushListContext(
|
|
|
|
XMLTextListBlockContext *i_pListBlock)
|
|
|
|
{
|
2016-02-04 15:56:46 +01:00
|
|
|
mListStack.emplace(i_pListBlock,
|
2015-11-10 10:29:15 +01:00
|
|
|
static_cast<XMLTextListItemContext*>(nullptr),
|
2016-02-04 15:56:46 +01:00
|
|
|
static_cast<XMLNumberedParaContext*>(nullptr));
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void XMLTextListsHelper::PushListContext(
|
|
|
|
XMLNumberedParaContext *i_pNumberedParagraph)
|
|
|
|
{
|
2016-02-04 15:56:46 +01:00
|
|
|
mListStack.emplace(
|
2015-11-10 10:29:15 +01:00
|
|
|
static_cast<XMLTextListBlockContext*>(nullptr),
|
2016-02-04 15:56:46 +01:00
|
|
|
static_cast<XMLTextListItemContext*>(nullptr), i_pNumberedParagraph);
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void XMLTextListsHelper::PopListContext()
|
|
|
|
{
|
2014-11-25 14:48:21 +01:00
|
|
|
assert(mListStack.size());
|
2009-04-23 10:42:05 +00:00
|
|
|
if ( !mListStack.empty())
|
|
|
|
mListStack.pop();
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void XMLTextListsHelper::ListContextTop(
|
|
|
|
XMLTextListBlockContext*& o_pListBlockContext,
|
|
|
|
XMLTextListItemContext*& o_pListItemContext,
|
|
|
|
XMLNumberedParaContext*& o_pNumberedParagraphContext )
|
|
|
|
{
|
2009-04-23 10:42:05 +00:00
|
|
|
if ( !mListStack.empty() ) {
|
2008-10-01 06:34:11 +00:00
|
|
|
o_pListBlockContext =
|
2016-09-06 16:12:40 +02:00
|
|
|
static_cast<XMLTextListBlockContext*>(std::get<0>(mListStack.top()).get());
|
2008-10-01 06:34:11 +00:00
|
|
|
o_pListItemContext =
|
2016-09-06 16:12:40 +02:00
|
|
|
static_cast<XMLTextListItemContext *>(std::get<1>(mListStack.top()).get());
|
2008-10-01 06:34:11 +00:00
|
|
|
o_pNumberedParagraphContext =
|
2016-09-06 16:12:40 +02:00
|
|
|
static_cast<XMLNumberedParaContext *>(std::get<2>(mListStack.top()).get());
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void XMLTextListsHelper::SetListItem( XMLTextListItemContext *i_pListItem )
|
|
|
|
{
|
|
|
|
// may be cleared by ListBlockContext for upper list...
|
|
|
|
if (i_pListItem) {
|
2014-11-25 14:48:21 +01:00
|
|
|
assert(mListStack.size());
|
2016-09-06 16:12:40 +02:00
|
|
|
assert(std::get<0>(mListStack.top()).is() &&
|
2008-10-01 06:34:11 +00:00
|
|
|
"internal error: SetListItem: mListStack has no ListBlock");
|
2016-09-06 16:12:40 +02:00
|
|
|
assert(!std::get<1>(mListStack.top()).is() &&
|
2008-10-01 06:34:11 +00:00
|
|
|
"error: SetListItem: list item already exists");
|
|
|
|
}
|
2009-04-23 10:42:05 +00:00
|
|
|
if ( !mListStack.empty() ) {
|
2016-01-31 12:28:28 +00:00
|
|
|
std::get<1>(mListStack.top()) = i_pListItem;
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-09 01:42:14 +05:00
|
|
|
// Handling for parameter <sListStyleDefaultListId> (#i92811#)
|
2014-03-13 15:04:48 +02:00
|
|
|
void XMLTextListsHelper::KeepListAsProcessed( const OUString& sListId,
|
|
|
|
const OUString& sListStyleName,
|
|
|
|
const OUString& sContinueListId,
|
|
|
|
const OUString& sListStyleDefaultListId )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
|
|
|
if ( IsListProcessed( sListId ) )
|
|
|
|
{
|
2014-11-25 14:48:21 +01:00
|
|
|
assert(false &&
|
2008-08-27 07:57:34 +00:00
|
|
|
"<XMLTextListsHelper::KeepListAsProcessed(..)> - list id already added" );
|
2008-06-13 08:21:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( !mpProcessedLists )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
mpProcessedLists = o3tl::make_unique<tMapForLists>();
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
::std::pair< OUString, OUString >
|
2008-06-13 08:21:15 +00:00
|
|
|
aListData( sListStyleName, sContinueListId );
|
|
|
|
(*mpProcessedLists)[ sListId ] = aListData;
|
|
|
|
|
|
|
|
msLastProcessedListId = sListId;
|
|
|
|
msListStyleOfLastProcessedList = sListStyleName;
|
2008-08-27 07:57:34 +00:00
|
|
|
|
2010-11-09 01:42:14 +05:00
|
|
|
// Inconsistent behavior regarding lists (#i92811#)
|
2012-01-27 15:39:50 -02:00
|
|
|
if ( !sListStyleDefaultListId.isEmpty())
|
2008-08-27 07:57:34 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( !mpMapListIdToListStyleDefaultListId )
|
2008-08-27 07:57:34 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
mpMapListIdToListStyleDefaultListId = o3tl::make_unique<tMapForLists>();
|
2008-08-27 07:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( mpMapListIdToListStyleDefaultListId->find( sListStyleName ) ==
|
|
|
|
mpMapListIdToListStyleDefaultListId->end() )
|
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
::std::pair< OUString, OUString >
|
2008-08-27 07:57:34 +00:00
|
|
|
aListIdMapData( sListId, sListStyleDefaultListId );
|
|
|
|
(*mpMapListIdToListStyleDefaultListId)[ sListStyleName ] =
|
|
|
|
aListIdMapData;
|
|
|
|
}
|
|
|
|
}
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
|
|
|
|
2014-04-07 16:42:18 +02:00
|
|
|
bool XMLTextListsHelper::IsListProcessed( const OUString& sListId ) const
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( !mpProcessedLists )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2014-04-07 16:42:18 +02:00
|
|
|
return false;
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return mpProcessedLists->find( sListId ) != mpProcessedLists->end();
|
|
|
|
}
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString XMLTextListsHelper::GetListStyleOfProcessedList(
|
2014-03-13 15:04:48 +02:00
|
|
|
const OUString& sListId ) const
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( mpProcessedLists )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
|
|
|
tMapForLists::const_iterator aIter = mpProcessedLists->find( sListId );
|
|
|
|
if ( aIter != mpProcessedLists->end() )
|
|
|
|
{
|
|
|
|
return (*aIter).second.first;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
return OUString();
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString XMLTextListsHelper::GetContinueListIdOfProcessedList(
|
2014-03-13 15:04:48 +02:00
|
|
|
const OUString& sListId ) const
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( mpProcessedLists )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
|
|
|
tMapForLists::const_iterator aIter = mpProcessedLists->find( sListId );
|
|
|
|
if ( aIter != mpProcessedLists->end() )
|
|
|
|
{
|
|
|
|
return (*aIter).second.second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
return OUString();
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString XMLTextListsHelper::GenerateNewListId() const
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2015-11-10 10:29:15 +01:00
|
|
|
static bool bHack = (getenv("LIBO_ONEWAY_STABLE_ODF_EXPORT") != nullptr);
|
Add hack to optionally get stable ODF output from the same input
To be used in regression testing and similar scenarios, where the output ODF
is *not* intended to be further manipulated in LibreOffice. An environment
variable LIBO_ONEWAY_STABLE_ODF_EXPORT is used to toggle this behaviour. I am
not 100% sure whether the generated ODF with the hack toggled on is even fully
correct, but correctness is not the purpose of the hack anyway.
Two classes of issues handled: 1) Automatic style names and 2) use of
randomness.
For class 1), when the hack toggle is in effect, we generate the names at
first as strings based on all the properties of the style, and sort them based
on those, and then rename them (for brevity in the output) to the "normal"
form of a short prefix plus a number (like "P12").
Sure, it would have been better to just figure out *why* the automatic style
naming currently is not stable in the first place, but outputs the styles in
different order (with some styles being assigned different numbers) in
separate invokations of LibreOffice), but I was unable to understand that.
Possibly this code could be used in all cases, except that it does break some
unit test (can't recall which right now). I don't know whether that is simply
because the unit test assumes too much knowledge of the internal workings of
the automatic style name generation, or whether the generated ODF is actually
invalid.
For 2), I found a handful of places where randomness was used to generated
various kinds of identifiers in ODF output. I changed those to just use large
(64-bit) non-overlapping integers instead. I assume there *is* a point in the
original code in each case that explains why randomness is needed, so the hack
definitely needs to be optional and used only for the above mentioned
scenarios.
Change-Id: I17b657197e38bcf24abdfe61ad4a277f4339eeae
2013-09-30 15:23:35 +03:00
|
|
|
OUString sTmpStr( "list" );
|
|
|
|
|
|
|
|
if (bHack)
|
|
|
|
{
|
|
|
|
static sal_Int64 nIdCounter = SAL_CONST_INT64(5000000000);
|
|
|
|
sTmpStr += OUString::number(nIdCounter++);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Value of xml:id in element <text:list> has to be a valid ID type (#i92478#)
|
2014-09-28 15:49:26 +02:00
|
|
|
sal_Int64 n = ::tools::Time( ::tools::Time::SYSTEM ).GetTime();
|
2016-07-08 17:08:47 +02:00
|
|
|
n += Date( Date::SYSTEM ).GetDateUnsigned();
|
2014-10-03 17:12:23 +01:00
|
|
|
n += comphelper::rng::uniform_int_distribution(0, std::numeric_limits<int>::max());
|
Add hack to optionally get stable ODF output from the same input
To be used in regression testing and similar scenarios, where the output ODF
is *not* intended to be further manipulated in LibreOffice. An environment
variable LIBO_ONEWAY_STABLE_ODF_EXPORT is used to toggle this behaviour. I am
not 100% sure whether the generated ODF with the hack toggled on is even fully
correct, but correctness is not the purpose of the hack anyway.
Two classes of issues handled: 1) Automatic style names and 2) use of
randomness.
For class 1), when the hack toggle is in effect, we generate the names at
first as strings based on all the properties of the style, and sort them based
on those, and then rename them (for brevity in the output) to the "normal"
form of a short prefix plus a number (like "P12").
Sure, it would have been better to just figure out *why* the automatic style
naming currently is not stable in the first place, but outputs the styles in
different order (with some styles being assigned different numbers) in
separate invokations of LibreOffice), but I was unable to understand that.
Possibly this code could be used in all cases, except that it does break some
unit test (can't recall which right now). I don't know whether that is simply
because the unit test assumes too much knowledge of the internal workings of
the automatic style name generation, or whether the generated ODF is actually
invalid.
For 2), I found a handful of places where randomness was used to generated
various kinds of identifiers in ODF output. I changed those to just use large
(64-bit) non-overlapping integers instead. I assume there *is* a point in the
original code in each case that explains why randomness is needed, so the hack
definitely needs to be optional and used only for the above mentioned
scenarios.
Change-Id: I17b657197e38bcf24abdfe61ad4a277f4339eeae
2013-09-30 15:23:35 +03:00
|
|
|
// Value of xml:id in element <text:list> has to be a valid ID type (#i92478#)
|
|
|
|
sTmpStr += OUString::number( n );
|
|
|
|
}
|
2008-06-13 08:21:15 +00:00
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString sNewListId( sTmpStr );
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( mpProcessedLists )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2011-07-30 23:51:40 +02:00
|
|
|
long nHitCount = 0;
|
2008-06-13 08:21:15 +00:00
|
|
|
while ( mpProcessedLists->find( sNewListId ) != mpProcessedLists->end() )
|
|
|
|
{
|
|
|
|
++nHitCount;
|
|
|
|
sNewListId = sTmpStr;
|
2013-08-21 15:07:31 +02:00
|
|
|
sNewListId += OUString::number( nHitCount );
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sNewListId;
|
|
|
|
}
|
|
|
|
|
2010-11-09 01:42:14 +05:00
|
|
|
// Provide list id for a certain list block for import (#i92811#)
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString XMLTextListsHelper::GetListIdForListBlock( XMLTextListBlockContext& rListBlock )
|
2008-08-27 07:57:34 +00:00
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString sListBlockListId( rListBlock.GetContinueListId() );
|
2012-01-27 15:39:50 -02:00
|
|
|
if ( sListBlockListId.isEmpty() )
|
2008-08-27 07:57:34 +00:00
|
|
|
{
|
|
|
|
sListBlockListId = rListBlock.GetListId();
|
|
|
|
}
|
|
|
|
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( mpMapListIdToListStyleDefaultListId )
|
2008-08-27 07:57:34 +00:00
|
|
|
{
|
2012-01-27 15:39:50 -02:00
|
|
|
if ( !sListBlockListId.isEmpty() )
|
2008-08-27 07:57:34 +00:00
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
const OUString sListStyleName =
|
2008-08-27 07:57:34 +00:00
|
|
|
GetListStyleOfProcessedList( sListBlockListId );
|
|
|
|
|
|
|
|
tMapForLists::const_iterator aIter =
|
|
|
|
mpMapListIdToListStyleDefaultListId->find( sListStyleName );
|
|
|
|
if ( aIter != mpMapListIdToListStyleDefaultListId->end() )
|
|
|
|
{
|
|
|
|
if ( (*aIter).second.first == sListBlockListId )
|
|
|
|
{
|
|
|
|
sListBlockListId = (*aIter).second.second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sListBlockListId;
|
|
|
|
}
|
|
|
|
|
2014-03-13 15:04:48 +02:00
|
|
|
void XMLTextListsHelper::StoreLastContinuingList( const OUString& sListId,
|
|
|
|
const OUString& sContinuingListId )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( !mpContinuingLists )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
mpContinuingLists = o3tl::make_unique<tMapForContinuingLists>();
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
(*mpContinuingLists)[ sListId ] = sContinuingListId;
|
|
|
|
}
|
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString XMLTextListsHelper::GetLastContinuingListId(
|
2014-03-13 15:04:48 +02:00
|
|
|
const OUString& sListId ) const
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( mpContinuingLists )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
|
|
|
tMapForContinuingLists::const_iterator aIter =
|
|
|
|
mpContinuingLists->find( sListId );
|
|
|
|
if ( aIter != mpContinuingLists->end() )
|
|
|
|
{
|
|
|
|
return (*aIter).second;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return sListId;
|
|
|
|
}
|
|
|
|
|
2014-03-13 15:04:48 +02:00
|
|
|
void XMLTextListsHelper::PushListOnStack( const OUString& sListId,
|
|
|
|
const OUString& sListStyleName )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( !mpListStack )
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
mpListStack = o3tl::make_unique<tStackForLists>();
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
2013-04-07 12:06:47 +02:00
|
|
|
::std::pair< OUString, OUString >
|
2008-06-13 08:21:15 +00:00
|
|
|
aListData( sListId, sListStyleName );
|
|
|
|
mpListStack->push_back( aListData );
|
|
|
|
}
|
|
|
|
void XMLTextListsHelper::PopListFromStack()
|
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
if ( mpListStack &&
|
2008-06-13 08:21:15 +00:00
|
|
|
mpListStack->size() > 0 )
|
|
|
|
{
|
|
|
|
mpListStack->pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-07 16:42:18 +02:00
|
|
|
bool XMLTextListsHelper::EqualsToTopListStyleOnStack( const OUString& sListId ) const
|
2008-06-13 08:21:15 +00:00
|
|
|
{
|
2016-09-09 14:13:49 +02:00
|
|
|
return mpListStack && sListId == mpListStack->back().second;
|
2008-06-13 08:21:15 +00:00
|
|
|
}
|
2008-10-01 06:34:11 +00:00
|
|
|
|
2013-04-07 12:06:47 +02:00
|
|
|
OUString
|
2008-10-01 06:34:11 +00:00
|
|
|
XMLTextListsHelper::GetNumberedParagraphListId(
|
|
|
|
const sal_uInt16 i_Level,
|
2014-03-13 15:04:48 +02:00
|
|
|
const OUString& i_StyleName)
|
2008-10-01 06:34:11 +00:00
|
|
|
{
|
2012-01-27 15:39:50 -02:00
|
|
|
if (i_StyleName.isEmpty()) {
|
2014-11-25 14:48:21 +01:00
|
|
|
SAL_INFO("xmloff.text", "invalid numbered-paragraph: no style-name");
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
2012-01-27 15:39:50 -02:00
|
|
|
if (!i_StyleName.isEmpty()
|
2008-10-01 06:34:11 +00:00
|
|
|
&& (i_Level < mLastNumberedParagraphs.size())
|
|
|
|
&& (mLastNumberedParagraphs[i_Level].first == i_StyleName) )
|
|
|
|
{
|
2014-11-25 14:48:21 +01:00
|
|
|
assert(!mLastNumberedParagraphs[i_Level].second.isEmpty() &&
|
2008-10-01 06:34:11 +00:00
|
|
|
"internal error: numbered-paragraph style-name but no list-id?");
|
|
|
|
return mLastNumberedParagraphs[i_Level].second;
|
|
|
|
} else {
|
|
|
|
return GenerateNewListId();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ClampLevel(uno::Reference<container::XIndexReplace> const& i_xNumRules,
|
|
|
|
sal_Int16 & io_rLevel)
|
|
|
|
{
|
2014-11-25 14:48:21 +01:00
|
|
|
assert(i_xNumRules.is());
|
2008-10-01 06:34:11 +00:00
|
|
|
if (i_xNumRules.is()) {
|
|
|
|
const sal_Int32 nLevelCount( i_xNumRules->getCount() );
|
|
|
|
if ( io_rLevel >= nLevelCount ) {
|
|
|
|
io_rLevel = sal::static_int_cast< sal_Int16 >(nLevelCount-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uno::Reference<container::XIndexReplace>
|
|
|
|
XMLTextListsHelper::EnsureNumberedParagraph(
|
|
|
|
SvXMLImport & i_rImport,
|
2014-03-13 15:04:48 +02:00
|
|
|
const OUString& i_ListId,
|
|
|
|
sal_Int16 & io_rLevel, const OUString& i_StyleName)
|
2008-10-01 06:34:11 +00:00
|
|
|
{
|
2014-11-25 14:48:21 +01:00
|
|
|
assert(!i_ListId.isEmpty());
|
|
|
|
assert(io_rLevel >= 0);
|
2008-10-01 06:34:11 +00:00
|
|
|
NumParaList_t & rNPList( mNPLists[i_ListId] );
|
2013-04-07 12:06:47 +02:00
|
|
|
const OUString none; // default
|
2013-04-11 11:31:40 +02:00
|
|
|
if ( rNPList.empty() ) {
|
2008-10-01 06:34:11 +00:00
|
|
|
// create default list style for top level
|
|
|
|
sal_Int16 lev(0);
|
|
|
|
rNPList.push_back(::std::make_pair(none,
|
2015-11-10 10:29:15 +01:00
|
|
|
MakeNumRule(i_rImport, nullptr, none, none, lev) ));
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
|
|
|
// create num rule first because this might clamp the level...
|
|
|
|
uno::Reference<container::XIndexReplace> xNumRules;
|
2012-01-27 15:39:50 -02:00
|
|
|
if ((0 == io_rLevel) || rNPList.empty() || !i_StyleName.isEmpty()) {
|
2008-10-01 06:34:11 +00:00
|
|
|
// no parent to inherit from, or explicit style given => new numrules!
|
|
|
|
// index of parent: level - 1, but maybe that does not exist
|
|
|
|
const size_t parent( std::min(static_cast<size_t>(io_rLevel),
|
|
|
|
rNPList.size()) - 1 );
|
|
|
|
xNumRules = MakeNumRule(i_rImport,
|
2015-11-10 10:29:15 +01:00
|
|
|
io_rLevel > 0 ? rNPList[parent].second : nullptr,
|
2008-10-01 06:34:11 +00:00
|
|
|
io_rLevel > 0 ? rNPList[parent].first : none,
|
|
|
|
i_StyleName, io_rLevel);
|
|
|
|
} else {
|
|
|
|
// no style given, but has a parent => reuse parent numrules!
|
|
|
|
ClampLevel(rNPList.back().second, io_rLevel);
|
|
|
|
}
|
|
|
|
if (static_cast<sal_uInt16>(io_rLevel) + 1U > rNPList.size()) {
|
|
|
|
// new level: need to enlarge
|
|
|
|
for (size_t i = rNPList.size();
|
2012-06-12 14:13:22 +02:00
|
|
|
i < static_cast<size_t>(io_rLevel); ++i)
|
|
|
|
{
|
|
|
|
NumParaList_t::value_type const rule(rNPList.back());
|
|
|
|
rNPList.push_back(rule);
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
2012-06-12 14:13:22 +02:00
|
|
|
NumParaList_t::value_type const rule(rNPList.back());
|
2008-10-01 06:34:11 +00:00
|
|
|
rNPList.push_back(xNumRules.is()
|
|
|
|
? ::std::make_pair(i_StyleName, xNumRules)
|
2012-06-12 14:13:22 +02:00
|
|
|
: rule);
|
2008-10-01 06:34:11 +00:00
|
|
|
} else {
|
|
|
|
// old level: no need to enlarge; possibly shrink
|
|
|
|
if (xNumRules.is()) {
|
|
|
|
rNPList[io_rLevel] = std::make_pair(i_StyleName, xNumRules);
|
|
|
|
}
|
|
|
|
if (static_cast<sal_uInt16>(io_rLevel) + 1U < rNPList.size()) {
|
|
|
|
rNPList.erase(rNPList.begin() + io_rLevel + 1, rNPList.end());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// remember the list id
|
|
|
|
if (mLastNumberedParagraphs.size() <= static_cast<size_t>(io_rLevel)) {
|
|
|
|
mLastNumberedParagraphs.resize(io_rLevel+1);
|
|
|
|
}
|
|
|
|
mLastNumberedParagraphs[io_rLevel] = std::make_pair(i_StyleName, i_ListId);
|
|
|
|
return rNPList.back().second;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** extracted from the XMLTextListBlockContext constructor */
|
|
|
|
uno::Reference<container::XIndexReplace>
|
|
|
|
XMLTextListsHelper::MakeNumRule(
|
|
|
|
SvXMLImport & i_rImport,
|
|
|
|
const uno::Reference<container::XIndexReplace>& i_rNumRule,
|
2014-03-13 15:04:48 +02:00
|
|
|
const OUString& i_ParentStyleName,
|
|
|
|
const OUString& i_StyleName,
|
2008-10-01 06:34:11 +00:00
|
|
|
sal_Int16 & io_rLevel,
|
2014-04-07 16:42:18 +02:00
|
|
|
bool* o_pRestartNumbering,
|
|
|
|
bool* io_pSetDefaults)
|
2008-10-01 06:34:11 +00:00
|
|
|
{
|
2014-11-03 14:03:54 +02:00
|
|
|
static const char s_NumberingRules[] = "NumberingRules";
|
2008-10-01 06:34:11 +00:00
|
|
|
uno::Reference<container::XIndexReplace> xNumRules(i_rNumRule);
|
2012-01-27 15:39:50 -02:00
|
|
|
if ( !i_StyleName.isEmpty() && i_StyleName != i_ParentStyleName )
|
2008-10-01 06:34:11 +00:00
|
|
|
{
|
2013-04-07 12:06:47 +02:00
|
|
|
const OUString sDisplayStyleName(
|
2008-10-01 06:34:11 +00:00
|
|
|
i_rImport.GetStyleDisplayName( XML_STYLE_FAMILY_TEXT_LIST,
|
|
|
|
i_StyleName) );
|
|
|
|
const uno::Reference < container::XNameContainer >& rNumStyles(
|
|
|
|
i_rImport.GetTextImport()->GetNumberingStyles() );
|
|
|
|
if( rNumStyles.is() && rNumStyles->hasByName( sDisplayStyleName ) )
|
|
|
|
{
|
|
|
|
uno::Reference < style::XStyle > xStyle;
|
|
|
|
uno::Any any = rNumStyles->getByName( sDisplayStyleName );
|
|
|
|
any >>= xStyle;
|
|
|
|
|
|
|
|
uno::Reference< beans::XPropertySet > xPropSet( xStyle,
|
|
|
|
uno::UNO_QUERY );
|
2010-03-15 12:53:14 +01:00
|
|
|
any = xPropSet->getPropertyValue(s_NumberingRules);
|
2008-10-01 06:34:11 +00:00
|
|
|
any >>= xNumRules;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const SvxXMLListStyleContext *pListStyle(
|
|
|
|
i_rImport.GetTextImport()->FindAutoListStyle( i_StyleName ) );
|
|
|
|
if( pListStyle )
|
|
|
|
{
|
|
|
|
xNumRules = pListStyle->GetNumRules();
|
|
|
|
if( !xNumRules.is() )
|
|
|
|
{
|
|
|
|
pListStyle->CreateAndInsertAuto();
|
|
|
|
xNumRules = pListStyle->GetNumRules();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-24 12:35:11 +02:00
|
|
|
bool bSetDefaults(io_pSetDefaults && *io_pSetDefaults);
|
2008-10-01 06:34:11 +00:00
|
|
|
if ( !xNumRules.is() )
|
|
|
|
{
|
|
|
|
// If no style name has been specified for this style and for any
|
|
|
|
// parent or if no num rule with the specified name exists,
|
|
|
|
// create a new one.
|
|
|
|
|
|
|
|
xNumRules =
|
|
|
|
SvxXMLListStyleContext::CreateNumRule( i_rImport.GetModel() );
|
2014-11-25 14:48:21 +01:00
|
|
|
assert(xNumRules.is());
|
2008-10-01 06:34:11 +00:00
|
|
|
if ( !xNumRules.is() )
|
|
|
|
return xNumRules;
|
|
|
|
|
|
|
|
// Because it is a new num rule, numbering must not be restarted.
|
2014-04-07 16:42:18 +02:00
|
|
|
if (o_pRestartNumbering) *o_pRestartNumbering = false;
|
|
|
|
bSetDefaults = true;
|
2008-10-01 06:34:11 +00:00
|
|
|
if (io_pSetDefaults) *io_pSetDefaults = bSetDefaults;
|
|
|
|
}
|
|
|
|
|
|
|
|
ClampLevel(xNumRules, io_rLevel);
|
|
|
|
|
|
|
|
if ( bSetDefaults )
|
|
|
|
{
|
|
|
|
// Because there is no list style sheet for this style, a default
|
|
|
|
// format must be set for any level of this num rule.
|
|
|
|
SvxXMLListStyleContext::SetDefaultStyle( xNumRules, io_rLevel,
|
2014-03-31 11:47:05 +02:00
|
|
|
false );
|
2008-10-01 06:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return xNumRules;
|
|
|
|
}
|
|
|
|
|
2010-10-12 15:53:47 +02:00
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|