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