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_svx.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #ifndef _SVX_FMRESIDS_HRC 32*cdf0e10cSrcweir #include "svx/fmresids.hrc" 33*cdf0e10cSrcweir #endif 34*cdf0e10cSrcweir #include "svx/fmtools.hxx" 35*cdf0e10cSrcweir #include "svx/fmsrccfg.hxx" 36*cdf0e10cSrcweir #include <tools/debug.hxx> 37*cdf0e10cSrcweir #include <tools/diagnose_ex.h> 38*cdf0e10cSrcweir #include <tools/wldcrd.hxx> 39*cdf0e10cSrcweir #include <vcl/msgbox.hxx> 40*cdf0e10cSrcweir #include <tools/shl.hxx> 41*cdf0e10cSrcweir #include <svx/dialmgr.hxx> 42*cdf0e10cSrcweir #include <cppuhelper/servicefactory.hxx> 43*cdf0e10cSrcweir #include <vcl/svapp.hxx> 44*cdf0e10cSrcweir #include <unotools/textsearch.hxx> 45*cdf0e10cSrcweir #include <com/sun/star/util/SearchOptions.hpp> 46*cdf0e10cSrcweir #include <com/sun/star/util/SearchAlgorithms.hpp> 47*cdf0e10cSrcweir #include <com/sun/star/util/SearchResult.hpp> 48*cdf0e10cSrcweir #include <com/sun/star/util/SearchFlags.hpp> 49*cdf0e10cSrcweir #include <com/sun/star/lang/Locale.hpp> 50*cdf0e10cSrcweir #include <com/sun/star/i18n/TransliterationModules.hpp> 51*cdf0e10cSrcweir #include <com/sun/star/i18n/CollatorOptions.hpp> 52*cdf0e10cSrcweir 53*cdf0e10cSrcweir #ifndef _COM_SUN_STAR_SDDB_XCOLUMNSSUPPLIER_HPP_ 54*cdf0e10cSrcweir #include <com/sun/star/sdbcx/XColumnsSupplier.hpp> 55*cdf0e10cSrcweir #endif 56*cdf0e10cSrcweir #include <com/sun/star/util/XNumberFormatter.hpp> 57*cdf0e10cSrcweir #include <com/sun/star/util/NumberFormat.hpp> 58*cdf0e10cSrcweir #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 59*cdf0e10cSrcweir #include <com/sun/star/util/XNumberFormats.hpp> 60*cdf0e10cSrcweir #include <comphelper/processfactory.hxx> 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir #ifndef _SVX_FMPROP_HRC 63*cdf0e10cSrcweir #include "fmprop.hrc" 64*cdf0e10cSrcweir #endif 65*cdf0e10cSrcweir #include "fmservs.hxx" 66*cdf0e10cSrcweir #include "svx/fmsrcimp.hxx" 67*cdf0e10cSrcweir #include <svx/fmsearch.hxx> 68*cdf0e10cSrcweir 69*cdf0e10cSrcweir #include <comphelper/numbers.hxx> 70*cdf0e10cSrcweir #include <unotools/syslocale.hxx> 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir #define EQUAL_BOOKMARKS(a, b) a == b 73*cdf0e10cSrcweir 74*cdf0e10cSrcweir #define IFACECAST(c) ((const Reference< XInterface >&)c) 75*cdf0e10cSrcweir // SUN C52 has some ambiguities without this cast .... 76*cdf0e10cSrcweir 77*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 78*cdf0e10cSrcweir using namespace ::com::sun::star::util; 79*cdf0e10cSrcweir using namespace ::com::sun::star::lang; 80*cdf0e10cSrcweir using namespace ::com::sun::star::sdbc; 81*cdf0e10cSrcweir using namespace ::com::sun::star::i18n; 82*cdf0e10cSrcweir using namespace ::com::sun::star::beans; 83*cdf0e10cSrcweir using namespace ::svxform; 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir //======================================================================== 87*cdf0e10cSrcweir // = FmSearchThread 88*cdf0e10cSrcweir //------------------------------------------------------------------------ 89*cdf0e10cSrcweir void FmSearchThread::run() 90*cdf0e10cSrcweir { 91*cdf0e10cSrcweir m_pEngine->SearchNextImpl(); 92*cdf0e10cSrcweir }; 93*cdf0e10cSrcweir 94*cdf0e10cSrcweir //------------------------------------------------------------------------ 95*cdf0e10cSrcweir void FmSearchThread::onTerminated() 96*cdf0e10cSrcweir { 97*cdf0e10cSrcweir if (m_aTerminationHdl.IsSet()) 98*cdf0e10cSrcweir m_aTerminationHdl.Call(this); 99*cdf0e10cSrcweir delete this; 100*cdf0e10cSrcweir } 101*cdf0e10cSrcweir 102*cdf0e10cSrcweir //======================================================================== 103*cdf0e10cSrcweir // = FmRecordCountListener 104*cdf0e10cSrcweir 105*cdf0e10cSrcweir // SMART_UNO_IMPLEMENTATION(FmRecordCountListener, UsrObject); 106*cdf0e10cSrcweir 107*cdf0e10cSrcweir DBG_NAME(FmRecordCountListener); 108*cdf0e10cSrcweir //------------------------------------------------------------------------ 109*cdf0e10cSrcweir FmRecordCountListener::FmRecordCountListener(const Reference< ::com::sun::star::sdbc::XResultSet > & dbcCursor) 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir DBG_CTOR(FmRecordCountListener,NULL); 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir m_xListening = Reference< ::com::sun::star::beans::XPropertySet > (dbcCursor, UNO_QUERY); 114*cdf0e10cSrcweir if (!m_xListening.is()) 115*cdf0e10cSrcweir return; 116*cdf0e10cSrcweir 117*cdf0e10cSrcweir if (::comphelper::getBOOL(m_xListening->getPropertyValue(FM_PROP_ROWCOUNTFINAL))) 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir m_xListening = NULL; 120*cdf0e10cSrcweir // there's nothing to do as the record count is already known 121*cdf0e10cSrcweir return; 122*cdf0e10cSrcweir } 123*cdf0e10cSrcweir 124*cdf0e10cSrcweir m_xListening->addPropertyChangeListener(FM_PROP_ROWCOUNT, (::com::sun::star::beans::XPropertyChangeListener*)this); 125*cdf0e10cSrcweir } 126*cdf0e10cSrcweir 127*cdf0e10cSrcweir //------------------------------------------------------------------------ 128*cdf0e10cSrcweir Link FmRecordCountListener::SetPropChangeHandler(const Link& lnk) 129*cdf0e10cSrcweir { 130*cdf0e10cSrcweir Link lnkReturn = m_lnkWhoWantsToKnow; 131*cdf0e10cSrcweir m_lnkWhoWantsToKnow = lnk; 132*cdf0e10cSrcweir 133*cdf0e10cSrcweir if (m_xListening.is()) 134*cdf0e10cSrcweir NotifyCurrentCount(); 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir return lnkReturn; 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir 139*cdf0e10cSrcweir //------------------------------------------------------------------------ 140*cdf0e10cSrcweir FmRecordCountListener::~FmRecordCountListener() 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir DBG_DTOR(FmRecordCountListener,NULL); 144*cdf0e10cSrcweir } 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir //------------------------------------------------------------------------ 147*cdf0e10cSrcweir void FmRecordCountListener::DisConnect() 148*cdf0e10cSrcweir { 149*cdf0e10cSrcweir if(m_xListening.is()) 150*cdf0e10cSrcweir m_xListening->removePropertyChangeListener(FM_PROP_ROWCOUNT, (::com::sun::star::beans::XPropertyChangeListener*)this); 151*cdf0e10cSrcweir m_xListening = NULL; 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir //------------------------------------------------------------------------ 155*cdf0e10cSrcweir void SAL_CALL FmRecordCountListener::disposing(const ::com::sun::star::lang::EventObject& /*Source*/) throw( RuntimeException ) 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir DBG_ASSERT(m_xListening.is(), "FmRecordCountListener::disposing should never have been called without a propset !"); 158*cdf0e10cSrcweir DisConnect(); 159*cdf0e10cSrcweir } 160*cdf0e10cSrcweir 161*cdf0e10cSrcweir //------------------------------------------------------------------------ 162*cdf0e10cSrcweir void FmRecordCountListener::NotifyCurrentCount() 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir if (m_lnkWhoWantsToKnow.IsSet()) 165*cdf0e10cSrcweir { 166*cdf0e10cSrcweir DBG_ASSERT(m_xListening.is(), "FmRecordCountListener::NotifyCurrentCount : I have no propset ... !?"); 167*cdf0e10cSrcweir void* pTheCount = (void*)::comphelper::getINT32(m_xListening->getPropertyValue(FM_PROP_ROWCOUNT)); 168*cdf0e10cSrcweir m_lnkWhoWantsToKnow.Call(pTheCount); 169*cdf0e10cSrcweir } 170*cdf0e10cSrcweir } 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir //------------------------------------------------------------------------ 173*cdf0e10cSrcweir void FmRecordCountListener::propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& /*evt*/) throw(::com::sun::star::uno::RuntimeException) 174*cdf0e10cSrcweir { 175*cdf0e10cSrcweir NotifyCurrentCount(); 176*cdf0e10cSrcweir } 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir //======================================================================== 179*cdf0e10cSrcweir // FmSearchEngine - local classes 180*cdf0e10cSrcweir //------------------------------------------------------------------------ 181*cdf0e10cSrcweir SimpleTextWrapper::SimpleTextWrapper(const Reference< ::com::sun::star::awt::XTextComponent > & _xText) 182*cdf0e10cSrcweir :ControlTextWrapper(_xText.get()) 183*cdf0e10cSrcweir ,m_xText(_xText) 184*cdf0e10cSrcweir { 185*cdf0e10cSrcweir DBG_ASSERT(m_xText.is(), "FmSearchEngine::SimpleTextWrapper::SimpleTextWrapper : invalid argument !"); 186*cdf0e10cSrcweir } 187*cdf0e10cSrcweir 188*cdf0e10cSrcweir //------------------------------------------------------------------------ 189*cdf0e10cSrcweir ::rtl::OUString SimpleTextWrapper::getCurrentText() const 190*cdf0e10cSrcweir { 191*cdf0e10cSrcweir return m_xText->getText(); 192*cdf0e10cSrcweir } 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir //------------------------------------------------------------------------ 195*cdf0e10cSrcweir ListBoxWrapper::ListBoxWrapper(const Reference< ::com::sun::star::awt::XListBox > & _xBox) 196*cdf0e10cSrcweir :ControlTextWrapper(_xBox.get()) 197*cdf0e10cSrcweir ,m_xBox(_xBox) 198*cdf0e10cSrcweir { 199*cdf0e10cSrcweir DBG_ASSERT(m_xBox.is(), "FmSearchEngine::ListBoxWrapper::ListBoxWrapper : invalid argument !"); 200*cdf0e10cSrcweir } 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir //------------------------------------------------------------------------ 203*cdf0e10cSrcweir ::rtl::OUString ListBoxWrapper::getCurrentText() const 204*cdf0e10cSrcweir { 205*cdf0e10cSrcweir return m_xBox->getSelectedItem(); 206*cdf0e10cSrcweir } 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir //------------------------------------------------------------------------ 209*cdf0e10cSrcweir CheckBoxWrapper::CheckBoxWrapper(const Reference< ::com::sun::star::awt::XCheckBox > & _xBox) 210*cdf0e10cSrcweir :ControlTextWrapper(_xBox.get()) 211*cdf0e10cSrcweir ,m_xBox(_xBox) 212*cdf0e10cSrcweir { 213*cdf0e10cSrcweir DBG_ASSERT(m_xBox.is(), "FmSearchEngine::CheckBoxWrapper::CheckBoxWrapper : invalid argument !"); 214*cdf0e10cSrcweir } 215*cdf0e10cSrcweir 216*cdf0e10cSrcweir //------------------------------------------------------------------------ 217*cdf0e10cSrcweir ::rtl::OUString CheckBoxWrapper::getCurrentText() const 218*cdf0e10cSrcweir { 219*cdf0e10cSrcweir switch ((TriState)m_xBox->getState()) 220*cdf0e10cSrcweir { 221*cdf0e10cSrcweir case STATE_NOCHECK: return rtl::OUString::createFromAscii("0"); 222*cdf0e10cSrcweir case STATE_CHECK: return rtl::OUString::createFromAscii("1"); 223*cdf0e10cSrcweir default: break; 224*cdf0e10cSrcweir } 225*cdf0e10cSrcweir return rtl::OUString(); 226*cdf0e10cSrcweir } 227*cdf0e10cSrcweir 228*cdf0e10cSrcweir //======================================================================== 229*cdf0e10cSrcweir // = FmSearchEngine 230*cdf0e10cSrcweir //------------------------------------------------------------------------ 231*cdf0e10cSrcweir sal_Bool FmSearchEngine::MoveCursor() 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir sal_Bool bSuccess = sal_True; 234*cdf0e10cSrcweir try 235*cdf0e10cSrcweir { 236*cdf0e10cSrcweir if (m_bForward) 237*cdf0e10cSrcweir if (m_xSearchCursor.isLast()) 238*cdf0e10cSrcweir m_xSearchCursor.first(); 239*cdf0e10cSrcweir else 240*cdf0e10cSrcweir m_xSearchCursor.next(); 241*cdf0e10cSrcweir else 242*cdf0e10cSrcweir if (m_xSearchCursor.isFirst()) 243*cdf0e10cSrcweir { 244*cdf0e10cSrcweir FmRecordCountListener* prclListener = new FmRecordCountListener(m_xSearchCursor); 245*cdf0e10cSrcweir prclListener->acquire(); 246*cdf0e10cSrcweir prclListener->SetPropChangeHandler(LINK(this, FmSearchEngine, OnNewRecordCount)); 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir m_xSearchCursor.last(); 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir prclListener->DisConnect(); 251*cdf0e10cSrcweir prclListener->release(); 252*cdf0e10cSrcweir } 253*cdf0e10cSrcweir else 254*cdf0e10cSrcweir m_xSearchCursor.previous(); 255*cdf0e10cSrcweir } 256*cdf0e10cSrcweir catch(::com::sun::star::sdbc::SQLException e) 257*cdf0e10cSrcweir { 258*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 259*cdf0e10cSrcweir String sDebugMessage; 260*cdf0e10cSrcweir sDebugMessage.AssignAscii("FmSearchEngine::MoveCursor : catched a DatabaseException ("); 261*cdf0e10cSrcweir sDebugMessage += (const sal_Unicode*)e.SQLState; 262*cdf0e10cSrcweir sDebugMessage.AppendAscii(") !"); 263*cdf0e10cSrcweir DBG_ERROR(ByteString(sDebugMessage, RTL_TEXTENCODING_ASCII_US).GetBuffer()); 264*cdf0e10cSrcweir #endif 265*cdf0e10cSrcweir bSuccess = sal_False; 266*cdf0e10cSrcweir } 267*cdf0e10cSrcweir catch(Exception e) 268*cdf0e10cSrcweir { 269*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0 270*cdf0e10cSrcweir UniString sDebugMessage; 271*cdf0e10cSrcweir sDebugMessage.AssignAscii("FmSearchEngine::MoveCursor : catched an Exception ("); 272*cdf0e10cSrcweir sDebugMessage += (const sal_Unicode*)e.Message; 273*cdf0e10cSrcweir sDebugMessage.AppendAscii(") !"); 274*cdf0e10cSrcweir DBG_ERROR(ByteString(sDebugMessage, RTL_TEXTENCODING_ASCII_US).GetBuffer()); 275*cdf0e10cSrcweir #endif 276*cdf0e10cSrcweir bSuccess = sal_False; 277*cdf0e10cSrcweir } 278*cdf0e10cSrcweir catch(...) 279*cdf0e10cSrcweir { 280*cdf0e10cSrcweir DBG_ERROR("FmSearchEngine::MoveCursor : catched an unknown Exception !"); 281*cdf0e10cSrcweir bSuccess = sal_False; 282*cdf0e10cSrcweir } 283*cdf0e10cSrcweir 284*cdf0e10cSrcweir return bSuccess; 285*cdf0e10cSrcweir } 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir //------------------------------------------------------------------------ 288*cdf0e10cSrcweir sal_Bool FmSearchEngine::MoveField(sal_Int32& nPos, FieldCollectionIterator& iter, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd) 289*cdf0e10cSrcweir { 290*cdf0e10cSrcweir sal_Bool bSuccess(sal_True); 291*cdf0e10cSrcweir if (m_bForward) 292*cdf0e10cSrcweir { 293*cdf0e10cSrcweir ++iter; 294*cdf0e10cSrcweir ++nPos; 295*cdf0e10cSrcweir if (iter == iterEnd) 296*cdf0e10cSrcweir { 297*cdf0e10cSrcweir bSuccess = MoveCursor(); 298*cdf0e10cSrcweir iter = iterBegin; 299*cdf0e10cSrcweir nPos = 0; 300*cdf0e10cSrcweir } 301*cdf0e10cSrcweir } else 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir if (iter == iterBegin) 304*cdf0e10cSrcweir { 305*cdf0e10cSrcweir bSuccess = MoveCursor(); 306*cdf0e10cSrcweir iter = iterEnd; 307*cdf0e10cSrcweir nPos = iter-iterBegin; 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir --iter; 310*cdf0e10cSrcweir --nPos; 311*cdf0e10cSrcweir } 312*cdf0e10cSrcweir return bSuccess; 313*cdf0e10cSrcweir } 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir //------------------------------------------------------------------------ 316*cdf0e10cSrcweir void FmSearchEngine::BuildAndInsertFieldInfo(const Reference< ::com::sun::star::container::XIndexAccess > & xAllFields, sal_Int32 nField) 317*cdf0e10cSrcweir { 318*cdf0e10cSrcweir DBG_ASSERT( xAllFields.is() && ( nField >= 0 ) && ( nField < xAllFields->getCount() ), 319*cdf0e10cSrcweir "FmSearchEngine::BuildAndInsertFieldInfo: invalid field descriptor!" ); 320*cdf0e10cSrcweir 321*cdf0e10cSrcweir // das Feld selber 322*cdf0e10cSrcweir Reference< XInterface > xCurrentField; 323*cdf0e10cSrcweir xAllFields->getByIndex(nField) >>= xCurrentField; 324*cdf0e10cSrcweir 325*cdf0e10cSrcweir // von dem weiss ich jetzt, dass es den DatabaseRecord-Service unterstuetzt (hoffe ich) 326*cdf0e10cSrcweir // fuer den FormatKey und den Typ brauche ich das PropertySet 327*cdf0e10cSrcweir Reference< ::com::sun::star::beans::XPropertySet > xProperties(xCurrentField, UNO_QUERY); 328*cdf0e10cSrcweir 329*cdf0e10cSrcweir // die FieldInfo dazu aufbauen 330*cdf0e10cSrcweir FieldInfo fiCurrent; 331*cdf0e10cSrcweir fiCurrent.xContents = Reference< ::com::sun::star::sdb::XColumn > (xCurrentField, UNO_QUERY); 332*cdf0e10cSrcweir fiCurrent.nFormatKey = ::comphelper::getINT32(xProperties->getPropertyValue(FM_PROP_FORMATKEY)); 333*cdf0e10cSrcweir fiCurrent.bDoubleHandling = sal_False; 334*cdf0e10cSrcweir if (m_xFormatSupplier.is()) 335*cdf0e10cSrcweir { 336*cdf0e10cSrcweir Reference< ::com::sun::star::util::XNumberFormats > xNumberFormats(m_xFormatSupplier->getNumberFormats()); 337*cdf0e10cSrcweir 338*cdf0e10cSrcweir sal_Int16 nFormatType = ::comphelper::getNumberFormatType(xNumberFormats, fiCurrent.nFormatKey) & ~((sal_Int16)::com::sun::star::util::NumberFormat::DEFINED); 339*cdf0e10cSrcweir fiCurrent.bDoubleHandling = (nFormatType != ::com::sun::star::util::NumberFormat::TEXT); 340*cdf0e10cSrcweir } 341*cdf0e10cSrcweir 342*cdf0e10cSrcweir // und merken 343*cdf0e10cSrcweir m_arrUsedFields.insert(m_arrUsedFields.end(), fiCurrent); 344*cdf0e10cSrcweir 345*cdf0e10cSrcweir } 346*cdf0e10cSrcweir //------------------------------------------------------------------------ 347*cdf0e10cSrcweir ::rtl::OUString FmSearchEngine::FormatField(const FieldInfo& rField) 348*cdf0e10cSrcweir { 349*cdf0e10cSrcweir DBG_ASSERT(!m_bUsingTextComponents, "FmSearchEngine::FormatField : im UsingTextComponents-Mode bitte FormatField(sal_Int32) benutzen !"); 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir if (!m_xFormatter.is()) 352*cdf0e10cSrcweir return ::rtl::OUString(); 353*cdf0e10cSrcweir // sonst werden Datumsflder zum Beispiel zu irgendeinem Default-Wert formatiert 354*cdf0e10cSrcweir 355*cdf0e10cSrcweir ::rtl::OUString sReturn; 356*cdf0e10cSrcweir try 357*cdf0e10cSrcweir { 358*cdf0e10cSrcweir if (rField.bDoubleHandling) 359*cdf0e10cSrcweir { 360*cdf0e10cSrcweir double fValue = rField.xContents->getDouble(); 361*cdf0e10cSrcweir if (!rField.xContents->wasNull()) 362*cdf0e10cSrcweir sReturn = m_xFormatter->convertNumberToString(rField.nFormatKey, fValue); 363*cdf0e10cSrcweir } 364*cdf0e10cSrcweir else 365*cdf0e10cSrcweir { 366*cdf0e10cSrcweir ::rtl::OUString sValue = rField.xContents->getString(); 367*cdf0e10cSrcweir if (!rField.xContents->wasNull()) 368*cdf0e10cSrcweir sReturn = m_xFormatter->formatString(rField.nFormatKey, sValue); 369*cdf0e10cSrcweir } 370*cdf0e10cSrcweir } 371*cdf0e10cSrcweir catch(...) 372*cdf0e10cSrcweir { 373*cdf0e10cSrcweir } 374*cdf0e10cSrcweir 375*cdf0e10cSrcweir 376*cdf0e10cSrcweir return sReturn; 377*cdf0e10cSrcweir } 378*cdf0e10cSrcweir 379*cdf0e10cSrcweir //------------------------------------------------------------------------ 380*cdf0e10cSrcweir ::rtl::OUString FmSearchEngine::FormatField(sal_Int32 nWhich) 381*cdf0e10cSrcweir { 382*cdf0e10cSrcweir if (m_bUsingTextComponents) 383*cdf0e10cSrcweir { 384*cdf0e10cSrcweir DBG_ASSERT((sal_uInt32)nWhich < m_aControlTexts.size(), "FmSearchEngine::FormatField(sal_Int32) : invalid position !"); 385*cdf0e10cSrcweir DBG_ASSERT(m_aControlTexts[nWhich] != NULL, "FmSearchEngine::FormatField(sal_Int32) : invalid object in array !"); 386*cdf0e10cSrcweir DBG_ASSERT(m_aControlTexts[nWhich]->getControl().is(), "FmSearchEngine::FormatField : invalid control !"); 387*cdf0e10cSrcweir 388*cdf0e10cSrcweir if (m_nCurrentFieldIndex != -1) 389*cdf0e10cSrcweir { 390*cdf0e10cSrcweir DBG_ASSERT((nWhich == 0) || (nWhich == m_nCurrentFieldIndex), "FmSearchEngine::FormatField : Parameter nWhich ist ungueltig"); 391*cdf0e10cSrcweir // analoge Situation wie unten 392*cdf0e10cSrcweir nWhich = m_nCurrentFieldIndex; 393*cdf0e10cSrcweir } 394*cdf0e10cSrcweir 395*cdf0e10cSrcweir DBG_ASSERT((nWhich >= 0) && ((sal_uInt32)nWhich < m_aControlTexts.size()), 396*cdf0e10cSrcweir "FmSearchEngine::FormatField : invalid argument nWhich !"); 397*cdf0e10cSrcweir return m_aControlTexts[m_nCurrentFieldIndex == -1 ? nWhich : m_nCurrentFieldIndex]->getCurrentText(); 398*cdf0e10cSrcweir } 399*cdf0e10cSrcweir else 400*cdf0e10cSrcweir { 401*cdf0e10cSrcweir if (m_nCurrentFieldIndex != -1) 402*cdf0e10cSrcweir { 403*cdf0e10cSrcweir DBG_ASSERT((nWhich == 0) || (nWhich == m_nCurrentFieldIndex), "FmSearchEngine::FormatField : Parameter nWhich ist ungueltig"); 404*cdf0e10cSrcweir // ich bin im single-field-modus, da ist auch die richtige Feld-Nummer erlaubt, obwohl dann der richtige ::com::sun::star::sdbcx::Index 405*cdf0e10cSrcweir // fuer meinen Array-Zugriff natuerlich 0 ist 406*cdf0e10cSrcweir nWhich = 0; 407*cdf0e10cSrcweir } 408*cdf0e10cSrcweir 409*cdf0e10cSrcweir DBG_ASSERT((nWhich>=0) && (nWhich < (m_arrUsedFields.end() - m_arrUsedFields.begin())), 410*cdf0e10cSrcweir "FmSearchEngine::FormatField : Parameter nWhich ist ungueltig"); 411*cdf0e10cSrcweir return FormatField(m_arrUsedFields[nWhich]); 412*cdf0e10cSrcweir } 413*cdf0e10cSrcweir } 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir //------------------------------------------------------------------------ 416*cdf0e10cSrcweir FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchSpecial(sal_Bool _bSearchForNull, sal_Int32& nFieldPos, 417*cdf0e10cSrcweir FieldCollectionIterator& iterFieldLoop, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd) 418*cdf0e10cSrcweir { 419*cdf0e10cSrcweir // die Startposition merken 420*cdf0e10cSrcweir Any aStartMark; 421*cdf0e10cSrcweir try { aStartMark = m_xSearchCursor.getBookmark(); } 422*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; } 423*cdf0e10cSrcweir FieldCollectionIterator iterInitialField = iterFieldLoop; 424*cdf0e10cSrcweir 425*cdf0e10cSrcweir // -------------------------------------------------------------- 426*cdf0e10cSrcweir sal_Bool bFound(sal_False); 427*cdf0e10cSrcweir sal_Bool bMovedAround(sal_False); 428*cdf0e10cSrcweir do 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir if (m_eMode == SM_ALLOWSCHEDULE) //CHINA001 if (m_eMode == FmSearchDialog::SM_ALLOWSCHEDULE) 431*cdf0e10cSrcweir { 432*cdf0e10cSrcweir Application::Reschedule(); 433*cdf0e10cSrcweir Application::Reschedule(); 434*cdf0e10cSrcweir // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event 435*cdf0e10cSrcweir // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings 436*cdf0e10cSrcweir // or anything like that. So within each loop we create one user event and handle one user event (and no 437*cdf0e10cSrcweir // paintings and these), so the office seems to be frozen while searching. 438*cdf0e10cSrcweir // FS - 70226 - 02.12.99 439*cdf0e10cSrcweir } 440*cdf0e10cSrcweir 441*cdf0e10cSrcweir // der aktuell zu vergleichende Inhalt 442*cdf0e10cSrcweir iterFieldLoop->xContents->getString(); // needed for wasNull 443*cdf0e10cSrcweir bFound = _bSearchForNull == iterFieldLoop->xContents->wasNull(); 444*cdf0e10cSrcweir if (bFound) 445*cdf0e10cSrcweir break; 446*cdf0e10cSrcweir 447*cdf0e10cSrcweir // naechstes Feld (implizit naechster Datensatz, wenn noetig) 448*cdf0e10cSrcweir if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd)) 449*cdf0e10cSrcweir { // beim Bewegen auf das naechste Feld ging was schief ... weitermachen ist nicht drin, da das naechste Mal genau 450*cdf0e10cSrcweir // das selbe bestimmt wieder schief geht, also Abbruch 451*cdf0e10cSrcweir // vorher aber noch, damit das Weitersuchen an der aktuellen Position weitermacht : 452*cdf0e10cSrcweir try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); } 453*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } 454*cdf0e10cSrcweir m_iterPreviousLocField = iterFieldLoop; 455*cdf0e10cSrcweir // und wech 456*cdf0e10cSrcweir return SR_ERROR; 457*cdf0e10cSrcweir } 458*cdf0e10cSrcweir 459*cdf0e10cSrcweir Any aCurrentBookmark; 460*cdf0e10cSrcweir try { aCurrentBookmark = m_xSearchCursor.getBookmark(); } 461*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; } 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir bMovedAround = EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField); 464*cdf0e10cSrcweir 465*cdf0e10cSrcweir if (nFieldPos == 0) 466*cdf0e10cSrcweir // das heisst, ich habe mich auf einen neuen Datensatz bewegt 467*cdf0e10cSrcweir PropagateProgress(bMovedAround); 468*cdf0e10cSrcweir // if we moved to the starting position we don't have to propagate an 'overflow' message 469*cdf0e10cSrcweir // FS - 07.12.99 - 68530 470*cdf0e10cSrcweir 471*cdf0e10cSrcweir // abbrechen gefordert ? 472*cdf0e10cSrcweir if (CancelRequested()) 473*cdf0e10cSrcweir return SR_CANCELED; 474*cdf0e10cSrcweir 475*cdf0e10cSrcweir } while (!bMovedAround); 476*cdf0e10cSrcweir 477*cdf0e10cSrcweir return bFound ? SR_FOUND : SR_NOTFOUND; 478*cdf0e10cSrcweir } 479*cdf0e10cSrcweir 480*cdf0e10cSrcweir //------------------------------------------------------------------------ 481*cdf0e10cSrcweir FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchWildcard(const ::rtl::OUString& strExpression, sal_Int32& nFieldPos, 482*cdf0e10cSrcweir FieldCollectionIterator& iterFieldLoop, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd) 483*cdf0e10cSrcweir { 484*cdf0e10cSrcweir // die Startposition merken 485*cdf0e10cSrcweir Any aStartMark; 486*cdf0e10cSrcweir try { aStartMark = m_xSearchCursor.getBookmark(); } 487*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; } 488*cdf0e10cSrcweir FieldCollectionIterator iterInitialField = iterFieldLoop; 489*cdf0e10cSrcweir 490*cdf0e10cSrcweir WildCard aSearchExpression(strExpression); 491*cdf0e10cSrcweir 492*cdf0e10cSrcweir // -------------------------------------------------------------- 493*cdf0e10cSrcweir sal_Bool bFound(sal_False); 494*cdf0e10cSrcweir sal_Bool bMovedAround(sal_False); 495*cdf0e10cSrcweir do 496*cdf0e10cSrcweir { 497*cdf0e10cSrcweir if (m_eMode == SM_ALLOWSCHEDULE) //CHINA001 if (m_eMode == FmSearchDialog::SM_ALLOWSCHEDULE) 498*cdf0e10cSrcweir { 499*cdf0e10cSrcweir Application::Reschedule(); 500*cdf0e10cSrcweir Application::Reschedule(); 501*cdf0e10cSrcweir // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event 502*cdf0e10cSrcweir // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings 503*cdf0e10cSrcweir // or anything like that. So within each loop we create one user event and hanel one user event (and no 504*cdf0e10cSrcweir // paintings and these), so the office seems to be frozen while searching. 505*cdf0e10cSrcweir // FS - 70226 - 02.12.99 506*cdf0e10cSrcweir } 507*cdf0e10cSrcweir 508*cdf0e10cSrcweir // der aktuell zu vergleichende Inhalt 509*cdf0e10cSrcweir ::rtl::OUString sCurrentCheck; 510*cdf0e10cSrcweir if (m_bFormatter) 511*cdf0e10cSrcweir sCurrentCheck = FormatField(nFieldPos); 512*cdf0e10cSrcweir else 513*cdf0e10cSrcweir sCurrentCheck = iterFieldLoop->xContents->getString(); 514*cdf0e10cSrcweir 515*cdf0e10cSrcweir if (!GetCaseSensitive()) 516*cdf0e10cSrcweir // norm the string 517*cdf0e10cSrcweir m_aCharacterClassficator.toLower_rtl(sCurrentCheck); 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir // jetzt ist der Test einfach ... 520*cdf0e10cSrcweir bFound = aSearchExpression.Matches(sCurrentCheck); 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir if (bFound) 523*cdf0e10cSrcweir break; 524*cdf0e10cSrcweir 525*cdf0e10cSrcweir // naechstes Feld (implizit naechster Datensatz, wenn noetig) 526*cdf0e10cSrcweir if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd)) 527*cdf0e10cSrcweir { // beim Bewegen auf das naechste Feld ging was schief ... weitermachen ist nicht drin, da das naechste Mal genau 528*cdf0e10cSrcweir // das selbe bestimmt wieder schief geht, also Abbruch 529*cdf0e10cSrcweir // vorher aber noch, damit das Weitersuchen an der aktuellen Position weitermacht : 530*cdf0e10cSrcweir try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); } 531*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } 532*cdf0e10cSrcweir m_iterPreviousLocField = iterFieldLoop; 533*cdf0e10cSrcweir // und wech 534*cdf0e10cSrcweir return SR_ERROR; 535*cdf0e10cSrcweir } 536*cdf0e10cSrcweir 537*cdf0e10cSrcweir Any aCurrentBookmark; 538*cdf0e10cSrcweir try { aCurrentBookmark = m_xSearchCursor.getBookmark(); } 539*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; } 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir bMovedAround = EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField); 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir if (nFieldPos == 0) 544*cdf0e10cSrcweir // das heisst, ich habe mich auf einen neuen Datensatz bewegt 545*cdf0e10cSrcweir PropagateProgress(bMovedAround); 546*cdf0e10cSrcweir // if we moved to the starting position we don't have to propagate an 'overflow' message 547*cdf0e10cSrcweir // FS - 07.12.99 - 68530 548*cdf0e10cSrcweir 549*cdf0e10cSrcweir // abbrechen gefordert ? 550*cdf0e10cSrcweir if (CancelRequested()) 551*cdf0e10cSrcweir return SR_CANCELED; 552*cdf0e10cSrcweir 553*cdf0e10cSrcweir } while (!bMovedAround); 554*cdf0e10cSrcweir 555*cdf0e10cSrcweir return bFound ? SR_FOUND : SR_NOTFOUND; 556*cdf0e10cSrcweir } 557*cdf0e10cSrcweir 558*cdf0e10cSrcweir //------------------------------------------------------------------------ 559*cdf0e10cSrcweir FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchRegularApprox(const ::rtl::OUString& strExpression, sal_Int32& nFieldPos, 560*cdf0e10cSrcweir FieldCollectionIterator& iterFieldLoop, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd) 561*cdf0e10cSrcweir { 562*cdf0e10cSrcweir DBG_ASSERT(m_bLevenshtein || m_bRegular, 563*cdf0e10cSrcweir "FmSearchEngine::SearchRegularApprox : ungueltiger Suchmodus !"); 564*cdf0e10cSrcweir DBG_ASSERT(!m_bLevenshtein || !m_bRegular, 565*cdf0e10cSrcweir "FmSearchEngine::SearchRegularApprox : kann nicht nach regulaeren Ausdruecken und nach Aehnlichkeiten gleichzeitig suchen !"); 566*cdf0e10cSrcweir 567*cdf0e10cSrcweir // Startposition merken 568*cdf0e10cSrcweir Any aStartMark; 569*cdf0e10cSrcweir try { aStartMark = m_xSearchCursor.getBookmark(); } 570*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; } 571*cdf0e10cSrcweir FieldCollectionIterator iterInitialField = iterFieldLoop; 572*cdf0e10cSrcweir 573*cdf0e10cSrcweir // Parameter sammeln 574*cdf0e10cSrcweir SearchOptions aParam; 575*cdf0e10cSrcweir aParam.algorithmType = m_bRegular ? SearchAlgorithms_REGEXP : SearchAlgorithms_APPROXIMATE; 576*cdf0e10cSrcweir aParam.searchFlag = 0; 577*cdf0e10cSrcweir aParam.transliterateFlags = GetTransliterationFlags(); 578*cdf0e10cSrcweir if ( !GetTransliteration() ) 579*cdf0e10cSrcweir { // if transliteration is not enabled, the only flags which matter are IGNORE_CASE and IGNORE_WIDTH 580*cdf0e10cSrcweir aParam.transliterateFlags &= TransliterationModules_IGNORE_CASE | TransliterationModules_IGNORE_WIDTH; 581*cdf0e10cSrcweir } 582*cdf0e10cSrcweir if (m_bLevenshtein) 583*cdf0e10cSrcweir { 584*cdf0e10cSrcweir if (m_bLevRelaxed) 585*cdf0e10cSrcweir aParam.searchFlag |= SearchFlags::LEV_RELAXED; 586*cdf0e10cSrcweir aParam.changedChars = m_nLevOther; 587*cdf0e10cSrcweir aParam.deletedChars = m_nLevShorter; 588*cdf0e10cSrcweir aParam.insertedChars = m_nLevLonger; 589*cdf0e10cSrcweir } 590*cdf0e10cSrcweir aParam.searchString = strExpression; 591*cdf0e10cSrcweir aParam.Locale = SvtSysLocale().GetLocaleData().getLocale(); 592*cdf0e10cSrcweir ::utl::TextSearch aLocalEngine(aParam); 593*cdf0e10cSrcweir 594*cdf0e10cSrcweir // -------------------------------------------------------------- 595*cdf0e10cSrcweir bool bFound = false; 596*cdf0e10cSrcweir sal_Bool bMovedAround(sal_False); 597*cdf0e10cSrcweir do 598*cdf0e10cSrcweir { 599*cdf0e10cSrcweir if (m_eMode == SM_ALLOWSCHEDULE) //CHINA001 if (m_eMode == FmSearchDialog::SM_ALLOWSCHEDULE) 600*cdf0e10cSrcweir { 601*cdf0e10cSrcweir Application::Reschedule(); 602*cdf0e10cSrcweir Application::Reschedule(); 603*cdf0e10cSrcweir // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event 604*cdf0e10cSrcweir // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings 605*cdf0e10cSrcweir // or anything like that. So within each loop we create one user event and handle one user event (and no 606*cdf0e10cSrcweir // paintings and these), so the office seems to be frozen while searching. 607*cdf0e10cSrcweir // FS - 70226 - 02.12.99 608*cdf0e10cSrcweir } 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir // der aktuell zu vergleichende Inhalt 611*cdf0e10cSrcweir ::rtl::OUString sCurrentCheck; 612*cdf0e10cSrcweir if (m_bFormatter) 613*cdf0e10cSrcweir sCurrentCheck = FormatField(nFieldPos); 614*cdf0e10cSrcweir else 615*cdf0e10cSrcweir sCurrentCheck = iterFieldLoop->xContents->getString(); 616*cdf0e10cSrcweir 617*cdf0e10cSrcweir // (don't care about case here, this is done by the TextSearch object, 'cause we passed our case parameter to it) 618*cdf0e10cSrcweir 619*cdf0e10cSrcweir xub_StrLen nStart = 0, nEnd = (xub_StrLen)sCurrentCheck.getLength(); 620*cdf0e10cSrcweir bFound = aLocalEngine.SearchFrwrd(sCurrentCheck, &nStart, &nEnd); 621*cdf0e10cSrcweir // das heisst hier 'forward' aber das bezieht sich nur auf die Suche innerhalb von sCurrentCheck, hat also mit 622*cdf0e10cSrcweir // der Richtung meines Datensatz-Durchwanderns nix zu tun (darum kuemmert sich MoveField) 623*cdf0e10cSrcweir 624*cdf0e10cSrcweir // checken, ob die Position stimmt 625*cdf0e10cSrcweir if (bFound) 626*cdf0e10cSrcweir { 627*cdf0e10cSrcweir switch (m_nPosition) 628*cdf0e10cSrcweir { 629*cdf0e10cSrcweir case MATCHING_WHOLETEXT : 630*cdf0e10cSrcweir if (nEnd != sCurrentCheck.getLength()) 631*cdf0e10cSrcweir { 632*cdf0e10cSrcweir bFound = false; 633*cdf0e10cSrcweir break; 634*cdf0e10cSrcweir } 635*cdf0e10cSrcweir // laeuft in den naechsten Case rein ! 636*cdf0e10cSrcweir case MATCHING_BEGINNING : 637*cdf0e10cSrcweir if (nStart != 0) 638*cdf0e10cSrcweir bFound = false; 639*cdf0e10cSrcweir break; 640*cdf0e10cSrcweir case MATCHING_END : 641*cdf0e10cSrcweir if (nEnd != sCurrentCheck.getLength()) 642*cdf0e10cSrcweir bFound = false; 643*cdf0e10cSrcweir break; 644*cdf0e10cSrcweir } 645*cdf0e10cSrcweir } 646*cdf0e10cSrcweir 647*cdf0e10cSrcweir if (bFound) // immer noch ? 648*cdf0e10cSrcweir break; 649*cdf0e10cSrcweir 650*cdf0e10cSrcweir // naechstes Feld (implizit naechster Datensatz, wenn noetig) 651*cdf0e10cSrcweir if (!MoveField(nFieldPos, iterFieldLoop, iterBegin, iterEnd)) 652*cdf0e10cSrcweir { // beim Bewegen auf das naechste Feld ging was schief ... weitermachen ist nicht drin, da das naechste Mal genau 653*cdf0e10cSrcweir // das selbe bestimmt wieder schief geht, also Abbruch (ohne Fehlermeldung, von der erwarte ich, dass sie im Move 654*cdf0e10cSrcweir // angezeigt wurde) 655*cdf0e10cSrcweir // vorher aber noch, damit das Weitersuchen an der aktuellen Position weitermacht : 656*cdf0e10cSrcweir try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); } 657*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } 658*cdf0e10cSrcweir m_iterPreviousLocField = iterFieldLoop; 659*cdf0e10cSrcweir // und wech 660*cdf0e10cSrcweir return SR_ERROR; 661*cdf0e10cSrcweir } 662*cdf0e10cSrcweir 663*cdf0e10cSrcweir Any aCurrentBookmark; 664*cdf0e10cSrcweir try { aCurrentBookmark = m_xSearchCursor.getBookmark(); } 665*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); return SR_ERROR; } 666*cdf0e10cSrcweir bMovedAround = EQUAL_BOOKMARKS(aStartMark, aCurrentBookmark) && (iterFieldLoop == iterInitialField); 667*cdf0e10cSrcweir 668*cdf0e10cSrcweir if (nFieldPos == 0) 669*cdf0e10cSrcweir // das heisst, ich habe mich auf einen neuen Datensatz bewegt 670*cdf0e10cSrcweir PropagateProgress(bMovedAround); 671*cdf0e10cSrcweir // if we moved to the starting position we don't have to propagate an 'overflow' message 672*cdf0e10cSrcweir // FS - 07.12.99 - 68530 673*cdf0e10cSrcweir 674*cdf0e10cSrcweir // abbrechen gefordert ? 675*cdf0e10cSrcweir if (CancelRequested()) 676*cdf0e10cSrcweir return SR_CANCELED; 677*cdf0e10cSrcweir 678*cdf0e10cSrcweir } while (!bMovedAround); 679*cdf0e10cSrcweir 680*cdf0e10cSrcweir return bFound ? SR_FOUND : SR_NOTFOUND; 681*cdf0e10cSrcweir } 682*cdf0e10cSrcweir 683*cdf0e10cSrcweir 684*cdf0e10cSrcweir DBG_NAME(FmSearchEngine); 685*cdf0e10cSrcweir //------------------------------------------------------------------------ 686*cdf0e10cSrcweir FmSearchEngine::FmSearchEngine(const Reference< XMultiServiceFactory >& _rxORB, 687*cdf0e10cSrcweir const Reference< XResultSet > & xCursor, const ::rtl::OUString& sVisibleFields, 688*cdf0e10cSrcweir const Reference< XNumberFormatsSupplier > & xFormatSupplier, FMSEARCH_MODE eMode)//CHINA001 const Reference< XNumberFormatsSupplier > & xFormatSupplier, FmSearchDialog::SEARCH_MODE eMode) 689*cdf0e10cSrcweir :m_xSearchCursor(xCursor) 690*cdf0e10cSrcweir ,m_xFormatSupplier(xFormatSupplier) 691*cdf0e10cSrcweir ,m_aCharacterClassficator( _rxORB, SvtSysLocale().GetLocaleData().getLocale() ) 692*cdf0e10cSrcweir ,m_aStringCompare( _rxORB ) 693*cdf0e10cSrcweir ,m_nCurrentFieldIndex(-2) // -1 hat schon eine Bedeutung, also nehme ich -2 fuer 'ungueltig' 694*cdf0e10cSrcweir ,m_bUsingTextComponents(sal_False) 695*cdf0e10cSrcweir ,m_eSearchForType(SEARCHFOR_STRING) 696*cdf0e10cSrcweir ,m_srResult(SR_FOUND) 697*cdf0e10cSrcweir ,m_bSearchingCurrently(sal_False) 698*cdf0e10cSrcweir ,m_bCancelAsynchRequest(sal_False) 699*cdf0e10cSrcweir ,m_eMode(eMode) 700*cdf0e10cSrcweir ,m_bFormatter(sal_False) 701*cdf0e10cSrcweir ,m_bForward(sal_False) 702*cdf0e10cSrcweir ,m_bWildcard(sal_False) 703*cdf0e10cSrcweir ,m_bRegular(sal_False) 704*cdf0e10cSrcweir ,m_bLevenshtein(sal_False) 705*cdf0e10cSrcweir ,m_bTransliteration(sal_False) 706*cdf0e10cSrcweir ,m_bLevRelaxed(sal_False) 707*cdf0e10cSrcweir ,m_nLevOther(0) 708*cdf0e10cSrcweir ,m_nLevShorter(0) 709*cdf0e10cSrcweir ,m_nLevLonger(0) 710*cdf0e10cSrcweir ,m_nPosition(MATCHING_ANYWHERE) 711*cdf0e10cSrcweir ,m_nTransliterationFlags(0) 712*cdf0e10cSrcweir { 713*cdf0e10cSrcweir DBG_CTOR(FmSearchEngine,NULL); 714*cdf0e10cSrcweir 715*cdf0e10cSrcweir m_xFormatter = Reference< ::com::sun::star::util::XNumberFormatter > (::comphelper::getProcessServiceFactory() 716*cdf0e10cSrcweir ->createInstance(FM_NUMBER_FORMATTER), UNO_QUERY); 717*cdf0e10cSrcweir if (m_xFormatter.is()) 718*cdf0e10cSrcweir m_xFormatter->attachNumberFormatsSupplier(m_xFormatSupplier); 719*cdf0e10cSrcweir 720*cdf0e10cSrcweir Init(sVisibleFields); 721*cdf0e10cSrcweir } 722*cdf0e10cSrcweir 723*cdf0e10cSrcweir //------------------------------------------------------------------------ 724*cdf0e10cSrcweir FmSearchEngine::FmSearchEngine(const Reference< XMultiServiceFactory >& _rxORB, 725*cdf0e10cSrcweir const Reference< XResultSet > & xCursor, const ::rtl::OUString& sVisibleFields, 726*cdf0e10cSrcweir const InterfaceArray& arrFields, FMSEARCH_MODE eMode)//CHINA001 const InterfaceArray& arrFields, FmSearchDialog::SEARCH_MODE eMode) 727*cdf0e10cSrcweir :m_xSearchCursor(xCursor) 728*cdf0e10cSrcweir ,m_aCharacterClassficator( _rxORB, SvtSysLocale().GetLocaleData().getLocale() ) 729*cdf0e10cSrcweir ,m_aStringCompare( _rxORB ) 730*cdf0e10cSrcweir ,m_nCurrentFieldIndex(-2) // -1 hat schon eine Bedeutung, also nehme ich -2 fuer 'ungueltig' 731*cdf0e10cSrcweir ,m_bUsingTextComponents(sal_True) 732*cdf0e10cSrcweir ,m_xOriginalIterator(xCursor) 733*cdf0e10cSrcweir ,m_xClonedIterator(m_xOriginalIterator, sal_True) 734*cdf0e10cSrcweir ,m_eSearchForType(SEARCHFOR_STRING) 735*cdf0e10cSrcweir ,m_srResult(SR_FOUND) 736*cdf0e10cSrcweir ,m_bSearchingCurrently(sal_False) 737*cdf0e10cSrcweir ,m_bCancelAsynchRequest(sal_False) 738*cdf0e10cSrcweir ,m_eMode(eMode) 739*cdf0e10cSrcweir ,m_bFormatter(sal_True) // das muss konsistent sein mit m_xSearchCursor, der i.A. == m_xOriginalIterator ist 740*cdf0e10cSrcweir ,m_bForward(sal_False) 741*cdf0e10cSrcweir ,m_bWildcard(sal_False) 742*cdf0e10cSrcweir ,m_bRegular(sal_False) 743*cdf0e10cSrcweir ,m_bLevenshtein(sal_False) 744*cdf0e10cSrcweir ,m_bTransliteration(sal_False) 745*cdf0e10cSrcweir ,m_bLevRelaxed(sal_False) 746*cdf0e10cSrcweir ,m_nLevOther(0) 747*cdf0e10cSrcweir ,m_nLevShorter(0) 748*cdf0e10cSrcweir ,m_nLevLonger(0) 749*cdf0e10cSrcweir ,m_nPosition(MATCHING_ANYWHERE) 750*cdf0e10cSrcweir ,m_nTransliterationFlags(0) 751*cdf0e10cSrcweir { 752*cdf0e10cSrcweir DBG_CTOR(FmSearchEngine,NULL); 753*cdf0e10cSrcweir 754*cdf0e10cSrcweir fillControlTexts(arrFields); 755*cdf0e10cSrcweir Init(sVisibleFields); 756*cdf0e10cSrcweir } 757*cdf0e10cSrcweir 758*cdf0e10cSrcweir //------------------------------------------------------------------------ 759*cdf0e10cSrcweir FmSearchEngine::~FmSearchEngine() 760*cdf0e10cSrcweir { 761*cdf0e10cSrcweir clearControlTexts(); 762*cdf0e10cSrcweir 763*cdf0e10cSrcweir DBG_DTOR(FmSearchEngine,NULL); 764*cdf0e10cSrcweir } 765*cdf0e10cSrcweir 766*cdf0e10cSrcweir //------------------------------------------------------------------------ 767*cdf0e10cSrcweir void FmSearchEngine::SetIgnoreWidthCJK(sal_Bool bSet) 768*cdf0e10cSrcweir { 769*cdf0e10cSrcweir if (bSet) 770*cdf0e10cSrcweir m_nTransliterationFlags |= TransliterationModules_IGNORE_WIDTH; 771*cdf0e10cSrcweir else 772*cdf0e10cSrcweir m_nTransliterationFlags &= ~TransliterationModules_IGNORE_WIDTH; 773*cdf0e10cSrcweir } 774*cdf0e10cSrcweir 775*cdf0e10cSrcweir //------------------------------------------------------------------------ 776*cdf0e10cSrcweir sal_Bool FmSearchEngine::GetIgnoreWidthCJK() const 777*cdf0e10cSrcweir { 778*cdf0e10cSrcweir return 0 != (m_nTransliterationFlags & TransliterationModules_IGNORE_WIDTH); 779*cdf0e10cSrcweir } 780*cdf0e10cSrcweir 781*cdf0e10cSrcweir //------------------------------------------------------------------------ 782*cdf0e10cSrcweir void FmSearchEngine::SetCaseSensitive(sal_Bool bSet) 783*cdf0e10cSrcweir { 784*cdf0e10cSrcweir if (bSet) 785*cdf0e10cSrcweir m_nTransliterationFlags &= ~TransliterationModules_IGNORE_CASE; 786*cdf0e10cSrcweir else 787*cdf0e10cSrcweir m_nTransliterationFlags |= TransliterationModules_IGNORE_CASE; 788*cdf0e10cSrcweir } 789*cdf0e10cSrcweir 790*cdf0e10cSrcweir //------------------------------------------------------------------------ 791*cdf0e10cSrcweir sal_Bool FmSearchEngine::GetCaseSensitive() const 792*cdf0e10cSrcweir { 793*cdf0e10cSrcweir return 0 == (m_nTransliterationFlags & TransliterationModules_IGNORE_CASE); 794*cdf0e10cSrcweir } 795*cdf0e10cSrcweir 796*cdf0e10cSrcweir //------------------------------------------------------------------------ 797*cdf0e10cSrcweir void FmSearchEngine::clearControlTexts() 798*cdf0e10cSrcweir { 799*cdf0e10cSrcweir for ( ControlTextSuppliersIterator aIter = m_aControlTexts.begin(); 800*cdf0e10cSrcweir aIter < m_aControlTexts.end(); 801*cdf0e10cSrcweir ++aIter 802*cdf0e10cSrcweir ) 803*cdf0e10cSrcweir { 804*cdf0e10cSrcweir delete *aIter; 805*cdf0e10cSrcweir } 806*cdf0e10cSrcweir m_aControlTexts.clear(); 807*cdf0e10cSrcweir } 808*cdf0e10cSrcweir 809*cdf0e10cSrcweir //------------------------------------------------------------------------ 810*cdf0e10cSrcweir void FmSearchEngine::fillControlTexts(const InterfaceArray& arrFields) 811*cdf0e10cSrcweir { 812*cdf0e10cSrcweir clearControlTexts(); 813*cdf0e10cSrcweir Reference< XInterface > xCurrent; 814*cdf0e10cSrcweir for (sal_uInt32 i=0; i<arrFields.size(); ++i) 815*cdf0e10cSrcweir { 816*cdf0e10cSrcweir xCurrent = arrFields.at(i); 817*cdf0e10cSrcweir DBG_ASSERT(xCurrent.is(), "FmSearchEngine::fillControlTexts : invalid field interface !"); 818*cdf0e10cSrcweir // check which type of control this is 819*cdf0e10cSrcweir Reference< ::com::sun::star::awt::XTextComponent > xAsText(xCurrent, UNO_QUERY); 820*cdf0e10cSrcweir if (xAsText.is()) 821*cdf0e10cSrcweir { 822*cdf0e10cSrcweir m_aControlTexts.insert(m_aControlTexts.end(), new SimpleTextWrapper(xAsText)); 823*cdf0e10cSrcweir continue; 824*cdf0e10cSrcweir } 825*cdf0e10cSrcweir 826*cdf0e10cSrcweir Reference< ::com::sun::star::awt::XListBox > xAsListBox(xCurrent, UNO_QUERY); 827*cdf0e10cSrcweir if (xAsListBox.is()) 828*cdf0e10cSrcweir { 829*cdf0e10cSrcweir m_aControlTexts.insert(m_aControlTexts.end(), new ListBoxWrapper(xAsListBox)); 830*cdf0e10cSrcweir continue; 831*cdf0e10cSrcweir } 832*cdf0e10cSrcweir 833*cdf0e10cSrcweir Reference< ::com::sun::star::awt::XCheckBox > xAsCheckBox(xCurrent, UNO_QUERY); 834*cdf0e10cSrcweir DBG_ASSERT(xAsCheckBox.is(), "FmSearchEngine::fillControlTexts : invalid field interface (no supported type) !"); 835*cdf0e10cSrcweir // we don't have any more options ... 836*cdf0e10cSrcweir m_aControlTexts.insert(m_aControlTexts.end(), new CheckBoxWrapper(xAsCheckBox)); 837*cdf0e10cSrcweir } 838*cdf0e10cSrcweir } 839*cdf0e10cSrcweir 840*cdf0e10cSrcweir //------------------------------------------------------------------------ 841*cdf0e10cSrcweir void FmSearchEngine::Init(const ::rtl::OUString& sVisibleFields) 842*cdf0e10cSrcweir { 843*cdf0e10cSrcweir // analyze the fields 844*cdf0e10cSrcweir // additionally, create the mapping: because the list of used columns can be shorter than the list 845*cdf0e10cSrcweir // of columns of the cursor, we need a mapping: "used column numer n" -> "cursor column m" 846*cdf0e10cSrcweir m_arrFieldMapping.clear(); 847*cdf0e10cSrcweir 848*cdf0e10cSrcweir // important: The case of the columns does not need to be exact - for instance: 849*cdf0e10cSrcweir // - a user created a form which works on a table, for which the driver returns a column name "COLUMN" 850*cdf0e10cSrcweir // - the driver itself works case-insensitve with column names 851*cdf0e10cSrcweir // - a control in the form is bound to "column" - not the different case 852*cdf0e10cSrcweir // In such a scenario, the form and the field would work okay, but we here need to case for the different case 853*cdf0e10cSrcweir // explicitly 854*cdf0e10cSrcweir // 2003-01-09 - #i8755# - fs@openoffice.org 855*cdf0e10cSrcweir 856*cdf0e10cSrcweir // so first of all, check if the database handles identifiers case sensitive 857*cdf0e10cSrcweir Reference< XConnection > xConn; 858*cdf0e10cSrcweir Reference< XDatabaseMetaData > xMeta; 859*cdf0e10cSrcweir Reference< XPropertySet > xCursorProps( IFACECAST( m_xSearchCursor ), UNO_QUERY ); 860*cdf0e10cSrcweir if ( xCursorProps.is() ) 861*cdf0e10cSrcweir { 862*cdf0e10cSrcweir try 863*cdf0e10cSrcweir { 864*cdf0e10cSrcweir xCursorProps->getPropertyValue( FM_PROP_ACTIVE_CONNECTION ) >>= xConn; 865*cdf0e10cSrcweir } 866*cdf0e10cSrcweir catch( Exception& ) { /* silent this - will be asserted below */ } 867*cdf0e10cSrcweir } 868*cdf0e10cSrcweir if ( xConn.is() ) 869*cdf0e10cSrcweir xMeta = xConn->getMetaData(); 870*cdf0e10cSrcweir OSL_ENSURE( xMeta.is(), "FmSearchEngine::Init: very strange cursor (could not derive connection meta data from it)!" ); 871*cdf0e10cSrcweir 872*cdf0e10cSrcweir sal_Bool bCaseSensitiveIdentifiers = sal_True; // assume case sensivity 873*cdf0e10cSrcweir if ( xMeta.is() ) 874*cdf0e10cSrcweir bCaseSensitiveIdentifiers = xMeta->supportsMixedCaseQuotedIdentifiers(); 875*cdf0e10cSrcweir 876*cdf0e10cSrcweir // now that we have this information, we need a collator which is able to case (in)sentively compare strings 877*cdf0e10cSrcweir m_aStringCompare.loadDefaultCollator( SvtSysLocale().GetLocaleData().getLocale(), 878*cdf0e10cSrcweir bCaseSensitiveIdentifiers ? 0 : ::com::sun::star::i18n::CollatorOptions::CollatorOptions_IGNORE_CASE ); 879*cdf0e10cSrcweir 880*cdf0e10cSrcweir try 881*cdf0e10cSrcweir { 882*cdf0e10cSrcweir // der Cursor kann mir einen Record (als PropertySet) liefern, dieser unterstuetzt den DatabaseRecord-Service 883*cdf0e10cSrcweir Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xSupplyCols(IFACECAST(m_xSearchCursor), UNO_QUERY); 884*cdf0e10cSrcweir DBG_ASSERT(xSupplyCols.is(), "FmSearchEngine::Init : invalid cursor (no columns supplier) !"); 885*cdf0e10cSrcweir Reference< ::com::sun::star::container::XNameAccess > xAllFieldNames = xSupplyCols->getColumns(); 886*cdf0e10cSrcweir Sequence< ::rtl::OUString > seqFieldNames = xAllFieldNames->getElementNames(); 887*cdf0e10cSrcweir ::rtl::OUString* pFieldNames = seqFieldNames.getArray(); 888*cdf0e10cSrcweir 889*cdf0e10cSrcweir 890*cdf0e10cSrcweir ::rtl::OUString sCurrentField; 891*cdf0e10cSrcweir UniString sVis(sVisibleFields.getStr()); 892*cdf0e10cSrcweir xub_StrLen nLen = sVis.GetTokenCount(); 893*cdf0e10cSrcweir for (xub_StrLen i=0; i<nLen; ++i) 894*cdf0e10cSrcweir { 895*cdf0e10cSrcweir sCurrentField = sVis.GetToken(i); 896*cdf0e10cSrcweir 897*cdf0e10cSrcweir // in der Feld-Sammlung suchen 898*cdf0e10cSrcweir sal_Int32 nFoundIndex = -1; 899*cdf0e10cSrcweir for (sal_Int32 j=0; j<seqFieldNames.getLength(); ++j, ++pFieldNames) 900*cdf0e10cSrcweir { 901*cdf0e10cSrcweir if ( 0 == m_aStringCompare.compareString( *pFieldNames, sCurrentField ) ) 902*cdf0e10cSrcweir { 903*cdf0e10cSrcweir nFoundIndex = j; 904*cdf0e10cSrcweir break; 905*cdf0e10cSrcweir } 906*cdf0e10cSrcweir } 907*cdf0e10cSrcweir // set the field selection back to the first 908*cdf0e10cSrcweir pFieldNames = seqFieldNames.getArray();; 909*cdf0e10cSrcweir DBG_ASSERT(nFoundIndex != -1, "FmSearchEngine::Init : Invalid field name were given !"); 910*cdf0e10cSrcweir m_arrFieldMapping.push_back(nFoundIndex); 911*cdf0e10cSrcweir } 912*cdf0e10cSrcweir } 913*cdf0e10cSrcweir catch(Exception&) 914*cdf0e10cSrcweir { 915*cdf0e10cSrcweir DBG_ERROR("Exception occured!"); 916*cdf0e10cSrcweir } 917*cdf0e10cSrcweir 918*cdf0e10cSrcweir } 919*cdf0e10cSrcweir 920*cdf0e10cSrcweir //------------------------------------------------------------------------ 921*cdf0e10cSrcweir void FmSearchEngine::SetFormatterUsing(sal_Bool bSet) 922*cdf0e10cSrcweir { 923*cdf0e10cSrcweir if (m_bFormatter == bSet) 924*cdf0e10cSrcweir return; 925*cdf0e10cSrcweir m_bFormatter = bSet; 926*cdf0e10cSrcweir 927*cdf0e10cSrcweir if (m_bUsingTextComponents) 928*cdf0e10cSrcweir { 929*cdf0e10cSrcweir // ich benutzte keinen Formatter, sondern TextComponents -> der SearchIterator muss angepasst werden 930*cdf0e10cSrcweir try 931*cdf0e10cSrcweir { 932*cdf0e10cSrcweir if (m_bFormatter) 933*cdf0e10cSrcweir { 934*cdf0e10cSrcweir DBG_ASSERT(m_xSearchCursor == m_xClonedIterator, "FmSearchEngine::SetFormatterUsing : inkonsistenter Zustand !"); 935*cdf0e10cSrcweir m_xSearchCursor = m_xOriginalIterator; 936*cdf0e10cSrcweir m_xSearchCursor.moveToBookmark(m_xClonedIterator.getBookmark()); 937*cdf0e10cSrcweir // damit ich mit dem neuen Iterator wirklich dort weitermache, wo ich vorher aufgehoert habe 938*cdf0e10cSrcweir } 939*cdf0e10cSrcweir else 940*cdf0e10cSrcweir { 941*cdf0e10cSrcweir DBG_ASSERT(m_xSearchCursor == m_xOriginalIterator, "FmSearchEngine::SetFormatterUsing : inkonsistenter Zustand !"); 942*cdf0e10cSrcweir m_xSearchCursor = m_xClonedIterator; 943*cdf0e10cSrcweir m_xSearchCursor.moveToBookmark(m_xOriginalIterator.getBookmark()); 944*cdf0e10cSrcweir } 945*cdf0e10cSrcweir } 946*cdf0e10cSrcweir catch( const Exception& ) 947*cdf0e10cSrcweir { 948*cdf0e10cSrcweir DBG_UNHANDLED_EXCEPTION(); 949*cdf0e10cSrcweir } 950*cdf0e10cSrcweir 951*cdf0e10cSrcweir // ich muss die Fields neu binden, da der Textaustausch eventuell ueber diese Fields erfolgt und sich der unterliegende Cursor 952*cdf0e10cSrcweir // geaendert hat 953*cdf0e10cSrcweir RebuildUsedFields(m_nCurrentFieldIndex, sal_True); 954*cdf0e10cSrcweir } 955*cdf0e10cSrcweir else 956*cdf0e10cSrcweir InvalidatePreviousLoc(); 957*cdf0e10cSrcweir } 958*cdf0e10cSrcweir 959*cdf0e10cSrcweir //------------------------------------------------------------------------ 960*cdf0e10cSrcweir void FmSearchEngine::PropagateProgress(sal_Bool _bDontPropagateOverflow) 961*cdf0e10cSrcweir { 962*cdf0e10cSrcweir if (m_aProgressHandler.IsSet()) 963*cdf0e10cSrcweir { 964*cdf0e10cSrcweir FmSearchProgress aProgress; 965*cdf0e10cSrcweir try 966*cdf0e10cSrcweir { 967*cdf0e10cSrcweir aProgress.aSearchState = FmSearchProgress::STATE_PROGRESS; 968*cdf0e10cSrcweir aProgress.nCurrentRecord = m_xSearchCursor.getRow() - 1; 969*cdf0e10cSrcweir if (m_bForward) 970*cdf0e10cSrcweir aProgress.bOverflow = !_bDontPropagateOverflow && m_xSearchCursor.isFirst(); 971*cdf0e10cSrcweir else 972*cdf0e10cSrcweir aProgress.bOverflow = !_bDontPropagateOverflow && m_xSearchCursor.isLast(); 973*cdf0e10cSrcweir } 974*cdf0e10cSrcweir catch( const Exception& ) 975*cdf0e10cSrcweir { 976*cdf0e10cSrcweir DBG_UNHANDLED_EXCEPTION(); 977*cdf0e10cSrcweir } 978*cdf0e10cSrcweir 979*cdf0e10cSrcweir m_aProgressHandler.Call(&aProgress); 980*cdf0e10cSrcweir } 981*cdf0e10cSrcweir } 982*cdf0e10cSrcweir 983*cdf0e10cSrcweir //------------------------------------------------------------------------ 984*cdf0e10cSrcweir void FmSearchEngine::SearchNextImpl() 985*cdf0e10cSrcweir { 986*cdf0e10cSrcweir DBG_ASSERT(!(m_bWildcard && m_bRegular) && !(m_bRegular && m_bLevenshtein) && !(m_bLevenshtein && m_bWildcard), 987*cdf0e10cSrcweir "FmSearchEngine::SearchNextImpl : Suchparameter schliessen sich gegenseitig aus !"); 988*cdf0e10cSrcweir 989*cdf0e10cSrcweir DBG_ASSERT(m_xSearchCursor.is(), "FmSearchEngine::SearchNextImpl : habe ungueltigen Iterator !"); 990*cdf0e10cSrcweir 991*cdf0e10cSrcweir // die Parameter der Suche 992*cdf0e10cSrcweir ::rtl::OUString strSearchExpression(m_strSearchExpression); // brauche ich non-const 993*cdf0e10cSrcweir if (!GetCaseSensitive()) 994*cdf0e10cSrcweir // norm the string 995*cdf0e10cSrcweir m_aCharacterClassficator.toLower_rtl(strSearchExpression); 996*cdf0e10cSrcweir 997*cdf0e10cSrcweir if (!m_bRegular && !m_bLevenshtein) 998*cdf0e10cSrcweir { // 'normale' Suche fuehre ich auf jeden Fall ueber WildCards durch, muss aber vorher je nach Modus den ::rtl::OUString anpassen 999*cdf0e10cSrcweir 1000*cdf0e10cSrcweir if (!m_bWildcard) 1001*cdf0e10cSrcweir { // da natuerlich in allen anderen Faellen auch * und ? im Suchstring erlaubt sind, aber nicht als WildCards zaehlen 1002*cdf0e10cSrcweir // sollen, muss ich normieren 1003*cdf0e10cSrcweir UniString aTmp(strSearchExpression.getStr()); 1004*cdf0e10cSrcweir static const UniString s_sStar = UniString::CreateFromAscii("\\*"); 1005*cdf0e10cSrcweir static const UniString s_sQuotation = UniString::CreateFromAscii("\\?"); 1006*cdf0e10cSrcweir aTmp.SearchAndReplaceAll('*', s_sStar); 1007*cdf0e10cSrcweir aTmp.SearchAndReplaceAll('?', s_sQuotation); 1008*cdf0e10cSrcweir strSearchExpression = aTmp; 1009*cdf0e10cSrcweir 1010*cdf0e10cSrcweir switch (m_nPosition) 1011*cdf0e10cSrcweir { 1012*cdf0e10cSrcweir case MATCHING_ANYWHERE : 1013*cdf0e10cSrcweir strSearchExpression = ::rtl::OUString::createFromAscii("*") + strSearchExpression 1014*cdf0e10cSrcweir + ::rtl::OUString::createFromAscii("*"); 1015*cdf0e10cSrcweir break; 1016*cdf0e10cSrcweir case MATCHING_BEGINNING : 1017*cdf0e10cSrcweir strSearchExpression = strSearchExpression + ::rtl::OUString::createFromAscii("*"); 1018*cdf0e10cSrcweir break; 1019*cdf0e10cSrcweir case MATCHING_END : 1020*cdf0e10cSrcweir strSearchExpression = ::rtl::OUString::createFromAscii("*") + strSearchExpression; 1021*cdf0e10cSrcweir break; 1022*cdf0e10cSrcweir case MATCHING_WHOLETEXT : 1023*cdf0e10cSrcweir break; 1024*cdf0e10cSrcweir default : 1025*cdf0e10cSrcweir DBG_ERROR("FmSearchEngine::SearchNextImpl() : die Methoden-Listbox duerfte nur 4 Eintraege enthalten ..."); 1026*cdf0e10cSrcweir } 1027*cdf0e10cSrcweir } 1028*cdf0e10cSrcweir } 1029*cdf0e10cSrcweir 1030*cdf0e10cSrcweir // fuer Arbeit auf Feldliste 1031*cdf0e10cSrcweir FieldCollectionIterator iterBegin = m_arrUsedFields.begin(); 1032*cdf0e10cSrcweir FieldCollectionIterator iterEnd = m_arrUsedFields.end(); 1033*cdf0e10cSrcweir FieldCollectionIterator iterFieldCheck; 1034*cdf0e10cSrcweir 1035*cdf0e10cSrcweir sal_Int32 nFieldPos; 1036*cdf0e10cSrcweir 1037*cdf0e10cSrcweir if (HasPreviousLoc()) 1038*cdf0e10cSrcweir { 1039*cdf0e10cSrcweir DBG_ASSERT(EQUAL_BOOKMARKS(m_aPreviousLocBookmark, m_xSearchCursor.getBookmark()), 1040*cdf0e10cSrcweir "FmSearchEngine::SearchNextImpl : ungueltige Position !"); 1041*cdf0e10cSrcweir iterFieldCheck = m_iterPreviousLocField; 1042*cdf0e10cSrcweir // im Feld nach (oder vor) der letzten Fundstelle weitermachen 1043*cdf0e10cSrcweir nFieldPos = iterFieldCheck - iterBegin; 1044*cdf0e10cSrcweir MoveField(nFieldPos, iterFieldCheck, iterBegin, iterEnd); 1045*cdf0e10cSrcweir } 1046*cdf0e10cSrcweir else 1047*cdf0e10cSrcweir { 1048*cdf0e10cSrcweir if (m_bForward) 1049*cdf0e10cSrcweir iterFieldCheck = iterBegin; 1050*cdf0e10cSrcweir else 1051*cdf0e10cSrcweir { 1052*cdf0e10cSrcweir iterFieldCheck = iterEnd; 1053*cdf0e10cSrcweir --iterFieldCheck; 1054*cdf0e10cSrcweir } 1055*cdf0e10cSrcweir nFieldPos = iterFieldCheck - iterBegin; 1056*cdf0e10cSrcweir } 1057*cdf0e10cSrcweir 1058*cdf0e10cSrcweir PropagateProgress(sal_True); 1059*cdf0e10cSrcweir SEARCH_RESULT srResult; 1060*cdf0e10cSrcweir if (m_eSearchForType != SEARCHFOR_STRING) 1061*cdf0e10cSrcweir srResult = SearchSpecial(m_eSearchForType == SEARCHFOR_NULL, nFieldPos, iterFieldCheck, iterBegin, iterEnd); 1062*cdf0e10cSrcweir else if (!m_bRegular && !m_bLevenshtein) 1063*cdf0e10cSrcweir srResult = SearchWildcard(strSearchExpression, nFieldPos, iterFieldCheck, iterBegin, iterEnd); 1064*cdf0e10cSrcweir else 1065*cdf0e10cSrcweir srResult = SearchRegularApprox(strSearchExpression, nFieldPos, iterFieldCheck, iterBegin, iterEnd); 1066*cdf0e10cSrcweir 1067*cdf0e10cSrcweir m_srResult = srResult; 1068*cdf0e10cSrcweir 1069*cdf0e10cSrcweir if (SR_ERROR == m_srResult) 1070*cdf0e10cSrcweir return; 1071*cdf0e10cSrcweir 1072*cdf0e10cSrcweir // gefunden ? 1073*cdf0e10cSrcweir if (SR_FOUND == m_srResult) 1074*cdf0e10cSrcweir { 1075*cdf0e10cSrcweir // die Pos merken 1076*cdf0e10cSrcweir try { m_aPreviousLocBookmark = m_xSearchCursor.getBookmark(); } 1077*cdf0e10cSrcweir catch ( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); } 1078*cdf0e10cSrcweir m_iterPreviousLocField = iterFieldCheck; 1079*cdf0e10cSrcweir } 1080*cdf0e10cSrcweir else 1081*cdf0e10cSrcweir // die "letzte Fundstelle" invalidieren 1082*cdf0e10cSrcweir InvalidatePreviousLoc(); 1083*cdf0e10cSrcweir } 1084*cdf0e10cSrcweir 1085*cdf0e10cSrcweir //------------------------------------------------------------------------ 1086*cdf0e10cSrcweir IMPL_LINK(FmSearchEngine, OnSearchTerminated, FmSearchThread*, /*pThread*/) 1087*cdf0e10cSrcweir { 1088*cdf0e10cSrcweir if (!m_aProgressHandler.IsSet()) 1089*cdf0e10cSrcweir return 0L; 1090*cdf0e10cSrcweir 1091*cdf0e10cSrcweir FmSearchProgress aProgress; 1092*cdf0e10cSrcweir try 1093*cdf0e10cSrcweir { 1094*cdf0e10cSrcweir switch (m_srResult) 1095*cdf0e10cSrcweir { 1096*cdf0e10cSrcweir case SR_ERROR : 1097*cdf0e10cSrcweir aProgress.aSearchState = FmSearchProgress::STATE_ERROR; 1098*cdf0e10cSrcweir break; 1099*cdf0e10cSrcweir case SR_FOUND : 1100*cdf0e10cSrcweir aProgress.aSearchState = FmSearchProgress::STATE_SUCCESSFULL; 1101*cdf0e10cSrcweir aProgress.aBookmark = m_aPreviousLocBookmark; 1102*cdf0e10cSrcweir aProgress.nFieldIndex = m_iterPreviousLocField - m_arrUsedFields.begin(); 1103*cdf0e10cSrcweir break; 1104*cdf0e10cSrcweir case SR_NOTFOUND : 1105*cdf0e10cSrcweir aProgress.aSearchState = FmSearchProgress::STATE_NOTHINGFOUND; 1106*cdf0e10cSrcweir aProgress.aBookmark = m_xSearchCursor.getBookmark(); 1107*cdf0e10cSrcweir break; 1108*cdf0e10cSrcweir case SR_CANCELED : 1109*cdf0e10cSrcweir aProgress.aSearchState = FmSearchProgress::STATE_CANCELED; 1110*cdf0e10cSrcweir aProgress.aBookmark = m_xSearchCursor.getBookmark(); 1111*cdf0e10cSrcweir break; 1112*cdf0e10cSrcweir } 1113*cdf0e10cSrcweir aProgress.nCurrentRecord = m_xSearchCursor.getRow() - 1; 1114*cdf0e10cSrcweir } 1115*cdf0e10cSrcweir catch( const Exception& ) 1116*cdf0e10cSrcweir { 1117*cdf0e10cSrcweir DBG_UNHANDLED_EXCEPTION(); 1118*cdf0e10cSrcweir } 1119*cdf0e10cSrcweir 1120*cdf0e10cSrcweir // per definitionem muss der Link Thread-sicher sein (das verlange ich einfach), so dass ich mich um so etwas hier nicht kuemmern muss 1121*cdf0e10cSrcweir m_aProgressHandler.Call(&aProgress); 1122*cdf0e10cSrcweir 1123*cdf0e10cSrcweir m_bSearchingCurrently = sal_False; 1124*cdf0e10cSrcweir return 0L; 1125*cdf0e10cSrcweir } 1126*cdf0e10cSrcweir 1127*cdf0e10cSrcweir //------------------------------------------------------------------------ 1128*cdf0e10cSrcweir IMPL_LINK(FmSearchEngine, OnNewRecordCount, void*, pCounterAsVoid) 1129*cdf0e10cSrcweir { 1130*cdf0e10cSrcweir if (!m_aProgressHandler.IsSet()) 1131*cdf0e10cSrcweir return 0L; 1132*cdf0e10cSrcweir 1133*cdf0e10cSrcweir FmSearchProgress aProgress; 1134*cdf0e10cSrcweir aProgress.nCurrentRecord = (sal_uIntPtr)pCounterAsVoid; 1135*cdf0e10cSrcweir aProgress.aSearchState = FmSearchProgress::STATE_PROGRESS_COUNTING; 1136*cdf0e10cSrcweir m_aProgressHandler.Call(&aProgress); 1137*cdf0e10cSrcweir 1138*cdf0e10cSrcweir return 0L; 1139*cdf0e10cSrcweir } 1140*cdf0e10cSrcweir 1141*cdf0e10cSrcweir //------------------------------------------------------------------------ 1142*cdf0e10cSrcweir sal_Bool FmSearchEngine::CancelRequested() 1143*cdf0e10cSrcweir { 1144*cdf0e10cSrcweir m_aCancelAsynchAccess.acquire(); 1145*cdf0e10cSrcweir sal_Bool bReturn = m_bCancelAsynchRequest; 1146*cdf0e10cSrcweir m_aCancelAsynchAccess.release(); 1147*cdf0e10cSrcweir return bReturn; 1148*cdf0e10cSrcweir } 1149*cdf0e10cSrcweir 1150*cdf0e10cSrcweir //------------------------------------------------------------------------ 1151*cdf0e10cSrcweir void FmSearchEngine::CancelSearch() 1152*cdf0e10cSrcweir { 1153*cdf0e10cSrcweir m_aCancelAsynchAccess.acquire(); 1154*cdf0e10cSrcweir m_bCancelAsynchRequest = sal_True; 1155*cdf0e10cSrcweir m_aCancelAsynchAccess.release(); 1156*cdf0e10cSrcweir } 1157*cdf0e10cSrcweir 1158*cdf0e10cSrcweir //------------------------------------------------------------------------ 1159*cdf0e10cSrcweir sal_Bool FmSearchEngine::SwitchToContext(const Reference< ::com::sun::star::sdbc::XResultSet > & xCursor, const ::rtl::OUString& sVisibleFields, const InterfaceArray& arrFields, 1160*cdf0e10cSrcweir sal_Int32 nFieldIndex) 1161*cdf0e10cSrcweir { 1162*cdf0e10cSrcweir DBG_ASSERT(!m_bSearchingCurrently, "FmSearchEngine::SwitchToContext : please do not call while I'm searching !"); 1163*cdf0e10cSrcweir if (m_bSearchingCurrently) 1164*cdf0e10cSrcweir return sal_False; 1165*cdf0e10cSrcweir 1166*cdf0e10cSrcweir m_xSearchCursor = xCursor; 1167*cdf0e10cSrcweir m_xOriginalIterator = xCursor; 1168*cdf0e10cSrcweir m_xClonedIterator = CursorWrapper(m_xOriginalIterator, sal_True); 1169*cdf0e10cSrcweir m_bUsingTextComponents = sal_True; 1170*cdf0e10cSrcweir 1171*cdf0e10cSrcweir fillControlTexts(arrFields); 1172*cdf0e10cSrcweir 1173*cdf0e10cSrcweir Init(sVisibleFields); 1174*cdf0e10cSrcweir RebuildUsedFields(nFieldIndex, sal_True); 1175*cdf0e10cSrcweir 1176*cdf0e10cSrcweir return sal_True; 1177*cdf0e10cSrcweir } 1178*cdf0e10cSrcweir 1179*cdf0e10cSrcweir //------------------------------------------------------------------------ 1180*cdf0e10cSrcweir void FmSearchEngine::ImplStartNextSearch() 1181*cdf0e10cSrcweir { 1182*cdf0e10cSrcweir m_bCancelAsynchRequest = sal_False; 1183*cdf0e10cSrcweir m_bSearchingCurrently = sal_True; 1184*cdf0e10cSrcweir 1185*cdf0e10cSrcweir if (m_eMode == SM_USETHREAD)//CHINA001 if (m_eMode == FmSearchDialog::SM_USETHREAD) 1186*cdf0e10cSrcweir { 1187*cdf0e10cSrcweir FmSearchThread* pSearcher = new FmSearchThread(this); 1188*cdf0e10cSrcweir // der loescht sich nach Beendigung selber ... 1189*cdf0e10cSrcweir pSearcher->setTerminationHandler(LINK(this, FmSearchEngine, OnSearchTerminated)); 1190*cdf0e10cSrcweir 1191*cdf0e10cSrcweir pSearcher->createSuspended(); 1192*cdf0e10cSrcweir pSearcher->setPriority(::vos::OThread::TPriority_Lowest); 1193*cdf0e10cSrcweir pSearcher->resume(); 1194*cdf0e10cSrcweir } 1195*cdf0e10cSrcweir else 1196*cdf0e10cSrcweir { 1197*cdf0e10cSrcweir SearchNextImpl(); 1198*cdf0e10cSrcweir LINK(this, FmSearchEngine, OnSearchTerminated).Call(NULL); 1199*cdf0e10cSrcweir } 1200*cdf0e10cSrcweir } 1201*cdf0e10cSrcweir 1202*cdf0e10cSrcweir //------------------------------------------------------------------------ 1203*cdf0e10cSrcweir void FmSearchEngine::SearchNext(const ::rtl::OUString& strExpression) 1204*cdf0e10cSrcweir { 1205*cdf0e10cSrcweir m_strSearchExpression = strExpression; 1206*cdf0e10cSrcweir m_eSearchForType = SEARCHFOR_STRING; 1207*cdf0e10cSrcweir ImplStartNextSearch(); 1208*cdf0e10cSrcweir } 1209*cdf0e10cSrcweir 1210*cdf0e10cSrcweir //------------------------------------------------------------------------ 1211*cdf0e10cSrcweir void FmSearchEngine::SearchNextSpecial(sal_Bool _bSearchForNull) 1212*cdf0e10cSrcweir { 1213*cdf0e10cSrcweir m_eSearchForType = _bSearchForNull ? SEARCHFOR_NULL : SEARCHFOR_NOTNULL; 1214*cdf0e10cSrcweir ImplStartNextSearch(); 1215*cdf0e10cSrcweir } 1216*cdf0e10cSrcweir 1217*cdf0e10cSrcweir //------------------------------------------------------------------------ 1218*cdf0e10cSrcweir void FmSearchEngine::StartOver(const ::rtl::OUString& strExpression) 1219*cdf0e10cSrcweir { 1220*cdf0e10cSrcweir try 1221*cdf0e10cSrcweir { 1222*cdf0e10cSrcweir if (m_bForward) 1223*cdf0e10cSrcweir m_xSearchCursor.first(); 1224*cdf0e10cSrcweir else 1225*cdf0e10cSrcweir m_xSearchCursor.last(); 1226*cdf0e10cSrcweir } 1227*cdf0e10cSrcweir catch( const Exception& ) 1228*cdf0e10cSrcweir { 1229*cdf0e10cSrcweir DBG_UNHANDLED_EXCEPTION(); 1230*cdf0e10cSrcweir return; 1231*cdf0e10cSrcweir } 1232*cdf0e10cSrcweir 1233*cdf0e10cSrcweir InvalidatePreviousLoc(); 1234*cdf0e10cSrcweir SearchNext(strExpression); 1235*cdf0e10cSrcweir } 1236*cdf0e10cSrcweir 1237*cdf0e10cSrcweir //------------------------------------------------------------------------ 1238*cdf0e10cSrcweir void FmSearchEngine::StartOverSpecial(sal_Bool _bSearchForNull) 1239*cdf0e10cSrcweir { 1240*cdf0e10cSrcweir try 1241*cdf0e10cSrcweir { 1242*cdf0e10cSrcweir if (m_bForward) 1243*cdf0e10cSrcweir m_xSearchCursor.first(); 1244*cdf0e10cSrcweir else 1245*cdf0e10cSrcweir m_xSearchCursor.last(); 1246*cdf0e10cSrcweir } 1247*cdf0e10cSrcweir catch( const Exception& ) 1248*cdf0e10cSrcweir { 1249*cdf0e10cSrcweir DBG_UNHANDLED_EXCEPTION(); 1250*cdf0e10cSrcweir return; 1251*cdf0e10cSrcweir } 1252*cdf0e10cSrcweir 1253*cdf0e10cSrcweir InvalidatePreviousLoc(); 1254*cdf0e10cSrcweir SearchNextSpecial(_bSearchForNull); 1255*cdf0e10cSrcweir } 1256*cdf0e10cSrcweir 1257*cdf0e10cSrcweir //------------------------------------------------------------------------ 1258*cdf0e10cSrcweir void FmSearchEngine::InvalidatePreviousLoc() 1259*cdf0e10cSrcweir { 1260*cdf0e10cSrcweir m_aPreviousLocBookmark.setValue(0,getVoidCppuType()); 1261*cdf0e10cSrcweir m_iterPreviousLocField = m_arrUsedFields.end(); 1262*cdf0e10cSrcweir } 1263*cdf0e10cSrcweir 1264*cdf0e10cSrcweir //------------------------------------------------------------------------ 1265*cdf0e10cSrcweir void FmSearchEngine::RebuildUsedFields(sal_Int32 nFieldIndex, sal_Bool bForce) 1266*cdf0e10cSrcweir { 1267*cdf0e10cSrcweir if (!bForce && (nFieldIndex == m_nCurrentFieldIndex)) 1268*cdf0e10cSrcweir return; 1269*cdf0e10cSrcweir // (da ich keinen Wechsel des Iterators von aussen zulasse, heisst selber ::com::sun::star::sdbcx::Index auch immer selbe Spalte, also habe ich nix zu tun) 1270*cdf0e10cSrcweir 1271*cdf0e10cSrcweir DBG_ASSERT((nFieldIndex == -1) || 1272*cdf0e10cSrcweir ((nFieldIndex >= 0) && 1273*cdf0e10cSrcweir (static_cast<size_t>(nFieldIndex) < m_arrFieldMapping.size())), 1274*cdf0e10cSrcweir "FmSearchEngine::RebuildUsedFields : nFieldIndex is invalid!"); 1275*cdf0e10cSrcweir // alle Felder, die ich durchsuchen muss, einsammeln 1276*cdf0e10cSrcweir m_arrUsedFields.clear(); 1277*cdf0e10cSrcweir if (nFieldIndex == -1) 1278*cdf0e10cSrcweir { 1279*cdf0e10cSrcweir Reference< ::com::sun::star::container::XIndexAccess > xFields; 1280*cdf0e10cSrcweir for (size_t i=0; i<m_arrFieldMapping.size(); ++i) 1281*cdf0e10cSrcweir { 1282*cdf0e10cSrcweir Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xSupplyCols(IFACECAST(m_xSearchCursor), UNO_QUERY); 1283*cdf0e10cSrcweir DBG_ASSERT(xSupplyCols.is(), "FmSearchEngine::RebuildUsedFields : invalid cursor (no columns supplier) !"); 1284*cdf0e10cSrcweir xFields = Reference< ::com::sun::star::container::XIndexAccess > (xSupplyCols->getColumns(), UNO_QUERY); 1285*cdf0e10cSrcweir BuildAndInsertFieldInfo(xFields, m_arrFieldMapping[i]); 1286*cdf0e10cSrcweir } 1287*cdf0e10cSrcweir } 1288*cdf0e10cSrcweir else 1289*cdf0e10cSrcweir { 1290*cdf0e10cSrcweir Reference< ::com::sun::star::container::XIndexAccess > xFields; 1291*cdf0e10cSrcweir Reference< ::com::sun::star::sdbcx::XColumnsSupplier > xSupplyCols(IFACECAST(m_xSearchCursor), UNO_QUERY); 1292*cdf0e10cSrcweir DBG_ASSERT(xSupplyCols.is(), "FmSearchEngine::RebuildUsedFields : invalid cursor (no columns supplier) !"); 1293*cdf0e10cSrcweir xFields = Reference< ::com::sun::star::container::XIndexAccess > (xSupplyCols->getColumns(), UNO_QUERY); 1294*cdf0e10cSrcweir BuildAndInsertFieldInfo(xFields, m_arrFieldMapping[static_cast< size_t >(nFieldIndex)]); 1295*cdf0e10cSrcweir } 1296*cdf0e10cSrcweir 1297*cdf0e10cSrcweir m_nCurrentFieldIndex = nFieldIndex; 1298*cdf0e10cSrcweir // und natuerlich beginne ich die naechste Suche wieder jungfraeulich 1299*cdf0e10cSrcweir InvalidatePreviousLoc(); 1300*cdf0e10cSrcweir } 1301*cdf0e10cSrcweir 1302