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_xmloff.hxx"
26 #include <tools/debug.hxx>
27 #include <com/sun/star/container/XNameContainer.hpp>
28 #include <com/sun/star/container/XIndexReplace.hpp>
29 #include <com/sun/star/style/XStyle.hpp>
30 #include <com/sun/star/beans/XPropertySet.hpp>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmlnumi.hxx>
33 #include <xmloff/nmspmap.hxx>
34 #include "xmloff/xmlnmspe.hxx"
35 #include <xmloff/xmltoken.hxx>
36 #include "XMLTextListItemContext.hxx"
37 #include "XMLTextListBlockContext.hxx"
38 #include "txtlists.hxx"
39 
40 using ::rtl::OUString;
41 using ::rtl::OUStringBuffer;
42 
43 using namespace ::com::sun::star;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::container;
46 using namespace ::com::sun::star::style;
47 using namespace ::com::sun::star::beans;
48 using namespace ::xmloff::token;
49 
50 TYPEINIT1( XMLTextListBlockContext, SvXMLImportContext );
51 
52 // OD 2008-05-07 #refactorlists#
53 // add optional parameter <bRestartNumberingAtSubList> and its handling
XMLTextListBlockContext(SvXMLImport & rImport,XMLTextImportHelper & rTxtImp,sal_uInt16 nPrfx,const OUString & rLName,const Reference<xml::sax::XAttributeList> & xAttrList,const sal_Bool bRestartNumberingAtSubList)54 XMLTextListBlockContext::XMLTextListBlockContext(
55 		SvXMLImport& rImport,
56 		XMLTextImportHelper& rTxtImp,
57         sal_uInt16 nPrfx,
58         const OUString& rLName,
59         const Reference< xml::sax::XAttributeList > & xAttrList,
60         const sal_Bool bRestartNumberingAtSubList )
61 :	SvXMLImportContext( rImport, nPrfx, rLName )
62 ,   mrTxtImport( rTxtImp )
63 // --> OD 2008-04-22 #refactorlists#
64 ,   msListStyleName()
65 // <--
66 ,   mxParentListBlock( )
67 ,   mnLevel( 0 )
68 // --> OD 2008-05-07 #refactorlists#
69 //,   mbRestartNumbering( sal_True )
70 ,   mbRestartNumbering( sal_False )
71 // <--
72 ,   mbSetDefaults( sal_False )
73 // --> OD 2008-04-22 #refactorlists#
74 ,   msListId()
75 ,   msContinueListId()
76 // <--
77 {
78     static ::rtl::OUString s_PropNameDefaultListId(
79         RTL_CONSTASCII_USTRINGPARAM("DefaultListId"));
80     {
81         // get the parent list block context (if any); this is a bit ugly...
82         XMLTextListBlockContext * pLB(0);
83         XMLTextListItemContext  * pLI(0);
84         XMLNumberedParaContext  * pNP(0);
85         rTxtImp.GetTextListHelper().ListContextTop(pLB, pLI, pNP);
86         mxParentListBlock = pLB;
87     }
88 	// Inherit style name from parent list, as well as the flags whether
89 	// numbering must be restarted and formats have to be created.
90     OUString sParentListStyleName;
91     // --> OD 2008-11-27 #158694#
92     sal_Bool bParentRestartNumbering( sal_False );
93     // <--
94     if( mxParentListBlock.Is() )
95 	{
96 		XMLTextListBlockContext *pParent =
97                                 (XMLTextListBlockContext *)&mxParentListBlock;
98         msListStyleName = pParent->GetListStyleName();
99         sParentListStyleName = msListStyleName;
100         mxNumRules = pParent->GetNumRules();
101         mnLevel = pParent->GetLevel() + 1;
102         // --> OD 2008-05-07 #refactorlists#
103 //        mbRestartNumbering = pParent->IsRestartNumbering();
104         mbRestartNumbering = pParent->IsRestartNumbering() ||
105                              bRestartNumberingAtSubList;
106         // <--
107         // --> OD 2008-11-27 #158694#
108         bParentRestartNumbering = pParent->IsRestartNumbering();
109         // <--
110         mbSetDefaults = pParent->mbSetDefaults;
111         // --> OD 2008-04-22 #refactorlists#
112         msListId = pParent->GetListId();
113         msContinueListId = pParent->GetContinueListId();
114         // <--
115 	}
116 
117     const SvXMLTokenMap& rTokenMap = mrTxtImport.GetTextListBlockAttrTokenMap();
118 
119     // --> OD 2008-05-07 #refactorlists#
120     bool bIsContinueNumberingAttributePresent( false );
121     // <--
122 	sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
123 	for( sal_Int16 i=0; i < nAttrCount; i++ )
124 	{
125 		const OUString& rAttrName = xAttrList->getNameByIndex( i );
126 		const OUString& rValue = xAttrList->getValueByIndex( i );
127 
128 		OUString aLocalName;
129 		sal_uInt16 nPrefix =
130 			GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
131 															&aLocalName );
132 		switch( rTokenMap.Get( nPrefix, aLocalName ) )
133 		{
134 		case XML_TOK_TEXT_LIST_BLOCK_XMLID:
135 			sXmlId = rValue;
136 //FIXME: there is no UNO API for lists
137             // --> OD 2008-07-31 #i92221# - xml:id is also the list ID
138             if ( mnLevel == 0 ) // root <list> element
139             {
140                 msListId = rValue;
141             }
142             // <--
143 			break;
144 		case XML_TOK_TEXT_LIST_BLOCK_CONTINUE_NUMBERING:
145             mbRestartNumbering = !IsXMLToken(rValue, XML_TRUE);
146             // --> OD 2008-05-07 #refactorlists#
147             bIsContinueNumberingAttributePresent = true;
148             // <--
149 			break;
150 		case XML_TOK_TEXT_LIST_BLOCK_STYLE_NAME:
151             msListStyleName = rValue;
152 			break;
153         // --> OD 2008-04-22 #refactorlists#
154         case XML_TOK_TEXT_LIST_BLOCK_CONTINUE_LIST:
155             if ( mnLevel == 0 ) // root <list> element
156             {
157                 msContinueListId = rValue;
158             }
159             break;
160 		}
161 	}
162 
163     mxNumRules = XMLTextListsHelper::MakeNumRule(GetImport(), mxNumRules,
164         sParentListStyleName, msListStyleName,
165         mnLevel, &mbRestartNumbering, &mbSetDefaults );
166     if( !mxNumRules.is() )
167         return;
168 
169     // --> OD 2008-04-23 #refactorlists#
170     if ( mnLevel == 0 ) // root <list> element
171     {
172         XMLTextListsHelper& rTextListsHelper( mrTxtImport.GetTextListHelper() );
173         // --> OD 2008-08-15 #i92811#
174         ::rtl::OUString sListStyleDefaultListId;
175         {
176             uno::Reference< beans::XPropertySet > xNumRuleProps( mxNumRules, UNO_QUERY );
177             if ( xNumRuleProps.is() )
178             {
179                 uno::Reference< beans::XPropertySetInfo > xNumRulePropSetInfo(
180                                             xNumRuleProps->getPropertySetInfo());
181                 if (xNumRulePropSetInfo.is() &&
182                     xNumRulePropSetInfo->hasPropertyByName(
183                          s_PropNameDefaultListId))
184                 {
185                     xNumRuleProps->getPropertyValue(s_PropNameDefaultListId)
186                         >>= sListStyleDefaultListId;
187                     DBG_ASSERT( sListStyleDefaultListId.getLength() != 0,
188                                 "no default list id found at numbering rules instance. Serious defect -> please inform OD." );
189                 }
190             }
191         }
192         // <--
193         if ( msListId.getLength() == 0 )  // no text:id property found
194         {
195             sal_Int32 nUPD( 0 );
196             sal_Int32 nBuild( 0 );
197             const bool bBuildIdFound = GetImport().getBuildIds( nUPD, nBuild );
198             if ( rImport.IsTextDocInOOoFileFormat() ||
199                  ( bBuildIdFound && nUPD == 680 ) )
200             {
201                 // handling former documents written by OpenOffice.org:
202                 // use default list id of numbering rules instance, if existing
203                 // --> OD 2008-08-15 #i92811#
204                 if ( sListStyleDefaultListId.getLength() != 0 )
205                 {
206                     msListId = sListStyleDefaultListId;
207                     if ( !bIsContinueNumberingAttributePresent &&
208                          !mbRestartNumbering &&
209                          rTextListsHelper.IsListProcessed( msListId ) )
210                     {
211                         mbRestartNumbering = sal_True;
212                     }
213                 }
214                 // <--
215             }
216             if ( msListId.getLength() == 0 )
217             {
218                 // generate a new list id for the list
219                 msListId = rTextListsHelper.GenerateNewListId();
220             }
221         }
222 
223         if ( bIsContinueNumberingAttributePresent && !mbRestartNumbering &&
224              msContinueListId.getLength() == 0 )
225         {
226             ::rtl::OUString Last( rTextListsHelper.GetLastProcessedListId() );
227             if ( rTextListsHelper.GetListStyleOfLastProcessedList() == msListStyleName
228                  && Last != msListId )
229             {
230                 msContinueListId = Last;
231             }
232         }
233 
234         if ( msContinueListId.getLength() > 0 )
235         {
236             if ( !rTextListsHelper.IsListProcessed( msContinueListId ) )
237             {
238                 msContinueListId = ::rtl::OUString();
239             }
240             else
241             {
242                 // search continue list chain for master list and
243                 // continue the master list.
244                 ::rtl::OUString sTmpStr =
245                     rTextListsHelper.GetContinueListIdOfProcessedList( msContinueListId );
246                 while ( sTmpStr.getLength() > 0 )
247                 {
248                     msContinueListId = sTmpStr;
249 
250                     sTmpStr =
251                         rTextListsHelper.GetContinueListIdOfProcessedList( msContinueListId );
252                 }
253             }
254         }
255 
256         if ( !rTextListsHelper.IsListProcessed( msListId ) )
257         {
258             // --> OD 2008-08-15 #i92811#
259             rTextListsHelper.KeepListAsProcessed(
260                 msListId, msListStyleName, msContinueListId,
261                 sListStyleDefaultListId );
262             // <--
263         }
264     }
265     // <--
266 
267     // Remember this list block.
268     mrTxtImport.GetTextListHelper().PushListContext( this );
269 }
270 
~XMLTextListBlockContext()271 XMLTextListBlockContext::~XMLTextListBlockContext()
272 {
273 }
274 
EndElement()275 void XMLTextListBlockContext::EndElement()
276 {
277 	// Numbering has not to be restarted if it has been restarted within
278 	// a child list.
279 	XMLTextListBlockContext *pParent =
280                                 (XMLTextListBlockContext *)&mxParentListBlock;
281 	if( pParent )
282 	{
283         pParent->mbRestartNumbering = mbRestartNumbering;
284 	}
285 
286 	// Restore current list block.
287     mrTxtImport.GetTextListHelper().PopListContext();
288 
289 	// Any paragraph following the list within the same list item must not
290 	// be numbered.
291     mrTxtImport.GetTextListHelper().SetListItem( 0 );
292 }
293 
CreateChildContext(sal_uInt16 nPrefix,const OUString & rLocalName,const Reference<xml::sax::XAttributeList> & xAttrList)294 SvXMLImportContext *XMLTextListBlockContext::CreateChildContext(
295 		sal_uInt16 nPrefix,
296 		const OUString& rLocalName,
297 		const Reference< xml::sax::XAttributeList > & xAttrList )
298 {
299 	SvXMLImportContext *pContext = 0;
300 
301 	const SvXMLTokenMap& rTokenMap =
302                         mrTxtImport.GetTextListBlockElemTokenMap();
303 	sal_Bool bHeader = sal_False;
304 	switch( rTokenMap.Get( nPrefix, rLocalName ) )
305 	{
306 	case XML_TOK_TEXT_LIST_HEADER:
307 		bHeader = sal_True;
308 	case XML_TOK_TEXT_LIST_ITEM:
309         pContext = new XMLTextListItemContext( GetImport(), mrTxtImport,
310 												nPrefix, rLocalName,
311 							 				 xAttrList, bHeader );
312 		break;
313 	}
314 
315 	if( !pContext )
316 		pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName );
317 
318 	return pContext;
319 }
320 
321 // --> OD 2008-04-22 #refactorlists#
GetListId() const322 const ::rtl::OUString& XMLTextListBlockContext::GetListId() const
323 {
324     return msListId;
325 }
326 
GetContinueListId() const327 const ::rtl::OUString& XMLTextListBlockContext::GetContinueListId() const
328 {
329     return msContinueListId;
330 }
331 // <--
332 
333