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