1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_basic.hxx" 30*cdf0e10cSrcweir #include <tools/errcode.hxx> 31*cdf0e10cSrcweir #ifndef _APP_HXX //autogen 32*cdf0e10cSrcweir #include <vcl/svapp.hxx> 33*cdf0e10cSrcweir #endif 34*cdf0e10cSrcweir #include <basic/sbx.hxx> 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir class SbxSimpleCharClass 38*cdf0e10cSrcweir { 39*cdf0e10cSrcweir public: 40*cdf0e10cSrcweir sal_Bool isAlpha( sal_Unicode c ) const 41*cdf0e10cSrcweir { 42*cdf0e10cSrcweir sal_Bool bRet = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); 43*cdf0e10cSrcweir return bRet; 44*cdf0e10cSrcweir } 45*cdf0e10cSrcweir 46*cdf0e10cSrcweir sal_Bool isDigit( sal_Unicode c ) const 47*cdf0e10cSrcweir { 48*cdf0e10cSrcweir sal_Bool bRet = (c >= '0' && c <= '9'); 49*cdf0e10cSrcweir return bRet; 50*cdf0e10cSrcweir } 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir sal_Bool isAlphaNumeric( sal_Unicode c ) const 53*cdf0e10cSrcweir { 54*cdf0e10cSrcweir sal_Bool bRet = isDigit( c ) || isAlpha( c ); 55*cdf0e10cSrcweir return bRet; 56*cdf0e10cSrcweir } 57*cdf0e10cSrcweir }; 58*cdf0e10cSrcweir 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir static SbxVariable* Element 61*cdf0e10cSrcweir ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, 62*cdf0e10cSrcweir SbxClassType, const SbxSimpleCharClass& rCharClass ); 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir static const xub_Unicode* SkipWhitespace( const xub_Unicode* p ) 65*cdf0e10cSrcweir { 66*cdf0e10cSrcweir while( *p && ( *p == ' ' || *p == '\t' ) ) 67*cdf0e10cSrcweir p++; 68*cdf0e10cSrcweir return p; 69*cdf0e10cSrcweir } 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir // Scannen eines Symbol. Das Symbol wird in rSym eingetragen, der Returnwert 72*cdf0e10cSrcweir // ist die neue Scanposition. Bei Fehlern ist das Symbol leer. 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir static const xub_Unicode* Symbol( const xub_Unicode* p, XubString& rSym, const SbxSimpleCharClass& rCharClass ) 75*cdf0e10cSrcweir { 76*cdf0e10cSrcweir sal_uInt16 nLen = 0; 77*cdf0e10cSrcweir // Haben wir ein Sondersymbol? 78*cdf0e10cSrcweir if( *p == '[' ) 79*cdf0e10cSrcweir { 80*cdf0e10cSrcweir rSym = ++p; 81*cdf0e10cSrcweir while( *p && *p != ']' ) 82*cdf0e10cSrcweir p++, nLen++; 83*cdf0e10cSrcweir p++; 84*cdf0e10cSrcweir } 85*cdf0e10cSrcweir else 86*cdf0e10cSrcweir { 87*cdf0e10cSrcweir // Ein Symbol muss mit einem Buchstaben oder einem Underline beginnen 88*cdf0e10cSrcweir if( !rCharClass.isAlpha( *p ) && *p != '_' ) 89*cdf0e10cSrcweir SbxBase::SetError( SbxERR_SYNTAX ); 90*cdf0e10cSrcweir else 91*cdf0e10cSrcweir { 92*cdf0e10cSrcweir rSym = p; 93*cdf0e10cSrcweir // Dann darf es Buchstaben, Zahlen oder Underlines enthalten 94*cdf0e10cSrcweir while( *p && (rCharClass.isAlphaNumeric( *p ) || *p == '_') ) 95*cdf0e10cSrcweir p++, nLen++; 96*cdf0e10cSrcweir // BASIC-Standard-Suffixe werden ignoriert 97*cdf0e10cSrcweir if( *p && (*p == '%' || *p == '&' || *p == '!' || *p == '#' || *p == '$' ) ) 98*cdf0e10cSrcweir p++; 99*cdf0e10cSrcweir } 100*cdf0e10cSrcweir } 101*cdf0e10cSrcweir rSym.Erase( nLen ); 102*cdf0e10cSrcweir return p; 103*cdf0e10cSrcweir } 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir // Qualifizierter Name. Element.Element.... 106*cdf0e10cSrcweir 107*cdf0e10cSrcweir static SbxVariable* QualifiedName 108*cdf0e10cSrcweir ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, SbxClassType t ) 109*cdf0e10cSrcweir { 110*cdf0e10cSrcweir static SbxSimpleCharClass aCharClass; 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir SbxVariableRef refVar; 113*cdf0e10cSrcweir const xub_Unicode* p = SkipWhitespace( *ppBuf ); 114*cdf0e10cSrcweir if( aCharClass.isAlpha( *p ) || *p == '_' || *p == '[' ) 115*cdf0e10cSrcweir { 116*cdf0e10cSrcweir // Element einlesen 117*cdf0e10cSrcweir refVar = Element( pObj, pGbl, &p, t, aCharClass ); 118*cdf0e10cSrcweir while( refVar.Is() && (*p == '.' || *p == '!') ) 119*cdf0e10cSrcweir { 120*cdf0e10cSrcweir // Es folgt noch ein Objektelement. Das aktuelle Element 121*cdf0e10cSrcweir // muss also ein SBX-Objekt sein oder liefern! 122*cdf0e10cSrcweir pObj = PTR_CAST(SbxObject,(SbxVariable*) refVar); 123*cdf0e10cSrcweir if( !pObj ) 124*cdf0e10cSrcweir // Dann muss es ein Objekt liefern 125*cdf0e10cSrcweir pObj = PTR_CAST(SbxObject,refVar->GetObject()); 126*cdf0e10cSrcweir refVar.Clear(); 127*cdf0e10cSrcweir if( !pObj ) 128*cdf0e10cSrcweir break; 129*cdf0e10cSrcweir p++; 130*cdf0e10cSrcweir // Und das naechste Element bitte 131*cdf0e10cSrcweir refVar = Element( pObj, pGbl, &p, t, aCharClass ); 132*cdf0e10cSrcweir } 133*cdf0e10cSrcweir } 134*cdf0e10cSrcweir else 135*cdf0e10cSrcweir SbxBase::SetError( SbxERR_SYNTAX ); 136*cdf0e10cSrcweir *ppBuf = p; 137*cdf0e10cSrcweir if( refVar.Is() ) 138*cdf0e10cSrcweir refVar->AddRef(); 139*cdf0e10cSrcweir return refVar; 140*cdf0e10cSrcweir } 141*cdf0e10cSrcweir 142*cdf0e10cSrcweir // Einlesen eines Operanden. Dies kann eine Zahl, ein String oder 143*cdf0e10cSrcweir // eine Funktion (mit optionalen Parametern) sein. 144*cdf0e10cSrcweir 145*cdf0e10cSrcweir static SbxVariable* Operand 146*cdf0e10cSrcweir ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, sal_Bool bVar ) 147*cdf0e10cSrcweir { 148*cdf0e10cSrcweir static SbxSimpleCharClass aCharClass; 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir SbxVariableRef refVar( new SbxVariable ); 151*cdf0e10cSrcweir const xub_Unicode* p = SkipWhitespace( *ppBuf ); 152*cdf0e10cSrcweir if( !bVar && ( aCharClass.isDigit( *p ) 153*cdf0e10cSrcweir || ( *p == '.' && aCharClass.isDigit( *( p+1 ) ) ) 154*cdf0e10cSrcweir || *p == '-' 155*cdf0e10cSrcweir || *p == '&' ) ) 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir // Eine Zahl kann direkt eingescant werden! 158*cdf0e10cSrcweir sal_uInt16 nLen; 159*cdf0e10cSrcweir if( !refVar->Scan( XubString( p ), &nLen ) ) 160*cdf0e10cSrcweir refVar.Clear(); 161*cdf0e10cSrcweir else 162*cdf0e10cSrcweir p += nLen; 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir else if( !bVar && *p == '"' ) 165*cdf0e10cSrcweir { 166*cdf0e10cSrcweir // Ein String 167*cdf0e10cSrcweir XubString aString; 168*cdf0e10cSrcweir p++; 169*cdf0e10cSrcweir for( ;; ) 170*cdf0e10cSrcweir { 171*cdf0e10cSrcweir // Das ist wohl ein Fehler 172*cdf0e10cSrcweir if( !*p ) 173*cdf0e10cSrcweir return NULL; 174*cdf0e10cSrcweir // Doppelte Quotes sind OK 175*cdf0e10cSrcweir if( *p == '"' ) 176*cdf0e10cSrcweir if( *++p != '"' ) 177*cdf0e10cSrcweir break; 178*cdf0e10cSrcweir aString += *p++; 179*cdf0e10cSrcweir } 180*cdf0e10cSrcweir refVar->PutString( aString ); 181*cdf0e10cSrcweir } 182*cdf0e10cSrcweir else 183*cdf0e10cSrcweir refVar = QualifiedName( pObj, pGbl, &p, SbxCLASS_DONTCARE ); 184*cdf0e10cSrcweir *ppBuf = p; 185*cdf0e10cSrcweir if( refVar.Is() ) 186*cdf0e10cSrcweir refVar->AddRef(); 187*cdf0e10cSrcweir return refVar; 188*cdf0e10cSrcweir } 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir // Einlesen einer einfachen Term. Die Operatoren +, -, * und / 191*cdf0e10cSrcweir // werden unterstuetzt. 192*cdf0e10cSrcweir 193*cdf0e10cSrcweir static SbxVariable* MulDiv( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) 194*cdf0e10cSrcweir { 195*cdf0e10cSrcweir const xub_Unicode* p = *ppBuf; 196*cdf0e10cSrcweir SbxVariableRef refVar( Operand( pObj, pGbl, &p, sal_False ) ); 197*cdf0e10cSrcweir p = SkipWhitespace( p ); 198*cdf0e10cSrcweir while( refVar.Is() && ( *p == '*' || *p == '/' ) ) 199*cdf0e10cSrcweir { 200*cdf0e10cSrcweir xub_Unicode cOp = *p++; 201*cdf0e10cSrcweir SbxVariableRef refVar2( Operand( pObj, pGbl, &p, sal_False ) ); 202*cdf0e10cSrcweir if( refVar2.Is() ) 203*cdf0e10cSrcweir { 204*cdf0e10cSrcweir // temporaere Variable! 205*cdf0e10cSrcweir SbxVariable* pVar = refVar; 206*cdf0e10cSrcweir pVar = new SbxVariable( *pVar ); 207*cdf0e10cSrcweir refVar = pVar; 208*cdf0e10cSrcweir if( cOp == '*' ) 209*cdf0e10cSrcweir *refVar *= *refVar2; 210*cdf0e10cSrcweir else 211*cdf0e10cSrcweir *refVar /= *refVar2; 212*cdf0e10cSrcweir } 213*cdf0e10cSrcweir else 214*cdf0e10cSrcweir { 215*cdf0e10cSrcweir refVar.Clear(); 216*cdf0e10cSrcweir break; 217*cdf0e10cSrcweir } 218*cdf0e10cSrcweir } 219*cdf0e10cSrcweir *ppBuf = p; 220*cdf0e10cSrcweir if( refVar.Is() ) 221*cdf0e10cSrcweir refVar->AddRef(); 222*cdf0e10cSrcweir return refVar; 223*cdf0e10cSrcweir } 224*cdf0e10cSrcweir 225*cdf0e10cSrcweir static SbxVariable* PlusMinus( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) 226*cdf0e10cSrcweir { 227*cdf0e10cSrcweir const xub_Unicode* p = *ppBuf; 228*cdf0e10cSrcweir SbxVariableRef refVar( MulDiv( pObj, pGbl, &p ) ); 229*cdf0e10cSrcweir p = SkipWhitespace( p ); 230*cdf0e10cSrcweir while( refVar.Is() && ( *p == '+' || *p == '-' ) ) 231*cdf0e10cSrcweir { 232*cdf0e10cSrcweir xub_Unicode cOp = *p++; 233*cdf0e10cSrcweir SbxVariableRef refVar2( MulDiv( pObj, pGbl, &p ) ); 234*cdf0e10cSrcweir if( refVar2.Is() ) 235*cdf0e10cSrcweir { 236*cdf0e10cSrcweir // temporaere Variable! 237*cdf0e10cSrcweir SbxVariable* pVar = refVar; 238*cdf0e10cSrcweir pVar = new SbxVariable( *pVar ); 239*cdf0e10cSrcweir refVar = pVar; 240*cdf0e10cSrcweir if( cOp == '+' ) 241*cdf0e10cSrcweir *refVar += *refVar2; 242*cdf0e10cSrcweir else 243*cdf0e10cSrcweir *refVar -= *refVar2; 244*cdf0e10cSrcweir } 245*cdf0e10cSrcweir else 246*cdf0e10cSrcweir { 247*cdf0e10cSrcweir refVar.Clear(); 248*cdf0e10cSrcweir break; 249*cdf0e10cSrcweir } 250*cdf0e10cSrcweir } 251*cdf0e10cSrcweir *ppBuf = p; 252*cdf0e10cSrcweir if( refVar.Is() ) 253*cdf0e10cSrcweir refVar->AddRef(); 254*cdf0e10cSrcweir return refVar; 255*cdf0e10cSrcweir } 256*cdf0e10cSrcweir 257*cdf0e10cSrcweir static SbxVariable* Assign( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf ) 258*cdf0e10cSrcweir { 259*cdf0e10cSrcweir const xub_Unicode* p = *ppBuf; 260*cdf0e10cSrcweir SbxVariableRef refVar( Operand( pObj, pGbl, &p, sal_True ) ); 261*cdf0e10cSrcweir p = SkipWhitespace( p ); 262*cdf0e10cSrcweir if( refVar.Is() ) 263*cdf0e10cSrcweir { 264*cdf0e10cSrcweir if( *p == '=' ) 265*cdf0e10cSrcweir { 266*cdf0e10cSrcweir // Nur auf Props zuweisen! 267*cdf0e10cSrcweir if( refVar->GetClass() != SbxCLASS_PROPERTY ) 268*cdf0e10cSrcweir { 269*cdf0e10cSrcweir SbxBase::SetError( SbxERR_BAD_ACTION ); 270*cdf0e10cSrcweir refVar.Clear(); 271*cdf0e10cSrcweir } 272*cdf0e10cSrcweir else 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir p++; 275*cdf0e10cSrcweir SbxVariableRef refVar2( PlusMinus( pObj, pGbl, &p ) ); 276*cdf0e10cSrcweir if( refVar2.Is() ) 277*cdf0e10cSrcweir { 278*cdf0e10cSrcweir SbxVariable* pVar = refVar; 279*cdf0e10cSrcweir SbxVariable* pVar2 = refVar2; 280*cdf0e10cSrcweir *pVar = *pVar2; 281*cdf0e10cSrcweir pVar->SetParameters( NULL ); 282*cdf0e10cSrcweir } 283*cdf0e10cSrcweir } 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir else 286*cdf0e10cSrcweir // Einfacher Aufruf: einmal aktivieren 287*cdf0e10cSrcweir refVar->Broadcast( SBX_HINT_DATAWANTED ); 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir *ppBuf = p; 290*cdf0e10cSrcweir if( refVar.Is() ) 291*cdf0e10cSrcweir refVar->AddRef(); 292*cdf0e10cSrcweir return refVar; 293*cdf0e10cSrcweir } 294*cdf0e10cSrcweir 295*cdf0e10cSrcweir // Einlesen eines Elements. Dies ist ein Symbol, optional gefolgt 296*cdf0e10cSrcweir // von einer Parameterliste. Das Symbol wird im angegebenen Objekt 297*cdf0e10cSrcweir // gesucht und die Parameterliste wird ggf. angefuegt. 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir static SbxVariable* Element 300*cdf0e10cSrcweir ( SbxObject* pObj, SbxObject* pGbl, const xub_Unicode** ppBuf, 301*cdf0e10cSrcweir SbxClassType t, const SbxSimpleCharClass& rCharClass ) 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir XubString aSym; 304*cdf0e10cSrcweir const xub_Unicode* p = Symbol( *ppBuf, aSym, rCharClass ); 305*cdf0e10cSrcweir SbxVariableRef refVar; 306*cdf0e10cSrcweir if( aSym.Len() ) 307*cdf0e10cSrcweir { 308*cdf0e10cSrcweir sal_uInt16 nOld = pObj->GetFlags(); 309*cdf0e10cSrcweir if( pObj == pGbl ) 310*cdf0e10cSrcweir pObj->SetFlag( SBX_GBLSEARCH ); 311*cdf0e10cSrcweir refVar = pObj->Find( aSym, t ); 312*cdf0e10cSrcweir pObj->SetFlags( nOld ); 313*cdf0e10cSrcweir if( refVar.Is() ) 314*cdf0e10cSrcweir { 315*cdf0e10cSrcweir refVar->SetParameters( NULL ); 316*cdf0e10cSrcweir // folgen noch Parameter? 317*cdf0e10cSrcweir p = SkipWhitespace( p ); 318*cdf0e10cSrcweir if( *p == '(' ) 319*cdf0e10cSrcweir { 320*cdf0e10cSrcweir p++; 321*cdf0e10cSrcweir SbxArrayRef refPar = new SbxArray; 322*cdf0e10cSrcweir sal_uInt16 nArg = 0; 323*cdf0e10cSrcweir // Wird sind mal relaxed und akzeptieren auch 324*cdf0e10cSrcweir // das Zeilen- oder Komandoende als Begrenzer 325*cdf0e10cSrcweir // Parameter immer global suchen! 326*cdf0e10cSrcweir while( *p && *p != ')' && *p != ']' ) 327*cdf0e10cSrcweir { 328*cdf0e10cSrcweir SbxVariableRef refArg = PlusMinus( pGbl, pGbl, &p ); 329*cdf0e10cSrcweir if( !refArg ) 330*cdf0e10cSrcweir { 331*cdf0e10cSrcweir // Fehler beim Parsing 332*cdf0e10cSrcweir refVar.Clear(); break; 333*cdf0e10cSrcweir } 334*cdf0e10cSrcweir else 335*cdf0e10cSrcweir { 336*cdf0e10cSrcweir // Man kopiere den Parameter, damit 337*cdf0e10cSrcweir // man den aktuellen Zustand hat (loest auch 338*cdf0e10cSrcweir // den Aufruf per Zugriff aus) 339*cdf0e10cSrcweir SbxVariable* pArg = refArg; 340*cdf0e10cSrcweir refPar->Put( new SbxVariable( *pArg ), ++nArg ); 341*cdf0e10cSrcweir } 342*cdf0e10cSrcweir p = SkipWhitespace( p ); 343*cdf0e10cSrcweir if( *p == ',' ) 344*cdf0e10cSrcweir p++; 345*cdf0e10cSrcweir } 346*cdf0e10cSrcweir if( *p == ')' ) 347*cdf0e10cSrcweir p++; 348*cdf0e10cSrcweir if( refVar.Is() ) 349*cdf0e10cSrcweir refVar->SetParameters( refPar ); 350*cdf0e10cSrcweir } 351*cdf0e10cSrcweir } 352*cdf0e10cSrcweir else 353*cdf0e10cSrcweir SbxBase::SetError( SbxERR_NO_METHOD ); 354*cdf0e10cSrcweir } 355*cdf0e10cSrcweir *ppBuf = p; 356*cdf0e10cSrcweir if( refVar.Is() ) 357*cdf0e10cSrcweir refVar->AddRef(); 358*cdf0e10cSrcweir return refVar; 359*cdf0e10cSrcweir } 360*cdf0e10cSrcweir 361*cdf0e10cSrcweir // Hauptroutine 362*cdf0e10cSrcweir 363*cdf0e10cSrcweir SbxVariable* SbxObject::Execute( const XubString& rTxt ) 364*cdf0e10cSrcweir { 365*cdf0e10cSrcweir SbxVariable* pVar = NULL; 366*cdf0e10cSrcweir const xub_Unicode* p = rTxt.GetBuffer(); 367*cdf0e10cSrcweir for( ;; ) 368*cdf0e10cSrcweir { 369*cdf0e10cSrcweir p = SkipWhitespace( p ); 370*cdf0e10cSrcweir if( !*p ) 371*cdf0e10cSrcweir break; 372*cdf0e10cSrcweir if( *p++ != '[' ) 373*cdf0e10cSrcweir { 374*cdf0e10cSrcweir SetError( SbxERR_SYNTAX ); break; 375*cdf0e10cSrcweir } 376*cdf0e10cSrcweir pVar = Assign( this, this, &p ); 377*cdf0e10cSrcweir if( !pVar ) 378*cdf0e10cSrcweir break; 379*cdf0e10cSrcweir p = SkipWhitespace( p ); 380*cdf0e10cSrcweir if( *p++ != ']' ) 381*cdf0e10cSrcweir { 382*cdf0e10cSrcweir SetError( SbxERR_SYNTAX ); break; 383*cdf0e10cSrcweir } 384*cdf0e10cSrcweir } 385*cdf0e10cSrcweir return pVar; 386*cdf0e10cSrcweir } 387*cdf0e10cSrcweir 388*cdf0e10cSrcweir SbxVariable* SbxObject::FindQualified( const XubString& rName, SbxClassType t ) 389*cdf0e10cSrcweir { 390*cdf0e10cSrcweir SbxVariable* pVar = NULL; 391*cdf0e10cSrcweir const xub_Unicode* p = rName.GetBuffer(); 392*cdf0e10cSrcweir p = SkipWhitespace( p ); 393*cdf0e10cSrcweir if( !*p ) 394*cdf0e10cSrcweir return NULL;; 395*cdf0e10cSrcweir pVar = QualifiedName( this, this, &p, t ); 396*cdf0e10cSrcweir p = SkipWhitespace( p ); 397*cdf0e10cSrcweir if( *p ) 398*cdf0e10cSrcweir SetError( SbxERR_SYNTAX ); 399*cdf0e10cSrcweir return pVar; 400*cdf0e10cSrcweir } 401*cdf0e10cSrcweir 402