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