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 #include <characterdata.hxx>
25 
26 #include <string.h>
27 
28 #include <boost/shared_ptr.hpp>
29 
30 #include <com/sun/star/xml/dom/events/XDocumentEvent.hpp>
31 
32 #include "../events/mutationevent.hxx"
33 
34 
35 namespace DOM
36 {
37 
CCharacterData(CDocument const & rDocument,::osl::Mutex const & rMutex,NodeType const & reNodeType,xmlNodePtr const & rpNode)38     CCharacterData::CCharacterData(
39             CDocument const& rDocument, ::osl::Mutex const& rMutex,
40             NodeType const& reNodeType, xmlNodePtr const& rpNode)
41         : CCharacterData_Base(rDocument, rMutex, reNodeType, rpNode)
42     {
43     }
44 
dispatchEvent_Impl(OUString const & prevValue,OUString const & newValue)45     void CCharacterData::dispatchEvent_Impl(
46             OUString const& prevValue, OUString const& newValue)
47     {
48         Reference< XDocumentEvent > docevent(getOwnerDocument(), UNO_QUERY);
49         Reference< XMutationEvent > event(docevent->createEvent(
50             OUString::createFromAscii("DOMCharacterDataModified")), UNO_QUERY);
51         event->initMutationEvent(
52                 OUString::createFromAscii("DOMCharacterDataModified"),
53                 sal_True, sal_False, Reference< XNode >(),
54                 prevValue, newValue, OUString(), (AttrChangeType)0 );
55         dispatchEvent(Reference< XEvent >(event, UNO_QUERY));
56         dispatchSubtreeModified();
57     }
58 
59     /**
60     Append the string to the end of the character data of the node.
61     */
appendData(const OUString & arg)62     void SAL_CALL CCharacterData::appendData(const OUString& arg)
63         throw (RuntimeException, DOMException)
64     {
65         ::osl::ClearableMutexGuard guard(m_rMutex);
66 
67         if (m_aNodePtr != NULL)
68         {
69             OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
70             xmlNodeAddContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(arg, RTL_TEXTENCODING_UTF8).getStr()));
71             OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
72 
73             guard.clear(); // release mutex before calling event handlers
74             dispatchEvent_Impl(oldValue, newValue);
75         }
76     }
77 
78     /**
79     Remove a range of 16-bit units from the node.
80     */
deleteData(sal_Int32 offset,sal_Int32 count)81     void SAL_CALL CCharacterData::deleteData(sal_Int32 offset, sal_Int32 count)
82         throw (RuntimeException, DOMException)
83     {
84         ::osl::ClearableMutexGuard guard(m_rMutex);
85 
86         if (m_aNodePtr != NULL)
87         {
88             // get current data
89             ::boost::shared_ptr<xmlChar const> const pContent(
90                 xmlNodeGetContent(m_aNodePtr), xmlFree);
91             OString aData(reinterpret_cast<sal_Char const*>(pContent.get()));
92             OUString tmp( aData.getStr(), aData.getLength(), RTL_TEXTENCODING_UTF8);
93             if (offset > tmp.getLength() || offset < 0 || count < 0) {
94                 DOMException e;
95                 e.Code = DOMExceptionType_INDEX_SIZE_ERR;
96                 throw e;
97             }
98             if ((offset+count) > tmp.getLength())
99                 count = tmp.getLength() - offset;
100 
101             OUString tmp2 = tmp.copy(0, offset);
102             tmp2 += tmp.copy(offset+count, tmp.getLength() - (offset+count));
103             OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
104             xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr()));
105             OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
106 
107             guard.clear(); // release mutex before calling event handlers
108             dispatchEvent_Impl(oldValue, newValue);
109         }
110     }
111 
112 
113     /**
114     Return the character data of the node that implements this interface.
115     */
getData()116     OUString SAL_CALL CCharacterData::getData() throw (RuntimeException)
117     {
118         ::osl::MutexGuard const g(m_rMutex);
119 
120         OUString aData;
121         if (m_aNodePtr != NULL)
122         {
123             OSL_ENSURE(m_aNodePtr->content, "character data node with NULL content, please inform lars.oppermann@sun.com!");
124             if (m_aNodePtr->content != NULL)
125             {
126                 aData = OUString((const sal_Char*)m_aNodePtr->content, strlen((const sal_Char*)m_aNodePtr->content),  RTL_TEXTENCODING_UTF8);
127             }
128         }
129         return aData;
130     }
131 
132     /**
133     The number of 16-bit units that are available through data and the
134     substringData method below.
135     */
getLength()136     sal_Int32 SAL_CALL CCharacterData::getLength() throw (RuntimeException)
137     {
138         ::osl::MutexGuard const g(m_rMutex);
139 
140         sal_Int32 length = 0;
141         if (m_aNodePtr != NULL)
142         {
143              OUString aData((const sal_Char*)m_aNodePtr->content, strlen((const sal_Char*)m_aNodePtr->content),  RTL_TEXTENCODING_UTF8);
144              length = aData.getLength();
145         }
146         return length;
147     }
148 
149     /**
150     Insert a string at the specified 16-bit unit offset.
151     */
insertData(sal_Int32 offset,const OUString & arg)152     void SAL_CALL CCharacterData::insertData(sal_Int32 offset, const OUString& arg)
153         throw (RuntimeException, DOMException)
154     {
155         ::osl::ClearableMutexGuard guard(m_rMutex);
156 
157         if (m_aNodePtr != NULL)
158         {
159             // get current data
160             ::boost::shared_ptr<xmlChar const> const pContent(
161                 xmlNodeGetContent(m_aNodePtr), xmlFree);
162             OString aData(reinterpret_cast<sal_Char const*>(pContent.get()));
163             OUString tmp( aData.getStr(), aData.getLength(), RTL_TEXTENCODING_UTF8);
164             if (offset > tmp.getLength() || offset < 0) {
165                 DOMException e;
166                 e.Code = DOMExceptionType_INDEX_SIZE_ERR;
167                 throw e;
168             }
169 
170             OUString tmp2 = tmp.copy(0, offset);
171             tmp2 += arg;
172             tmp2 += tmp.copy(offset, tmp.getLength() - offset);
173             OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
174             xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr()));
175             OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
176 
177             guard.clear(); // release mutex before calling event handlers
178             dispatchEvent_Impl(oldValue, newValue);
179         }
180     }
181 
182 
183     /**
184     Replace the characters starting at the specified 16-bit unit offset
185     with the specified string.
186     */
replaceData(sal_Int32 offset,sal_Int32 count,const OUString & arg)187     void SAL_CALL CCharacterData::replaceData(sal_Int32 offset, sal_Int32 count, const OUString& arg)
188         throw (RuntimeException, DOMException)
189     {
190         ::osl::ClearableMutexGuard guard(m_rMutex);
191 
192         if (m_aNodePtr != NULL)
193         {
194             // get current data
195             ::boost::shared_ptr<xmlChar const> const pContent(
196                 xmlNodeGetContent(m_aNodePtr), xmlFree);
197             OString aData(reinterpret_cast<sal_Char const*>(pContent.get()));
198             OUString tmp( aData.getStr(), aData.getLength(), RTL_TEXTENCODING_UTF8);
199             if (offset > tmp.getLength() || offset < 0 || count < 0){
200                 DOMException e;
201                 e.Code = DOMExceptionType_INDEX_SIZE_ERR;
202                 throw e;
203             }
204             if ((offset+count) > tmp.getLength())
205                 count = tmp.getLength() - offset;
206 
207             OUString tmp2 = tmp.copy(0, offset);
208             tmp2 += arg;
209             tmp2 += tmp.copy(offset+count, tmp.getLength() - (offset+count));
210             OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
211             xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(tmp2, RTL_TEXTENCODING_UTF8).getStr()));
212             OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
213 
214             guard.clear(); // release mutex before calling event handlers
215             dispatchEvent_Impl(oldValue, newValue);
216         }
217     }
218 
219     /**
220     Set the character data of the node that implements this interface.
221     */
setData(const OUString & data)222     void SAL_CALL CCharacterData::setData(const OUString& data)
223         throw (RuntimeException, DOMException)
224     {
225         ::osl::ClearableMutexGuard guard(m_rMutex);
226 
227         if (m_aNodePtr != NULL)
228         {
229             OUString oldValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
230             xmlNodeSetContent(m_aNodePtr, (const xmlChar*)(OUStringToOString(data, RTL_TEXTENCODING_UTF8).getStr()));
231             OUString newValue((char*)m_aNodePtr->content, strlen((char*)m_aNodePtr->content), RTL_TEXTENCODING_UTF8);
232 
233             guard.clear(); // release mutex before calling event handlers
234             dispatchEvent_Impl(oldValue, newValue);
235         }
236     }
237 
238     /**
239     Extracts a range of data from the node.
240     */
subStringData(sal_Int32 offset,sal_Int32 count)241     OUString SAL_CALL CCharacterData::subStringData(sal_Int32 offset, sal_Int32 count)
242         throw (RuntimeException, DOMException)
243     {
244         ::osl::MutexGuard const g(m_rMutex);
245 
246         OUString aStr;
247         if (m_aNodePtr != NULL)
248         {
249             // get current data
250             ::boost::shared_ptr<xmlChar const> const pContent(
251                 xmlNodeGetContent(m_aNodePtr), xmlFree);
252             OString aData(reinterpret_cast<sal_Char const*>(pContent.get()));
253             OUString tmp( aData.getStr(), aData.getLength(), RTL_TEXTENCODING_UTF8);
254             if (offset > tmp.getLength() || offset < 0 || count < 0) {
255                 DOMException e;
256                 e.Code = DOMExceptionType_INDEX_SIZE_ERR;
257                 throw e;
258             }
259             aStr = tmp.copy(offset, count);
260         }
261         return aStr;
262     }
263 
264 
265 } // namspace DOM
266 
267