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