1*b1cdbd2cSJim Jagielski /**************************************************************
2*b1cdbd2cSJim Jagielski  *
3*b1cdbd2cSJim Jagielski  * Licensed to the Apache Software Foundation (ASF) under one
4*b1cdbd2cSJim Jagielski  * or more contributor license agreements.  See the NOTICE file
5*b1cdbd2cSJim Jagielski  * distributed with this work for additional information
6*b1cdbd2cSJim Jagielski  * regarding copyright ownership.  The ASF licenses this file
7*b1cdbd2cSJim Jagielski  * to you under the Apache License, Version 2.0 (the
8*b1cdbd2cSJim Jagielski  * "License"); you may not use this file except in compliance
9*b1cdbd2cSJim Jagielski  * with the License.  You may obtain a copy of the License at
10*b1cdbd2cSJim Jagielski  *
11*b1cdbd2cSJim Jagielski  *   http://www.apache.org/licenses/LICENSE-2.0
12*b1cdbd2cSJim Jagielski  *
13*b1cdbd2cSJim Jagielski  * Unless required by applicable law or agreed to in writing,
14*b1cdbd2cSJim Jagielski  * software distributed under the License is distributed on an
15*b1cdbd2cSJim Jagielski  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*b1cdbd2cSJim Jagielski  * KIND, either express or implied.  See the License for the
17*b1cdbd2cSJim Jagielski  * specific language governing permissions and limitations
18*b1cdbd2cSJim Jagielski  * under the License.
19*b1cdbd2cSJim Jagielski  *
20*b1cdbd2cSJim Jagielski  *************************************************************/
21*b1cdbd2cSJim Jagielski 
22*b1cdbd2cSJim Jagielski 
23*b1cdbd2cSJim Jagielski #include <string.h>
24*b1cdbd2cSJim Jagielski 
25*b1cdbd2cSJim Jagielski #include <com/sun/star/lang/XServiceInfo.hpp>
26*b1cdbd2cSJim Jagielski #include <com/sun/star/util/XCloneable.hpp>
27*b1cdbd2cSJim Jagielski #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
28*b1cdbd2cSJim Jagielski #include <com/sun/star/xml/sax/XParser.hpp>
29*b1cdbd2cSJim Jagielski #include <com/sun/star/xml/sax/SAXParseException.hpp>
30*b1cdbd2cSJim Jagielski #include <com/sun/star/xml/sax/SAXInvalidCharacterException.hpp>
31*b1cdbd2cSJim Jagielski 
32*b1cdbd2cSJim Jagielski #include <com/sun/star/io/XActiveDataSource.hpp>
33*b1cdbd2cSJim Jagielski 
34*b1cdbd2cSJim Jagielski #include <cppuhelper/factory.hxx>
35*b1cdbd2cSJim Jagielski #include <cppuhelper/weak.hxx>
36*b1cdbd2cSJim Jagielski #include <cppuhelper/implbase3.hxx>
37*b1cdbd2cSJim Jagielski 
38*b1cdbd2cSJim Jagielski #include <rtl/strbuf.hxx>
39*b1cdbd2cSJim Jagielski #include <rtl/byteseq.hxx>
40*b1cdbd2cSJim Jagielski #include <rtl/ustrbuf.hxx>
41*b1cdbd2cSJim Jagielski 
42*b1cdbd2cSJim Jagielski using namespace ::rtl;
43*b1cdbd2cSJim Jagielski using namespace ::std;
44*b1cdbd2cSJim Jagielski using namespace ::osl;
45*b1cdbd2cSJim Jagielski using namespace ::cppu;
46*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::uno;
47*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::lang;
48*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::registry;
49*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::xml::sax;
50*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::util;
51*b1cdbd2cSJim Jagielski using namespace ::com::sun::star::io;
52*b1cdbd2cSJim Jagielski 
53*b1cdbd2cSJim Jagielski #include "factory.hxx"
54*b1cdbd2cSJim Jagielski #include "xml2utf.hxx"
55*b1cdbd2cSJim Jagielski 
56*b1cdbd2cSJim Jagielski #define LINEFEED 10
57*b1cdbd2cSJim Jagielski #define SEQUENCESIZE 1024
58*b1cdbd2cSJim Jagielski #define MAXCOLUMNCOUNT 72
59*b1cdbd2cSJim Jagielski 
60*b1cdbd2cSJim Jagielski /******
61*b1cdbd2cSJim Jagielski *
62*b1cdbd2cSJim Jagielski *
63*b1cdbd2cSJim Jagielski * Character conversion functions
64*b1cdbd2cSJim Jagielski *
65*b1cdbd2cSJim Jagielski *
66*b1cdbd2cSJim Jagielski *****/
67*b1cdbd2cSJim Jagielski 
68*b1cdbd2cSJim Jagielski namespace sax_expatwrap {
69*b1cdbd2cSJim Jagielski /*****
70*b1cdbd2cSJim Jagielski *
71*b1cdbd2cSJim Jagielski * Calculates the length of the sequence after conversion, but the conversion is not done.
72*b1cdbd2cSJim Jagielski * .g. &<>"' plus some more are
73*b1cdbd2cSJim Jagielski * special characters in XML that need to be transformed
74*b1cdbd2cSJim Jagielski *
75*b1cdbd2cSJim Jagielski * @param bConvertAll For Attributes it is necessary to convert every symbol (including line feed and tab)
76*b1cdbd2cSJim Jagielski *                    Set this to true, if you want to perform this special conversion
77*b1cdbd2cSJim Jagielski * @return The returned value is equal to the length of the incoming sequence, when no
78*b1cdbd2cSJim Jagielski +         conversion is necessary, otherwise it is larger than the length of the sequence.
79*b1cdbd2cSJim Jagielski ****/
80*b1cdbd2cSJim Jagielski //  inline sal_Int32 CalcXMLLen( const Sequence<sal_Int8> & seq , sal_Bool bConvertAll ) throw()
81*b1cdbd2cSJim Jagielski //  {
82*b1cdbd2cSJim Jagielski //  	sal_Int32 nLen = 0;
83*b1cdbd2cSJim Jagielski //  	const sal_Int8 *pArray = seq.getConstArray();
84*b1cdbd2cSJim Jagielski 
85*b1cdbd2cSJim Jagielski //  	for( int i = 0 ; i < seq.getLength() ; i ++ ) {
86*b1cdbd2cSJim Jagielski 
87*b1cdbd2cSJim Jagielski //  		sal_Int8 c = pArray[i];
88*b1cdbd2cSJim Jagielski //  		switch( c )
89*b1cdbd2cSJim Jagielski //  		{
90*b1cdbd2cSJim Jagielski //  		case '&':       // resemble to &amp;
91*b1cdbd2cSJim Jagielski //  			nLen +=5;
92*b1cdbd2cSJim Jagielski //  			break;
93*b1cdbd2cSJim Jagielski //  		case '<':       // &lt;
94*b1cdbd2cSJim Jagielski //  		case '>':       // &gt;
95*b1cdbd2cSJim Jagielski //  			nLen +=4;
96*b1cdbd2cSJim Jagielski //  			break;
97*b1cdbd2cSJim Jagielski //  		case 39:        // 39 == ''', &apos;
98*b1cdbd2cSJim Jagielski //  		case '"':       // &quot;
99*b1cdbd2cSJim Jagielski //  		case 13:        // &#x0d;
100*b1cdbd2cSJim Jagielski //  			nLen += 6;
101*b1cdbd2cSJim Jagielski //  			break;
102*b1cdbd2cSJim Jagielski 
103*b1cdbd2cSJim Jagielski //  		case 10:        // &#x0a;
104*b1cdbd2cSJim Jagielski //  		case 9:         // &#x09;
105*b1cdbd2cSJim Jagielski //  			if( bConvertAll )
106*b1cdbd2cSJim Jagielski //  			{
107*b1cdbd2cSJim Jagielski //  				nLen += 6;		  //
108*b1cdbd2cSJim Jagielski //  			}
109*b1cdbd2cSJim Jagielski //  			break;
110*b1cdbd2cSJim Jagielski //  		default:
111*b1cdbd2cSJim Jagielski //  			nLen ++;
112*b1cdbd2cSJim Jagielski //  		}
113*b1cdbd2cSJim Jagielski //  	}
114*b1cdbd2cSJim Jagielski 
115*b1cdbd2cSJim Jagielski //  	return nLen;
116*b1cdbd2cSJim Jagielski //  }
117*b1cdbd2cSJim Jagielski 
118*b1cdbd2cSJim Jagielski enum SaxInvalidCharacterError
119*b1cdbd2cSJim Jagielski {
120*b1cdbd2cSJim Jagielski 	SAX_NONE,
121*b1cdbd2cSJim Jagielski 	SAX_WARNING,
122*b1cdbd2cSJim Jagielski 	SAX_ERROR
123*b1cdbd2cSJim Jagielski };
124*b1cdbd2cSJim Jagielski 
125*b1cdbd2cSJim Jagielski class SaxWriterHelper
126*b1cdbd2cSJim Jagielski {
127*b1cdbd2cSJim Jagielski 	Reference< XOutputStream >	m_out;
128*b1cdbd2cSJim Jagielski 	Sequence < sal_Int8 >		m_Sequence;
129*b1cdbd2cSJim Jagielski 	sal_Int8*					mp_Sequence;
130*b1cdbd2cSJim Jagielski 
131*b1cdbd2cSJim Jagielski 	sal_Int32					nLastLineFeedPos; // is negative after writing a sequence
132*b1cdbd2cSJim Jagielski 	sal_uInt32					nCurrentPos;
133*b1cdbd2cSJim Jagielski 	sal_Bool					m_bStartElementFinished;
134*b1cdbd2cSJim Jagielski 
135*b1cdbd2cSJim Jagielski 
136*b1cdbd2cSJim Jagielski 	inline sal_uInt32 writeSequence() throw( SAXException );
137*b1cdbd2cSJim Jagielski 
138*b1cdbd2cSJim Jagielski 	// use only if to insert the bytes more space in the sequence is needed and
139*b1cdbd2cSJim Jagielski 	// so the sequence has to write out and reset rPos to 0
140*b1cdbd2cSJim Jagielski 	// writes sequence only on overflow, sequence could be full on the end (rPos == SEQUENCESIZE)
141*b1cdbd2cSJim Jagielski 	inline void AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
142*b1cdbd2cSJim Jagielski 				const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException );
143*b1cdbd2cSJim Jagielski 	inline sal_Bool convertToXML(const sal_Unicode * pStr,
144*b1cdbd2cSJim Jagielski 						sal_Int32 nStrLen,
145*b1cdbd2cSJim Jagielski 						sal_Bool bDoNormalization,
146*b1cdbd2cSJim Jagielski 						sal_Bool bNormalizeWhitespace,
147*b1cdbd2cSJim Jagielski 						sal_Int8 *pTarget,
148*b1cdbd2cSJim Jagielski 						sal_uInt32& rPos) throw( SAXException );
149*b1cdbd2cSJim Jagielski 	inline void FinishStartElement() throw( SAXException );
150*b1cdbd2cSJim Jagielski public:
SaxWriterHelper(Reference<XOutputStream> m_TempOut)151*b1cdbd2cSJim Jagielski 	SaxWriterHelper(Reference< XOutputStream > m_TempOut) :
152*b1cdbd2cSJim Jagielski 		m_out(m_TempOut),
153*b1cdbd2cSJim Jagielski 		m_Sequence(SEQUENCESIZE),
154*b1cdbd2cSJim Jagielski 		mp_Sequence(NULL),
155*b1cdbd2cSJim Jagielski 		nLastLineFeedPos(0),
156*b1cdbd2cSJim Jagielski 		nCurrentPos(0),
157*b1cdbd2cSJim Jagielski 		m_bStartElementFinished(sal_True)
158*b1cdbd2cSJim Jagielski 	{
159*b1cdbd2cSJim Jagielski 		OSL_ENSURE(SEQUENCESIZE > 50, "Sequence cache size to small");
160*b1cdbd2cSJim Jagielski 		mp_Sequence = m_Sequence.getArray();
161*b1cdbd2cSJim Jagielski 	}
~SaxWriterHelper()162*b1cdbd2cSJim Jagielski 	~SaxWriterHelper()
163*b1cdbd2cSJim Jagielski 	{
164*b1cdbd2cSJim Jagielski 		OSL_ENSURE(!nCurrentPos, "cached Sequence not written");
165*b1cdbd2cSJim Jagielski 		OSL_ENSURE(m_bStartElementFinished, "StartElement not complettly written");
166*b1cdbd2cSJim Jagielski 	}
167*b1cdbd2cSJim Jagielski 
168*b1cdbd2cSJim Jagielski 	inline void insertIndentation(sal_uInt32 m_nLevel)  throw( SAXException );
169*b1cdbd2cSJim Jagielski 
170*b1cdbd2cSJim Jagielski // returns whether it works correct or invalid characters were in the string
171*b1cdbd2cSJim Jagielski // If there are invalid characters in the string it returns sal_False.
172*b1cdbd2cSJim Jagielski // Than the calling method has to throw the needed Exception.
173*b1cdbd2cSJim Jagielski 	inline sal_Bool writeString(const rtl::OUString& rWriteOutString,
174*b1cdbd2cSJim Jagielski 						sal_Bool bDoNormalization,
175*b1cdbd2cSJim Jagielski 						sal_Bool bNormalizeWhitespace) throw( SAXException );
176*b1cdbd2cSJim Jagielski 
GetLastColumnCount()177*b1cdbd2cSJim Jagielski 	sal_uInt32 GetLastColumnCount() { return (sal_uInt32)(nCurrentPos - nLastLineFeedPos); }
178*b1cdbd2cSJim Jagielski 
179*b1cdbd2cSJim Jagielski 	inline void startDocument() throw( SAXException );
180*b1cdbd2cSJim Jagielski 
181*b1cdbd2cSJim Jagielski // returns whether it works correct or invalid characters were in the strings
182*b1cdbd2cSJim Jagielski // If there are invalid characters in one of the strings it returns sal_False.
183*b1cdbd2cSJim Jagielski // Than the calling method has to throw the needed Exception.
184*b1cdbd2cSJim Jagielski 	inline SaxInvalidCharacterError startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException );
185*b1cdbd2cSJim Jagielski 	inline sal_Bool FinishEmptyElement() throw( SAXException );
186*b1cdbd2cSJim Jagielski 
187*b1cdbd2cSJim Jagielski // returns whether it works correct or invalid characters were in the string
188*b1cdbd2cSJim Jagielski // If there are invalid characters in the string it returns sal_False.
189*b1cdbd2cSJim Jagielski // Than the calling method has to throw the needed Exception.
190*b1cdbd2cSJim Jagielski 	inline sal_Bool endElement(const rtl::OUString& rName) throw( SAXException );
191*b1cdbd2cSJim Jagielski 	inline void endDocument() throw( SAXException );
192*b1cdbd2cSJim Jagielski 
193*b1cdbd2cSJim Jagielski // returns whether it works correct or invalid characters were in the strings
194*b1cdbd2cSJim Jagielski // If there are invalid characters in the string it returns sal_False.
195*b1cdbd2cSJim Jagielski // Than the calling method has to throw the needed Exception.
196*b1cdbd2cSJim Jagielski 	inline sal_Bool processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException );
197*b1cdbd2cSJim Jagielski 	inline void startCDATA() throw( SAXException );
198*b1cdbd2cSJim Jagielski 	inline void endCDATA() throw( SAXException );
199*b1cdbd2cSJim Jagielski 
200*b1cdbd2cSJim Jagielski // returns whether it works correct or invalid characters were in the strings
201*b1cdbd2cSJim Jagielski // If there are invalid characters in the string it returns sal_False.
202*b1cdbd2cSJim Jagielski // Than the calling method has to throw the needed Exception.
203*b1cdbd2cSJim Jagielski 	inline sal_Bool comment(const rtl::OUString& rComment) throw( SAXException );
204*b1cdbd2cSJim Jagielski 
205*b1cdbd2cSJim Jagielski 	inline void clearBuffer() throw( SAXException );
206*b1cdbd2cSJim Jagielski };
207*b1cdbd2cSJim Jagielski 
208*b1cdbd2cSJim Jagielski const sal_Bool g_bValidCharsBelow32[32] =
209*b1cdbd2cSJim Jagielski {
210*b1cdbd2cSJim Jagielski //  0 1 2 3 4 5 6 7
211*b1cdbd2cSJim Jagielski 	0,0,0,0,0,0,0,0,  //0
212*b1cdbd2cSJim Jagielski 	0,1,1,0,0,1,0,0,  //8
213*b1cdbd2cSJim Jagielski 	0,0,0,0,0,0,0,0,  //16
214*b1cdbd2cSJim Jagielski 	0,0,0,0,0,0,0,0
215*b1cdbd2cSJim Jagielski };
216*b1cdbd2cSJim Jagielski 
IsInvalidChar(const sal_Unicode aChar)217*b1cdbd2cSJim Jagielski inline sal_Bool IsInvalidChar(const sal_Unicode aChar)
218*b1cdbd2cSJim Jagielski {
219*b1cdbd2cSJim Jagielski 	sal_Bool bRet(sal_False);
220*b1cdbd2cSJim Jagielski 	// check first for the most common characters
221*b1cdbd2cSJim Jagielski 	if( aChar < 32 || aChar >= 0xd800 )
222*b1cdbd2cSJim Jagielski 		bRet = ( (aChar < 32 && ! g_bValidCharsBelow32[aChar]) ||
223*b1cdbd2cSJim Jagielski 			aChar == 0xffff ||
224*b1cdbd2cSJim Jagielski 			aChar == 0xfffe );
225*b1cdbd2cSJim Jagielski 	return bRet;
226*b1cdbd2cSJim Jagielski }
227*b1cdbd2cSJim Jagielski 
228*b1cdbd2cSJim Jagielski /********
229*b1cdbd2cSJim Jagielski * write through to the output stream
230*b1cdbd2cSJim Jagielski *
231*b1cdbd2cSJim Jagielski *****/
writeSequence()232*b1cdbd2cSJim Jagielski inline sal_uInt32 SaxWriterHelper::writeSequence() throw( SAXException )
233*b1cdbd2cSJim Jagielski {
234*b1cdbd2cSJim Jagielski 	try
235*b1cdbd2cSJim Jagielski 	{
236*b1cdbd2cSJim Jagielski 		m_out->writeBytes( m_Sequence );
237*b1cdbd2cSJim Jagielski 	}
238*b1cdbd2cSJim Jagielski 	catch( IOException & e )
239*b1cdbd2cSJim Jagielski 	{
240*b1cdbd2cSJim Jagielski 		Any a;
241*b1cdbd2cSJim Jagielski 		a <<= e;
242*b1cdbd2cSJim Jagielski 		throw SAXException(
243*b1cdbd2cSJim Jagielski 			OUString::createFromAscii( "io exception during writing" ),
244*b1cdbd2cSJim Jagielski 			Reference< XInterface > (),
245*b1cdbd2cSJim Jagielski 			a );
246*b1cdbd2cSJim Jagielski 	}
247*b1cdbd2cSJim Jagielski 	nLastLineFeedPos -= SEQUENCESIZE;
248*b1cdbd2cSJim Jagielski 	return 0;
249*b1cdbd2cSJim Jagielski }
250*b1cdbd2cSJim Jagielski 
AddBytes(sal_Int8 * pTarget,sal_uInt32 & rPos,const sal_Int8 * pBytes,sal_uInt32 nBytesCount)251*b1cdbd2cSJim Jagielski inline void SaxWriterHelper::AddBytes(sal_Int8* pTarget, sal_uInt32& rPos,
252*b1cdbd2cSJim Jagielski 				const sal_Int8* pBytes, sal_uInt32 nBytesCount) throw( SAXException )
253*b1cdbd2cSJim Jagielski {
254*b1cdbd2cSJim Jagielski 	OSL_ENSURE((rPos + nBytesCount) > SEQUENCESIZE, "wrong use of AddBytesMethod");
255*b1cdbd2cSJim Jagielski 	sal_uInt32 nCount(SEQUENCESIZE - rPos);
256*b1cdbd2cSJim Jagielski 	memcpy( &(pTarget[rPos]) , pBytes,  nCount);
257*b1cdbd2cSJim Jagielski 
258*b1cdbd2cSJim Jagielski 	OSL_ENSURE(rPos + nCount == SEQUENCESIZE, "the position should be the at the end");
259*b1cdbd2cSJim Jagielski 
260*b1cdbd2cSJim Jagielski 	rPos = writeSequence();
261*b1cdbd2cSJim Jagielski 	sal_uInt32 nRestCount(nBytesCount - nCount);
262*b1cdbd2cSJim Jagielski 	if ((rPos + nRestCount) <= SEQUENCESIZE)
263*b1cdbd2cSJim Jagielski 	{
264*b1cdbd2cSJim Jagielski 		memcpy( &(pTarget[rPos]), &pBytes[nCount], nRestCount);
265*b1cdbd2cSJim Jagielski 		rPos += nRestCount;
266*b1cdbd2cSJim Jagielski 	}
267*b1cdbd2cSJim Jagielski 	else
268*b1cdbd2cSJim Jagielski 		AddBytes(pTarget, rPos, &pBytes[nCount], nRestCount);
269*b1cdbd2cSJim Jagielski }
270*b1cdbd2cSJim Jagielski 
271*b1cdbd2cSJim Jagielski /** Converts an UTF16 string to UTF8 and does XML normalization
272*b1cdbd2cSJim Jagielski 
273*b1cdbd2cSJim Jagielski 	@param pTarget
274*b1cdbd2cSJim Jagielski 	       Pointer to a piece of memory, to where the output should be written. The caller
275*b1cdbd2cSJim Jagielski 		   must call calcXMLByteLength on the same string, to ensure,
276*b1cdbd2cSJim Jagielski 		   that there is enough memory for converting.
277*b1cdbd2cSJim Jagielski  */
convertToXML(const sal_Unicode * pStr,sal_Int32 nStrLen,sal_Bool bDoNormalization,sal_Bool bNormalizeWhitespace,sal_Int8 * pTarget,sal_uInt32 & rPos)278*b1cdbd2cSJim Jagielski inline sal_Bool SaxWriterHelper::convertToXML( const sal_Unicode * pStr,
279*b1cdbd2cSJim Jagielski 						sal_Int32 nStrLen,
280*b1cdbd2cSJim Jagielski 						sal_Bool bDoNormalization,
281*b1cdbd2cSJim Jagielski 						sal_Bool bNormalizeWhitespace,
282*b1cdbd2cSJim Jagielski 						sal_Int8 *pTarget,
283*b1cdbd2cSJim Jagielski 						sal_uInt32& rPos ) throw( SAXException )
284*b1cdbd2cSJim Jagielski {
285*b1cdbd2cSJim Jagielski 	sal_Bool bRet(sal_True);
286*b1cdbd2cSJim Jagielski     sal_uInt32 nSurrogate = 0;
287*b1cdbd2cSJim Jagielski 
288*b1cdbd2cSJim Jagielski 	for( sal_Int32 i = 0 ; i < nStrLen ; i ++ )
289*b1cdbd2cSJim Jagielski 	{
290*b1cdbd2cSJim Jagielski 	    sal_uInt16 c = pStr[i];
291*b1cdbd2cSJim Jagielski 	    if (IsInvalidChar(c))
292*b1cdbd2cSJim Jagielski 	    	bRet = sal_False;
293*b1cdbd2cSJim Jagielski 	    else if( (c >= 0x0001) && (c <= 0x007F) )
294*b1cdbd2cSJim Jagielski 		{
295*b1cdbd2cSJim Jagielski 			if( bDoNormalization )
296*b1cdbd2cSJim Jagielski 			{
297*b1cdbd2cSJim Jagielski 				switch( c )
298*b1cdbd2cSJim Jagielski 				{
299*b1cdbd2cSJim Jagielski 					case '&':  // resemble to &amp;
300*b1cdbd2cSJim Jagielski 					{
301*b1cdbd2cSJim Jagielski 						if ((rPos + 5) > SEQUENCESIZE)
302*b1cdbd2cSJim Jagielski 							AddBytes(pTarget, rPos, (sal_Int8*)"&amp;", 5);
303*b1cdbd2cSJim Jagielski 						else
304*b1cdbd2cSJim Jagielski 						{
305*b1cdbd2cSJim Jagielski 							memcpy( &(pTarget[rPos]) , "&amp;", 5 );
306*b1cdbd2cSJim Jagielski 							rPos += 5;
307*b1cdbd2cSJim Jagielski 						}
308*b1cdbd2cSJim Jagielski 					}
309*b1cdbd2cSJim Jagielski 					break;
310*b1cdbd2cSJim Jagielski 					case '<':
311*b1cdbd2cSJim Jagielski 					{
312*b1cdbd2cSJim Jagielski 						if ((rPos + 4) > SEQUENCESIZE)
313*b1cdbd2cSJim Jagielski 							AddBytes(pTarget, rPos, (sal_Int8*)"&lt;", 4);
314*b1cdbd2cSJim Jagielski 						else
315*b1cdbd2cSJim Jagielski 						{
316*b1cdbd2cSJim Jagielski 							memcpy( &(pTarget[rPos]) , "&lt;" , 4 );
317*b1cdbd2cSJim Jagielski 							rPos += 4;        // &lt;
318*b1cdbd2cSJim Jagielski 						}
319*b1cdbd2cSJim Jagielski 					}
320*b1cdbd2cSJim Jagielski 					break;
321*b1cdbd2cSJim Jagielski 					case '>':
322*b1cdbd2cSJim Jagielski 					{
323*b1cdbd2cSJim Jagielski 						if ((rPos + 4) > SEQUENCESIZE)
324*b1cdbd2cSJim Jagielski 							AddBytes(pTarget, rPos, (sal_Int8*)"&gt;", 4);
325*b1cdbd2cSJim Jagielski 						else
326*b1cdbd2cSJim Jagielski 						{
327*b1cdbd2cSJim Jagielski 							memcpy( &(pTarget[rPos]) , "&gt;" , 4 );
328*b1cdbd2cSJim Jagielski 							rPos += 4;        // &gt;
329*b1cdbd2cSJim Jagielski 						}
330*b1cdbd2cSJim Jagielski 					}
331*b1cdbd2cSJim Jagielski 					break;
332*b1cdbd2cSJim Jagielski 					case 39:                 // 39 == '''
333*b1cdbd2cSJim Jagielski 					{
334*b1cdbd2cSJim Jagielski 						if ((rPos + 6) > SEQUENCESIZE)
335*b1cdbd2cSJim Jagielski 							AddBytes(pTarget, rPos, (sal_Int8*)"&apos;", 6);
336*b1cdbd2cSJim Jagielski 						else
337*b1cdbd2cSJim Jagielski 						{
338*b1cdbd2cSJim Jagielski 							memcpy( &(pTarget[rPos]) , "&apos;" , 6 );
339*b1cdbd2cSJim Jagielski 							rPos += 6;        // &apos;
340*b1cdbd2cSJim Jagielski 						}
341*b1cdbd2cSJim Jagielski 					}
342*b1cdbd2cSJim Jagielski 					break;
343*b1cdbd2cSJim Jagielski 					case '"':
344*b1cdbd2cSJim Jagielski 					{
345*b1cdbd2cSJim Jagielski 						if ((rPos + 6) > SEQUENCESIZE)
346*b1cdbd2cSJim Jagielski 							AddBytes(pTarget, rPos, (sal_Int8*)"&quot;", 6);
347*b1cdbd2cSJim Jagielski 						else
348*b1cdbd2cSJim Jagielski 						{
349*b1cdbd2cSJim Jagielski 							memcpy( &(pTarget[rPos]) , "&quot;" , 6 );
350*b1cdbd2cSJim Jagielski 							rPos += 6;		  // &quot;
351*b1cdbd2cSJim Jagielski 						}
352*b1cdbd2cSJim Jagielski 					}
353*b1cdbd2cSJim Jagielski 					break;
354*b1cdbd2cSJim Jagielski 					case 13:
355*b1cdbd2cSJim Jagielski 					{
356*b1cdbd2cSJim Jagielski 						if ((rPos + 6) > SEQUENCESIZE)
357*b1cdbd2cSJim Jagielski 							AddBytes(pTarget, rPos, (sal_Int8*)"&#x0d;", 6);
358*b1cdbd2cSJim Jagielski 						else
359*b1cdbd2cSJim Jagielski 						{
360*b1cdbd2cSJim Jagielski 							memcpy( &(pTarget[rPos]) , "&#x0d;" , 6 );
361*b1cdbd2cSJim Jagielski 							rPos += 6;
362*b1cdbd2cSJim Jagielski 						}
363*b1cdbd2cSJim Jagielski 					}
364*b1cdbd2cSJim Jagielski 					break;
365*b1cdbd2cSJim Jagielski 					case LINEFEED:
366*b1cdbd2cSJim Jagielski 					{
367*b1cdbd2cSJim Jagielski 						if( bNormalizeWhitespace )
368*b1cdbd2cSJim Jagielski 						{
369*b1cdbd2cSJim Jagielski 							if ((rPos + 6) > SEQUENCESIZE)
370*b1cdbd2cSJim Jagielski 								AddBytes(pTarget, rPos, (sal_Int8*)"&#x0a;" , 6);
371*b1cdbd2cSJim Jagielski 							else
372*b1cdbd2cSJim Jagielski 							{
373*b1cdbd2cSJim Jagielski 								memcpy( &(pTarget[rPos]) , "&#x0a;" , 6 );
374*b1cdbd2cSJim Jagielski 								rPos += 6;
375*b1cdbd2cSJim Jagielski 							}
376*b1cdbd2cSJim Jagielski 						}
377*b1cdbd2cSJim Jagielski 						else
378*b1cdbd2cSJim Jagielski 						{
379*b1cdbd2cSJim Jagielski 							pTarget[rPos] = LINEFEED;
380*b1cdbd2cSJim Jagielski 							nLastLineFeedPos = rPos;
381*b1cdbd2cSJim Jagielski 							rPos ++;
382*b1cdbd2cSJim Jagielski 						}
383*b1cdbd2cSJim Jagielski 					}
384*b1cdbd2cSJim Jagielski 					break;
385*b1cdbd2cSJim Jagielski 					case 9:
386*b1cdbd2cSJim Jagielski 					{
387*b1cdbd2cSJim Jagielski 						if( bNormalizeWhitespace )
388*b1cdbd2cSJim Jagielski 						{
389*b1cdbd2cSJim Jagielski 							if ((rPos + 6) > SEQUENCESIZE)
390*b1cdbd2cSJim Jagielski 								AddBytes(pTarget, rPos, (sal_Int8*)"&#x09;" , 6);
391*b1cdbd2cSJim Jagielski 							else
392*b1cdbd2cSJim Jagielski 							{
393*b1cdbd2cSJim Jagielski 								memcpy( &(pTarget[rPos]) , "&#x09;" , 6 );
394*b1cdbd2cSJim Jagielski 								rPos += 6;
395*b1cdbd2cSJim Jagielski 							}
396*b1cdbd2cSJim Jagielski 						}
397*b1cdbd2cSJim Jagielski 						else
398*b1cdbd2cSJim Jagielski 						{
399*b1cdbd2cSJim Jagielski 							pTarget[rPos] = 9;
400*b1cdbd2cSJim Jagielski 							rPos ++;
401*b1cdbd2cSJim Jagielski 						}
402*b1cdbd2cSJim Jagielski 					}
403*b1cdbd2cSJim Jagielski 					break;
404*b1cdbd2cSJim Jagielski 					default:
405*b1cdbd2cSJim Jagielski 					{
406*b1cdbd2cSJim Jagielski 						pTarget[rPos] = (sal_Int8)c;
407*b1cdbd2cSJim Jagielski 						rPos ++;
408*b1cdbd2cSJim Jagielski 					}
409*b1cdbd2cSJim Jagielski 					break;
410*b1cdbd2cSJim Jagielski 				}
411*b1cdbd2cSJim Jagielski 			}
412*b1cdbd2cSJim Jagielski 			else
413*b1cdbd2cSJim Jagielski 			{
414*b1cdbd2cSJim Jagielski 				pTarget[rPos] = (sal_Int8)c;
415*b1cdbd2cSJim Jagielski 				if ((sal_Int8)c == LINEFEED)
416*b1cdbd2cSJim Jagielski 					nLastLineFeedPos = rPos;
417*b1cdbd2cSJim Jagielski 				rPos ++;
418*b1cdbd2cSJim Jagielski 			}
419*b1cdbd2cSJim Jagielski 	    }
420*b1cdbd2cSJim Jagielski         else if( c >= 0xd800 && c < 0xdc00  )
421*b1cdbd2cSJim Jagielski         {
422*b1cdbd2cSJim Jagielski             // 1. surrogate: save (until 2. surrogate)
423*b1cdbd2cSJim Jagielski             OSL_ENSURE( nSurrogate == 0, "left-over Unicode surrogate" );
424*b1cdbd2cSJim Jagielski             nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
425*b1cdbd2cSJim Jagielski         }
426*b1cdbd2cSJim Jagielski         else if( c >= 0xdc00 && c < 0xe000 )
427*b1cdbd2cSJim Jagielski         {
428*b1cdbd2cSJim Jagielski             // 2. surrogate: write as UTF-8
429*b1cdbd2cSJim Jagielski             OSL_ENSURE( nSurrogate != 0, "lone 2nd Unicode surrogate" );
430*b1cdbd2cSJim Jagielski 
431*b1cdbd2cSJim Jagielski             nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
432*b1cdbd2cSJim Jagielski             if( nSurrogate >= 0x00010000  &&  nSurrogate <= 0x0010FFFF )
433*b1cdbd2cSJim Jagielski             {
434*b1cdbd2cSJim Jagielski     			sal_Int8 aBytes[] = { sal_Int8(0xF0 | ((nSurrogate >> 18) & 0x0F)),
435*b1cdbd2cSJim Jagielski 	    							  sal_Int8(0x80 | ((nSurrogate >> 12) & 0x3F)),
436*b1cdbd2cSJim Jagielski 		    						  sal_Int8(0x80 | ((nSurrogate >>  6) & 0x3F)),
437*b1cdbd2cSJim Jagielski 			    					  sal_Int8(0x80 | ((nSurrogate >>  0) & 0x3F)) };
438*b1cdbd2cSJim Jagielski     			if ((rPos + 4) > SEQUENCESIZE)
439*b1cdbd2cSJim Jagielski 	    			AddBytes(pTarget, rPos, aBytes, 4);
440*b1cdbd2cSJim Jagielski 		    	else
441*b1cdbd2cSJim Jagielski 			    {
442*b1cdbd2cSJim Jagielski 				    pTarget[rPos] = aBytes[0];
443*b1cdbd2cSJim Jagielski     				rPos ++;
444*b1cdbd2cSJim Jagielski 	    			pTarget[rPos] = aBytes[1];
445*b1cdbd2cSJim Jagielski 		    		rPos ++;
446*b1cdbd2cSJim Jagielski 			    	pTarget[rPos] = aBytes[2];
447*b1cdbd2cSJim Jagielski 				    rPos ++;
448*b1cdbd2cSJim Jagielski     				pTarget[rPos] = aBytes[3];
449*b1cdbd2cSJim Jagielski 	    			rPos ++;
450*b1cdbd2cSJim Jagielski 		    	}
451*b1cdbd2cSJim Jagielski             }
452*b1cdbd2cSJim Jagielski             else
453*b1cdbd2cSJim Jagielski             {
454*b1cdbd2cSJim Jagielski                 OSL_ENSURE( false, "illegal Unicode character" );
455*b1cdbd2cSJim Jagielski                 bRet = sal_False;
456*b1cdbd2cSJim Jagielski             }
457*b1cdbd2cSJim Jagielski 
458*b1cdbd2cSJim Jagielski             // reset surrogate
459*b1cdbd2cSJim Jagielski             nSurrogate = 0;
460*b1cdbd2cSJim Jagielski         }
461*b1cdbd2cSJim Jagielski 		else if( c > 0x07FF )
462*b1cdbd2cSJim Jagielski 		{
463*b1cdbd2cSJim Jagielski 			sal_Int8 aBytes[] = { sal_Int8(0xE0 | ((c >> 12) & 0x0F)),
464*b1cdbd2cSJim Jagielski 								  sal_Int8(0x80 | ((c >>  6) & 0x3F)),
465*b1cdbd2cSJim Jagielski 								  sal_Int8(0x80 | ((c >>  0) & 0x3F)) };
466*b1cdbd2cSJim Jagielski 			if ((rPos + 3) > SEQUENCESIZE)
467*b1cdbd2cSJim Jagielski 				AddBytes(pTarget, rPos, aBytes, 3);
468*b1cdbd2cSJim Jagielski 			else
469*b1cdbd2cSJim Jagielski 			{
470*b1cdbd2cSJim Jagielski 				pTarget[rPos] = aBytes[0];
471*b1cdbd2cSJim Jagielski 				rPos ++;
472*b1cdbd2cSJim Jagielski 				pTarget[rPos] = aBytes[1];
473*b1cdbd2cSJim Jagielski 				rPos ++;
474*b1cdbd2cSJim Jagielski 				pTarget[rPos] = aBytes[2];
475*b1cdbd2cSJim Jagielski 				rPos ++;
476*b1cdbd2cSJim Jagielski 			}
477*b1cdbd2cSJim Jagielski 	    }
478*b1cdbd2cSJim Jagielski 		else
479*b1cdbd2cSJim Jagielski 		{
480*b1cdbd2cSJim Jagielski 			sal_Int8 aBytes[] = { sal_Int8(0xC0 | ((c >>  6) & 0x1F)),
481*b1cdbd2cSJim Jagielski 								sal_Int8(0x80 | ((c >>  0) & 0x3F)) };
482*b1cdbd2cSJim Jagielski 			if ((rPos + 2) > SEQUENCESIZE)
483*b1cdbd2cSJim Jagielski 				AddBytes(pTarget, rPos, aBytes, 2);
484*b1cdbd2cSJim Jagielski 			else
485*b1cdbd2cSJim Jagielski 			{
486*b1cdbd2cSJim Jagielski 				pTarget[rPos] = aBytes[0];
487*b1cdbd2cSJim Jagielski 				rPos ++;
488*b1cdbd2cSJim Jagielski 				pTarget[rPos] = aBytes[1];
489*b1cdbd2cSJim Jagielski 				rPos ++;
490*b1cdbd2cSJim Jagielski 			}
491*b1cdbd2cSJim Jagielski 		}
492*b1cdbd2cSJim Jagielski 		OSL_ENSURE(rPos <= SEQUENCESIZE, "not reset current position");
493*b1cdbd2cSJim Jagielski 		if (rPos == SEQUENCESIZE)
494*b1cdbd2cSJim Jagielski 			rPos = writeSequence();
495*b1cdbd2cSJim Jagielski 
496*b1cdbd2cSJim Jagielski         // reset left-over surrogate
497*b1cdbd2cSJim Jagielski         if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
498*b1cdbd2cSJim Jagielski         {
499*b1cdbd2cSJim Jagielski             OSL_ENSURE( nSurrogate != 0, "left-over Unicode surrogate" );
500*b1cdbd2cSJim Jagielski             nSurrogate = 0;
501*b1cdbd2cSJim Jagielski             bRet = sal_False;
502*b1cdbd2cSJim Jagielski         }
503*b1cdbd2cSJim Jagielski     }
504*b1cdbd2cSJim Jagielski 	return bRet;
505*b1cdbd2cSJim Jagielski }
506*b1cdbd2cSJim Jagielski 
FinishStartElement()507*b1cdbd2cSJim Jagielski inline void SaxWriterHelper::FinishStartElement() throw( SAXException )
508*b1cdbd2cSJim Jagielski {
509*b1cdbd2cSJim Jagielski 	if (!m_bStartElementFinished)
510*b1cdbd2cSJim Jagielski 	{
511*b1cdbd2cSJim Jagielski 		mp_Sequence[nCurrentPos] = '>';
512*b1cdbd2cSJim Jagielski 		nCurrentPos++;
513*b1cdbd2cSJim Jagielski 		if (nCurrentPos == SEQUENCESIZE)
514*b1cdbd2cSJim Jagielski 			nCurrentPos = writeSequence();
515*b1cdbd2cSJim Jagielski 		m_bStartElementFinished = sal_True;
516*b1cdbd2cSJim Jagielski 	}
517*b1cdbd2cSJim Jagielski }
518*b1cdbd2cSJim Jagielski 
insertIndentation(sal_uInt32 m_nLevel)519*b1cdbd2cSJim Jagielski inline void SaxWriterHelper::insertIndentation(sal_uInt32 m_nLevel) throw( SAXException )
520*b1cdbd2cSJim Jagielski {
521*b1cdbd2cSJim Jagielski 	FinishStartElement();
522*b1cdbd2cSJim Jagielski 	if (m_nLevel > 0)
523*b1cdbd2cSJim Jagielski 	{
524*b1cdbd2cSJim Jagielski 		if ((nCurrentPos + m_nLevel + 1) <= SEQUENCESIZE)
525*b1cdbd2cSJim Jagielski 		{
526*b1cdbd2cSJim Jagielski 			mp_Sequence[nCurrentPos] = LINEFEED;
527*b1cdbd2cSJim Jagielski 			nLastLineFeedPos = nCurrentPos;
528*b1cdbd2cSJim Jagielski 			nCurrentPos++;
529*b1cdbd2cSJim Jagielski 			memset( &(mp_Sequence[nCurrentPos]) , 32 , m_nLevel );
530*b1cdbd2cSJim Jagielski 			nCurrentPos += m_nLevel;
531*b1cdbd2cSJim Jagielski 			if (nCurrentPos == SEQUENCESIZE)
532*b1cdbd2cSJim Jagielski 				nCurrentPos = writeSequence();
533*b1cdbd2cSJim Jagielski 		}
534*b1cdbd2cSJim Jagielski 		else
535*b1cdbd2cSJim Jagielski 		{
536*b1cdbd2cSJim Jagielski 			sal_uInt32 nCount(m_nLevel + 1);
537*b1cdbd2cSJim Jagielski 			sal_Int8* pBytes = new sal_Int8[nCount];
538*b1cdbd2cSJim Jagielski 			pBytes[0] = LINEFEED;
539*b1cdbd2cSJim Jagielski 			memset( &(pBytes[1]), 32, m_nLevel );
540*b1cdbd2cSJim Jagielski 			AddBytes(mp_Sequence, nCurrentPos, pBytes, nCount);
541*b1cdbd2cSJim Jagielski 			delete[] pBytes;
542*b1cdbd2cSJim Jagielski 			nLastLineFeedPos = nCurrentPos - nCount;
543*b1cdbd2cSJim Jagielski 			if (nCurrentPos == SEQUENCESIZE)
544*b1cdbd2cSJim Jagielski 				nCurrentPos = writeSequence();
545*b1cdbd2cSJim Jagielski 		}
546*b1cdbd2cSJim Jagielski 	}
547*b1cdbd2cSJim Jagielski 	else
548*b1cdbd2cSJim Jagielski 	{
549*b1cdbd2cSJim Jagielski 		mp_Sequence[nCurrentPos] = LINEFEED;
550*b1cdbd2cSJim Jagielski 		nLastLineFeedPos = nCurrentPos;
551*b1cdbd2cSJim Jagielski 		nCurrentPos++;
552*b1cdbd2cSJim Jagielski 		if (nCurrentPos == SEQUENCESIZE)
553*b1cdbd2cSJim Jagielski 			nCurrentPos = writeSequence();
554*b1cdbd2cSJim Jagielski 	}
555*b1cdbd2cSJim Jagielski }
556*b1cdbd2cSJim Jagielski 
writeString(const rtl::OUString & rWriteOutString,sal_Bool bDoNormalization,sal_Bool bNormalizeWhitespace)557*b1cdbd2cSJim Jagielski inline sal_Bool SaxWriterHelper::writeString( const rtl::OUString& rWriteOutString,
558*b1cdbd2cSJim Jagielski 						sal_Bool bDoNormalization,
559*b1cdbd2cSJim Jagielski 						sal_Bool bNormalizeWhitespace ) throw( SAXException )
560*b1cdbd2cSJim Jagielski {
561*b1cdbd2cSJim Jagielski 	FinishStartElement();
562*b1cdbd2cSJim Jagielski 	return convertToXML(rWriteOutString.getStr(),
563*b1cdbd2cSJim Jagielski 					rWriteOutString.getLength(),
564*b1cdbd2cSJim Jagielski 					bDoNormalization,
565*b1cdbd2cSJim Jagielski 					bNormalizeWhitespace,
566*b1cdbd2cSJim Jagielski 					mp_Sequence,
567*b1cdbd2cSJim Jagielski 					nCurrentPos);
568*b1cdbd2cSJim Jagielski }
569*b1cdbd2cSJim Jagielski 
startDocument()570*b1cdbd2cSJim Jagielski inline void SaxWriterHelper::startDocument() throw( SAXException )
571*b1cdbd2cSJim Jagielski {
572*b1cdbd2cSJim Jagielski 	const char pc[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
573*b1cdbd2cSJim Jagielski 	const int nLen = strlen( pc );
574*b1cdbd2cSJim Jagielski 	if ((nCurrentPos + nLen) <= SEQUENCESIZE)
575*b1cdbd2cSJim Jagielski 	{
576*b1cdbd2cSJim Jagielski 		memcpy( mp_Sequence, pc , nLen );
577*b1cdbd2cSJim Jagielski 		nCurrentPos += nLen;
578*b1cdbd2cSJim Jagielski 	}
579*b1cdbd2cSJim Jagielski 	else
580*b1cdbd2cSJim Jagielski 	{
581*b1cdbd2cSJim Jagielski 		AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)pc, nLen);
582*b1cdbd2cSJim Jagielski 	}
583*b1cdbd2cSJim Jagielski 	OSL_ENSURE(nCurrentPos <= SEQUENCESIZE, "not reset current position");
584*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
585*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
586*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = LINEFEED;
587*b1cdbd2cSJim Jagielski 	nCurrentPos++;
588*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
589*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
590*b1cdbd2cSJim Jagielski }
591*b1cdbd2cSJim Jagielski 
startElement(const rtl::OUString & rName,const Reference<XAttributeList> & xAttribs)592*b1cdbd2cSJim Jagielski inline SaxInvalidCharacterError SaxWriterHelper::startElement(const rtl::OUString& rName, const Reference< XAttributeList >& xAttribs) throw( SAXException )
593*b1cdbd2cSJim Jagielski {
594*b1cdbd2cSJim Jagielski 	FinishStartElement();
595*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '<';
596*b1cdbd2cSJim Jagielski 	nCurrentPos++;
597*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
598*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
599*b1cdbd2cSJim Jagielski 
600*b1cdbd2cSJim Jagielski 	SaxInvalidCharacterError eRet(SAX_NONE);
601*b1cdbd2cSJim Jagielski 	if (!writeString(rName, sal_False, sal_False))
602*b1cdbd2cSJim Jagielski 		eRet = SAX_ERROR;
603*b1cdbd2cSJim Jagielski 
604*b1cdbd2cSJim Jagielski 	sal_Int16 nAttribCount = xAttribs.is() ? static_cast<sal_Int16>(xAttribs->getLength()) : 0;
605*b1cdbd2cSJim Jagielski 	for(sal_Int16 i = 0 ; i < nAttribCount ; i++ )
606*b1cdbd2cSJim Jagielski 	{
607*b1cdbd2cSJim Jagielski 		mp_Sequence[nCurrentPos] = ' ';
608*b1cdbd2cSJim Jagielski 		nCurrentPos++;
609*b1cdbd2cSJim Jagielski 		if (nCurrentPos == SEQUENCESIZE)
610*b1cdbd2cSJim Jagielski 			nCurrentPos = writeSequence();
611*b1cdbd2cSJim Jagielski 
612*b1cdbd2cSJim Jagielski 		if (!writeString(xAttribs->getNameByIndex( i ), sal_False, sal_False))
613*b1cdbd2cSJim Jagielski 			eRet = SAX_ERROR;
614*b1cdbd2cSJim Jagielski 
615*b1cdbd2cSJim Jagielski 		mp_Sequence[nCurrentPos] = '=';
616*b1cdbd2cSJim Jagielski 		nCurrentPos++;
617*b1cdbd2cSJim Jagielski 		if (nCurrentPos == SEQUENCESIZE)
618*b1cdbd2cSJim Jagielski 			nCurrentPos = writeSequence();
619*b1cdbd2cSJim Jagielski 		mp_Sequence[nCurrentPos] = '"';
620*b1cdbd2cSJim Jagielski 		nCurrentPos++;
621*b1cdbd2cSJim Jagielski 		if (nCurrentPos == SEQUENCESIZE)
622*b1cdbd2cSJim Jagielski 			nCurrentPos = writeSequence();
623*b1cdbd2cSJim Jagielski 
624*b1cdbd2cSJim Jagielski 		if (!writeString(xAttribs->getValueByIndex( i ), sal_True, sal_True) &&
625*b1cdbd2cSJim Jagielski 			!(eRet == SAX_ERROR))
626*b1cdbd2cSJim Jagielski 			eRet = SAX_WARNING;
627*b1cdbd2cSJim Jagielski 
628*b1cdbd2cSJim Jagielski 		mp_Sequence[nCurrentPos] = '"';
629*b1cdbd2cSJim Jagielski 		nCurrentPos++;
630*b1cdbd2cSJim Jagielski 		if (nCurrentPos == SEQUENCESIZE)
631*b1cdbd2cSJim Jagielski 			nCurrentPos = writeSequence();
632*b1cdbd2cSJim Jagielski 	}
633*b1cdbd2cSJim Jagielski 
634*b1cdbd2cSJim Jagielski 	m_bStartElementFinished = sal_False;	// because the '>' character is not added,
635*b1cdbd2cSJim Jagielski 											// because it is possible, that the "/>"
636*b1cdbd2cSJim Jagielski 											// characters have to add
637*b1cdbd2cSJim Jagielski 	return eRet;
638*b1cdbd2cSJim Jagielski }
639*b1cdbd2cSJim Jagielski 
FinishEmptyElement()640*b1cdbd2cSJim Jagielski inline sal_Bool SaxWriterHelper::FinishEmptyElement() throw( SAXException )
641*b1cdbd2cSJim Jagielski {
642*b1cdbd2cSJim Jagielski 	if (m_bStartElementFinished)
643*b1cdbd2cSJim Jagielski 		return sal_False;
644*b1cdbd2cSJim Jagielski 
645*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '/';
646*b1cdbd2cSJim Jagielski 	nCurrentPos++;
647*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
648*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
649*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '>';
650*b1cdbd2cSJim Jagielski 	nCurrentPos++;
651*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
652*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
653*b1cdbd2cSJim Jagielski 
654*b1cdbd2cSJim Jagielski 	m_bStartElementFinished = sal_True;
655*b1cdbd2cSJim Jagielski 
656*b1cdbd2cSJim Jagielski 	return sal_True;
657*b1cdbd2cSJim Jagielski }
658*b1cdbd2cSJim Jagielski 
endElement(const rtl::OUString & rName)659*b1cdbd2cSJim Jagielski inline sal_Bool SaxWriterHelper::endElement(const rtl::OUString& rName) throw( SAXException )
660*b1cdbd2cSJim Jagielski {
661*b1cdbd2cSJim Jagielski 	FinishStartElement();
662*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '<';
663*b1cdbd2cSJim Jagielski 	nCurrentPos++;
664*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
665*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
666*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '/';
667*b1cdbd2cSJim Jagielski 	nCurrentPos++;
668*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
669*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
670*b1cdbd2cSJim Jagielski 
671*b1cdbd2cSJim Jagielski 	sal_Bool bRet(writeString( rName, sal_False, sal_False));
672*b1cdbd2cSJim Jagielski 
673*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '>';
674*b1cdbd2cSJim Jagielski 	nCurrentPos++;
675*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
676*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
677*b1cdbd2cSJim Jagielski 
678*b1cdbd2cSJim Jagielski 	return bRet;
679*b1cdbd2cSJim Jagielski }
680*b1cdbd2cSJim Jagielski 
endDocument()681*b1cdbd2cSJim Jagielski inline void SaxWriterHelper::endDocument() throw( SAXException )
682*b1cdbd2cSJim Jagielski {
683*b1cdbd2cSJim Jagielski 	if (nCurrentPos > 0)
684*b1cdbd2cSJim Jagielski 	{
685*b1cdbd2cSJim Jagielski 		m_Sequence.realloc(nCurrentPos);
686*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
687*b1cdbd2cSJim Jagielski 		//m_Sequence.realloc(SEQUENCESIZE);
688*b1cdbd2cSJim Jagielski 	}
689*b1cdbd2cSJim Jagielski }
690*b1cdbd2cSJim Jagielski 
clearBuffer()691*b1cdbd2cSJim Jagielski inline void SaxWriterHelper::clearBuffer() throw( SAXException )
692*b1cdbd2cSJim Jagielski {
693*b1cdbd2cSJim Jagielski     FinishStartElement();
694*b1cdbd2cSJim Jagielski     if (nCurrentPos > 0)
695*b1cdbd2cSJim Jagielski     {
696*b1cdbd2cSJim Jagielski         m_Sequence.realloc(nCurrentPos);
697*b1cdbd2cSJim Jagielski         nCurrentPos = writeSequence();
698*b1cdbd2cSJim Jagielski         m_Sequence.realloc(SEQUENCESIZE);
699*b1cdbd2cSJim Jagielski         // Be sure to update the array pointer after the reallocation.
700*b1cdbd2cSJim Jagielski         mp_Sequence = m_Sequence.getArray();
701*b1cdbd2cSJim Jagielski     }
702*b1cdbd2cSJim Jagielski }
703*b1cdbd2cSJim Jagielski 
processingInstruction(const rtl::OUString & rTarget,const rtl::OUString & rData)704*b1cdbd2cSJim Jagielski inline sal_Bool SaxWriterHelper::processingInstruction(const rtl::OUString& rTarget, const rtl::OUString& rData) throw( SAXException )
705*b1cdbd2cSJim Jagielski {
706*b1cdbd2cSJim Jagielski 	FinishStartElement();
707*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '<';
708*b1cdbd2cSJim Jagielski 	nCurrentPos++;
709*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
710*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
711*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '?';
712*b1cdbd2cSJim Jagielski 	nCurrentPos++;
713*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
714*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
715*b1cdbd2cSJim Jagielski 
716*b1cdbd2cSJim Jagielski 	sal_Bool bRet(writeString( rTarget, sal_False, sal_False ));
717*b1cdbd2cSJim Jagielski 
718*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = ' ';
719*b1cdbd2cSJim Jagielski 	nCurrentPos++;
720*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
721*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
722*b1cdbd2cSJim Jagielski 
723*b1cdbd2cSJim Jagielski 	if (!writeString( rData, sal_False, sal_False ))
724*b1cdbd2cSJim Jagielski 		bRet = sal_False;
725*b1cdbd2cSJim Jagielski 
726*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '?';
727*b1cdbd2cSJim Jagielski 	nCurrentPos++;
728*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
729*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
730*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '>';
731*b1cdbd2cSJim Jagielski 	nCurrentPos++;
732*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
733*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
734*b1cdbd2cSJim Jagielski 
735*b1cdbd2cSJim Jagielski 	return bRet;
736*b1cdbd2cSJim Jagielski }
737*b1cdbd2cSJim Jagielski 
startCDATA()738*b1cdbd2cSJim Jagielski inline void SaxWriterHelper::startCDATA() throw( SAXException )
739*b1cdbd2cSJim Jagielski {
740*b1cdbd2cSJim Jagielski 	FinishStartElement();
741*b1cdbd2cSJim Jagielski 	if ((nCurrentPos + 9) <= SEQUENCESIZE)
742*b1cdbd2cSJim Jagielski 	{
743*b1cdbd2cSJim Jagielski 		memcpy( &(mp_Sequence[nCurrentPos]), "<![CDATA[" , 9 );
744*b1cdbd2cSJim Jagielski 		nCurrentPos += 9;
745*b1cdbd2cSJim Jagielski 	}
746*b1cdbd2cSJim Jagielski 	else
747*b1cdbd2cSJim Jagielski 		AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"<![CDATA[" , 9);
748*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
749*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
750*b1cdbd2cSJim Jagielski }
751*b1cdbd2cSJim Jagielski 
endCDATA()752*b1cdbd2cSJim Jagielski inline void SaxWriterHelper::endCDATA() throw( SAXException )
753*b1cdbd2cSJim Jagielski {
754*b1cdbd2cSJim Jagielski 	FinishStartElement();
755*b1cdbd2cSJim Jagielski 	if ((nCurrentPos + 3) <= SEQUENCESIZE)
756*b1cdbd2cSJim Jagielski 	{
757*b1cdbd2cSJim Jagielski 		memcpy( &(mp_Sequence[nCurrentPos]), "]]>" , 3 );
758*b1cdbd2cSJim Jagielski 		nCurrentPos += 3;
759*b1cdbd2cSJim Jagielski 	}
760*b1cdbd2cSJim Jagielski 	else
761*b1cdbd2cSJim Jagielski 		AddBytes(mp_Sequence, nCurrentPos, (sal_Int8*)"]]>" , 3);
762*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
763*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
764*b1cdbd2cSJim Jagielski }
765*b1cdbd2cSJim Jagielski 
comment(const rtl::OUString & rComment)766*b1cdbd2cSJim Jagielski inline sal_Bool SaxWriterHelper::comment(const rtl::OUString& rComment) throw( SAXException )
767*b1cdbd2cSJim Jagielski {
768*b1cdbd2cSJim Jagielski 	FinishStartElement();
769*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '<';
770*b1cdbd2cSJim Jagielski 	nCurrentPos++;
771*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
772*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
773*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '!';
774*b1cdbd2cSJim Jagielski 	nCurrentPos++;
775*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
776*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
777*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '-';
778*b1cdbd2cSJim Jagielski 	nCurrentPos++;
779*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
780*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
781*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '-';
782*b1cdbd2cSJim Jagielski 	nCurrentPos++;
783*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
784*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
785*b1cdbd2cSJim Jagielski 
786*b1cdbd2cSJim Jagielski 	sal_Bool bRet(writeString( rComment, sal_False, sal_False));
787*b1cdbd2cSJim Jagielski 
788*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '-';
789*b1cdbd2cSJim Jagielski 	nCurrentPos++;
790*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
791*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
792*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '-';
793*b1cdbd2cSJim Jagielski 	nCurrentPos++;
794*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
795*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
796*b1cdbd2cSJim Jagielski 	mp_Sequence[nCurrentPos] = '>';
797*b1cdbd2cSJim Jagielski 	nCurrentPos++;
798*b1cdbd2cSJim Jagielski 	if (nCurrentPos == SEQUENCESIZE)
799*b1cdbd2cSJim Jagielski 		nCurrentPos = writeSequence();
800*b1cdbd2cSJim Jagielski 
801*b1cdbd2cSJim Jagielski 	return bRet;
802*b1cdbd2cSJim Jagielski }
803*b1cdbd2cSJim Jagielski 
calcXMLByteLength(const sal_Unicode * pStr,sal_Int32 nStrLen,sal_Bool bDoNormalization,sal_Bool bNormalizeWhitespace)804*b1cdbd2cSJim Jagielski inline sal_Int32 calcXMLByteLength( const sal_Unicode *pStr, sal_Int32 nStrLen,
805*b1cdbd2cSJim Jagielski 									sal_Bool bDoNormalization,
806*b1cdbd2cSJim Jagielski 									sal_Bool bNormalizeWhitespace )
807*b1cdbd2cSJim Jagielski {
808*b1cdbd2cSJim Jagielski 	sal_Int32 nOutputLength = 0;
809*b1cdbd2cSJim Jagielski     sal_uInt32 nSurrogate = 0;
810*b1cdbd2cSJim Jagielski 
811*b1cdbd2cSJim Jagielski 	for( sal_Int32 i = 0 ; i < nStrLen ; i++ )
812*b1cdbd2cSJim Jagielski 	{
813*b1cdbd2cSJim Jagielski 	    sal_uInt16 c = pStr[i];
814*b1cdbd2cSJim Jagielski 	    if( !IsInvalidChar(c) && (c >= 0x0001) && (c <= 0x007F) )
815*b1cdbd2cSJim Jagielski 		{
816*b1cdbd2cSJim Jagielski 			if( bDoNormalization )
817*b1cdbd2cSJim Jagielski 			{
818*b1cdbd2cSJim Jagielski 				switch( c )
819*b1cdbd2cSJim Jagielski 				{
820*b1cdbd2cSJim Jagielski 				case '&':       // resemble to &amp;
821*b1cdbd2cSJim Jagielski 					nOutputLength +=5;
822*b1cdbd2cSJim Jagielski 					break;
823*b1cdbd2cSJim Jagielski 				case '<':       // &lt;
824*b1cdbd2cSJim Jagielski 				case '>':       // &gt;
825*b1cdbd2cSJim Jagielski 					nOutputLength +=4;
826*b1cdbd2cSJim Jagielski 					break;
827*b1cdbd2cSJim Jagielski 				case 39:        // 39 == ''', &apos;
828*b1cdbd2cSJim Jagielski 				case '"':       // &quot;
829*b1cdbd2cSJim Jagielski 				case 13:        // &#x0d;
830*b1cdbd2cSJim Jagielski 					nOutputLength += 6;
831*b1cdbd2cSJim Jagielski 					break;
832*b1cdbd2cSJim Jagielski 
833*b1cdbd2cSJim Jagielski 				case 10:        // &#x0a;
834*b1cdbd2cSJim Jagielski 				case 9:         // &#x09;
835*b1cdbd2cSJim Jagielski 					if( bNormalizeWhitespace )
836*b1cdbd2cSJim Jagielski 					{
837*b1cdbd2cSJim Jagielski 						nOutputLength += 6;		  //
838*b1cdbd2cSJim Jagielski 					}
839*b1cdbd2cSJim Jagielski 					else
840*b1cdbd2cSJim Jagielski 					{
841*b1cdbd2cSJim Jagielski 						nOutputLength ++;
842*b1cdbd2cSJim Jagielski 					}
843*b1cdbd2cSJim Jagielski 					break;
844*b1cdbd2cSJim Jagielski 				default:
845*b1cdbd2cSJim Jagielski 					nOutputLength ++;
846*b1cdbd2cSJim Jagielski 				}
847*b1cdbd2cSJim Jagielski 			}
848*b1cdbd2cSJim Jagielski 			else
849*b1cdbd2cSJim Jagielski 			{
850*b1cdbd2cSJim Jagielski 				nOutputLength ++;
851*b1cdbd2cSJim Jagielski 			}
852*b1cdbd2cSJim Jagielski 	    }
853*b1cdbd2cSJim Jagielski         else if( c >= 0xd800 && c < 0xdc00  )
854*b1cdbd2cSJim Jagielski         {
855*b1cdbd2cSJim Jagielski             // save surrogate
856*b1cdbd2cSJim Jagielski             nSurrogate = ( ( c & 0x03ff ) + 0x0040 );
857*b1cdbd2cSJim Jagielski         }
858*b1cdbd2cSJim Jagielski         else if( c >= 0xdc00 && c < 0xe000 )
859*b1cdbd2cSJim Jagielski         {
860*b1cdbd2cSJim Jagielski             // 2. surrogate: write as UTF-8 (if range is OK
861*b1cdbd2cSJim Jagielski             nSurrogate = ( nSurrogate << 10 ) | ( c & 0x03ff );
862*b1cdbd2cSJim Jagielski             if( nSurrogate >= 0x00010000  &&  nSurrogate <= 0x0010FFFF )
863*b1cdbd2cSJim Jagielski                 nOutputLength += 4;
864*b1cdbd2cSJim Jagielski             nSurrogate = 0;
865*b1cdbd2cSJim Jagielski         }
866*b1cdbd2cSJim Jagielski 		else if( c > 0x07FF )
867*b1cdbd2cSJim Jagielski 		{
868*b1cdbd2cSJim Jagielski 			nOutputLength += 3;
869*b1cdbd2cSJim Jagielski 	    }
870*b1cdbd2cSJim Jagielski 		else
871*b1cdbd2cSJim Jagielski 		{
872*b1cdbd2cSJim Jagielski 			nOutputLength += 2;
873*b1cdbd2cSJim Jagielski 	    }
874*b1cdbd2cSJim Jagielski 
875*b1cdbd2cSJim Jagielski         // surrogate processing
876*b1cdbd2cSJim Jagielski         if( ( nSurrogate != 0 ) && !( c >= 0xd800 && c < 0xdc00 ) )
877*b1cdbd2cSJim Jagielski             nSurrogate = 0;
878*b1cdbd2cSJim Jagielski     }
879*b1cdbd2cSJim Jagielski 
880*b1cdbd2cSJim Jagielski 	return nOutputLength;
881*b1cdbd2cSJim Jagielski }
882*b1cdbd2cSJim Jagielski 
883*b1cdbd2cSJim Jagielski /** returns position of first ascii 10 within the string, -1 when no 10 in string.
884*b1cdbd2cSJim Jagielski  */
getFirstLineBreak(const OUString & str)885*b1cdbd2cSJim Jagielski static inline sal_Int32 getFirstLineBreak( const OUString & str ) throw ()
886*b1cdbd2cSJim Jagielski {
887*b1cdbd2cSJim Jagielski 	const sal_Unicode *pSource = str.getStr();
888*b1cdbd2cSJim Jagielski 	sal_Int32 nLen  = str.getLength();
889*b1cdbd2cSJim Jagielski 
890*b1cdbd2cSJim Jagielski 	for( int n = 0; n < nLen ; n ++ )
891*b1cdbd2cSJim Jagielski 	{
892*b1cdbd2cSJim Jagielski 		if( LINEFEED == pSource[n] ) {
893*b1cdbd2cSJim Jagielski 			return n;
894*b1cdbd2cSJim Jagielski 		}
895*b1cdbd2cSJim Jagielski 	}
896*b1cdbd2cSJim Jagielski 	return -1;
897*b1cdbd2cSJim Jagielski }
898*b1cdbd2cSJim Jagielski 
899*b1cdbd2cSJim Jagielski /** returns position of last ascii 10 within sequence, -1 when no 10 in string.
900*b1cdbd2cSJim Jagielski  */
getLastLineBreak(const Sequence<sal_Int8> & seq)901*b1cdbd2cSJim Jagielski static inline sal_Int32 getLastLineBreak( const Sequence<sal_Int8>  & seq) throw ()
902*b1cdbd2cSJim Jagielski {
903*b1cdbd2cSJim Jagielski 	const sal_Int8 *pSource = seq.getConstArray();
904*b1cdbd2cSJim Jagielski 	sal_Int32 nLen  = seq.getLength();
905*b1cdbd2cSJim Jagielski 
906*b1cdbd2cSJim Jagielski 	for( int n = nLen-1; n >= 0 ; n -- )
907*b1cdbd2cSJim Jagielski 	{
908*b1cdbd2cSJim Jagielski 		if( LINEFEED == pSource[n] ) {
909*b1cdbd2cSJim Jagielski 			return n;
910*b1cdbd2cSJim Jagielski 		}
911*b1cdbd2cSJim Jagielski 	}
912*b1cdbd2cSJim Jagielski 	return -1;
913*b1cdbd2cSJim Jagielski }
914*b1cdbd2cSJim Jagielski 
915*b1cdbd2cSJim Jagielski 
916*b1cdbd2cSJim Jagielski class SAXWriter :
917*b1cdbd2cSJim Jagielski 	public WeakImplHelper3<
918*b1cdbd2cSJim Jagielski             XActiveDataSource,
919*b1cdbd2cSJim Jagielski             XExtendedDocumentHandler,
920*b1cdbd2cSJim Jagielski   	        XServiceInfo >
921*b1cdbd2cSJim Jagielski {
922*b1cdbd2cSJim Jagielski public:
SAXWriter()923*b1cdbd2cSJim Jagielski 	SAXWriter( ) :
924*b1cdbd2cSJim Jagielski 		m_seqStartElement(),
925*b1cdbd2cSJim Jagielski 		mp_SaxWriterHelper( NULL ),
926*b1cdbd2cSJim Jagielski 		m_bForceLineBreak(sal_False),
927*b1cdbd2cSJim Jagielski 		m_bAllowLineBreak(sal_False)
928*b1cdbd2cSJim Jagielski 		{}
~SAXWriter()929*b1cdbd2cSJim Jagielski 	~SAXWriter()
930*b1cdbd2cSJim Jagielski 	{
931*b1cdbd2cSJim Jagielski 		delete mp_SaxWriterHelper;
932*b1cdbd2cSJim Jagielski 	}
933*b1cdbd2cSJim Jagielski 
934*b1cdbd2cSJim Jagielski public: // XActiveDataSource
setOutputStream(const Reference<XOutputStream> & aStream)935*b1cdbd2cSJim Jagielski     virtual void SAL_CALL setOutputStream(const Reference< XOutputStream > & aStream)
936*b1cdbd2cSJim Jagielski 		throw (RuntimeException)
937*b1cdbd2cSJim Jagielski     		{
938*b1cdbd2cSJim Jagielski                 // temporary: set same stream again to clear buffer
939*b1cdbd2cSJim Jagielski                 if ( m_out == aStream && mp_SaxWriterHelper && m_bDocStarted )
940*b1cdbd2cSJim Jagielski                     mp_SaxWriterHelper->clearBuffer();
941*b1cdbd2cSJim Jagielski                 else
942*b1cdbd2cSJim Jagielski                 {
943*b1cdbd2cSJim Jagielski 
944*b1cdbd2cSJim Jagielski 				m_out = aStream;
945*b1cdbd2cSJim Jagielski 				delete mp_SaxWriterHelper;
946*b1cdbd2cSJim Jagielski 				mp_SaxWriterHelper = new SaxWriterHelper(m_out);
947*b1cdbd2cSJim Jagielski 				m_bDocStarted = sal_False;
948*b1cdbd2cSJim Jagielski 				m_nLevel = 0;
949*b1cdbd2cSJim Jagielski 				m_bIsCDATA = sal_False;
950*b1cdbd2cSJim Jagielski 
951*b1cdbd2cSJim Jagielski                 }
952*b1cdbd2cSJim Jagielski 			}
getOutputStream(void)953*b1cdbd2cSJim Jagielski     virtual Reference< XOutputStream >  SAL_CALL getOutputStream(void)
954*b1cdbd2cSJim Jagielski 		throw(RuntimeException)
955*b1cdbd2cSJim Jagielski     		{ return m_out; }
956*b1cdbd2cSJim Jagielski 
957*b1cdbd2cSJim Jagielski public: // XDocumentHandler
958*b1cdbd2cSJim Jagielski     virtual void SAL_CALL startDocument(void)
959*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
960*b1cdbd2cSJim Jagielski 
961*b1cdbd2cSJim Jagielski     virtual void SAL_CALL endDocument(void)
962*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
963*b1cdbd2cSJim Jagielski 
964*b1cdbd2cSJim Jagielski     virtual void SAL_CALL startElement(const OUString& aName,
965*b1cdbd2cSJim Jagielski 									   const Reference< XAttributeList > & xAttribs)
966*b1cdbd2cSJim Jagielski 		throw (SAXException, RuntimeException);
967*b1cdbd2cSJim Jagielski 
968*b1cdbd2cSJim Jagielski     virtual void SAL_CALL endElement(const OUString& aName)
969*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
970*b1cdbd2cSJim Jagielski 
971*b1cdbd2cSJim Jagielski     virtual void SAL_CALL characters(const OUString& aChars)
972*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
973*b1cdbd2cSJim Jagielski 
974*b1cdbd2cSJim Jagielski     virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces)
975*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
976*b1cdbd2cSJim Jagielski     virtual void SAL_CALL processingInstruction(const OUString& aTarget,
977*b1cdbd2cSJim Jagielski 												const OUString& aData)
978*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
979*b1cdbd2cSJim Jagielski     virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator)
980*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
981*b1cdbd2cSJim Jagielski 
982*b1cdbd2cSJim Jagielski public: // XExtendedDocumentHandler
983*b1cdbd2cSJim Jagielski     virtual void SAL_CALL startCDATA(void) throw(SAXException, RuntimeException);
984*b1cdbd2cSJim Jagielski     virtual void SAL_CALL endCDATA(void) throw(RuntimeException);
985*b1cdbd2cSJim Jagielski     virtual void SAL_CALL comment(const OUString& sComment)
986*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
987*b1cdbd2cSJim Jagielski     virtual void SAL_CALL unknown(const OUString& sString)
988*b1cdbd2cSJim Jagielski 		throw(SAXException, RuntimeException);
989*b1cdbd2cSJim Jagielski 	virtual void SAL_CALL allowLineBreak(void)
990*b1cdbd2cSJim Jagielski 		throw(SAXException,RuntimeException);
991*b1cdbd2cSJim Jagielski 
992*b1cdbd2cSJim Jagielski public: // XServiceInfo
993*b1cdbd2cSJim Jagielski     OUString                     SAL_CALL getImplementationName() throw();
994*b1cdbd2cSJim Jagielski     Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw();
995*b1cdbd2cSJim Jagielski     sal_Bool                    SAL_CALL supportsService(const OUString& ServiceName) throw();
996*b1cdbd2cSJim Jagielski 
997*b1cdbd2cSJim Jagielski private:
998*b1cdbd2cSJim Jagielski 
999*b1cdbd2cSJim Jagielski 	void writeSequence( const Sequence<sal_Int8> & seq );
1000*b1cdbd2cSJim Jagielski 	sal_Int32 getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw();
1001*b1cdbd2cSJim Jagielski 
1002*b1cdbd2cSJim Jagielski 	Reference< XOutputStream > 	m_out;
1003*b1cdbd2cSJim Jagielski 	Sequence < sal_Int8 > 		m_seqStartElement;
1004*b1cdbd2cSJim Jagielski 	SaxWriterHelper*			mp_SaxWriterHelper;
1005*b1cdbd2cSJim Jagielski 
1006*b1cdbd2cSJim Jagielski 	// Status information
1007*b1cdbd2cSJim Jagielski 	sal_Bool m_bDocStarted : 1;
1008*b1cdbd2cSJim Jagielski 	sal_Bool m_bIsCDATA : 1;
1009*b1cdbd2cSJim Jagielski 	sal_Bool m_bForceLineBreak : 1;
1010*b1cdbd2cSJim Jagielski 	sal_Bool m_bAllowLineBreak : 1;
1011*b1cdbd2cSJim Jagielski 	sal_Int32 m_nLevel;
1012*b1cdbd2cSJim Jagielski };
1013*b1cdbd2cSJim Jagielski 
1014*b1cdbd2cSJim Jagielski 
1015*b1cdbd2cSJim Jagielski //--------------------------------------
1016*b1cdbd2cSJim Jagielski // the extern interface
1017*b1cdbd2cSJim Jagielski //---------------------------------------
SaxWriter_CreateInstance(const Reference<XMultiServiceFactory> &)1018*b1cdbd2cSJim Jagielski Reference < XInterface > SAL_CALL SaxWriter_CreateInstance(
1019*b1cdbd2cSJim Jagielski 	const Reference < XMultiServiceFactory >  &  )
1020*b1cdbd2cSJim Jagielski 	throw (Exception)
1021*b1cdbd2cSJim Jagielski {
1022*b1cdbd2cSJim Jagielski 	SAXWriter *p = new SAXWriter;
1023*b1cdbd2cSJim Jagielski 	return Reference< XInterface > ( SAL_STATIC_CAST(OWeakObject *, p ) );
1024*b1cdbd2cSJim Jagielski }
1025*b1cdbd2cSJim Jagielski 
SaxWriter_getServiceName()1026*b1cdbd2cSJim Jagielski OUString SaxWriter_getServiceName() throw()
1027*b1cdbd2cSJim Jagielski {
1028*b1cdbd2cSJim Jagielski 	return OUString::createFromAscii( "com.sun.star.xml.sax.Writer" );
1029*b1cdbd2cSJim Jagielski }
1030*b1cdbd2cSJim Jagielski 
SaxWriter_getImplementationName()1031*b1cdbd2cSJim Jagielski OUString SaxWriter_getImplementationName() throw()
1032*b1cdbd2cSJim Jagielski {
1033*b1cdbd2cSJim Jagielski 	return OUString::createFromAscii( "com.sun.star.extensions.xml.sax.Writer" );
1034*b1cdbd2cSJim Jagielski }
1035*b1cdbd2cSJim Jagielski 
SaxWriter_getSupportedServiceNames(void)1036*b1cdbd2cSJim Jagielski Sequence< OUString > 	SaxWriter_getSupportedServiceNames(void) throw()
1037*b1cdbd2cSJim Jagielski {
1038*b1cdbd2cSJim Jagielski 	Sequence<OUString> aRet(1);
1039*b1cdbd2cSJim Jagielski 	aRet.getArray()[0] = SaxWriter_getServiceName();
1040*b1cdbd2cSJim Jagielski 	return aRet;
1041*b1cdbd2cSJim Jagielski }
1042*b1cdbd2cSJim Jagielski 
1043*b1cdbd2cSJim Jagielski 
getIndentPrefixLength(sal_Int32 nFirstLineBreakOccurence)1044*b1cdbd2cSJim Jagielski sal_Int32 SAXWriter::getIndentPrefixLength( sal_Int32 nFirstLineBreakOccurence ) throw()
1045*b1cdbd2cSJim Jagielski {
1046*b1cdbd2cSJim Jagielski 	sal_Int32 nLength =-1;
1047*b1cdbd2cSJim Jagielski 	if (mp_SaxWriterHelper)
1048*b1cdbd2cSJim Jagielski 	{
1049*b1cdbd2cSJim Jagielski 		if ( m_bForceLineBreak ||
1050*b1cdbd2cSJim Jagielski 			(m_bAllowLineBreak &&
1051*b1cdbd2cSJim Jagielski 			((nFirstLineBreakOccurence + mp_SaxWriterHelper->GetLastColumnCount()) > MAXCOLUMNCOUNT)) )
1052*b1cdbd2cSJim Jagielski 			nLength = m_nLevel;
1053*b1cdbd2cSJim Jagielski 	}
1054*b1cdbd2cSJim Jagielski 	m_bForceLineBreak = sal_False;
1055*b1cdbd2cSJim Jagielski 	m_bAllowLineBreak = sal_False;
1056*b1cdbd2cSJim Jagielski 	return nLength;
1057*b1cdbd2cSJim Jagielski }
1058*b1cdbd2cSJim Jagielski 
isFirstCharWhitespace(const sal_Unicode * p)1059*b1cdbd2cSJim Jagielski static inline sal_Bool isFirstCharWhitespace( const sal_Unicode *p ) throw()
1060*b1cdbd2cSJim Jagielski {
1061*b1cdbd2cSJim Jagielski 	return *p == ' ';
1062*b1cdbd2cSJim Jagielski }
1063*b1cdbd2cSJim Jagielski 
1064*b1cdbd2cSJim Jagielski 
1065*b1cdbd2cSJim Jagielski // XServiceInfo
getImplementationName()1066*b1cdbd2cSJim Jagielski OUString SAXWriter::getImplementationName() throw()
1067*b1cdbd2cSJim Jagielski {
1068*b1cdbd2cSJim Jagielski     return SaxWriter_getImplementationName();
1069*b1cdbd2cSJim Jagielski }
1070*b1cdbd2cSJim Jagielski 
1071*b1cdbd2cSJim Jagielski // XServiceInfo
supportsService(const OUString & ServiceName)1072*b1cdbd2cSJim Jagielski sal_Bool SAXWriter::supportsService(const OUString& ServiceName) throw()
1073*b1cdbd2cSJim Jagielski {
1074*b1cdbd2cSJim Jagielski     Sequence< OUString > aSNL = getSupportedServiceNames();
1075*b1cdbd2cSJim Jagielski     const OUString * pArray = aSNL.getConstArray();
1076*b1cdbd2cSJim Jagielski 
1077*b1cdbd2cSJim Jagielski     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
1078*b1cdbd2cSJim Jagielski         if( pArray[i] == ServiceName )
1079*b1cdbd2cSJim Jagielski             return sal_True;
1080*b1cdbd2cSJim Jagielski 
1081*b1cdbd2cSJim Jagielski     return sal_False;
1082*b1cdbd2cSJim Jagielski }
1083*b1cdbd2cSJim Jagielski 
1084*b1cdbd2cSJim Jagielski // XServiceInfo
getSupportedServiceNames(void)1085*b1cdbd2cSJim Jagielski Sequence< OUString > SAXWriter::getSupportedServiceNames(void) throw ()
1086*b1cdbd2cSJim Jagielski {
1087*b1cdbd2cSJim Jagielski     Sequence<OUString> seq(1);
1088*b1cdbd2cSJim Jagielski     seq.getArray()[0] = SaxWriter_getServiceName();
1089*b1cdbd2cSJim Jagielski     return seq;
1090*b1cdbd2cSJim Jagielski }
1091*b1cdbd2cSJim Jagielski 
1092*b1cdbd2cSJim Jagielski 
1093*b1cdbd2cSJim Jagielski 
startDocument()1094*b1cdbd2cSJim Jagielski void SAXWriter::startDocument()						throw(SAXException, RuntimeException )
1095*b1cdbd2cSJim Jagielski {
1096*b1cdbd2cSJim Jagielski 	if( m_bDocStarted || ! m_out.is() || !mp_SaxWriterHelper ) {
1097*b1cdbd2cSJim Jagielski 		throw SAXException();
1098*b1cdbd2cSJim Jagielski 	}
1099*b1cdbd2cSJim Jagielski 	m_bDocStarted = sal_True;
1100*b1cdbd2cSJim Jagielski 	mp_SaxWriterHelper->startDocument();
1101*b1cdbd2cSJim Jagielski }
1102*b1cdbd2cSJim Jagielski 
1103*b1cdbd2cSJim Jagielski 
endDocument(void)1104*b1cdbd2cSJim Jagielski void SAXWriter::endDocument(void) 					throw(SAXException, RuntimeException)
1105*b1cdbd2cSJim Jagielski {
1106*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted )
1107*b1cdbd2cSJim Jagielski 	{
1108*b1cdbd2cSJim Jagielski 		throw SAXException(
1109*b1cdbd2cSJim Jagielski 			OUString::createFromAscii( "endDocument called before startDocument" ),
1110*b1cdbd2cSJim Jagielski 			Reference< XInterface >() , Any() );
1111*b1cdbd2cSJim Jagielski 	}
1112*b1cdbd2cSJim Jagielski 	if( m_nLevel ) {
1113*b1cdbd2cSJim Jagielski 		throw SAXException(
1114*b1cdbd2cSJim Jagielski 			OUString::createFromAscii( "unexpected end of document" ),
1115*b1cdbd2cSJim Jagielski 			Reference< XInterface >() , Any() );
1116*b1cdbd2cSJim Jagielski 	}
1117*b1cdbd2cSJim Jagielski 	mp_SaxWriterHelper->endDocument();
1118*b1cdbd2cSJim Jagielski 	try
1119*b1cdbd2cSJim Jagielski 	{
1120*b1cdbd2cSJim Jagielski 		m_out->closeOutput();
1121*b1cdbd2cSJim Jagielski 	}
1122*b1cdbd2cSJim Jagielski 	catch( IOException & e )
1123*b1cdbd2cSJim Jagielski 	{
1124*b1cdbd2cSJim Jagielski 		Any a;
1125*b1cdbd2cSJim Jagielski 		a <<= e;
1126*b1cdbd2cSJim Jagielski 		throw SAXException(
1127*b1cdbd2cSJim Jagielski 			OUString::createFromAscii( "IO exception during closing the IO Stream" ),
1128*b1cdbd2cSJim Jagielski 			Reference< XInterface > (),
1129*b1cdbd2cSJim Jagielski 			a );
1130*b1cdbd2cSJim Jagielski 	}
1131*b1cdbd2cSJim Jagielski }
1132*b1cdbd2cSJim Jagielski 
1133*b1cdbd2cSJim Jagielski 
startElement(const OUString & aName,const Reference<XAttributeList> & xAttribs)1134*b1cdbd2cSJim Jagielski void SAXWriter::startElement(const OUString& aName, const Reference< XAttributeList >& xAttribs)
1135*b1cdbd2cSJim Jagielski 	throw(SAXException, RuntimeException)
1136*b1cdbd2cSJim Jagielski {
1137*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted )
1138*b1cdbd2cSJim Jagielski 	{
1139*b1cdbd2cSJim Jagielski 		SAXException except;
1140*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement called before startDocument" ));
1141*b1cdbd2cSJim Jagielski 		throw except;
1142*b1cdbd2cSJim Jagielski 	}
1143*b1cdbd2cSJim Jagielski 	if( m_bIsCDATA )
1144*b1cdbd2cSJim Jagielski 	{
1145*b1cdbd2cSJim Jagielski 		SAXException except;
1146*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "startElement call not allowed with CDATA sections" ));
1147*b1cdbd2cSJim Jagielski 		throw except;
1148*b1cdbd2cSJim Jagielski 	}
1149*b1cdbd2cSJim Jagielski 
1150*b1cdbd2cSJim Jagielski 	sal_Int32 nLength(0);
1151*b1cdbd2cSJim Jagielski 	if (m_bAllowLineBreak)
1152*b1cdbd2cSJim Jagielski 	{
1153*b1cdbd2cSJim Jagielski 		sal_Int32 nAttribCount = xAttribs.is() ? xAttribs->getLength() : 0;
1154*b1cdbd2cSJim Jagielski 
1155*b1cdbd2cSJim Jagielski 		nLength ++; // "<"
1156*b1cdbd2cSJim Jagielski 		nLength += calcXMLByteLength( aName.getStr() , aName.getLength(),
1157*b1cdbd2cSJim Jagielski 								  sal_False, sal_False ); // the tag name
1158*b1cdbd2cSJim Jagielski 
1159*b1cdbd2cSJim Jagielski 		sal_Int16 n;
1160*b1cdbd2cSJim Jagielski 		for( n = 0 ; n < static_cast<sal_Int16>(nAttribCount) ; n ++ ) {
1161*b1cdbd2cSJim Jagielski 			nLength ++; // " "
1162*b1cdbd2cSJim Jagielski 			OUString tmp =  xAttribs->getNameByIndex( n );
1163*b1cdbd2cSJim Jagielski 
1164*b1cdbd2cSJim Jagielski 			nLength += calcXMLByteLength( tmp.getStr() , tmp.getLength() , sal_False, sal_False );
1165*b1cdbd2cSJim Jagielski 
1166*b1cdbd2cSJim Jagielski 			nLength += 2; // ="
1167*b1cdbd2cSJim Jagielski 
1168*b1cdbd2cSJim Jagielski 			tmp = xAttribs->getValueByIndex( n );
1169*b1cdbd2cSJim Jagielski 
1170*b1cdbd2cSJim Jagielski 			nLength += calcXMLByteLength( tmp.getStr(), tmp.getLength(), sal_True, sal_True );
1171*b1cdbd2cSJim Jagielski 
1172*b1cdbd2cSJim Jagielski 			nLength += 1; // "
1173*b1cdbd2cSJim Jagielski 		}
1174*b1cdbd2cSJim Jagielski 
1175*b1cdbd2cSJim Jagielski 		nLength ++;  // '>'
1176*b1cdbd2cSJim Jagielski 	}
1177*b1cdbd2cSJim Jagielski 
1178*b1cdbd2cSJim Jagielski 	// Is there a new indentation necesarry ?
1179*b1cdbd2cSJim Jagielski 	sal_Int32 nPrefix(getIndentPrefixLength( nLength ));
1180*b1cdbd2cSJim Jagielski 
1181*b1cdbd2cSJim Jagielski 	// write into sequence
1182*b1cdbd2cSJim Jagielski 	if( nPrefix >= 0 )
1183*b1cdbd2cSJim Jagielski 		mp_SaxWriterHelper->insertIndentation( nPrefix );
1184*b1cdbd2cSJim Jagielski 
1185*b1cdbd2cSJim Jagielski 	SaxInvalidCharacterError eRet(mp_SaxWriterHelper->startElement(aName, xAttribs));
1186*b1cdbd2cSJim Jagielski 
1187*b1cdbd2cSJim Jagielski 	m_nLevel++;
1188*b1cdbd2cSJim Jagielski 
1189*b1cdbd2cSJim Jagielski 	if (eRet == SAX_WARNING)
1190*b1cdbd2cSJim Jagielski 	{
1191*b1cdbd2cSJim Jagielski 		SAXInvalidCharacterException except;
1192*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export in a attribute value" ) );
1193*b1cdbd2cSJim Jagielski 		throw except;
1194*b1cdbd2cSJim Jagielski 	}
1195*b1cdbd2cSJim Jagielski 	else if (eRet == SAX_ERROR)
1196*b1cdbd2cSJim Jagielski 	{
1197*b1cdbd2cSJim Jagielski 		SAXException except;
1198*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1199*b1cdbd2cSJim Jagielski 		throw except;
1200*b1cdbd2cSJim Jagielski 	}
1201*b1cdbd2cSJim Jagielski }
1202*b1cdbd2cSJim Jagielski 
endElement(const OUString & aName)1203*b1cdbd2cSJim Jagielski void SAXWriter::endElement(const OUString& aName) 	throw (SAXException, RuntimeException)
1204*b1cdbd2cSJim Jagielski {
1205*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted ) {
1206*b1cdbd2cSJim Jagielski 		throw SAXException ();
1207*b1cdbd2cSJim Jagielski 	}
1208*b1cdbd2cSJim Jagielski 	m_nLevel --;
1209*b1cdbd2cSJim Jagielski 
1210*b1cdbd2cSJim Jagielski 	if( m_nLevel < 0 ) {
1211*b1cdbd2cSJim Jagielski 		throw SAXException();
1212*b1cdbd2cSJim Jagielski 	}
1213*b1cdbd2cSJim Jagielski 	sal_Bool bRet(sal_True);
1214*b1cdbd2cSJim Jagielski 
1215*b1cdbd2cSJim Jagielski 	if( mp_SaxWriterHelper->FinishEmptyElement() )
1216*b1cdbd2cSJim Jagielski         m_bForceLineBreak = sal_False;
1217*b1cdbd2cSJim Jagielski 	else
1218*b1cdbd2cSJim Jagielski 	{
1219*b1cdbd2cSJim Jagielski 		// only ascii chars allowed
1220*b1cdbd2cSJim Jagielski 		sal_Int32 nLength(0);
1221*b1cdbd2cSJim Jagielski 		if (m_bAllowLineBreak)
1222*b1cdbd2cSJim Jagielski 			nLength = 3 + calcXMLByteLength( aName.getStr(), aName.getLength(), sal_False, sal_False );
1223*b1cdbd2cSJim Jagielski 		sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1224*b1cdbd2cSJim Jagielski 
1225*b1cdbd2cSJim Jagielski 		if( nPrefix >= 0 )
1226*b1cdbd2cSJim Jagielski 			mp_SaxWriterHelper->insertIndentation( nPrefix );
1227*b1cdbd2cSJim Jagielski 
1228*b1cdbd2cSJim Jagielski 		bRet = mp_SaxWriterHelper->endElement(aName);
1229*b1cdbd2cSJim Jagielski 	}
1230*b1cdbd2cSJim Jagielski 
1231*b1cdbd2cSJim Jagielski 	if (!bRet)
1232*b1cdbd2cSJim Jagielski 	{
1233*b1cdbd2cSJim Jagielski 		SAXException except;
1234*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1235*b1cdbd2cSJim Jagielski 		throw except;
1236*b1cdbd2cSJim Jagielski 	}
1237*b1cdbd2cSJim Jagielski }
1238*b1cdbd2cSJim Jagielski 
characters(const OUString & aChars)1239*b1cdbd2cSJim Jagielski void SAXWriter::characters(const OUString& aChars) 	throw(SAXException, RuntimeException)
1240*b1cdbd2cSJim Jagielski {
1241*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted )
1242*b1cdbd2cSJim Jagielski 	{
1243*b1cdbd2cSJim Jagielski 		SAXException except;
1244*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "characters method called before startDocument" ) );
1245*b1cdbd2cSJim Jagielski 		throw except;
1246*b1cdbd2cSJim Jagielski 	}
1247*b1cdbd2cSJim Jagielski 
1248*b1cdbd2cSJim Jagielski 	sal_Bool bThrowException(sal_False);
1249*b1cdbd2cSJim Jagielski 	if( aChars.getLength() )
1250*b1cdbd2cSJim Jagielski 	{
1251*b1cdbd2cSJim Jagielski 		if( m_bIsCDATA )
1252*b1cdbd2cSJim Jagielski 			bThrowException = !mp_SaxWriterHelper->writeString( aChars, sal_False, sal_False );
1253*b1cdbd2cSJim Jagielski 		else
1254*b1cdbd2cSJim Jagielski 		{
1255*b1cdbd2cSJim Jagielski 			// Note : nFirstLineBreakOccurence is not exact, because we don't know, how
1256*b1cdbd2cSJim Jagielski 			//        many 2 and 3 byte chars are inbetween. However this whole stuff
1257*b1cdbd2cSJim Jagielski 			//        is eitherway for pretty printing only, so it does not need to be exact.
1258*b1cdbd2cSJim Jagielski 			sal_Int32 nLength(0);
1259*b1cdbd2cSJim Jagielski 			sal_Int32 nIndentPrefix(-1);
1260*b1cdbd2cSJim Jagielski 			if (m_bAllowLineBreak)
1261*b1cdbd2cSJim Jagielski 			{
1262*b1cdbd2cSJim Jagielski 				sal_Int32 nFirstLineBreakOccurence = getFirstLineBreak( aChars );
1263*b1cdbd2cSJim Jagielski 
1264*b1cdbd2cSJim Jagielski 				nLength = calcXMLByteLength( aChars.getStr(), aChars.getLength(),
1265*b1cdbd2cSJim Jagielski 											   ! m_bIsCDATA , sal_False );
1266*b1cdbd2cSJim Jagielski 				nIndentPrefix = getIndentPrefixLength(
1267*b1cdbd2cSJim Jagielski 					nFirstLineBreakOccurence >= 0 ? nFirstLineBreakOccurence : nLength );
1268*b1cdbd2cSJim Jagielski 			}
1269*b1cdbd2cSJim Jagielski 			else
1270*b1cdbd2cSJim Jagielski 				nIndentPrefix = getIndentPrefixLength(nLength);
1271*b1cdbd2cSJim Jagielski 
1272*b1cdbd2cSJim Jagielski 			// insert indentation
1273*b1cdbd2cSJim Jagielski 			if( nIndentPrefix >= 0 )
1274*b1cdbd2cSJim Jagielski 			{
1275*b1cdbd2cSJim Jagielski 				if( isFirstCharWhitespace( aChars.getStr() ) )
1276*b1cdbd2cSJim Jagielski 					mp_SaxWriterHelper->insertIndentation( nIndentPrefix - 1 );
1277*b1cdbd2cSJim Jagielski 				else
1278*b1cdbd2cSJim Jagielski 					mp_SaxWriterHelper->insertIndentation( nIndentPrefix );
1279*b1cdbd2cSJim Jagielski 			}
1280*b1cdbd2cSJim Jagielski 			bThrowException = !mp_SaxWriterHelper->writeString(aChars, sal_True , sal_False);
1281*b1cdbd2cSJim Jagielski 		}
1282*b1cdbd2cSJim Jagielski 	}
1283*b1cdbd2cSJim Jagielski 	if (bThrowException)
1284*b1cdbd2cSJim Jagielski 	{
1285*b1cdbd2cSJim Jagielski 		SAXInvalidCharacterException except;
1286*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1287*b1cdbd2cSJim Jagielski 		throw except;
1288*b1cdbd2cSJim Jagielski 	}
1289*b1cdbd2cSJim Jagielski }
1290*b1cdbd2cSJim Jagielski 
1291*b1cdbd2cSJim Jagielski 
ignorableWhitespace(const OUString &)1292*b1cdbd2cSJim Jagielski void SAXWriter::ignorableWhitespace(const OUString&) throw(SAXException, RuntimeException)
1293*b1cdbd2cSJim Jagielski {
1294*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted )
1295*b1cdbd2cSJim Jagielski 	{
1296*b1cdbd2cSJim Jagielski 		throw SAXException ();
1297*b1cdbd2cSJim Jagielski 	}
1298*b1cdbd2cSJim Jagielski 
1299*b1cdbd2cSJim Jagielski 	m_bForceLineBreak = sal_True;
1300*b1cdbd2cSJim Jagielski }
1301*b1cdbd2cSJim Jagielski 
processingInstruction(const OUString & aTarget,const OUString & aData)1302*b1cdbd2cSJim Jagielski void SAXWriter::processingInstruction(const OUString& aTarget, const OUString& aData)
1303*b1cdbd2cSJim Jagielski 	throw (SAXException, RuntimeException)
1304*b1cdbd2cSJim Jagielski {
1305*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted || m_bIsCDATA )
1306*b1cdbd2cSJim Jagielski 	{
1307*b1cdbd2cSJim Jagielski 		throw SAXException();
1308*b1cdbd2cSJim Jagielski 	}
1309*b1cdbd2cSJim Jagielski 
1310*b1cdbd2cSJim Jagielski 	sal_Int32 nLength(0);
1311*b1cdbd2cSJim Jagielski 	if (m_bAllowLineBreak)
1312*b1cdbd2cSJim Jagielski 	{
1313*b1cdbd2cSJim Jagielski 		nLength = 2;  // "<?"
1314*b1cdbd2cSJim Jagielski 		nLength += calcXMLByteLength( aTarget.getStr(), aTarget.getLength(), sal_False, sal_False );
1315*b1cdbd2cSJim Jagielski 
1316*b1cdbd2cSJim Jagielski 		nLength += 1;  // " "
1317*b1cdbd2cSJim Jagielski 
1318*b1cdbd2cSJim Jagielski 		nLength += calcXMLByteLength( aData.getStr(), aData.getLength(), sal_False, sal_False );
1319*b1cdbd2cSJim Jagielski 
1320*b1cdbd2cSJim Jagielski 		nLength += 2; // "?>"
1321*b1cdbd2cSJim Jagielski 	}
1322*b1cdbd2cSJim Jagielski 
1323*b1cdbd2cSJim Jagielski 	sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1324*b1cdbd2cSJim Jagielski 
1325*b1cdbd2cSJim Jagielski 	if( nPrefix >= 0 )
1326*b1cdbd2cSJim Jagielski 		mp_SaxWriterHelper->insertIndentation( nPrefix );
1327*b1cdbd2cSJim Jagielski 
1328*b1cdbd2cSJim Jagielski 	if (!mp_SaxWriterHelper->processingInstruction(aTarget, aData))
1329*b1cdbd2cSJim Jagielski 	{
1330*b1cdbd2cSJim Jagielski 		SAXException except;
1331*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1332*b1cdbd2cSJim Jagielski 		throw except;
1333*b1cdbd2cSJim Jagielski 	}
1334*b1cdbd2cSJim Jagielski }
1335*b1cdbd2cSJim Jagielski 
1336*b1cdbd2cSJim Jagielski 
setDocumentLocator(const Reference<XLocator> &)1337*b1cdbd2cSJim Jagielski void SAXWriter::setDocumentLocator(const Reference< XLocator >&)
1338*b1cdbd2cSJim Jagielski 		throw (SAXException, RuntimeException)
1339*b1cdbd2cSJim Jagielski {
1340*b1cdbd2cSJim Jagielski 
1341*b1cdbd2cSJim Jagielski }
1342*b1cdbd2cSJim Jagielski 
startCDATA(void)1343*b1cdbd2cSJim Jagielski void SAXWriter::startCDATA(void) throw(SAXException, RuntimeException)
1344*b1cdbd2cSJim Jagielski {
1345*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted || m_bIsCDATA)
1346*b1cdbd2cSJim Jagielski 	{
1347*b1cdbd2cSJim Jagielski 		throw SAXException ();
1348*b1cdbd2cSJim Jagielski 	}
1349*b1cdbd2cSJim Jagielski 
1350*b1cdbd2cSJim Jagielski 	sal_Int32 nLength = 9;
1351*b1cdbd2cSJim Jagielski 	sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1352*b1cdbd2cSJim Jagielski 	if( nPrefix >= 0 )
1353*b1cdbd2cSJim Jagielski 		mp_SaxWriterHelper->insertIndentation( nPrefix );
1354*b1cdbd2cSJim Jagielski 
1355*b1cdbd2cSJim Jagielski 	mp_SaxWriterHelper->startCDATA();
1356*b1cdbd2cSJim Jagielski 
1357*b1cdbd2cSJim Jagielski 	m_bIsCDATA = sal_True;
1358*b1cdbd2cSJim Jagielski }
1359*b1cdbd2cSJim Jagielski 
endCDATA(void)1360*b1cdbd2cSJim Jagielski void SAXWriter::endCDATA(void) throw (RuntimeException)
1361*b1cdbd2cSJim Jagielski {
1362*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted | ! m_bIsCDATA)
1363*b1cdbd2cSJim Jagielski 	{
1364*b1cdbd2cSJim Jagielski 		SAXException except;
1365*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "endCDATA was called without startCDATA" ) );
1366*b1cdbd2cSJim Jagielski 		throw except;
1367*b1cdbd2cSJim Jagielski 	}
1368*b1cdbd2cSJim Jagielski 
1369*b1cdbd2cSJim Jagielski 	sal_Int32 nLength = 3;
1370*b1cdbd2cSJim Jagielski 	sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1371*b1cdbd2cSJim Jagielski 	if( nPrefix >= 0 )
1372*b1cdbd2cSJim Jagielski 		mp_SaxWriterHelper->insertIndentation( nPrefix );
1373*b1cdbd2cSJim Jagielski 
1374*b1cdbd2cSJim Jagielski 	mp_SaxWriterHelper->endCDATA();
1375*b1cdbd2cSJim Jagielski 
1376*b1cdbd2cSJim Jagielski 	m_bIsCDATA = sal_False;
1377*b1cdbd2cSJim Jagielski }
1378*b1cdbd2cSJim Jagielski 
1379*b1cdbd2cSJim Jagielski 
comment(const OUString & sComment)1380*b1cdbd2cSJim Jagielski void SAXWriter::comment(const OUString& sComment) throw(SAXException, RuntimeException)
1381*b1cdbd2cSJim Jagielski {
1382*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted || m_bIsCDATA )
1383*b1cdbd2cSJim Jagielski 	{
1384*b1cdbd2cSJim Jagielski 		throw SAXException();
1385*b1cdbd2cSJim Jagielski 	}
1386*b1cdbd2cSJim Jagielski 
1387*b1cdbd2cSJim Jagielski 	sal_Int32 nLength(0);
1388*b1cdbd2cSJim Jagielski 	if (m_bAllowLineBreak)
1389*b1cdbd2cSJim Jagielski 	{
1390*b1cdbd2cSJim Jagielski 		nLength = 4; // "<!--"
1391*b1cdbd2cSJim Jagielski 		nLength += calcXMLByteLength( sComment.getStr(), sComment.getLength(), sal_False, sal_False);
1392*b1cdbd2cSJim Jagielski 
1393*b1cdbd2cSJim Jagielski 		nLength += 3;
1394*b1cdbd2cSJim Jagielski 	}
1395*b1cdbd2cSJim Jagielski 
1396*b1cdbd2cSJim Jagielski 	sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1397*b1cdbd2cSJim Jagielski 	if( nPrefix >= 0 )
1398*b1cdbd2cSJim Jagielski 		mp_SaxWriterHelper->insertIndentation( nPrefix );
1399*b1cdbd2cSJim Jagielski 
1400*b1cdbd2cSJim Jagielski 	if (!mp_SaxWriterHelper->comment(sComment))
1401*b1cdbd2cSJim Jagielski 	{
1402*b1cdbd2cSJim Jagielski 		SAXException except;
1403*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1404*b1cdbd2cSJim Jagielski 		throw except;
1405*b1cdbd2cSJim Jagielski 	}
1406*b1cdbd2cSJim Jagielski }
1407*b1cdbd2cSJim Jagielski 
1408*b1cdbd2cSJim Jagielski 
allowLineBreak()1409*b1cdbd2cSJim Jagielski void SAXWriter::allowLineBreak( ) 	throw ( SAXException , RuntimeException)
1410*b1cdbd2cSJim Jagielski {
1411*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted || m_bAllowLineBreak ) {
1412*b1cdbd2cSJim Jagielski 		throw SAXException();
1413*b1cdbd2cSJim Jagielski 	}
1414*b1cdbd2cSJim Jagielski 
1415*b1cdbd2cSJim Jagielski 	 m_bAllowLineBreak = sal_True;
1416*b1cdbd2cSJim Jagielski }
1417*b1cdbd2cSJim Jagielski 
unknown(const OUString & sString)1418*b1cdbd2cSJim Jagielski void SAXWriter::unknown(const OUString& sString) throw (SAXException, RuntimeException)
1419*b1cdbd2cSJim Jagielski {
1420*b1cdbd2cSJim Jagielski 
1421*b1cdbd2cSJim Jagielski 	if( ! m_bDocStarted )
1422*b1cdbd2cSJim Jagielski 	{
1423*b1cdbd2cSJim Jagielski 		throw SAXException ();
1424*b1cdbd2cSJim Jagielski 	}
1425*b1cdbd2cSJim Jagielski 	if( m_bIsCDATA )
1426*b1cdbd2cSJim Jagielski 	{
1427*b1cdbd2cSJim Jagielski 		throw SAXException();
1428*b1cdbd2cSJim Jagielski 	}
1429*b1cdbd2cSJim Jagielski 
1430*b1cdbd2cSJim Jagielski 	if( sString.matchAsciiL( "<?xml", 5 ) )
1431*b1cdbd2cSJim Jagielski 		return;
1432*b1cdbd2cSJim Jagielski 
1433*b1cdbd2cSJim Jagielski 	sal_Int32 nLength(0);
1434*b1cdbd2cSJim Jagielski 	if (m_bAllowLineBreak)
1435*b1cdbd2cSJim Jagielski 		nLength = calcXMLByteLength( sString.getStr(), sString.getLength(), sal_False, sal_False );
1436*b1cdbd2cSJim Jagielski 
1437*b1cdbd2cSJim Jagielski 	sal_Int32 nPrefix = getIndentPrefixLength( nLength );
1438*b1cdbd2cSJim Jagielski 	if( nPrefix >= 0 )
1439*b1cdbd2cSJim Jagielski 		mp_SaxWriterHelper->insertIndentation( nPrefix );
1440*b1cdbd2cSJim Jagielski 
1441*b1cdbd2cSJim Jagielski 	if (!mp_SaxWriterHelper->writeString( sString, sal_False, sal_False))
1442*b1cdbd2cSJim Jagielski 	{
1443*b1cdbd2cSJim Jagielski 		SAXException except;
1444*b1cdbd2cSJim Jagielski 		except.Message = OUString( RTL_CONSTASCII_USTRINGPARAM( "Invalid charcter during XML-Export" ) );
1445*b1cdbd2cSJim Jagielski 		throw except;
1446*b1cdbd2cSJim Jagielski 	}
1447*b1cdbd2cSJim Jagielski }
1448*b1cdbd2cSJim Jagielski 
1449*b1cdbd2cSJim Jagielski }
1450*b1cdbd2cSJim Jagielski 
1451