xref: /trunk/main/basic/source/sbx/sbxstr.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basic.hxx"
30 #include <tools/errcode.hxx>
31 #include <basic/sbx.hxx>
32 #include "sbxconv.hxx"
33 #include "sbxres.hxx"
34 #include "runtime.hxx"
35 #ifndef _RTL_USTRBUF_HXX_
36 #include <rtl/ustrbuf.hxx>
37 #endif
38 // AB 29.10.99 Unicode
39 #ifndef _USE_NO_NAMESPACE
40 using namespace rtl;
41 #endif
42 
43 
44 // Die Konversion eines Items auf String wird ueber die Put-Methoden
45 // der einzelnen Datentypen abgewickelt, um doppelten Code zu vermeiden.
46 
47 ::rtl::OUString ImpGetString( const SbxValues* p )
48 {
49     SbxValues aTmp;
50     ::rtl::OUString aRes;
51     aTmp.eType = SbxSTRING;
52     aTmp.pOUString = &aRes;
53     switch( +p->eType )
54     {
55         case SbxNULL:
56             SbxBase::SetError( SbxERR_CONVERSION );
57         case SbxEMPTY:
58             break;
59         case SbxCHAR:
60             ImpPutChar( &aTmp, p->nChar ); break;
61         case SbxBYTE:
62             ImpPutByte( &aTmp, p->nByte ); break;
63         case SbxINTEGER:
64             ImpPutInteger( &aTmp, p->nInteger ); break;
65         case SbxBOOL:
66             ImpPutBool( &aTmp, p->nUShort ); break;
67         case SbxUSHORT:
68             ImpPutUShort( &aTmp, p->nUShort ); break;
69         case SbxLONG:
70             ImpPutLong( &aTmp, p->nLong ); break;
71         case SbxULONG:
72             ImpPutULong( &aTmp, p->nULong ); break;
73         case SbxSINGLE:
74             ImpPutSingle( &aTmp, p->nSingle ); break;
75         case SbxDOUBLE:
76             ImpPutDouble( &aTmp, p->nDouble ); break;
77         case SbxCURRENCY:
78             ImpPutCurrency( &aTmp, p->nLong64 ); break;
79         case SbxDECIMAL:
80         case SbxBYREF | SbxDECIMAL:
81             ImpPutDecimal( &aTmp, p->pDecimal ); break;
82         case SbxSALINT64:
83             ImpPutInt64( &aTmp, p->nInt64 ); break;
84         case SbxSALUINT64:
85             ImpPutUInt64( &aTmp, p->uInt64 ); break;
86         case SbxBYREF | SbxSTRING:
87         case SbxSTRING:
88         case SbxLPSTR:
89             if ( p->pOUString )
90                 *aTmp.pOUString = *p->pOUString;
91             break;
92         case SbxOBJECT:
93         {
94             SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
95             if( pVal )
96                 aRes = pVal->GetString();
97             else if( p->pObj && p->pObj->IsFixed()
98                     && (p->pObj->GetType() == (SbxARRAY | SbxBYTE )) )
99             {
100                 // convert byte array to string
101                 SbxArray* pArr = PTR_CAST(SbxArray, p->pObj);
102                 if( pArr )
103                     aRes = ByteArrayToString( pArr );
104             }
105             else
106                 SbxBase::SetError( SbxERR_NO_OBJECT );
107             break;
108         }
109         case SbxERROR:
110             // Hier wird der String "Error n" erzeugt
111             aRes = SbxRes( STRING_ERRORMSG );
112             aRes += ::rtl::OUString( p->nUShort ); break;
113         case SbxDATE:
114             ImpPutDate( &aTmp, p->nDouble ); break;
115 
116         case SbxBYREF | SbxCHAR:
117             ImpPutChar( &aTmp, *p->pChar ); break;
118         case SbxBYREF | SbxBYTE:
119             ImpPutByte( &aTmp, *p->pByte ); break;
120         case SbxBYREF | SbxINTEGER:
121         case SbxBYREF | SbxBOOL:
122             ImpPutInteger( &aTmp, *p->pInteger ); break;
123         case SbxBYREF | SbxLONG:
124             ImpPutLong( &aTmp, *p->pLong ); break;
125         case SbxBYREF | SbxULONG:
126             ImpPutULong( &aTmp, *p->pULong ); break;
127         case SbxBYREF | SbxERROR:
128         case SbxBYREF | SbxUSHORT:
129             ImpPutUShort( &aTmp, *p->pUShort ); break;
130         case SbxBYREF | SbxSINGLE:
131             ImpPutSingle( &aTmp, *p->pSingle ); break;
132         case SbxBYREF | SbxDATE:
133         case SbxBYREF | SbxDOUBLE:
134             ImpPutDouble( &aTmp, *p->pDouble ); break;
135         case SbxBYREF | SbxCURRENCY:
136             ImpPutCurrency( &aTmp, *p->pLong64 ); break;
137         case SbxBYREF | SbxSALINT64:
138             ImpPutInt64( &aTmp, *p->pnInt64 ); break;
139         case SbxBYREF | SbxSALUINT64:
140             ImpPutUInt64( &aTmp, *p->puInt64 ); break;
141         default:
142             SbxBase::SetError( SbxERR_CONVERSION );
143     }
144     return aRes;
145 }
146 
147 // AB 10.4.97, neue Funktion fuer SbxValue::GetCoreString()
148 ::rtl::OUString ImpGetCoreString( const SbxValues* p )
149 {
150     // Vorerst nur fuer double
151     if( ( p->eType & (~SbxBYREF) ) == SbxDOUBLE )
152     {
153         SbxValues aTmp;
154         XubString aRes;
155         aTmp.eType = SbxSTRING;
156         if( p->eType == SbxDOUBLE )
157             ImpPutDouble( &aTmp, p->nDouble, /*bCoreString=*/sal_True );
158         else
159             ImpPutDouble( &aTmp, *p->pDouble, /*bCoreString=*/sal_True );
160         return aRes;
161     }
162     else
163         return ImpGetString( p );
164 }
165 
166 void ImpPutString( SbxValues* p, const ::rtl::OUString* n )
167 {
168     SbxValues aTmp;
169     aTmp.eType = SbxSTRING;
170     ::rtl::OUString* pTmp = NULL;
171     // Sicherheitshalber, falls ein NULL-Ptr kommt
172     if( !n )
173         n = pTmp = new ::rtl::OUString;
174     aTmp.pOUString = (::rtl::OUString*)n;
175     switch( +p->eType )
176     {
177         case SbxCHAR:
178             p->nChar = ImpGetChar( &aTmp ); break;
179         case SbxBYTE:
180             p->nByte = ImpGetByte( &aTmp ); break;
181         case SbxINTEGER:
182         case SbxBOOL:
183             p->nInteger = ImpGetInteger( &aTmp ); break;
184         case SbxLONG:
185             p->nLong = ImpGetLong( &aTmp ); break;
186         case SbxULONG:
187             p->nULong = ImpGetULong( &aTmp ); break;
188         case SbxERROR:
189         case SbxUSHORT:
190             p->nUShort = ImpGetUShort( &aTmp ); break;
191         case SbxSINGLE:
192             p->nSingle = ImpGetSingle( &aTmp ); break;
193         case SbxDATE:
194             p->nDouble = ImpGetDate( &aTmp ); break;
195         case SbxDOUBLE:
196             p->nDouble = ImpGetDouble( &aTmp ); break;
197         case SbxULONG64:
198             p->nLong64 = ImpGetCurrency( &aTmp ); break;
199         case SbxDECIMAL:
200         case SbxBYREF | SbxDECIMAL:
201             releaseDecimalPtr( p->pDecimal );
202             p->pDecimal = ImpGetDecimal( &aTmp ); break;
203         case SbxSALINT64:
204             p->nInt64 = ImpGetInt64( &aTmp ); break;
205         case SbxSALUINT64:
206             p->uInt64 = ImpGetUInt64( &aTmp ); break;
207 
208         case SbxBYREF | SbxSTRING:
209         case SbxSTRING:
210         case SbxLPSTR:
211             if( n->getLength() )
212             {
213                 if( !p->pOUString )
214                     p->pOUString = new ::rtl::OUString( *n );
215                 else
216                     *p->pOUString = *n;
217             }
218             else
219                 delete p->pOUString, p->pOUString = NULL;
220             break;
221         case SbxOBJECT:
222         {
223             SbxValue* pVal = PTR_CAST(SbxValue,p->pObj);
224             if( pVal )
225                 pVal->PutString( *n );
226             else
227                 SbxBase::SetError( SbxERR_NO_OBJECT );
228             break;
229         }
230         case SbxBYREF | SbxCHAR:
231             *p->pChar = ImpGetChar( p ); break;
232         case SbxBYREF | SbxBYTE:
233             *p->pByte = ImpGetByte( p ); break;
234         case SbxBYREF | SbxINTEGER:
235             *p->pInteger = ImpGetInteger( p ); break;
236         case SbxBYREF | SbxBOOL:
237             *p->pUShort = sal::static_int_cast< sal_uInt16 >( ImpGetBool( p ) );
238             break;
239         case SbxBYREF | SbxERROR:
240         case SbxBYREF | SbxUSHORT:
241             *p->pUShort = ImpGetUShort( p ); break;
242         case SbxBYREF | SbxLONG:
243             *p->pLong = ImpGetLong( p ); break;
244         case SbxBYREF | SbxULONG:
245             *p->pULong = ImpGetULong( p ); break;
246         case SbxBYREF | SbxSINGLE:
247             *p->pSingle = ImpGetSingle( p ); break;
248         case SbxBYREF | SbxDATE:
249             *p->pDouble = ImpGetDate( p ); break;
250         case SbxBYREF | SbxDOUBLE:
251             *p->pDouble = ImpGetDouble( p ); break;
252         case SbxBYREF | SbxCURRENCY:
253             *p->pLong64 = ImpGetCurrency( p ); break;
254         default:
255             SbxBase::SetError( SbxERR_CONVERSION );
256     }
257     delete pTmp;
258 }
259 
260 // Convert string to an array of bytes, preserving unicode (2bytes per character)
261 SbxArray* StringToByteArray(const ::rtl::OUString& rStr)
262 {
263     sal_Int32 nArraySize = rStr.getLength() * 2;
264     const sal_Unicode* pSrc = rStr.getStr();
265     SbxDimArray* pArray = new SbxDimArray(SbxBYTE);
266     bool bIncIndex = ( IsBaseIndexOne() && SbiRuntime::isVBAEnabled() );
267     if( nArraySize )
268     {
269         if( bIncIndex )
270             pArray->AddDim32( 1, nArraySize );
271         else
272             pArray->AddDim32( 0, nArraySize-1 );
273     }
274     else
275     {
276         pArray->unoAddDim( 0, -1 );
277     }
278 
279     for( sal_uInt16 i=0; i< nArraySize; i++)
280     {
281         SbxVariable* pNew = new SbxVariable( SbxBYTE );
282         sal_uInt8 aByte = static_cast< sal_uInt8 >( i%2 ? ((*pSrc) >> 8) & 0xff : (*pSrc) & 0xff );
283         pNew->PutByte( aByte );
284         pNew->SetFlag( SBX_WRITE );
285         pArray->Put( pNew, i );
286         if( i%2 )
287             pSrc++;
288     }
289     return pArray;
290 }
291 
292 // Convert an array of bytes to string (2bytes per character)
293 ::rtl::OUString ByteArrayToString(SbxArray* pArr)
294 {
295     sal_uInt16 nCount = pArr->Count();
296     OUStringBuffer aStrBuf;
297     sal_Unicode aChar = 0;
298     for( sal_uInt16 i = 0 ; i < nCount ; i++ )
299     {
300         sal_Unicode aTempChar = pArr->Get(i)->GetByte();
301         if( i%2 )
302         {
303             aChar = (aTempChar << 8 ) | aChar;
304             aStrBuf.append(aChar);
305             aChar = 0;
306         }
307         else
308         {
309             aChar = aTempChar;
310         }
311     }
312 
313     if( nCount%2 )
314     {
315         aStrBuf.append(aChar);
316     }
317 
318     return aStrBuf.makeStringAndClear();
319 }
320