xref: /trunk/main/svx/inc/svx/fmsrcimp.hxx (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #ifndef _FMSRCIMP_HXX
25 #define _FMSRCIMP_HXX
26 
27 #include <svx/fmtools.hxx>
28 #include "svx/svxdllapi.h"
29 
30 /** === begin UNO includes === **/
31 #include <com/sun/star/awt/XCheckBox.hpp>
32 #include <com/sun/star/awt/XListBox.hpp>
33 #include <com/sun/star/awt/XTextComponent.hpp>
34 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
35 #include <com/sun/star/util/XNumberFormatter.hpp>
36 /** === end UNO includes === **/
37 
38 #include <comphelper/stl_types.hxx>
39 #include <cppuhelper/implbase1.hxx>
40 #include <osl/mutex.hxx>
41 #include <unotools/charclass.hxx>
42 #include <unotools/collatorwrapper.hxx>
43 #include <vos/thread.hxx>
44 
45 #include <deque>
46 
47 // ===================================================================================================
48 // = class FmSearchThread - wie der Name schon sagt
49 // ===================================================================================================
50 
51 class FmSearchEngine;
52 class FmSearchThread : public ::vos::OThread
53 {
54 	FmSearchEngine*		m_pEngine;
55 	Link				m_aTerminationHdl;
56 
57 	virtual void SAL_CALL run();
58 	virtual void SAL_CALL onTerminated();
59 
60 public:
FmSearchThread(FmSearchEngine * pEngine)61 	FmSearchThread(FmSearchEngine* pEngine) : m_pEngine(pEngine) { }
setTerminationHandler(Link aHdl)62 	void setTerminationHandler(Link aHdl) { m_aTerminationHdl = aHdl; }
63 };
64 
65 // ===================================================================================================
66 // = struct FmSearchProgress - diese Struktur bekommt der Owner der SearchEngine fuer Status-Updates
67 // = (und am Ende der Suche)
68 // ===================================================================================================
69 
70 struct FmSearchProgress
71 {
72 	enum STATE { STATE_PROGRESS, STATE_PROGRESS_COUNTING, STATE_CANCELED, STATE_SUCCESSFULL, STATE_NOTHINGFOUND, STATE_ERROR };
73 		// (Bewegung auf neuen Datensatz; Fortschritt beim Zaehlen von Datensaetzen; abgebrochen; Datensatz gefunden;
74 		// nichts gefunden, irgendein nicht zu handelnder Fehler)
75 	STATE	aSearchState;
76 
77 	// aktueller Datensatz - immer gueltig (ist zum Beispiel bei Abbrechen auch fuer das Weitersuchen interesant)
78 	sal_uInt32	nCurrentRecord;
79 	// Ueberlauf - nur gueltig bei STATE_PROGRESS
80 	sal_Bool	bOverflow;
81 
82 	// die Position des Such-Cursors - bei STATE_SUCCESSFULL, STATE_CANCELED und STATE_NOTHING_FOUND gueltig
83 	::com::sun::star::uno::Any	aBookmark;
84 	// das Feld, in dem der Text gefunden wurde - bei STATE_SUCCESSFULL gueltig
85 	sal_Int32	nFieldIndex;
86 };
87 
88 // ===================================================================================================
89 // = class FmRecordCountListener - Hilfsklasse fuer FmSearchEngine, lauscht an einem Cursor und teilt
90 // =								Aenderungem im RecordCount mit
91 // ===================================================================================================
92 
93 class FmRecordCountListener : public ::cppu::WeakImplHelper1< ::com::sun::star::beans::XPropertyChangeListener>
94 {
95 // Attribute
96 	Link			m_lnkWhoWantsToKnow;
97 	::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > 	m_xListening;
98 
99 // Attribut-Zugriff
100 public:
101 	Link SetPropChangeHandler(const Link& lnk);
102 
103 // Oprationen
104 public:
105 	FmRecordCountListener(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& dbcCursor);
106 		// the set has to support the sdb::ResultSet service
107 	virtual ~FmRecordCountListener();
108 
109 	//	DECLARE_UNO3_AGG_DEFAULTS(FmPropertyListener, UsrObject);
110 	//	virtual sal_Bool queryInterface(::com::sun::star::uno::Uik aUik, ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rOut);
111 
112 // ::com::sun::star::lang::XEventListener
113 	virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw(::com::sun::star::uno::RuntimeException);
114 
115 // ::com::sun::star::beans::XPropertyChangeListener
116 	virtual void SAL_CALL propertyChange(const ::com::sun::star::beans::PropertyChangeEvent& evt) throw(::com::sun::star::uno::RuntimeException);
117 
118 	void DisConnect();
119 
120 private:
121 	void NotifyCurrentCount();
122 
123 };
124 
125 // ===================================================================================================
126 // = class FmSearchEngine - Impl-Klasse fuer FmSearchDialog
127 // ===================================================================================================
128 
129 namespace svxform {
130 	// We have three possible control types we may search in, determined by the supported interfaces : ::com::sun::star::awt::XTextComponent, ::com::sun::star::awt::XListBox, ::com::sun::star::awt::XCheckBox.
131 	// While searching we don't want to do this distinction for every control in every round. So we need some helpers.
132 	class ControlTextWrapper
133 	{
134 		// attributes
135 		::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > 	m_xControl;
136 		// attribute access
137 	public:
getControl() const138 		::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >  getControl() const{ return m_xControl; }
139 	public:
ControlTextWrapper(const::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface> & _xControl)140 		ControlTextWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& _xControl) { m_xControl = _xControl; }
~ControlTextWrapper()141 		virtual ~ControlTextWrapper() { }
142 
143 		virtual ::rtl::OUString getCurrentText() const = 0;
144 	};
145 	class SimpleTextWrapper : public ControlTextWrapper
146 	{
147 		::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextComponent >  m_xText;
148 	public:
149 		SimpleTextWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XTextComponent >& _xText);
150 		virtual ::rtl::OUString getCurrentText() const;
151 	};
152 	class ListBoxWrapper : public ControlTextWrapper
153 	{
154 		::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox >  m_xBox;
155 	public:
156 		ListBoxWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XListBox >& _xBox);
157 		virtual ::rtl::OUString getCurrentText() const;
158 	};
159 	class CheckBoxWrapper : public ControlTextWrapper
160 	{
161 		::com::sun::star::uno::Reference< ::com::sun::star::awt::XCheckBox >  m_xBox;
162 	public:
163 		CheckBoxWrapper(const ::com::sun::star::uno::Reference< ::com::sun::star::awt::XCheckBox >& _xBox);
164 		virtual ::rtl::OUString getCurrentText() const;
165 	};
166 }
167 
168 enum FMSEARCH_MODE { SM_BRUTE, SM_ALLOWSCHEDULE, SM_USETHREAD };
169 
170 DECLARE_STL_VECTOR( ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>, InterfaceArray);
171 
172 class SVX_DLLPUBLIC FmSearchEngine
173 {
174 	friend class FmSearchThread;
175 
176 	enum SEARCH_RESULT { SR_FOUND, SR_NOTFOUND, SR_ERROR, SR_CANCELED };
177 	enum SEARCHFOR_TYPE { SEARCHFOR_STRING, SEARCHFOR_NULL, SEARCHFOR_NOTNULL };
178 
179 	// zugrundeliegende Daten
180 	CursorWrapper                   m_xSearchCursor;
181 	std::deque<sal_Int32>           m_arrFieldMapping;
182 		// da der Iterator durchaus mehr Spalten haben kann, als ich eigentlich verwalte (in meiner Feld-Listbox),
183 		// muss ich mir hier ein Mapping dieser ::com::sun::star::form-Schluessel auf die Indizies der entsprechenden Spalten im Iterator halten
184 
185 	// der Formatter
186 	::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier > 	m_xFormatSupplier;
187 	::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatter > 		m_xFormatter;
188 
189 	CharClass				m_aCharacterClassficator;
190 	CollatorWrapper			m_aStringCompare;
191 
192 	// die Sammlung aller interesanten Felder (bzw. ihre ::com::sun::star::data::XDatabaseVariant-Interfaces und ihre FormatKeys)
193 	struct FieldInfo
194 	{
195 		::com::sun::star::uno::Reference< ::com::sun::star::sdb::XColumn > 			xContents;
196 		sal_uInt32				nFormatKey;
197 		sal_Bool				bDoubleHandling;
198 	};
199 
200 	DECLARE_STL_VECTOR(FieldInfo, FieldCollection);
201 	FieldCollection				m_arrUsedFields;
202 	sal_Int32					m_nCurrentFieldIndex;	// der letzte Parameter von RebuildUsedFields, ermoeglicht mir Checks in FormatField
203 
204 	DECLARE_STL_VECTOR(svxform::ControlTextWrapper*, ControlTextSuppliers);
205 	ControlTextSuppliers	m_aControlTexts;
206 
207 	sal_Bool				m_bUsingTextComponents;
208 	CursorWrapper			m_xOriginalIterator;
209 	CursorWrapper			m_xClonedIterator;
210 
211 	// Daten fuer Entscheidung, in welchem Feld ich ein "Found" akzeptiere
212 	::com::sun::star::uno::Any	m_aPreviousLocBookmark;				// Position, an der ich zuletzt fuendig war
213 	FieldCollectionIterator		m_iterPreviousLocField;				// dito Feld
214 
215 	// Kommunikation mit dem Thread, der die eigentliche Suche durchfuehrt
216 	::rtl::OUString				m_strSearchExpression;				// Hinrichtung
217 	SEARCHFOR_TYPE		m_eSearchForType;					// dito
218 	SEARCH_RESULT		m_srResult;							// Rueckrichtung
219 
220 	// der Link, dem ich Fortschritte und Ergebnisse mitteile
221 	Link				m_aProgressHandler;
222     sal_Bool			m_bSearchingCurrently : 1;      // laeuft gerade eine (asynchrone) Suche ?
223 	sal_Bool			m_bCancelAsynchRequest : 1;		// soll abgebrochen werden ?
224 	::osl::Mutex		m_aCancelAsynchAccess;			// Zugriff auf m_bCancelAsynchRequest (eigentlich nur bei
225 														// m_eMode == SM_USETHREAD interesant)
226 	FMSEARCH_MODE	m_eMode;		//CHINA001 	FmSearchDialog::SEARCH_MODE	m_eMode;				// der aktuelle Modus
227 	// der aktuelle Modus
228 
229 	// Parameter fuer die Suche
230 	sal_Bool	m_bFormatter : 1;		// Feldformatierung benutzen
231 	sal_Bool	m_bForward : 1;			// Richtung
232 	sal_Bool	m_bWildcard : 1;		// Platzhalter-Suche ?
233 	sal_Bool	m_bRegular : 1;			// regulaerer Ausdruck
234 	sal_Bool	m_bLevenshtein : 1;		// Levenshtein-Suche
235 	sal_Bool	m_bTransliteration : 1;	// Levenshtein-Suche
236 
237 	sal_Bool	m_bLevRelaxed : 1;		// Parameter fuer Levenshtein-Suche
238 	sal_uInt16	m_nLevOther;
239 	sal_uInt16	m_nLevShorter;
240 	sal_uInt16	m_nLevLonger;
241 
242 	sal_uInt16	m_nPosition;			// wenn nicht regulaer oder lev, dann einer der MATCHING_...-Werte
243 
244 	sal_Int32	m_nTransliterationFlags;
245 
246 // -------------
247 // Memberzugriff
248 private:
249 	SVX_DLLPRIVATE sal_Bool	CancelRequested();		// liefert eine durch m_aCancelAsynchAccess gesicherte Auswertung von m_bCancelAsynchRequest
250 
251 public:
252 	void		SetCaseSensitive(sal_Bool bSet);
253 	sal_Bool	GetCaseSensitive() const;
254 
255 	void		SetFormatterUsing(sal_Bool bSet);	// das ist etwas umfangreicher, deshalb kein hier inline ....
GetFormatterUsing() const256 	sal_Bool	GetFormatterUsing() const			{ return m_bFormatter; }
257 
SetDirection(sal_Bool bForward)258 	void		SetDirection(sal_Bool bForward)		{ m_bForward = bForward; }
GetDirection() const259 	sal_Bool	GetDirection() const				{ return m_bForward; }
260 
SetWildcard(sal_Bool bSet)261 	void		SetWildcard(sal_Bool bSet)			{ m_bWildcard = bSet; }
GetWildcard() const262 	sal_Bool	GetWildcard() const					{ return m_bWildcard; }
263 
SetRegular(sal_Bool bSet)264 	void		SetRegular(sal_Bool bSet)			{ m_bRegular = bSet; }
GetRegular() const265 	sal_Bool	GetRegular() const					{ return m_bRegular; }
266 
SetLevenshtein(sal_Bool bSet)267 	void		SetLevenshtein(sal_Bool bSet)		{ m_bLevenshtein = bSet; }
GetLevenshtein() const268 	sal_Bool	GetLevenshtein() const				{ return m_bLevenshtein; }
269 
270 	void		SetIgnoreWidthCJK(sal_Bool bSet);
271 	sal_Bool	GetIgnoreWidthCJK() const;
272 
SetTransliteration(sal_Bool bSet)273 	void		SetTransliteration(sal_Bool bSet)	{ m_bTransliteration = bSet; }
GetTransliteration() const274 	sal_Bool	GetTransliteration() const			{ return m_bTransliteration; }
275 
SetLevRelaxed(sal_Bool bSet)276 	void		SetLevRelaxed(sal_Bool bSet)		{ m_bLevRelaxed = bSet; }
GetLevRelaxed() const277 	sal_Bool	GetLevRelaxed() const				{ return m_bLevRelaxed; }
SetLevOther(sal_uInt16 nHowMuch)278 	void		SetLevOther(sal_uInt16 nHowMuch)	{ m_nLevOther = nHowMuch; }
GetLevOther() const279 	sal_uInt16	GetLevOther() const					{ return m_nLevOther; }
SetLevShorter(sal_uInt16 nHowMuch)280 	void		SetLevShorter(sal_uInt16 nHowMuch)	{ m_nLevShorter = nHowMuch; }
GetLevShorter() const281 	sal_uInt16	GetLevShorter() const				{ return m_nLevShorter; }
SetLevLonger(sal_uInt16 nHowMuch)282 	void		SetLevLonger(sal_uInt16 nHowMuch)	{ m_nLevLonger = nHowMuch; }
GetLevLonger() const283 	sal_uInt16	GetLevLonger() const				{ return m_nLevLonger; }
284 		// die ganzen Lev-Werte werden nur bei  m_bLevenshtein==sal_True beachtet
285 
SetTransliterationFlags(sal_Int32 _nFlags)286 	void		SetTransliterationFlags(sal_Int32 _nFlags)	{ m_nTransliterationFlags = _nFlags; }
GetTransliterationFlags() const287 	sal_Int32	GetTransliterationFlags() const				{ return m_nTransliterationFlags; }
288 
SetPosition(sal_uInt16 nValue)289 	void	SetPosition(sal_uInt16 nValue)		{ m_nPosition = nValue; }
GetPosition() const290 	sal_uInt16	GetPosition() const				{ return m_nPosition; }
291 		// Position wird bei m_bWildCard==sal_True nicht beachtet
292 
GetSearchMode() const293 	FMSEARCH_MODE GetSearchMode() const { return m_eMode; }
294 
295 public:
296 	/**	zwei Constructoren, beide analog zu denen des FmSearchDialog, Erklaerung siehe also dort ....
297 		xCursor muss jeweils den ::com::sun::star::data::DatabaseCursor-Service implementieren.
298 		wenn eMode == SM_USETHREAD, sollte ein ProgressHandler gesetzt sein, da dann die Ergebnisuebermittlung ueber diesen
299 		Handler erfolgt.
300 		Ist eMode != SM_USETHREAD, kehren SearchNext und StarOver nicht zurueck, bevor die Suche (erfolgreich oder nicht) beendet
301 		wurde, dann kann man das Ergebnis danach abfragen. Ist zusaetzlich der ProgressHandler gesetzt, wird dieser fuer jeden neuen
302 		Datensatz sowie am Ende der Suche aufgerufen.
303 	*/
304 	FmSearchEngine(
305 		const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
306 		const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& xCursor,
307 		const ::rtl::OUString& strVisibleFields,
308 		const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xFormat,
309 		FMSEARCH_MODE eMode);//CHINA001 FmSearchDialog::SEARCH_MODE eMode);
310 	FmSearchEngine(
311 		const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
312 		const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& xCursor,
313 		const ::rtl::OUString& strVisibleFields,
314 		const InterfaceArray& arrFields,
315 		FMSEARCH_MODE eMode); //CHINA001 FmSearchDialog::SEARCH_MODE eMode);
316 
317 	virtual ~FmSearchEngine();
318 
319 	/**	der Link wird fuer jeden Datensatz und nach Beendigung der Suche aufgerufen, Parameter ist ein Zeiger auf
320 		eine FmSearchProgress-Struktur
321 		der Handler sollte auf jeden Fall Thread-sicher sein
322 	*/
SetProgressHandler(Link aHdl)323 	void SetProgressHandler(Link aHdl) { m_aProgressHandler = aHdl; }
324 
325 	///	das naechste Vorkommen suchen (Werte fuer nDirection siehe DIRECTION_*-defines)
326 	void SearchNext(const ::rtl::OUString& strExpression);
327 	/// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
328 	void SearchNextSpecial(sal_Bool _bSearchForNull);
329 	///	das naechste Vorkommen suchen, abhaengig von nDirection wird dabei am Anfang oder am Ende neu begonnen
330 	void StartOver(const ::rtl::OUString& strExpression);
331 	/// analogous, search for "NULL" (_bSearchForNull==sal_True) or "not NULL"
332 	void StartOverSpecial(sal_Bool _bSearchForNull);
333 	/// die Angaben ueber letzte Fundstelle invalidieren
334 	void InvalidatePreviousLoc();
335 
336 	/**	baut m_arrUsedFields neu auf (nFieldIndex==-1 bedeutet alle Felder, ansonsten gibt es den Feldindex an)
337 		wenn bForce nicht gesetzt ist, passiert bei nFieldIndex == m_nCurrentFieldIndex nichts
338 		(ruft InvalidatePreviousLoc auf)
339 	*/
340 	void RebuildUsedFields(sal_Int32 nFieldIndex, sal_Bool bForce = sal_False);
341 	::rtl::OUString FormatField(sal_Int32 nWhich);
342 
343 	/// kehrt sofort zurueck; nachdem wirklich abgebrochen wurde, wird der ProgressHandler mit STATE_CANCELED aufgerufen
344 	void CancelSearch();
345 
346 	/**	nur gueltig, wenn nicht gerade eine (asynchrone) Suche laeuft, die naechste Suche wird dann auf dem neuen Iterator
347 		mit den neuen Parametern durchgefuehrt
348 	*/
349 	sal_Bool SwitchToContext(const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XResultSet >& xCursor, const ::rtl::OUString& strVisibleFields, const InterfaceArray& arrFields,
350 		sal_Int32 nFieldIndex);
351 
352 protected:
353 	void Init(const ::rtl::OUString& strVisibleFields);
354 
355 	void SearchNextImpl();
356 		// diese Impl-Methode laeuft im SearchThread
357 
358 	// start a thread-search (or call SearchNextImpl directly, depending on the search mode)
359 	void ImplStartNextSearch();
360 
361 private:
362 	SVX_DLLPRIVATE void clearControlTexts();
363 	SVX_DLLPRIVATE void fillControlTexts(const InterfaceArray& arrFields);
364 
365 	// three methods implementing a complete search loop (null/not null, wildcard, SearchText)
366 	// (they all have some code in common, but with this solution we have do do a distinction only once per search (before
367 	// starting the loop), not in every loop step
368 	SVX_DLLPRIVATE SEARCH_RESULT SearchSpecial(sal_Bool _bSearchForNull, sal_Int32& nFieldPos, FieldCollectionIterator& iterFieldLoop,
369 		const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd);
370 	SVX_DLLPRIVATE SEARCH_RESULT SearchWildcard(const ::rtl::OUString& strExpression, sal_Int32& nFieldPos, FieldCollectionIterator& iterFieldLoop,
371 		const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd);
372 	SVX_DLLPRIVATE SEARCH_RESULT SearchRegularApprox(const ::rtl::OUString& strExpression, sal_Int32& nFieldPos, FieldCollectionIterator& iterFieldLoop,
373 		const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd);
374 
375 	SVX_DLLPRIVATE void PropagateProgress(sal_Bool _bDontPropagateOverflow);
376 		// ruft den ProgressHandler mit STATE_PROGRESS und der aktuellen Position des SearchIterators auf
377 
378 	// helpers, die ich mehrmals brauche
379 	SVX_DLLPRIVATE sal_Bool MoveCursor();
380 		// bewegt m_xSearchIterator unter Beachtung von Richtung/Ueberlauf Cursor
381 	SVX_DLLPRIVATE sal_Bool MoveField(sal_Int32& nPos, FieldCollectionIterator& iter, const FieldCollectionIterator& iterBegin, const FieldCollectionIterator& iterEnd);
382 		// bewegt den Iterator unter Beachtung von Richtung/Ueberlauf Iterator/Ueberlauf Cursor
383 	SVX_DLLPRIVATE void BuildAndInsertFieldInfo(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XIndexAccess >& xAllFields, sal_Int32 nField);
384 		// baut eine FieldInfo zum Feld Nummer nField (in xAllFields) auf und fuegt sie zu m_arrUsedFields hinzu
385 		// xAllFields muss den DatabaseRecord-Service unterstuetzen
386 	SVX_DLLPRIVATE ::rtl::OUString FormatField(const FieldInfo& rField);
387 		// formatiert das Feld mit dem NumberFormatter
388 
HasPreviousLoc()389 	SVX_DLLPRIVATE sal_Bool HasPreviousLoc() { return m_aPreviousLocBookmark.hasValue(); }
390 
391 	DECL_LINK(OnSearchTerminated, FmSearchThread*);
392 		// wird vom SuchThread benutzt, nach Rueckkehr aus diesem Handler loescht sich der Thread selber
393 	DECL_LINK(OnNewRecordCount, void*);
394 };
395 
396 #endif // _FMSRCIMP_HXX
397 
398