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