xref: /aoo41x/main/sw/source/ui/dbui/dbmgr.cxx (revision 43f0f119)
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 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 #include <cstdarg>
28 #include <cstdio>
29 
30 #include <unotxdoc.hxx>
31 #include <com/sun/star/text/NotePrintMode.hpp>
32 #include <sfx2/app.hxx>
33 #include <com/sun/star/sdb/CommandType.hpp>
34 #include <com/sun/star/sdb/XDocumentDataSource.hpp>
35 #include <com/sun/star/frame/XComponentLoader.hpp>
36 #include <com/sun/star/lang/DisposedException.hpp>
37 #include <com/sun/star/lang/XEventListener.hpp>
38 #include <com/sun/star/util/XNumberFormatter.hpp>
39 #include <com/sun/star/sdb/XCompletedConnection.hpp>
40 #include <com/sun/star/sdb/XCompletedExecution.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/text/MailMergeEvent.hpp>
43 #include <com/sun/star/frame/XStorable.hpp>
44 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
45 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
46 #include <com/sun/star/ui/dialogs/XFilterManager.hpp>
47 #include <com/sun/star/uno/XNamingService.hpp>
48 #include <com/sun/star/util/XCloseable.hpp>
49 #include <com/sun/star/beans/XPropertySet.hpp>
50 #include <sfx2/fcontnr.hxx>
51 #include <sfx2/filedlghelper.hxx>
52 #include <sfx2/viewfrm.hxx>
53 #include <dbconfig.hxx>
54 #include <swdbtoolsclient.hxx>
55 #include <pagedesc.hxx>
56 #include <vcl/lstbox.hxx>
57 #include <unotools/tempfile.hxx>
58 #include <unotools/pathoptions.hxx>
59 #include <svl/urihelper.hxx>
60 #define _SVSTDARR_STRINGSDTOR
61 #include <svl/svstdarr.hxx>
62 #include <svl/zforlist.hxx>
63 #include <svl/zformat.hxx>
64 #include <svl/stritem.hxx>
65 #include <svl/eitem.hxx>
66 #include <vcl/oldprintadaptor.hxx>
67 #include <sfx2/docfile.hxx>
68 #include <sfx2/progress.hxx>
69 #include <sfx2/dispatch.hxx>
70 #include <svl/mailenum.hxx>
71 #include <cmdid.h>
72 #include <swmodule.hxx>
73 #include <view.hxx>
74 #include <docsh.hxx>
75 #include <edtwin.hxx>
76 #include <wrtsh.hxx>
77 #include <fldbas.hxx>
78 #include <initui.hxx>
79 #include <swundo.hxx>
80 #include <flddat.hxx>
81 #include <modcfg.hxx>
82 #include <shellio.hxx>
83 #include <dbui.hxx>
84 #include <dbmgr.hxx>
85 #include <doc.hxx>
86 #include <swwait.hxx>
87 #include <swunohelper.hxx>
88 #include <dbui.hrc>
89 #include <globals.hrc>
90 #include <statstr.hrc>
91 #include <mmconfigitem.hxx>
92 #include <sfx2/request.hxx>
93 #include <hintids.hxx>
94 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
95 #include <com/sun/star/sdbc/XRowSet.hpp>
96 #include <com/sun/star/sdbcx/XTablesSupplier.hpp>
97 #include <com/sun/star/sdbcx/XColumnsSupplier.hpp>
98 #include <com/sun/star/sdb/XQueriesSupplier.hpp>
99 #include <com/sun/star/sdb/XColumn.hpp>
100 #include <com/sun/star/sdbc/DataType.hpp>
101 #include <com/sun/star/sdbc/ResultSetType.hpp>
102 #include <com/sun/star/mail/MailAttachment.hpp>
103 #include <comphelper/processfactory.hxx>
104 #include <comphelper/types.hxx>
105 #include <comphelper/property.hxx>
106 #include <mailmergehelper.hxx>
107 #include <maildispatcher.hxx>
108 #include <svtools/htmlcfg.hxx>
109 #include <i18npool/mslangid.hxx>
110 #include <com/sun/star/util/XNumberFormatTypes.hpp>
111 #include <editeng/langitem.hxx>
112 #include <svl/numuno.hxx>
113 
114 #include <unomailmerge.hxx>
115 #include <sfx2/event.hxx>
116 #include <vcl/msgbox.hxx>
117 #include <svx/dataaccessdescriptor.hxx>
118 #include <vos/mutex.hxx>
119 #include <rtl/textenc.h>
120 #include <ndindex.hxx>
121 #include <pam.hxx>
122 #include <swcrsr.hxx>
123 #include <swevent.hxx>
124 #include <osl/file.hxx>
125 #include <swabstdlg.hxx>
126 #include <fmthdft.hxx>
127 #include <dbui.hrc>
128 #include <envelp.hrc>
129 #include <memory>
130 #include <vector>
131 #include <unomid.h>
132 #include <section.hxx>
133 
134 using namespace ::osl;
135 using namespace ::svx;
136 using namespace ::com::sun::star;
137 using namespace ::com::sun::star::text;
138 using namespace ::com::sun::star::uno;
139 using namespace ::com::sun::star::container;
140 using namespace ::com::sun::star::frame;
141 using namespace ::com::sun::star::lang;
142 using namespace ::com::sun::star::sdb;
143 using namespace ::com::sun::star::sdbc;
144 using namespace ::com::sun::star::sdbcx;
145 using namespace ::com::sun::star::beans;
146 using namespace ::com::sun::star::util;
147 using namespace ::com::sun::star::task;
148 using namespace ::com::sun::star::ui::dialogs;
149 
150 #define DB_SEP_SPACE  	0
151 #define DB_SEP_TAB  	1
152 #define DB_SEP_RETURN   2
153 #define DB_SEP_NEWLINE  3
154 
155 SV_IMPL_PTRARR(SwDSParamArr, SwDSParamPtr);
156 const sal_Char cCursor[] = "Cursor";
157 const sal_Char cCommand[] = "Command";
158 const sal_Char cCommandType[] = "CommandType";
159 const sal_Char cDataSourceName[] = "DataSourceName";
160 const sal_Char cSelection[] = "Selection";
161 const sal_Char cActiveConnection[] = "ActiveConnection";
162 
163 // -----------------------------------------------------------------------------
164 // Use nameless namespace to avoid to rubbish the global namespace
165 // -----------------------------------------------------------------------------
166 namespace
167 {
168 
169 bool lcl_getCountFromResultSet( sal_Int32& rCount, const uno::Reference<XResultSet>& xResultSet )
170 {
171     uno::Reference<XPropertySet> xPrSet(xResultSet, UNO_QUERY);
172     if(xPrSet.is())
173     {
174         try
175         {
176             sal_Bool bFinal = sal_False;
177             Any aFinal = xPrSet->getPropertyValue(C2U("IsRowCountFinal"));
178             aFinal >>= bFinal;
179             if(!bFinal)
180             {
181                 xResultSet->last();
182                 xResultSet->first();
183             }
184             Any aCount = xPrSet->getPropertyValue(C2U("RowCount"));
185             if( aCount >>= rCount )
186                 return true;
187         }
188         catch(Exception&)
189         {
190         }
191     }
192     return false;
193 }
194 // #122799# copy compatibility options
195 void lcl_CopyCompatibilityOptions( SwWrtShell& rSourceShell, SwWrtShell& rTargetShell)
196 {
197     IDocumentSettingAccess* pIDsa = rSourceShell.getIDocumentSettingAccess();
198 
199     rTargetShell.SetParaSpaceMax( pIDsa->get(IDocumentSettingAccess::PARA_SPACE_MAX));
200     rTargetShell.SetParaSpaceMaxAtPages(pIDsa->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES));
201     rTargetShell.SetTabCompat( pIDsa->get(IDocumentSettingAccess::TAB_COMPAT));
202     rTargetShell.SetAddExtLeading( pIDsa->get(IDocumentSettingAccess::ADD_EXT_LEADING));
203     rTargetShell.SetUseVirDev( pIDsa->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE));
204     rTargetShell.SetAddParaSpacingToTableCells( pIDsa->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS));
205     rTargetShell.SetUseFormerLineSpacing( pIDsa->get(IDocumentSettingAccess::OLD_LINE_SPACING));
206     rTargetShell.SetUseFormerObjectPositioning( pIDsa->get(IDocumentSettingAccess::USE_FORMER_OBJECT_POS));
207     rTargetShell.SetConsiderWrapOnObjPos( pIDsa->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION));
208     rTargetShell.SetUseFormerTextWrapping( pIDsa->get(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING));
209 }
210 }
211 /* -----------------09.12.2002 12:35-----------------
212  *
213  * --------------------------------------------------*/
214 
215 class SwConnectionDisposedListener_Impl : public cppu::WeakImplHelper1
216 < lang::XEventListener >
217 {
218     SwNewDBMgr&     rDBMgr;
219 
220     virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
221 public:
222     SwConnectionDisposedListener_Impl(SwNewDBMgr& rMgr);
223     ~SwConnectionDisposedListener_Impl();
224 
225 };
226 // -----------------------------------------------------------------------------
227 struct SwNewDBMgr_Impl
228 {
229     SwDSParam*          pMergeData;
230     AbstractMailMergeDlg*     pMergeDialog;
231     uno::Reference<lang::XEventListener> xDisposeListener;
232 
233     SwNewDBMgr_Impl(SwNewDBMgr& rDBMgr)
234        :pMergeData(0)
235        ,pMergeDialog(0)
236        ,xDisposeListener(new SwConnectionDisposedListener_Impl(rDBMgr))
237         {}
238 };
239 /*-- 24.10.2003 15:54:18---------------------------------------------------
240 
241   -----------------------------------------------------------------------*/
242 void lcl_InitNumberFormatter(SwDSParam& rParam, uno::Reference<XDataSource> xSource)
243 {
244     uno::Reference<XMultiServiceFactory> xMgr = ::comphelper::getProcessServiceFactory();
245     if( xMgr.is() )
246     {
247         uno::Reference<XInterface> xInstance = xMgr->createInstance( C2U( "com.sun.star.util.NumberFormatter" ));
248         rParam.xFormatter = uno::Reference<util::XNumberFormatter>(xInstance, UNO_QUERY) ;
249     }
250     if(!xSource.is())
251         xSource = SwNewDBMgr::getDataSourceAsParent(rParam.xConnection, rParam.sDataSource);
252 
253     uno::Reference<XPropertySet> xSourceProps(xSource, UNO_QUERY);
254     if(xSourceProps.is())
255     {
256         Any aFormats = xSourceProps->getPropertyValue(C2U("NumberFormatsSupplier"));
257         if(aFormats.hasValue())
258         {
259             uno::Reference<XNumberFormatsSupplier> xSuppl;
260             aFormats >>= xSuppl;
261             if(xSuppl.is())
262             {
263                 uno::Reference< XPropertySet > xSettings = xSuppl->getNumberFormatSettings();
264                 Any aNull = xSettings->getPropertyValue(C2U("NullDate"));
265                 aNull >>= rParam.aNullDate;
266 				if(rParam.xFormatter.is())
267 					rParam.xFormatter->attachNumberFormatsSupplier(xSuppl);
268             }
269         }
270     }
271 }
272 /* -----------------------------17.07.00 17:04--------------------------------
273 
274  ---------------------------------------------------------------------------*/
275 sal_Bool lcl_MoveAbsolute(SwDSParam* pParam, long nAbsPos)
276 {
277 	sal_Bool bRet = sal_False;
278 	try
279 	{
280 		if(pParam->bScrollable)
281 		{
282 			bRet = pParam->xResultSet->absolute( nAbsPos );
283 		}
284 		else
285 		{
286             DBG_ERROR("no absolute positioning available");
287         }
288 	}
289 	catch(Exception aExcept)
290 	{
291 	}
292 	return bRet;
293 }
294 /* -----------------------------17.07.00 17:23--------------------------------
295 
296  ---------------------------------------------------------------------------*/
297 sal_Bool lcl_GetColumnCnt(SwDSParam* pParam,
298 	const String& rColumnName, long nLanguage, String& rResult, double* pNumber)
299 {
300     uno::Reference< XColumnsSupplier > xColsSupp( pParam->xResultSet, UNO_QUERY );
301     uno::Reference<XNameAccess> xCols;
302     try
303     {
304         xCols = xColsSupp->getColumns();
305     }
306     catch( lang::DisposedException& )
307     {
308     }
309 	if(!xCols.is() || !xCols->hasByName(rColumnName))
310 		return sal_False;
311 	Any aCol = xCols->getByName(rColumnName);
312     uno::Reference< XPropertySet > xColumnProps;
313     aCol >>= xColumnProps;
314 
315 	SwDBFormatData aFormatData;
316     if(!pParam->xFormatter.is())
317 	{
318         uno::Reference<XDataSource> xSource = SwNewDBMgr::getDataSourceAsParent(
319 									pParam->xConnection,pParam->sDataSource);
320         lcl_InitNumberFormatter(*pParam, xSource );
321 	}
322     aFormatData.aNullDate = pParam->aNullDate;
323 	aFormatData.xFormatter = pParam->xFormatter;
324 
325     MsLangId::convertLanguageToLocale( (LanguageType)nLanguage, aFormatData.aLocale );
326 
327 	rResult = SwNewDBMgr::GetDBField( xColumnProps, aFormatData, pNumber);
328 	return sal_True;
329 };
330 /*--------------------------------------------------------------------
331 	Beschreibung: Daten importieren
332  --------------------------------------------------------------------*/
333 sal_Bool SwNewDBMgr::MergeNew(const SwMergeDescriptor& rMergeDesc )
334 {
335     SetMergeType( rMergeDesc.nMergeType );
336 
337     DBG_ASSERT(!bInMerge && !pImpl->pMergeData, "merge already activated!");
338 
339     SwDBData aData;
340     aData.nCommandType = CommandType::TABLE;
341     uno::Reference<XResultSet>  xResSet;
342     Sequence<Any> aSelection;
343     uno::Reference< XConnection> xConnection;
344 
345     aData.sDataSource = rMergeDesc.rDescriptor.getDataSource();
346     rMergeDesc.rDescriptor[daCommand]      >>= aData.sCommand;
347     rMergeDesc.rDescriptor[daCommandType]  >>= aData.nCommandType;
348 
349     if ( rMergeDesc.rDescriptor.has(daCursor) )
350         rMergeDesc.rDescriptor[daCursor] >>= xResSet;
351     if ( rMergeDesc.rDescriptor.has(daSelection) )
352         rMergeDesc.rDescriptor[daSelection] >>= aSelection;
353     if ( rMergeDesc.rDescriptor.has(daConnection) )
354         rMergeDesc.rDescriptor[daConnection] >>= xConnection;
355 
356     if(!aData.sDataSource.getLength() || !aData.sCommand.getLength() || !xResSet.is())
357 	{
358 		return sal_False;
359 	}
360 
361     pImpl->pMergeData = new SwDSParam(aData, xResSet, aSelection);
362     SwDSParam*  pTemp = FindDSData(aData, sal_False);
363 	if(pTemp)
364         *pTemp = *pImpl->pMergeData;
365 	else
366 	{
367         //#94779# calls from the calculator may have added a connection with an invalid commandtype
368         //"real" data base connections added here have to re-use the already available
369         //DSData and set the correct CommandType
370         SwDBData aTempData(aData);
371 		aData.nCommandType = -1;
372 		pTemp = FindDSData(aData, sal_False);
373 		if(pTemp)
374 			*pTemp = *pImpl->pMergeData;
375 		else
376         {
377 			SwDSParam* pInsert = new SwDSParam(*pImpl->pMergeData);
378 			aDataSourceParams.Insert(pInsert, aDataSourceParams.Count());
379 			try
380 			{
381                 uno::Reference<XComponent> xComponent(pInsert->xConnection, UNO_QUERY);
382 				if(xComponent.is())
383 					xComponent->addEventListener(pImpl->xDisposeListener);
384 			}
385 			catch(Exception&)
386 			{
387 			}
388         }
389 	}
390     if(!pImpl->pMergeData->xConnection.is())
391         pImpl->pMergeData->xConnection = xConnection;
392     // add an XEventListener
393 
394 	try{
395 		//set to start position
396         if(pImpl->pMergeData->aSelection.getLength())
397 		{
398 			sal_Int32 nPos = 0;
399 			pImpl->pMergeData->aSelection.getConstArray()[ pImpl->pMergeData->nSelectionIndex++ ] >>= nPos;
400             pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->absolute( nPos );
401             pImpl->pMergeData->CheckEndOfDB();
402             if(pImpl->pMergeData->nSelectionIndex >= pImpl->pMergeData->aSelection.getLength())
403                 pImpl->pMergeData->bEndOfDB = sal_True;
404 		}
405 		else
406 		{
407             pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->first();
408             pImpl->pMergeData->CheckEndOfDB();
409 		}
410 	}
411     catch(Exception&)
412 	{
413         pImpl->pMergeData->bEndOfDB = sal_True;
414         pImpl->pMergeData->CheckEndOfDB();
415 		DBG_ERROR("exception in MergeNew()");
416 	}
417 
418     uno::Reference<XDataSource> xSource = SwNewDBMgr::getDataSourceAsParent(xConnection,aData.sDataSource);
419 
420 	lcl_InitNumberFormatter(*pImpl->pMergeData, xSource);
421 
422     rMergeDesc.rSh.ChgDBData(aData);
423 	bInMerge = sal_True;
424 
425 	if (IsInitDBFields())
426 	{
427 		// Bei Datenbankfeldern ohne DB-Name DB-Name von Dok einsetzen
428 		SvStringsDtor aDBNames(1, 1);
429 		aDBNames.Insert( new String(), 0);
430         SwDBData aInsertData = rMergeDesc.rSh.GetDBData();
431         String sDBName = aInsertData.sDataSource;
432 		sDBName += DB_DELIM;
433         sDBName += (String)aInsertData.sCommand;
434 		sDBName += DB_DELIM;
435         sDBName += String::CreateFromInt32(aInsertData.nCommandType);
436         rMergeDesc.rSh.ChangeDBFields( aDBNames, sDBName);
437 		SetInitDBFields(sal_False);
438 	}
439 
440 	sal_Bool bRet = sal_True;
441     switch(rMergeDesc.nMergeType)
442 	{
443 		case DBMGR_MERGE:
444             bRet = Merge(&rMergeDesc.rSh);   // Mischen
445 			break;
446 
447         case DBMGR_MERGE_MAILMERGE: // printing merge from 'old' merge dialog or from UNO-component
448 		case DBMGR_MERGE_MAILING:
449         case DBMGR_MERGE_MAILFILES:
450         case DBMGR_MERGE_SINGLE_FILE:
451             // save files and send them as e-Mail if required
452             bRet = MergeMailFiles(&rMergeDesc.rSh,
453                     rMergeDesc);
454 			break;
455 
456 		default:    	// Einfuegen der selektierten Eintraege
457 						// (war: InsertRecord)
458             ImportFromConnection(&rMergeDesc.rSh);
459 			break;
460 	}
461 
462 	EndMerge();
463 	return bRet;
464 }
465 
466 /*--------------------------------------------------------------------
467 	Beschreibung: Daten importieren
468  --------------------------------------------------------------------*/
469 
470 
471 sal_Bool SwNewDBMgr::Merge(SwWrtShell* pSh)
472 {
473 	pSh->StartAllAction();
474 
475 	pSh->ViewShell::UpdateFlds(sal_True);
476 	pSh->SetModified();
477 
478 	pSh->EndAllAction();
479 
480 	return sal_True;
481 }
482 
483 /*--------------------------------------------------------------------
484 	Beschreibung:
485  --------------------------------------------------------------------*/
486 void SwNewDBMgr::ImportFromConnection(	SwWrtShell* pSh )
487 {
488     if(pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB)
489 	{
490 		{
491 			pSh->StartAllAction();
492             pSh->StartUndo(UNDO_EMPTY);
493 			sal_Bool bGroupUndo(pSh->DoesGroupUndo());
494 			pSh->DoGroupUndo(sal_False);
495 
496 			if( pSh->HasSelection() )
497 				pSh->DelRight();
498 
499 			SwWait *pWait = 0;
500 
501 			{
502 				sal_uLong i = 0;
503 				do {
504 
505 					ImportDBEntry(pSh);
506 					if( 10 == ++i )
507 						pWait = new SwWait( *pSh->GetView().GetDocShell(), sal_True);
508 
509 				} while(ToNextMergeRecord());
510 			}
511 
512 			pSh->DoGroupUndo(bGroupUndo);
513             pSh->EndUndo(UNDO_EMPTY);
514 			pSh->EndAllAction();
515 			delete pWait;
516 		}
517 	}
518 }
519 /*-----------------24.02.97 10.30-------------------
520 
521 --------------------------------------------------*/
522 
523 String 	lcl_FindColumn(const String& sFormatStr,sal_uInt16  &nUsedPos, sal_uInt8 &nSeparator)
524 {
525 	String sReturn;
526 	sal_uInt16 nLen = sFormatStr.Len();
527 	nSeparator = 0xff;
528 	while(nUsedPos < nLen && nSeparator == 0xff)
529 	{
530 		sal_Unicode cAkt = sFormatStr.GetChar(nUsedPos);
531 		switch(cAkt)
532 		{
533 			case ',':
534 				nSeparator = DB_SEP_SPACE;
535 			break;
536 			case ';':
537 				nSeparator = DB_SEP_RETURN;
538 			break;
539 			case ':':
540 				nSeparator = DB_SEP_TAB;
541 			break;
542 			case '#':
543 				nSeparator = DB_SEP_NEWLINE;
544 			break;
545 			default:
546 				sReturn += cAkt;
547 		}
548 		nUsedPos++;
549 
550 	}
551 	return sReturn;
552 }
553 
554 /*--------------------------------------------------------------------
555 	Beschreibung:
556  --------------------------------------------------------------------*/
557 void SwNewDBMgr::ImportDBEntry(SwWrtShell* pSh)
558 {
559     if(pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB)
560 	{
561         uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY );
562         uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
563         String sFormatStr;
564 		sal_uInt16 nFmtLen = sFormatStr.Len();
565 		if( nFmtLen )
566 		{
567 			const char cSpace = ' ';
568 			const char cTab = '\t';
569 			sal_uInt16 nUsedPos = 0;
570 			sal_uInt8	nSeparator;
571 			String sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator);
572 			while( sColumn.Len() )
573 			{
574 				if(!xCols->hasByName(sColumn))
575 					return;
576 				Any aCol = xCols->getByName(sColumn);
577                 uno::Reference< XPropertySet > xColumnProp;
578                 aCol >>= xColumnProp;
579 				if(xColumnProp.is())
580 				{
581 					SwDBFormatData aDBFormat;
582 					String sInsert = GetDBField( xColumnProp,	aDBFormat);
583 					if( DB_SEP_SPACE == nSeparator )
584 							sInsert += cSpace;
585 					else if( DB_SEP_TAB == nSeparator)
586 							sInsert += cTab;
587 					pSh->Insert(sInsert);
588 					if( DB_SEP_RETURN == nSeparator)
589 						pSh->SplitNode();
590 					else if(DB_SEP_NEWLINE == nSeparator)
591 							pSh->InsertLineBreak();
592 				}
593 				else
594 				{
595 					// Spalte nicht gefunden -> Fehler anzeigen
596 					String sInsert = '?';
597 					sInsert += sColumn;
598 					sInsert += '?';
599 					pSh->Insert(sInsert);
600 				}
601 				sColumn = lcl_FindColumn(sFormatStr, nUsedPos, nSeparator);
602 			}
603 			pSh->SplitNode();
604 		}
605 		else
606 		{
607 			String sStr;
608             Sequence<rtl::OUString> aColNames = xCols->getElementNames();
609             const rtl::OUString* pColNames = aColNames.getConstArray();
610 			long nLength = aColNames.getLength();
611 			for(long i = 0; i < nLength; i++)
612 			{
613 				Any aCol = xCols->getByName(pColNames[i]);
614                 uno::Reference< XPropertySet > xColumnProp;
615                 aCol >>= xColumnProp;
616 				SwDBFormatData aDBFormat;
617 				sStr += GetDBField( xColumnProp, aDBFormat);
618 				if (i < nLength - 1)
619 					sStr += '\t';
620 			}
621             pSh->SwEditShell::Insert2(sStr);
622 			pSh->SwFEShell::SplitNode();	// Zeilenvorschub
623 		}
624 	}
625 }
626 /*--------------------------------------------------------------------
627 	Beschreibung: Listbox mit Tabellenliste fuellen
628  --------------------------------------------------------------------*/
629 sal_Bool SwNewDBMgr::GetTableNames(ListBox* pListBox, const String& rDBName)
630 {
631 	sal_Bool bRet = sal_False;
632     String sOldTableName(pListBox->GetSelectEntry());
633 	pListBox->Clear();
634     SwDSParam* pParam = FindDSConnection(rDBName, sal_False);
635     uno::Reference< XConnection> xConnection;
636     if(pParam && pParam->xConnection.is())
637         xConnection = pParam->xConnection;
638     else
639     {
640         rtl::OUString sDBName(rDBName);
641         if ( sDBName.getLength() )
642             xConnection = RegisterConnection( sDBName );
643     }
644 	if(xConnection.is())
645 	{
646         uno::Reference<XTablesSupplier> xTSupplier = uno::Reference<XTablesSupplier>(xConnection, UNO_QUERY);
647 		if(xTSupplier.is())
648 		{
649             uno::Reference<XNameAccess> xTbls = xTSupplier->getTables();
650             Sequence<rtl::OUString> aTbls = xTbls->getElementNames();
651             const rtl::OUString* pTbls = aTbls.getConstArray();
652 			for(long i = 0; i < aTbls.getLength(); i++)
653             {
654                 sal_uInt16 nEntry = pListBox->InsertEntry(pTbls[i]);
655                 pListBox->SetEntryData(nEntry, (void*)0);
656             }
657 		}
658         uno::Reference<XQueriesSupplier> xQSupplier = uno::Reference<XQueriesSupplier>(xConnection, UNO_QUERY);
659 		if(xQSupplier.is())
660 		{
661             uno::Reference<XNameAccess> xQueries = xQSupplier->getQueries();
662             Sequence<rtl::OUString> aQueries = xQueries->getElementNames();
663             const rtl::OUString* pQueries = aQueries.getConstArray();
664 			for(long i = 0; i < aQueries.getLength(); i++)
665             {
666                 sal_uInt16 nEntry = pListBox->InsertEntry(pQueries[i]);
667                 pListBox->SetEntryData(nEntry, (void*)1);
668             }
669         }
670 		if (sOldTableName.Len())
671 			pListBox->SelectEntry(sOldTableName);
672 		bRet = sal_True;
673 	}
674 	return bRet;
675 }
676 
677 /*--------------------------------------------------------------------
678 	Beschreibung: Listbox mit Spaltennamen einer Datenbank fuellen
679  --------------------------------------------------------------------*/
680 sal_Bool SwNewDBMgr::GetColumnNames(ListBox* pListBox,
681 			const String& rDBName, const String& rTableName, sal_Bool bAppend)
682 {
683 	if (!bAppend)
684 		pListBox->Clear();
685     SwDBData aData;
686     aData.sDataSource = rDBName;
687     aData.sCommand = rTableName;
688     aData.nCommandType = -1;
689     SwDSParam* pParam = FindDSData(aData, sal_False);
690     uno::Reference< XConnection> xConnection;
691     if(pParam && pParam->xConnection.is())
692         xConnection = pParam->xConnection;
693     else
694     {
695         rtl::OUString sDBName(rDBName);
696         xConnection = RegisterConnection( sDBName );
697     }
698     uno::Reference< XColumnsSupplier> xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName);
699 	if(xColsSupp.is())
700 	{
701         uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
702         const Sequence<rtl::OUString> aColNames = xCols->getElementNames();
703         const rtl::OUString* pColNames = aColNames.getConstArray();
704 		for(int nCol = 0; nCol < aColNames.getLength(); nCol++)
705 		{
706 			pListBox->InsertEntry(pColNames[nCol]);
707 		}
708         ::comphelper::disposeComponent( xColsSupp );
709     }
710     return(sal_True);
711 }
712 /* -----------------------------08.06.01 15:11--------------------------------
713 
714  ---------------------------------------------------------------------------*/
715 sal_Bool SwNewDBMgr::GetColumnNames(ListBox* pListBox,
716         uno::Reference< XConnection> xConnection,
717         const String& rTableName, sal_Bool bAppend)
718 {
719 	if (!bAppend)
720 		pListBox->Clear();
721     uno::Reference< XColumnsSupplier> xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName);
722 	if(xColsSupp.is())
723 	{
724         uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
725         const Sequence<rtl::OUString> aColNames = xCols->getElementNames();
726         const rtl::OUString* pColNames = aColNames.getConstArray();
727 		for(int nCol = 0; nCol < aColNames.getLength(); nCol++)
728 		{
729 			pListBox->InsertEntry(pColNames[nCol]);
730 		}
731         ::comphelper::disposeComponent( xColsSupp );
732     }
733 	return(sal_True);
734 }
735 
736 /*--------------------------------------------------------------------
737 	Beschreibung: CTOR
738  --------------------------------------------------------------------*/
739 
740 SwNewDBMgr::SwNewDBMgr() :
741             nMergeType(DBMGR_INSERT),
742             bInitDBFields(sal_False),
743             bInMerge(sal_False),
744             bMergeSilent(sal_False),
745             bMergeLock(sal_False),
746             pImpl(new SwNewDBMgr_Impl(*this)),
747             pMergeEvtSrc(NULL)
748 {
749 }
750 /* -----------------------------18.07.00 08:56--------------------------------
751 
752  ---------------------------------------------------------------------------*/
753 SwNewDBMgr::~SwNewDBMgr()
754 {
755     for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.Count(); nPos++)
756     {
757         SwDSParam* pParam = aDataSourceParams[nPos];
758         if(pParam->xConnection.is())
759         {
760             try
761             {
762                 uno::Reference<XComponent> xComp(pParam->xConnection, UNO_QUERY);
763                 if(xComp.is())
764                     xComp->dispose();
765             }
766             catch(const RuntimeException& )
767             {
768                 //may be disposed already since multiple entries may have used the same connection
769             }
770         }
771     }
772     delete pImpl;
773 }
774 
775 /*--------------------------------------------------------------------
776 	Beschreibung:	Serienbriefe als einzelne Dokumente speichern
777  --------------------------------------------------------------------*/
778 String lcl_FindUniqueName(SwWrtShell* pTargetShell, const String& rStartingPageDesc, sal_uLong nDocNo )
779 {
780     do
781     {
782         String sTest = rStartingPageDesc;
783         sTest += String::CreateFromInt32( nDocNo );
784         if( !pTargetShell->FindPageDescByName( sTest ) )
785             return sTest;
786         ++nDocNo;
787     }while(true);
788 }
789 void lcl_CopyDynamicDefaults( const SwDoc& rSource, SwDoc& rTarget )
790 {
791     sal_uInt16 __FAR_DATA aRangeOfDefaults[] = {
792         RES_FRMATR_BEGIN, RES_FRMATR_END-1,
793         RES_CHRATR_BEGIN, RES_CHRATR_END-1,
794         RES_PARATR_BEGIN, RES_PARATR_END-1,
795         // --> OD 2008-02-25 #refactorlists##
796         RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
797         // <--
798         RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END-1,
799         0
800     };
801 
802     SfxItemSet aNewDefaults( rTarget.GetAttrPool(), aRangeOfDefaults );
803 
804     sal_uInt16 nWhich;
805     sal_uInt16 nRange = 0;
806     while( aRangeOfDefaults[nRange] != 0)
807     {
808         for( nWhich = aRangeOfDefaults[nRange]; nWhich < aRangeOfDefaults[nRange + 1]; ++nWhich )
809         {
810             const SfxPoolItem& rSourceAttr = rSource.GetDefault( nWhich );
811             if( rSourceAttr != rTarget.GetDefault( nWhich ) )
812                 aNewDefaults.Put( rSourceAttr );
813         }
814         nRange += 2;
815     }
816     if( aNewDefaults.Count() )
817         rTarget.SetDefault( aNewDefaults );
818 }
819 void lcl_CopyFollowPageDesc(
820                             SwWrtShell& rTargetShell,
821                             const SwPageDesc& rSourcePageDesc,
822                             const SwPageDesc& rTargetPageDesc,
823                             const sal_uLong nDocNo )
824 {
825     //now copy the follow page desc, too
826     const SwPageDesc* pFollowPageDesc = rSourcePageDesc.GetFollow();
827     String sFollowPageDesc = pFollowPageDesc->GetName();
828     if( sFollowPageDesc != rSourcePageDesc.GetName() )
829     {
830         SwDoc* pTargetDoc = rTargetShell.GetDoc();
831         String sNewFollowPageDesc = lcl_FindUniqueName(&rTargetShell, sFollowPageDesc, nDocNo );
832         sal_uInt16 nNewDesc = pTargetDoc->MakePageDesc( sNewFollowPageDesc );
833         SwPageDesc& rTargetFollowPageDesc = pTargetDoc->_GetPageDesc( nNewDesc );
834 
835         pTargetDoc->CopyPageDesc( *pFollowPageDesc, rTargetFollowPageDesc, sal_False );
836         SwPageDesc aDesc( rTargetPageDesc );
837         aDesc.SetFollow( &rTargetFollowPageDesc );
838         pTargetDoc->ChgPageDesc( rTargetPageDesc.GetName(), aDesc );
839     }
840 }
841 
842 void lcl_RemoveSectionLinks( SwWrtShell& rWorkShell )
843 {
844     //reset all links of the sections of synchronized labels
845     sal_uInt16 nSections = rWorkShell.GetSectionFmtCount();
846     for( sal_uInt16 nSection = 0; nSection < nSections; ++nSection )
847     {
848         SwSectionData aSectionData( *rWorkShell.GetSectionFmt( nSection ).GetSection() );
849         if( aSectionData.GetType() == FILE_LINK_SECTION )
850         {
851             aSectionData.SetType( CONTENT_SECTION );
852             aSectionData.SetLinkFileName( String() );
853             rWorkShell.UpdateSection( nSection, aSectionData );
854         }
855     }
856     rWorkShell.SetLabelDoc( sal_False );
857 }
858 
859 sal_Bool SwNewDBMgr::MergeMailFiles(SwWrtShell* pSourceShell,
860         const SwMergeDescriptor& rMergeDescriptor)
861 {
862 	//check if the doc is synchronized and contains at least one linked section
863     sal_Bool bSynchronizedDoc = pSourceShell->IsLabelDoc() && pSourceShell->GetSectionFmtCount() > 1;
864 	sal_Bool bLoop = sal_True;
865     sal_Bool bEMail = rMergeDescriptor.nMergeType == DBMGR_MERGE_MAILING;
866     const bool bAsSingleFile = rMergeDescriptor.nMergeType == DBMGR_MERGE_SINGLE_FILE;
867 
868     ::rtl::Reference< MailDispatcher >          xMailDispatcher;
869     ::rtl::OUString sBodyMimeType;
870     rtl_TextEncoding eEncoding = ::gsl_getSystemTextEncoding();
871 
872     if(bEMail)
873     {
874         xMailDispatcher.set( new MailDispatcher(rMergeDescriptor.xSmtpServer));
875         if(!rMergeDescriptor.bSendAsAttachment && rMergeDescriptor.bSendAsHTML)
876         {
877             sBodyMimeType = ::rtl::OUString::createFromAscii("text/html; charset=");
878             sBodyMimeType += ::rtl::OUString::createFromAscii(
879                                 rtl_getBestMimeCharsetFromTextEncoding( eEncoding ));
880             SvxHtmlOptions* pHtmlOptions = SvxHtmlOptions::Get();
881             eEncoding = pHtmlOptions->GetTextEncoding();
882         }
883         else
884             sBodyMimeType =
885                 ::rtl::OUString::createFromAscii("text/plain; charset=UTF-8; format=flowed");
886     }
887 
888     uno::Reference< XPropertySet > xColumnProp;
889 	{
890 		sal_Bool bColumnName = sEMailAddrFld.Len() > 0;
891 
892 		if (bColumnName)
893 		{
894             uno::Reference< XColumnsSupplier > xColsSupp( pImpl->pMergeData->xResultSet, UNO_QUERY );
895             uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
896 			if(!xCols->hasByName(sEMailAddrFld))
897 				return sal_False;
898 			Any aCol = xCols->getByName(sEMailAddrFld);
899             aCol >>= xColumnProp;
900 		}
901 
902         SfxDispatcher* pSfxDispatcher = pSourceShell->GetView().GetViewFrame()->GetDispatcher();
903         SwDocShell* pSourrceDocSh = pSourceShell->GetView().GetDocShell();
904         pSfxDispatcher->Execute( pSourrceDocSh->HasName() ? SID_SAVEDOC : SID_SAVEASDOC, SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD);
905         // has document been saved successfully?
906         if( !pSourrceDocSh->IsModified() )
907 		{
908             SfxMedium* pOrig = pSourceShell->GetView().GetDocShell()->GetMedium();
909             String sSourceDocumentURL(pOrig->GetURLObject().GetMainURL( INetURLObject::NO_DECODE ));
910 			const SfxFilter* pSfxFlt = SwIoSystem::GetFileFilter(
911                                                     sSourceDocumentURL, ::aEmptyStr );
912             const SfxFilter* pStoreToFilter = pSfxFlt;
913             SfxFilterContainer* pFilterContainer = SwDocShell::Factory().GetFilterContainer();
914             const String* pStoreToFilterOptions = 0;
915             // if a save_to filter is set then use it - otherwise use the default
916             if( bEMail && !rMergeDescriptor.bSendAsAttachment )
917             {
918                 String sExtension( String::CreateFromAscii(
919                         rMergeDescriptor.bSendAsHTML ? "html" : "txt" ));
920                 pStoreToFilter = pFilterContainer->GetFilter4Extension(sExtension, SFX_FILTER_EXPORT);
921             }
922             else if( rMergeDescriptor.sSaveToFilter.Len())
923             {
924                 const SfxFilter* pFilter =
925                         pFilterContainer->GetFilter4FilterName( rMergeDescriptor.sSaveToFilter );
926                 if(pFilter)
927                 {
928                     pStoreToFilter = pFilter;
929                     if(rMergeDescriptor.sSaveToFilterOptions.Len())
930                         pStoreToFilterOptions = &rMergeDescriptor.sSaveToFilterOptions;
931                 }
932             }
933 			bCancel = sal_False;
934 
935             // in case of creating a single resulting file this has to be created here
936             SwWrtShell* pTargetShell = 0;
937 
938             // the shell will be explicitly closed at the end of the method, but it is
939             // still more safe to use SfxObjectShellLock here
940             SfxObjectShellLock xTargetDocShell;
941 
942             SwView* pTargetView = 0;
943             std::auto_ptr< utl::TempFile > aTempFile;
944             String sModifiedStartingPageDesc;
945             String sStartingPageDesc;
946             sal_uInt16 nStartingPageNo = 0;
947             bool bPageStylesWithHeaderFooter = false;
948             if(bAsSingleFile || rMergeDescriptor.bCreateSingleFile)
949             {
950                 // create a target docshell to put the merged document into
951                 xTargetDocShell = new SwDocShell( SFX_CREATE_MODE_STANDARD );
952                 xTargetDocShell->DoInitNew( 0 );
953                 SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
954 
955                 pTargetView = static_cast<SwView*>( pTargetFrame->GetViewShell() );
956 
957                 //initiate SelectShell() to create sub shells
958                 pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
959                 pTargetShell = pTargetView->GetWrtShellPtr();
960                 //copy the styles from the source to the target document
961                 SwgReaderOption aOpt;
962                 aOpt.SetTxtFmts( sal_True );
963                 aOpt.SetFrmFmts( sal_True );
964                 aOpt.SetPageDescs( sal_True );
965                 aOpt.SetNumRules( sal_True );
966                 aOpt.SetMerge( sal_False );
967                 pTargetView->GetDocShell()->LoadStylesFromFile(
968                         sSourceDocumentURL, aOpt, sal_True );
969                 //determine the page style and number used at the start of the source document
970                 pSourceShell->SttEndDoc(sal_True);
971                 nStartingPageNo = pSourceShell->GetVirtPageNum();
972                 sStartingPageDesc = sModifiedStartingPageDesc = pSourceShell->GetPageDesc(
973                                             pSourceShell->GetCurPageDesc()).GetName();
974                 // #122799# copy compatibility options
975                 lcl_CopyCompatibilityOptions( *pSourceShell, *pTargetShell);
976                 // #72821# copy dynamic defaults
977                 lcl_CopyDynamicDefaults( *pSourceShell->GetDoc(), *pTargetShell->GetDoc() );
978                 // #i72517#
979                 const SwPageDesc* pSourcePageDesc = pSourceShell->FindPageDescByName( sStartingPageDesc );
980                 const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
981                 bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive()  ||
982                                                 rMaster.GetFooter().IsActive();
983 
984             }
985 
986             PrintMonitor aPrtMonDlg(&pSourceShell->GetView().GetEditWin(), PrintMonitor::MONITOR_TYPE_PRINT);
987             aPrtMonDlg.aDocName.SetText(pSourceShell->GetView().GetDocShell()->GetTitle(22));
988 
989 			aPrtMonDlg.aCancel.SetClickHdl(LINK(this, SwNewDBMgr, PrtCancelHdl));
990             if (!IsMergeSilent())
991                 aPrtMonDlg.Show();
992 
993 			// Progress, um KeyInputs zu unterbinden
994             SfxProgress aProgress(pSourrceDocSh, ::aEmptyStr, 1);
995 
996 			// Alle Dispatcher sperren
997             SfxViewFrame* pViewFrm = SfxViewFrame::GetFirst(pSourrceDocSh);
998 			while (pViewFrm)
999 			{
1000 				pViewFrm->GetDispatcher()->Lock(sal_True);
1001                 pViewFrm = SfxViewFrame::GetNext(*pViewFrm, pSourrceDocSh);
1002 			}
1003 			sal_uLong nDocNo = 1;
1004 
1005             long nStartRow, nEndRow;
1006             // collect temporary files
1007             ::std::vector< String> aFilesToRemove;
1008             do
1009             {
1010                 nStartRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
1011                 {
1012 					String sPath(sSubject);
1013 
1014                     String sAddress;
1015                     if( !bEMail && bColumnName )
1016 					{
1017 						SwDBFormatData aDBFormat;
1018 						aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
1019 						aDBFormat.aNullDate = pImpl->pMergeData->aNullDate;
1020 						sAddress = GetDBField( xColumnProp,	aDBFormat);
1021 						if (!sAddress.Len())
1022 							sAddress = '_';
1023 						sPath += sAddress;
1024 					}
1025 
1026                     // create a new temporary file name - only done once in case of bCreateSingleFile
1027                     if( 1 == nDocNo || (!rMergeDescriptor.bCreateSingleFile && !bAsSingleFile) )
1028                     {
1029                         INetURLObject aEntry(sPath);
1030                         String sLeading;
1031                         //#i97667# if the name is from a database field then it will be used _as is_
1032                         if( sAddress.Len() )
1033                             sLeading = sAddress;
1034                         else
1035                             sLeading = aEntry.GetBase();
1036                         aEntry.removeSegment();
1037                         sPath = aEntry.GetMainURL( INetURLObject::NO_DECODE );
1038                         String sExt( pStoreToFilter->GetDefaultExtension() );
1039                         sExt.EraseLeadingChars('*');
1040                         aTempFile = std::auto_ptr< utl::TempFile >(
1041                                 new utl::TempFile(sLeading,&sExt,&sPath ));
1042                         if( bAsSingleFile )
1043                             aTempFile->EnableKillingFile();
1044                     }
1045 
1046                     if( !aTempFile->IsValid() )
1047 					{
1048 						ErrorHandler::HandleError( ERRCODE_IO_NOTSUPPORTED );
1049 						bLoop = sal_False;
1050 						bCancel = sal_True;
1051 					}
1052 					else
1053 					{
1054                         INetURLObject aTempFileURL(aTempFile->GetURL());
1055                         aPrtMonDlg.aPrinter.SetText( aTempFileURL.GetBase() );
1056 						String sStat(SW_RES(STR_STATSTR_LETTER));	// Brief
1057 						sStat += ' ';
1058 						sStat += String::CreateFromInt32( nDocNo );
1059 						aPrtMonDlg.aPrintInfo.SetText(sStat);
1060 
1061 						// Rechenzeit fuer Save-Monitor:
1062 						for (sal_uInt16 i = 0; i < 10; i++)
1063 							Application::Reschedule();
1064 
1065 						// Create and save new document
1066                         // The SfxObjectShell will be closed explicitly later but it is more safe to use SfxObjectShellLock here
1067                         SfxObjectShellLock xWorkDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
1068                         SfxMedium* pWorkMed = new SfxMedium( sSourceDocumentURL, STREAM_STD_READ, sal_True );
1069                         pWorkMed->SetFilter( pSfxFlt );
1070 
1071                         if (xWorkDocSh->DoLoad(pWorkMed))
1072 						{
1073                             //create a view frame for the document
1074                             SfxViewFrame* pWorkFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 );
1075                             //request the layout calculation
1076                             SwWrtShell& rWorkShell =
1077                                     static_cast< SwView* >(pWorkFrame->GetViewShell())->GetWrtShell();
1078                             rWorkShell.CalcLayout();
1079                             SwDoc* pWorkDoc = ((SwDocShell*)(&xWorkDocSh))->GetDoc();
1080                             SwNewDBMgr* pOldDBMgr = pWorkDoc->GetNewDBMgr();
1081                             pWorkDoc->SetNewDBMgr( this );
1082                             SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), xWorkDocSh));
1083                             pWorkDoc->UpdateFlds(NULL, false);
1084                             SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), xWorkDocSh));
1085 
1086 							// alle versteckten Felder/Bereiche entfernen
1087                             pWorkDoc->RemoveInvisibleContent();
1088 
1089                             // launch MailMergeEvent if required
1090                             const SwXMailMerge *pEvtSrc = GetMailMergeEvtSrc();
1091                             if(pEvtSrc)
1092                             {
1093                                 uno::Reference< XInterface > xRef( (XMailMergeBroadcaster *) pEvtSrc );
1094                                 text::MailMergeEvent aEvt( xRef, xWorkDocSh->GetModel() );
1095                                 pEvtSrc->LaunchMailMergeEvent( aEvt );
1096                             }
1097 
1098                             if(rMergeDescriptor.bCreateSingleFile || bAsSingleFile )
1099                             {
1100                                 DBG_ASSERT( pTargetShell, "no target shell available!" );
1101                                 // copy created file into the target document
1102                                 rWorkShell.ConvertFieldsToText();
1103                                 rWorkShell.SetNumberingRestart();
1104                                 if( bSynchronizedDoc )
1105                                 {
1106                                     lcl_RemoveSectionLinks( rWorkShell );
1107                                 }
1108 
1109                                 // insert the document into the target document
1110                                 rWorkShell.SttEndDoc(sal_False);
1111                                 rWorkShell.SttEndDoc(sal_True);
1112                                 rWorkShell.SelAll();
1113                                 pTargetShell->SwCrsrShell::SttEndDoc( sal_False );
1114                                 //#i72517# the headers and footers are still those from the source - update in case of fields inside header/footer
1115                                 if( !nDocNo && bPageStylesWithHeaderFooter )
1116                                     pTargetShell->GetView().GetDocShell()->_LoadStyles( *rWorkShell.GetView().GetDocShell(), sal_True );
1117                                 //#i72517# put the styles to the target document
1118                                 //if the source uses headers or footers each new copy need to copy a new page styles
1119                                 if(bPageStylesWithHeaderFooter)
1120                                 {
1121                                     //create a new pagestyle
1122                                     //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style
1123 
1124                                     SwDoc* pTargetDoc = pTargetShell->GetDoc();
1125                                     SwPageDesc* pSourcePageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
1126                                     String sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
1127                                     pTargetDoc->MakePageDesc( sNewPageDescName );
1128                                     SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
1129                                     if(pSourcePageDesc && pTargetPageDesc)
1130                                     {
1131                                         pTargetDoc->CopyPageDesc( *pSourcePageDesc, *pTargetPageDesc, sal_False );
1132                                         sModifiedStartingPageDesc = sNewPageDescName;
1133                                         lcl_CopyFollowPageDesc( *pTargetShell, *pSourcePageDesc, *pTargetPageDesc, nDocNo );
1134                                     }
1135                                 }
1136 
1137                                 if(nDocNo > 1)
1138                                     pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo );
1139                                 else
1140                                     pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
1141                                 DBG_ASSERT(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
1142                                 //#i51359# add a second paragraph in case there's only one
1143                                 {
1144                                     SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 );
1145                                     SwPosition aTestPos( aIdx );
1146                                     SwCursor aTestCrsr(aTestPos,0,false);
1147                                     if(!aTestCrsr.MovePara(fnParaNext, fnParaStart))
1148                                     {
1149                                         //append a paragraph
1150                                         pWorkDoc->AppendTxtNode( aTestPos );
1151                                     }
1152                                 }
1153                                 pTargetShell->Paste( rWorkShell.GetDoc(), sal_True );
1154 
1155                                 //convert fields in page styles (header/footer - has to be done after the first document has been pasted
1156                                 if(1 == nDocNo)
1157                                 {
1158                                     pTargetShell->CalcLayout();
1159                                     pTargetShell->ConvertFieldsToText();
1160                                 }
1161                             }
1162                             else
1163                             {
1164                                 String sFileURL =  aTempFileURL.GetMainURL( INetURLObject::NO_DECODE );
1165                                 SfxMedium* pDstMed = new SfxMedium(
1166                                     sFileURL,
1167                                     STREAM_STD_READWRITE, sal_True );
1168                                 pDstMed->SetFilter( pStoreToFilter );
1169                                 if(pDstMed->GetItemSet())
1170                                 {
1171                                     if(pStoreToFilterOptions )
1172                                         pDstMed->GetItemSet()->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, *pStoreToFilterOptions));
1173                                     if(rMergeDescriptor.aSaveToFilterData.getLength())
1174                                         pDstMed->GetItemSet()->Put(SfxUsrAnyItem(SID_FILTER_DATA, makeAny(rMergeDescriptor.aSaveToFilterData)));
1175                                 }
1176 
1177                                 //convert fields to text if we are exporting to PDF
1178                                 //this prevents a second merge while updating the fields in SwXTextDocument::getRendererCount()
1179                                 if( pStoreToFilter && pStoreToFilter->GetFilterName().EqualsAscii("writer_pdf_Export"))
1180                                     rWorkShell.ConvertFieldsToText();
1181                                 xWorkDocSh->DoSaveAs(*pDstMed);
1182                                 xWorkDocSh->DoSaveCompleted(pDstMed);
1183                                 if( xWorkDocSh->GetError() )
1184                                 {
1185                                     // error message ??
1186                                     ErrorHandler::HandleError( xWorkDocSh->GetError() );
1187                                     bCancel = sal_True;
1188                                     bLoop = sal_False;
1189                                 }
1190                                 if( bEMail )
1191                                 {
1192                                     SwDBFormatData aDBFormat;
1193                                     aDBFormat.xFormatter = pImpl->pMergeData->xFormatter;
1194                                     aDBFormat.aNullDate = pImpl->pMergeData->aNullDate;
1195                                     String sMailAddress = GetDBField( xColumnProp, aDBFormat);
1196                                     if(!SwMailMergeHelper::CheckMailAddress( sMailAddress ))
1197                                     {
1198                                         DBG_ERROR("invalid e-Mail address in database column");
1199                                     }
1200                                     else
1201                                     {
1202                                         SwMailMessage* pMessage = 0;
1203                                         uno::Reference< mail::XMailMessage > xMessage =
1204                                                                 pMessage = new SwMailMessage;
1205                                         if(rMergeDescriptor.pMailMergeConfigItem->IsMailReplyTo())
1206                                             pMessage->setReplyToAddress(rMergeDescriptor.pMailMergeConfigItem->GetMailReplyTo());
1207                                         pMessage->addRecipient( sMailAddress );
1208                                         pMessage->SetSenderAddress( rMergeDescriptor.pMailMergeConfigItem->GetMailAddress() );
1209                                         ::rtl::OUString sBody;
1210                                         if(rMergeDescriptor.bSendAsAttachment)
1211                                         {
1212                                             sBody = rMergeDescriptor.sMailBody;
1213                                             mail::MailAttachment aAttach;
1214                                             aAttach.Data = new SwMailTransferable(
1215                                                     sFileURL,
1216                                                     rMergeDescriptor.sAttachmentName,
1217                                                     pStoreToFilter->GetMimeType());
1218                                             aAttach.ReadableName = rMergeDescriptor.sAttachmentName;
1219                                             pMessage->addAttachment( aAttach );
1220                                         }
1221                                         else
1222                                         {
1223                                             {
1224                                                 //read in the temporary file and use it as mail body
1225                                                 SfxMedium aMedium( sFileURL, STREAM_READ, sal_True);
1226                                                 SvStream* pInStream = aMedium.GetInStream();
1227                                                 DBG_ASSERT(pInStream, "no output file created?");
1228                                                 if(pInStream)
1229                                                 {
1230                                                     pInStream->SetStreamCharSet( eEncoding );
1231                                                     ByteString sLine;
1232                                                     sal_Bool bDone = pInStream->ReadLine( sLine );
1233                                                     while ( bDone )
1234                                                     {
1235                                                         sBody += String(sLine, eEncoding);
1236                                                         sBody += ::rtl::OUString('\n');
1237                                                         bDone = pInStream->ReadLine( sLine );
1238                                                     }
1239                                                 }
1240                                             }
1241                                         }
1242                                         pMessage->setSubject( rMergeDescriptor.sSubject );
1243                                         uno::Reference< datatransfer::XTransferable> xBody =
1244                                                     new SwMailTransferable(
1245                                                         sBody,
1246                                                         sBodyMimeType);
1247                                         pMessage->setBody( xBody );
1248 
1249                                         if(rMergeDescriptor.aCopiesTo.getLength())
1250                                         {
1251                                             const ::rtl::OUString* pCopies = rMergeDescriptor.aCopiesTo.getConstArray();
1252                                             for( sal_Int32 nToken = 0; nToken < rMergeDescriptor.aCopiesTo.getLength(); ++nToken)
1253                                                 pMessage->addCcRecipient( pCopies[nToken] );
1254                                         }
1255                                         if(rMergeDescriptor.aBlindCopiesTo.getLength())
1256                                         {
1257                                             const ::rtl::OUString* pCopies = rMergeDescriptor.aBlindCopiesTo.getConstArray();
1258                                             for( sal_Int32 nToken = 0; nToken < rMergeDescriptor.aBlindCopiesTo.getLength(); ++nToken)
1259                                                 pMessage->addBccRecipient( pCopies[nToken] );
1260                                         }
1261                                         xMailDispatcher->enqueueMailMessage( xMessage );
1262                                         if(!xMailDispatcher->isStarted())
1263                                                 xMailDispatcher->start();
1264                                         //schedule for removal
1265                                         aFilesToRemove.push_back(sFileURL);
1266                                     }
1267                                 }
1268                             }
1269                             pWorkDoc->SetNewDBMgr( pOldDBMgr );
1270 						}
1271                         xWorkDocSh->DoClose();
1272 					}
1273 				}
1274                 nDocNo++;
1275                 nEndRow = pImpl->pMergeData ? pImpl->pMergeData->xResultSet->getRow() : 0;
1276             } while( !bCancel &&
1277                 (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
1278 
1279             aPrtMonDlg.Show( sal_False );
1280 
1281             // save the single output document
1282             if(rMergeDescriptor.bCreateSingleFile || bAsSingleFile)
1283             {
1284                 if( rMergeDescriptor.nMergeType != DBMGR_MERGE_MAILMERGE )
1285                 {
1286                     DBG_ASSERT( aTempFile.get(), "Temporary file not available" );
1287                     INetURLObject aTempFileURL(bAsSingleFile ? sSubject : aTempFile->GetURL());
1288                     SfxMedium* pDstMed = new SfxMedium(
1289                         aTempFileURL.GetMainURL( INetURLObject::NO_DECODE ),
1290                         STREAM_STD_READWRITE, sal_True );
1291                     pDstMed->SetFilter( pStoreToFilter );
1292                     if(pDstMed->GetItemSet())
1293                     {
1294                         if(pStoreToFilterOptions )
1295                             pDstMed->GetItemSet()->Put(SfxStringItem(SID_FILE_FILTEROPTIONS, *pStoreToFilterOptions));
1296                         if(rMergeDescriptor.aSaveToFilterData.getLength())
1297                             pDstMed->GetItemSet()->Put(SfxUsrAnyItem(SID_FILTER_DATA, makeAny(rMergeDescriptor.aSaveToFilterData)));
1298                     }
1299 
1300                     xTargetDocShell->DoSaveAs(*pDstMed);
1301                     xTargetDocShell->DoSaveCompleted(pDstMed);
1302                     if( xTargetDocShell->GetError() )
1303                     {
1304                         // error message ??
1305                         ErrorHandler::HandleError( xTargetDocShell->GetError() );
1306                         bLoop = sal_False;
1307                     }
1308                 }
1309                 else if( pTargetView ) // must be available!
1310                 {
1311                     //print the target document
1312         #if OSL_DEBUG_LEVEL > 1
1313                     sal_Bool  _bVal;
1314                     sal_Int16 _nVal;
1315                     rtl::OUString  _sVal;
1316                     const beans::PropertyValue* pDbgPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray();
1317                     for( sal_Int32 nOption = 0; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption)
1318                     {
1319                         rtl::OUString aName( pDbgPrintOptions[nOption].Name );
1320                         uno::Any aVal( pDbgPrintOptions[nOption].Value );
1321                         aVal >>= _bVal;
1322                         aVal >>= _nVal;
1323                         aVal >>= _sVal;
1324                     }
1325         #endif
1326                     // printing should be done synchronously otherwise the document
1327                     // might already become invalid during the process
1328                     uno::Sequence< beans::PropertyValue > aOptions( rMergeDescriptor.aPrintOptions );
1329                     const sal_Int32 nOpts = aOptions.getLength();
1330                     aOptions.realloc( nOpts + 1 );
1331                     aOptions[ nOpts ].Name = rtl::OUString::createFromAscii( "Wait" );
1332                     aOptions[ nOpts ].Value <<= sal_True ;
1333 //                    aPrintArgs.Put(SfxBoolItem(FN_QRY_MERGE, sal_True) );
1334 //                    // #i52629# aynchronous printing should only be done in silent mode - otherwise
1335 //                    // the printer dialog does not come up
1336 //                    aPrintArgs.Put( SfxBoolItem( SID_ASYNCHRON, rMergeDescriptor.bPrintAsync ));
1337                     // move print options
1338                     const beans::PropertyValue* pPrintOptions = rMergeDescriptor.aPrintOptions.getConstArray();
1339                     for( sal_Int32 nOption = 0; nOption < rMergeDescriptor.aPrintOptions.getLength(); ++nOption)
1340                     {
1341                         if( pPrintOptions[nOption].Name.equalsAscii( "CopyCount" )
1342                             ||( pPrintOptions[nOption].Name.equalsAscii( "FileName" ))
1343                             ||( pPrintOptions[nOption].Name.equalsAscii( "Collate" ))
1344                             ||( pPrintOptions[nOption].Name.equalsAscii( "Pages" ))
1345                             ||( pPrintOptions[nOption].Name.equalsAscii( "Wait" )))
1346                         {
1347                             aOptions.realloc( nOpts + 1 );
1348                             aOptions[ nOpts ].Name = pPrintOptions[nOption].Name;
1349                             aOptions[ nOpts ].Value = pPrintOptions[nOption].Value ;
1350                         }
1351                     }
1352 
1353 //                    const SwModuleOptions * pModOpt = SW_MOD()->GetModuleConfig();
1354 //                    if (pModOpt->IsSinglePrintJob())
1355 //                    {
1356 //                    }
1357 //                    else
1358 //                    {
1359                         pTargetView->ExecPrint( aOptions, IsMergeSilent(), rMergeDescriptor.bPrintAsync );
1360 //                    }
1361                 }
1362                 xTargetDocShell->DoClose();
1363             }
1364 
1365             //remove the temporary files
1366             ::std::vector<String>::iterator aFileIter;
1367             for(aFileIter = aFilesToRemove.begin();
1368                         aFileIter != aFilesToRemove.end(); aFileIter++)
1369                 SWUnoHelper::UCB_DeleteFile( *aFileIter );
1370 
1371             // Alle Dispatcher freigeben
1372             pViewFrm = SfxViewFrame::GetFirst(pSourrceDocSh);
1373 			while (pViewFrm)
1374 			{
1375 				pViewFrm->GetDispatcher()->Lock(sal_False);
1376                 pViewFrm = SfxViewFrame::GetNext(*pViewFrm, pSourrceDocSh);
1377 			}
1378 
1379             SW_MOD()->SetView(&pSourceShell->GetView());
1380 		}
1381 
1382 		nMergeType = DBMGR_INSERT;
1383 	}
1384 
1385     if(bEMail)
1386     {
1387         xMailDispatcher->stop();
1388         xMailDispatcher->shutdown();
1389 
1390     }
1391 
1392     return bLoop;
1393 }
1394 
1395 /*--------------------------------------------------------------------
1396 	Beschreibung:
1397   --------------------------------------------------------------------*/
1398 
1399 IMPL_LINK_INLINE_START( SwNewDBMgr, PrtCancelHdl, Button *, pButton )
1400 {
1401 	pButton->GetParent()->Hide();
1402 	bCancel = sal_True;
1403 	return 0;
1404 }
1405 IMPL_LINK_INLINE_END( SwNewDBMgr, PrtCancelHdl, Button *, pButton )
1406 
1407 
1408 /*--------------------------------------------------------------------
1409 	Beschreibung: Numberformat der Spalte ermitteln und ggfs. in
1410 					den uebergebenen Formatter uebertragen
1411   --------------------------------------------------------------------*/
1412 
1413 sal_uLong SwNewDBMgr::GetColumnFmt( const String& rDBName,
1414 								const String& rTableName,
1415 								const String& rColNm,
1416 								SvNumberFormatter* pNFmtr,
1417 								long nLanguage )
1418 {
1419 	sal_uLong nRet = 0;
1420 	if(pNFmtr)
1421 	{
1422         uno::Reference< XDataSource> xSource;
1423         uno::Reference< XConnection> xConnection;
1424         sal_Bool bUseMergeData = sal_False;
1425         uno::Reference< XColumnsSupplier> xColsSupp;
1426         bool bDisposeConnection = false;
1427         if(pImpl->pMergeData &&
1428             pImpl->pMergeData->sDataSource.equals(rDBName) && pImpl->pMergeData->sCommand.equals(rTableName))
1429 		{
1430             xConnection = pImpl->pMergeData->xConnection;
1431             xSource = SwNewDBMgr::getDataSourceAsParent(xConnection,rDBName);
1432             bUseMergeData = sal_True;
1433             xColsSupp = xColsSupp.query( pImpl->pMergeData->xResultSet );
1434 		}
1435         if(!xConnection.is())
1436         {
1437             SwDBData aData;
1438             aData.sDataSource = rDBName;
1439             aData.sCommand = rTableName;
1440             aData.nCommandType = -1;
1441             SwDSParam* pParam = FindDSData(aData, sal_False);
1442             if(pParam && pParam->xConnection.is())
1443             {
1444                 xConnection = pParam->xConnection;
1445                 xColsSupp = xColsSupp.query( pParam->xResultSet );
1446             }
1447             else
1448             {
1449                 rtl::OUString sDBName(rDBName);
1450                 xConnection = RegisterConnection( sDBName );
1451                 bDisposeConnection = true;
1452             }
1453             if(bUseMergeData)
1454                 pImpl->pMergeData->xConnection = xConnection;
1455         }
1456         bool bDispose = !xColsSupp.is();
1457         if(bDispose)
1458         {
1459             xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName);
1460         }
1461 		if(xColsSupp.is())
1462 		{
1463             uno::Reference<XNameAccess> xCols;
1464             try
1465             {
1466                 xCols = xColsSupp->getColumns();
1467             }
1468             catch(Exception&)
1469             {
1470                 DBG_ERROR("Exception in getColumns()");
1471             }
1472             if(!xCols.is() || !xCols->hasByName(rColNm))
1473 				return nRet;
1474 			Any aCol = xCols->getByName(rColNm);
1475             uno::Reference< XPropertySet > xColumn;
1476             aCol >>= xColumn;
1477             nRet = GetColumnFmt(xSource, xConnection, xColumn, pNFmtr, nLanguage);
1478             if(bDispose)
1479             {
1480                 ::comphelper::disposeComponent( xColsSupp );
1481             }
1482             if(bDisposeConnection)
1483             {
1484                 ::comphelper::disposeComponent( xConnection );
1485             }
1486         }
1487         else
1488 			nRet = pNFmtr->GetFormatIndex( NF_NUMBER_STANDARD, LANGUAGE_SYSTEM );
1489 	}
1490 	return nRet;
1491 }
1492 /* -----------------------------07.06.01 15:43--------------------------------
1493 
1494  ---------------------------------------------------------------------------*/
1495 sal_uLong SwNewDBMgr::GetColumnFmt( uno::Reference< XDataSource> xSource,
1496                         uno::Reference< XConnection> xConnection,
1497                         uno::Reference< XPropertySet> xColumn,
1498 						SvNumberFormatter* pNFmtr,
1499                         long nLanguage )
1500 {
1501 	//JP 12.01.99: ggfs. das NumberFormat im Doc setzen
1502 	sal_uLong nRet = 0;
1503 
1504     if(!xSource.is())
1505     {
1506         uno::Reference<XChild> xChild(xConnection, UNO_QUERY);
1507         if ( xChild.is() )
1508             xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
1509     }
1510     if(xSource.is() && xConnection.is() && xColumn.is() && pNFmtr)
1511 	{
1512 		SvNumberFormatsSupplierObj* pNumFmt = new SvNumberFormatsSupplierObj( pNFmtr );
1513         uno::Reference< util::XNumberFormatsSupplier >  xDocNumFmtsSupplier = pNumFmt;
1514         uno::Reference< XNumberFormats > xDocNumberFormats = xDocNumFmtsSupplier->getNumberFormats();
1515         uno::Reference< XNumberFormatTypes > xDocNumberFormatTypes(xDocNumberFormats, UNO_QUERY);
1516 
1517 		Locale aLocale( MsLangId::convertLanguageToLocale( (LanguageType)nLanguage ));
1518 
1519 		//get the number formatter of the data source
1520         uno::Reference<XPropertySet> xSourceProps(xSource, UNO_QUERY);
1521         uno::Reference< XNumberFormats > xNumberFormats;
1522 		if(xSourceProps.is())
1523 		{
1524 			Any aFormats = xSourceProps->getPropertyValue(C2U("NumberFormatsSupplier"));
1525 			if(aFormats.hasValue())
1526 			{
1527                 uno::Reference<XNumberFormatsSupplier> xSuppl;
1528                 aFormats >>= xSuppl;
1529 				if(xSuppl.is())
1530 				{
1531 					xNumberFormats = xSuppl->getNumberFormats();
1532 				}
1533 			}
1534 		}
1535         bool bUseDefault = true;
1536         try
1537         {
1538             Any aFormatKey = xColumn->getPropertyValue(C2U("FormatKey"));
1539             if(aFormatKey.hasValue())
1540             {
1541                 sal_Int32 nFmt = 0;
1542                 aFormatKey >>= nFmt;
1543                 if(xNumberFormats.is())
1544                 {
1545                     try
1546                     {
1547                         uno::Reference<XPropertySet> xNumProps = xNumberFormats->getByKey( nFmt );
1548                         Any aFormatString = xNumProps->getPropertyValue(C2U("FormatString"));
1549                         Any aLocaleVal = xNumProps->getPropertyValue(C2U("Locale"));
1550                         rtl::OUString sFormat;
1551                         aFormatString >>= sFormat;
1552                         lang::Locale aLoc;
1553                         aLocaleVal >>= aLoc;
1554                         nFmt = xDocNumberFormats->queryKey( sFormat, aLoc, sal_False );
1555                         if(NUMBERFORMAT_ENTRY_NOT_FOUND == sal::static_int_cast< sal_uInt32, sal_Int32>(nFmt))
1556                             nFmt = xDocNumberFormats->addNew( sFormat, aLoc );
1557                         nRet = nFmt;
1558                         bUseDefault = false;
1559                     }
1560                     catch(const Exception&)
1561                     {
1562                         DBG_ERROR("illegal number format key");
1563                     }
1564                 }
1565             }
1566         }
1567         catch( const Exception& )
1568         {
1569             DBG_ERROR("no FormatKey property found");
1570         }
1571         if(bUseDefault)
1572             nRet = SwNewDBMgr::GetDbtoolsClient().getDefaultNumberFormat(xColumn, xDocNumberFormatTypes,  aLocale);
1573 	}
1574 	return nRet;
1575 }
1576 
1577 /* -----------------------------17.07.00 09:47--------------------------------
1578 
1579  ---------------------------------------------------------------------------*/
1580 sal_Int32 SwNewDBMgr::GetColumnType( const String& rDBName,
1581 						  const String& rTableName,
1582 						  const String& rColNm )
1583 {
1584 	sal_Int32 nRet = DataType::SQLNULL;
1585     SwDBData aData;
1586     aData.sDataSource = rDBName;
1587     aData.sCommand = rTableName;
1588     aData.nCommandType = -1;
1589     SwDSParam* pParam = FindDSData(aData, sal_False);
1590     uno::Reference< XConnection> xConnection;
1591     uno::Reference< XColumnsSupplier > xColsSupp;
1592     bool bDispose = false;
1593     if(pParam && pParam->xConnection.is())
1594     {
1595         xConnection = pParam->xConnection;
1596         xColsSupp = uno::Reference< XColumnsSupplier >( pParam->xResultSet, UNO_QUERY );
1597     }
1598     else
1599     {
1600         rtl::OUString sDBName(rDBName);
1601         xConnection = RegisterConnection( sDBName );
1602     }
1603     if( !xColsSupp.is() )
1604     {
1605         xColsSupp = SwNewDBMgr::GetColumnSupplier(xConnection, rTableName);
1606         bDispose = true;
1607     }
1608 	if(xColsSupp.is())
1609 	{
1610         uno::Reference<XNameAccess> xCols = xColsSupp->getColumns();
1611 		if(xCols->hasByName(rColNm))
1612 		{
1613 			Any aCol = xCols->getByName(rColNm);
1614             uno::Reference<XPropertySet> xCol;
1615             aCol >>= xCol;
1616 			Any aType = xCol->getPropertyValue(C2S("Type"));
1617 			aType >>= nRet;
1618 		}
1619         if(bDispose)
1620             ::comphelper::disposeComponent( xColsSupp );
1621     }
1622 	return nRet;
1623 }
1624 
1625 /* -----------------------------03.07.00 17:12--------------------------------
1626 
1627  ---------------------------------------------------------------------------*/
1628 uno::Reference< sdbc::XConnection> SwNewDBMgr::GetConnection(const String& rDataSource,
1629                                                     uno::Reference<XDataSource>& rxSource)
1630 {
1631 	Reference< sdbc::XConnection> xConnection;
1632 	Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
1633 	try
1634 	{
1635 		Reference<XCompletedConnection> xComplConnection(SwNewDBMgr::GetDbtoolsClient().getDataSource(rDataSource, xMgr),UNO_QUERY);
1636 		if ( xComplConnection.is() )
1637 		{
1638 			rxSource.set(xComplConnection,UNO_QUERY);
1639 			Reference< XInteractionHandler > xHandler(
1640 					xMgr->createInstance( C2U( "com.sun.star.task.InteractionHandler" )), UNO_QUERY);
1641 				xConnection = xComplConnection->connectWithCompletion( xHandler );
1642 		}
1643 	}
1644 	catch(Exception&) {}
1645 
1646 	return xConnection;
1647 }
1648 /* -----------------------------03.07.00 17:12--------------------------------
1649 
1650  ---------------------------------------------------------------------------*/
1651 uno::Reference< sdbcx::XColumnsSupplier> SwNewDBMgr::GetColumnSupplier(uno::Reference<sdbc::XConnection> xConnection,
1652 									const String& rTableOrQuery,
1653 									sal_uInt8	eTableOrQuery)
1654 {
1655     Reference< sdbcx::XColumnsSupplier> xRet;
1656     try
1657     {
1658         if(eTableOrQuery == SW_DB_SELECT_UNKNOWN)
1659         {
1660             //search for a table with the given command name
1661             Reference<XTablesSupplier> xTSupplier = Reference<XTablesSupplier>(xConnection, UNO_QUERY);
1662             if(xTSupplier.is())
1663             {
1664                 Reference<XNameAccess> xTbls = xTSupplier->getTables();
1665                 eTableOrQuery = xTbls->hasByName(rTableOrQuery) ?
1666                             SW_DB_SELECT_TABLE : SW_DB_SELECT_QUERY;
1667             }
1668         }
1669         sal_Int32 nCommandType = SW_DB_SELECT_TABLE == eTableOrQuery ?
1670                 CommandType::TABLE : CommandType::QUERY;
1671         Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
1672         Reference<XRowSet> xRowSet(
1673                 xMgr->createInstance(C2U("com.sun.star.sdb.RowSet")), UNO_QUERY);
1674 
1675         ::rtl::OUString sDataSource;
1676         Reference<XDataSource> xSource = SwNewDBMgr::getDataSourceAsParent(xConnection, sDataSource);
1677         Reference<XPropertySet> xSourceProperties(xSource, UNO_QUERY);
1678         if(xSourceProperties.is())
1679         {
1680             xSourceProperties->getPropertyValue(C2U("Name")) >>= sDataSource;
1681         }
1682 
1683         Reference<XPropertySet> xRowProperties(xRowSet, UNO_QUERY);
1684         xRowProperties->setPropertyValue(C2U("DataSourceName"), makeAny(sDataSource));
1685         xRowProperties->setPropertyValue(C2U("Command"), makeAny(::rtl::OUString(rTableOrQuery)));
1686         xRowProperties->setPropertyValue(C2U("CommandType"), makeAny(nCommandType));
1687         xRowProperties->setPropertyValue(C2U("FetchSize"), makeAny((sal_Int32)10));
1688         xRowProperties->setPropertyValue(C2U("ActiveConnection"), makeAny(xConnection));
1689         xRowSet->execute();
1690         xRet = Reference<XColumnsSupplier>( xRowSet, UNO_QUERY );
1691     }
1692     catch( const uno::Exception& )
1693     {
1694         DBG_ERROR("Exception in SwDBMgr::GetColumnSupplier");
1695     }
1696 
1697     return xRet;
1698 }
1699 /* -----------------------------05.07.00 13:44--------------------------------
1700 
1701  ---------------------------------------------------------------------------*/
1702 String SwNewDBMgr::GetDBField(uno::Reference<XPropertySet> xColumnProps,
1703 						const SwDBFormatData& rDBFormatData,
1704 						double* pNumber)
1705 {
1706     uno::Reference< XColumn > xColumn(xColumnProps, UNO_QUERY);
1707 	String sRet;
1708 	DBG_ASSERT(xColumn.is(), "SwNewDBMgr::::ImportDBField: illegal arguments");
1709 	if(!xColumn.is())
1710 		return sRet;
1711 
1712 	Any aType = xColumnProps->getPropertyValue(C2U("Type"));
1713 	sal_Int32 eDataType = 0;
1714 	aType >>= eDataType;
1715 	switch(eDataType)
1716 	{
1717 		case DataType::CHAR:
1718 		case DataType::VARCHAR:
1719 		case DataType::LONGVARCHAR:
1720             try
1721             {
1722 			    sRet = xColumn->getString();
1723             }
1724             catch( SQLException& )
1725             {
1726             }
1727 		break;
1728 		case DataType::BIT:
1729 		case DataType::BOOLEAN:
1730 		case DataType::TINYINT:
1731 		case DataType::SMALLINT:
1732 		case DataType::INTEGER:
1733 		case DataType::BIGINT:
1734 		case DataType::FLOAT:
1735 		case DataType::REAL:
1736 		case DataType::DOUBLE:
1737 		case DataType::NUMERIC:
1738 		case DataType::DECIMAL:
1739 		case DataType::DATE:
1740 		case DataType::TIME:
1741 		case DataType::TIMESTAMP:
1742 		{
1743 //			::Date aTempDate(rDBFormatData.aNullDate.Day,
1744 //				rDBFormatData.aNullDate.Month, rDBFormatData.aNullDate.Year);
1745 
1746 			try
1747 			{
1748                 SwDbtoolsClient& aClient = SwNewDBMgr::GetDbtoolsClient();
1749                 sRet = aClient.getFormattedValue(
1750 					xColumnProps,
1751 					rDBFormatData.xFormatter,
1752 					rDBFormatData.aLocale,
1753 					rDBFormatData.aNullDate);
1754 				if (pNumber)
1755                 {
1756 				    double fVal = xColumn->getDouble();
1757                     if(!xColumn->wasNull())
1758                     {
1759                         *pNumber = fVal;
1760                     }
1761                 }
1762 			}
1763             catch(Exception& )
1764 			{
1765 				DBG_ERROR("exception caught");
1766 			}
1767 
1768 		}
1769 		break;
1770 
1771 //		case DataType::BINARY:
1772 //		case DataType::VARBINARY:
1773 //		case DataType::LONGVARBINARY:
1774 //		case DataType::SQLNULL:
1775 //		case DataType::OTHER:
1776 //		case DataType::OBJECT:
1777 //		case DataType::DISTINCT:
1778 //		case DataType::STRUCT:
1779 //		case DataType::ARRAY:
1780 //		case DataType::BLOB:
1781 //		case DataType::CLOB:
1782 //		case DataType::REF:
1783 //		default:
1784 	}
1785 //	if (pFormat)
1786 //	{
1787 //		SFX_ITEMSET_GET(*pCol, pFormatItem, SfxUInt32Item, SBA_DEF_FMTVALUE, sal_True);
1788 //		*pFormat = pFormatItem->GetValue();
1789 //	}
1790 
1791 	return sRet;
1792 }
1793 /* -----------------------------06.07.00 14:28--------------------------------
1794 	releases the merge data source table or query after merge is completed
1795  ---------------------------------------------------------------------------*/
1796 void	SwNewDBMgr::EndMerge()
1797 {
1798 	DBG_ASSERT(bInMerge, "merge is not active");
1799 	bInMerge = sal_False;
1800     delete pImpl->pMergeData;
1801     pImpl->pMergeData = 0;
1802 }
1803 /* -----------------------------06.07.00 14:28--------------------------------
1804 	checks if a desired data source table or query is open
1805  ---------------------------------------------------------------------------*/
1806 sal_Bool    SwNewDBMgr::IsDataSourceOpen(const String& rDataSource,
1807             const String& rTableOrQuery, sal_Bool bMergeOnly)
1808 {
1809     if(pImpl->pMergeData)
1810 	{
1811         return !bMergeLock &&
1812                 ((rDataSource == (String)pImpl->pMergeData->sDataSource &&
1813                     rTableOrQuery == (String)pImpl->pMergeData->sCommand)
1814                     ||(!rDataSource.Len() && !rTableOrQuery.Len()))
1815                     &&
1816                     pImpl->pMergeData->xResultSet.is();
1817 	}
1818     else if(!bMergeOnly)
1819     {
1820         SwDBData aData;
1821         aData.sDataSource = rDataSource;
1822         aData.sCommand = rTableOrQuery;
1823         aData.nCommandType = -1;
1824         SwDSParam* pFound = FindDSData(aData, sal_False);
1825         return (pFound && pFound->xResultSet.is());
1826     }
1827     return sal_False;
1828 }
1829 /* -----------------------------17.07.00 16:44--------------------------------
1830 	read column data a a specified position
1831  ---------------------------------------------------------------------------*/
1832 sal_Bool SwNewDBMgr::GetColumnCnt(const String& rSourceName, const String& rTableName,
1833 							const String& rColumnName, sal_uInt32 nAbsRecordId,
1834 							long nLanguage,
1835 							String& rResult, double* pNumber)
1836 {
1837 	sal_Bool bRet = sal_False;
1838     SwDSParam* pFound = 0;
1839     //check if it's the merge data source
1840     if(pImpl->pMergeData &&
1841         rSourceName == (String)pImpl->pMergeData->sDataSource &&
1842         rTableName == (String)pImpl->pMergeData->sCommand)
1843 	{
1844         pFound = pImpl->pMergeData;
1845     }
1846     else
1847 	{
1848         SwDBData aData;
1849         aData.sDataSource = rSourceName;
1850         aData.sCommand = rTableName;
1851         aData.nCommandType = -1;
1852         pFound = FindDSData(aData, sal_False);
1853     }
1854     //check validity of supplied record Id
1855     if(pFound->aSelection.getLength())
1856     {
1857         //the destination has to be an element of the selection
1858         const Any* pSelection = pFound->aSelection.getConstArray();
1859         sal_Bool bFound = sal_False;
1860         for(sal_Int32 nPos = 0; !bFound && nPos < pFound->aSelection.getLength(); nPos++)
1861         {
1862             sal_Int32 nSelection = 0;
1863             pSelection[nPos] >>= nSelection;
1864             if(nSelection == static_cast<sal_Int32>(nAbsRecordId))
1865                 bFound = sal_True;
1866         }
1867         if(!bFound)
1868             return sal_False;
1869     }
1870     if(pFound && pFound->xResultSet.is() && !pFound->bAfterSelection)
1871     {
1872         sal_Int32 nOldRow = 0;
1873         try
1874         {
1875             nOldRow = pFound->xResultSet->getRow();
1876         }
1877         catch(const Exception& )
1878         {
1879 			return sal_False;
1880         }
1881         //position to the desired index
1882         sal_Bool bMove = sal_True;
1883         if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) )
1884             bMove = lcl_MoveAbsolute(pFound, nAbsRecordId);
1885         if(bMove)
1886         {
1887             bRet = lcl_GetColumnCnt(pFound, rColumnName, nLanguage, rResult, pNumber);
1888         }
1889         if ( nOldRow != static_cast<sal_Int32>(nAbsRecordId) )
1890             bMove = lcl_MoveAbsolute(pFound, nOldRow);
1891     }
1892 	return bRet;
1893 }
1894 /* -----------------------------06.07.00 16:47--------------------------------
1895 	reads the column data at the current position
1896  ---------------------------------------------------------------------------*/
1897 sal_Bool	SwNewDBMgr::GetMergeColumnCnt(const String& rColumnName, sal_uInt16 nLanguage,
1898                                 String &rResult, double *pNumber, sal_uInt32 * /*pFormat*/)
1899 {
1900     if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is() || pImpl->pMergeData->bAfterSelection )
1901 	{
1902 		rResult.Erase();
1903 		return sal_False;
1904 	}
1905 
1906     sal_Bool bRet = lcl_GetColumnCnt(pImpl->pMergeData, rColumnName, nLanguage, rResult, pNumber);
1907 	return bRet;
1908 }
1909 /* -----------------------------07.07.00 14:28--------------------------------
1910 
1911  ---------------------------------------------------------------------------*/
1912 sal_Bool SwNewDBMgr::ToNextMergeRecord()
1913 {
1914     DBG_ASSERT(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
1915     return ToNextRecord(pImpl->pMergeData);
1916 }
1917 /* -----------------------------10.07.01 14:28--------------------------------
1918 
1919  ---------------------------------------------------------------------------*/
1920 sal_Bool SwNewDBMgr::ToNextRecord(
1921     const String& rDataSource, const String& rCommand, sal_Int32 /*nCommandType*/)
1922 {
1923     SwDSParam* pFound = 0;
1924     if(pImpl->pMergeData &&
1925         rDataSource == (String)pImpl->pMergeData->sDataSource &&
1926         rCommand == (String)pImpl->pMergeData->sCommand)
1927         pFound = pImpl->pMergeData;
1928     else
1929     {
1930         SwDBData aData;
1931         aData.sDataSource = rDataSource;
1932         aData.sCommand = rCommand;
1933         aData.nCommandType = -1;
1934         pFound = FindDSData(aData, sal_False);
1935     }
1936     return ToNextRecord(pFound);
1937 }
1938 /* -----------------------------10.07.01 14:38--------------------------------
1939 
1940  ---------------------------------------------------------------------------*/
1941 sal_Bool SwNewDBMgr::ToNextRecord(SwDSParam* pParam)
1942 {
1943     sal_Bool bRet = sal_True;
1944     if(!pParam || !pParam->xResultSet.is() || pParam->bEndOfDB ||
1945 			(pParam->aSelection.getLength() && pParam->aSelection.getLength() <= pParam->nSelectionIndex))
1946 	{
1947         if(pParam)
1948             pParam->CheckEndOfDB();
1949 		return sal_False;
1950 	}
1951 	try
1952 	{
1953         if(pParam->aSelection.getLength())
1954 		{
1955 			sal_Int32 nPos = 0;
1956 			pParam->aSelection.getConstArray()[ pParam->nSelectionIndex++ ] >>= nPos;
1957             pParam->bEndOfDB = !pParam->xResultSet->absolute( nPos );
1958             pParam->CheckEndOfDB();
1959             bRet = !pParam->bEndOfDB;
1960             if(pParam->nSelectionIndex >= pParam->aSelection.getLength())
1961                 pParam->bEndOfDB = sal_True;
1962 		}
1963 		else
1964 		{
1965             sal_Int32 nBefore = pParam->xResultSet->getRow();
1966             pParam->bEndOfDB = !pParam->xResultSet->next();
1967             if( !pParam->bEndOfDB && nBefore == pParam->xResultSet->getRow())
1968             {
1969                 //next returned true but it didn't move
1970                 pParam->bEndOfDB = sal_True;
1971             }
1972 
1973             pParam->CheckEndOfDB();
1974             bRet = !pParam->bEndOfDB;
1975             ++pParam->nSelectionIndex;
1976 		}
1977 	}
1978     catch(Exception&)
1979 	{
1980 	}
1981     return bRet;
1982 }
1983 
1984 /* -----------------------------13.07.00 17:23--------------------------------
1985 	synchronized labels contain a next record field at their end
1986 	to assure that the next page can be created in mail merge
1987 	the cursor position must be validated
1988  ---------------------------------------------------------------------------*/
1989 sal_Bool SwNewDBMgr::ExistsNextRecord() const
1990 {
1991     return pImpl->pMergeData && !pImpl->pMergeData->bEndOfDB;
1992 }
1993 /* -----------------------------13.07.00 10:41--------------------------------
1994 
1995  ---------------------------------------------------------------------------*/
1996 sal_uInt32 	SwNewDBMgr::GetSelectedRecordId()
1997 {
1998 	sal_uInt32 	nRet = 0;
1999     DBG_ASSERT(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
2000     if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is())
2001 		return sal_False;
2002 	try
2003 	{
2004         nRet = pImpl->pMergeData->xResultSet->getRow();
2005 	}
2006     catch(Exception& )
2007 	{
2008 	}
2009 	return nRet;
2010 }
2011 /* -----------------------------13.07.00 10:58--------------------------------
2012 
2013  ---------------------------------------------------------------------------*/
2014 sal_Bool SwNewDBMgr::ToRecordId(sal_Int32 nSet)
2015 {
2016     DBG_ASSERT(pImpl->pMergeData && pImpl->pMergeData->xResultSet.is(), "no data source in merge");
2017     if(!pImpl->pMergeData || !pImpl->pMergeData->xResultSet.is()|| nSet < 0)
2018 		return sal_False;
2019 	sal_Bool bRet = sal_False;
2020     sal_Int32 nAbsPos = nSet;
2021 
2022 	if(nAbsPos >= 0)
2023 	{
2024         bRet = lcl_MoveAbsolute(pImpl->pMergeData, nAbsPos);
2025         pImpl->pMergeData->bEndOfDB = !bRet;
2026         pImpl->pMergeData->CheckEndOfDB();
2027 	}
2028 	return bRet;
2029 }
2030 
2031 /* -----------------------------17.07.00 14:17--------------------------------
2032 
2033  ---------------------------------------------------------------------------*/
2034 sal_Bool SwNewDBMgr::OpenDataSource(const String& rDataSource, const String& rTableOrQuery,
2035             sal_Int32 nCommandType, bool bCreate)
2036 {
2037     SwDBData aData;
2038     aData.sDataSource = rDataSource;
2039     aData.sCommand = rTableOrQuery;
2040     aData.nCommandType = nCommandType;
2041 
2042     SwDSParam* pFound = FindDSData(aData, sal_True);
2043     uno::Reference< XDataSource> xSource;
2044 	if(pFound->xResultSet.is())
2045 		return sal_True;
2046     SwDSParam* pParam = FindDSConnection(rDataSource, sal_False);
2047     uno::Reference< XConnection> xConnection;
2048     if(pParam && pParam->xConnection.is())
2049         pFound->xConnection = pParam->xConnection;
2050     else if(bCreate)
2051     {
2052         rtl::OUString sDataSource(rDataSource);
2053         pFound->xConnection = RegisterConnection( sDataSource );
2054     }
2055 	if(pFound->xConnection.is())
2056 	{
2057 		try
2058 		{
2059             uno::Reference< sdbc::XDatabaseMetaData >  xMetaData = pFound->xConnection->getMetaData();
2060             try
2061             {
2062                 pFound->bScrollable = xMetaData
2063 						->supportsResultSetType((sal_Int32)ResultSetType::SCROLL_INSENSITIVE);
2064             }
2065             catch(Exception&)
2066             {
2067                 //#98373# DB driver may not be ODBC 3.0 compliant
2068                 pFound->bScrollable = sal_True;
2069             }
2070 			pFound->xStatement = pFound->xConnection->createStatement();
2071             rtl::OUString aQuoteChar = xMetaData->getIdentifierQuoteString();
2072             rtl::OUString sStatement(C2U("SELECT * FROM "));
2073             sStatement = C2U("SELECT * FROM ");
2074             sStatement += aQuoteChar;
2075             sStatement += rTableOrQuery;
2076             sStatement += aQuoteChar;
2077             pFound->xResultSet = pFound->xStatement->executeQuery( sStatement );
2078 
2079 			//after executeQuery the cursor must be positioned
2080             pFound->bEndOfDB = !pFound->xResultSet->next();
2081             pFound->bAfterSelection = sal_False;
2082             pFound->CheckEndOfDB();
2083             ++pFound->nSelectionIndex;
2084 		}
2085 		catch (Exception&)
2086 		{
2087 			pFound->xResultSet = 0;
2088 			pFound->xStatement = 0;
2089 			pFound->xConnection = 0;
2090 		}
2091 	}
2092 	return pFound->xResultSet.is();
2093 }
2094 /* -----------------------------14.08.2001 10:26------------------------------
2095 
2096  ---------------------------------------------------------------------------*/
2097 uno::Reference< XConnection> SwNewDBMgr::RegisterConnection(rtl::OUString& rDataSource)
2098 {
2099     SwDSParam* pFound = SwNewDBMgr::FindDSConnection(rDataSource, sal_True);
2100     uno::Reference< XDataSource> xSource;
2101     if(!pFound->xConnection.is())
2102 	{
2103         pFound->xConnection = SwNewDBMgr::GetConnection(rDataSource, xSource );
2104         try
2105         {
2106             uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2107             if(xComponent.is())
2108                 xComponent->addEventListener(pImpl->xDisposeListener);
2109         }
2110         catch(Exception&)
2111         {
2112         }
2113 	}
2114     return pFound->xConnection;
2115 }
2116 /* -----------------------------17.07.00 15:55--------------------------------
2117 
2118  ---------------------------------------------------------------------------*/
2119 sal_uInt32      SwNewDBMgr::GetSelectedRecordId(
2120     const String& rDataSource, const String& rTableOrQuery, sal_Int32 nCommandType)
2121 {
2122     sal_uInt32 nRet = 0xffffffff;
2123 	//check for merge data source first
2124     if(pImpl->pMergeData && rDataSource == (String)pImpl->pMergeData->sDataSource &&
2125                     rTableOrQuery == (String)pImpl->pMergeData->sCommand &&
2126                     (nCommandType == -1 || nCommandType == pImpl->pMergeData->nCommandType) &&
2127                     pImpl->pMergeData->xResultSet.is())
2128 		nRet = GetSelectedRecordId();
2129 	else
2130 	{
2131         SwDBData aData;
2132         aData.sDataSource = rDataSource;
2133         aData.sCommand = rTableOrQuery;
2134         aData.nCommandType = nCommandType;
2135         SwDSParam* pFound = FindDSData(aData, sal_False);
2136 		if(pFound && pFound->xResultSet.is())
2137 		{
2138 			try
2139 			{	//if a selection array is set the current row at the result set may not be set yet
2140 				if(pFound->aSelection.getLength())
2141 				{
2142 					sal_Int32 nSelIndex = pFound->nSelectionIndex;
2143                     if(nSelIndex >= pFound->aSelection.getLength())
2144 						nSelIndex = pFound->aSelection.getLength() -1;
2145 					pFound->aSelection.getConstArray()[nSelIndex] >>= nRet;
2146 
2147 				}
2148 				else
2149 					nRet = pFound->xResultSet->getRow();
2150 			}
2151 			catch(Exception&){}
2152 		}
2153 	}
2154 	return nRet;
2155 }
2156 
2157 /* -----------------------------17.07.00 14:18--------------------------------
2158 	close all data sources - after fields were updated
2159  ---------------------------------------------------------------------------*/
2160 void	SwNewDBMgr::CloseAll(sal_Bool bIncludingMerge)
2161 {
2162     //the only thing done here is to reset the selection index
2163 	//all connections stay open
2164     for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.Count(); nPos++)
2165     {
2166         SwDSParam* pParam = aDataSourceParams[nPos];
2167         if(bIncludingMerge || pParam != pImpl->pMergeData)
2168         {
2169 			pParam->nSelectionIndex = 0;
2170 			pParam->bAfterSelection = sal_False;
2171             pParam->bEndOfDB = sal_False;
2172             try
2173             {
2174                 if(!bInMerge && pParam->xResultSet.is())
2175                     pParam->xResultSet->first();
2176             }
2177             catch(Exception& )
2178             {}
2179         }
2180     }
2181 }
2182 /* -----------------------------17.07.00 14:54--------------------------------
2183 
2184  ---------------------------------------------------------------------------*/
2185 SwDSParam* SwNewDBMgr::FindDSData(const SwDBData& rData, sal_Bool bCreate)
2186 {
2187     //prefer merge data if available
2188     if(pImpl->pMergeData && rData.sDataSource == pImpl->pMergeData->sDataSource &&
2189         rData.sCommand == pImpl->pMergeData->sCommand &&
2190         (rData.nCommandType == -1 || rData.nCommandType == pImpl->pMergeData->nCommandType ||
2191         (bCreate && pImpl->pMergeData->nCommandType == -1)))
2192     {
2193          return pImpl->pMergeData;
2194     }
2195 
2196     SwDSParam* pFound = 0;
2197 	for(sal_uInt16 nPos = aDataSourceParams.Count(); nPos; nPos--)
2198 	{
2199 		SwDSParam* pParam = aDataSourceParams[nPos - 1];
2200         if(rData.sDataSource == pParam->sDataSource &&
2201             rData.sCommand == pParam->sCommand &&
2202             (rData.nCommandType == -1 || rData.nCommandType == pParam->nCommandType ||
2203             (bCreate && pParam->nCommandType == -1)))
2204 			{
2205                 //#94779# calls from the calculator may add a connection with an invalid commandtype
2206                 //later added "real" data base connections have to re-use the already available
2207                 //DSData and set the correct CommandType
2208                 if(bCreate && pParam->nCommandType == -1)
2209                     pParam->nCommandType = rData.nCommandType;
2210 				pFound = pParam;
2211 				break;
2212 			}
2213 	}
2214 	if(bCreate)
2215 	{
2216 		if(!pFound)
2217 		{
2218             pFound = new SwDSParam(rData);
2219             aDataSourceParams.Insert(pFound, aDataSourceParams.Count());
2220             try
2221             {
2222                 uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2223                 if(xComponent.is())
2224                     xComponent->addEventListener(pImpl->xDisposeListener);
2225             }
2226             catch(Exception&)
2227             {
2228             }
2229         }
2230 	}
2231 	return pFound;
2232 }
2233 /* -----------------------------14.08.2001 10:27------------------------------
2234 
2235  ---------------------------------------------------------------------------*/
2236 
2237 SwDSParam*  SwNewDBMgr::FindDSConnection(const rtl::OUString& rDataSource, sal_Bool bCreate)
2238 {
2239     //prefer merge data if available
2240     if(pImpl->pMergeData && rDataSource == pImpl->pMergeData->sDataSource )
2241     {
2242          return pImpl->pMergeData;
2243     }
2244 	SwDSParam* pFound = 0;
2245 	for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.Count(); nPos++)
2246 	{
2247 		SwDSParam* pParam = aDataSourceParams[nPos];
2248         if(rDataSource == pParam->sDataSource)
2249         {
2250             pFound = pParam;
2251             break;
2252         }
2253 	}
2254 	if(bCreate && !pFound)
2255 	{
2256         SwDBData aData;
2257         aData.sDataSource = rDataSource;
2258         pFound = new SwDSParam(aData);
2259 		aDataSourceParams.Insert(pFound, aDataSourceParams.Count());
2260         try
2261         {
2262             uno::Reference<XComponent> xComponent(pFound->xConnection, UNO_QUERY);
2263             if(xComponent.is())
2264                 xComponent->addEventListener(pImpl->xDisposeListener);
2265         }
2266         catch(Exception&)
2267         {
2268         }
2269     }
2270 	return pFound;
2271 }
2272 
2273 /* -----------------------------17.07.00 14:34--------------------------------
2274 
2275  ---------------------------------------------------------------------------*/
2276 const SwDBData&	SwNewDBMgr::GetAddressDBName()
2277 {
2278 	return SW_MOD()->GetDBConfig()->GetAddressSource();
2279 }
2280 /* -----------------------------18.07.00 13:13--------------------------------
2281 
2282  ---------------------------------------------------------------------------*/
2283 Sequence<rtl::OUString> SwNewDBMgr::GetExistingDatabaseNames()
2284 {
2285     uno::Reference<XNameAccess> xDBContext;
2286     uno::Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
2287 	if( xMgr.is() )
2288 	{
2289         uno::Reference<XInterface> xInstance = xMgr->createInstance( C2U( "com.sun.star.sdb.DatabaseContext" ));
2290         xDBContext = uno::Reference<XNameAccess>(xInstance, UNO_QUERY) ;
2291 	}
2292 	if(xDBContext.is())
2293 	{
2294 		return xDBContext->getElementNames();
2295 	}
2296     return Sequence<rtl::OUString>();
2297 }
2298 /*-- 26.05.2004 14:33:13---------------------------------------------------
2299 
2300   -----------------------------------------------------------------------*/
2301 String SwNewDBMgr::LoadAndRegisterDataSource()
2302 {
2303     sfx2::FileDialogHelper aDlgHelper( TemplateDescription::FILEOPEN_SIMPLE, 0 );
2304     Reference < XFilePicker > xFP = aDlgHelper.GetFilePicker();
2305 
2306     String sHomePath(SvtPathOptions().GetWorkPath());
2307     aDlgHelper.SetDisplayDirectory( sHomePath );
2308 
2309     Reference<XFilterManager> xFltMgr(xFP, UNO_QUERY);
2310 
2311     String sFilterAll(SW_RES(STR_FILTER_ALL));
2312     String sFilterAllData(SW_RES(STR_FILTER_ALL_DATA));
2313     String sFilterSXB(SW_RES(STR_FILTER_SXB));
2314     String sFilterSXC(SW_RES(STR_FILTER_SXC));
2315     String sFilterDBF(SW_RES(STR_FILTER_DBF));
2316     String sFilterXLS(SW_RES(STR_FILTER_XLS));
2317     String sFilterTXT(SW_RES(STR_FILTER_TXT));
2318     String sFilterCSV(SW_RES(STR_FILTER_CSV));
2319 #ifdef WNT
2320     String sFilterMDB(SW_RES(STR_FILTER_MDB));
2321     String sFilterACCDB(SW_RES(STR_FILTER_ACCDB));
2322 #endif
2323     xFltMgr->appendFilter( sFilterAll, C2U("*") );
2324     xFltMgr->appendFilter( sFilterAllData, C2U("*.ods;*.sxc;*.dbf;*.xls;*.txt;*.csv"));
2325 
2326     xFltMgr->appendFilter( sFilterSXB, C2U("*.odb") );
2327     xFltMgr->appendFilter( sFilterSXC, C2U("*.ods;*.sxc") );
2328     xFltMgr->appendFilter( sFilterDBF, C2U("*.dbf") );
2329     xFltMgr->appendFilter( sFilterXLS, C2U("*.xls") );
2330     xFltMgr->appendFilter( sFilterTXT, C2U("*.txt") );
2331     xFltMgr->appendFilter( sFilterCSV, C2U("*.csv") );
2332 #ifdef WNT
2333     xFltMgr->appendFilter( sFilterMDB, C2U("*.mdb") );
2334     xFltMgr->appendFilter( sFilterACCDB, C2U("*.accdb") );
2335 #endif
2336 
2337     xFltMgr->setCurrentFilter( sFilterAll ) ;
2338     String sFind;
2339     bool bTextConnection = false;
2340     if( ERRCODE_NONE == aDlgHelper.Execute() )
2341     {
2342         String sURL = xFP->getFiles().getConstArray()[0];
2343         //data sources have to be registered depending on their extensions
2344         INetURLObject aURL( sURL );
2345         String sExt( aURL.GetExtension() );
2346         Any aURLAny;
2347         Any aTableFilterAny;
2348         Any aSuppressVersionsAny;
2349         Any aInfoAny;
2350         INetURLObject aTempURL(aURL);
2351         bool bStore = true;
2352         if(sExt.EqualsAscii("odb"))
2353         {
2354             bStore = false;
2355         }
2356         else if(sExt.EqualsIgnoreCaseAscii("sxc")
2357             || sExt.EqualsIgnoreCaseAscii("ods")
2358                 || sExt.EqualsIgnoreCaseAscii("xls"))
2359         {
2360             rtl::OUString sDBURL(C2U("sdbc:calc:"));
2361             sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE);
2362             aURLAny <<= sDBURL;
2363         }
2364         else if(sExt.EqualsIgnoreCaseAscii("dbf"))
2365         {
2366             aTempURL.removeSegment();
2367             aTempURL.removeFinalSlash();
2368             rtl::OUString sDBURL(C2U("sdbc:dbase:"));
2369             sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE);
2370             aURLAny <<= sDBURL;
2371             //set the filter to the file name without extension
2372             Sequence<rtl::OUString> aFilters(1);
2373             rtl::OUString sTmp(aURL.getBase());
2374             aFilters[0] = aURL.getBase();
2375             aTableFilterAny <<= aFilters;
2376         }
2377         else if(sExt.EqualsIgnoreCaseAscii("csv") || sExt.EqualsIgnoreCaseAscii("txt"))
2378         {
2379             aTempURL.removeSegment();
2380             aTempURL.removeFinalSlash();
2381             rtl::OUString sDBURL(C2U("sdbc:flat:"));
2382             //only the 'path' has to be added
2383             sDBURL += aTempURL.GetMainURL(INetURLObject::NO_DECODE);
2384             aURLAny <<= sDBURL;
2385 
2386             bTextConnection = true;
2387             //set the filter to the file name without extension
2388             Sequence<rtl::OUString> aFilters(1);
2389             rtl::OUString sTmp(aURL.getBase());
2390             aFilters[0] = aURL.getBase();
2391             aTableFilterAny <<= aFilters;
2392         }
2393 #ifdef WNT
2394         else if(sExt.EqualsIgnoreCaseAscii("mdb"))
2395         {
2396             rtl::OUString sDBURL(C2U("sdbc:ado:access:PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE="));
2397             sDBURL += aTempURL.PathToFileName();
2398             aURLAny <<= sDBURL;
2399             aSuppressVersionsAny <<= makeAny(true);
2400         }
2401         else if(sExt.EqualsIgnoreCaseAscii("accdb"))
2402         {
2403             rtl::OUString sDBURL(C2U("sdbc:ado:PROVIDER=Microsoft.ACE.OLEDB.12.0;DATA SOURCE="));
2404             sDBURL += aTempURL.PathToFileName();
2405             aURLAny <<= sDBURL;
2406             aSuppressVersionsAny <<= makeAny(true);
2407         }
2408 #endif
2409         try
2410         {
2411             Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
2412             Reference<XInterface> xInstance = xMgr->createInstance( C2U( "com.sun.star.sdb.DatabaseContext" ));
2413             Reference<XNameAccess> xDBContext(xInstance, UNO_QUERY_THROW);
2414             Reference<XSingleServiceFactory> xFact( xDBContext, UNO_QUERY);
2415 
2416 			String sNewName = INetURLObject::decode( aURL.getName(),
2417 													 INET_HEX_ESCAPE,
2418 													 INetURLObject::DECODE_UNAMBIGUOUS,
2419 													 RTL_TEXTENCODING_UTF8 );
2420             xub_StrLen nExtLen = static_cast< xub_StrLen >(aURL.GetExtension().getLength());
2421             sNewName.Erase( sNewName.Len() - nExtLen - 1, nExtLen + 1 );
2422 
2423             //find a unique name if sNewName already exists
2424             sFind = sNewName;
2425             sal_Int32 nIndex = 0;
2426             while(xDBContext->hasByName(sFind))
2427             {
2428                 sFind = sNewName;
2429                 sFind += String::CreateFromInt32(++nIndex);
2430             }
2431 
2432             Reference<XInterface> xNewInstance;
2433             if(!bStore)
2434             {
2435                 //odb-file
2436                 Any aDataSource = xDBContext->getByName(aTempURL.GetMainURL(INetURLObject::NO_DECODE));
2437                 aDataSource >>= xNewInstance;
2438             }
2439             else
2440             {
2441                 xNewInstance = xFact->createInstance();
2442                 Reference<XPropertySet> xDataProperties(xNewInstance, UNO_QUERY);
2443 
2444                 if(aURLAny.hasValue())
2445                     xDataProperties->setPropertyValue(C2U("URL"), aURLAny);
2446                 if(aTableFilterAny.hasValue())
2447                     xDataProperties->setPropertyValue(C2U("TableFilter"), aTableFilterAny);
2448                 if(aSuppressVersionsAny.hasValue())
2449                     xDataProperties->setPropertyValue(C2U("SuppressVersionColumns"), aSuppressVersionsAny);
2450                 if(aInfoAny.hasValue())
2451                     xDataProperties->setPropertyValue(C2U("Info"), aInfoAny);
2452 
2453                 if( bTextConnection )
2454                 {
2455                     uno::Reference < ui::dialogs::XExecutableDialog > xSettingsDlg(
2456                                 xMgr->createInstance( C2U( "com.sun.star.sdb.TextConnectionSettings" ) ), uno::UNO_QUERY);
2457                     if( xSettingsDlg->execute() )
2458                     {
2459                         uno::Any aSettings = xDataProperties->getPropertyValue( C2U( "Settings" ) );
2460                         uno::Reference < beans::XPropertySet > xDSSettings;
2461                         aSettings >>= xDSSettings;
2462                         ::comphelper::copyProperties(
2463                             uno::Reference < beans::XPropertySet >( xSettingsDlg, uno::UNO_QUERY ),
2464                             xDSSettings );
2465                         xDSSettings->setPropertyValue( C2U("Extension"), uno::makeAny( ::rtl::OUString( sExt )));
2466                     }
2467                 }
2468 
2469                 Reference<XDocumentDataSource> xDS(xNewInstance, UNO_QUERY_THROW);
2470                 Reference<XStorable> xStore(xDS->getDatabaseDocument(), UNO_QUERY_THROW);
2471                 String sOutputExt = String::CreateFromAscii(".odb");
2472                 String sTmpName;
2473                 {
2474                     utl::TempFile aTempFile(sNewName , &sOutputExt, &sHomePath);
2475                     aTempFile.EnableKillingFile(sal_True);
2476                     sTmpName = aTempFile.GetURL();
2477                 }
2478                 xStore->storeAsURL(sTmpName, Sequence< PropertyValue >());
2479             }
2480             Reference<XNamingService> xNaming(xDBContext, UNO_QUERY);
2481             xNaming->registerObject( sFind, xNewInstance );
2482 
2483         }
2484         catch(Exception&)
2485         {
2486         }
2487     }
2488     return sFind;
2489 
2490 }
2491 /* -----------------------------10.11.00 17:10--------------------------------
2492 
2493  ---------------------------------------------------------------------------*/
2494 void SwNewDBMgr::ExecuteFormLetter(	SwWrtShell& rSh,
2495                         const Sequence<PropertyValue>& rProperties,
2496                         sal_Bool bWithDataSourceBrowser)
2497 {
2498 	//prevent second call
2499     if(pImpl->pMergeDialog)
2500 		return ;
2501     rtl::OUString sDataSource, sDataTableOrQuery;
2502     Sequence<Any> aSelection;
2503 
2504 	sal_Int32 nCmdType = CommandType::TABLE;
2505     uno::Reference< XConnection> xConnection;
2506 
2507 	ODataAccessDescriptor aDescriptor(rProperties);
2508 	sDataSource = aDescriptor.getDataSource();
2509 	aDescriptor[daCommand]		>>= sDataTableOrQuery;
2510 	aDescriptor[daCommandType]	>>= nCmdType;
2511 
2512 	if ( aDescriptor.has(daSelection) )
2513 		aDescriptor[daSelection] >>= aSelection;
2514 	if ( aDescriptor.has(daConnection) )
2515 		aDescriptor[daConnection] >>= xConnection;
2516 
2517     if(!sDataSource.getLength() || !sDataTableOrQuery.getLength())
2518 	{
2519 		DBG_ERROR("PropertyValues missing or unset");
2520 		return;
2521 	}
2522 
2523     //always create a connection for the dialog and dispose it after the dialog has been closed
2524     SwDSParam* pFound = 0;
2525     if(!xConnection.is())
2526     {
2527         xConnection = SwNewDBMgr::RegisterConnection(sDataSource);
2528         pFound = FindDSConnection(sDataSource, sal_True);
2529     }
2530 	SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2531     DBG_ASSERT(pFact, "Dialogdiet fail!");
2532     pImpl->pMergeDialog = pFact->CreateMailMergeDlg( DLG_MAILMERGE,
2533 														&rSh.GetView().GetViewFrame()->GetWindow(), rSh,
2534 														sDataSource,
2535 														sDataTableOrQuery,
2536 														nCmdType,
2537 														xConnection,
2538 														bWithDataSourceBrowser ? 0 : &aSelection);
2539     DBG_ASSERT(pImpl->pMergeDialog, "Dialogdiet fail!");
2540     if(pImpl->pMergeDialog->Execute() == RET_OK)
2541 	{
2542 		aDescriptor[daSelection] <<= pImpl->pMergeDialog->GetSelection();
2543 
2544         uno::Reference<XResultSet> xResSet = pImpl->pMergeDialog->GetResultSet();
2545         if(xResSet.is())
2546 			aDescriptor[daCursor] <<= xResSet;
2547 
2548         // SfxObjectShellRef is ok, since there should be no control over the document lifetime here
2549         SfxObjectShellRef xDocShell = rSh.GetView().GetViewFrame()->GetObjectShell();
2550         SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE), xDocShell));
2551         {
2552             //copy rSh to aTempFile
2553             ::rtl::OUString sTempURL;
2554             const SfxFilter *pSfxFlt = SwIoSystem::GetFilterOfFormat(
2555                         String::CreateFromAscii( FILTER_XML ),
2556                         SwDocShell::Factory().GetFilterContainer() );
2557             try
2558             {
2559 
2560                 uno::Sequence< beans::PropertyValue > aValues(1);
2561                 beans::PropertyValue* pValues = aValues.getArray();
2562                 pValues[0].Name = C2U("FilterName");
2563                 pValues[0].Value <<= ::rtl::OUString(pSfxFlt->GetFilterName());
2564                 uno::Reference< frame::XStorable > xStore( xDocShell->GetModel(), uno::UNO_QUERY);
2565                 sTempURL = URIHelper::SmartRel2Abs( INetURLObject(), utl::TempFile::CreateTempName() );
2566                 xStore->storeToURL( sTempURL, aValues );
2567             }
2568             catch( const uno::Exception& rEx )
2569             {
2570                 (void) rEx;
2571             }
2572             if( xDocShell->GetError() )
2573             {
2574                 // error message ??
2575                 ErrorHandler::HandleError( xDocShell->GetError() );
2576             }
2577             else
2578             {
2579                 // the shell will be explicitly closed, but it is more safe to use SfxObjectShellLock here
2580                 // especially for the case that the loading has failed
2581                 SfxObjectShellLock xWorkDocSh( new SwDocShell( SFX_CREATE_MODE_INTERNAL ));
2582                 SfxMedium* pWorkMed = new SfxMedium( sTempURL, STREAM_STD_READ, sal_True );
2583                 pWorkMed->SetFilter( pSfxFlt );
2584                 if( xWorkDocSh->DoLoad(pWorkMed) )
2585                 {
2586                     SfxViewFrame *pFrame = SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 );
2587                     SwView *pView = (SwView*) pFrame->GetViewShell();
2588                     pView->AttrChangedNotify( &pView->GetWrtShell() );//Damit SelectShell gerufen wird.
2589                     //set the current DBMgr
2590                     SwDoc* pWorkDoc = pView->GetWrtShell().GetDoc();
2591                     SwNewDBMgr* pWorkDBMgr = pWorkDoc->GetNewDBMgr();
2592                     pWorkDoc->SetNewDBMgr( this );
2593 
2594                     SwMergeDescriptor aMergeDesc( pImpl->pMergeDialog->GetMergeType(), pView->GetWrtShell(), aDescriptor );
2595                     aMergeDesc.sSaveToFilter = pImpl->pMergeDialog->GetSaveFilter();
2596                     aMergeDesc.bCreateSingleFile = !pImpl->pMergeDialog->IsSaveIndividualDocs();
2597                     if( !aMergeDesc.bCreateSingleFile && pImpl->pMergeDialog->IsGenerateFromDataBase() )
2598                     {
2599                         aMergeDesc.sAddressFromColumn = pImpl->pMergeDialog->GetColumnName();
2600                         aMergeDesc.sSubject = pImpl->pMergeDialog->GetPath();
2601                     }
2602 
2603                     MergeNew(aMergeDesc);
2604 
2605                     pWorkDoc->SetNewDBMgr( pWorkDBMgr );
2606                     //close the temporary file
2607                     uno::Reference< util::XCloseable > xClose( xWorkDocSh->GetModel(), uno::UNO_QUERY );
2608                     if (xClose.is())
2609                     {
2610                         try
2611                         {
2612                             //! 'sal_True' -> transfer ownership to vetoing object if vetoed!
2613                             //! I.e. now that object is responsible for closing the model and doc shell.
2614                             xClose->close( sal_True );
2615                         }
2616                         catch ( const uno::Exception& )
2617                         {
2618                         }
2619                     }
2620                 }
2621             }
2622             //remove the temporary file
2623             SWUnoHelper::UCB_DeleteFile( sTempURL );
2624         }
2625         SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_MAIL_MERGE_END, SwDocShell::GetEventName(STR_SW_EVENT_MAIL_MERGE_END), rSh.GetView().GetViewFrame()->GetObjectShell()));
2626 
2627 		// reset the cursor inside
2628 		xResSet = NULL;
2629 		aDescriptor[daCursor] <<= xResSet;
2630 	}
2631     if(pFound)
2632     {
2633         for(sal_uInt16 nPos = 0; nPos < aDataSourceParams.Count(); nPos++)
2634         {
2635             SwDSParam* pParam = aDataSourceParams[nPos];
2636             if(pParam == pFound)
2637             {
2638                 try
2639                 {
2640                     uno::Reference<XComponent> xComp(pParam->xConnection, UNO_QUERY);
2641                     if(xComp.is())
2642                         xComp->dispose();
2643                 }
2644                 catch(const RuntimeException& )
2645                 {
2646                     //may be disposed already since multiple entries may have used the same connection
2647                 }
2648                 break;
2649             }
2650             //pFound doesn't need to be removed/deleted -
2651             //this has been done by the SwConnectionDisposedListener_Impl already
2652         }
2653     }
2654     DELETEZ(pImpl->pMergeDialog);
2655 }
2656 /* -----------------------------13.11.00 08:20--------------------------------
2657 
2658  ---------------------------------------------------------------------------*/
2659 void SwNewDBMgr::InsertText(SwWrtShell& rSh,
2660 						const Sequence< PropertyValue>& rProperties)
2661 {
2662     rtl::OUString sDataSource, sDataTableOrQuery;
2663     uno::Reference<XResultSet>  xResSet;
2664     Sequence<Any> aSelection;
2665 	sal_Bool bHasSelectionProperty = sal_False;
2666 	sal_Int32 nSelectionPos = 0;
2667 	sal_Int16 nCmdType = CommandType::TABLE;
2668 	const PropertyValue* pValues = rProperties.getConstArray();
2669     uno::Reference< XConnection> xConnection;
2670     for(sal_Int32 nPos = 0; nPos < rProperties.getLength(); nPos++)
2671 	{
2672         if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cDataSourceName)))
2673 			pValues[nPos].Value >>= sDataSource;
2674         else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cCommand)))
2675 			pValues[nPos].Value >>= sDataTableOrQuery;
2676         else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cCursor)))
2677 			pValues[nPos].Value >>= xResSet;
2678         else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cSelection)))
2679 		{
2680 			bHasSelectionProperty = sal_True;
2681 			nSelectionPos = nPos;
2682 			pValues[nPos].Value >>= aSelection;
2683 		}
2684         else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cCommandType)))
2685 			pValues[nPos].Value >>= nCmdType;
2686         else if(pValues[nPos].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM(cActiveConnection)))
2687             pValues[nPos].Value >>= xConnection;
2688     }
2689 	if(!sDataSource.getLength() || !sDataTableOrQuery.getLength() || !xResSet.is())
2690 	{
2691 		DBG_ERROR("PropertyValues missing or unset");
2692 		return;
2693 	}
2694     uno::Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
2695     uno::Reference<XDataSource> xSource;
2696     uno::Reference<XChild> xChild(xConnection, UNO_QUERY);
2697     if(xChild.is())
2698         xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
2699     if(!xSource.is())
2700         xSource = SwNewDBMgr::GetDbtoolsClient().getDataSource(sDataSource, xMgr);
2701     uno::Reference< XColumnsSupplier > xColSupp( xResSet, UNO_QUERY );
2702 	SwDBData aDBData;
2703 	aDBData.sDataSource = sDataSource;
2704 	aDBData.sCommand = sDataTableOrQuery;
2705 	aDBData.nCommandType = nCmdType;
2706 
2707     SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
2708     DBG_ASSERT(pFact, "SwAbstractDialogFactory fail!");
2709 
2710 	AbstractSwInsertDBColAutoPilot* pDlg = pFact->CreateSwInsertDBColAutoPilot( rSh.GetView(),
2711 																				xSource,
2712 																				xColSupp,
2713 																				aDBData,
2714                                                                                 DLG_AP_INSERT_DB_SEL );
2715     DBG_ASSERT(pDlg, "Dialogdiet fail!");
2716 	if( RET_OK == pDlg->Execute() )
2717 	{
2718         rtl::OUString sDummy;
2719         if(!xConnection.is())
2720             xConnection = xSource->getConnection(sDummy, sDummy);
2721         try
2722         {
2723             pDlg->DataToDoc( aSelection , xSource, xConnection, xResSet);
2724         }
2725         catch(Exception& )
2726         {
2727             DBG_ERROR("exception caught");
2728         }
2729     }
2730 	delete pDlg;
2731 
2732 }
2733 /* -----------------------------30.08.2001 12:00------------------------------
2734 
2735  ---------------------------------------------------------------------------*/
2736 SwDbtoolsClient* SwNewDBMgr::pDbtoolsClient = NULL;
2737 
2738 SwDbtoolsClient& SwNewDBMgr::GetDbtoolsClient()
2739 {
2740     if ( !pDbtoolsClient )
2741         pDbtoolsClient = new SwDbtoolsClient;
2742     return *pDbtoolsClient;
2743 }
2744 /* -----------------13.05.2003 15:34-----------------
2745 
2746  --------------------------------------------------*/
2747 void SwNewDBMgr::RemoveDbtoolsClient()
2748 {
2749     delete pDbtoolsClient;
2750     pDbtoolsClient = 0;
2751 }
2752 /* -----------------------------20.08.2002 12:00------------------------------
2753 
2754  ---------------------------------------------------------------------------*/
2755 uno::Reference<XDataSource> SwNewDBMgr::getDataSourceAsParent(const uno::Reference< XConnection>& _xConnection,const ::rtl::OUString& _sDataSourceName)
2756 {
2757     uno::Reference<XDataSource> xSource;
2758 	try
2759 	{
2760         uno::Reference<XChild> xChild(_xConnection, UNO_QUERY);
2761 		if ( xChild.is() )
2762             xSource = uno::Reference<XDataSource>(xChild->getParent(), UNO_QUERY);
2763 		if ( !xSource.is() )
2764 			xSource = SwNewDBMgr::GetDbtoolsClient().getDataSource(_sDataSourceName, ::comphelper::getProcessServiceFactory());
2765 	}
2766 	catch(const Exception&)
2767 	{
2768 		DBG_ERROR("exception in getDataSourceAsParent caught");
2769 	}
2770 	return xSource;
2771 }
2772 /* -----------------------------20.08.2002 12:00------------------------------
2773 
2774  ---------------------------------------------------------------------------*/
2775 uno::Reference<XResultSet> SwNewDBMgr::createCursor(const ::rtl::OUString& _sDataSourceName,
2776 									   const ::rtl::OUString& _sCommand,
2777 									   sal_Int32 _nCommandType,
2778                                        const uno::Reference<XConnection>& _xConnection
2779 									  )
2780 {
2781     uno::Reference<XResultSet> xResultSet;
2782 	try
2783 	{
2784         uno::Reference< XMultiServiceFactory > xMgr( ::comphelper::getProcessServiceFactory() );
2785 		if( xMgr.is() )
2786 		{
2787             uno::Reference<XInterface> xInstance = xMgr->createInstance(
2788 				C2U( "com.sun.star.sdb.RowSet" ));
2789             uno::Reference<XPropertySet> xRowSetPropSet(xInstance, UNO_QUERY);
2790 			if(xRowSetPropSet.is())
2791 			{
2792 				xRowSetPropSet->setPropertyValue(C2U("DataSourceName"), makeAny(_sDataSourceName));
2793 				xRowSetPropSet->setPropertyValue(C2U("ActiveConnection"), makeAny(_xConnection));
2794 				xRowSetPropSet->setPropertyValue(C2U("Command"), makeAny(_sCommand));
2795 				xRowSetPropSet->setPropertyValue(C2U("CommandType"), makeAny(_nCommandType));
2796 
2797                 uno::Reference< XCompletedExecution > xRowSet(xInstance, UNO_QUERY);
2798 
2799 				if ( xRowSet.is() )
2800 				{
2801                     uno::Reference< XInteractionHandler > xHandler(xMgr->createInstance(C2U("com.sun.star.task.InteractionHandler")), UNO_QUERY);
2802 					xRowSet->executeWithCompletion(xHandler);
2803 				}
2804                 xResultSet = uno::Reference<XResultSet>(xRowSet, UNO_QUERY);
2805 			}
2806 		}
2807 	}
2808 	catch(const Exception&)
2809 	{
2810 		DBG_ASSERT(0,"Caught exception while creating a new RowSet!");
2811 	}
2812 	return xResultSet;
2813 }
2814 /*-- 13.05.2004 16:14:15---------------------------------------------------
2815     merge all data into one resulting document and return the number of
2816     merged documents
2817   -----------------------------------------------------------------------*/
2818 
2819 sal_Int32 SwNewDBMgr::MergeDocuments( SwMailMergeConfigItem& rMMConfig,
2820                             SwView& rSourceView )
2821 {
2822     // check the availability of all data in the config item
2823     uno::Reference< XResultSet> xResultSet = rMMConfig.GetResultSet();
2824     if(!xResultSet.is())
2825         return false;
2826     bInMerge = sal_True;
2827     sal_Int32 nRet  = 0;
2828     pImpl->pMergeData = new SwDSParam(
2829                 rMMConfig.GetCurrentDBData(), xResultSet, rMMConfig.GetSelection());
2830 
2831     try{
2832         //set to start position
2833         if(pImpl->pMergeData->aSelection.getLength())
2834         {
2835             sal_Int32 nPos = 0;
2836             pImpl->pMergeData->aSelection.getConstArray()[ pImpl->pMergeData->nSelectionIndex++ ] >>= nPos;
2837             pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->absolute( nPos );
2838             pImpl->pMergeData->CheckEndOfDB();
2839             if(pImpl->pMergeData->nSelectionIndex >= pImpl->pMergeData->aSelection.getLength())
2840                 pImpl->pMergeData->bEndOfDB = sal_True;
2841         }
2842         else
2843         {
2844             pImpl->pMergeData->bEndOfDB = !pImpl->pMergeData->xResultSet->first();
2845             pImpl->pMergeData->CheckEndOfDB();
2846         }
2847     }
2848     catch(Exception&)
2849     {
2850         pImpl->pMergeData->bEndOfDB = sal_True;
2851         pImpl->pMergeData->CheckEndOfDB();
2852         DBG_ERROR("exception in MergeNew()");
2853     }
2854 
2855     //bCancel is set from the PrintMonitor
2856     bCancel = sal_False;
2857 
2858     CreateMonitor aMonitorDlg(&rSourceView.GetEditWin());
2859     aMonitorDlg.SetCancelHdl(LINK(this, SwNewDBMgr, PrtCancelHdl));
2860     if (!IsMergeSilent())
2861     {
2862         aMonitorDlg.Show();
2863         aMonitorDlg.Invalidate();
2864         aMonitorDlg.Update();
2865         // the print monitor needs some time to act
2866         for( sal_uInt16 i = 0; i < 25; i++)
2867             Application::Reschedule();
2868     }
2869 
2870     SwWrtShell& rSourceShell = rSourceView.GetWrtShell();
2871     sal_Bool bSynchronizedDoc = rSourceShell.IsLabelDoc() && rSourceShell.GetSectionFmtCount() > 1;
2872     //save the settings of the first
2873     rSourceShell.SttEndDoc(sal_True);
2874     sal_uInt16 nStartingPageNo = rSourceShell.GetVirtPageNum();
2875     String sModifiedStartingPageDesc;
2876     String sStartingPageDesc = sModifiedStartingPageDesc = rSourceShell.GetPageDesc(
2877                                 rSourceShell.GetCurPageDesc()).GetName();
2878 
2879     try
2880     {
2881         // create a target docshell to put the merged document into
2882         SfxObjectShellRef xTargetDocShell( new SwDocShell( SFX_CREATE_MODE_STANDARD ) );
2883         xTargetDocShell->DoInitNew( 0 );
2884         SfxViewFrame* pTargetFrame = SfxViewFrame::LoadHiddenDocument( *xTargetDocShell, 0 );
2885 
2886         //the created window has to be located at the same position as the source window
2887         Window& rTargetWindow = pTargetFrame->GetFrame().GetWindow();
2888         Window& rSourceWindow = rSourceView.GetViewFrame()->GetFrame().GetWindow();
2889         rTargetWindow.SetPosPixel(rSourceWindow.GetPosPixel());
2890 
2891 //        pTargetFrame->GetFrame().Appear();
2892         SwView* pTargetView = static_cast<SwView*>( pTargetFrame->GetViewShell() );
2893         rMMConfig.SetTargetView(pTargetView);
2894         //initiate SelectShell() to create sub shells
2895         pTargetView->AttrChangedNotify( &pTargetView->GetWrtShell() );
2896         SwWrtShell* pTargetShell = pTargetView->GetWrtShellPtr();
2897         // #i63806#
2898         const SwPageDesc* pSourcePageDesc = rSourceShell.FindPageDescByName( sStartingPageDesc );
2899         const SwFrmFmt& rMaster = pSourcePageDesc->GetMaster();
2900         bool bPageStylesWithHeaderFooter = rMaster.GetHeader().IsActive()  ||
2901                                         rMaster.GetFooter().IsActive();
2902 
2903 
2904         // #122799# copy compatibility options
2905         lcl_CopyCompatibilityOptions( rSourceShell, *pTargetShell);
2906         // #72821# copy dynamic defaults
2907         lcl_CopyDynamicDefaults( *rSourceShell.GetDoc(), *pTargetShell->GetDoc() );
2908 
2909 
2910         long nStartRow, nEndRow;
2911         sal_uLong nDocNo = 1;
2912         sal_Int32 nDocCount = 0;
2913         if( !IsMergeSilent() && lcl_getCountFromResultSet( nDocCount, pImpl->pMergeData->xResultSet ) )
2914             aMonitorDlg.SetTotalCount( nDocCount );
2915 
2916         do
2917         {
2918             nStartRow = pImpl->pMergeData->xResultSet->getRow();
2919             if (!IsMergeSilent())
2920             {
2921                 aMonitorDlg.SetCurrentPosition( nDocNo );
2922                 aMonitorDlg.Invalidate();
2923                 aMonitorDlg.Update();
2924                 // the print monitor needs some time to act
2925                 for( sal_uInt16 i = 0; i < 25; i++)
2926                     Application::Reschedule();
2927             }
2928 
2929             // copy the source document
2930             // the copy will be closed later, but it is more safe to use SfxObjectShellLock here
2931             SfxObjectShellLock xWorkDocSh;
2932             if(nDocNo == 1 )
2933             {
2934                 uno::Reference< util::XCloneable > xClone( rSourceView.GetDocShell()->GetModel(), uno::UNO_QUERY);
2935                 uno::Reference< lang::XUnoTunnel > xWorkDocShell( xClone->createClone(), uno::UNO_QUERY);
2936                 SwXTextDocument* pWorkModel = reinterpret_cast<SwXTextDocument*>(xWorkDocShell->getSomething(SwXTextDocument::getUnoTunnelId()));
2937                 xWorkDocSh = pWorkModel->GetDocShell();
2938             }
2939             else
2940             {
2941                 xWorkDocSh = rSourceView.GetDocShell()->GetDoc()->CreateCopy(true);
2942             }
2943             //create a ViewFrame
2944             SwView* pWorkView = static_cast< SwView* >( SfxViewFrame::LoadHiddenDocument( *xWorkDocSh, 0 )->GetViewShell() );
2945             SwWrtShell& rWorkShell = pWorkView->GetWrtShell();
2946             pWorkView->AttrChangedNotify( &rWorkShell );//Damit SelectShell gerufen wird.
2947 
2948                 // merge the data
2949                 SwDoc* pWorkDoc = rWorkShell.GetDoc();
2950                 SwNewDBMgr* pWorkDBMgr = pWorkDoc->GetNewDBMgr();
2951                 pWorkDoc->SetNewDBMgr( this );
2952                 pWorkDoc->EmbedAllLinks();
2953                 SwUndoId nLastUndoId(UNDO_EMPTY);
2954                 if (rWorkShell.GetLastUndoInfo(0, & nLastUndoId))
2955                 {
2956                     if (UNDO_UI_DELETE_INVISIBLECNTNT == nLastUndoId)
2957                     {
2958                         rWorkShell.Undo();
2959                     }
2960                 }
2961                 // #i69485# lock fields to prevent access to the result set while calculating layout
2962 	            rWorkShell.LockExpFlds();
2963                 // create a layout
2964                 rWorkShell.CalcLayout();
2965                 rWorkShell.UnlockExpFlds();
2966                 SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
2967             rWorkShell.ViewShell::UpdateFlds();
2968                 SFX_APP()->NotifyEvent(SfxEventHint(SW_EVENT_FIELD_MERGE_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_FIELD_MERGE_FINISHED), rWorkShell.GetView().GetViewFrame()->GetObjectShell()));
2969 
2970             // strip invisible content and convert fields to text
2971             rWorkShell.RemoveInvisibleContent();
2972             rWorkShell.ConvertFieldsToText();
2973             rWorkShell.SetNumberingRestart();
2974             if( bSynchronizedDoc )
2975             {
2976                 lcl_RemoveSectionLinks( rWorkShell );
2977             }
2978 
2979             // insert the document into the target document
2980             rWorkShell.SttEndDoc(sal_False);
2981             rWorkShell.SttEndDoc(sal_True);
2982             rWorkShell.SelAll();
2983             pTargetShell->SttEndDoc(sal_False);
2984 
2985             //#i63806# put the styles to the target document
2986             //if the source uses headers or footers each new copy need to copy a new page styles
2987             if(bPageStylesWithHeaderFooter)
2988             {
2989                 //create a new pagestyle
2990                 //copy the pagedesc from the current document to the new document and change the name of the to-be-applied style
2991 
2992                 SwDoc* pTargetDoc = pTargetShell->GetDoc();
2993                 String sNewPageDescName = lcl_FindUniqueName(pTargetShell, sStartingPageDesc, nDocNo );
2994                 pTargetShell->GetDoc()->MakePageDesc( sNewPageDescName );
2995                 SwPageDesc* pTargetPageDesc = pTargetShell->FindPageDescByName( sNewPageDescName );
2996                 const SwPageDesc* pWorkPageDesc = rWorkShell.FindPageDescByName( sStartingPageDesc );
2997 
2998                 if(pWorkPageDesc && pTargetPageDesc)
2999                 {
3000                     pTargetDoc->CopyPageDesc( *pWorkPageDesc, *pTargetPageDesc, sal_False );
3001                     sModifiedStartingPageDesc = sNewPageDescName;
3002                     lcl_CopyFollowPageDesc( *pTargetShell, *pWorkPageDesc, *pTargetPageDesc, nDocNo );
3003                 }
3004             }
3005             if(nDocNo == 1 || bPageStylesWithHeaderFooter)
3006             {
3007                 pTargetView->GetDocShell()->_LoadStyles( *rSourceView.GetDocShell(), sal_True );
3008             }
3009             if(nDocNo > 1)
3010             {
3011                 pTargetShell->InsertPageBreak( &sModifiedStartingPageDesc, nStartingPageNo );
3012             }
3013             else
3014             {
3015                 pTargetShell->SetPageStyle(sModifiedStartingPageDesc);
3016             }
3017             sal_uInt16 nPageCountBefore = pTargetShell->GetPageCnt();
3018             DBG_ASSERT(!pTargetShell->GetTableFmt(),"target document ends with a table - paragraph should be appended");
3019             //#i51359# add a second paragraph in case there's only one
3020             {
3021                 SwNodeIndex aIdx( pWorkDoc->GetNodes().GetEndOfExtras(), 2 );
3022               SwPosition aTestPos( aIdx );
3023               SwCursor aTestCrsr(aTestPos,0,false);
3024                 if(!aTestCrsr.MovePara(fnParaNext, fnParaStart))
3025                 {
3026                     //append a paragraph
3027                     pWorkDoc->AppendTxtNode( aTestPos );
3028                 }
3029             }
3030             pTargetShell->Paste( rWorkShell.GetDoc(), sal_True );
3031             //convert fields in page styles (header/footer - has to be done after the first document has been pasted
3032             if(1 == nDocNo)
3033             {
3034                 pTargetShell->CalcLayout();
3035                 pTargetShell->ConvertFieldsToText();
3036             }
3037             //add the document info to the config item
3038             SwDocMergeInfo aMergeInfo;
3039             aMergeInfo.nStartPageInTarget = nPageCountBefore;
3040             //#i72820# calculate layout to be able to find the correct page index
3041             pTargetShell->CalcLayout();
3042             aMergeInfo.nEndPageInTarget = pTargetShell->GetPageCnt();
3043             aMergeInfo.nDBRow = nStartRow;
3044             rMMConfig.AddMergedDocument( aMergeInfo );
3045             ++nRet;
3046 
3047             // the print monitor needs some time to act
3048             for( sal_uInt16 i = 0; i < 25; i++)
3049                 Application::Reschedule();
3050 
3051             //restore the ole DBMgr
3052             pWorkDoc->SetNewDBMgr( pWorkDBMgr );
3053             //now the temporary document should be closed
3054             SfxObjectShellRef xDocSh(pWorkView->GetDocShell());
3055             xDocSh->DoClose();
3056             nEndRow = pImpl->pMergeData->xResultSet->getRow();
3057             ++nDocNo;
3058         } while( !bCancel &&
3059                 (bSynchronizedDoc && (nStartRow != nEndRow)? ExistsNextRecord() : ToNextMergeRecord()));
3060 
3061         //deselect all, go out of the frame and go to the beginning of the document
3062         Point aPt(LONG_MIN, LONG_MIN);
3063         pTargetShell->SelectObj(aPt, SW_LEAVE_FRAME);
3064         if (pTargetShell->IsSelFrmMode())
3065         {
3066             pTargetShell->UnSelectFrm();
3067             pTargetShell->LeaveSelFrmMode();
3068         }
3069         pTargetShell->EnterStdMode();
3070         pTargetShell->SttDoc();
3071         //
3072     }
3073     catch( Exception& rEx)
3074     {
3075         (void)rEx;
3076         DBG_ERROR("exception caught in SwNewDBMgr::MergeDocuments");
3077     }
3078     DELETEZ(pImpl->pMergeData);
3079     bInMerge = sal_False;
3080     return nRet;
3081 }
3082 /* -----------------09.12.2002 12:38-----------------
3083  *
3084  * --------------------------------------------------*/
3085 SwConnectionDisposedListener_Impl::SwConnectionDisposedListener_Impl(SwNewDBMgr& rMgr) :
3086     rDBMgr(rMgr)
3087 {};
3088 /* -----------------09.12.2002 12:39-----------------
3089  *
3090  * --------------------------------------------------*/
3091 SwConnectionDisposedListener_Impl::~SwConnectionDisposedListener_Impl()
3092 {};
3093 /* -----------------09.12.2002 12:39-----------------
3094  *
3095  * --------------------------------------------------*/
3096 void SwConnectionDisposedListener_Impl::disposing( const EventObject& rSource )
3097         throw (RuntimeException)
3098 {
3099     ::vos::OGuard aGuard(Application::GetSolarMutex());
3100     uno::Reference<XConnection> xSource(rSource.Source, UNO_QUERY);
3101     for(sal_uInt16 nPos = rDBMgr.aDataSourceParams.Count(); nPos; nPos--)
3102     {
3103         SwDSParam* pParam = rDBMgr.aDataSourceParams[nPos - 1];
3104         if(pParam->xConnection.is() &&
3105                 (xSource == pParam->xConnection))
3106         {
3107             rDBMgr.aDataSourceParams.DeleteAndDestroy(nPos - 1);
3108         }
3109     }
3110 }
3111