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