xref: /AOO41X/main/sc/source/filter/xml/XMLTextPContext.cxx (revision 3219702d903b8672ccad071eb5122597ab41728c)
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