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_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 #include "XMLTextPContext.hxx"
31 #include "xmlimprt.hxx"
32 #include "xmlcelli.hxx"
33 #include <xmloff/xmlnmspe.hxx>
34 #include <xmloff/xmltoken.hxx>
35 #include <xmloff/nmspmap.hxx>
36 #include <tools/debug.hxx>
37 #include <com/sun/star/text/XTextCursor.hpp>
38 
39 using namespace com::sun::star;
40 using namespace xmloff::token;
41 
42 class ScXMLTextTContext : public SvXMLImportContext
43 {
GetScImport() const44 	const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); }
GetScImport()45 	ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); }
46 public:
47 	ScXMLTextTContext( ScXMLImport& rImport, sal_uInt16 nPrfx,
48 						const ::rtl::OUString& rLName,
49 						const ::com::sun::star::uno::Reference<
50 										::com::sun::star::xml::sax::XAttributeList>& xAttrList,
51 						ScXMLTextPContext* pTextPContext);
52 
53 	virtual ~ScXMLTextTContext();
54 };
55 
56 
ScXMLTextTContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xAttrList,ScXMLTextPContext * pTextPContext)57 ScXMLTextTContext::ScXMLTextTContext( ScXMLImport& rImport,
58 									  sal_uInt16 nPrfx,
59 									  const ::rtl::OUString& rLName,
60 									  const ::com::sun::star::uno::Reference<
61 									  ::com::sun::star::xml::sax::XAttributeList>& xAttrList,
62 									  ScXMLTextPContext* pTextPContext) :
63 	SvXMLImportContext( rImport, nPrfx, rLName )
64 {
65 	if (pTextPContext)
66 	{
67 		sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
68 		rtl::OUString aLocalName;
69 		sal_Int32 nCount(1);
70 		for( sal_Int16 i=0; i < nAttrCount; ++i )
71 		{
72 			sal_uInt16 nPrefix(GetScImport().GetNamespaceMap().GetKeyByAttrName(
73 												xAttrList->getNameByIndex( i ), &aLocalName ));
74     		const rtl::OUString& sValue(xAttrList->getValueByIndex( i ));
75 
76 			if ((nPrefix == XML_NAMESPACE_TEXT) && IsXMLToken(aLocalName, XML_C))
77 				nCount = sValue.toInt32();
78 		}
79 		pTextPContext->AddSpaces(nCount);
80 	}
81 }
82 
~ScXMLTextTContext()83 ScXMLTextTContext::~ScXMLTextTContext()
84 {
85 }
86 
87 //------------------------------------------------------------------
88 
ScXMLTextPContext(ScXMLImport & rImport,sal_uInt16 nPrfx,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xTempAttrList,ScXMLTableRowCellContext * pTempCellContext)89 ScXMLTextPContext::ScXMLTextPContext( ScXMLImport& rImport,
90 									  sal_uInt16 nPrfx,
91 									  const ::rtl::OUString& rLName,
92 									  const ::com::sun::star::uno::Reference<
93 									  ::com::sun::star::xml::sax::XAttributeList>& xTempAttrList,
94 									  ScXMLTableRowCellContext* pTempCellContext) :
95 	SvXMLImportContext( rImport, nPrfx, rLName ),
96 	xAttrList(xTempAttrList),
97 	pTextPContext(NULL),
98 	pCellContext(pTempCellContext),
99 	sLName(rLName),
100     sSimpleContent(),
101     pContentBuffer(NULL),
102 	nPrefix(nPrfx),
103 	bIsOwn(sal_True)
104 {
105 	// here are no attributes
106 }
107 
~ScXMLTextPContext()108 ScXMLTextPContext::~ScXMLTextPContext()
109 {
110 	if (pTextPContext)
111 		delete pTextPContext;
112     if (pContentBuffer)
113         delete pContentBuffer;
114 }
115 
AddSpaces(sal_Int32 nSpaceCount)116 void ScXMLTextPContext::AddSpaces(sal_Int32 nSpaceCount)
117 {
118     // use pContentBuffer
119     if ( !pContentBuffer )
120         pContentBuffer = new rtl::OUStringBuffer( sSimpleContent );
121 
122 	sal_Char* pChars = new sal_Char[nSpaceCount];
123 	memset(pChars, ' ', nSpaceCount);
124     pContentBuffer->appendAscii(pChars, nSpaceCount);
125 	delete[] pChars;
126 }
127 
CreateChildContext(sal_uInt16 nTempPrefix,const::rtl::OUString & rLName,const::com::sun::star::uno::Reference<::com::sun::star::xml::sax::XAttributeList> & xTempAttrList)128 SvXMLImportContext *ScXMLTextPContext::CreateChildContext( sal_uInt16 nTempPrefix,
129 											const ::rtl::OUString& rLName,
130 											const ::com::sun::star::uno::Reference<
131 									  	::com::sun::star::xml::sax::XAttributeList>& xTempAttrList )
132 {
133 	SvXMLImportContext *pContext(NULL);
134 	if (!pTextPContext &&
135 		(nTempPrefix == XML_NAMESPACE_TEXT) &&
136 		IsXMLToken(rLName, XML_S))
137 		pContext = new ScXMLTextTContext( GetScImport(), nTempPrefix, rLName, xTempAttrList, this);
138 	else
139 	{
140 		if (!pTextPContext)
141 		{
142             rtl::OUString sSetString;
143             if ( pContentBuffer )
144                 sSetString = pContentBuffer->makeStringAndClear();
145             else
146                 sSetString = sSimpleContent;
147 
148             sal_Unicode cNonSpace(0);
149 
150             sal_Int32 nLength = sSetString.getLength();
151             if ( nLength > 0 )
152             {
153                 sal_Unicode cLast = sSetString.getStr()[ nLength - 1 ];
154                 if ( cLast != (sal_Unicode)' ' )
155                 {
156                     // #i53253# To keep XMLParaContext's whitespace handling in sync,
157                     // if there's a non-space character at the end of the existing string,
158                     // it has to be processed by XMLParaContext.
159 
160                     cNonSpace = cLast;
161                     sSetString = sSetString.copy( 0, nLength - 1 );  // remove from the string for SetCursorOnTextImport
162                 }
163             }
164 
165             pCellContext->SetCursorOnTextImport( sSetString );
166 
167 			pTextPContext = GetScImport().GetTextImport()->CreateTextChildContext(
168 									GetScImport(), nPrefix, sLName, xAttrList);
169 
170             if ( cNonSpace != 0 )
171             {
172                 // pass non-space character through XMLParaContext, so a following space isn't ignored
173                 pTextPContext->Characters( rtl::OUString( cNonSpace ) );
174             }
175 		}
176 		if (pTextPContext)
177 			pContext = pTextPContext->CreateChildContext(nTempPrefix, rLName, xTempAttrList);
178 	}
179 
180 	if( !pContext )
181 		pContext = new SvXMLImportContext( GetScImport(), nTempPrefix, rLName );
182 
183 	return pContext;
184 }
185 
Characters(const::rtl::OUString & rChars)186 void ScXMLTextPContext::Characters( const ::rtl::OUString& rChars )
187 {
188 	if (!pTextPContext)
189     {
190         // For the first call to an empty context, copy (ref-counted) the OUString.
191         // The OUStringBuffer is used only if there is more complex content.
192 
193         if ( !pContentBuffer && sSimpleContent.getLength() == 0 )
194             sSimpleContent = rChars;
195         else
196         {
197             if ( !pContentBuffer )
198                 pContentBuffer = new rtl::OUStringBuffer( sSimpleContent );
199             pContentBuffer->append(rChars);
200         }
201     }
202 	else
203 		pTextPContext->Characters(rChars);
204 }
205 
EndElement()206 void ScXMLTextPContext::EndElement()
207 {
208 	if (!pTextPContext)
209     {
210         if ( pContentBuffer )
211             pCellContext->SetString(pContentBuffer->makeStringAndClear());
212         else
213             pCellContext->SetString(sSimpleContent);
214     }
215 	else
216 	{
217 		pTextPContext->EndElement();
218 		GetScImport().SetRemoveLastChar(sal_True);
219 	}
220 }
221 
222